diff options
-rw-r--r-- | .travis.yml | 4 | ||||
-rw-r--r-- | SConstruct | 115 | ||||
-rw-r--r-- | bin/SCsub | 2 | ||||
-rw-r--r-- | bin/tests/SCsub | 2 | ||||
-rw-r--r-- | bin/tests/test_gdscript.cpp | 1 | ||||
-rw-r--r-- | bin/tests/test_math.cpp | 402 | ||||
-rw-r--r-- | bin/tests/test_misc.cpp | 2 | ||||
-rw-r--r-- | bin/tests/test_physics.cpp | 2 | ||||
-rw-r--r-- | bin/tests/test_physics_2d.cpp | 2 | ||||
-rw-r--r-- | bin/tests/test_string.cpp | 58 | ||||
-rw-r--r-- | core/SCsub | 2 | ||||
-rw-r--r-- | core/array.cpp | 20 | ||||
-rw-r--r-- | core/array.h | 4 | ||||
-rw-r--r-- | core/bind/SCsub | 2 | ||||
-rw-r--r-- | core/dvector.h | 28 | ||||
-rw-r--r-- | core/func_ref.cpp | 6 | ||||
-rw-r--r-- | core/globals.cpp | 2 | ||||
-rw-r--r-- | core/hashfuncs.h | 5 | ||||
-rw-r--r-- | core/image.cpp | 1 | ||||
-rw-r--r-- | core/input_map.cpp | 58 | ||||
-rw-r--r-- | core/input_map.h | 1 | ||||
-rw-r--r-- | core/io/SCsub | 2 | ||||
-rw-r--r-- | core/io/file_access_pack.cpp | 2 | ||||
-rw-r--r-- | core/io/http_client.cpp | 7 | ||||
-rw-r--r-- | core/io/http_client.h | 2 | ||||
-rw-r--r-- | core/io/ip.cpp | 37 | ||||
-rw-r--r-- | core/io/ip.h | 16 | ||||
-rw-r--r-- | core/io/ip_address.cpp | 186 | ||||
-rw-r--r-- | core/io/ip_address.h | 38 | ||||
-rw-r--r-- | core/io/packet_peer_udp.cpp | 9 | ||||
-rw-r--r-- | core/io/packet_peer_udp.h | 3 | ||||
-rw-r--r-- | core/io/pck_packer.cpp (renamed from tools/pck/pck_packer.cpp) | 0 | ||||
-rw-r--r-- | core/io/pck_packer.h (renamed from tools/pck/pck_packer.h) | 0 | ||||
-rw-r--r-- | core/io/tcp_server.cpp | 8 | ||||
-rw-r--r-- | core/io/tcp_server.h | 4 | ||||
-rw-r--r-- | core/math/SCsub | 2 | ||||
-rw-r--r-- | core/math/a_star.cpp | 412 | ||||
-rw-r--r-- | core/math/a_star.h | 92 | ||||
-rw-r--r-- | core/math/math_2d.cpp | 24 | ||||
-rw-r--r-- | core/math/math_2d.h | 15 | ||||
-rw-r--r-- | core/math/triangulate.cpp | 5 | ||||
-rw-r--r-- | core/math/vector3.cpp | 22 | ||||
-rw-r--r-- | core/math/vector3.h | 197 | ||||
-rw-r--r-- | core/method_bind.h | 19 | ||||
-rw-r--r-- | core/object.cpp | 34 | ||||
-rw-r--r-- | core/object_type_db.cpp | 181 | ||||
-rw-r--r-- | core/object_type_db.h | 19 | ||||
-rw-r--r-- | core/os/SCsub | 2 | ||||
-rw-r--r-- | core/os/input.cpp | 6 | ||||
-rw-r--r-- | core/os/input.h | 5 | ||||
-rw-r--r-- | core/os/input_event.cpp | 5 | ||||
-rw-r--r-- | core/os/os.h | 1 | ||||
-rw-r--r-- | core/register_core_types.cpp | 5 | ||||
-rw-r--r-- | core/script_debugger_remote.cpp | 9 | ||||
-rw-r--r-- | core/script_language.h | 20 | ||||
-rw-r--r-- | core/translation.cpp | 39 | ||||
-rw-r--r-- | core/undo_redo.cpp | 16 | ||||
-rw-r--r-- | core/ustring.cpp | 97 | ||||
-rw-r--r-- | core/ustring.h | 5 | ||||
-rw-r--r-- | core/variant.cpp | 14 | ||||
-rw-r--r-- | core/variant_call.cpp | 19 | ||||
-rw-r--r-- | core/variant_parser.cpp | 24 | ||||
-rw-r--r-- | doc/base/classes.xml | 1220 | ||||
-rw-r--r-- | doc/tools/doc_merge.py | 2 | ||||
-rwxr-xr-x | doc/tools/doc_status.py | 2 | ||||
-rw-r--r-- | doc/tools/makedocs.py | 2 | ||||
-rw-r--r-- | doc/tools/makedoku.py | 2 | ||||
-rw-r--r-- | doc/tools/makehtml.py | 2 | ||||
-rw-r--r-- | doc/tools/makemd.py | 2 | ||||
-rw-r--r-- | doc/tools/makerst.py | 2 | ||||
-rw-r--r-- | drivers/SCsub | 105 | ||||
-rw-r--r-- | drivers/alsa/SCsub | 4 | ||||
-rw-r--r-- | drivers/builtin_openssl2/SCsub | 658 | ||||
-rw-r--r-- | drivers/builtin_openssl2/crypto/rand/rand_win.c | 752 | ||||
-rw-r--r-- | drivers/builtin_openssl2/openssl/dtls1.h | 275 | ||||
-rw-r--r-- | drivers/builtin_zlib/SCsub | 22 | ||||
-rw-r--r-- | drivers/chibi/SCsub | 5 | ||||
-rw-r--r-- | drivers/convex_decomp/SCsub | 7 | ||||
-rw-r--r-- | drivers/dds/SCsub | 10 | ||||
-rw-r--r-- | drivers/etc1/SCsub | 15 | ||||
-rw-r--r-- | drivers/freetype/SCsub | 68 | ||||
-rw-r--r-- | drivers/freetype/src/Jamfile | 19 | ||||
-rw-r--r-- | drivers/freetype/src/autofit/Jamfile | 53 | ||||
-rw-r--r-- | drivers/freetype/src/base/Jamfile | 88 | ||||
-rw-r--r-- | drivers/freetype/src/bdf/Jamfile | 31 | ||||
-rw-r--r-- | drivers/freetype/src/cache/Jamfile | 37 | ||||
-rw-r--r-- | drivers/freetype/src/cff/Jamfile | 45 | ||||
-rw-r--r-- | drivers/freetype/src/cid/Jamfile | 34 | ||||
-rw-r--r-- | drivers/freetype/src/gxvalid/Jamfile | 52 | ||||
-rw-r--r-- | drivers/freetype/src/otvalid/Jamfile | 37 | ||||
-rw-r--r-- | drivers/freetype/src/pcf/Jamfile | 32 | ||||
-rw-r--r-- | drivers/freetype/src/pfr/Jamfile | 35 | ||||
-rw-r--r-- | drivers/freetype/src/psaux/Jamfile | 35 | ||||
-rw-r--r-- | drivers/freetype/src/pshinter/Jamfile | 34 | ||||
-rw-r--r-- | drivers/freetype/src/psnames/Jamfile | 31 | ||||
-rw-r--r-- | drivers/freetype/src/raster/Jamfile | 32 | ||||
-rw-r--r-- | drivers/freetype/src/sfnt/Jamfile | 40 | ||||
-rw-r--r-- | drivers/freetype/src/smooth/Jamfile | 32 | ||||
-rw-r--r-- | drivers/freetype/src/truetype/Jamfile | 37 | ||||
-rw-r--r-- | drivers/freetype/src/type1/Jamfile | 35 | ||||
-rw-r--r-- | drivers/freetype/src/type42/Jamfile | 32 | ||||
-rw-r--r-- | drivers/freetype/src/winfonts/Jamfile | 16 | ||||
-rw-r--r-- | drivers/gl_context/SCsub | 22 | ||||
-rw-r--r-- | drivers/gles2/SCsub | 6 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_gles2.cpp | 97 | ||||
-rw-r--r-- | drivers/gles2/shader_compiler_gles2.cpp | 1 | ||||
-rw-r--r-- | drivers/gles2/shaders/SCsub | 4 | ||||
-rw-r--r-- | drivers/gles2/shaders/canvas.glsl | 4 | ||||
-rw-r--r-- | drivers/gles2/shaders/material.glsl | 20 | ||||
-rw-r--r-- | drivers/jpegd/SCsub | 11 | ||||
-rw-r--r-- | drivers/jpegd/image_loader_jpegd.cpp | 143 | ||||
-rw-r--r-- | drivers/mpc/SCsub | 21 | ||||
-rw-r--r-- | drivers/mpc/audio_stream_mpc.h | 147 | ||||
-rw-r--r-- | drivers/nedmalloc/License.txt | 23 | ||||
-rw-r--r-- | drivers/nedmalloc/Readme.txt | 136 | ||||
-rw-r--r-- | drivers/nedmalloc/SCsub | 4 | ||||
-rw-r--r-- | drivers/nedmalloc/malloc.c.h | 5814 | ||||
-rw-r--r-- | drivers/nedmalloc/memory_pool_static_nedmalloc.cpp | 163 | ||||
-rw-r--r-- | drivers/nedmalloc/memory_pool_static_nedmalloc.h | 77 | ||||
-rw-r--r-- | drivers/nedmalloc/nedmalloc.cpp | 1467 | ||||
-rw-r--r-- | drivers/nedmalloc/nedmalloc.h | 302 | ||||
-rw-r--r-- | drivers/nrex/SCsub | 10 | ||||
-rw-r--r-- | drivers/ogg/SCsub | 9 | ||||
-rw-r--r-- | drivers/openssl/SCsub | 6 | ||||
-rw-r--r-- | drivers/openssl/curl_hostcheck.c | 221 | ||||
-rw-r--r-- | drivers/openssl/curl_hostcheck.h | 43 | ||||
-rw-r--r-- | drivers/openssl/register_openssl.cpp | 47 | ||||
-rw-r--r-- | drivers/openssl/register_openssl.h | 39 | ||||
-rw-r--r-- | drivers/openssl/stream_peer_openssl.cpp | 649 | ||||
-rw-r--r-- | drivers/openssl/stream_peer_openssl.h | 113 | ||||
-rw-r--r-- | drivers/opus/SCsub | 196 | ||||
-rw-r--r-- | drivers/opus/analysis.c | 672 | ||||
-rw-r--r-- | drivers/opus/analysis.h | 103 | ||||
-rw-r--r-- | drivers/opus/audio_stream_opus.h | 141 | ||||
-rw-r--r-- | drivers/opus/celt/_kiss_fft_guts.h | 182 | ||||
-rw-r--r-- | drivers/opus/celt/arch.h | 241 | ||||
-rw-r--r-- | drivers/opus/celt/arm/arm_celt_map.c | 118 | ||||
-rw-r--r-- | drivers/opus/celt/arm/armcpu.c | 171 | ||||
-rw-r--r-- | drivers/opus/celt/arm/celt_ne10_fft.c | 172 | ||||
-rw-r--r-- | drivers/opus/celt/arm/celt_ne10_mdct.c | 256 | ||||
-rw-r--r-- | drivers/opus/celt/arm/celt_neon_intr.c | 249 | ||||
-rw-r--r-- | drivers/opus/celt/arm/fft_arm.h | 72 | ||||
-rw-r--r-- | drivers/opus/celt/arm/fixed_armv5e.h | 151 | ||||
-rw-r--r-- | drivers/opus/celt/arm/kiss_fft_armv4.h | 121 | ||||
-rw-r--r-- | drivers/opus/celt/arm/kiss_fft_armv5e.h | 118 | ||||
-rw-r--r-- | drivers/opus/celt/arm/mdct_arm.h | 60 | ||||
-rw-r--r-- | drivers/opus/celt/arm/pitch_arm.h | 68 | ||||
-rw-r--r-- | drivers/opus/celt/bands.c | 1526 | ||||
-rw-r--r-- | drivers/opus/celt/bands.h | 120 | ||||
-rw-r--r-- | drivers/opus/celt/celt.c | 296 | ||||
-rw-r--r-- | drivers/opus/celt/celt.h | 229 | ||||
-rw-r--r-- | drivers/opus/celt/celt_decoder.c | 1241 | ||||
-rw-r--r-- | drivers/opus/celt/celt_encoder.c | 2404 | ||||
-rw-r--r-- | drivers/opus/celt/celt_lpc.c | 312 | ||||
-rw-r--r-- | drivers/opus/celt/celt_lpc.h | 67 | ||||
-rw-r--r-- | drivers/opus/celt/cpu_support.h | 70 | ||||
-rw-r--r-- | drivers/opus/celt/cwrs.c | 712 | ||||
-rw-r--r-- | drivers/opus/celt/cwrs.h | 48 | ||||
-rw-r--r-- | drivers/opus/celt/ecintrin.h | 87 | ||||
-rw-r--r-- | drivers/opus/celt/entcode.c | 150 | ||||
-rw-r--r-- | drivers/opus/celt/entcode.h | 152 | ||||
-rw-r--r-- | drivers/opus/celt/entdec.c | 242 | ||||
-rw-r--r-- | drivers/opus/celt/entdec.h | 100 | ||||
-rw-r--r-- | drivers/opus/celt/entenc.c | 291 | ||||
-rw-r--r-- | drivers/opus/celt/entenc.h | 110 | ||||
-rw-r--r-- | drivers/opus/celt/fixed_debug.h | 784 | ||||
-rw-r--r-- | drivers/opus/celt/fixed_generic.h | 151 | ||||
-rw-r--r-- | drivers/opus/celt/float_cast.h | 140 | ||||
-rw-r--r-- | drivers/opus/celt/kiss_fft.c | 602 | ||||
-rw-r--r-- | drivers/opus/celt/kiss_fft.h | 200 | ||||
-rw-r--r-- | drivers/opus/celt/laplace.c | 131 | ||||
-rw-r--r-- | drivers/opus/celt/laplace.h | 48 | ||||
-rw-r--r-- | drivers/opus/celt/mathops.c | 205 | ||||
-rw-r--r-- | drivers/opus/celt/mathops.h | 258 | ||||
-rw-r--r-- | drivers/opus/celt/mdct.c | 341 | ||||
-rw-r--r-- | drivers/opus/celt/mdct.h | 112 | ||||
-rw-r--r-- | drivers/opus/celt/mfrngcod.h | 48 | ||||
-rw-r--r-- | drivers/opus/celt/mips/celt_mipsr1.h | 148 | ||||
-rw-r--r-- | drivers/opus/celt/mips/kiss_fft_mipsr1.h | 167 | ||||
-rw-r--r-- | drivers/opus/celt/mips/mdct_mipsr1.h | 286 | ||||
-rw-r--r-- | drivers/opus/celt/mips/vq_mipsr1.h | 122 | ||||
-rw-r--r-- | drivers/opus/celt/modes.c | 439 | ||||
-rw-r--r-- | drivers/opus/celt/modes.h | 75 | ||||
-rw-r--r-- | drivers/opus/celt/opus_custom_demo.c | 207 | ||||
-rw-r--r-- | drivers/opus/celt/os_support.h | 92 | ||||
-rw-r--r-- | drivers/opus/celt/pitch.c | 541 | ||||
-rw-r--r-- | drivers/opus/celt/pitch.h | 220 | ||||
-rw-r--r-- | drivers/opus/celt/quant_bands.c | 553 | ||||
-rw-r--r-- | drivers/opus/celt/quant_bands.h | 66 | ||||
-rw-r--r-- | drivers/opus/celt/rate.c | 636 | ||||
-rw-r--r-- | drivers/opus/celt/rate.h | 101 | ||||
-rw-r--r-- | drivers/opus/celt/stack_alloc.h | 184 | ||||
-rw-r--r-- | drivers/opus/celt/static_modes_fixed.h | 892 | ||||
-rw-r--r-- | drivers/opus/celt/static_modes_float.h | 888 | ||||
-rw-r--r-- | drivers/opus/celt/vq.c | 405 | ||||
-rw-r--r-- | drivers/opus/celt/vq.h | 75 | ||||
-rw-r--r-- | drivers/opus/celt/x86/celt_lpc_sse.c | 129 | ||||
-rw-r--r-- | drivers/opus/celt/x86/celt_lpc_sse.h | 65 | ||||
-rw-r--r-- | drivers/opus/celt/x86/pitch_sse.c | 182 | ||||
-rw-r--r-- | drivers/opus/celt/x86/pitch_sse.h | 189 | ||||
-rw-r--r-- | drivers/opus/celt/x86/pitch_sse2.c | 92 | ||||
-rw-r--r-- | drivers/opus/celt/x86/pitch_sse4_1.c | 192 | ||||
-rw-r--r-- | drivers/opus/celt/x86/x86_celt_map.c | 152 | ||||
-rw-r--r-- | drivers/opus/celt/x86/x86cpu.c | 154 | ||||
-rw-r--r-- | drivers/opus/http.c | 3427 | ||||
-rw-r--r-- | drivers/opus/info.c | 751 | ||||
-rw-r--r-- | drivers/opus/internal.c | 40 | ||||
-rw-r--r-- | drivers/opus/internal.h | 254 | ||||
-rw-r--r-- | drivers/opus/mlp.c | 142 | ||||
-rw-r--r-- | drivers/opus/mlp.h | 43 | ||||
-rw-r--r-- | drivers/opus/mlp_data.c | 106 | ||||
-rw-r--r-- | drivers/opus/opus.c | 347 | ||||
-rw-r--r-- | drivers/opus/opus.h | 981 | ||||
-rw-r--r-- | drivers/opus/opus_custom.h | 342 | ||||
-rw-r--r-- | drivers/opus/opus_decoder.c | 978 | ||||
-rw-r--r-- | drivers/opus/opus_defines.h | 753 | ||||
-rw-r--r-- | drivers/opus/opus_encoder.c | 2524 | ||||
-rw-r--r-- | drivers/opus/opus_multistream.c | 89 | ||||
-rw-r--r-- | drivers/opus/opus_multistream.h | 660 | ||||
-rw-r--r-- | drivers/opus/opus_multistream_decoder.c | 534 | ||||
-rw-r--r-- | drivers/opus/opus_multistream_encoder.c | 1217 | ||||
-rw-r--r-- | drivers/opus/opus_private.h | 134 | ||||
-rw-r--r-- | drivers/opus/opusfile.c | 3275 | ||||
-rw-r--r-- | drivers/opus/opusfile.h | 2148 | ||||
-rw-r--r-- | drivers/opus/repacketizer.c | 343 | ||||
-rw-r--r-- | drivers/opus/repacketizer_demo.c | 214 | ||||
-rw-r--r-- | drivers/opus/silk/A2NLSF.c | 264 | ||||
-rw-r--r-- | drivers/opus/silk/API.h | 134 | ||||
-rw-r--r-- | drivers/opus/silk/CNG.c | 178 | ||||
-rw-r--r-- | drivers/opus/silk/HP_variable_cutoff.c | 74 | ||||
-rw-r--r-- | drivers/opus/silk/LPC_analysis_filter.c | 105 | ||||
-rw-r--r-- | drivers/opus/silk/LPC_inv_pred_gain.c | 151 | ||||
-rw-r--r-- | drivers/opus/silk/LP_variable_cutoff.c | 132 | ||||
-rw-r--r-- | drivers/opus/silk/NLSF2A.c | 175 | ||||
-rw-r--r-- | drivers/opus/silk/NLSF_VQ.c | 65 | ||||
-rw-r--r-- | drivers/opus/silk/NLSF_VQ_weights_laroia.c | 77 | ||||
-rw-r--r-- | drivers/opus/silk/NLSF_decode.c | 98 | ||||
-rw-r--r-- | drivers/opus/silk/NLSF_del_dec_quant.c | 214 | ||||
-rw-r--r-- | drivers/opus/silk/NLSF_encode.c | 133 | ||||
-rw-r--r-- | drivers/opus/silk/NLSF_stabilize.c | 139 | ||||
-rw-r--r-- | drivers/opus/silk/NLSF_unpack.c | 52 | ||||
-rw-r--r-- | drivers/opus/silk/NSQ.c | 450 | ||||
-rw-r--r-- | drivers/opus/silk/NSQ_del_dec.c | 721 | ||||
-rw-r--r-- | drivers/opus/silk/PLC.c | 442 | ||||
-rw-r--r-- | drivers/opus/silk/PLC.h | 62 | ||||
-rw-r--r-- | drivers/opus/silk/SigProc_FIX.h | 615 | ||||
-rw-r--r-- | drivers/opus/silk/VAD.c | 359 | ||||
-rw-r--r-- | drivers/opus/silk/VQ_WMat_EC.c | 117 | ||||
-rw-r--r-- | drivers/opus/silk/ana_filt_bank_1.c | 71 | ||||
-rw-r--r-- | drivers/opus/silk/biquad_alt.c | 75 | ||||
-rw-r--r-- | drivers/opus/silk/bwexpander.c | 48 | ||||
-rw-r--r-- | drivers/opus/silk/bwexpander_32.c | 47 | ||||
-rw-r--r-- | drivers/opus/silk/check_control_input.c | 103 | ||||
-rw-r--r-- | drivers/opus/silk/code_signs.c | 112 | ||||
-rw-r--r-- | drivers/opus/silk/control.h | 142 | ||||
-rw-r--r-- | drivers/opus/silk/control_SNR.c | 73 | ||||
-rw-r--r-- | drivers/opus/silk/control_audio_bandwidth.c | 123 | ||||
-rw-r--r-- | drivers/opus/silk/control_codec.c | 425 | ||||
-rw-r--r-- | drivers/opus/silk/debug.c | 167 | ||||
-rw-r--r-- | drivers/opus/silk/debug.h | 279 | ||||
-rw-r--r-- | drivers/opus/silk/dec_API.c | 416 | ||||
-rw-r--r-- | drivers/opus/silk/decode_core.c | 236 | ||||
-rw-r--r-- | drivers/opus/silk/decode_frame.c | 126 | ||||
-rw-r--r-- | drivers/opus/silk/decode_indices.c | 148 | ||||
-rw-r--r-- | drivers/opus/silk/decode_parameters.c | 112 | ||||
-rw-r--r-- | drivers/opus/silk/decode_pitch.c | 74 | ||||
-rw-r--r-- | drivers/opus/silk/decode_pulses.c | 112 | ||||
-rw-r--r-- | drivers/opus/silk/decoder_set_fs.c | 105 | ||||
-rw-r--r-- | drivers/opus/silk/define.h | 235 | ||||
-rw-r--r-- | drivers/opus/silk/enc_API.c | 560 | ||||
-rw-r--r-- | drivers/opus/silk/encode_indices.c | 178 | ||||
-rw-r--r-- | drivers/opus/silk/encode_pulses.c | 203 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/LTP_analysis_filter_FIX.c | 87 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/LTP_scale_ctrl_FIX.c | 50 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/apply_sine_window_FIX.c | 98 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/autocorr_FIX.c | 45 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/burg_modified_FIX.c | 272 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/corrMatrix_FIX.c | 155 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/encode_frame_FIX.c | 384 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/find_LPC_FIX.c | 148 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/find_LTP_FIX.c | 242 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/find_pitch_lags_FIX.c | 142 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/find_pred_coefs_FIX.c | 145 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/k2a_FIX.c | 50 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/k2a_Q16_FIX.c | 50 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/main_FIX.h | 272 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/mips/prefilter_FIX_mipsr1.h | 181 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h | 162 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/noise_shape_analysis_FIX.c | 448 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/pitch_analysis_core_FIX.c | 743 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/prefilter_FIX.c | 218 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/process_gains_FIX.c | 114 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/regularize_correlations_FIX.c | 44 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/residual_energy16_FIX.c | 100 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/residual_energy_FIX.c | 95 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/schur64_FIX.c | 89 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/schur_FIX.c | 103 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/solve_LS_FIX.c | 246 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/structs_FIX.h | 134 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/vector_ops_FIX.c | 99 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/warped_autocorrelation_FIX.c | 92 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/x86/burg_modified_FIX_sse.c | 372 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/x86/prefilter_FIX_sse.c | 157 | ||||
-rw-r--r-- | drivers/opus/silk/fixed/x86/vector_ops_FIX_sse.c | 85 | ||||
-rw-r--r-- | drivers/opus/silk/float/LPC_analysis_filter_FLP.c | 246 | ||||
-rw-r--r-- | drivers/opus/silk/float/LPC_inv_pred_gain_FLP.c | 73 | ||||
-rw-r--r-- | drivers/opus/silk/float/LTP_analysis_filter_FLP.c | 72 | ||||
-rw-r--r-- | drivers/opus/silk/float/LTP_scale_ctrl_FLP.c | 49 | ||||
-rw-r--r-- | drivers/opus/silk/float/SigProc_FLP.h | 204 | ||||
-rw-r--r-- | drivers/opus/silk/float/apply_sine_window_FLP.c | 78 | ||||
-rw-r--r-- | drivers/opus/silk/float/autocorrelation_FLP.c | 49 | ||||
-rw-r--r-- | drivers/opus/silk/float/burg_modified_FLP.c | 183 | ||||
-rw-r--r-- | drivers/opus/silk/float/bwexpander_FLP.c | 46 | ||||
-rw-r--r-- | drivers/opus/silk/float/corrMatrix_FLP.c | 90 | ||||
-rw-r--r-- | drivers/opus/silk/float/encode_frame_FLP.c | 369 | ||||
-rw-r--r-- | drivers/opus/silk/float/energy_FLP.c | 57 | ||||
-rw-r--r-- | drivers/opus/silk/float/find_LPC_FLP.c | 101 | ||||
-rw-r--r-- | drivers/opus/silk/float/find_LTP_FLP.c | 129 | ||||
-rw-r--r-- | drivers/opus/silk/float/find_pitch_lags_FLP.c | 129 | ||||
-rw-r--r-- | drivers/opus/silk/float/find_pred_coefs_FLP.c | 115 | ||||
-rw-r--r-- | drivers/opus/silk/float/inner_product_FLP.c | 57 | ||||
-rw-r--r-- | drivers/opus/silk/float/k2a_FLP.c | 50 | ||||
-rw-r--r-- | drivers/opus/silk/float/levinsondurbin_FLP.c | 78 | ||||
-rw-r--r-- | drivers/opus/silk/float/main_FLP.h | 313 | ||||
-rw-r--r-- | drivers/opus/silk/float/noise_shape_analysis_FLP.c | 362 | ||||
-rw-r--r-- | drivers/opus/silk/float/pitch_analysis_core_FLP.c | 627 | ||||
-rw-r--r-- | drivers/opus/silk/float/prefilter_FLP.c | 203 | ||||
-rw-r--r-- | drivers/opus/silk/float/process_gains_FLP.c | 100 | ||||
-rw-r--r-- | drivers/opus/silk/float/regularize_correlations_FLP.c | 45 | ||||
-rw-r--r-- | drivers/opus/silk/float/residual_energy_FLP.c | 114 | ||||
-rw-r--r-- | drivers/opus/silk/float/scale_copy_vector_FLP.c | 54 | ||||
-rw-r--r-- | drivers/opus/silk/float/scale_vector_FLP.c | 53 | ||||
-rw-r--r-- | drivers/opus/silk/float/schur_FLP.c | 67 | ||||
-rw-r--r-- | drivers/opus/silk/float/solve_LS_FLP.c | 204 | ||||
-rw-r--r-- | drivers/opus/silk/float/sort_FLP.c | 80 | ||||
-rw-r--r-- | drivers/opus/silk/float/structs_FLP.h | 132 | ||||
-rw-r--r-- | drivers/opus/silk/float/warped_autocorrelation_FLP.c | 70 | ||||
-rw-r--r-- | drivers/opus/silk/float/wrappers_FLP.c | 199 | ||||
-rw-r--r-- | drivers/opus/silk/gain_quant.c | 138 | ||||
-rw-r--r-- | drivers/opus/silk/init_decoder.c | 53 | ||||
-rw-r--r-- | drivers/opus/silk/init_encoder.c | 61 | ||||
-rw-r--r-- | drivers/opus/silk/inner_prod_aligned.c | 44 | ||||
-rw-r--r-- | drivers/opus/silk/interpolate.c | 48 | ||||
-rw-r--r-- | drivers/opus/silk/lin2log.c | 43 | ||||
-rw-r--r-- | drivers/opus/silk/log2lin.c | 55 | ||||
-rw-r--r-- | drivers/opus/silk/macros.h | 150 | ||||
-rw-r--r-- | drivers/opus/silk/main.h | 471 | ||||
-rw-r--r-- | drivers/opus/silk/mips/NSQ_del_dec_mipsr1.h | 402 | ||||
-rw-r--r-- | drivers/opus/silk/pitch_est_defines.h | 88 | ||||
-rw-r--r-- | drivers/opus/silk/pitch_est_tables.c | 96 | ||||
-rw-r--r-- | drivers/opus/silk/process_NLSFs.c | 102 | ||||
-rw-r--r-- | drivers/opus/silk/quant_LTP_gains.c | 126 | ||||
-rw-r--r-- | drivers/opus/silk/resampler.c | 212 | ||||
-rw-r--r-- | drivers/opus/silk/resampler_down2.c | 71 | ||||
-rw-r--r-- | drivers/opus/silk/resampler_down2_3.c | 100 | ||||
-rw-r--r-- | drivers/opus/silk/resampler_private.h | 88 | ||||
-rw-r--r-- | drivers/opus/silk/resampler_private_AR2.c | 52 | ||||
-rw-r--r-- | drivers/opus/silk/resampler_private_IIR_FIR.c | 104 | ||||
-rw-r--r-- | drivers/opus/silk/resampler_private_down_FIR.c | 191 | ||||
-rw-r--r-- | drivers/opus/silk/resampler_private_up2_HQ.c | 110 | ||||
-rw-r--r-- | drivers/opus/silk/resampler_rom.c | 93 | ||||
-rw-r--r-- | drivers/opus/silk/resampler_rom.h | 68 | ||||
-rw-r--r-- | drivers/opus/silk/shell_coder.c | 148 | ||||
-rw-r--r-- | drivers/opus/silk/sigm_Q15.c | 73 | ||||
-rw-r--r-- | drivers/opus/silk/sort.c | 151 | ||||
-rw-r--r-- | drivers/opus/silk/stereo_LR_to_MS.c | 226 | ||||
-rw-r--r-- | drivers/opus/silk/stereo_MS_to_LR.c | 82 | ||||
-rw-r--r-- | drivers/opus/silk/stereo_decode_pred.c | 70 | ||||
-rw-r--r-- | drivers/opus/silk/stereo_encode_pred.c | 59 | ||||
-rw-r--r-- | drivers/opus/silk/stereo_find_predictor.c | 76 | ||||
-rw-r--r-- | drivers/opus/silk/stereo_quant_pred.c | 70 | ||||
-rw-r--r-- | drivers/opus/silk/structs.h | 327 | ||||
-rw-r--r-- | drivers/opus/silk/sum_sqr_shift.c | 83 | ||||
-rw-r--r-- | drivers/opus/silk/table_LSF_cos.c | 67 | ||||
-rw-r--r-- | drivers/opus/silk/tables.h | 122 | ||||
-rw-r--r-- | drivers/opus/silk/tables_LTP.c | 293 | ||||
-rw-r--r-- | drivers/opus/silk/tables_NLSF_CB_NB_MB.c | 156 | ||||
-rw-r--r-- | drivers/opus/silk/tables_NLSF_CB_WB.c | 195 | ||||
-rw-r--r-- | drivers/opus/silk/tables_gain.c | 60 | ||||
-rw-r--r-- | drivers/opus/silk/tables_other.c | 135 | ||||
-rw-r--r-- | drivers/opus/silk/tables_pitch_lag.c | 66 | ||||
-rw-r--r-- | drivers/opus/silk/tables_pulses_per_block.c | 261 | ||||
-rw-r--r-- | drivers/opus/silk/typedef.h | 78 | ||||
-rw-r--r-- | drivers/opus/silk/x86/NSQ_del_dec_sse.c | 854 | ||||
-rw-r--r-- | drivers/opus/silk/x86/NSQ_sse.c | 717 | ||||
-rw-r--r-- | drivers/opus/silk/x86/SigProc_FIX_sse.h | 91 | ||||
-rw-r--r-- | drivers/opus/silk/x86/VAD_sse.c | 274 | ||||
-rw-r--r-- | drivers/opus/silk/x86/VQ_WMat_EC_sse.c | 139 | ||||
-rw-r--r-- | drivers/opus/silk/x86/main_sse.h | 273 | ||||
-rw-r--r-- | drivers/opus/silk/x86/x86_silk_map.c | 171 | ||||
-rw-r--r-- | drivers/opus/stream.c | 364 | ||||
-rw-r--r-- | drivers/opus/wincerts.c | 168 | ||||
-rw-r--r-- | drivers/png/SCsub | 76 | ||||
-rw-r--r-- | drivers/png/image_loader_png.cpp | 3 | ||||
-rw-r--r-- | drivers/png/image_loader_png.h | 3 | ||||
-rw-r--r-- | drivers/png/resource_saver_png.cpp | 10 | ||||
-rw-r--r-- | drivers/pnm/SCsub | 10 | ||||
-rw-r--r-- | drivers/pnm/bitmap_loader_pnm.cpp | 252 | ||||
-rw-r--r-- | drivers/pnm/bitmap_loader_pnm.h | 50 | ||||
-rw-r--r-- | drivers/pulseaudio/SCsub | 4 | ||||
-rw-r--r-- | drivers/pulseaudio/audio_driver_pulseaudio.cpp | 4 | ||||
-rw-r--r-- | drivers/pvr/SCsub | 15 | ||||
-rw-r--r-- | drivers/register_driver_types.cpp | 252 | ||||
-rw-r--r-- | drivers/rtaudio/SCsub | 20 | ||||
-rw-r--r-- | drivers/rtaudio/audio_driver_rtaudio.cpp | 2 | ||||
-rw-r--r-- | drivers/rtaudio/audio_driver_rtaudio.h | 3 | ||||
-rw-r--r-- | drivers/speex/SCsub | 55 | ||||
-rw-r--r-- | drivers/speex/_kiss_fft_guts.h | 160 | ||||
-rw-r--r-- | drivers/speex/arch.h | 249 | ||||
-rw-r--r-- | drivers/speex/audio_stream_speex.cpp | 581 | ||||
-rw-r--r-- | drivers/speex/audio_stream_speex.h | 153 | ||||
-rw-r--r-- | drivers/speex/bits.c | 372 | ||||
-rw-r--r-- | drivers/speex/buffer.c | 176 | ||||
-rw-r--r-- | drivers/speex/cb_search.c | 612 | ||||
-rw-r--r-- | drivers/speex/cb_search.h | 103 | ||||
-rw-r--r-- | drivers/speex/cb_search_arm4.h | 137 | ||||
-rw-r--r-- | drivers/speex/cb_search_bfin.h | 112 | ||||
-rw-r--r-- | drivers/speex/cb_search_sse.h | 84 | ||||
-rw-r--r-- | drivers/speex/config.h | 52 | ||||
-rw-r--r-- | drivers/speex/echo_diagnostic.m | 72 | ||||
-rw-r--r-- | drivers/speex/exc_10_16_table.c | 50 | ||||
-rw-r--r-- | drivers/speex/exc_10_32_table.c | 66 | ||||
-rw-r--r-- | drivers/speex/exc_20_32_table.c | 66 | ||||
-rw-r--r-- | drivers/speex/exc_5_256_table.c | 290 | ||||
-rw-r--r-- | drivers/speex/exc_5_64_table.c | 98 | ||||
-rw-r--r-- | drivers/speex/exc_8_128_table.c | 162 | ||||
-rw-r--r-- | drivers/speex/fftwrap.c | 397 | ||||
-rw-r--r-- | drivers/speex/fftwrap.h | 58 | ||||
-rw-r--r-- | drivers/speex/filterbank.c | 227 | ||||
-rw-r--r-- | drivers/speex/filterbank.h | 66 | ||||
-rw-r--r-- | drivers/speex/filters.c | 821 | ||||
-rw-r--r-- | drivers/speex/filters.h | 90 | ||||
-rw-r--r-- | drivers/speex/filters_arm4.h | 96 | ||||
-rw-r--r-- | drivers/speex/filters_bfin.h | 515 | ||||
-rw-r--r-- | drivers/speex/filters_sse.h | 336 | ||||
-rw-r--r-- | drivers/speex/fixed_arm4.h | 148 | ||||
-rw-r--r-- | drivers/speex/fixed_arm5e.h | 178 | ||||
-rw-r--r-- | drivers/speex/fixed_bfin.h | 173 | ||||
-rw-r--r-- | drivers/speex/fixed_debug.h | 487 | ||||
-rw-r--r-- | drivers/speex/fixed_generic.h | 106 | ||||
-rw-r--r-- | drivers/speex/gain_table.c | 160 | ||||
-rw-r--r-- | drivers/speex/gain_table_lbr.c | 64 | ||||
-rw-r--r-- | drivers/speex/hexc_10_32_table.c | 66 | ||||
-rw-r--r-- | drivers/speex/hexc_table.c | 162 | ||||
-rw-r--r-- | drivers/speex/high_lsp_tables.c | 163 | ||||
-rw-r--r-- | drivers/speex/jitter.c | 843 | ||||
-rw-r--r-- | drivers/speex/kiss_fft.c | 523 | ||||
-rw-r--r-- | drivers/speex/kiss_fft.h | 108 | ||||
-rw-r--r-- | drivers/speex/kiss_fftr.c | 297 | ||||
-rw-r--r-- | drivers/speex/kiss_fftr.h | 51 | ||||
-rw-r--r-- | drivers/speex/lpc.c | 201 | ||||
-rw-r--r-- | drivers/speex/lpc.h | 53 | ||||
-rw-r--r-- | drivers/speex/lpc_bfin.h | 131 | ||||
-rw-r--r-- | drivers/speex/lsp.c | 656 | ||||
-rw-r--r-- | drivers/speex/lsp.h | 64 | ||||
-rw-r--r-- | drivers/speex/lsp_bfin.h | 89 | ||||
-rw-r--r-- | drivers/speex/lsp_tables_nb.c | 360 | ||||
-rw-r--r-- | drivers/speex/ltp.c | 839 | ||||
-rw-r--r-- | drivers/speex/ltp.h | 141 | ||||
-rw-r--r-- | drivers/speex/ltp_arm4.h | 187 | ||||
-rw-r--r-- | drivers/speex/ltp_bfin.h | 419 | ||||
-rw-r--r-- | drivers/speex/ltp_sse.h | 92 | ||||
-rw-r--r-- | drivers/speex/math_approx.h | 333 | ||||
-rw-r--r-- | drivers/speex/mdf.c | 1285 | ||||
-rw-r--r-- | drivers/speex/misc_bfin.h | 54 | ||||
-rw-r--r-- | drivers/speex/modes.c | 366 | ||||
-rw-r--r-- | drivers/speex/modes.h | 161 | ||||
-rw-r--r-- | drivers/speex/modes_wb.c | 300 | ||||
-rw-r--r-- | drivers/speex/nb_celp.c | 1903 | ||||
-rw-r--r-- | drivers/speex/nb_celp.h | 203 | ||||
-rw-r--r-- | drivers/speex/os_support.h | 172 | ||||
-rw-r--r-- | drivers/speex/preprocess.c | 1219 | ||||
-rw-r--r-- | drivers/speex/pseudofloat.h | 379 | ||||
-rw-r--r-- | drivers/speex/quant_lsp.c | 385 | ||||
-rw-r--r-- | drivers/speex/quant_lsp.h | 74 | ||||
-rw-r--r-- | drivers/speex/quant_lsp_bfin.h | 165 | ||||
-rw-r--r-- | drivers/speex/resample.c | 1131 | ||||
-rw-r--r-- | drivers/speex/resample_sse.h | 128 | ||||
-rw-r--r-- | drivers/speex/sb_celp.c | 1488 | ||||
-rw-r--r-- | drivers/speex/sb_celp.h | 155 | ||||
-rw-r--r-- | drivers/speex/scal.c | 289 | ||||
-rw-r--r-- | drivers/speex/smallft.c | 1261 | ||||
-rw-r--r-- | drivers/speex/smallft.h | 46 | ||||
-rw-r--r-- | drivers/speex/speex.c | 250 | ||||
-rw-r--r-- | drivers/speex/speex.h | 424 | ||||
-rw-r--r-- | drivers/speex/speex_bind.cpp | 64 | ||||
-rw-r--r-- | drivers/speex/speex_bind.h | 48 | ||||
-rw-r--r-- | drivers/speex/speex_bits.h | 174 | ||||
-rw-r--r-- | drivers/speex/speex_buffer.h | 68 | ||||
-rw-r--r-- | drivers/speex/speex_callbacks.c | 144 | ||||
-rw-r--r-- | drivers/speex/speex_callbacks.h | 134 | ||||
-rw-r--r-- | drivers/speex/speex_config_types.h | 11 | ||||
-rw-r--r-- | drivers/speex/speex_echo.h | 170 | ||||
-rw-r--r-- | drivers/speex/speex_header.c | 200 | ||||
-rw-r--r-- | drivers/speex/speex_header.h | 94 | ||||
-rw-r--r-- | drivers/speex/speex_jitter.h | 197 | ||||
-rw-r--r-- | drivers/speex/speex_preprocess.h | 219 | ||||
-rw-r--r-- | drivers/speex/speex_resampler.h | 340 | ||||
-rw-r--r-- | drivers/speex/speex_stereo.h | 91 | ||||
-rw-r--r-- | drivers/speex/speex_types.h | 126 | ||||
-rw-r--r-- | drivers/speex/stack_alloc.h | 115 | ||||
-rw-r--r-- | drivers/speex/stereo.c | 296 | ||||
-rw-r--r-- | drivers/speex/vbr.c | 275 | ||||
-rw-r--r-- | drivers/speex/vbr.h | 70 | ||||
-rw-r--r-- | drivers/speex/vorbis_psy.h | 97 | ||||
-rw-r--r-- | drivers/speex/vq.c | 147 | ||||
-rw-r--r-- | drivers/speex/vq.h | 54 | ||||
-rw-r--r-- | drivers/speex/vq_arm4.h | 115 | ||||
-rw-r--r-- | drivers/speex/vq_bfin.h | 107 | ||||
-rw-r--r-- | drivers/speex/vq_sse.h | 120 | ||||
-rw-r--r-- | drivers/speex/window.c | 102 | ||||
-rw-r--r-- | drivers/squish/SCsub | 23 | ||||
-rw-r--r-- | drivers/squish/alpha.cpp | 348 | ||||
-rw-r--r-- | drivers/squish/alpha.h | 41 | ||||
-rw-r--r-- | drivers/squish/clusterfit.cpp | 393 | ||||
-rw-r--r-- | drivers/squish/clusterfit.h | 61 | ||||
-rw-r--r-- | drivers/squish/colourblock.cpp | 214 | ||||
-rw-r--r-- | drivers/squish/colourblock.h | 41 | ||||
-rw-r--r-- | drivers/squish/colourfit.cpp | 50 | ||||
-rw-r--r-- | drivers/squish/colourfit.h | 53 | ||||
-rw-r--r-- | drivers/squish/colourset.cpp | 121 | ||||
-rw-r--r-- | drivers/squish/colourset.h | 58 | ||||
-rw-r--r-- | drivers/squish/config.h | 49 | ||||
-rw-r--r-- | drivers/squish/image_compress_squish.cpp | 91 | ||||
-rw-r--r-- | drivers/squish/image_compress_squish.h | 39 | ||||
-rw-r--r-- | drivers/squish/maths.cpp | 227 | ||||
-rw-r--r-- | drivers/squish/maths.h | 233 | ||||
-rw-r--r-- | drivers/squish/rangefit.cpp | 202 | ||||
-rw-r--r-- | drivers/squish/rangefit.h | 54 | ||||
-rw-r--r-- | drivers/squish/simd.h | 40 | ||||
-rw-r--r-- | drivers/squish/simd_float.h | 183 | ||||
-rw-r--r-- | drivers/squish/simd_sse.h | 180 | ||||
-rw-r--r-- | drivers/squish/simd_ve.h | 166 | ||||
-rw-r--r-- | drivers/squish/singlecolourfit.cpp | 172 | ||||
-rw-r--r-- | drivers/squish/singlecolourfit.h | 58 | ||||
-rw-r--r-- | drivers/squish/singlecolourlookup.inl | 1040 | ||||
-rw-r--r-- | drivers/squish/squish.cpp | 239 | ||||
-rw-r--r-- | drivers/squish/squish.h | 247 | ||||
-rw-r--r-- | drivers/theora/SCsub | 67 | ||||
-rw-r--r-- | drivers/theora/theora.exp | 55 | ||||
-rw-r--r-- | drivers/theora/video_stream_theora.cpp | 945 | ||||
-rw-r--r-- | drivers/theora/video_stream_theora.h | 204 | ||||
-rw-r--r-- | drivers/unix/SCsub | 4 | ||||
-rw-r--r-- | drivers/unix/ip_unix.cpp | 100 | ||||
-rw-r--r-- | drivers/unix/ip_unix.h | 2 | ||||
-rw-r--r-- | drivers/unix/os_unix.cpp | 2 | ||||
-rw-r--r-- | drivers/unix/packet_peer_udp_posix.cpp | 80 | ||||
-rw-r--r-- | drivers/unix/packet_peer_udp_posix.h | 8 | ||||
-rw-r--r-- | drivers/unix/socket_helpers.h | 70 | ||||
-rw-r--r-- | drivers/unix/stream_peer_tcp_posix.cpp | 26 | ||||
-rw-r--r-- | drivers/unix/tcp_server_posix.cpp | 32 | ||||
-rw-r--r-- | drivers/unix/tcp_server_posix.h | 2 | ||||
-rw-r--r-- | drivers/vorbis/SCsub | 36 | ||||
-rw-r--r-- | drivers/vorbis/audio_stream_ogg_vorbis.h | 142 | ||||
-rw-r--r-- | drivers/webp/SCsub | 115 | ||||
-rw-r--r-- | drivers/webp/dec/alpha.c | 232 | ||||
-rw-r--r-- | drivers/webp/dec/decode_vp8.h | 185 | ||||
-rw-r--r-- | drivers/webp/dec/webp.c | 846 | ||||
-rw-r--r-- | drivers/webp/demux/anim_decode.c | 442 | ||||
-rw-r--r-- | drivers/webp/demux/demux.c | 966 | ||||
-rw-r--r-- | drivers/webp/dsp/dsp.h | 569 | ||||
-rw-r--r-- | drivers/webp/dsp/lossless.h | 372 | ||||
-rw-r--r-- | drivers/webp/enc/alpha.c | 433 | ||||
-rw-r--r-- | drivers/webp/enc/backward_references.h | 206 | ||||
-rw-r--r-- | drivers/webp/enc/config.c | 173 | ||||
-rw-r--r-- | drivers/webp/enc/delta_palettization.c | 455 | ||||
-rw-r--r-- | drivers/webp/enc/delta_palettization.h | 25 | ||||
-rw-r--r-- | drivers/webp/enc/frame.c | 850 | ||||
-rw-r--r-- | drivers/webp/enc/histogram.c | 937 | ||||
-rw-r--r-- | drivers/webp/enc/histogram.h | 123 | ||||
-rw-r--r-- | drivers/webp/enc/syntax.c | 383 | ||||
-rw-r--r-- | drivers/webp/enc/vp8enci.h | 531 | ||||
-rw-r--r-- | drivers/webp/enc/vp8l.c | 1603 | ||||
-rw-r--r-- | drivers/webp/enc/vp8li.h | 81 | ||||
-rw-r--r-- | drivers/webp/extras.h | 51 | ||||
-rw-r--r-- | drivers/webp/image_loader_webp.cpp | 182 | ||||
-rw-r--r-- | drivers/webp/mux/anim_encode.c | 1534 | ||||
-rw-r--r-- | drivers/webp/mux/muxi.h | 232 | ||||
-rw-r--r-- | drivers/webp/utils/bit_reader.c | 227 | ||||
-rw-r--r-- | drivers/webp/utils/bit_reader.h | 182 | ||||
-rw-r--r-- | drivers/webp/utils/bit_reader_inl.h | 173 | ||||
-rw-r--r-- | drivers/webp/utils/bit_writer.h | 145 | ||||
-rw-r--r-- | drivers/webp/utils/color_cache.h | 80 | ||||
-rw-r--r-- | drivers/webp/utils/filters.h | 32 | ||||
-rw-r--r-- | drivers/webp/utils/huffman.c | 205 | ||||
-rw-r--r-- | drivers/webp/utils/huffman.h | 88 | ||||
-rw-r--r-- | drivers/webp/utils/huffman_encode.c | 417 | ||||
-rw-r--r-- | drivers/webp/utils/huffman_encode.h | 60 | ||||
-rw-r--r-- | drivers/webp/utils/quant_levels.h | 36 | ||||
-rw-r--r-- | drivers/webp/utils/quant_levels_dec.h | 35 | ||||
-rw-r--r-- | drivers/webp/utils/random.h | 63 | ||||
-rw-r--r-- | drivers/webp/utils/rescaler.h | 101 | ||||
-rw-r--r-- | drivers/webp/utils/thread.h | 93 | ||||
-rw-r--r-- | drivers/webp/utils/utils.c | 305 | ||||
-rw-r--r-- | drivers/webp/utils/utils.h | 182 | ||||
-rw-r--r-- | drivers/windows/SCsub | 4 | ||||
-rw-r--r-- | drivers/windows/dir_access_windows.cpp | 25 | ||||
-rw-r--r-- | drivers/windows/file_access_windows.cpp | 10 | ||||
-rw-r--r-- | drivers/windows/semaphore_windows.cpp | 2 | ||||
-rw-r--r-- | drivers/xaudio2/SCsub | 9 | ||||
-rw-r--r-- | drivers/xaudio2/audio_driver_xaudio2.cpp | 235 | ||||
-rw-r--r-- | drivers/xaudio2/audio_driver_xaudio2.h | 109 | ||||
-rw-r--r-- | drivers/zlib/SCsub | 26 | ||||
-rw-r--r-- | main/SCsub | 2 | ||||
-rw-r--r-- | main/input_default.cpp | 77 | ||||
-rw-r--r-- | main/input_default.h | 5 | ||||
-rw-r--r-- | main/main.cpp | 178 | ||||
-rwxr-xr-x | methods.py | 73 | ||||
-rw-r--r-- | modules/SCsub | 2 | ||||
-rw-r--r-- | modules/chibi/SCsub | 9 | ||||
-rw-r--r-- | modules/chibi/config.py | 6 | ||||
-rw-r--r-- | modules/chibi/cp_config.h (renamed from drivers/chibi/cp_config.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_envelope.cpp (renamed from drivers/chibi/cp_envelope.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_envelope.h (renamed from drivers/chibi/cp_envelope.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_file_access_wrapper.h (renamed from drivers/chibi/cp_file_access_wrapper.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_instrument.cpp (renamed from drivers/chibi/cp_instrument.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_instrument.h (renamed from drivers/chibi/cp_instrument.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_loader.h (renamed from drivers/chibi/cp_loader.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_loader_it.cpp (renamed from drivers/chibi/cp_loader_it.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_loader_it.h (renamed from drivers/chibi/cp_loader_it.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_loader_it_info.cpp (renamed from drivers/chibi/cp_loader_it_info.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_loader_it_instruments.cpp (renamed from drivers/chibi/cp_loader_it_instruments.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_loader_it_patterns.cpp (renamed from drivers/chibi/cp_loader_it_patterns.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_loader_it_samples.cpp (renamed from drivers/chibi/cp_loader_it_samples.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_loader_mod.cpp (renamed from drivers/chibi/cp_loader_mod.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_loader_mod.h (renamed from drivers/chibi/cp_loader_mod.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_loader_s3m.cpp (renamed from drivers/chibi/cp_loader_s3m.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_loader_s3m.h (renamed from drivers/chibi/cp_loader_s3m.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_loader_xm.cpp (renamed from drivers/chibi/cp_loader_xm.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_loader_xm.h (renamed from drivers/chibi/cp_loader_xm.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_mixer.h (renamed from drivers/chibi/cp_mixer.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_note.h (renamed from drivers/chibi/cp_note.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_order.h (renamed from drivers/chibi/cp_order.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_pattern.cpp (renamed from drivers/chibi/cp_pattern.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_pattern.h (renamed from drivers/chibi/cp_pattern.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_player_data.cpp (renamed from drivers/chibi/cp_player_data.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_player_data.h (renamed from drivers/chibi/cp_player_data.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_player_data_control.cpp (renamed from drivers/chibi/cp_player_data_control.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_player_data_effects.cpp (renamed from drivers/chibi/cp_player_data_effects.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_player_data_envelopes.cpp (renamed from drivers/chibi/cp_player_data_envelopes.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_player_data_events.cpp (renamed from drivers/chibi/cp_player_data_events.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_player_data_filter.cpp (renamed from drivers/chibi/cp_player_data_filter.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_player_data_nna.cpp (renamed from drivers/chibi/cp_player_data_nna.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_player_data_notes.cpp (renamed from drivers/chibi/cp_player_data_notes.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_player_data_utils.cpp (renamed from drivers/chibi/cp_player_data_utils.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_sample.cpp (renamed from drivers/chibi/cp_sample.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_sample.h (renamed from drivers/chibi/cp_sample.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_sample_defs.h (renamed from drivers/chibi/cp_sample_defs.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_sample_manager.cpp (renamed from drivers/chibi/cp_sample_manager.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_sample_manager.h (renamed from drivers/chibi/cp_sample_manager.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_song.cpp (renamed from drivers/chibi/cp_song.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_song.h (renamed from drivers/chibi/cp_song.h) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_tables.cpp (renamed from drivers/chibi/cp_tables.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/cp_tables.h (renamed from drivers/chibi/cp_tables.h) | 0 | ||||
-rw-r--r-- | modules/chibi/event_stream_chibi.cpp (renamed from drivers/chibi/event_stream_chibi.cpp) | 0 | ||||
-rw-r--r-- | modules/chibi/event_stream_chibi.h (renamed from drivers/chibi/event_stream_chibi.h) | 0 | ||||
-rw-r--r-- | modules/chibi/register_types.cpp | 41 | ||||
-rw-r--r-- | modules/chibi/register_types.h | 30 | ||||
-rw-r--r-- | modules/cscript/SCsub | 4 | ||||
-rw-r--r-- | modules/dds/SCsub | 8 | ||||
-rw-r--r-- | modules/dds/config.py | 6 | ||||
-rw-r--r-- | modules/dds/register_types.cpp | 44 | ||||
-rw-r--r-- | modules/dds/register_types.h | 30 | ||||
-rw-r--r-- | modules/dds/texture_loader_dds.cpp (renamed from drivers/dds/texture_loader_dds.cpp) | 0 | ||||
-rw-r--r-- | modules/dds/texture_loader_dds.h (renamed from drivers/dds/texture_loader_dds.h) | 0 | ||||
-rw-r--r-- | modules/enet/SCsub | 30 | ||||
-rw-r--r-- | modules/enet/config.py | 7 | ||||
-rw-r--r-- | modules/enet/networked_multiplayer_enet.cpp | 82 | ||||
-rw-r--r-- | modules/enet/networked_multiplayer_enet.h | 35 | ||||
-rw-r--r-- | modules/enet/win32.c | 422 | ||||
-rw-r--r-- | modules/etc1/SCsub | 20 | ||||
-rw-r--r-- | modules/etc1/config.py | 6 | ||||
-rw-r--r-- | modules/etc1/image_etc.cpp (renamed from drivers/etc1/image_etc.cpp) | 0 | ||||
-rw-r--r-- | modules/etc1/image_etc.h (renamed from drivers/etc1/image_etc.h) | 0 | ||||
-rw-r--r-- | modules/etc1/register_types.cpp | 47 | ||||
-rw-r--r-- | modules/etc1/register_types.h | 30 | ||||
-rw-r--r-- | modules/etc1/texture_loader_pkm.cpp (renamed from drivers/etc1/texture_loader_pkm.cpp) | 0 | ||||
-rw-r--r-- | modules/etc1/texture_loader_pkm.h (renamed from drivers/etc1/texture_loader_pkm.h) | 0 | ||||
-rw-r--r-- | modules/freetype/SCsub | 90 | ||||
-rw-r--r-- | modules/freetype/config.py | 6 | ||||
-rw-r--r-- | modules/freetype/register_types.cpp | 33 | ||||
-rw-r--r-- | modules/freetype/register_types.h | 30 | ||||
-rw-r--r-- | modules/freetype/winrtdef.h | 32 | ||||
-rw-r--r-- | modules/gdscript/SCsub | 4 | ||||
-rw-r--r-- | modules/gdscript/gd_compiler.cpp | 65 | ||||
-rw-r--r-- | modules/gdscript/gd_editor.cpp | 468 | ||||
-rw-r--r-- | modules/gdscript/gd_function.cpp | 2 | ||||
-rw-r--r-- | modules/gdscript/gd_functions.cpp | 18 | ||||
-rw-r--r-- | modules/gdscript/gd_functions.h | 1 | ||||
-rw-r--r-- | modules/gdscript/gd_parser.cpp | 257 | ||||
-rw-r--r-- | modules/gdscript/gd_parser.h | 6 | ||||
-rw-r--r-- | modules/gdscript/gd_script.cpp | 2 | ||||
-rw-r--r-- | modules/gdscript/gd_script.h | 17 | ||||
-rw-r--r-- | modules/gdscript/gd_tokenizer.cpp | 18 | ||||
-rw-r--r-- | modules/gdscript/gd_tokenizer.h | 1 | ||||
-rw-r--r-- | modules/gridmap/SCsub | 6 | ||||
-rw-r--r-- | modules/ik/SCsub | 6 | ||||
-rw-r--r-- | modules/jpg/SCsub | 20 | ||||
-rw-r--r-- | modules/jpg/config.py | 6 | ||||
-rw-r--r-- | modules/jpg/image_loader_jpegd.cpp | 144 | ||||
-rw-r--r-- | modules/jpg/image_loader_jpegd.h (renamed from drivers/jpegd/image_loader_jpegd.h) | 0 | ||||
-rw-r--r-- | modules/jpg/register_types.cpp | 44 | ||||
-rw-r--r-- | modules/jpg/register_types.h | 30 | ||||
-rw-r--r-- | modules/mpc/SCsub | 28 | ||||
-rw-r--r-- | modules/mpc/audio_stream_mpc.cpp (renamed from drivers/mpc/audio_stream_mpc.cpp) | 0 | ||||
-rw-r--r-- | modules/mpc/audio_stream_mpc.h | 146 | ||||
-rw-r--r-- | modules/mpc/config.py | 6 | ||||
-rw-r--r-- | modules/mpc/register_types.cpp | 45 | ||||
-rw-r--r-- | modules/mpc/register_types.h | 30 | ||||
-rw-r--r-- | modules/ogg/SCsub | 21 | ||||
-rw-r--r-- | modules/ogg/config.py | 6 | ||||
-rw-r--r-- | modules/ogg/register_types.cpp | 35 | ||||
-rw-r--r-- | modules/ogg/register_types.h | 30 | ||||
-rw-r--r-- | modules/openssl/SCsub | 687 | ||||
-rw-r--r-- | modules/openssl/config.py | 6 | ||||
-rw-r--r-- | modules/openssl/curl_hostcheck.c | 217 | ||||
-rw-r--r-- | modules/openssl/curl_hostcheck.h | 39 | ||||
-rw-r--r-- | modules/openssl/register_types.cpp | 42 | ||||
-rw-r--r-- | modules/openssl/register_types.h | 30 | ||||
-rw-r--r-- | modules/openssl/stream_peer_openssl.cpp | 646 | ||||
-rw-r--r-- | modules/openssl/stream_peer_openssl.h | 109 | ||||
-rw-r--r-- | modules/opus/SCsub | 215 | ||||
-rw-r--r-- | modules/opus/audio_stream_opus.cpp (renamed from drivers/opus/audio_stream_opus.cpp) | 0 | ||||
-rw-r--r-- | modules/opus/audio_stream_opus.h | 141 | ||||
-rw-r--r-- | modules/opus/config.py | 6 | ||||
-rw-r--r-- | modules/opus/register_types.cpp | 45 | ||||
-rw-r--r-- | modules/opus/register_types.h | 30 | ||||
-rw-r--r-- | modules/pbm/SCsub | 8 | ||||
-rw-r--r-- | modules/pbm/bitmap_loader_pbm.cpp | 252 | ||||
-rw-r--r-- | modules/pbm/bitmap_loader_pbm.h | 50 | ||||
-rw-r--r-- | modules/pbm/config.py | 6 | ||||
-rw-r--r-- | modules/pbm/register_types.cpp | 44 | ||||
-rw-r--r-- | modules/pbm/register_types.h | 30 | ||||
-rw-r--r-- | modules/pvr/SCsub | 24 | ||||
-rw-r--r-- | modules/pvr/config.py | 6 | ||||
-rw-r--r-- | modules/pvr/register_types.cpp | 44 | ||||
-rw-r--r-- | modules/pvr/register_types.h | 30 | ||||
-rw-r--r-- | modules/pvr/texture_loader_pvr.cpp (renamed from drivers/pvr/texture_loader_pvr.cpp) | 0 | ||||
-rw-r--r-- | modules/pvr/texture_loader_pvr.h (renamed from drivers/pvr/texture_loader_pvr.h) | 0 | ||||
-rw-r--r-- | modules/squish/SCsub | 29 | ||||
-rw-r--r-- | modules/squish/config.py | 10 | ||||
-rw-r--r-- | modules/squish/image_compress_squish.cpp | 92 | ||||
-rw-r--r-- | modules/squish/image_compress_squish.h | 36 | ||||
-rw-r--r-- | modules/squish/register_types.cpp | 42 | ||||
-rw-r--r-- | modules/squish/register_types.h | 32 | ||||
-rw-r--r-- | modules/theora/SCsub | 83 | ||||
-rw-r--r-- | modules/theora/config.py | 6 | ||||
-rw-r--r-- | modules/theora/register_types.cpp | 45 | ||||
-rw-r--r-- | modules/theora/register_types.h | 30 | ||||
-rw-r--r-- | modules/theora/video_stream_theora.cpp | 940 | ||||
-rw-r--r-- | modules/theora/video_stream_theora.h | 199 | ||||
-rw-r--r-- | modules/theora/yuv2rgb.h (renamed from drivers/theora/yuv2rgb.h) | 0 | ||||
-rw-r--r-- | modules/visual_script/SCsub | 4 | ||||
-rw-r--r-- | modules/visual_script/register_types.cpp | 4 | ||||
-rw-r--r-- | modules/visual_script/visual_script.cpp | 60 | ||||
-rw-r--r-- | modules/visual_script/visual_script.h | 3 | ||||
-rw-r--r-- | modules/visual_script/visual_script_builtin_funcs.cpp | 797 | ||||
-rw-r--r-- | modules/visual_script/visual_script_builtin_funcs.h | 6 | ||||
-rw-r--r-- | modules/visual_script/visual_script_editor.cpp | 46 | ||||
-rw-r--r-- | modules/visual_script/visual_script_editor.h | 1 | ||||
-rw-r--r-- | modules/visual_script/visual_script_expression.cpp | 1523 | ||||
-rw-r--r-- | modules/visual_script/visual_script_expression.h | 280 | ||||
-rw-r--r-- | modules/visual_script/visual_script_func_nodes.cpp | 8 | ||||
-rw-r--r-- | modules/visual_script/visual_script_nodes.cpp | 2 | ||||
-rw-r--r-- | modules/vorbis/SCsub | 49 | ||||
-rw-r--r-- | modules/vorbis/audio_stream_ogg_vorbis.cpp (renamed from drivers/vorbis/audio_stream_ogg_vorbis.cpp) | 0 | ||||
-rw-r--r-- | modules/vorbis/audio_stream_ogg_vorbis.h | 142 | ||||
-rw-r--r-- | modules/vorbis/config.py | 6 | ||||
-rw-r--r-- | modules/vorbis/register_types.cpp | 45 | ||||
-rw-r--r-- | modules/vorbis/register_types.h | 30 | ||||
-rw-r--r-- | modules/webp/SCsub | 121 | ||||
-rw-r--r-- | modules/webp/config.py | 6 | ||||
-rw-r--r-- | modules/webp/image_loader_webp.cpp | 183 | ||||
-rw-r--r-- | modules/webp/image_loader_webp.h (renamed from drivers/webp/image_loader_webp.h) | 0 | ||||
-rw-r--r-- | modules/webp/register_types.cpp | 44 | ||||
-rw-r--r-- | modules/webp/register_types.h | 30 | ||||
-rw-r--r-- | platform/android/SCsub | 2 | ||||
-rw-r--r-- | platform/android/build.gradle.template | 1 | ||||
-rw-r--r-- | platform/android/detect.py | 34 | ||||
-rw-r--r-- | platform/android/dir_access_jandroid.cpp | 1 | ||||
-rw-r--r-- | platform/android/export/export.cpp | 44 | ||||
-rw-r--r-- | platform/android/os_android.cpp | 13 | ||||
-rw-r--r-- | platform/bb10/SCsub | 2 | ||||
-rw-r--r-- | platform/bb10/detect.py | 6 | ||||
-rw-r--r-- | platform/haiku/SCsub | 2 | ||||
-rw-r--r-- | platform/haiku/detect.py | 2 | ||||
-rw-r--r-- | platform/iphone/SCsub | 2 | ||||
-rw-r--r-- | platform/iphone/detect.py | 4 | ||||
-rw-r--r-- | platform/javascript/SCsub | 2 | ||||
-rw-r--r-- | platform/javascript/detect.py | 23 | ||||
-rw-r--r-- | platform/javascript/export/export.cpp | 4 | ||||
-rw-r--r-- | platform/osx/SCsub | 3 | ||||
-rw-r--r-- | platform/osx/detect.py | 14 | ||||
-rw-r--r-- | platform/osx/export/export.cpp | 2 | ||||
-rw-r--r-- | platform/osx/joystick_osx.cpp | 623 | ||||
-rw-r--r-- | platform/osx/joystick_osx.h | 125 | ||||
-rw-r--r-- | platform/osx/os_osx.h | 3 | ||||
-rw-r--r-- | platform/osx/os_osx.mm | 9 | ||||
-rw-r--r-- | platform/osx/platform_config.h | 2 | ||||
-rw-r--r-- | platform/server/SCsub | 2 | ||||
-rw-r--r-- | platform/server/detect.py | 4 | ||||
-rw-r--r-- | platform/windows/SCsub | 2 | ||||
-rw-r--r-- | platform/windows/detect.py | 111 | ||||
-rw-r--r-- | platform/windows/os_windows.cpp | 25 | ||||
-rw-r--r-- | platform/windows/os_windows.h | 7 | ||||
-rw-r--r-- | platform/windows/packet_peer_udp_winsock.cpp | 78 | ||||
-rw-r--r-- | platform/windows/packet_peer_udp_winsock.h | 8 | ||||
-rw-r--r-- | platform/windows/platform_config.h | 4 | ||||
-rw-r--r-- | platform/windows/stream_peer_winsock.cpp | 28 | ||||
-rw-r--r-- | platform/windows/tcp_server_winsock.cpp | 21 | ||||
-rw-r--r-- | platform/windows/tcp_server_winsock.h | 2 | ||||
-rw-r--r-- | platform/winrt/SCsub | 16 | ||||
-rw-r--r-- | platform/winrt/app.cpp | 302 | ||||
-rw-r--r-- | platform/winrt/app.h | 53 | ||||
-rw-r--r-- | platform/winrt/detect.py | 172 | ||||
-rw-r--r-- | platform/winrt/export/export.cpp | 2391 | ||||
-rw-r--r-- | platform/winrt/export/export.h | 29 | ||||
-rw-r--r-- | platform/winrt/gl_context_egl.cpp | 15 | ||||
-rw-r--r-- | platform/winrt/gl_context_egl.h | 5 | ||||
-rw-r--r-- | platform/winrt/include/EGL/egl.h | 298 | ||||
-rw-r--r-- | platform/winrt/include/EGL/eglext.h | 766 | ||||
-rw-r--r-- | platform/winrt/include/EGL/eglplatform.h | 131 | ||||
-rw-r--r-- | platform/winrt/include/GLES2/gl2.h | 620 | ||||
-rw-r--r-- | platform/winrt/include/GLES2/gl2ext.h | 2013 | ||||
-rw-r--r-- | platform/winrt/include/GLES2/gl2platform.h | 30 | ||||
-rw-r--r-- | platform/winrt/include/GLES3/gl3.h | 1061 | ||||
-rw-r--r-- | platform/winrt/include/GLES3/gl3ext.h | 24 | ||||
-rw-r--r-- | platform/winrt/include/GLES3/gl3platform.h | 30 | ||||
-rw-r--r-- | platform/winrt/include/GLSLANG/ShaderLang.h | 411 | ||||
-rw-r--r-- | platform/winrt/include/GLSLANG/ShaderVars.h | 185 | ||||
-rw-r--r-- | platform/winrt/include/KHR/khrplatform.h | 282 | ||||
-rw-r--r-- | platform/winrt/include/LICENSE.ANGLE.txt | 32 | ||||
-rw-r--r-- | platform/winrt/include/angle_gl.h | 23 | ||||
-rw-r--r-- | platform/winrt/include/angle_windowsstore.h | 37 | ||||
-rw-r--r-- | platform/winrt/joystick_winrt.cpp | 147 | ||||
-rw-r--r-- | platform/winrt/joystick_winrt.h | 81 | ||||
-rw-r--r-- | platform/winrt/os_winrt.cpp | 445 | ||||
-rw-r--r-- | platform/winrt/os_winrt.h | 108 | ||||
-rw-r--r-- | platform/winrt/thread_winrt.cpp | 4 | ||||
-rw-r--r-- | platform/x11/SCsub | 2 | ||||
-rw-r--r-- | platform/x11/detect.py | 55 | ||||
-rw-r--r-- | platform/x11/os_x11.cpp | 13 | ||||
-rw-r--r-- | platform/x11/platform_config.h | 4 | ||||
-rw-r--r-- | scene/2d/SCsub | 2 | ||||
-rw-r--r-- | scene/2d/area_2d.cpp | 4 | ||||
-rw-r--r-- | scene/2d/camera_2d.cpp | 70 | ||||
-rw-r--r-- | scene/2d/camera_2d.h | 5 | ||||
-rw-r--r-- | scene/2d/light_2d.cpp | 34 | ||||
-rw-r--r-- | scene/2d/light_2d.h | 4 | ||||
-rw-r--r-- | scene/2d/node_2d.cpp | 2 | ||||
-rw-r--r-- | scene/2d/node_2d.h | 4 | ||||
-rw-r--r-- | scene/2d/polygon_2d.cpp | 4 | ||||
-rw-r--r-- | scene/2d/polygon_2d.h | 6 | ||||
-rw-r--r-- | scene/2d/ray_cast_2d.cpp | 48 | ||||
-rw-r--r-- | scene/2d/ray_cast_2d.h | 3 | ||||
-rw-r--r-- | scene/2d/sprite.cpp | 1 | ||||
-rw-r--r-- | scene/3d/SCsub | 2 | ||||
-rw-r--r-- | scene/3d/area.cpp | 4 | ||||
-rw-r--r-- | scene/3d/camera.cpp | 12 | ||||
-rw-r--r-- | scene/3d/immediate_geometry.cpp | 9 | ||||
-rw-r--r-- | scene/3d/immediate_geometry.h | 2 | ||||
-rw-r--r-- | scene/3d/light.cpp | 6 | ||||
-rw-r--r-- | scene/3d/ray_cast.cpp | 48 | ||||
-rw-r--r-- | scene/3d/ray_cast.h | 2 | ||||
-rw-r--r-- | scene/3d/remote_transform.cpp | 132 | ||||
-rw-r--r-- | scene/3d/remote_transform.h | 30 | ||||
-rw-r--r-- | scene/3d/visual_instance.cpp | 4 | ||||
-rw-r--r-- | scene/SCsub | 2 | ||||
-rw-r--r-- | scene/animation/SCsub | 2 | ||||
-rw-r--r-- | scene/animation/tween.cpp | 25 | ||||
-rw-r--r-- | scene/audio/SCsub | 2 | ||||
-rw-r--r-- | scene/gui/SCsub | 2 | ||||
-rw-r--r-- | scene/gui/base_button.cpp | 10 | ||||
-rw-r--r-- | scene/gui/button_array.cpp | 60 | ||||
-rw-r--r-- | scene/gui/button_array.h | 8 | ||||
-rw-r--r-- | scene/gui/button_group.cpp | 4 | ||||
-rw-r--r-- | scene/gui/color_picker.cpp | 17 | ||||
-rw-r--r-- | scene/gui/color_rect.cpp | 36 | ||||
-rw-r--r-- | scene/gui/color_rect.h | 22 | ||||
-rw-r--r-- | scene/gui/control.cpp | 57 | ||||
-rw-r--r-- | scene/gui/control.h | 2 | ||||
-rw-r--r-- | scene/gui/dialogs.cpp | 38 | ||||
-rw-r--r-- | scene/gui/graph_edit.cpp | 34 | ||||
-rw-r--r-- | scene/gui/graph_node.cpp | 5 | ||||
-rw-r--r-- | scene/gui/item_list.cpp | 55 | ||||
-rw-r--r-- | scene/gui/item_list.h | 6 | ||||
-rw-r--r-- | scene/gui/line_edit.cpp | 100 | ||||
-rw-r--r-- | scene/gui/line_edit.h | 8 | ||||
-rw-r--r-- | scene/gui/panel.h | 2 | ||||
-rw-r--r-- | scene/gui/popup_menu.cpp | 38 | ||||
-rw-r--r-- | scene/gui/popup_menu.h | 2 | ||||
-rw-r--r-- | scene/gui/scroll_container.cpp | 4 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 229 | ||||
-rw-r--r-- | scene/gui/text_edit.h | 25 | ||||
-rw-r--r-- | scene/gui/texture_progress.cpp | 1 | ||||
-rw-r--r-- | scene/gui/tree.cpp | 44 | ||||
-rw-r--r-- | scene/gui/tree.h | 3 | ||||
-rw-r--r-- | scene/gui/video_player.cpp | 3 | ||||
-rw-r--r-- | scene/io/SCsub | 2 | ||||
-rw-r--r-- | scene/io/resource_format_image.cpp | 118 | ||||
-rw-r--r-- | scene/io/resource_format_image.h | 2 | ||||
-rw-r--r-- | scene/main/SCsub | 2 | ||||
-rw-r--r-- | scene/main/canvas_layer.cpp | 60 | ||||
-rw-r--r-- | scene/main/canvas_layer.h | 14 | ||||
-rw-r--r-- | scene/main/http_request.cpp | 12 | ||||
-rw-r--r-- | scene/main/http_request.h | 4 | ||||
-rw-r--r-- | scene/main/node.cpp | 168 | ||||
-rw-r--r-- | scene/main/node.h | 9 | ||||
-rw-r--r-- | scene/main/scene_main_loop.cpp | 8 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 88 | ||||
-rw-r--r-- | scene/main/viewport.h | 4 | ||||
-rw-r--r-- | scene/register_scene_types.cpp | 4 | ||||
-rw-r--r-- | scene/resources/SCsub | 2 | ||||
-rw-r--r-- | scene/resources/default_theme/SCsub | 2 | ||||
-rw-r--r-- | scene/resources/default_theme/button_pressed.png | bin | 610 -> 499 bytes | |||
-rw-r--r-- | scene/resources/default_theme/default_theme.cpp | 33 | ||||
-rw-r--r-- | scene/resources/default_theme/default_theme.h | 2 | ||||
-rw-r--r-- | scene/resources/shader_graph.cpp | 4 | ||||
-rw-r--r-- | scene/resources/world.cpp | 4 | ||||
-rw-r--r-- | scene/resources/world_2d.cpp | 6 | ||||
-rw-r--r-- | scene/resources/world_2d.h | 1 | ||||
-rw-r--r-- | servers/SCsub | 2 | ||||
-rw-r--r-- | servers/audio/SCsub | 2 | ||||
-rw-r--r-- | servers/physics/SCsub | 2 | ||||
-rw-r--r-- | servers/physics/joints/SCsub | 2 | ||||
-rw-r--r-- | servers/physics/space_sw.cpp | 2 | ||||
-rw-r--r-- | servers/physics/space_sw.h | 1 | ||||
-rw-r--r-- | servers/physics_2d/SCsub | 2 | ||||
-rw-r--r-- | servers/physics_2d/shape_2d_sw.cpp | 14 | ||||
-rw-r--r-- | servers/physics_2d/shape_2d_sw.h | 18 | ||||
-rw-r--r-- | servers/physics_2d/space_2d_sw.cpp | 19 | ||||
-rw-r--r-- | servers/physics_2d/space_2d_sw.h | 1 | ||||
-rw-r--r-- | servers/spatial_sound/SCsub | 2 | ||||
-rw-r--r-- | servers/spatial_sound_2d/SCsub | 2 | ||||
-rw-r--r-- | servers/visual/SCsub | 2 | ||||
-rw-r--r-- | servers/visual/rasterizer.cpp | 3 | ||||
-rw-r--r-- | servers/visual/shader_language.cpp | 1 | ||||
-rw-r--r-- | servers/visual/visual_server_raster.cpp | 9 | ||||
-rw-r--r-- | servers/visual/visual_server_raster.h | 1 | ||||
-rw-r--r-- | servers/visual/visual_server_wrap_mt.h | 1 | ||||
-rw-r--r-- | servers/visual_server.cpp | 4 | ||||
-rw-r--r-- | servers/visual_server.h | 1 | ||||
-rw-r--r-- | thirdparty/README.md | 218 | ||||
-rw-r--r-- | thirdparty/enet/LICENSE | 7 | ||||
-rw-r--r-- | thirdparty/enet/callbacks.c (renamed from modules/enet/callbacks.c) | 0 | ||||
-rw-r--r-- | thirdparty/enet/compress.c (renamed from modules/enet/compress.c) | 0 | ||||
-rw-r--r-- | thirdparty/enet/enet/callbacks.h (renamed from modules/enet/enet/callbacks.h) | 0 | ||||
-rw-r--r-- | thirdparty/enet/enet/enet.h (renamed from modules/enet/enet/enet.h) | 0 | ||||
-rw-r--r-- | thirdparty/enet/enet/list.h (renamed from modules/enet/enet/list.h) | 0 | ||||
-rw-r--r-- | thirdparty/enet/enet/protocol.h (renamed from modules/enet/enet/protocol.h) | 0 | ||||
-rw-r--r-- | thirdparty/enet/enet/time.h (renamed from modules/enet/enet/time.h) | 0 | ||||
-rw-r--r-- | thirdparty/enet/enet/types.h (renamed from modules/enet/enet/types.h) | 0 | ||||
-rw-r--r-- | thirdparty/enet/enet/unix.h (renamed from modules/enet/enet/unix.h) | 0 | ||||
-rw-r--r-- | thirdparty/enet/enet/utility.h (renamed from modules/enet/enet/utility.h) | 0 | ||||
-rw-r--r-- | thirdparty/enet/enet/win32.h (renamed from modules/enet/enet/win32.h) | 0 | ||||
-rw-r--r-- | thirdparty/enet/host.c (renamed from modules/enet/host.c) | 0 | ||||
-rw-r--r-- | thirdparty/enet/list.c (renamed from modules/enet/list.c) | 0 | ||||
-rw-r--r-- | thirdparty/enet/packet.c (renamed from modules/enet/packet.c) | 0 | ||||
-rw-r--r-- | thirdparty/enet/peer.c (renamed from modules/enet/peer.c) | 0 | ||||
-rw-r--r-- | thirdparty/enet/protocol.c (renamed from modules/enet/protocol.c) | 0 | ||||
-rw-r--r-- | thirdparty/enet/unix.c (renamed from modules/enet/unix.c) | 0 | ||||
-rw-r--r-- | thirdparty/enet/win32.c | 435 | ||||
-rw-r--r-- | thirdparty/freetype/FTL.TXT (renamed from drivers/freetype/FTL.TXT) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/LICENSE.TXT (renamed from drivers/freetype/LICENSE.TXT) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/config/ftconfig.h (renamed from drivers/freetype/include/freetype/config/ftconfig.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/config/ftheader.h (renamed from drivers/freetype/include/freetype/config/ftheader.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/config/ftmodule.h (renamed from drivers/freetype/include/freetype/config/ftmodule.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/config/ftoption.h (renamed from drivers/freetype/include/freetype/config/ftoption.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/config/ftstdlib.h (renamed from drivers/freetype/include/freetype/config/ftstdlib.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/freetype.h (renamed from drivers/freetype/include/freetype/freetype.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftadvanc.h (renamed from drivers/freetype/include/freetype/ftadvanc.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftautoh.h (renamed from drivers/freetype/include/freetype/ftautoh.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftbbox.h (renamed from drivers/freetype/include/freetype/ftbbox.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftbdf.h (renamed from drivers/freetype/include/freetype/ftbdf.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftbitmap.h (renamed from drivers/freetype/include/freetype/ftbitmap.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftbzip2.h (renamed from drivers/freetype/include/freetype/ftbzip2.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftcache.h (renamed from drivers/freetype/include/freetype/ftcache.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftcffdrv.h (renamed from drivers/freetype/include/freetype/ftcffdrv.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftchapters.h (renamed from drivers/freetype/include/freetype/ftchapters.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftcid.h (renamed from drivers/freetype/include/freetype/ftcid.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/fterrdef.h (renamed from drivers/freetype/include/freetype/fterrdef.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/fterrors.h (renamed from drivers/freetype/include/freetype/fterrors.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftfntfmt.h (renamed from drivers/freetype/include/freetype/ftfntfmt.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftgasp.h (renamed from drivers/freetype/include/freetype/ftgasp.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftglyph.h (renamed from drivers/freetype/include/freetype/ftglyph.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftgxval.h (renamed from drivers/freetype/include/freetype/ftgxval.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftgzip.h (renamed from drivers/freetype/include/freetype/ftgzip.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftimage.h (renamed from drivers/freetype/include/freetype/ftimage.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftincrem.h (renamed from drivers/freetype/include/freetype/ftincrem.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftlcdfil.h (renamed from drivers/freetype/include/freetype/ftlcdfil.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftlist.h (renamed from drivers/freetype/include/freetype/ftlist.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftlzw.h (renamed from drivers/freetype/include/freetype/ftlzw.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftmac.h (renamed from drivers/freetype/include/freetype/ftmac.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftmm.h (renamed from drivers/freetype/include/freetype/ftmm.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftmodapi.h (renamed from drivers/freetype/include/freetype/ftmodapi.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftmoderr.h (renamed from drivers/freetype/include/freetype/ftmoderr.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftotval.h (renamed from drivers/freetype/include/freetype/ftotval.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftoutln.h (renamed from drivers/freetype/include/freetype/ftoutln.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftpfr.h (renamed from drivers/freetype/include/freetype/ftpfr.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftrender.h (renamed from drivers/freetype/include/freetype/ftrender.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftsizes.h (renamed from drivers/freetype/include/freetype/ftsizes.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftsnames.h (renamed from drivers/freetype/include/freetype/ftsnames.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftstroke.h (renamed from drivers/freetype/include/freetype/ftstroke.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftsynth.h (renamed from drivers/freetype/include/freetype/ftsynth.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftsystem.h (renamed from drivers/freetype/include/freetype/ftsystem.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/fttrigon.h (renamed from drivers/freetype/include/freetype/fttrigon.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftttdrv.h (renamed from drivers/freetype/include/freetype/ftttdrv.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/fttypes.h (renamed from drivers/freetype/include/freetype/fttypes.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ftwinfnt.h (renamed from drivers/freetype/include/freetype/ftwinfnt.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/autohint.h (renamed from drivers/freetype/include/freetype/internal/autohint.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/ftcalc.h (renamed from drivers/freetype/include/freetype/internal/ftcalc.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/ftdebug.h (renamed from drivers/freetype/include/freetype/internal/ftdebug.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/ftdriver.h (renamed from drivers/freetype/include/freetype/internal/ftdriver.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/ftgloadr.h (renamed from drivers/freetype/include/freetype/internal/ftgloadr.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/fthash.h (renamed from drivers/freetype/include/freetype/internal/fthash.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/ftmemory.h (renamed from drivers/freetype/include/freetype/internal/ftmemory.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/ftobjs.h (renamed from drivers/freetype/include/freetype/internal/ftobjs.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/ftpic.h (renamed from drivers/freetype/include/freetype/internal/ftpic.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/ftrfork.h (renamed from drivers/freetype/include/freetype/internal/ftrfork.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/ftserv.h (renamed from drivers/freetype/include/freetype/internal/ftserv.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/ftstream.h (renamed from drivers/freetype/include/freetype/internal/ftstream.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/fttrace.h (renamed from drivers/freetype/include/freetype/internal/fttrace.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/ftvalid.h (renamed from drivers/freetype/include/freetype/internal/ftvalid.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/internal.h (renamed from drivers/freetype/include/freetype/internal/internal.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/psaux.h (renamed from drivers/freetype/include/freetype/internal/psaux.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/pshints.h (renamed from drivers/freetype/include/freetype/internal/pshints.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svbdf.h (renamed from drivers/freetype/include/freetype/internal/services/svbdf.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svcid.h (renamed from drivers/freetype/include/freetype/internal/services/svcid.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svfntfmt.h (renamed from drivers/freetype/include/freetype/internal/services/svfntfmt.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svgldict.h (renamed from drivers/freetype/include/freetype/internal/services/svgldict.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svgxval.h (renamed from drivers/freetype/include/freetype/internal/services/svgxval.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svkern.h (renamed from drivers/freetype/include/freetype/internal/services/svkern.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svmm.h (renamed from drivers/freetype/include/freetype/internal/services/svmm.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svotval.h (renamed from drivers/freetype/include/freetype/internal/services/svotval.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svpfr.h (renamed from drivers/freetype/include/freetype/internal/services/svpfr.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svpostnm.h (renamed from drivers/freetype/include/freetype/internal/services/svpostnm.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svprop.h (renamed from drivers/freetype/include/freetype/internal/services/svprop.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svpscmap.h (renamed from drivers/freetype/include/freetype/internal/services/svpscmap.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svpsinfo.h (renamed from drivers/freetype/include/freetype/internal/services/svpsinfo.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svsfnt.h (renamed from drivers/freetype/include/freetype/internal/services/svsfnt.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svttcmap.h (renamed from drivers/freetype/include/freetype/internal/services/svttcmap.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svtteng.h (renamed from drivers/freetype/include/freetype/internal/services/svtteng.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svttglyf.h (renamed from drivers/freetype/include/freetype/internal/services/svttglyf.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/services/svwinfnt.h (renamed from drivers/freetype/include/freetype/internal/services/svwinfnt.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/sfnt.h (renamed from drivers/freetype/include/freetype/internal/sfnt.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/t1types.h (renamed from drivers/freetype/include/freetype/internal/t1types.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/internal/tttypes.h (renamed from drivers/freetype/include/freetype/internal/tttypes.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/t1tables.h (renamed from drivers/freetype/include/freetype/t1tables.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ttnameid.h (renamed from drivers/freetype/include/freetype/ttnameid.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/tttables.h (renamed from drivers/freetype/include/freetype/tttables.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/tttags.h (renamed from drivers/freetype/include/freetype/tttags.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/freetype/ttunpat.h (renamed from drivers/freetype/include/freetype/ttunpat.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/include/ft2build.h (renamed from drivers/freetype/include/ft2build.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afangles.c (renamed from drivers/freetype/src/autofit/afangles.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afangles.h (renamed from drivers/freetype/src/autofit/afangles.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afblue.c (renamed from drivers/freetype/src/autofit/afblue.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afblue.cin (renamed from drivers/freetype/src/autofit/afblue.cin) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afblue.dat (renamed from drivers/freetype/src/autofit/afblue.dat) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afblue.h (renamed from drivers/freetype/src/autofit/afblue.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afblue.hin (renamed from drivers/freetype/src/autofit/afblue.hin) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afcjk.c (renamed from drivers/freetype/src/autofit/afcjk.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afcjk.h (renamed from drivers/freetype/src/autofit/afcjk.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afcover.h (renamed from drivers/freetype/src/autofit/afcover.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afdummy.c (renamed from drivers/freetype/src/autofit/afdummy.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afdummy.h (renamed from drivers/freetype/src/autofit/afdummy.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/aferrors.h (renamed from drivers/freetype/src/autofit/aferrors.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afglobal.c (renamed from drivers/freetype/src/autofit/afglobal.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afglobal.h (renamed from drivers/freetype/src/autofit/afglobal.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afhints.c (renamed from drivers/freetype/src/autofit/afhints.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afhints.h (renamed from drivers/freetype/src/autofit/afhints.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afindic.c (renamed from drivers/freetype/src/autofit/afindic.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afindic.h (renamed from drivers/freetype/src/autofit/afindic.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/aflatin.c (renamed from drivers/freetype/src/autofit/aflatin.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/aflatin.h (renamed from drivers/freetype/src/autofit/aflatin.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/aflatin2.c (renamed from drivers/freetype/src/autofit/aflatin2.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/aflatin2.h (renamed from drivers/freetype/src/autofit/aflatin2.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afloader.c (renamed from drivers/freetype/src/autofit/afloader.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afloader.h (renamed from drivers/freetype/src/autofit/afloader.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afmodule.c (renamed from drivers/freetype/src/autofit/afmodule.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afmodule.h (renamed from drivers/freetype/src/autofit/afmodule.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afpic.c (renamed from drivers/freetype/src/autofit/afpic.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afpic.h (renamed from drivers/freetype/src/autofit/afpic.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afranges.c (renamed from drivers/freetype/src/autofit/afranges.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afranges.h (renamed from drivers/freetype/src/autofit/afranges.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afscript.h (renamed from drivers/freetype/src/autofit/afscript.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afshaper.c (renamed from drivers/freetype/src/autofit/afshaper.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afshaper.h (renamed from drivers/freetype/src/autofit/afshaper.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afstyles.h (renamed from drivers/freetype/src/autofit/afstyles.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/aftypes.h (renamed from drivers/freetype/src/autofit/aftypes.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afwarp.c (renamed from drivers/freetype/src/autofit/afwarp.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afwarp.h (renamed from drivers/freetype/src/autofit/afwarp.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/afwrtsys.h (renamed from drivers/freetype/src/autofit/afwrtsys.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/autofit.c (renamed from drivers/freetype/src/autofit/autofit.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/module.mk (renamed from drivers/freetype/src/autofit/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/autofit/rules.mk (renamed from drivers/freetype/src/autofit/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/basepic.c (renamed from drivers/freetype/src/base/basepic.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/basepic.h (renamed from drivers/freetype/src/base/basepic.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftadvanc.c (renamed from drivers/freetype/src/base/ftadvanc.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftapi.c (renamed from drivers/freetype/src/base/ftapi.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftbase.c (renamed from drivers/freetype/src/base/ftbase.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftbase.h (renamed from drivers/freetype/src/base/ftbase.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftbbox.c (renamed from drivers/freetype/src/base/ftbbox.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftbdf.c (renamed from drivers/freetype/src/base/ftbdf.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftbitmap.c (renamed from drivers/freetype/src/base/ftbitmap.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftcalc.c (renamed from drivers/freetype/src/base/ftcalc.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftcid.c (renamed from drivers/freetype/src/base/ftcid.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftdbgmem.c (renamed from drivers/freetype/src/base/ftdbgmem.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftdebug.c (renamed from drivers/freetype/src/base/ftdebug.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftfntfmt.c (renamed from drivers/freetype/src/base/ftfntfmt.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftfstype.c (renamed from drivers/freetype/src/base/ftfstype.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftgasp.c (renamed from drivers/freetype/src/base/ftgasp.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftgloadr.c (renamed from drivers/freetype/src/base/ftgloadr.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftglyph.c (renamed from drivers/freetype/src/base/ftglyph.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftgxval.c (renamed from drivers/freetype/src/base/ftgxval.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/fthash.c (renamed from drivers/freetype/src/base/fthash.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftinit.c (renamed from drivers/freetype/src/base/ftinit.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftlcdfil.c (renamed from drivers/freetype/src/base/ftlcdfil.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftmac.c (renamed from drivers/freetype/src/base/ftmac.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftmm.c (renamed from drivers/freetype/src/base/ftmm.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftobjs.c (renamed from drivers/freetype/src/base/ftobjs.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftotval.c (renamed from drivers/freetype/src/base/ftotval.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftoutln.c (renamed from drivers/freetype/src/base/ftoutln.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftpatent.c (renamed from drivers/freetype/src/base/ftpatent.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftpfr.c (renamed from drivers/freetype/src/base/ftpfr.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftpic.c (renamed from drivers/freetype/src/base/ftpic.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftrfork.c (renamed from drivers/freetype/src/base/ftrfork.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftsnames.c (renamed from drivers/freetype/src/base/ftsnames.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftstream.c (renamed from drivers/freetype/src/base/ftstream.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftstroke.c (renamed from drivers/freetype/src/base/ftstroke.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftsynth.c (renamed from drivers/freetype/src/base/ftsynth.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftsystem.c (renamed from drivers/freetype/src/base/ftsystem.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/fttrigon.c (renamed from drivers/freetype/src/base/fttrigon.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/fttype1.c (renamed from drivers/freetype/src/base/fttype1.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftutil.c (renamed from drivers/freetype/src/base/ftutil.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/ftwinfnt.c (renamed from drivers/freetype/src/base/ftwinfnt.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/md5.c (renamed from drivers/freetype/src/base/md5.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/md5.h (renamed from drivers/freetype/src/base/md5.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/base/rules.mk (renamed from drivers/freetype/src/base/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/bdf/README (renamed from drivers/freetype/src/bdf/README) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/bdf/bdf.c (renamed from drivers/freetype/src/bdf/bdf.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/bdf/bdf.h (renamed from drivers/freetype/src/bdf/bdf.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/bdf/bdfdrivr.c (renamed from drivers/freetype/src/bdf/bdfdrivr.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/bdf/bdfdrivr.h (renamed from drivers/freetype/src/bdf/bdfdrivr.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/bdf/bdferror.h (renamed from drivers/freetype/src/bdf/bdferror.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/bdf/bdflib.c (renamed from drivers/freetype/src/bdf/bdflib.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/bdf/module.mk (renamed from drivers/freetype/src/bdf/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/bdf/rules.mk (renamed from drivers/freetype/src/bdf/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftcache.c (renamed from drivers/freetype/src/cache/ftcache.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftcbasic.c (renamed from drivers/freetype/src/cache/ftcbasic.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftccache.c (renamed from drivers/freetype/src/cache/ftccache.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftccache.h (renamed from drivers/freetype/src/cache/ftccache.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftccback.h (renamed from drivers/freetype/src/cache/ftccback.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftccmap.c (renamed from drivers/freetype/src/cache/ftccmap.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftcerror.h (renamed from drivers/freetype/src/cache/ftcerror.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftcglyph.c (renamed from drivers/freetype/src/cache/ftcglyph.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftcglyph.h (renamed from drivers/freetype/src/cache/ftcglyph.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftcimage.c (renamed from drivers/freetype/src/cache/ftcimage.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftcimage.h (renamed from drivers/freetype/src/cache/ftcimage.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftcmanag.c (renamed from drivers/freetype/src/cache/ftcmanag.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftcmanag.h (renamed from drivers/freetype/src/cache/ftcmanag.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftcmru.c (renamed from drivers/freetype/src/cache/ftcmru.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftcmru.h (renamed from drivers/freetype/src/cache/ftcmru.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftcsbits.c (renamed from drivers/freetype/src/cache/ftcsbits.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/ftcsbits.h (renamed from drivers/freetype/src/cache/ftcsbits.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cache/rules.mk (renamed from drivers/freetype/src/cache/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2arrst.c (renamed from drivers/freetype/src/cff/cf2arrst.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2arrst.h (renamed from drivers/freetype/src/cff/cf2arrst.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2blues.c (renamed from drivers/freetype/src/cff/cf2blues.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2blues.h (renamed from drivers/freetype/src/cff/cf2blues.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2error.c (renamed from drivers/freetype/src/cff/cf2error.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2error.h (renamed from drivers/freetype/src/cff/cf2error.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2fixed.h (renamed from drivers/freetype/src/cff/cf2fixed.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2font.c (renamed from drivers/freetype/src/cff/cf2font.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2font.h (renamed from drivers/freetype/src/cff/cf2font.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2ft.c (renamed from drivers/freetype/src/cff/cf2ft.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2ft.h (renamed from drivers/freetype/src/cff/cf2ft.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2glue.h (renamed from drivers/freetype/src/cff/cf2glue.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2hints.c (renamed from drivers/freetype/src/cff/cf2hints.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2hints.h (renamed from drivers/freetype/src/cff/cf2hints.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2intrp.c (renamed from drivers/freetype/src/cff/cf2intrp.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2intrp.h (renamed from drivers/freetype/src/cff/cf2intrp.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2read.c (renamed from drivers/freetype/src/cff/cf2read.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2read.h (renamed from drivers/freetype/src/cff/cf2read.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2stack.c (renamed from drivers/freetype/src/cff/cf2stack.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2stack.h (renamed from drivers/freetype/src/cff/cf2stack.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cf2types.h (renamed from drivers/freetype/src/cff/cf2types.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cff.c (renamed from drivers/freetype/src/cff/cff.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cffcmap.c (renamed from drivers/freetype/src/cff/cffcmap.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cffcmap.h (renamed from drivers/freetype/src/cff/cffcmap.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cffdrivr.c (renamed from drivers/freetype/src/cff/cffdrivr.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cffdrivr.h (renamed from drivers/freetype/src/cff/cffdrivr.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cfferrs.h (renamed from drivers/freetype/src/cff/cfferrs.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cffgload.c (renamed from drivers/freetype/src/cff/cffgload.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cffgload.h (renamed from drivers/freetype/src/cff/cffgload.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cffload.c (renamed from drivers/freetype/src/cff/cffload.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cffload.h (renamed from drivers/freetype/src/cff/cffload.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cffobjs.c (renamed from drivers/freetype/src/cff/cffobjs.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cffobjs.h (renamed from drivers/freetype/src/cff/cffobjs.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cffparse.c (renamed from drivers/freetype/src/cff/cffparse.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cffparse.h (renamed from drivers/freetype/src/cff/cffparse.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cffpic.c (renamed from drivers/freetype/src/cff/cffpic.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cffpic.h (renamed from drivers/freetype/src/cff/cffpic.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cfftoken.h (renamed from drivers/freetype/src/cff/cfftoken.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/cfftypes.h (renamed from drivers/freetype/src/cff/cfftypes.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/module.mk (renamed from drivers/freetype/src/cff/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cff/rules.mk (renamed from drivers/freetype/src/cff/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/ciderrs.h (renamed from drivers/freetype/src/cid/ciderrs.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/cidgload.c (renamed from drivers/freetype/src/cid/cidgload.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/cidgload.h (renamed from drivers/freetype/src/cid/cidgload.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/cidload.c (renamed from drivers/freetype/src/cid/cidload.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/cidload.h (renamed from drivers/freetype/src/cid/cidload.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/cidobjs.c (renamed from drivers/freetype/src/cid/cidobjs.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/cidobjs.h (renamed from drivers/freetype/src/cid/cidobjs.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/cidparse.c (renamed from drivers/freetype/src/cid/cidparse.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/cidparse.h (renamed from drivers/freetype/src/cid/cidparse.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/cidriver.c (renamed from drivers/freetype/src/cid/cidriver.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/cidriver.h (renamed from drivers/freetype/src/cid/cidriver.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/cidtoken.h (renamed from drivers/freetype/src/cid/cidtoken.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/module.mk (renamed from drivers/freetype/src/cid/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/rules.mk (renamed from drivers/freetype/src/cid/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/cid/type1cid.c (renamed from drivers/freetype/src/cid/type1cid.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/README (renamed from drivers/freetype/src/gxvalid/README) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvalid.c (renamed from drivers/freetype/src/gxvalid/gxvalid.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvalid.h (renamed from drivers/freetype/src/gxvalid/gxvalid.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvbsln.c (renamed from drivers/freetype/src/gxvalid/gxvbsln.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvcommn.c (renamed from drivers/freetype/src/gxvalid/gxvcommn.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvcommn.h (renamed from drivers/freetype/src/gxvalid/gxvcommn.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxverror.h (renamed from drivers/freetype/src/gxvalid/gxverror.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvfeat.c (renamed from drivers/freetype/src/gxvalid/gxvfeat.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvfeat.h (renamed from drivers/freetype/src/gxvalid/gxvfeat.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvfgen.c (renamed from drivers/freetype/src/gxvalid/gxvfgen.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvjust.c (renamed from drivers/freetype/src/gxvalid/gxvjust.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvkern.c (renamed from drivers/freetype/src/gxvalid/gxvkern.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvlcar.c (renamed from drivers/freetype/src/gxvalid/gxvlcar.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmod.c (renamed from drivers/freetype/src/gxvalid/gxvmod.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmod.h (renamed from drivers/freetype/src/gxvalid/gxvmod.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmort.c (renamed from drivers/freetype/src/gxvalid/gxvmort.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmort.h (renamed from drivers/freetype/src/gxvalid/gxvmort.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmort0.c (renamed from drivers/freetype/src/gxvalid/gxvmort0.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmort1.c (renamed from drivers/freetype/src/gxvalid/gxvmort1.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmort2.c (renamed from drivers/freetype/src/gxvalid/gxvmort2.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmort4.c (renamed from drivers/freetype/src/gxvalid/gxvmort4.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmort5.c (renamed from drivers/freetype/src/gxvalid/gxvmort5.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmorx.c (renamed from drivers/freetype/src/gxvalid/gxvmorx.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmorx.h (renamed from drivers/freetype/src/gxvalid/gxvmorx.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmorx0.c (renamed from drivers/freetype/src/gxvalid/gxvmorx0.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmorx1.c (renamed from drivers/freetype/src/gxvalid/gxvmorx1.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmorx2.c (renamed from drivers/freetype/src/gxvalid/gxvmorx2.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmorx4.c (renamed from drivers/freetype/src/gxvalid/gxvmorx4.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvmorx5.c (renamed from drivers/freetype/src/gxvalid/gxvmorx5.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvopbd.c (renamed from drivers/freetype/src/gxvalid/gxvopbd.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvprop.c (renamed from drivers/freetype/src/gxvalid/gxvprop.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/gxvtrak.c (renamed from drivers/freetype/src/gxvalid/gxvtrak.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/module.mk (renamed from drivers/freetype/src/gxvalid/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/gxvalid/rules.mk (renamed from drivers/freetype/src/gxvalid/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/module.mk (renamed from drivers/freetype/src/otvalid/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/otvalid.c (renamed from drivers/freetype/src/otvalid/otvalid.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/otvalid.h (renamed from drivers/freetype/src/otvalid/otvalid.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/otvbase.c (renamed from drivers/freetype/src/otvalid/otvbase.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/otvcommn.c (renamed from drivers/freetype/src/otvalid/otvcommn.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/otvcommn.h (renamed from drivers/freetype/src/otvalid/otvcommn.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/otverror.h (renamed from drivers/freetype/src/otvalid/otverror.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/otvgdef.c (renamed from drivers/freetype/src/otvalid/otvgdef.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/otvgpos.c (renamed from drivers/freetype/src/otvalid/otvgpos.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/otvgpos.h (renamed from drivers/freetype/src/otvalid/otvgpos.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/otvgsub.c (renamed from drivers/freetype/src/otvalid/otvgsub.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/otvjstf.c (renamed from drivers/freetype/src/otvalid/otvjstf.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/otvmath.c (renamed from drivers/freetype/src/otvalid/otvmath.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/otvmod.c (renamed from drivers/freetype/src/otvalid/otvmod.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/otvmod.h (renamed from drivers/freetype/src/otvalid/otvmod.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/otvalid/rules.mk (renamed from drivers/freetype/src/otvalid/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pcf/README (renamed from drivers/freetype/src/pcf/README) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pcf/module.mk (renamed from drivers/freetype/src/pcf/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pcf/pcf.c (renamed from drivers/freetype/src/pcf/pcf.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pcf/pcf.h (renamed from drivers/freetype/src/pcf/pcf.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pcf/pcfdrivr.c (renamed from drivers/freetype/src/pcf/pcfdrivr.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pcf/pcfdrivr.h (renamed from drivers/freetype/src/pcf/pcfdrivr.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pcf/pcferror.h (renamed from drivers/freetype/src/pcf/pcferror.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pcf/pcfread.c (renamed from drivers/freetype/src/pcf/pcfread.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pcf/pcfread.h (renamed from drivers/freetype/src/pcf/pcfread.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pcf/pcfutil.c (renamed from drivers/freetype/src/pcf/pcfutil.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pcf/pcfutil.h (renamed from drivers/freetype/src/pcf/pcfutil.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pcf/rules.mk (renamed from drivers/freetype/src/pcf/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/module.mk (renamed from drivers/freetype/src/pfr/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfr.c (renamed from drivers/freetype/src/pfr/pfr.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfrcmap.c (renamed from drivers/freetype/src/pfr/pfrcmap.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfrcmap.h (renamed from drivers/freetype/src/pfr/pfrcmap.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfrdrivr.c (renamed from drivers/freetype/src/pfr/pfrdrivr.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfrdrivr.h (renamed from drivers/freetype/src/pfr/pfrdrivr.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfrerror.h (renamed from drivers/freetype/src/pfr/pfrerror.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfrgload.c (renamed from drivers/freetype/src/pfr/pfrgload.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfrgload.h (renamed from drivers/freetype/src/pfr/pfrgload.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfrload.c (renamed from drivers/freetype/src/pfr/pfrload.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfrload.h (renamed from drivers/freetype/src/pfr/pfrload.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfrobjs.c (renamed from drivers/freetype/src/pfr/pfrobjs.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfrobjs.h (renamed from drivers/freetype/src/pfr/pfrobjs.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfrsbit.c (renamed from drivers/freetype/src/pfr/pfrsbit.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfrsbit.h (renamed from drivers/freetype/src/pfr/pfrsbit.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/pfrtypes.h (renamed from drivers/freetype/src/pfr/pfrtypes.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pfr/rules.mk (renamed from drivers/freetype/src/pfr/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/afmparse.c (renamed from drivers/freetype/src/psaux/afmparse.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/afmparse.h (renamed from drivers/freetype/src/psaux/afmparse.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/module.mk (renamed from drivers/freetype/src/psaux/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/psaux.c (renamed from drivers/freetype/src/psaux/psaux.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/psauxerr.h (renamed from drivers/freetype/src/psaux/psauxerr.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/psauxmod.c (renamed from drivers/freetype/src/psaux/psauxmod.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/psauxmod.h (renamed from drivers/freetype/src/psaux/psauxmod.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/psconv.c (renamed from drivers/freetype/src/psaux/psconv.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/psconv.h (renamed from drivers/freetype/src/psaux/psconv.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/psobjs.c (renamed from drivers/freetype/src/psaux/psobjs.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/psobjs.h (renamed from drivers/freetype/src/psaux/psobjs.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/rules.mk (renamed from drivers/freetype/src/psaux/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/t1cmap.c (renamed from drivers/freetype/src/psaux/t1cmap.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/t1cmap.h (renamed from drivers/freetype/src/psaux/t1cmap.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/t1decode.c (renamed from drivers/freetype/src/psaux/t1decode.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psaux/t1decode.h (renamed from drivers/freetype/src/psaux/t1decode.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pshinter/module.mk (renamed from drivers/freetype/src/pshinter/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pshinter/pshalgo.c (renamed from drivers/freetype/src/pshinter/pshalgo.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pshinter/pshalgo.h (renamed from drivers/freetype/src/pshinter/pshalgo.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pshinter/pshglob.c (renamed from drivers/freetype/src/pshinter/pshglob.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pshinter/pshglob.h (renamed from drivers/freetype/src/pshinter/pshglob.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pshinter/pshinter.c (renamed from drivers/freetype/src/pshinter/pshinter.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pshinter/pshmod.c (renamed from drivers/freetype/src/pshinter/pshmod.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pshinter/pshmod.h (renamed from drivers/freetype/src/pshinter/pshmod.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pshinter/pshnterr.h (renamed from drivers/freetype/src/pshinter/pshnterr.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pshinter/pshpic.c (renamed from drivers/freetype/src/pshinter/pshpic.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pshinter/pshpic.h (renamed from drivers/freetype/src/pshinter/pshpic.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pshinter/pshrec.c (renamed from drivers/freetype/src/pshinter/pshrec.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pshinter/pshrec.h (renamed from drivers/freetype/src/pshinter/pshrec.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/pshinter/rules.mk (renamed from drivers/freetype/src/pshinter/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psnames/module.mk (renamed from drivers/freetype/src/psnames/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psnames/psmodule.c (renamed from drivers/freetype/src/psnames/psmodule.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psnames/psmodule.h (renamed from drivers/freetype/src/psnames/psmodule.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psnames/psnamerr.h (renamed from drivers/freetype/src/psnames/psnamerr.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psnames/psnames.c (renamed from drivers/freetype/src/psnames/psnames.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psnames/pspic.c (renamed from drivers/freetype/src/psnames/pspic.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psnames/pspic.h (renamed from drivers/freetype/src/psnames/pspic.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psnames/pstables.h (renamed from drivers/freetype/src/psnames/pstables.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/psnames/rules.mk (renamed from drivers/freetype/src/psnames/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/raster/ftmisc.h (renamed from drivers/freetype/src/raster/ftmisc.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/raster/ftraster.c (renamed from drivers/freetype/src/raster/ftraster.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/raster/ftraster.h (renamed from drivers/freetype/src/raster/ftraster.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/raster/ftrend1.c (renamed from drivers/freetype/src/raster/ftrend1.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/raster/ftrend1.h (renamed from drivers/freetype/src/raster/ftrend1.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/raster/module.mk (renamed from drivers/freetype/src/raster/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/raster/raster.c (renamed from drivers/freetype/src/raster/raster.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/raster/rasterrs.h (renamed from drivers/freetype/src/raster/rasterrs.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/raster/rastpic.c (renamed from drivers/freetype/src/raster/rastpic.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/raster/rastpic.h (renamed from drivers/freetype/src/raster/rastpic.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/raster/rules.mk (renamed from drivers/freetype/src/raster/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/module.mk (renamed from drivers/freetype/src/sfnt/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/pngshim.c (renamed from drivers/freetype/src/sfnt/pngshim.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/pngshim.h (renamed from drivers/freetype/src/sfnt/pngshim.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/rules.mk (renamed from drivers/freetype/src/sfnt/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/sfdriver.c (renamed from drivers/freetype/src/sfnt/sfdriver.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/sfdriver.h (renamed from drivers/freetype/src/sfnt/sfdriver.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/sferrors.h (renamed from drivers/freetype/src/sfnt/sferrors.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/sfnt.c (renamed from drivers/freetype/src/sfnt/sfnt.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/sfntpic.c (renamed from drivers/freetype/src/sfnt/sfntpic.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/sfntpic.h (renamed from drivers/freetype/src/sfnt/sfntpic.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/sfobjs.c (renamed from drivers/freetype/src/sfnt/sfobjs.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/sfobjs.h (renamed from drivers/freetype/src/sfnt/sfobjs.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttbdf.c (renamed from drivers/freetype/src/sfnt/ttbdf.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttbdf.h (renamed from drivers/freetype/src/sfnt/ttbdf.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttcmap.c (renamed from drivers/freetype/src/sfnt/ttcmap.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttcmap.h (renamed from drivers/freetype/src/sfnt/ttcmap.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttcmapc.h (renamed from drivers/freetype/src/sfnt/ttcmapc.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttkern.c (renamed from drivers/freetype/src/sfnt/ttkern.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttkern.h (renamed from drivers/freetype/src/sfnt/ttkern.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttload.c (renamed from drivers/freetype/src/sfnt/ttload.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttload.h (renamed from drivers/freetype/src/sfnt/ttload.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttmtx.c (renamed from drivers/freetype/src/sfnt/ttmtx.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttmtx.h (renamed from drivers/freetype/src/sfnt/ttmtx.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttpost.c (renamed from drivers/freetype/src/sfnt/ttpost.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttpost.h (renamed from drivers/freetype/src/sfnt/ttpost.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttsbit.c (renamed from drivers/freetype/src/sfnt/ttsbit.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/sfnt/ttsbit.h (renamed from drivers/freetype/src/sfnt/ttsbit.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/smooth/ftgrays.c (renamed from drivers/freetype/src/smooth/ftgrays.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/smooth/ftgrays.h (renamed from drivers/freetype/src/smooth/ftgrays.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/smooth/ftsmerrs.h (renamed from drivers/freetype/src/smooth/ftsmerrs.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/smooth/ftsmooth.c (renamed from drivers/freetype/src/smooth/ftsmooth.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/smooth/ftsmooth.h (renamed from drivers/freetype/src/smooth/ftsmooth.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/smooth/ftspic.c (renamed from drivers/freetype/src/smooth/ftspic.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/smooth/ftspic.h (renamed from drivers/freetype/src/smooth/ftspic.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/smooth/module.mk (renamed from drivers/freetype/src/smooth/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/smooth/rules.mk (renamed from drivers/freetype/src/smooth/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/smooth/smooth.c (renamed from drivers/freetype/src/smooth/smooth.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/module.mk (renamed from drivers/freetype/src/truetype/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/rules.mk (renamed from drivers/freetype/src/truetype/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/truetype.c (renamed from drivers/freetype/src/truetype/truetype.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttdriver.c (renamed from drivers/freetype/src/truetype/ttdriver.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttdriver.h (renamed from drivers/freetype/src/truetype/ttdriver.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/tterrors.h (renamed from drivers/freetype/src/truetype/tterrors.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttgload.c (renamed from drivers/freetype/src/truetype/ttgload.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttgload.h (renamed from drivers/freetype/src/truetype/ttgload.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttgxvar.c (renamed from drivers/freetype/src/truetype/ttgxvar.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttgxvar.h (renamed from drivers/freetype/src/truetype/ttgxvar.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttinterp.c (renamed from drivers/freetype/src/truetype/ttinterp.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttinterp.h (renamed from drivers/freetype/src/truetype/ttinterp.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttobjs.c (renamed from drivers/freetype/src/truetype/ttobjs.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttobjs.h (renamed from drivers/freetype/src/truetype/ttobjs.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttpic.c (renamed from drivers/freetype/src/truetype/ttpic.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttpic.h (renamed from drivers/freetype/src/truetype/ttpic.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttpload.c (renamed from drivers/freetype/src/truetype/ttpload.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttpload.h (renamed from drivers/freetype/src/truetype/ttpload.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttsubpix.c (renamed from drivers/freetype/src/truetype/ttsubpix.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/truetype/ttsubpix.h (renamed from drivers/freetype/src/truetype/ttsubpix.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/module.mk (renamed from drivers/freetype/src/type1/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/rules.mk (renamed from drivers/freetype/src/type1/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/t1afm.c (renamed from drivers/freetype/src/type1/t1afm.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/t1afm.h (renamed from drivers/freetype/src/type1/t1afm.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/t1driver.c (renamed from drivers/freetype/src/type1/t1driver.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/t1driver.h (renamed from drivers/freetype/src/type1/t1driver.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/t1errors.h (renamed from drivers/freetype/src/type1/t1errors.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/t1gload.c (renamed from drivers/freetype/src/type1/t1gload.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/t1gload.h (renamed from drivers/freetype/src/type1/t1gload.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/t1load.c (renamed from drivers/freetype/src/type1/t1load.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/t1load.h (renamed from drivers/freetype/src/type1/t1load.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/t1objs.c (renamed from drivers/freetype/src/type1/t1objs.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/t1objs.h (renamed from drivers/freetype/src/type1/t1objs.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/t1parse.c (renamed from drivers/freetype/src/type1/t1parse.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/t1parse.h (renamed from drivers/freetype/src/type1/t1parse.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/t1tokens.h (renamed from drivers/freetype/src/type1/t1tokens.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type1/type1.c (renamed from drivers/freetype/src/type1/type1.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type42/module.mk (renamed from drivers/freetype/src/type42/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type42/rules.mk (renamed from drivers/freetype/src/type42/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type42/t42drivr.c (renamed from drivers/freetype/src/type42/t42drivr.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type42/t42drivr.h (renamed from drivers/freetype/src/type42/t42drivr.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type42/t42error.h (renamed from drivers/freetype/src/type42/t42error.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type42/t42objs.c (renamed from drivers/freetype/src/type42/t42objs.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type42/t42objs.h (renamed from drivers/freetype/src/type42/t42objs.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type42/t42parse.c (renamed from drivers/freetype/src/type42/t42parse.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type42/t42parse.h (renamed from drivers/freetype/src/type42/t42parse.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type42/t42types.h (renamed from drivers/freetype/src/type42/t42types.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/type42/type42.c (renamed from drivers/freetype/src/type42/type42.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/winfonts/fnterrs.h (renamed from drivers/freetype/src/winfonts/fnterrs.h) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/winfonts/module.mk (renamed from drivers/freetype/src/winfonts/module.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/winfonts/rules.mk (renamed from drivers/freetype/src/winfonts/rules.mk) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/winfonts/winfnt.c (renamed from drivers/freetype/src/winfonts/winfnt.c) | 0 | ||||
-rw-r--r-- | thirdparty/freetype/src/winfonts/winfnt.h (renamed from drivers/freetype/src/winfonts/winfnt.h) | 0 | ||||
-rw-r--r-- | thirdparty/glew/GL/glew.h (renamed from drivers/gl_context/GL/glew.h) | 0 | ||||
-rw-r--r-- | thirdparty/glew/GL/glxew.h (renamed from drivers/gl_context/GL/glxew.h) | 0 | ||||
-rw-r--r-- | thirdparty/glew/GL/wglew.h (renamed from drivers/gl_context/GL/wglew.h) | 0 | ||||
-rw-r--r-- | thirdparty/glew/LICENSE.txt | 73 | ||||
-rw-r--r-- | thirdparty/glew/glew.c (renamed from drivers/gl_context/glew.c) | 0 | ||||
-rw-r--r-- | thirdparty/jpeg-compressor/jpgd.cpp (renamed from drivers/jpegd/jpgd.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/jpeg-compressor/jpgd.h (renamed from drivers/jpegd/jpgd.h) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/COPYING | 31 | ||||
-rw-r--r-- | thirdparty/libmpcdec/decoder.h (renamed from drivers/mpc/decoder.h) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/huffman.c (renamed from drivers/mpc/huffman.c) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/huffman.h (renamed from drivers/mpc/huffman.h) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/internal.h (renamed from drivers/mpc/internal.h) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/mpc/datatypes.h (renamed from drivers/mpc/datatypes.h) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/mpc/minimax.h (renamed from drivers/mpc/minimax.h) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/mpc/mpc_types.h (renamed from drivers/mpc/mpc_types.h) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/mpc/mpcdec.h (renamed from drivers/mpc/mpcdec.h) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/mpc/mpcmath.h (renamed from drivers/mpc/mpcmath.h) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/mpc/reader.h (renamed from drivers/mpc/reader.h) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/mpc/streaminfo.h (renamed from drivers/mpc/streaminfo.h) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/mpc_bits_reader.c (renamed from drivers/mpc/mpc_bits_reader.c) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/mpc_bits_reader.h (renamed from drivers/mpc/mpc_bits_reader.h) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/mpc_decoder.c (renamed from drivers/mpc/mpc_decoder.c) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/mpc_demux.c (renamed from drivers/mpc/mpc_demux.c) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/mpc_reader.c (renamed from drivers/mpc/mpc_reader.c) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/mpcdec_math.h (renamed from drivers/mpc/mpcdec_math.h) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/requant.c (renamed from drivers/mpc/requant.c) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/requant.h (renamed from drivers/mpc/requant.h) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/streaminfo.c (renamed from drivers/mpc/streaminfo.c) | 0 | ||||
-rw-r--r-- | thirdparty/libmpcdec/synth_filter.c (renamed from drivers/mpc/synth_filter.c) | 0 | ||||
-rw-r--r-- | thirdparty/libogg/COPYING (renamed from drivers/ogg/COPYING) | 0 | ||||
-rw-r--r-- | thirdparty/libogg/bitwise.c (renamed from drivers/ogg/bitwise.c) | 0 | ||||
-rw-r--r-- | thirdparty/libogg/framing.c (renamed from drivers/ogg/framing.c) | 0 | ||||
-rw-r--r-- | thirdparty/libogg/ogg/config_types.h (renamed from drivers/ogg/config_types.h) | 0 | ||||
-rw-r--r-- | thirdparty/libogg/ogg/ogg.h (renamed from drivers/ogg/ogg.h) | 0 | ||||
-rw-r--r-- | thirdparty/libogg/ogg/os_types.h (renamed from drivers/ogg/os_types.h) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/LICENSE | 130 | ||||
-rw-r--r-- | thirdparty/libpng/arm/arm_init.c (renamed from drivers/png/arm/arm_init.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/arm/filter_neon.S (renamed from drivers/png/arm/filter_neon.S) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/arm/filter_neon_intrinsics.c (renamed from drivers/png/arm/filter_neon_intrinsics.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/png.c (renamed from drivers/png/png.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/png.h (renamed from drivers/png/png.h) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngconf.h (renamed from drivers/png/pngconf.h) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngdebug.h (renamed from drivers/png/pngdebug.h) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngerror.c (renamed from drivers/png/pngerror.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngget.c (renamed from drivers/png/pngget.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pnginfo.h (renamed from drivers/png/pnginfo.h) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pnglibconf.h (renamed from drivers/png/pnglibconf.h) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngmem.c (renamed from drivers/png/pngmem.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngpread.c (renamed from drivers/png/pngpread.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngpriv.h (renamed from drivers/png/pngpriv.h) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngread.c (renamed from drivers/png/pngread.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngrio.c (renamed from drivers/png/pngrio.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngrtran.c (renamed from drivers/png/pngrtran.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngrutil.c (renamed from drivers/png/pngrutil.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngset.c (renamed from drivers/png/pngset.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngstruct.h (renamed from drivers/png/pngstruct.h) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngtrans.c (renamed from drivers/png/pngtrans.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngwio.c (renamed from drivers/png/pngwio.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngwrite.c (renamed from drivers/png/pngwrite.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngwtran.c (renamed from drivers/png/pngwtran.c) | 0 | ||||
-rw-r--r-- | thirdparty/libpng/pngwutil.c (renamed from drivers/png/pngwutil.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/COPYING (renamed from drivers/theora/COPYING) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/LICENSE (renamed from drivers/theora/LICENSE) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/analyze.c (renamed from drivers/theora/analyze.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/apiwrapper.c (renamed from drivers/theora/apiwrapper.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/apiwrapper.h (renamed from drivers/theora/apiwrapper.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/bitpack.c (renamed from drivers/theora/bitpack.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/bitpack.h (renamed from drivers/theora/bitpack.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/cpu.c (renamed from drivers/theora/cpu.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/cpu.h (renamed from drivers/theora/cpu.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/dct.h (renamed from drivers/theora/dct.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/decapiwrapper.c (renamed from drivers/theora/decapiwrapper.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/decinfo.c (renamed from drivers/theora/decinfo.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/decint.h (renamed from drivers/theora/decint.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/decode.c (renamed from drivers/theora/decode.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/dequant.c (renamed from drivers/theora/dequant.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/dequant.h (renamed from drivers/theora/dequant.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/encapiwrapper.c (renamed from drivers/theora/encapiwrapper.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/encfrag.c (renamed from drivers/theora/encfrag.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/encinfo.c (renamed from drivers/theora/encinfo.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/encint.h (renamed from drivers/theora/encint.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/encode.c (renamed from drivers/theora/encode.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/encoder_disabled.c (renamed from drivers/theora/encoder_disabled.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/enquant.c (renamed from drivers/theora/enquant.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/enquant.h (renamed from drivers/theora/enquant.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/fdct.c (renamed from drivers/theora/fdct.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/fragment.c (renamed from drivers/theora/fragment.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/huffdec.c (renamed from drivers/theora/huffdec.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/huffdec.h (renamed from drivers/theora/huffdec.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/huffenc.c (renamed from drivers/theora/huffenc.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/huffenc.h (renamed from drivers/theora/huffenc.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/huffman.h (renamed from drivers/theora/huffman.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/idct.c (renamed from drivers/theora/idct.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/info.c (renamed from drivers/theora/info.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/internal.c (renamed from drivers/theora/internal.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/internal.h (renamed from drivers/theora/internal.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/mathops.c (renamed from drivers/theora/mathops.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/mathops.h (renamed from drivers/theora/mathops.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/mcenc.c (renamed from drivers/theora/mcenc.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/modedec.h (renamed from drivers/theora/modedec.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/ocintrin.h (renamed from drivers/theora/ocintrin.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/quant.c (renamed from drivers/theora/quant.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/quant.h (renamed from drivers/theora/quant.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/rate.c (renamed from drivers/theora/rate.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/state.c (renamed from drivers/theora/state.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/theora/codec.h (renamed from drivers/theora/codec.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/theora/theora.h (renamed from drivers/theora/theora.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/theora/theoradec.h (renamed from drivers/theora/theoradec.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/theora/theoraenc.h (renamed from drivers/theora/theoraenc.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/tokenize.c (renamed from drivers/theora/tokenize.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86/mmxencfrag.c (renamed from drivers/theora/x86/mmxencfrag.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86/mmxfdct.c (renamed from drivers/theora/x86/mmxfdct.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86/mmxfrag.c (renamed from drivers/theora/x86/mmxfrag.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86/mmxfrag.h (renamed from drivers/theora/x86/mmxfrag.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86/mmxidct.c (renamed from drivers/theora/x86/mmxidct.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86/mmxloop.h (renamed from drivers/theora/x86/mmxloop.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86/mmxstate.c (renamed from drivers/theora/x86/mmxstate.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86/sse2fdct.c (renamed from drivers/theora/x86/sse2fdct.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86/x86enc.c (renamed from drivers/theora/x86/x86enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86/x86enc.h (renamed from drivers/theora/x86/x86enc.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86/x86int.h (renamed from drivers/theora/x86/x86int.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86/x86state.c (renamed from drivers/theora/x86/x86state.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86_vc/mmxencfrag.c (renamed from drivers/theora/x86_vc/mmxencfrag.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86_vc/mmxfdct.c (renamed from drivers/theora/x86_vc/mmxfdct.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86_vc/mmxfrag.c (renamed from drivers/theora/x86_vc/mmxfrag.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86_vc/mmxfrag.h (renamed from drivers/theora/x86_vc/mmxfrag.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86_vc/mmxidct.c (renamed from drivers/theora/x86_vc/mmxidct.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86_vc/mmxloop.h (renamed from drivers/theora/x86_vc/mmxloop.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86_vc/mmxstate.c (renamed from drivers/theora/x86_vc/mmxstate.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86_vc/x86enc.c (renamed from drivers/theora/x86_vc/x86enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86_vc/x86enc.h (renamed from drivers/theora/x86_vc/x86enc.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86_vc/x86int.h (renamed from drivers/theora/x86_vc/x86int.h) | 0 | ||||
-rw-r--r-- | thirdparty/libtheora/x86_vc/x86state.c (renamed from drivers/theora/x86_vc/x86state.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/COPYING (renamed from drivers/vorbis/COPYING) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/analysis.c (renamed from drivers/vorbis/analysis.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/backends.h (renamed from drivers/vorbis/backends.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/barkmel.c (renamed from drivers/vorbis/barkmel.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/bitrate.c (renamed from drivers/vorbis/bitrate.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/bitrate.h (renamed from drivers/vorbis/bitrate.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/block.c (renamed from drivers/vorbis/block.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/books/coupled/res_books_51.h (renamed from drivers/vorbis/books/coupled/res_books_51.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/books/coupled/res_books_stereo.h (renamed from drivers/vorbis/books/coupled/res_books_stereo.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/books/floor/floor_books.h (renamed from drivers/vorbis/books/floor/floor_books.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/books/uncoupled/res_books_uncoupled.h (renamed from drivers/vorbis/books/uncoupled/res_books_uncoupled.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/codebook.c (renamed from drivers/vorbis/codebook.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/codebook.h (renamed from drivers/vorbis/codebook.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/codec_internal.h (renamed from drivers/vorbis/codec_internal.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/envelope.c (renamed from drivers/vorbis/envelope.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/envelope.h (renamed from drivers/vorbis/envelope.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/floor0.c (renamed from drivers/vorbis/floor0.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/floor1.c (renamed from drivers/vorbis/floor1.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/highlevel.h (renamed from drivers/vorbis/highlevel.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/info.c (renamed from drivers/vorbis/info.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/lookup.c (renamed from drivers/vorbis/lookup.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/lookup.h (renamed from drivers/vorbis/lookup.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/lookup_data.h (renamed from drivers/vorbis/lookup_data.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/lpc.c (renamed from drivers/vorbis/lpc.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/lpc.h (renamed from drivers/vorbis/lpc.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/lsp.c (renamed from drivers/vorbis/lsp.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/lsp.h (renamed from drivers/vorbis/lsp.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/mapping0.c (renamed from drivers/vorbis/mapping0.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/masking.h (renamed from drivers/vorbis/masking.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/mdct.c (renamed from drivers/vorbis/mdct.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/mdct.h (renamed from drivers/vorbis/mdct.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/misc.h (renamed from drivers/vorbis/misc.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/floor_all.h (renamed from drivers/vorbis/modes/floor_all.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/psych_11.h (renamed from drivers/vorbis/modes/psych_11.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/psych_16.h (renamed from drivers/vorbis/modes/psych_16.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/psych_44.h (renamed from drivers/vorbis/modes/psych_44.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/psych_8.h (renamed from drivers/vorbis/modes/psych_8.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/residue_16.h (renamed from drivers/vorbis/modes/residue_16.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/residue_44.h (renamed from drivers/vorbis/modes/residue_44.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/residue_44p51.h (renamed from drivers/vorbis/modes/residue_44p51.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/residue_44u.h (renamed from drivers/vorbis/modes/residue_44u.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/residue_8.h (renamed from drivers/vorbis/modes/residue_8.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/setup_11.h (renamed from drivers/vorbis/modes/setup_11.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/setup_16.h (renamed from drivers/vorbis/modes/setup_16.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/setup_22.h (renamed from drivers/vorbis/modes/setup_22.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/setup_32.h (renamed from drivers/vorbis/modes/setup_32.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/setup_44.h (renamed from drivers/vorbis/modes/setup_44.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/setup_44p51.h (renamed from drivers/vorbis/modes/setup_44p51.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/setup_44u.h (renamed from drivers/vorbis/modes/setup_44u.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/setup_8.h (renamed from drivers/vorbis/modes/setup_8.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/modes/setup_X.h (renamed from drivers/vorbis/modes/setup_X.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/os.h (renamed from drivers/vorbis/os.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/psy.c (renamed from drivers/vorbis/psy.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/psy.h (renamed from drivers/vorbis/psy.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/psytune.c (renamed from drivers/vorbis/psytune.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/registry.c (renamed from drivers/vorbis/registry.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/registry.h (renamed from drivers/vorbis/registry.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/res0.c (renamed from drivers/vorbis/res0.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/scales.h (renamed from drivers/vorbis/scales.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/sharedbook.c (renamed from drivers/vorbis/sharedbook.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/smallft.c (renamed from drivers/vorbis/smallft.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/smallft.h (renamed from drivers/vorbis/smallft.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/synthesis.c (renamed from drivers/vorbis/synthesis.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/tone.c (renamed from drivers/vorbis/tone.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/vorbis/codec.h (renamed from drivers/vorbis/codec.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/vorbis/vorbisenc.h (renamed from drivers/vorbis/vorbisenc.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/vorbis/vorbisfile.h (renamed from drivers/vorbis/vorbisfile.h) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/vorbisenc.c (renamed from drivers/vorbis/vorbisenc.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/vorbisfile.c (renamed from drivers/vorbis/vorbisfile.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/window.c (renamed from drivers/vorbis/window.c) | 0 | ||||
-rw-r--r-- | thirdparty/libvorbis/window.h (renamed from drivers/vorbis/window.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/AUTHORS (renamed from drivers/webp/AUTHORS) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/COPYING (renamed from drivers/webp/COPYING) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/PATENTS (renamed from drivers/webp/PATENTS) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/alpha.c | 232 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/alphai.h (renamed from drivers/webp/dec/alphai.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/buffer.c (renamed from drivers/webp/dec/buffer.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/common.h (renamed from drivers/webp/dec/common.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/decode_vp8.h | 185 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/frame.c (renamed from drivers/webp/dec/frame.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/idec.c (renamed from drivers/webp/dec/idec.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/io.c (renamed from drivers/webp/dec/io.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/quant.c (renamed from drivers/webp/dec/quant.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/tree.c (renamed from drivers/webp/dec/tree.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/vp8.c (renamed from drivers/webp/dec/vp8.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/vp8i.h (renamed from drivers/webp/dec/vp8i.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/vp8l.c (renamed from drivers/webp/dec/vp8l.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/vp8li.h (renamed from drivers/webp/dec/vp8li.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/webp.c | 846 | ||||
-rw-r--r-- | thirdparty/libwebp/dec/webpi.h (renamed from drivers/webp/dec/webpi.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/demux/anim_decode.c | 442 | ||||
-rw-r--r-- | thirdparty/libwebp/demux/demux.c | 966 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/alpha_processing.c (renamed from drivers/webp/dsp/alpha_processing.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/alpha_processing_mips_dsp_r2.c (renamed from drivers/webp/dsp/alpha_processing_mips_dsp_r2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/alpha_processing_sse2.c (renamed from drivers/webp/dsp/alpha_processing_sse2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/alpha_processing_sse41.c (renamed from drivers/webp/dsp/alpha_processing_sse41.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/argb.c (renamed from drivers/webp/dsp/argb.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/argb_mips_dsp_r2.c (renamed from drivers/webp/dsp/argb_mips_dsp_r2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/argb_sse2.c (renamed from drivers/webp/dsp/argb_sse2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/common_sse2.h (renamed from drivers/webp/dsp/common_sse2.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/cost.c (renamed from drivers/webp/dsp/cost.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/cost_mips32.c (renamed from drivers/webp/dsp/cost_mips32.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/cost_mips_dsp_r2.c (renamed from drivers/webp/dsp/cost_mips_dsp_r2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/cost_sse2.c (renamed from drivers/webp/dsp/cost_sse2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/cpu.c (renamed from drivers/webp/dsp/cpu.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/dec.c (renamed from drivers/webp/dsp/dec.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/dec_clip_tables.c (renamed from drivers/webp/dsp/dec_clip_tables.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/dec_mips32.c (renamed from drivers/webp/dsp/dec_mips32.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/dec_mips_dsp_r2.c (renamed from drivers/webp/dsp/dec_mips_dsp_r2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/dec_msa.c (renamed from drivers/webp/dsp/dec_msa.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/dec_neon.c (renamed from drivers/webp/dsp/dec_neon.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/dec_sse2.c (renamed from drivers/webp/dsp/dec_sse2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/dec_sse41.c (renamed from drivers/webp/dsp/dec_sse41.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/dsp.h | 569 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/enc.c (renamed from drivers/webp/dsp/enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/enc_avx2.c (renamed from drivers/webp/dsp/enc_avx2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/enc_mips32.c (renamed from drivers/webp/dsp/enc_mips32.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/enc_mips_dsp_r2.c (renamed from drivers/webp/dsp/enc_mips_dsp_r2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/enc_neon.c (renamed from drivers/webp/dsp/enc_neon.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/enc_sse2.c (renamed from drivers/webp/dsp/enc_sse2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/enc_sse41.c (renamed from drivers/webp/dsp/enc_sse41.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/filters.c (renamed from drivers/webp/dsp/filters.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/filters_mips_dsp_r2.c (renamed from drivers/webp/dsp/filters_mips_dsp_r2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/filters_sse2.c (renamed from drivers/webp/dsp/filters_sse2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/lossless.c (renamed from drivers/webp/dsp/lossless.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/lossless.h | 372 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/lossless_enc.c (renamed from drivers/webp/dsp/lossless_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/lossless_enc_mips32.c (renamed from drivers/webp/dsp/lossless_enc_mips32.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/lossless_enc_mips_dsp_r2.c (renamed from drivers/webp/dsp/lossless_enc_mips_dsp_r2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/lossless_enc_neon.c (renamed from drivers/webp/dsp/lossless_enc_neon.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/lossless_enc_sse2.c (renamed from drivers/webp/dsp/lossless_enc_sse2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/lossless_enc_sse41.c (renamed from drivers/webp/dsp/lossless_enc_sse41.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/lossless_mips_dsp_r2.c (renamed from drivers/webp/dsp/lossless_mips_dsp_r2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/lossless_neon.c (renamed from drivers/webp/dsp/lossless_neon.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/lossless_sse2.c (renamed from drivers/webp/dsp/lossless_sse2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/mips_macro.h (renamed from drivers/webp/dsp/mips_macro.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/msa_macro.h (renamed from drivers/webp/dsp/msa_macro.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/neon.h (renamed from drivers/webp/dsp/neon.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/rescaler.c (renamed from drivers/webp/dsp/rescaler.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/rescaler_mips32.c (renamed from drivers/webp/dsp/rescaler_mips32.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/rescaler_mips_dsp_r2.c (renamed from drivers/webp/dsp/rescaler_mips_dsp_r2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/rescaler_neon.c (renamed from drivers/webp/dsp/rescaler_neon.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/rescaler_sse2.c (renamed from drivers/webp/dsp/rescaler_sse2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/upsampling.c (renamed from drivers/webp/dsp/upsampling.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/upsampling_mips_dsp_r2.c (renamed from drivers/webp/dsp/upsampling_mips_dsp_r2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/upsampling_neon.c (renamed from drivers/webp/dsp/upsampling_neon.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/upsampling_sse2.c (renamed from drivers/webp/dsp/upsampling_sse2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/yuv.c (renamed from drivers/webp/dsp/yuv.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/yuv.h (renamed from drivers/webp/dsp/yuv.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/yuv_mips32.c (renamed from drivers/webp/dsp/yuv_mips32.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/yuv_mips_dsp_r2.c (renamed from drivers/webp/dsp/yuv_mips_dsp_r2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/yuv_sse2.c (renamed from drivers/webp/dsp/yuv_sse2.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/dsp/yuv_tables_sse2.h (renamed from drivers/webp/dsp/yuv_tables_sse2.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/alpha.c | 433 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/analysis.c (renamed from drivers/webp/enc/analysis.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/backward_references.c (renamed from drivers/webp/enc/backward_references.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/backward_references.h | 206 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/config.c | 173 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/cost.c (renamed from drivers/webp/enc/cost.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/cost.h (renamed from drivers/webp/enc/cost.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/delta_palettization.c | 455 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/delta_palettization.h | 25 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/filter.c (renamed from drivers/webp/enc/filter.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/frame.c | 850 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/histogram.c | 937 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/histogram.h | 123 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/iterator.c (renamed from drivers/webp/enc/iterator.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/near_lossless.c (renamed from drivers/webp/enc/near_lossless.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/picture.c (renamed from drivers/webp/enc/picture.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/picture_csp.c (renamed from drivers/webp/enc/picture_csp.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/picture_psnr.c (renamed from drivers/webp/enc/picture_psnr.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/picture_rescale.c (renamed from drivers/webp/enc/picture_rescale.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/picture_tools.c (renamed from drivers/webp/enc/picture_tools.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/quant.c (renamed from drivers/webp/enc/quant.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/syntax.c | 383 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/token.c (renamed from drivers/webp/enc/token.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/tree.c (renamed from drivers/webp/enc/tree.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/vp8enci.h | 531 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/vp8l.c | 1603 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/vp8li.h | 81 | ||||
-rw-r--r-- | thirdparty/libwebp/enc/webpenc.c (renamed from drivers/webp/enc/webpenc.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/mux/anim_encode.c | 1534 | ||||
-rw-r--r-- | thirdparty/libwebp/mux/muxedit.c (renamed from drivers/webp/mux/muxedit.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/mux/muxi.h | 232 | ||||
-rw-r--r-- | thirdparty/libwebp/mux/muxinternal.c (renamed from drivers/webp/mux/muxinternal.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/mux/muxread.c (renamed from drivers/webp/mux/muxread.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/bit_reader.c | 229 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/bit_reader.h | 184 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/bit_reader_inl.h | 173 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/bit_writer.c (renamed from drivers/webp/utils/bit_writer.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/bit_writer.h | 145 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/color_cache.c (renamed from drivers/webp/utils/color_cache.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/color_cache.h | 80 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/endian_inl.h (renamed from drivers/webp/utils/endian_inl.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/filters.c (renamed from drivers/webp/utils/filters.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/filters.h | 32 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/huffman.c | 205 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/huffman.h | 88 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/huffman_encode.c | 417 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/huffman_encode.h | 60 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/quant_levels.c (renamed from drivers/webp/utils/quant_levels.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/quant_levels.h | 36 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/quant_levels_dec.c (renamed from drivers/webp/utils/quant_levels_dec.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/quant_levels_dec.h | 35 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/random.c (renamed from drivers/webp/utils/random.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/random.h | 63 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/rescaler.c (renamed from drivers/webp/utils/rescaler.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/rescaler.h | 101 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/thread.c (renamed from drivers/webp/utils/thread.c) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/thread.h | 93 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/utils.c | 305 | ||||
-rw-r--r-- | thirdparty/libwebp/utils/utils.h | 182 | ||||
-rw-r--r-- | thirdparty/libwebp/webp/config.h (renamed from drivers/webp/config.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/webp/decode.h (renamed from drivers/webp/decode.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/webp/demux.h (renamed from drivers/webp/demux.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/webp/encode.h (renamed from drivers/webp/encode.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/webp/format_constants.h (renamed from drivers/webp/format_constants.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/webp/mux.h (renamed from drivers/webp/mux.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/webp/mux_types.h (renamed from drivers/webp/mux_types.h) | 0 | ||||
-rw-r--r-- | thirdparty/libwebp/webp/types.h (renamed from drivers/webp/types.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/LICENSE | 127 | ||||
-rw-r--r-- | thirdparty/openssl/buildinf.h (renamed from drivers/builtin_openssl2/buildinf.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/LPdir_nyi.c (renamed from drivers/builtin_openssl2/crypto/LPdir_nyi.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/LPdir_unix.c (renamed from drivers/builtin_openssl2/crypto/LPdir_unix.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/LPdir_vms.c (renamed from drivers/builtin_openssl2/crypto/LPdir_vms.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/LPdir_win.c (renamed from drivers/builtin_openssl2/crypto/LPdir_win.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/LPdir_win32.c (renamed from drivers/builtin_openssl2/crypto/LPdir_win32.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/LPdir_wince.c (renamed from drivers/builtin_openssl2/crypto/LPdir_wince.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/aes/README (renamed from drivers/builtin_openssl2/crypto/aes/README) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/aes/aes_cbc.c (renamed from drivers/builtin_openssl2/crypto/aes/aes_cbc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/aes/aes_cfb.c (renamed from drivers/builtin_openssl2/crypto/aes/aes_cfb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/aes/aes_core.c (renamed from drivers/builtin_openssl2/crypto/aes/aes_core.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/aes/aes_ctr.c (renamed from drivers/builtin_openssl2/crypto/aes/aes_ctr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/aes/aes_ecb.c (renamed from drivers/builtin_openssl2/crypto/aes/aes_ecb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/aes/aes_ige.c (renamed from drivers/builtin_openssl2/crypto/aes/aes_ige.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/aes/aes_locl.h (renamed from drivers/builtin_openssl2/crypto/aes/aes_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/aes/aes_misc.c (renamed from drivers/builtin_openssl2/crypto/aes/aes_misc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/aes/aes_ofb.c (renamed from drivers/builtin_openssl2/crypto/aes/aes_ofb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/aes/aes_wrap.c (renamed from drivers/builtin_openssl2/crypto/aes/aes_wrap.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/aes/aes_x86core.c (renamed from drivers/builtin_openssl2/crypto/aes/aes_x86core.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/arm_arch.h (renamed from drivers/builtin_openssl2/crypto/arm_arch.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/armcap.c (renamed from drivers/builtin_openssl2/crypto/armcap.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_bitstr.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_bitstr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_bool.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_bool.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_bytes.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_bytes.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_d2i_fp.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_d2i_fp.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_digest.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_digest.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_dup.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_dup.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_enum.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_enum.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_gentm.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_gentm.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_i2d_fp.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_i2d_fp.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_int.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_int.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_mbstr.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_mbstr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_object.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_object.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_octet.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_octet.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_print.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_print.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_set.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_set.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_sign.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_sign.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_strex.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_strex.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_strnid.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_strnid.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_time.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_time.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_type.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_type.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_utctm.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_utctm.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_utf8.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_utf8.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/a_verify.c (renamed from drivers/builtin_openssl2/crypto/asn1/a_verify.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/ameth_lib.c (renamed from drivers/builtin_openssl2/crypto/asn1/ameth_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/asn1_err.c (renamed from drivers/builtin_openssl2/crypto/asn1/asn1_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/asn1_gen.c (renamed from drivers/builtin_openssl2/crypto/asn1/asn1_gen.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/asn1_lib.c (renamed from drivers/builtin_openssl2/crypto/asn1/asn1_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/asn1_locl.h (renamed from drivers/builtin_openssl2/crypto/asn1/asn1_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/asn1_par.c (renamed from drivers/builtin_openssl2/crypto/asn1/asn1_par.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/asn_mime.c (renamed from drivers/builtin_openssl2/crypto/asn1/asn_mime.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/asn_moid.c (renamed from drivers/builtin_openssl2/crypto/asn1/asn_moid.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/asn_pack.c (renamed from drivers/builtin_openssl2/crypto/asn1/asn_pack.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/bio_asn1.c (renamed from drivers/builtin_openssl2/crypto/asn1/bio_asn1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/bio_ndef.c (renamed from drivers/builtin_openssl2/crypto/asn1/bio_ndef.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/charmap.h (renamed from drivers/builtin_openssl2/crypto/asn1/charmap.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/d2i_pr.c (renamed from drivers/builtin_openssl2/crypto/asn1/d2i_pr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/d2i_pu.c (renamed from drivers/builtin_openssl2/crypto/asn1/d2i_pu.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/evp_asn1.c (renamed from drivers/builtin_openssl2/crypto/asn1/evp_asn1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/f_enum.c (renamed from drivers/builtin_openssl2/crypto/asn1/f_enum.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/f_int.c (renamed from drivers/builtin_openssl2/crypto/asn1/f_int.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/f_string.c (renamed from drivers/builtin_openssl2/crypto/asn1/f_string.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/i2d_pr.c (renamed from drivers/builtin_openssl2/crypto/asn1/i2d_pr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/i2d_pu.c (renamed from drivers/builtin_openssl2/crypto/asn1/i2d_pu.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/n_pkey.c (renamed from drivers/builtin_openssl2/crypto/asn1/n_pkey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/nsseq.c (renamed from drivers/builtin_openssl2/crypto/asn1/nsseq.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/p5_pbe.c (renamed from drivers/builtin_openssl2/crypto/asn1/p5_pbe.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/p5_pbev2.c (renamed from drivers/builtin_openssl2/crypto/asn1/p5_pbev2.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/p8_pkey.c (renamed from drivers/builtin_openssl2/crypto/asn1/p8_pkey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/t_bitst.c (renamed from drivers/builtin_openssl2/crypto/asn1/t_bitst.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/t_crl.c (renamed from drivers/builtin_openssl2/crypto/asn1/t_crl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/t_pkey.c (renamed from drivers/builtin_openssl2/crypto/asn1/t_pkey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/t_req.c (renamed from drivers/builtin_openssl2/crypto/asn1/t_req.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/t_spki.c (renamed from drivers/builtin_openssl2/crypto/asn1/t_spki.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/t_x509.c (renamed from drivers/builtin_openssl2/crypto/asn1/t_x509.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/t_x509a.c (renamed from drivers/builtin_openssl2/crypto/asn1/t_x509a.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/tasn_dec.c (renamed from drivers/builtin_openssl2/crypto/asn1/tasn_dec.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/tasn_enc.c (renamed from drivers/builtin_openssl2/crypto/asn1/tasn_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/tasn_fre.c (renamed from drivers/builtin_openssl2/crypto/asn1/tasn_fre.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/tasn_new.c (renamed from drivers/builtin_openssl2/crypto/asn1/tasn_new.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/tasn_prn.c (renamed from drivers/builtin_openssl2/crypto/asn1/tasn_prn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/tasn_typ.c (renamed from drivers/builtin_openssl2/crypto/asn1/tasn_typ.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/tasn_utl.c (renamed from drivers/builtin_openssl2/crypto/asn1/tasn_utl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_algor.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_algor.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_attrib.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_attrib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_bignum.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_bignum.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_crl.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_crl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_exten.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_exten.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_info.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_info.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_long.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_long.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_name.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_name.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_nx509.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_nx509.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_pkey.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_pkey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_pubkey.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_pubkey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_req.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_req.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_sig.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_sig.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_spki.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_spki.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_val.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_val.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_x509.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_x509.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/asn1/x_x509a.c (renamed from drivers/builtin_openssl2/crypto/asn1/x_x509a.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/COPYRIGHT (renamed from drivers/builtin_openssl2/crypto/bf/COPYRIGHT) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/INSTALL (renamed from drivers/builtin_openssl2/crypto/bf/INSTALL) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/README (renamed from drivers/builtin_openssl2/crypto/bf/README) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/VERSION (renamed from drivers/builtin_openssl2/crypto/bf/VERSION) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/asm/readme (renamed from drivers/builtin_openssl2/crypto/bf/asm/readme) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/bf_cbc.c (renamed from drivers/builtin_openssl2/crypto/bf/bf_cbc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/bf_cfb64.c (renamed from drivers/builtin_openssl2/crypto/bf/bf_cfb64.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/bf_ecb.c (renamed from drivers/builtin_openssl2/crypto/bf/bf_ecb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/bf_enc.c (renamed from drivers/builtin_openssl2/crypto/bf/bf_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/bf_locl.h (renamed from drivers/builtin_openssl2/crypto/bf/bf_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/bf_ofb64.c (renamed from drivers/builtin_openssl2/crypto/bf/bf_ofb64.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/bf_opts.c (renamed from drivers/builtin_openssl2/crypto/bf/bf_opts.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/bf_pi.h (renamed from drivers/builtin_openssl2/crypto/bf/bf_pi.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/bf_skey.c (renamed from drivers/builtin_openssl2/crypto/bf/bf_skey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/bfs.cpp (renamed from drivers/builtin_openssl2/crypto/bf/bfs.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bf/bfspeed.c (renamed from drivers/builtin_openssl2/crypto/bf/bfspeed.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/b_dump.c (renamed from drivers/builtin_openssl2/crypto/bio/b_dump.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/b_print.c (renamed from drivers/builtin_openssl2/crypto/bio/b_print.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/b_sock.c (renamed from drivers/builtin_openssl2/crypto/bio/b_sock.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bf_buff.c (renamed from drivers/builtin_openssl2/crypto/bio/bf_buff.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bf_lbuf.c (renamed from drivers/builtin_openssl2/crypto/bio/bf_lbuf.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bf_nbio.c (renamed from drivers/builtin_openssl2/crypto/bio/bf_nbio.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bf_null.c (renamed from drivers/builtin_openssl2/crypto/bio/bf_null.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bio_cb.c (renamed from drivers/builtin_openssl2/crypto/bio/bio_cb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bio_err.c (renamed from drivers/builtin_openssl2/crypto/bio/bio_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bio_lcl.h (renamed from drivers/builtin_openssl2/crypto/bio/bio_lcl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bio_lib.c (renamed from drivers/builtin_openssl2/crypto/bio/bio_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bss_acpt.c (renamed from drivers/builtin_openssl2/crypto/bio/bss_acpt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bss_bio.c (renamed from drivers/builtin_openssl2/crypto/bio/bss_bio.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bss_conn.c (renamed from drivers/builtin_openssl2/crypto/bio/bss_conn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bss_dgram.c (renamed from drivers/builtin_openssl2/crypto/bio/bss_dgram.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bss_fd.c (renamed from drivers/builtin_openssl2/crypto/bio/bss_fd.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bss_file.c (renamed from drivers/builtin_openssl2/crypto/bio/bss_file.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bss_log.c (renamed from drivers/builtin_openssl2/crypto/bio/bss_log.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bss_mem.c (renamed from drivers/builtin_openssl2/crypto/bio/bss_mem.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bss_null.c (renamed from drivers/builtin_openssl2/crypto/bio/bss_null.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bss_rtcp.c (renamed from drivers/builtin_openssl2/crypto/bio/bss_rtcp.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bio/bss_sock.c (renamed from drivers/builtin_openssl2/crypto/bio/bss_sock.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/asm/README (renamed from drivers/builtin_openssl2/crypto/bn/asm/README) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/asm/vms.mar (renamed from drivers/builtin_openssl2/crypto/bn/asm/vms.mar) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/asm/x86/f (renamed from drivers/builtin_openssl2/crypto/bn/asm/x86/f) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/asm/x86_64-gcc.c (renamed from drivers/builtin_openssl2/crypto/bn/asm/x86_64-gcc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn.mul (renamed from drivers/builtin_openssl2/crypto/bn/bn.mul) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_add.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_add.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_asm.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_asm.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_blind.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_blind.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_const.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_const.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_ctx.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_ctx.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_depr.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_depr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_div.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_div.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_err.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_exp.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_exp.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_exp2.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_exp2.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_gcd.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_gcd.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_gf2m.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_gf2m.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_kron.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_kron.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_lcl.h (renamed from drivers/builtin_openssl2/crypto/bn/bn_lcl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_lib.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_mod.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_mod.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_mont.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_mont.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_mpi.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_mpi.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_mul.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_mul.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_nist.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_nist.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_prime.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_prime.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_prime.h (renamed from drivers/builtin_openssl2/crypto/bn/bn_prime.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_print.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_print.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_rand.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_rand.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_recp.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_recp.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_shift.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_shift.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_sqr.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_sqr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_sqrt.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_sqrt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_word.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_word.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bn_x931p.c (renamed from drivers/builtin_openssl2/crypto/bn/bn_x931p.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/bnspeed.c (renamed from drivers/builtin_openssl2/crypto/bn/bnspeed.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/exp.c (renamed from drivers/builtin_openssl2/crypto/bn/exp.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/expspeed.c (renamed from drivers/builtin_openssl2/crypto/bn/expspeed.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/rsaz_exp.c (renamed from drivers/builtin_openssl2/crypto/bn/rsaz_exp.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/rsaz_exp.h (renamed from drivers/builtin_openssl2/crypto/bn/rsaz_exp.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/todo (renamed from drivers/builtin_openssl2/crypto/bn/todo) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/bn/vms-helper.c (renamed from drivers/builtin_openssl2/crypto/bn/vms-helper.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/buffer/buf_err.c (renamed from drivers/builtin_openssl2/crypto/buffer/buf_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/buffer/buf_str.c (renamed from drivers/builtin_openssl2/crypto/buffer/buf_str.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/buffer/buffer.c (renamed from drivers/builtin_openssl2/crypto/buffer/buffer.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/camellia/camellia.c (renamed from drivers/builtin_openssl2/crypto/camellia/camellia.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/camellia/cmll_cbc.c (renamed from drivers/builtin_openssl2/crypto/camellia/cmll_cbc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/camellia/cmll_cfb.c (renamed from drivers/builtin_openssl2/crypto/camellia/cmll_cfb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/camellia/cmll_ctr.c (renamed from drivers/builtin_openssl2/crypto/camellia/cmll_ctr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/camellia/cmll_ecb.c (renamed from drivers/builtin_openssl2/crypto/camellia/cmll_ecb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/camellia/cmll_locl.h (renamed from drivers/builtin_openssl2/crypto/camellia/cmll_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/camellia/cmll_misc.c (renamed from drivers/builtin_openssl2/crypto/camellia/cmll_misc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/camellia/cmll_ofb.c (renamed from drivers/builtin_openssl2/crypto/camellia/cmll_ofb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/camellia/cmll_utl.c (renamed from drivers/builtin_openssl2/crypto/camellia/cmll_utl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cast/asm/readme (renamed from drivers/builtin_openssl2/crypto/cast/asm/readme) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cast/c_cfb64.c (renamed from drivers/builtin_openssl2/crypto/cast/c_cfb64.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cast/c_ecb.c (renamed from drivers/builtin_openssl2/crypto/cast/c_ecb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cast/c_enc.c (renamed from drivers/builtin_openssl2/crypto/cast/c_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cast/c_ofb64.c (renamed from drivers/builtin_openssl2/crypto/cast/c_ofb64.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cast/c_skey.c (renamed from drivers/builtin_openssl2/crypto/cast/c_skey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cast/cast_lcl.h (renamed from drivers/builtin_openssl2/crypto/cast/cast_lcl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cast/cast_s.h (renamed from drivers/builtin_openssl2/crypto/cast/cast_s.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cast/cast_spd.c (renamed from drivers/builtin_openssl2/crypto/cast/cast_spd.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cast/castopts.c (renamed from drivers/builtin_openssl2/crypto/cast/castopts.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cast/casts.cpp (renamed from drivers/builtin_openssl2/crypto/cast/casts.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cmac/cm_ameth.c (renamed from drivers/builtin_openssl2/crypto/cmac/cm_ameth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cmac/cm_pmeth.c (renamed from drivers/builtin_openssl2/crypto/cmac/cm_pmeth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cmac/cmac.c (renamed from drivers/builtin_openssl2/crypto/cmac/cmac.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_asn1.c (renamed from drivers/builtin_openssl2/crypto/cms/cms_asn1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_att.c (renamed from drivers/builtin_openssl2/crypto/cms/cms_att.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_cd.c (renamed from drivers/builtin_openssl2/crypto/cms/cms_cd.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_dd.c (renamed from drivers/builtin_openssl2/crypto/cms/cms_dd.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_enc.c (renamed from drivers/builtin_openssl2/crypto/cms/cms_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_env.c (renamed from drivers/builtin_openssl2/crypto/cms/cms_env.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_err.c (renamed from drivers/builtin_openssl2/crypto/cms/cms_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_ess.c (renamed from drivers/builtin_openssl2/crypto/cms/cms_ess.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_io.c (renamed from drivers/builtin_openssl2/crypto/cms/cms_io.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_kari.c (renamed from drivers/builtin_openssl2/crypto/cms/cms_kari.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_lcl.h (renamed from drivers/builtin_openssl2/crypto/cms/cms_lcl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_lib.c (renamed from drivers/builtin_openssl2/crypto/cms/cms_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_pwri.c (renamed from drivers/builtin_openssl2/crypto/cms/cms_pwri.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_sd.c (renamed from drivers/builtin_openssl2/crypto/cms/cms_sd.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cms/cms_smime.c (renamed from drivers/builtin_openssl2/crypto/cms/cms_smime.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/comp/c_rle.c (renamed from drivers/builtin_openssl2/crypto/comp/c_rle.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/comp/c_zlib.c (renamed from drivers/builtin_openssl2/crypto/comp/c_zlib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/comp/comp_err.c (renamed from drivers/builtin_openssl2/crypto/comp/comp_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/comp/comp_lib.c (renamed from drivers/builtin_openssl2/crypto/comp/comp_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/conf/README (renamed from drivers/builtin_openssl2/crypto/conf/README) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/conf/cnf_save.c (renamed from drivers/builtin_openssl2/crypto/conf/cnf_save.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/conf/conf_api.c (renamed from drivers/builtin_openssl2/crypto/conf/conf_api.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/conf/conf_def.c (renamed from drivers/builtin_openssl2/crypto/conf/conf_def.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/conf/conf_def.h (renamed from drivers/builtin_openssl2/crypto/conf/conf_def.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/conf/conf_err.c (renamed from drivers/builtin_openssl2/crypto/conf/conf_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/conf/conf_lib.c (renamed from drivers/builtin_openssl2/crypto/conf/conf_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/conf/conf_mall.c (renamed from drivers/builtin_openssl2/crypto/conf/conf_mall.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/conf/conf_mod.c (renamed from drivers/builtin_openssl2/crypto/conf/conf_mod.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/conf/conf_sap.c (renamed from drivers/builtin_openssl2/crypto/conf/conf_sap.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/conf/ssleay.cnf (renamed from drivers/builtin_openssl2/crypto/conf/ssleay.cnf) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/constant_time_locl.h (renamed from drivers/builtin_openssl2/crypto/constant_time_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cpt_err.c (renamed from drivers/builtin_openssl2/crypto/cpt_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cryptlib.c (renamed from drivers/builtin_openssl2/crypto/cryptlib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cryptlib.h (renamed from drivers/builtin_openssl2/crypto/cryptlib.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/crypto-lib.com (renamed from drivers/builtin_openssl2/crypto/crypto-lib.com) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/cversion.c (renamed from drivers/builtin_openssl2/crypto/cversion.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/COPYRIGHT (renamed from drivers/builtin_openssl2/crypto/des/COPYRIGHT) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/DES.pm (renamed from drivers/builtin_openssl2/crypto/des/DES.pm) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/DES.xs (renamed from drivers/builtin_openssl2/crypto/des/DES.xs) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/FILES0 (renamed from drivers/builtin_openssl2/crypto/des/FILES0) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/INSTALL (renamed from drivers/builtin_openssl2/crypto/des/INSTALL) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/Imakefile (renamed from drivers/builtin_openssl2/crypto/des/Imakefile) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/KERBEROS (renamed from drivers/builtin_openssl2/crypto/des/KERBEROS) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/README (renamed from drivers/builtin_openssl2/crypto/des/README) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/VERSION (renamed from drivers/builtin_openssl2/crypto/des/VERSION) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/asm/des_enc.m4 (renamed from drivers/builtin_openssl2/crypto/des/asm/des_enc.m4) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/asm/readme (renamed from drivers/builtin_openssl2/crypto/des/asm/readme) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/cbc3_enc.c (renamed from drivers/builtin_openssl2/crypto/des/cbc3_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/cbc_cksm.c (renamed from drivers/builtin_openssl2/crypto/des/cbc_cksm.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/cbc_enc.c (renamed from drivers/builtin_openssl2/crypto/des/cbc_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/cfb64ede.c (renamed from drivers/builtin_openssl2/crypto/des/cfb64ede.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/cfb64enc.c (renamed from drivers/builtin_openssl2/crypto/des/cfb64enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/cfb_enc.c (renamed from drivers/builtin_openssl2/crypto/des/cfb_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/des-lib.com (renamed from drivers/builtin_openssl2/crypto/des/des-lib.com) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/des.c (renamed from drivers/builtin_openssl2/crypto/des/des.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/des3s.cpp (renamed from drivers/builtin_openssl2/crypto/des/des3s.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/des_enc.c (renamed from drivers/builtin_openssl2/crypto/des/des_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/des_locl.h (renamed from drivers/builtin_openssl2/crypto/des/des_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/des_old.c (renamed from drivers/builtin_openssl2/crypto/des/des_old.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/des_old2.c (renamed from drivers/builtin_openssl2/crypto/des/des_old2.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/des_opts.c (renamed from drivers/builtin_openssl2/crypto/des/des_opts.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/des_ver.h (renamed from drivers/builtin_openssl2/crypto/des/des_ver.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/dess.cpp (renamed from drivers/builtin_openssl2/crypto/des/dess.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/ecb3_enc.c (renamed from drivers/builtin_openssl2/crypto/des/ecb3_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/ecb_enc.c (renamed from drivers/builtin_openssl2/crypto/des/ecb_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/ede_cbcm_enc.c (renamed from drivers/builtin_openssl2/crypto/des/ede_cbcm_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/enc_read.c (renamed from drivers/builtin_openssl2/crypto/des/enc_read.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/enc_writ.c (renamed from drivers/builtin_openssl2/crypto/des/enc_writ.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/fcrypt.c (renamed from drivers/builtin_openssl2/crypto/des/fcrypt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/fcrypt_b.c (renamed from drivers/builtin_openssl2/crypto/des/fcrypt_b.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/makefile.bc (renamed from drivers/builtin_openssl2/crypto/des/makefile.bc) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/ncbc_enc.c (renamed from drivers/builtin_openssl2/crypto/des/ncbc_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/ofb64ede.c (renamed from drivers/builtin_openssl2/crypto/des/ofb64ede.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/ofb64enc.c (renamed from drivers/builtin_openssl2/crypto/des/ofb64enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/ofb_enc.c (renamed from drivers/builtin_openssl2/crypto/des/ofb_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/options.txt (renamed from drivers/builtin_openssl2/crypto/des/options.txt) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/pcbc_enc.c (renamed from drivers/builtin_openssl2/crypto/des/pcbc_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/qud_cksm.c (renamed from drivers/builtin_openssl2/crypto/des/qud_cksm.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/rand_key.c (renamed from drivers/builtin_openssl2/crypto/des/rand_key.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/read2pwd.c (renamed from drivers/builtin_openssl2/crypto/des/read2pwd.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/read_pwd.c (renamed from drivers/builtin_openssl2/crypto/des/read_pwd.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/rpc_des.h (renamed from drivers/builtin_openssl2/crypto/des/rpc_des.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/rpc_enc.c (renamed from drivers/builtin_openssl2/crypto/des/rpc_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/rpw.c (renamed from drivers/builtin_openssl2/crypto/des/rpw.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/set_key.c (renamed from drivers/builtin_openssl2/crypto/des/set_key.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/speed.c (renamed from drivers/builtin_openssl2/crypto/des/speed.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/spr.h (renamed from drivers/builtin_openssl2/crypto/des/spr.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/str2key.c (renamed from drivers/builtin_openssl2/crypto/des/str2key.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/t/test (renamed from drivers/builtin_openssl2/crypto/des/t/test) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/times/486-50.sol (renamed from drivers/builtin_openssl2/crypto/des/times/486-50.sol) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/times/586-100.lnx (renamed from drivers/builtin_openssl2/crypto/des/times/586-100.lnx) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/times/686-200.fre (renamed from drivers/builtin_openssl2/crypto/des/times/686-200.fre) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/times/aix.cc (renamed from drivers/builtin_openssl2/crypto/des/times/aix.cc) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/times/alpha.cc (renamed from drivers/builtin_openssl2/crypto/des/times/alpha.cc) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/times/hpux.cc (renamed from drivers/builtin_openssl2/crypto/des/times/hpux.cc) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/times/sparc.gcc (renamed from drivers/builtin_openssl2/crypto/des/times/sparc.gcc) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/times/usparc.cc (renamed from drivers/builtin_openssl2/crypto/des/times/usparc.cc) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/typemap (renamed from drivers/builtin_openssl2/crypto/des/typemap) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/des/xcbc_enc.c (renamed from drivers/builtin_openssl2/crypto/des/xcbc_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh1024.pem (renamed from drivers/builtin_openssl2/crypto/dh/dh1024.pem) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh192.pem (renamed from drivers/builtin_openssl2/crypto/dh/dh192.pem) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh2048.pem (renamed from drivers/builtin_openssl2/crypto/dh/dh2048.pem) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh4096.pem (renamed from drivers/builtin_openssl2/crypto/dh/dh4096.pem) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh512.pem (renamed from drivers/builtin_openssl2/crypto/dh/dh512.pem) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh_ameth.c (renamed from drivers/builtin_openssl2/crypto/dh/dh_ameth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh_asn1.c (renamed from drivers/builtin_openssl2/crypto/dh/dh_asn1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh_check.c (renamed from drivers/builtin_openssl2/crypto/dh/dh_check.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh_depr.c (renamed from drivers/builtin_openssl2/crypto/dh/dh_depr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh_err.c (renamed from drivers/builtin_openssl2/crypto/dh/dh_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh_gen.c (renamed from drivers/builtin_openssl2/crypto/dh/dh_gen.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh_kdf.c (renamed from drivers/builtin_openssl2/crypto/dh/dh_kdf.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh_key.c (renamed from drivers/builtin_openssl2/crypto/dh/dh_key.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh_lib.c (renamed from drivers/builtin_openssl2/crypto/dh/dh_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh_pmeth.c (renamed from drivers/builtin_openssl2/crypto/dh/dh_pmeth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh_prn.c (renamed from drivers/builtin_openssl2/crypto/dh/dh_prn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/dh_rfc5114.c (renamed from drivers/builtin_openssl2/crypto/dh/dh_rfc5114.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/example (renamed from drivers/builtin_openssl2/crypto/dh/example) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/generate (renamed from drivers/builtin_openssl2/crypto/dh/generate) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/p1024.c (renamed from drivers/builtin_openssl2/crypto/dh/p1024.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/p192.c (renamed from drivers/builtin_openssl2/crypto/dh/p192.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dh/p512.c (renamed from drivers/builtin_openssl2/crypto/dh/p512.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/README (renamed from drivers/builtin_openssl2/crypto/dsa/README) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/dsa_ameth.c (renamed from drivers/builtin_openssl2/crypto/dsa/dsa_ameth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/dsa_asn1.c (renamed from drivers/builtin_openssl2/crypto/dsa/dsa_asn1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/dsa_depr.c (renamed from drivers/builtin_openssl2/crypto/dsa/dsa_depr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/dsa_err.c (renamed from drivers/builtin_openssl2/crypto/dsa/dsa_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/dsa_gen.c (renamed from drivers/builtin_openssl2/crypto/dsa/dsa_gen.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/dsa_key.c (renamed from drivers/builtin_openssl2/crypto/dsa/dsa_key.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/dsa_lib.c (renamed from drivers/builtin_openssl2/crypto/dsa/dsa_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/dsa_locl.h (renamed from drivers/builtin_openssl2/crypto/dsa/dsa_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/dsa_ossl.c (renamed from drivers/builtin_openssl2/crypto/dsa/dsa_ossl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/dsa_pmeth.c (renamed from drivers/builtin_openssl2/crypto/dsa/dsa_pmeth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/dsa_prn.c (renamed from drivers/builtin_openssl2/crypto/dsa/dsa_prn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/dsa_sign.c (renamed from drivers/builtin_openssl2/crypto/dsa/dsa_sign.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/dsa_vrf.c (renamed from drivers/builtin_openssl2/crypto/dsa/dsa_vrf.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/dsagen.c (renamed from drivers/builtin_openssl2/crypto/dsa/dsagen.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dsa/fips186a.txt (renamed from drivers/builtin_openssl2/crypto/dsa/fips186a.txt) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dso/README (renamed from drivers/builtin_openssl2/crypto/dso/README) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dso/dso_beos.c (renamed from drivers/builtin_openssl2/crypto/dso/dso_beos.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dso/dso_dl.c (renamed from drivers/builtin_openssl2/crypto/dso/dso_dl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dso/dso_dlfcn.c (renamed from drivers/builtin_openssl2/crypto/dso/dso_dlfcn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dso/dso_err.c (renamed from drivers/builtin_openssl2/crypto/dso/dso_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dso/dso_lib.c (renamed from drivers/builtin_openssl2/crypto/dso/dso_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dso/dso_null.c (renamed from drivers/builtin_openssl2/crypto/dso/dso_null.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dso/dso_openssl.c (renamed from drivers/builtin_openssl2/crypto/dso/dso_openssl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dso/dso_vms.c (renamed from drivers/builtin_openssl2/crypto/dso/dso_vms.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/dso/dso_win32.c (renamed from drivers/builtin_openssl2/crypto/dso/dso_win32.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ebcdic.c (renamed from drivers/builtin_openssl2/crypto/ebcdic.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec2_mult.c (renamed from drivers/builtin_openssl2/crypto/ec/ec2_mult.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec2_oct.c (renamed from drivers/builtin_openssl2/crypto/ec/ec2_oct.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec2_smpl.c (renamed from drivers/builtin_openssl2/crypto/ec/ec2_smpl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec_ameth.c (renamed from drivers/builtin_openssl2/crypto/ec/ec_ameth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec_asn1.c (renamed from drivers/builtin_openssl2/crypto/ec/ec_asn1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec_check.c (renamed from drivers/builtin_openssl2/crypto/ec/ec_check.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec_curve.c (renamed from drivers/builtin_openssl2/crypto/ec/ec_curve.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec_cvt.c (renamed from drivers/builtin_openssl2/crypto/ec/ec_cvt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec_err.c (renamed from drivers/builtin_openssl2/crypto/ec/ec_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec_key.c (renamed from drivers/builtin_openssl2/crypto/ec/ec_key.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec_lcl.h (renamed from drivers/builtin_openssl2/crypto/ec/ec_lcl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec_lib.c (renamed from drivers/builtin_openssl2/crypto/ec/ec_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec_mult.c (renamed from drivers/builtin_openssl2/crypto/ec/ec_mult.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec_oct.c (renamed from drivers/builtin_openssl2/crypto/ec/ec_oct.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec_pmeth.c (renamed from drivers/builtin_openssl2/crypto/ec/ec_pmeth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ec_print.c (renamed from drivers/builtin_openssl2/crypto/ec/ec_print.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/eck_prn.c (renamed from drivers/builtin_openssl2/crypto/ec/eck_prn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ecp_mont.c (renamed from drivers/builtin_openssl2/crypto/ec/ecp_mont.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ecp_nist.c (renamed from drivers/builtin_openssl2/crypto/ec/ecp_nist.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ecp_nistp224.c (renamed from drivers/builtin_openssl2/crypto/ec/ecp_nistp224.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ecp_nistp256.c (renamed from drivers/builtin_openssl2/crypto/ec/ecp_nistp256.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ecp_nistp521.c (renamed from drivers/builtin_openssl2/crypto/ec/ecp_nistp521.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ecp_nistputil.c (renamed from drivers/builtin_openssl2/crypto/ec/ecp_nistputil.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ecp_nistz256.c (renamed from drivers/builtin_openssl2/crypto/ec/ecp_nistz256.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ecp_nistz256_table.c (renamed from drivers/builtin_openssl2/crypto/ec/ecp_nistz256_table.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ecp_oct.c (renamed from drivers/builtin_openssl2/crypto/ec/ecp_oct.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ec/ecp_smpl.c (renamed from drivers/builtin_openssl2/crypto/ec/ecp_smpl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ecdh/ech_err.c (renamed from drivers/builtin_openssl2/crypto/ecdh/ech_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ecdh/ech_kdf.c (renamed from drivers/builtin_openssl2/crypto/ecdh/ech_kdf.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ecdh/ech_key.c (renamed from drivers/builtin_openssl2/crypto/ecdh/ech_key.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ecdh/ech_lib.c (renamed from drivers/builtin_openssl2/crypto/ecdh/ech_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ecdh/ech_locl.h (renamed from drivers/builtin_openssl2/crypto/ecdh/ech_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ecdh/ech_ossl.c (renamed from drivers/builtin_openssl2/crypto/ecdh/ech_ossl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ecdsa/ecs_asn1.c (renamed from drivers/builtin_openssl2/crypto/ecdsa/ecs_asn1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ecdsa/ecs_err.c (renamed from drivers/builtin_openssl2/crypto/ecdsa/ecs_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ecdsa/ecs_lib.c (renamed from drivers/builtin_openssl2/crypto/ecdsa/ecs_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ecdsa/ecs_locl.h (renamed from drivers/builtin_openssl2/crypto/ecdsa/ecs_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ecdsa/ecs_ossl.c (renamed from drivers/builtin_openssl2/crypto/ecdsa/ecs_ossl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ecdsa/ecs_sign.c (renamed from drivers/builtin_openssl2/crypto/ecdsa/ecs_sign.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ecdsa/ecs_vrf.c (renamed from drivers/builtin_openssl2/crypto/ecdsa/ecs_vrf.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/README (renamed from drivers/builtin_openssl2/crypto/engine/README) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_all.c (renamed from drivers/builtin_openssl2/crypto/engine/eng_all.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_cnf.c (renamed from drivers/builtin_openssl2/crypto/engine/eng_cnf.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_cryptodev.c (renamed from drivers/builtin_openssl2/crypto/engine/eng_cryptodev.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_ctrl.c (renamed from drivers/builtin_openssl2/crypto/engine/eng_ctrl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_dyn.c (renamed from drivers/builtin_openssl2/crypto/engine/eng_dyn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_err.c (renamed from drivers/builtin_openssl2/crypto/engine/eng_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_fat.c (renamed from drivers/builtin_openssl2/crypto/engine/eng_fat.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_init.c (renamed from drivers/builtin_openssl2/crypto/engine/eng_init.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_int.h (renamed from drivers/builtin_openssl2/crypto/engine/eng_int.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_lib.c (renamed from drivers/builtin_openssl2/crypto/engine/eng_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_list.c (renamed from drivers/builtin_openssl2/crypto/engine/eng_list.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_openssl.c (renamed from drivers/builtin_openssl2/crypto/engine/eng_openssl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_pkey.c (renamed from drivers/builtin_openssl2/crypto/engine/eng_pkey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_rdrand.c (renamed from drivers/builtin_openssl2/crypto/engine/eng_rdrand.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/eng_table.c (renamed from drivers/builtin_openssl2/crypto/engine/eng_table.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/tb_asnmth.c (renamed from drivers/builtin_openssl2/crypto/engine/tb_asnmth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/tb_cipher.c (renamed from drivers/builtin_openssl2/crypto/engine/tb_cipher.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/tb_dh.c (renamed from drivers/builtin_openssl2/crypto/engine/tb_dh.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/tb_digest.c (renamed from drivers/builtin_openssl2/crypto/engine/tb_digest.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/tb_dsa.c (renamed from drivers/builtin_openssl2/crypto/engine/tb_dsa.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/tb_ecdh.c (renamed from drivers/builtin_openssl2/crypto/engine/tb_ecdh.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/tb_ecdsa.c (renamed from drivers/builtin_openssl2/crypto/engine/tb_ecdsa.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/tb_pkmeth.c (renamed from drivers/builtin_openssl2/crypto/engine/tb_pkmeth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/tb_rand.c (renamed from drivers/builtin_openssl2/crypto/engine/tb_rand.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/tb_rsa.c (renamed from drivers/builtin_openssl2/crypto/engine/tb_rsa.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/engine/tb_store.c (renamed from drivers/builtin_openssl2/crypto/engine/tb_store.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/err/err.c (renamed from drivers/builtin_openssl2/crypto/err/err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/err/err_all.c (renamed from drivers/builtin_openssl2/crypto/err/err_all.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/err/err_prn.c (renamed from drivers/builtin_openssl2/crypto/err/err_prn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/err/openssl.ec (renamed from drivers/builtin_openssl2/crypto/err/openssl.ec) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/bio_b64.c (renamed from drivers/builtin_openssl2/crypto/evp/bio_b64.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/bio_enc.c (renamed from drivers/builtin_openssl2/crypto/evp/bio_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/bio_md.c (renamed from drivers/builtin_openssl2/crypto/evp/bio_md.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/bio_ok.c (renamed from drivers/builtin_openssl2/crypto/evp/bio_ok.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/c_all.c (renamed from drivers/builtin_openssl2/crypto/evp/c_all.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/c_allc.c (renamed from drivers/builtin_openssl2/crypto/evp/c_allc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/c_alld.c (renamed from drivers/builtin_openssl2/crypto/evp/c_alld.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/digest.c (renamed from drivers/builtin_openssl2/crypto/evp/digest.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_aes.c (renamed from drivers/builtin_openssl2/crypto/evp/e_aes.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_aes_cbc_hmac_sha1.c (renamed from drivers/builtin_openssl2/crypto/evp/e_aes_cbc_hmac_sha1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_aes_cbc_hmac_sha256.c (renamed from drivers/builtin_openssl2/crypto/evp/e_aes_cbc_hmac_sha256.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_bf.c (renamed from drivers/builtin_openssl2/crypto/evp/e_bf.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_camellia.c (renamed from drivers/builtin_openssl2/crypto/evp/e_camellia.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_cast.c (renamed from drivers/builtin_openssl2/crypto/evp/e_cast.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_des.c (renamed from drivers/builtin_openssl2/crypto/evp/e_des.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_des3.c (renamed from drivers/builtin_openssl2/crypto/evp/e_des3.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_dsa.c (renamed from drivers/builtin_openssl2/crypto/evp/e_dsa.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_idea.c (renamed from drivers/builtin_openssl2/crypto/evp/e_idea.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_null.c (renamed from drivers/builtin_openssl2/crypto/evp/e_null.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_old.c (renamed from drivers/builtin_openssl2/crypto/evp/e_old.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_rc2.c (renamed from drivers/builtin_openssl2/crypto/evp/e_rc2.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_rc4.c (renamed from drivers/builtin_openssl2/crypto/evp/e_rc4.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_rc4_hmac_md5.c (renamed from drivers/builtin_openssl2/crypto/evp/e_rc4_hmac_md5.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_rc5.c (renamed from drivers/builtin_openssl2/crypto/evp/e_rc5.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_seed.c (renamed from drivers/builtin_openssl2/crypto/evp/e_seed.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/e_xcbc_d.c (renamed from drivers/builtin_openssl2/crypto/evp/e_xcbc_d.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/encode.c (renamed from drivers/builtin_openssl2/crypto/evp/encode.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/evp_acnf.c (renamed from drivers/builtin_openssl2/crypto/evp/evp_acnf.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/evp_cnf.c (renamed from drivers/builtin_openssl2/crypto/evp/evp_cnf.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/evp_enc.c (renamed from drivers/builtin_openssl2/crypto/evp/evp_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/evp_err.c (renamed from drivers/builtin_openssl2/crypto/evp/evp_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/evp_key.c (renamed from drivers/builtin_openssl2/crypto/evp/evp_key.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/evp_lib.c (renamed from drivers/builtin_openssl2/crypto/evp/evp_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/evp_locl.h (renamed from drivers/builtin_openssl2/crypto/evp/evp_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/evp_pbe.c (renamed from drivers/builtin_openssl2/crypto/evp/evp_pbe.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/evp_pkey.c (renamed from drivers/builtin_openssl2/crypto/evp/evp_pkey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/evptests.txt (renamed from drivers/builtin_openssl2/crypto/evp/evptests.txt) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/m_dss.c (renamed from drivers/builtin_openssl2/crypto/evp/m_dss.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/m_dss1.c (renamed from drivers/builtin_openssl2/crypto/evp/m_dss1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/m_ecdsa.c (renamed from drivers/builtin_openssl2/crypto/evp/m_ecdsa.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/m_md2.c (renamed from drivers/builtin_openssl2/crypto/evp/m_md2.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/m_md4.c (renamed from drivers/builtin_openssl2/crypto/evp/m_md4.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/m_md5.c (renamed from drivers/builtin_openssl2/crypto/evp/m_md5.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/m_mdc2.c (renamed from drivers/builtin_openssl2/crypto/evp/m_mdc2.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/m_null.c (renamed from drivers/builtin_openssl2/crypto/evp/m_null.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/m_ripemd.c (renamed from drivers/builtin_openssl2/crypto/evp/m_ripemd.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/m_sha.c (renamed from drivers/builtin_openssl2/crypto/evp/m_sha.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/m_sha1.c (renamed from drivers/builtin_openssl2/crypto/evp/m_sha1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/m_sigver.c (renamed from drivers/builtin_openssl2/crypto/evp/m_sigver.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/m_wp.c (renamed from drivers/builtin_openssl2/crypto/evp/m_wp.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/names.c (renamed from drivers/builtin_openssl2/crypto/evp/names.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/openbsd_hw.c (renamed from drivers/builtin_openssl2/crypto/evp/openbsd_hw.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/p5_crpt.c (renamed from drivers/builtin_openssl2/crypto/evp/p5_crpt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/p5_crpt2.c (renamed from drivers/builtin_openssl2/crypto/evp/p5_crpt2.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/p_dec.c (renamed from drivers/builtin_openssl2/crypto/evp/p_dec.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/p_enc.c (renamed from drivers/builtin_openssl2/crypto/evp/p_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/p_lib.c (renamed from drivers/builtin_openssl2/crypto/evp/p_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/p_open.c (renamed from drivers/builtin_openssl2/crypto/evp/p_open.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/p_seal.c (renamed from drivers/builtin_openssl2/crypto/evp/p_seal.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/p_sign.c (renamed from drivers/builtin_openssl2/crypto/evp/p_sign.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/p_verify.c (renamed from drivers/builtin_openssl2/crypto/evp/p_verify.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/pmeth_fn.c (renamed from drivers/builtin_openssl2/crypto/evp/pmeth_fn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/pmeth_gn.c (renamed from drivers/builtin_openssl2/crypto/evp/pmeth_gn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/evp/pmeth_lib.c (renamed from drivers/builtin_openssl2/crypto/evp/pmeth_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ex_data.c (renamed from drivers/builtin_openssl2/crypto/ex_data.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/fips_err.h (renamed from drivers/builtin_openssl2/crypto/fips_err.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/fips_ers.c (renamed from drivers/builtin_openssl2/crypto/fips_ers.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/hmac/hm_ameth.c (renamed from drivers/builtin_openssl2/crypto/hmac/hm_ameth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/hmac/hm_pmeth.c (renamed from drivers/builtin_openssl2/crypto/hmac/hm_pmeth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/hmac/hmac.c (renamed from drivers/builtin_openssl2/crypto/hmac/hmac.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/idea/i_cbc.c (renamed from drivers/builtin_openssl2/crypto/idea/i_cbc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/idea/i_cfb64.c (renamed from drivers/builtin_openssl2/crypto/idea/i_cfb64.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/idea/i_ecb.c (renamed from drivers/builtin_openssl2/crypto/idea/i_ecb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/idea/i_ofb64.c (renamed from drivers/builtin_openssl2/crypto/idea/i_ofb64.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/idea/i_skey.c (renamed from drivers/builtin_openssl2/crypto/idea/i_skey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/idea/idea_lcl.h (renamed from drivers/builtin_openssl2/crypto/idea/idea_lcl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/idea/idea_spd.c (renamed from drivers/builtin_openssl2/crypto/idea/idea_spd.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/idea/version (renamed from drivers/builtin_openssl2/crypto/idea/version) | 0 | ||||
-rwxr-xr-x | thirdparty/openssl/crypto/install-crypto.com (renamed from drivers/builtin_openssl2/crypto/install-crypto.com) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/jpake/jpake.c (renamed from drivers/builtin_openssl2/crypto/jpake/jpake.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/jpake/jpake.h (renamed from drivers/builtin_openssl2/crypto/jpake/jpake.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/jpake/jpake_err.c (renamed from drivers/builtin_openssl2/crypto/jpake/jpake_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/krb5/krb5_asn.c (renamed from drivers/builtin_openssl2/crypto/krb5/krb5_asn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/lhash/lh_stats.c (renamed from drivers/builtin_openssl2/crypto/lhash/lh_stats.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/lhash/lhash.c (renamed from drivers/builtin_openssl2/crypto/lhash/lhash.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md2/md2.c (renamed from drivers/builtin_openssl2/crypto/md2/md2.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md2/md2.h (renamed from drivers/builtin_openssl2/crypto/md2/md2.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md2/md2_dgst.c (renamed from drivers/builtin_openssl2/crypto/md2/md2_dgst.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md2/md2_one.c (renamed from drivers/builtin_openssl2/crypto/md2/md2_one.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md32_common.h (renamed from drivers/builtin_openssl2/crypto/md32_common.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md4/md4.c (renamed from drivers/builtin_openssl2/crypto/md4/md4.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md4/md4_dgst.c (renamed from drivers/builtin_openssl2/crypto/md4/md4_dgst.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md4/md4_locl.h (renamed from drivers/builtin_openssl2/crypto/md4/md4_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md4/md4_one.c (renamed from drivers/builtin_openssl2/crypto/md4/md4_one.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md4/md4s.cpp (renamed from drivers/builtin_openssl2/crypto/md4/md4s.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md5/md5.c (renamed from drivers/builtin_openssl2/crypto/md5/md5.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md5/md5_dgst.c (renamed from drivers/builtin_openssl2/crypto/md5/md5_dgst.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md5/md5_locl.h (renamed from drivers/builtin_openssl2/crypto/md5/md5_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md5/md5_one.c (renamed from drivers/builtin_openssl2/crypto/md5/md5_one.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/md5/md5s.cpp (renamed from drivers/builtin_openssl2/crypto/md5/md5s.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/mdc2/mdc2_one.c (renamed from drivers/builtin_openssl2/crypto/mdc2/mdc2_one.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/mdc2/mdc2dgst.c (renamed from drivers/builtin_openssl2/crypto/mdc2/mdc2dgst.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/mem.c (renamed from drivers/builtin_openssl2/crypto/mem.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/mem_clr.c (renamed from drivers/builtin_openssl2/crypto/mem_clr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/mem_dbg.c (renamed from drivers/builtin_openssl2/crypto/mem_dbg.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/modes/cbc128.c (renamed from drivers/builtin_openssl2/crypto/modes/cbc128.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/modes/ccm128.c (renamed from drivers/builtin_openssl2/crypto/modes/ccm128.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/modes/cfb128.c (renamed from drivers/builtin_openssl2/crypto/modes/cfb128.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/modes/ctr128.c (renamed from drivers/builtin_openssl2/crypto/modes/ctr128.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/modes/cts128.c (renamed from drivers/builtin_openssl2/crypto/modes/cts128.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/modes/gcm128.c (renamed from drivers/builtin_openssl2/crypto/modes/gcm128.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/modes/modes_lcl.h (renamed from drivers/builtin_openssl2/crypto/modes/modes_lcl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/modes/ofb128.c (renamed from drivers/builtin_openssl2/crypto/modes/ofb128.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/modes/wrap128.c (renamed from drivers/builtin_openssl2/crypto/modes/wrap128.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/modes/xts128.c (renamed from drivers/builtin_openssl2/crypto/modes/xts128.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/o_dir.c (renamed from drivers/builtin_openssl2/crypto/o_dir.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/o_dir.h (renamed from drivers/builtin_openssl2/crypto/o_dir.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/o_fips.c (renamed from drivers/builtin_openssl2/crypto/o_fips.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/o_init.c (renamed from drivers/builtin_openssl2/crypto/o_init.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/o_str.c (renamed from drivers/builtin_openssl2/crypto/o_str.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/o_str.h (renamed from drivers/builtin_openssl2/crypto/o_str.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/o_time.c (renamed from drivers/builtin_openssl2/crypto/o_time.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/o_time.h (renamed from drivers/builtin_openssl2/crypto/o_time.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/objects/o_names.c (renamed from drivers/builtin_openssl2/crypto/objects/o_names.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/objects/obj_dat.c (renamed from drivers/builtin_openssl2/crypto/objects/obj_dat.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/objects/obj_dat.h (renamed from drivers/builtin_openssl2/crypto/objects/obj_dat.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/objects/obj_err.c (renamed from drivers/builtin_openssl2/crypto/objects/obj_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/objects/obj_lib.c (renamed from drivers/builtin_openssl2/crypto/objects/obj_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/objects/obj_mac.num (renamed from drivers/builtin_openssl2/crypto/objects/obj_mac.num) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/objects/obj_xref.c (renamed from drivers/builtin_openssl2/crypto/objects/obj_xref.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/objects/obj_xref.h (renamed from drivers/builtin_openssl2/crypto/objects/obj_xref.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/objects/obj_xref.txt (renamed from drivers/builtin_openssl2/crypto/objects/obj_xref.txt) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/objects/objects.README (renamed from drivers/builtin_openssl2/crypto/objects/objects.README) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/objects/objects.txt (renamed from drivers/builtin_openssl2/crypto/objects/objects.txt) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ocsp/ocsp_asn.c (renamed from drivers/builtin_openssl2/crypto/ocsp/ocsp_asn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ocsp/ocsp_cl.c (renamed from drivers/builtin_openssl2/crypto/ocsp/ocsp_cl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ocsp/ocsp_err.c (renamed from drivers/builtin_openssl2/crypto/ocsp/ocsp_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ocsp/ocsp_ext.c (renamed from drivers/builtin_openssl2/crypto/ocsp/ocsp_ext.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ocsp/ocsp_ht.c (renamed from drivers/builtin_openssl2/crypto/ocsp/ocsp_ht.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ocsp/ocsp_lib.c (renamed from drivers/builtin_openssl2/crypto/ocsp/ocsp_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ocsp/ocsp_prn.c (renamed from drivers/builtin_openssl2/crypto/ocsp/ocsp_prn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ocsp/ocsp_srv.c (renamed from drivers/builtin_openssl2/crypto/ocsp/ocsp_srv.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ocsp/ocsp_vfy.c (renamed from drivers/builtin_openssl2/crypto/ocsp/ocsp_vfy.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/opensslconf.h.in (renamed from drivers/builtin_openssl2/crypto/opensslconf.h.in) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pem/message (renamed from drivers/builtin_openssl2/crypto/pem/message) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pem/pem_all.c (renamed from drivers/builtin_openssl2/crypto/pem/pem_all.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pem/pem_err.c (renamed from drivers/builtin_openssl2/crypto/pem/pem_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pem/pem_info.c (renamed from drivers/builtin_openssl2/crypto/pem/pem_info.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pem/pem_lib.c (renamed from drivers/builtin_openssl2/crypto/pem/pem_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pem/pem_oth.c (renamed from drivers/builtin_openssl2/crypto/pem/pem_oth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pem/pem_pk8.c (renamed from drivers/builtin_openssl2/crypto/pem/pem_pk8.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pem/pem_pkey.c (renamed from drivers/builtin_openssl2/crypto/pem/pem_pkey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pem/pem_seal.c (renamed from drivers/builtin_openssl2/crypto/pem/pem_seal.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pem/pem_sign.c (renamed from drivers/builtin_openssl2/crypto/pem/pem_sign.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pem/pem_x509.c (renamed from drivers/builtin_openssl2/crypto/pem/pem_x509.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pem/pem_xaux.c (renamed from drivers/builtin_openssl2/crypto/pem/pem_xaux.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pem/pkcs7.lis (renamed from drivers/builtin_openssl2/crypto/pem/pkcs7.lis) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pem/pvkfmt.c (renamed from drivers/builtin_openssl2/crypto/pem/pvkfmt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/perlasm/readme (renamed from drivers/builtin_openssl2/crypto/perlasm/readme) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/p12_add.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/p12_add.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/p12_asn.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/p12_asn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/p12_attr.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/p12_attr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/p12_crpt.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/p12_crpt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/p12_crt.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/p12_crt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/p12_decr.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/p12_decr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/p12_init.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/p12_init.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/p12_key.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/p12_key.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/p12_kiss.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/p12_kiss.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/p12_mutl.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/p12_mutl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/p12_npas.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/p12_npas.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/p12_p8d.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/p12_p8d.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/p12_p8e.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/p12_p8e.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/p12_utl.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/p12_utl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs12/pk12err.c (renamed from drivers/builtin_openssl2/crypto/pkcs12/pk12err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs7/bio_pk7.c (renamed from drivers/builtin_openssl2/crypto/pkcs7/bio_pk7.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs7/pk7_asn1.c (renamed from drivers/builtin_openssl2/crypto/pkcs7/pk7_asn1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs7/pk7_attr.c (renamed from drivers/builtin_openssl2/crypto/pkcs7/pk7_attr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs7/pk7_dgst.c (renamed from drivers/builtin_openssl2/crypto/pkcs7/pk7_dgst.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs7/pk7_doit.c (renamed from drivers/builtin_openssl2/crypto/pkcs7/pk7_doit.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs7/pk7_enc.c (renamed from drivers/builtin_openssl2/crypto/pkcs7/pk7_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs7/pk7_lib.c (renamed from drivers/builtin_openssl2/crypto/pkcs7/pk7_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs7/pk7_mime.c (renamed from drivers/builtin_openssl2/crypto/pkcs7/pk7_mime.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs7/pk7_smime.c (renamed from drivers/builtin_openssl2/crypto/pkcs7/pk7_smime.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pkcs7/pkcs7err.c (renamed from drivers/builtin_openssl2/crypto/pkcs7/pkcs7err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ppc_arch.h (renamed from drivers/builtin_openssl2/crypto/ppc_arch.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ppccap.c (renamed from drivers/builtin_openssl2/crypto/ppccap.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/pqueue/pqueue.c (renamed from drivers/builtin_openssl2/crypto/pqueue/pqueue.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rand/md_rand.c (renamed from drivers/builtin_openssl2/crypto/rand/md_rand.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rand/rand_egd.c (renamed from drivers/builtin_openssl2/crypto/rand/rand_egd.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rand/rand_err.c (renamed from drivers/builtin_openssl2/crypto/rand/rand_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rand/rand_lcl.h (renamed from drivers/builtin_openssl2/crypto/rand/rand_lcl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rand/rand_lib.c (renamed from drivers/builtin_openssl2/crypto/rand/rand_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rand/rand_nw.c (renamed from drivers/builtin_openssl2/crypto/rand/rand_nw.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rand/rand_os2.c (renamed from drivers/builtin_openssl2/crypto/rand/rand_os2.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rand/rand_unix.c (renamed from drivers/builtin_openssl2/crypto/rand/rand_unix.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rand/rand_vms.c (renamed from drivers/builtin_openssl2/crypto/rand/rand_vms.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rand/rand_win.c | 757 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rand/randfile.c (renamed from drivers/builtin_openssl2/crypto/rand/randfile.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc2/rc2_cbc.c (renamed from drivers/builtin_openssl2/crypto/rc2/rc2_cbc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc2/rc2_ecb.c (renamed from drivers/builtin_openssl2/crypto/rc2/rc2_ecb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc2/rc2_locl.h (renamed from drivers/builtin_openssl2/crypto/rc2/rc2_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc2/rc2_skey.c (renamed from drivers/builtin_openssl2/crypto/rc2/rc2_skey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc2/rc2cfb64.c (renamed from drivers/builtin_openssl2/crypto/rc2/rc2cfb64.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc2/rc2ofb64.c (renamed from drivers/builtin_openssl2/crypto/rc2/rc2ofb64.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc2/rc2speed.c (renamed from drivers/builtin_openssl2/crypto/rc2/rc2speed.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc2/rrc2.doc (renamed from drivers/builtin_openssl2/crypto/rc2/rrc2.doc) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc2/tab.c (renamed from drivers/builtin_openssl2/crypto/rc2/tab.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc2/version (renamed from drivers/builtin_openssl2/crypto/rc2/version) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc4/rc4.c (renamed from drivers/builtin_openssl2/crypto/rc4/rc4.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc4/rc4_enc.c (renamed from drivers/builtin_openssl2/crypto/rc4/rc4_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc4/rc4_locl.h (renamed from drivers/builtin_openssl2/crypto/rc4/rc4_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc4/rc4_skey.c (renamed from drivers/builtin_openssl2/crypto/rc4/rc4_skey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc4/rc4_utl.c (renamed from drivers/builtin_openssl2/crypto/rc4/rc4_utl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc4/rc4s.cpp (renamed from drivers/builtin_openssl2/crypto/rc4/rc4s.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc4/rc4speed.c (renamed from drivers/builtin_openssl2/crypto/rc4/rc4speed.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc4/rrc4.doc (renamed from drivers/builtin_openssl2/crypto/rc4/rrc4.doc) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc5/rc5.h (renamed from drivers/builtin_openssl2/crypto/rc5/rc5.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc5/rc5_ecb.c (renamed from drivers/builtin_openssl2/crypto/rc5/rc5_ecb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc5/rc5_enc.c (renamed from drivers/builtin_openssl2/crypto/rc5/rc5_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc5/rc5_locl.h (renamed from drivers/builtin_openssl2/crypto/rc5/rc5_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc5/rc5_skey.c (renamed from drivers/builtin_openssl2/crypto/rc5/rc5_skey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc5/rc5cfb64.c (renamed from drivers/builtin_openssl2/crypto/rc5/rc5cfb64.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc5/rc5ofb64.c (renamed from drivers/builtin_openssl2/crypto/rc5/rc5ofb64.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc5/rc5s.cpp (renamed from drivers/builtin_openssl2/crypto/rc5/rc5s.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rc5/rc5speed.c (renamed from drivers/builtin_openssl2/crypto/rc5/rc5speed.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ripemd/README (renamed from drivers/builtin_openssl2/crypto/ripemd/README) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ripemd/asm/rips.cpp (renamed from drivers/builtin_openssl2/crypto/ripemd/asm/rips.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ripemd/rmd160.c (renamed from drivers/builtin_openssl2/crypto/ripemd/rmd160.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ripemd/rmd_dgst.c (renamed from drivers/builtin_openssl2/crypto/ripemd/rmd_dgst.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ripemd/rmd_locl.h (renamed from drivers/builtin_openssl2/crypto/ripemd/rmd_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ripemd/rmd_one.c (renamed from drivers/builtin_openssl2/crypto/ripemd/rmd_one.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ripemd/rmdconst.h (renamed from drivers/builtin_openssl2/crypto/ripemd/rmdconst.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_ameth.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_ameth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_asn1.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_asn1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_chk.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_chk.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_crpt.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_crpt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_depr.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_depr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_eay.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_eay.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_err.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_gen.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_gen.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_lib.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_locl.h (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_none.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_none.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_null.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_null.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_oaep.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_oaep.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_pk1.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_pk1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_pmeth.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_pmeth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_prn.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_prn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_pss.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_pss.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_saos.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_saos.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_sign.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_sign.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_ssl.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_ssl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/rsa/rsa_x931.c (renamed from drivers/builtin_openssl2/crypto/rsa/rsa_x931.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/s390xcap.c (renamed from drivers/builtin_openssl2/crypto/s390xcap.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/seed/seed.c (renamed from drivers/builtin_openssl2/crypto/seed/seed.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/seed/seed_cbc.c (renamed from drivers/builtin_openssl2/crypto/seed/seed_cbc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/seed/seed_cfb.c (renamed from drivers/builtin_openssl2/crypto/seed/seed_cfb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/seed/seed_ecb.c (renamed from drivers/builtin_openssl2/crypto/seed/seed_ecb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/seed/seed_locl.h (renamed from drivers/builtin_openssl2/crypto/seed/seed_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/seed/seed_ofb.c (renamed from drivers/builtin_openssl2/crypto/seed/seed_ofb.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/sha/asm/README (renamed from drivers/builtin_openssl2/crypto/sha/asm/README) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/sha/sha.c (renamed from drivers/builtin_openssl2/crypto/sha/sha.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/sha/sha1.c (renamed from drivers/builtin_openssl2/crypto/sha/sha1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/sha/sha1_one.c (renamed from drivers/builtin_openssl2/crypto/sha/sha1_one.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/sha/sha1dgst.c (renamed from drivers/builtin_openssl2/crypto/sha/sha1dgst.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/sha/sha256.c (renamed from drivers/builtin_openssl2/crypto/sha/sha256.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/sha/sha256t.c (renamed from drivers/builtin_openssl2/crypto/sha/sha256t.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/sha/sha512.c (renamed from drivers/builtin_openssl2/crypto/sha/sha512.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/sha/sha512t.c (renamed from drivers/builtin_openssl2/crypto/sha/sha512t.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/sha/sha_dgst.c (renamed from drivers/builtin_openssl2/crypto/sha/sha_dgst.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/sha/sha_locl.h (renamed from drivers/builtin_openssl2/crypto/sha/sha_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/sha/sha_one.c (renamed from drivers/builtin_openssl2/crypto/sha/sha_one.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/sparc_arch.h (renamed from drivers/builtin_openssl2/crypto/sparc_arch.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/sparcv9cap.c (renamed from drivers/builtin_openssl2/crypto/sparcv9cap.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/srp/srp_grps.h (renamed from drivers/builtin_openssl2/crypto/srp/srp_grps.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/srp/srp_lcl.h (renamed from drivers/builtin_openssl2/crypto/srp/srp_lcl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/srp/srp_lib.c (renamed from drivers/builtin_openssl2/crypto/srp/srp_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/srp/srp_vfy.c (renamed from drivers/builtin_openssl2/crypto/srp/srp_vfy.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/stack/stack.c (renamed from drivers/builtin_openssl2/crypto/stack/stack.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/store/README (renamed from drivers/builtin_openssl2/crypto/store/README) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/store/store.h (renamed from drivers/builtin_openssl2/crypto/store/store.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/store/str_err.c (renamed from drivers/builtin_openssl2/crypto/store/str_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/store/str_lib.c (renamed from drivers/builtin_openssl2/crypto/store/str_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/store/str_locl.h (renamed from drivers/builtin_openssl2/crypto/store/str_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/store/str_mem.c (renamed from drivers/builtin_openssl2/crypto/store/str_mem.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/store/str_meth.c (renamed from drivers/builtin_openssl2/crypto/store/str_meth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/threads/README (renamed from drivers/builtin_openssl2/crypto/threads/README) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/threads/netware.bat (renamed from drivers/builtin_openssl2/crypto/threads/netware.bat) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/threads/profile.sh (renamed from drivers/builtin_openssl2/crypto/threads/profile.sh) | 0 | ||||
-rwxr-xr-x | thirdparty/openssl/crypto/threads/ptest.bat (renamed from drivers/builtin_openssl2/crypto/threads/ptest.bat) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/threads/pthread.sh (renamed from drivers/builtin_openssl2/crypto/threads/pthread.sh) | 0 | ||||
-rwxr-xr-x | thirdparty/openssl/crypto/threads/pthread2.sh (renamed from drivers/builtin_openssl2/crypto/threads/pthread2.sh) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/threads/pthreads-vms.com (renamed from drivers/builtin_openssl2/crypto/threads/pthreads-vms.com) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/threads/purify.sh (renamed from drivers/builtin_openssl2/crypto/threads/purify.sh) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/threads/solaris.sh (renamed from drivers/builtin_openssl2/crypto/threads/solaris.sh) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/threads/th-lock.c (renamed from drivers/builtin_openssl2/crypto/threads/th-lock.c) | 0 | ||||
-rwxr-xr-x | thirdparty/openssl/crypto/threads/win32.bat (renamed from drivers/builtin_openssl2/crypto/threads/win32.bat) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ts/ts_asn1.c (renamed from drivers/builtin_openssl2/crypto/ts/ts_asn1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ts/ts_conf.c (renamed from drivers/builtin_openssl2/crypto/ts/ts_conf.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ts/ts_err.c (renamed from drivers/builtin_openssl2/crypto/ts/ts_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ts/ts_lib.c (renamed from drivers/builtin_openssl2/crypto/ts/ts_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ts/ts_req_print.c (renamed from drivers/builtin_openssl2/crypto/ts/ts_req_print.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ts/ts_req_utils.c (renamed from drivers/builtin_openssl2/crypto/ts/ts_req_utils.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ts/ts_rsp_print.c (renamed from drivers/builtin_openssl2/crypto/ts/ts_rsp_print.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ts/ts_rsp_sign.c (renamed from drivers/builtin_openssl2/crypto/ts/ts_rsp_sign.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ts/ts_rsp_utils.c (renamed from drivers/builtin_openssl2/crypto/ts/ts_rsp_utils.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ts/ts_rsp_verify.c (renamed from drivers/builtin_openssl2/crypto/ts/ts_rsp_verify.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ts/ts_verify_ctx.c (renamed from drivers/builtin_openssl2/crypto/ts/ts_verify_ctx.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/txt_db/txt_db.c (renamed from drivers/builtin_openssl2/crypto/txt_db/txt_db.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ui/ui_compat.c (renamed from drivers/builtin_openssl2/crypto/ui/ui_compat.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ui/ui_err.c (renamed from drivers/builtin_openssl2/crypto/ui/ui_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ui/ui_lib.c (renamed from drivers/builtin_openssl2/crypto/ui/ui_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ui/ui_locl.h (renamed from drivers/builtin_openssl2/crypto/ui/ui_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ui/ui_openssl.c (renamed from drivers/builtin_openssl2/crypto/ui/ui_openssl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/ui/ui_util.c (renamed from drivers/builtin_openssl2/crypto/ui/ui_util.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/uid.c (renamed from drivers/builtin_openssl2/crypto/uid.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/vms_rms.h (renamed from drivers/builtin_openssl2/crypto/vms_rms.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/whrlpool/wp_block.c (renamed from drivers/builtin_openssl2/crypto/whrlpool/wp_block.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/whrlpool/wp_dgst.c (renamed from drivers/builtin_openssl2/crypto/whrlpool/wp_dgst.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/whrlpool/wp_locl.h (renamed from drivers/builtin_openssl2/crypto/whrlpool/wp_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/by_dir.c (renamed from drivers/builtin_openssl2/crypto/x509/by_dir.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/by_file.c (renamed from drivers/builtin_openssl2/crypto/x509/by_file.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/vpm_int.h (renamed from drivers/builtin_openssl2/crypto/x509/vpm_int.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_att.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_att.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_cmp.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_cmp.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_d2.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_d2.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_def.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_def.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_err.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_ext.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_ext.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_lu.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_lu.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_obj.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_obj.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_r2x.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_r2x.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_req.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_req.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_set.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_set.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_trs.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_trs.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_txt.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_txt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_v3.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_v3.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_vfy.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_vfy.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509_vpm.c (renamed from drivers/builtin_openssl2/crypto/x509/x509_vpm.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509cset.c (renamed from drivers/builtin_openssl2/crypto/x509/x509cset.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509name.c (renamed from drivers/builtin_openssl2/crypto/x509/x509name.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509rset.c (renamed from drivers/builtin_openssl2/crypto/x509/x509rset.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509spki.c (renamed from drivers/builtin_openssl2/crypto/x509/x509spki.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x509type.c (renamed from drivers/builtin_openssl2/crypto/x509/x509type.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509/x_all.c (renamed from drivers/builtin_openssl2/crypto/x509/x_all.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/ext_dat.h (renamed from drivers/builtin_openssl2/crypto/x509v3/ext_dat.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/pcy_cache.c (renamed from drivers/builtin_openssl2/crypto/x509v3/pcy_cache.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/pcy_data.c (renamed from drivers/builtin_openssl2/crypto/x509v3/pcy_data.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/pcy_int.h (renamed from drivers/builtin_openssl2/crypto/x509v3/pcy_int.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/pcy_lib.c (renamed from drivers/builtin_openssl2/crypto/x509v3/pcy_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/pcy_map.c (renamed from drivers/builtin_openssl2/crypto/x509v3/pcy_map.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/pcy_node.c (renamed from drivers/builtin_openssl2/crypto/x509v3/pcy_node.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/pcy_tree.c (renamed from drivers/builtin_openssl2/crypto/x509v3/pcy_tree.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_addr.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_addr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_akey.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_akey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_akeya.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_akeya.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_alt.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_alt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_asid.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_asid.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_bcons.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_bcons.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_bitst.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_bitst.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_conf.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_conf.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_cpols.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_cpols.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_crld.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_crld.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_enum.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_enum.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_extku.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_extku.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_genn.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_genn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_ia5.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_ia5.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_info.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_info.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_int.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_int.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_lib.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_ncons.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_ncons.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_ocsp.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_ocsp.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_pci.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_pci.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_pcia.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_pcia.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_pcons.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_pcons.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_pku.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_pku.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_pmaps.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_pmaps.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_prn.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_prn.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_purp.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_purp.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_scts.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_scts.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_skey.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_skey.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_sxnet.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_sxnet.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3_utl.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3_utl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3conf.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3conf.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3err.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/crypto/x509v3/v3prin.c (renamed from drivers/builtin_openssl2/crypto/x509v3/v3prin.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/e_os.h (renamed from drivers/builtin_openssl2/e_os.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/aes.h (renamed from drivers/builtin_openssl2/openssl/aes.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/asn1.h (renamed from drivers/builtin_openssl2/openssl/asn1.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/asn1_mac.h (renamed from drivers/builtin_openssl2/openssl/asn1_mac.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/asn1t.h (renamed from drivers/builtin_openssl2/openssl/asn1t.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/bio.h (renamed from drivers/builtin_openssl2/openssl/bio.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/blowfish.h (renamed from drivers/builtin_openssl2/openssl/blowfish.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/bn.h (renamed from drivers/builtin_openssl2/openssl/bn.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/buffer.h (renamed from drivers/builtin_openssl2/openssl/buffer.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/camellia.h (renamed from drivers/builtin_openssl2/openssl/camellia.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/cast.h (renamed from drivers/builtin_openssl2/openssl/cast.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/cmac.h (renamed from drivers/builtin_openssl2/openssl/cmac.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/cms.h (renamed from drivers/builtin_openssl2/openssl/cms.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/comp.h (renamed from drivers/builtin_openssl2/openssl/comp.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/conf.h (renamed from drivers/builtin_openssl2/openssl/conf.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/conf_api.h (renamed from drivers/builtin_openssl2/openssl/conf_api.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/crypto.h (renamed from drivers/builtin_openssl2/openssl/crypto.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/des.h (renamed from drivers/builtin_openssl2/openssl/des.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/des_old.h (renamed from drivers/builtin_openssl2/openssl/des_old.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/dh.h (renamed from drivers/builtin_openssl2/openssl/dh.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/dsa.h (renamed from drivers/builtin_openssl2/openssl/dsa.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/dso.h (renamed from drivers/builtin_openssl2/openssl/dso.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/dtls1.h | 278 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/e_os2.h (renamed from drivers/builtin_openssl2/openssl/e_os2.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/ebcdic.h (renamed from drivers/builtin_openssl2/openssl/ebcdic.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/ec.h (renamed from drivers/builtin_openssl2/openssl/ec.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/ecdh.h (renamed from drivers/builtin_openssl2/openssl/ecdh.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/ecdsa.h (renamed from drivers/builtin_openssl2/openssl/ecdsa.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/engine.h (renamed from drivers/builtin_openssl2/openssl/engine.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/err.h (renamed from drivers/builtin_openssl2/openssl/err.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/evp.h (renamed from drivers/builtin_openssl2/openssl/evp.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/hmac.h (renamed from drivers/builtin_openssl2/openssl/hmac.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/idea.h (renamed from drivers/builtin_openssl2/openssl/idea.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/krb5_asn.h (renamed from drivers/builtin_openssl2/openssl/krb5_asn.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/kssl.h (renamed from drivers/builtin_openssl2/openssl/kssl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/lhash.h (renamed from drivers/builtin_openssl2/openssl/lhash.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/md4.h (renamed from drivers/builtin_openssl2/openssl/md4.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/md5.h (renamed from drivers/builtin_openssl2/openssl/md5.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/mdc2.h (renamed from drivers/builtin_openssl2/openssl/mdc2.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/modes.h (renamed from drivers/builtin_openssl2/openssl/modes.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/obj_mac.h (renamed from drivers/builtin_openssl2/openssl/obj_mac.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/objects.h (renamed from drivers/builtin_openssl2/openssl/objects.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/ocsp.h (renamed from drivers/builtin_openssl2/openssl/ocsp.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/opensslconf.h (renamed from drivers/builtin_openssl2/openssl/opensslconf.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/opensslv.h (renamed from drivers/builtin_openssl2/openssl/opensslv.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/ossl_typ.h (renamed from drivers/builtin_openssl2/openssl/ossl_typ.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/pem.h (renamed from drivers/builtin_openssl2/openssl/pem.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/pem2.h (renamed from drivers/builtin_openssl2/openssl/pem2.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/pkcs12.h (renamed from drivers/builtin_openssl2/openssl/pkcs12.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/pkcs7.h (renamed from drivers/builtin_openssl2/openssl/pkcs7.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/pqueue.h (renamed from drivers/builtin_openssl2/openssl/pqueue.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/rand.h (renamed from drivers/builtin_openssl2/openssl/rand.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/rc2.h (renamed from drivers/builtin_openssl2/openssl/rc2.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/rc4.h (renamed from drivers/builtin_openssl2/openssl/rc4.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/ripemd.h (renamed from drivers/builtin_openssl2/openssl/ripemd.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/rsa.h (renamed from drivers/builtin_openssl2/openssl/rsa.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/safestack.h (renamed from drivers/builtin_openssl2/openssl/safestack.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/seed.h (renamed from drivers/builtin_openssl2/openssl/seed.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/sha.h (renamed from drivers/builtin_openssl2/openssl/sha.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/srp.h (renamed from drivers/builtin_openssl2/openssl/srp.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/srtp.h (renamed from drivers/builtin_openssl2/openssl/srtp.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/ssl.h (renamed from drivers/builtin_openssl2/openssl/ssl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/ssl2.h (renamed from drivers/builtin_openssl2/openssl/ssl2.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/ssl23.h (renamed from drivers/builtin_openssl2/openssl/ssl23.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/ssl3.h (renamed from drivers/builtin_openssl2/openssl/ssl3.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/stack.h (renamed from drivers/builtin_openssl2/openssl/stack.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/symhacks.h (renamed from drivers/builtin_openssl2/openssl/symhacks.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/tls1.h (renamed from drivers/builtin_openssl2/openssl/tls1.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/ts.h (renamed from drivers/builtin_openssl2/openssl/ts.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/txt_db.h (renamed from drivers/builtin_openssl2/openssl/txt_db.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/ui.h (renamed from drivers/builtin_openssl2/openssl/ui.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/ui_compat.h (renamed from drivers/builtin_openssl2/openssl/ui_compat.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/whrlpool.h (renamed from drivers/builtin_openssl2/openssl/whrlpool.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/x509.h (renamed from drivers/builtin_openssl2/openssl/x509.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/x509_vfy.h (renamed from drivers/builtin_openssl2/openssl/x509_vfy.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/openssl/x509v3.h (renamed from drivers/builtin_openssl2/openssl/x509v3.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/bio_ssl.c (renamed from drivers/builtin_openssl2/ssl/bio_ssl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/d1_both.c (renamed from drivers/builtin_openssl2/ssl/d1_both.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/d1_clnt.c (renamed from drivers/builtin_openssl2/ssl/d1_clnt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/d1_lib.c (renamed from drivers/builtin_openssl2/ssl/d1_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/d1_meth.c (renamed from drivers/builtin_openssl2/ssl/d1_meth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/d1_pkt.c (renamed from drivers/builtin_openssl2/ssl/d1_pkt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/d1_srtp.c (renamed from drivers/builtin_openssl2/ssl/d1_srtp.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/d1_srvr.c (renamed from drivers/builtin_openssl2/ssl/d1_srvr.c) | 0 | ||||
-rwxr-xr-x | thirdparty/openssl/ssl/install-ssl.com (renamed from drivers/builtin_openssl2/ssl/install-ssl.com) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/kssl.c (renamed from drivers/builtin_openssl2/ssl/kssl.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/kssl_lcl.h (renamed from drivers/builtin_openssl2/ssl/kssl_lcl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s23_clnt.c (renamed from drivers/builtin_openssl2/ssl/s23_clnt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s23_lib.c (renamed from drivers/builtin_openssl2/ssl/s23_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s23_meth.c (renamed from drivers/builtin_openssl2/ssl/s23_meth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s23_pkt.c (renamed from drivers/builtin_openssl2/ssl/s23_pkt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s23_srvr.c (renamed from drivers/builtin_openssl2/ssl/s23_srvr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s2_clnt.c (renamed from drivers/builtin_openssl2/ssl/s2_clnt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s2_enc.c (renamed from drivers/builtin_openssl2/ssl/s2_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s2_lib.c (renamed from drivers/builtin_openssl2/ssl/s2_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s2_meth.c (renamed from drivers/builtin_openssl2/ssl/s2_meth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s2_pkt.c (renamed from drivers/builtin_openssl2/ssl/s2_pkt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s2_srvr.c (renamed from drivers/builtin_openssl2/ssl/s2_srvr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s3_both.c (renamed from drivers/builtin_openssl2/ssl/s3_both.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s3_cbc.c (renamed from drivers/builtin_openssl2/ssl/s3_cbc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s3_clnt.c (renamed from drivers/builtin_openssl2/ssl/s3_clnt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s3_enc.c (renamed from drivers/builtin_openssl2/ssl/s3_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s3_lib.c (renamed from drivers/builtin_openssl2/ssl/s3_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s3_meth.c (renamed from drivers/builtin_openssl2/ssl/s3_meth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s3_pkt.c (renamed from drivers/builtin_openssl2/ssl/s3_pkt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/s3_srvr.c (renamed from drivers/builtin_openssl2/ssl/s3_srvr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl-lib.com (renamed from drivers/builtin_openssl2/ssl/ssl-lib.com) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_algs.c (renamed from drivers/builtin_openssl2/ssl/ssl_algs.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_asn1.c (renamed from drivers/builtin_openssl2/ssl/ssl_asn1.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_cert.c (renamed from drivers/builtin_openssl2/ssl/ssl_cert.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_ciph.c (renamed from drivers/builtin_openssl2/ssl/ssl_ciph.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_conf.c (renamed from drivers/builtin_openssl2/ssl/ssl_conf.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_err.c (renamed from drivers/builtin_openssl2/ssl/ssl_err.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_err2.c (renamed from drivers/builtin_openssl2/ssl/ssl_err2.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_lib.c (renamed from drivers/builtin_openssl2/ssl/ssl_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_locl.h (renamed from drivers/builtin_openssl2/ssl/ssl_locl.h) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_rsa.c (renamed from drivers/builtin_openssl2/ssl/ssl_rsa.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_sess.c (renamed from drivers/builtin_openssl2/ssl/ssl_sess.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_stat.c (renamed from drivers/builtin_openssl2/ssl/ssl_stat.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_task.c (renamed from drivers/builtin_openssl2/ssl/ssl_task.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_txt.c (renamed from drivers/builtin_openssl2/ssl/ssl_txt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/ssl_utst.c (renamed from drivers/builtin_openssl2/ssl/ssl_utst.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/t1_clnt.c (renamed from drivers/builtin_openssl2/ssl/t1_clnt.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/t1_enc.c (renamed from drivers/builtin_openssl2/ssl/t1_enc.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/t1_ext.c (renamed from drivers/builtin_openssl2/ssl/t1_ext.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/t1_lib.c (renamed from drivers/builtin_openssl2/ssl/t1_lib.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/t1_meth.c (renamed from drivers/builtin_openssl2/ssl/t1_meth.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/t1_reneg.c (renamed from drivers/builtin_openssl2/ssl/t1_reneg.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/t1_srvr.c (renamed from drivers/builtin_openssl2/ssl/t1_srvr.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/t1_trce.c (renamed from drivers/builtin_openssl2/ssl/t1_trce.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/ssl/tls_srp.c (renamed from drivers/builtin_openssl2/ssl/tls_srp.c) | 0 | ||||
-rw-r--r-- | thirdparty/openssl/winrt.cpp | 155 | ||||
-rw-r--r-- | thirdparty/openssl/winrt_fix.patch | 64 | ||||
-rw-r--r-- | thirdparty/opus/COPYING (renamed from drivers/opus/COPYING) | 0 | ||||
-rw-r--r-- | thirdparty/opus/analysis.c | 675 | ||||
-rw-r--r-- | thirdparty/opus/analysis.h | 103 | ||||
-rw-r--r-- | thirdparty/opus/celt/_kiss_fft_guts.h | 182 | ||||
-rw-r--r-- | thirdparty/opus/celt/arch.h | 241 | ||||
-rwxr-xr-x | thirdparty/opus/celt/arm/arm2gnu.pl (renamed from drivers/opus/celt/arm/arm2gnu.pl) | 0 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/arm_celt_map.c | 121 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/armcpu.c | 174 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/armcpu.h (renamed from drivers/opus/celt/arm/armcpu.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/armopts.s.in (renamed from drivers/opus/celt/arm/armopts.s.in) | 0 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/celt_ne10_fft.c | 174 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/celt_ne10_mdct.c | 258 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/celt_neon_intr.c | 252 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S (renamed from drivers/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S) | 0 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/celt_pitch_xcorr_arm.s (renamed from drivers/opus/celt/arm/celt_pitch_xcorr_arm.s) | 0 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/fft_arm.h | 72 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/fixed_arm64.h | 35 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/fixed_armv4.h (renamed from drivers/opus/celt/arm/fixed_armv4.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/fixed_armv5e.h | 151 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/kiss_fft_armv4.h | 121 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/kiss_fft_armv5e.h | 118 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/mdct_arm.h | 60 | ||||
-rw-r--r-- | thirdparty/opus/celt/arm/pitch_arm.h | 68 | ||||
-rw-r--r-- | thirdparty/opus/celt/bands.c | 1529 | ||||
-rw-r--r-- | thirdparty/opus/celt/bands.h | 120 | ||||
-rw-r--r-- | thirdparty/opus/celt/celt.c | 299 | ||||
-rw-r--r-- | thirdparty/opus/celt/celt.h | 229 | ||||
-rw-r--r-- | thirdparty/opus/celt/celt_decoder.c | 1244 | ||||
-rw-r--r-- | thirdparty/opus/celt/celt_encoder.c | 2407 | ||||
-rw-r--r-- | thirdparty/opus/celt/celt_lpc.c | 315 | ||||
-rw-r--r-- | thirdparty/opus/celt/celt_lpc.h | 67 | ||||
-rw-r--r-- | thirdparty/opus/celt/cpu_support.h | 70 | ||||
-rw-r--r-- | thirdparty/opus/celt/cwrs.c | 715 | ||||
-rw-r--r-- | thirdparty/opus/celt/cwrs.h | 48 | ||||
-rw-r--r-- | thirdparty/opus/celt/ecintrin.h | 87 | ||||
-rw-r--r-- | thirdparty/opus/celt/entcode.c | 153 | ||||
-rw-r--r-- | thirdparty/opus/celt/entcode.h | 152 | ||||
-rw-r--r-- | thirdparty/opus/celt/entdec.c | 245 | ||||
-rw-r--r-- | thirdparty/opus/celt/entdec.h | 100 | ||||
-rw-r--r-- | thirdparty/opus/celt/entenc.c | 294 | ||||
-rw-r--r-- | thirdparty/opus/celt/entenc.h | 110 | ||||
-rw-r--r-- | thirdparty/opus/celt/fixed_debug.h | 784 | ||||
-rw-r--r-- | thirdparty/opus/celt/fixed_generic.h | 151 | ||||
-rw-r--r-- | thirdparty/opus/celt/float_cast.h | 140 | ||||
-rw-r--r-- | thirdparty/opus/celt/kiss_fft.c | 604 | ||||
-rw-r--r-- | thirdparty/opus/celt/kiss_fft.h | 200 | ||||
-rw-r--r-- | thirdparty/opus/celt/laplace.c | 134 | ||||
-rw-r--r-- | thirdparty/opus/celt/laplace.h | 48 | ||||
-rw-r--r-- | thirdparty/opus/celt/mathops.c | 208 | ||||
-rw-r--r-- | thirdparty/opus/celt/mathops.h | 258 | ||||
-rw-r--r-- | thirdparty/opus/celt/mdct.c | 343 | ||||
-rw-r--r-- | thirdparty/opus/celt/mdct.h | 112 | ||||
-rw-r--r-- | thirdparty/opus/celt/mfrngcod.h | 48 | ||||
-rw-r--r-- | thirdparty/opus/celt/mips/celt_mipsr1.h | 151 | ||||
-rw-r--r-- | thirdparty/opus/celt/mips/fixed_generic_mipsr1.h (renamed from drivers/opus/celt/mips/fixed_generic_mipsr1.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/celt/mips/kiss_fft_mipsr1.h | 167 | ||||
-rw-r--r-- | thirdparty/opus/celt/mips/mdct_mipsr1.h | 288 | ||||
-rw-r--r-- | thirdparty/opus/celt/mips/pitch_mipsr1.h (renamed from drivers/opus/celt/mips/pitch_mipsr1.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/celt/mips/vq_mipsr1.h | 125 | ||||
-rw-r--r-- | thirdparty/opus/celt/modes.c | 442 | ||||
-rw-r--r-- | thirdparty/opus/celt/modes.h | 75 | ||||
-rw-r--r-- | thirdparty/opus/celt/opus_custom_demo.c | 210 | ||||
-rw-r--r-- | thirdparty/opus/celt/os_support.h | 92 | ||||
-rw-r--r-- | thirdparty/opus/celt/pitch.c | 544 | ||||
-rw-r--r-- | thirdparty/opus/celt/pitch.h | 220 | ||||
-rw-r--r-- | thirdparty/opus/celt/quant_bands.c | 556 | ||||
-rw-r--r-- | thirdparty/opus/celt/quant_bands.h | 66 | ||||
-rw-r--r-- | thirdparty/opus/celt/rate.c | 639 | ||||
-rw-r--r-- | thirdparty/opus/celt/rate.h | 101 | ||||
-rw-r--r-- | thirdparty/opus/celt/stack_alloc.h | 184 | ||||
-rw-r--r-- | thirdparty/opus/celt/static_modes_fixed.h | 892 | ||||
-rw-r--r-- | thirdparty/opus/celt/static_modes_fixed_arm_ne10.h (renamed from drivers/opus/celt/static_modes_fixed_arm_ne10.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/celt/static_modes_float.h | 888 | ||||
-rw-r--r-- | thirdparty/opus/celt/static_modes_float_arm_ne10.h (renamed from drivers/opus/celt/static_modes_float_arm_ne10.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/celt/tests/test_unit_cwrs32.c | 161 | ||||
-rw-r--r-- | thirdparty/opus/celt/tests/test_unit_dft.c | 189 | ||||
-rw-r--r-- | thirdparty/opus/celt/tests/test_unit_entropy.c | 382 | ||||
-rw-r--r-- | thirdparty/opus/celt/tests/test_unit_laplace.c | 93 | ||||
-rw-r--r-- | thirdparty/opus/celt/tests/test_unit_mathops.c | 304 | ||||
-rw-r--r-- | thirdparty/opus/celt/tests/test_unit_mdct.c | 230 | ||||
-rw-r--r-- | thirdparty/opus/celt/tests/test_unit_rotation.c | 120 | ||||
-rw-r--r-- | thirdparty/opus/celt/tests/test_unit_types.c | 50 | ||||
-rw-r--r-- | thirdparty/opus/celt/vq.c | 408 | ||||
-rw-r--r-- | thirdparty/opus/celt/vq.h | 75 | ||||
-rw-r--r-- | thirdparty/opus/celt/x86/celt_lpc_sse.c | 132 | ||||
-rw-r--r-- | thirdparty/opus/celt/x86/celt_lpc_sse.h | 68 | ||||
-rw-r--r-- | thirdparty/opus/celt/x86/pitch_sse.c | 185 | ||||
-rw-r--r-- | thirdparty/opus/celt/x86/pitch_sse.h | 192 | ||||
-rw-r--r-- | thirdparty/opus/celt/x86/pitch_sse2.c | 95 | ||||
-rw-r--r-- | thirdparty/opus/celt/x86/pitch_sse4_1.c | 195 | ||||
-rw-r--r-- | thirdparty/opus/celt/x86/x86_celt_map.c | 155 | ||||
-rw-r--r-- | thirdparty/opus/celt/x86/x86cpu.c | 157 | ||||
-rw-r--r-- | thirdparty/opus/celt/x86/x86cpu.h (renamed from drivers/opus/celt/x86/x86cpu.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/config.h (renamed from drivers/opus/opus_config.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/http.c | 3429 | ||||
-rw-r--r-- | thirdparty/opus/info.c | 753 | ||||
-rw-r--r-- | thirdparty/opus/internal.c | 42 | ||||
-rw-r--r-- | thirdparty/opus/internal.h | 254 | ||||
-rw-r--r-- | thirdparty/opus/mlp.c | 145 | ||||
-rw-r--r-- | thirdparty/opus/mlp.h | 43 | ||||
-rw-r--r-- | thirdparty/opus/mlp_data.c | 109 | ||||
-rw-r--r-- | thirdparty/opus/opus.c | 350 | ||||
-rw-r--r-- | thirdparty/opus/opus.h | 981 | ||||
-rw-r--r-- | thirdparty/opus/opus_compare.c (renamed from drivers/opus/opus_compare.c) | 0 | ||||
-rw-r--r-- | thirdparty/opus/opus_custom.h | 342 | ||||
-rw-r--r-- | thirdparty/opus/opus_decoder.c | 981 | ||||
-rw-r--r-- | thirdparty/opus/opus_defines.h | 753 | ||||
-rw-r--r-- | thirdparty/opus/opus_encoder.c | 2527 | ||||
-rw-r--r-- | thirdparty/opus/opus_multistream.c | 92 | ||||
-rw-r--r-- | thirdparty/opus/opus_multistream.h | 660 | ||||
-rw-r--r-- | thirdparty/opus/opus_multistream_decoder.c | 537 | ||||
-rw-r--r-- | thirdparty/opus/opus_multistream_encoder.c | 1220 | ||||
-rw-r--r-- | thirdparty/opus/opus_private.h | 134 | ||||
-rw-r--r-- | thirdparty/opus/opus_types.h (renamed from drivers/opus/opus_types.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/opusfile.c | 3277 | ||||
-rw-r--r-- | thirdparty/opus/opusfile.h | 2148 | ||||
-rw-r--r-- | thirdparty/opus/repacketizer.c | 346 | ||||
-rw-r--r-- | thirdparty/opus/repacketizer_demo.c | 217 | ||||
-rw-r--r-- | thirdparty/opus/silk/A2NLSF.c | 267 | ||||
-rw-r--r-- | thirdparty/opus/silk/API.h | 134 | ||||
-rw-r--r-- | thirdparty/opus/silk/CNG.c | 181 | ||||
-rw-r--r-- | thirdparty/opus/silk/HP_variable_cutoff.c | 77 | ||||
-rw-r--r-- | thirdparty/opus/silk/Inlines.h (renamed from drivers/opus/silk/Inlines.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/silk/LPC_analysis_filter.c | 108 | ||||
-rw-r--r-- | thirdparty/opus/silk/LPC_inv_pred_gain.c | 154 | ||||
-rw-r--r-- | thirdparty/opus/silk/LP_variable_cutoff.c | 135 | ||||
-rw-r--r-- | thirdparty/opus/silk/MacroCount.h (renamed from drivers/opus/silk/MacroCount.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/silk/MacroDebug.h (renamed from drivers/opus/silk/MacroDebug.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/silk/NLSF2A.c | 178 | ||||
-rw-r--r-- | thirdparty/opus/silk/NLSF_VQ.c | 68 | ||||
-rw-r--r-- | thirdparty/opus/silk/NLSF_VQ_weights_laroia.c | 80 | ||||
-rw-r--r-- | thirdparty/opus/silk/NLSF_decode.c | 101 | ||||
-rw-r--r-- | thirdparty/opus/silk/NLSF_del_dec_quant.c | 217 | ||||
-rw-r--r-- | thirdparty/opus/silk/NLSF_encode.c | 136 | ||||
-rw-r--r-- | thirdparty/opus/silk/NLSF_stabilize.c | 142 | ||||
-rw-r--r-- | thirdparty/opus/silk/NLSF_unpack.c | 55 | ||||
-rw-r--r-- | thirdparty/opus/silk/NSQ.c | 453 | ||||
-rw-r--r-- | thirdparty/opus/silk/NSQ.h | 101 | ||||
-rw-r--r-- | thirdparty/opus/silk/NSQ_del_dec.c | 724 | ||||
-rw-r--r-- | thirdparty/opus/silk/PLC.c | 445 | ||||
-rw-r--r-- | thirdparty/opus/silk/PLC.h | 62 | ||||
-rw-r--r-- | thirdparty/opus/silk/SigProc_FIX.h | 615 | ||||
-rw-r--r-- | thirdparty/opus/silk/VAD.c | 362 | ||||
-rw-r--r-- | thirdparty/opus/silk/VQ_WMat_EC.c | 120 | ||||
-rw-r--r-- | thirdparty/opus/silk/ana_filt_bank_1.c | 74 | ||||
-rw-r--r-- | thirdparty/opus/silk/arm/NSQ_neon.c | 112 | ||||
-rw-r--r-- | thirdparty/opus/silk/arm/NSQ_neon.h | 113 | ||||
-rw-r--r-- | thirdparty/opus/silk/arm/SigProc_FIX_armv4.h (renamed from drivers/opus/silk/arm/SigProc_FIX_armv4.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/silk/arm/SigProc_FIX_armv5e.h (renamed from drivers/opus/silk/arm/SigProc_FIX_armv5e.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/silk/arm/arm_silk_map.c | 55 | ||||
-rw-r--r-- | thirdparty/opus/silk/arm/macros_arm64.h | 39 | ||||
-rw-r--r-- | thirdparty/opus/silk/arm/macros_armv4.h (renamed from drivers/opus/silk/arm/macros_armv4.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/silk/arm/macros_armv5e.h (renamed from drivers/opus/silk/arm/macros_armv5e.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/silk/biquad_alt.c | 78 | ||||
-rw-r--r-- | thirdparty/opus/silk/bwexpander.c | 51 | ||||
-rw-r--r-- | thirdparty/opus/silk/bwexpander_32.c | 50 | ||||
-rw-r--r-- | thirdparty/opus/silk/check_control_input.c | 106 | ||||
-rw-r--r-- | thirdparty/opus/silk/code_signs.c | 115 | ||||
-rw-r--r-- | thirdparty/opus/silk/control.h | 142 | ||||
-rw-r--r-- | thirdparty/opus/silk/control_SNR.c | 76 | ||||
-rw-r--r-- | thirdparty/opus/silk/control_audio_bandwidth.c | 126 | ||||
-rw-r--r-- | thirdparty/opus/silk/control_codec.c | 428 | ||||
-rw-r--r-- | thirdparty/opus/silk/debug.c | 170 | ||||
-rw-r--r-- | thirdparty/opus/silk/debug.h | 279 | ||||
-rw-r--r-- | thirdparty/opus/silk/dec_API.c | 419 | ||||
-rw-r--r-- | thirdparty/opus/silk/decode_core.c | 239 | ||||
-rw-r--r-- | thirdparty/opus/silk/decode_frame.c | 129 | ||||
-rw-r--r-- | thirdparty/opus/silk/decode_indices.c | 151 | ||||
-rw-r--r-- | thirdparty/opus/silk/decode_parameters.c | 115 | ||||
-rw-r--r-- | thirdparty/opus/silk/decode_pitch.c | 77 | ||||
-rw-r--r-- | thirdparty/opus/silk/decode_pulses.c | 115 | ||||
-rw-r--r-- | thirdparty/opus/silk/decoder_set_fs.c | 108 | ||||
-rw-r--r-- | thirdparty/opus/silk/define.h | 235 | ||||
-rw-r--r-- | thirdparty/opus/silk/enc_API.c | 563 | ||||
-rw-r--r-- | thirdparty/opus/silk/encode_indices.c | 181 | ||||
-rw-r--r-- | thirdparty/opus/silk/encode_pulses.c | 206 | ||||
-rw-r--r-- | thirdparty/opus/silk/errors.h (renamed from drivers/opus/silk/errors.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/LTP_analysis_filter_FIX.c | 90 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/LTP_scale_ctrl_FIX.c | 53 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/apply_sine_window_FIX.c | 101 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/autocorr_FIX.c | 48 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/burg_modified_FIX.c | 275 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/corrMatrix_FIX.c | 158 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/encode_frame_FIX.c | 387 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/find_LPC_FIX.c | 151 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/find_LTP_FIX.c | 245 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/find_pitch_lags_FIX.c | 145 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/find_pred_coefs_FIX.c | 148 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/k2a_FIX.c | 53 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/k2a_Q16_FIX.c | 53 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/main_FIX.h | 272 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h (renamed from drivers/opus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/mips/prefilter_FIX_mipsr1.h | 184 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h | 165 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/noise_shape_analysis_FIX.c | 451 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/pitch_analysis_core_FIX.c | 746 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/prefilter_FIX.c | 221 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/process_gains_FIX.c | 117 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/regularize_correlations_FIX.c | 47 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/residual_energy16_FIX.c | 103 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/residual_energy_FIX.c | 98 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/schur64_FIX.c | 92 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/schur_FIX.c | 106 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/solve_LS_FIX.c | 249 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/structs_FIX.h | 134 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/vector_ops_FIX.c | 102 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/warped_autocorrelation_FIX.c | 95 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/x86/burg_modified_FIX_sse.c | 375 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/x86/prefilter_FIX_sse.c | 160 | ||||
-rw-r--r-- | thirdparty/opus/silk/fixed/x86/vector_ops_FIX_sse.c | 88 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/LPC_analysis_filter_FLP.c | 249 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/LPC_inv_pred_gain_FLP.c | 76 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/LTP_analysis_filter_FLP.c | 75 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/LTP_scale_ctrl_FLP.c | 52 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/SigProc_FLP.h | 204 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/apply_sine_window_FLP.c | 81 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/autocorrelation_FLP.c | 52 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/burg_modified_FLP.c | 186 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/bwexpander_FLP.c | 49 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/corrMatrix_FLP.c | 93 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/encode_frame_FLP.c | 372 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/energy_FLP.c | 60 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/find_LPC_FLP.c | 104 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/find_LTP_FLP.c | 132 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/find_pitch_lags_FLP.c | 132 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/find_pred_coefs_FLP.c | 118 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/inner_product_FLP.c | 60 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/k2a_FLP.c | 53 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/levinsondurbin_FLP.c | 81 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/main_FLP.h | 313 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/noise_shape_analysis_FLP.c | 365 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/pitch_analysis_core_FLP.c | 630 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/prefilter_FLP.c | 206 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/process_gains_FLP.c | 103 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/regularize_correlations_FLP.c | 48 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/residual_energy_FLP.c | 117 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/scale_copy_vector_FLP.c | 57 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/scale_vector_FLP.c | 56 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/schur_FLP.c | 70 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/solve_LS_FLP.c | 207 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/sort_FLP.c | 83 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/structs_FLP.h | 132 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/warped_autocorrelation_FLP.c | 73 | ||||
-rw-r--r-- | thirdparty/opus/silk/float/wrappers_FLP.c | 202 | ||||
-rw-r--r-- | thirdparty/opus/silk/gain_quant.c | 141 | ||||
-rw-r--r-- | thirdparty/opus/silk/init_decoder.c | 56 | ||||
-rw-r--r-- | thirdparty/opus/silk/init_encoder.c | 64 | ||||
-rw-r--r-- | thirdparty/opus/silk/inner_prod_aligned.c | 47 | ||||
-rw-r--r-- | thirdparty/opus/silk/interpolate.c | 51 | ||||
-rw-r--r-- | thirdparty/opus/silk/lin2log.c | 46 | ||||
-rw-r--r-- | thirdparty/opus/silk/log2lin.c | 58 | ||||
-rw-r--r-- | thirdparty/opus/silk/macros.h | 153 | ||||
-rw-r--r-- | thirdparty/opus/silk/main.h | 471 | ||||
-rw-r--r-- | thirdparty/opus/silk/mips/NSQ_del_dec_mipsr1.h | 405 | ||||
-rw-r--r-- | thirdparty/opus/silk/mips/macros_mipsr1.h (renamed from drivers/opus/silk/mips/macros_mipsr1.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/silk/mips/sigproc_fix_mipsr1.h (renamed from drivers/opus/silk/mips/sigproc_fix_mipsr1.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/silk/pitch_est_defines.h | 88 | ||||
-rw-r--r-- | thirdparty/opus/silk/pitch_est_tables.c | 99 | ||||
-rw-r--r-- | thirdparty/opus/silk/process_NLSFs.c | 105 | ||||
-rw-r--r-- | thirdparty/opus/silk/quant_LTP_gains.c | 129 | ||||
-rw-r--r-- | thirdparty/opus/silk/resampler.c | 215 | ||||
-rw-r--r-- | thirdparty/opus/silk/resampler_down2.c | 74 | ||||
-rw-r--r-- | thirdparty/opus/silk/resampler_down2_3.c | 103 | ||||
-rw-r--r-- | thirdparty/opus/silk/resampler_private.h | 88 | ||||
-rw-r--r-- | thirdparty/opus/silk/resampler_private_AR2.c | 55 | ||||
-rw-r--r-- | thirdparty/opus/silk/resampler_private_IIR_FIR.c | 107 | ||||
-rw-r--r-- | thirdparty/opus/silk/resampler_private_down_FIR.c | 194 | ||||
-rw-r--r-- | thirdparty/opus/silk/resampler_private_up2_HQ.c | 113 | ||||
-rw-r--r-- | thirdparty/opus/silk/resampler_rom.c | 96 | ||||
-rw-r--r-- | thirdparty/opus/silk/resampler_rom.h | 68 | ||||
-rw-r--r-- | thirdparty/opus/silk/resampler_structs.h (renamed from drivers/opus/silk/resampler_structs.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/silk/shell_coder.c | 151 | ||||
-rw-r--r-- | thirdparty/opus/silk/sigm_Q15.c | 76 | ||||
-rw-r--r-- | thirdparty/opus/silk/sort.c | 154 | ||||
-rw-r--r-- | thirdparty/opus/silk/stereo_LR_to_MS.c | 229 | ||||
-rw-r--r-- | thirdparty/opus/silk/stereo_MS_to_LR.c | 85 | ||||
-rw-r--r-- | thirdparty/opus/silk/stereo_decode_pred.c | 73 | ||||
-rw-r--r-- | thirdparty/opus/silk/stereo_encode_pred.c | 62 | ||||
-rw-r--r-- | thirdparty/opus/silk/stereo_find_predictor.c | 79 | ||||
-rw-r--r-- | thirdparty/opus/silk/stereo_quant_pred.c | 73 | ||||
-rw-r--r-- | thirdparty/opus/silk/structs.h | 327 | ||||
-rw-r--r-- | thirdparty/opus/silk/sum_sqr_shift.c | 86 | ||||
-rw-r--r-- | thirdparty/opus/silk/table_LSF_cos.c | 70 | ||||
-rw-r--r-- | thirdparty/opus/silk/tables.h | 122 | ||||
-rw-r--r-- | thirdparty/opus/silk/tables_LTP.c | 296 | ||||
-rw-r--r-- | thirdparty/opus/silk/tables_NLSF_CB_NB_MB.c | 159 | ||||
-rw-r--r-- | thirdparty/opus/silk/tables_NLSF_CB_WB.c | 198 | ||||
-rw-r--r-- | thirdparty/opus/silk/tables_gain.c | 63 | ||||
-rw-r--r-- | thirdparty/opus/silk/tables_other.c | 138 | ||||
-rw-r--r-- | thirdparty/opus/silk/tables_pitch_lag.c | 69 | ||||
-rw-r--r-- | thirdparty/opus/silk/tables_pulses_per_block.c | 264 | ||||
-rw-r--r-- | thirdparty/opus/silk/tuning_parameters.h (renamed from drivers/opus/silk/tuning_parameters.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/silk/typedef.h | 78 | ||||
-rw-r--r-- | thirdparty/opus/silk/x86/NSQ_del_dec_sse.c | 857 | ||||
-rw-r--r-- | thirdparty/opus/silk/x86/NSQ_sse.c | 720 | ||||
-rw-r--r-- | thirdparty/opus/silk/x86/SigProc_FIX_sse.h | 94 | ||||
-rw-r--r-- | thirdparty/opus/silk/x86/VAD_sse.c | 277 | ||||
-rw-r--r-- | thirdparty/opus/silk/x86/VQ_WMat_EC_sse.c | 142 | ||||
-rw-r--r-- | thirdparty/opus/silk/x86/main_sse.h | 276 | ||||
-rw-r--r-- | thirdparty/opus/silk/x86/x86_silk_map.c | 174 | ||||
-rw-r--r-- | thirdparty/opus/stream.c | 366 | ||||
-rw-r--r-- | thirdparty/opus/tansig_table.h (renamed from drivers/opus/tansig_table.h) | 0 | ||||
-rw-r--r-- | thirdparty/opus/wincerts.c | 171 | ||||
-rw-r--r-- | thirdparty/opus/winerrno.h (renamed from drivers/opus/winerrno.h) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/AlphaBitmap.h (renamed from drivers/pvr/AlphaBitmap.h) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/BitScale.cpp (renamed from drivers/pvr/BitScale.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/BitScale.h (renamed from drivers/pvr/BitScale.h) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/BitUtility.h (renamed from drivers/pvr/BitUtility.h) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/Bitmap.h (renamed from drivers/pvr/Bitmap.h) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/ColorRgba.h (renamed from drivers/pvr/ColorRgba.h) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/Interval.h (renamed from drivers/pvr/Interval.h) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/LICENSE.TXT | 25 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/MortonTable.cpp (renamed from drivers/pvr/MortonTable.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/MortonTable.h (renamed from drivers/pvr/MortonTable.h) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/Point2.h (renamed from drivers/pvr/Point2.h) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/PvrTcDecoder.cpp (renamed from drivers/pvr/PvrTcDecoder.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/PvrTcDecoder.h (renamed from drivers/pvr/PvrTcDecoder.h) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/PvrTcEncoder.cpp (renamed from drivers/pvr/PvrTcEncoder.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/PvrTcEncoder.h (renamed from drivers/pvr/PvrTcEncoder.h) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/PvrTcPacket.cpp (renamed from drivers/pvr/PvrTcPacket.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/PvrTcPacket.h (renamed from drivers/pvr/PvrTcPacket.h) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/RgbBitmap.h (renamed from drivers/pvr/RgbBitmap.h) | 0 | ||||
-rw-r--r-- | thirdparty/pvrtccompressor/RgbaBitmap.h (renamed from drivers/pvr/RgbaBitmap.h) | 0 | ||||
-rw-r--r-- | thirdparty/rg-etc1/rg_etc1.cpp (renamed from drivers/etc1/rg_etc1.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/rg-etc1/rg_etc1.h (renamed from drivers/etc1/rg_etc1.h) | 0 | ||||
-rw-r--r-- | thirdparty/rtaudio/RtAudio.cpp (renamed from drivers/rtaudio/RtAudio.cpp) | 0 | ||||
-rw-r--r-- | thirdparty/rtaudio/RtAudio.h (renamed from drivers/rtaudio/RtAudio.h) | 0 | ||||
-rw-r--r-- | thirdparty/squish/alpha.cpp | 350 | ||||
-rw-r--r-- | thirdparty/squish/alpha.h | 41 | ||||
-rw-r--r-- | thirdparty/squish/clusterfit.cpp | 392 | ||||
-rw-r--r-- | thirdparty/squish/clusterfit.h | 61 | ||||
-rw-r--r-- | thirdparty/squish/colourblock.cpp | 214 | ||||
-rw-r--r-- | thirdparty/squish/colourblock.h | 41 | ||||
-rw-r--r-- | thirdparty/squish/colourfit.cpp | 54 | ||||
-rw-r--r-- | thirdparty/squish/colourfit.h | 56 | ||||
-rw-r--r-- | thirdparty/squish/colourset.cpp | 121 | ||||
-rw-r--r-- | thirdparty/squish/colourset.h | 58 | ||||
-rw-r--r-- | thirdparty/squish/config.h | 49 | ||||
-rw-r--r-- | thirdparty/squish/maths.cpp | 259 | ||||
-rw-r--r-- | thirdparty/squish/maths.h | 233 | ||||
-rw-r--r-- | thirdparty/squish/rangefit.cpp | 201 | ||||
-rw-r--r-- | thirdparty/squish/rangefit.h | 54 | ||||
-rw-r--r-- | thirdparty/squish/simd.h | 40 | ||||
-rw-r--r-- | thirdparty/squish/simd_float.h | 183 | ||||
-rw-r--r-- | thirdparty/squish/simd_sse.h | 180 | ||||
-rw-r--r-- | thirdparty/squish/simd_ve.h | 166 | ||||
-rw-r--r-- | thirdparty/squish/singlecolourfit.cpp | 172 | ||||
-rw-r--r-- | thirdparty/squish/singlecolourfit.h | 58 | ||||
-rw-r--r-- | thirdparty/squish/singlecolourlookup.inl | 1064 | ||||
-rw-r--r-- | thirdparty/squish/squish.cpp | 395 | ||||
-rw-r--r-- | thirdparty/squish/squish.h | 300 | ||||
-rw-r--r-- | thirdparty/zlib/adler32.c (renamed from drivers/builtin_zlib/zlib/adler32.c) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/compress.c (renamed from drivers/builtin_zlib/zlib/compress.c) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/crc32.c (renamed from drivers/builtin_zlib/zlib/crc32.c) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/crc32.h (renamed from drivers/builtin_zlib/zlib/crc32.h) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/deflate.c (renamed from drivers/builtin_zlib/zlib/deflate.c) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/deflate.h (renamed from drivers/builtin_zlib/zlib/deflate.h) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/infback.c (renamed from drivers/builtin_zlib/zlib/infback.c) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/inffast.c (renamed from drivers/builtin_zlib/zlib/inffast.c) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/inffast.h (renamed from drivers/builtin_zlib/zlib/inffast.h) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/inffixed.h (renamed from drivers/builtin_zlib/zlib/inffixed.h) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/inflate.c (renamed from drivers/builtin_zlib/zlib/inflate.c) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/inflate.h (renamed from drivers/builtin_zlib/zlib/inflate.h) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/inftrees.c (renamed from drivers/builtin_zlib/zlib/inftrees.c) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/inftrees.h (renamed from drivers/builtin_zlib/zlib/inftrees.h) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/trees.c (renamed from drivers/builtin_zlib/zlib/trees.c) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/trees.h (renamed from drivers/builtin_zlib/zlib/trees.h) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/uncompr.c (renamed from drivers/builtin_zlib/zlib/uncompr.c) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/zconf.h (renamed from drivers/builtin_zlib/zlib/zconf.h) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/zlib.h (renamed from drivers/builtin_zlib/zlib/zlib.h) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/zutil.c (renamed from drivers/builtin_zlib/zlib/zutil.c) | 0 | ||||
-rw-r--r-- | thirdparty/zlib/zutil.h (renamed from drivers/builtin_zlib/zlib/zutil.h) | 0 | ||||
-rw-r--r-- | tools/SCsub | 6 | ||||
-rw-r--r-- | tools/addheader/files | 158 | ||||
-rw-r--r-- | tools/addheader/header.txt | 12 | ||||
-rw-r--r-- | tools/buildstuff/zlib_freetype231_jpeg_libpng-bin-win32-vs81.zip | bin | 3557519 -> 0 bytes | |||
-rw-r--r-- | tools/collada/SCsub | 2 | ||||
-rw-r--r-- | tools/dist/docker/Dockerfile (renamed from tools/docker/Dockerfile) | 0 | ||||
-rw-r--r-- | tools/dist/docker/README.md (renamed from tools/docker/README.md) | 0 | ||||
-rw-r--r-- | tools/dist/docker/scripts/install-android-tools (renamed from tools/docker/scripts/install-android-tools) | 0 | ||||
-rw-r--r-- | tools/dist/html_fs/godot.html (renamed from tools/html_fs/godot.html) | 0 | ||||
-rw-r--r-- | tools/dist/html_fs/godotfs.js (renamed from tools/html_fs/godotfs.js) | 0 | ||||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/data.pck (renamed from platform/iphone/xcode/godot_xcode/data.pck) | 0 | ||||
-rwxr-xr-x | tools/dist/ios_xcode/godot_xcode/godot_debug.iphone (renamed from platform/iphone/xcode/godot_xcode/godot_debug.iphone) | 0 | ||||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios.xcodeproj/project.pbxproj (renamed from platform/iphone/xcode/godot_xcode/godot_ios.xcodeproj/project.pbxproj) | 0 | ||||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata (renamed from platform/iphone/xcode/godot_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata) | 0 | ||||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Default-568h@2x~iphone.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Default-568h@2x~iphone.png) | bin | 564 -> 564 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Default-667h.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Default-667h.png) | bin | 683 -> 683 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Default-667h@2x.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Default-667h@2x.png) | bin | 817 -> 817 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Default-736h.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Default-736h.png) | bin | 1676 -> 1676 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Default-736h@3x.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Default-736h@3x.png) | bin | 2582 -> 2582 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Landscape-736h.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape-736h.png) | bin | 2582 -> 2582 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Landscape@2x~ipad.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape@2x~ipad.png) | bin | 3131 -> 3131 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Landscape~ipad.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape~ipad.png) | bin | 634 -> 634 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Portrait@2x~ipad.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Default-Portrait@2x~ipad.png) | bin | 3070 -> 3070 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Portrait~ipad.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Default-Portrait~ipad.png) | bin | 589 -> 589 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Default@2x~iphone.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Default@2x~iphone.png) | bin | 515 -> 515 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Default~iphone.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Default~iphone.png) | bin | 309 -> 309 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Contents.json (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Contents.json) | 0 | ||||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-100.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-100.png) | bin | 250 -> 250 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-114.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-114.png) | bin | 253 -> 253 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-120.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-120.png) | bin | 253 -> 253 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-144.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-144.png) | bin | 259 -> 259 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-152.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-152.png) | bin | 260 -> 260 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-180.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-180.png) | bin | 265 -> 265 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-29.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-29.png) | bin | 242 -> 242 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-40.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-40.png) | bin | 240 -> 240 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-50.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-50.png) | bin | 243 -> 243 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-57.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-57.png) | bin | 243 -> 243 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-58.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-58.png) | bin | 243 -> 243 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-60.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-60.png) | bin | 244 -> 244 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-72.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-72.png) | bin | 244 -> 244 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-76.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-76.png) | bin | 246 -> 246 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-80.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-80.png) | bin | 245 -> 245 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-167.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-167.png) | bin | 262 -> 262 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-87.png (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-87.png) | bin | 247 -> 247 bytes | |||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/sizes (renamed from platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/sizes) | 0 | ||||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/en.lproj/InfoPlist.strings (renamed from platform/iphone/xcode/godot_xcode/godot_ios/en.lproj/InfoPlist.strings) | 0 | ||||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/godot_ios-Info.plist (renamed from platform/iphone/xcode/godot_xcode/godot_ios/godot_ios-Info.plist) | 0 | ||||
-rw-r--r-- | tools/dist/ios_xcode/godot_xcode/godot_ios/main.m (renamed from platform/iphone/xcode/godot_xcode/godot_ios/main.m) | 0 | ||||
-rwxr-xr-x | tools/dist/ios_xcode/godot_xcode/godot_opt.iphone (renamed from platform/iphone/xcode/godot_xcode/godot_opt.iphone) | 0 | ||||
-rwxr-xr-x | tools/dist/osx_template.app/Contents/Info.plist (renamed from tools/osx_template.app/Contents/Info.plist) | 0 | ||||
-rw-r--r-- | tools/dist/osx_template.app/Contents/PkgInfo (renamed from tools/Godot.app/Contents/PkgInfo) | 0 | ||||
-rw-r--r-- | tools/dist/osx_template.app/Contents/Resources/icon.icns (renamed from tools/osx_template.app/Contents/Resources/icon.icns) | bin | 120942 -> 120942 bytes | |||
-rwxr-xr-x | tools/dist/osx_tools.app/Contents/Info.plist (renamed from tools/Godot.app/Contents/Info.plist) | 0 | ||||
-rw-r--r-- | tools/dist/osx_tools.app/Contents/PkgInfo (renamed from tools/osx_template.app/Contents/PkgInfo) | 0 | ||||
-rw-r--r-- | tools/dist/osx_tools.app/Contents/Resources/Godot.icns (renamed from tools/Godot.app/Contents/Resources/Godot.icns) | bin | 120942 -> 120942 bytes | |||
-rw-r--r-- | tools/dist/uwp_template/AppxManifest.xml | 32 | ||||
-rw-r--r-- | tools/dist/uwp_template/Assets/SplashScreen.scale-100.png | bin | 0 -> 14919 bytes | |||
-rw-r--r-- | tools/dist/uwp_template/Assets/Square150x150Logo.scale-100.png | bin | 0 -> 7001 bytes | |||
-rw-r--r-- | tools/dist/uwp_template/Assets/Square310x310Logo.scale-100.png | bin | 0 -> 14490 bytes | |||
-rw-r--r-- | tools/dist/uwp_template/Assets/Square44x44Logo.scale-100.png | bin | 0 -> 2067 bytes | |||
-rw-r--r-- | tools/dist/uwp_template/Assets/Square71x71Logo.scale-100.png | bin | 0 -> 3369 bytes | |||
-rw-r--r-- | tools/dist/uwp_template/Assets/StoreLogo.scale-100.png | bin | 0 -> 2339 bytes | |||
-rw-r--r-- | tools/dist/uwp_template/Assets/Wide310x150Logo.scale-100.png | bin | 0 -> 7390 bytes | |||
-rw-r--r-- | tools/doc/SCsub | 2 | ||||
-rw-r--r-- | tools/doc/doc_data.cpp | 5 | ||||
-rw-r--r-- | tools/doc/doc_dump.cpp (renamed from tools/docdump/doc_dump.cpp) | 0 | ||||
-rw-r--r-- | tools/doc/doc_dump.h (renamed from tools/docdump/doc_dump.h) | 0 | ||||
-rw-r--r-- | tools/docdump/SCsub | 5 | ||||
-rw-r--r-- | tools/editor/SCsub | 2 | ||||
-rw-r--r-- | tools/editor/animation_editor.cpp | 12 | ||||
-rw-r--r-- | tools/editor/code_editor.cpp | 54 | ||||
-rw-r--r-- | tools/editor/code_editor.h | 6 | ||||
-rw-r--r-- | tools/editor/connections_dialog.cpp | 8 | ||||
-rw-r--r-- | tools/editor/create_dialog.cpp | 324 | ||||
-rw-r--r-- | tools/editor/create_dialog.h | 19 | ||||
-rw-r--r-- | tools/editor/editor_data.cpp | 16 | ||||
-rw-r--r-- | tools/editor/editor_data.h | 2 | ||||
-rw-r--r-- | tools/editor/editor_dir_dialog.cpp | 14 | ||||
-rw-r--r-- | tools/editor/editor_file_system.cpp | 18 | ||||
-rw-r--r-- | tools/editor/editor_fonts.cpp | 15 | ||||
-rw-r--r-- | tools/editor/editor_help.cpp | 9 | ||||
-rw-r--r-- | tools/editor/editor_import_export.cpp | 2 | ||||
-rw-r--r-- | tools/editor/editor_log.cpp | 12 | ||||
-rw-r--r-- | tools/editor/editor_log.h | 2 | ||||
-rw-r--r-- | tools/editor/editor_node.cpp | 204 | ||||
-rw-r--r-- | tools/editor/editor_node.h | 20 | ||||
-rw-r--r-- | tools/editor/editor_plugin.cpp | 58 | ||||
-rw-r--r-- | tools/editor/editor_plugin.h | 18 | ||||
-rw-r--r-- | tools/editor/editor_resource_preview.cpp | 42 | ||||
-rw-r--r-- | tools/editor/editor_resource_preview.h | 8 | ||||
-rw-r--r-- | tools/editor/editor_run.cpp | 4 | ||||
-rw-r--r-- | tools/editor/editor_run.h | 2 | ||||
-rw-r--r-- | tools/editor/editor_scale.cpp | 11 | ||||
-rw-r--r-- | tools/editor/editor_scale.h | 6 | ||||
-rw-r--r-- | tools/editor/editor_settings.cpp | 41 | ||||
-rw-r--r-- | tools/editor/editor_settings.h | 3 | ||||
-rw-r--r-- | tools/editor/editor_themes.cpp | 23 | ||||
-rw-r--r-- | tools/editor/editor_themes.h | 4 | ||||
-rw-r--r-- | tools/editor/fileserver/SCsub | 2 | ||||
-rw-r--r-- | tools/editor/filesystem_dock.cpp | 7 | ||||
-rw-r--r-- | tools/editor/icons/2x/icon_distraction_free.png | bin | 0 -> 575 bytes | |||
-rw-r--r-- | tools/editor/icons/2x/icon_load.png | bin | 228 -> 503 bytes | |||
-rw-r--r-- | tools/editor/icons/2x/icon_mini_aabb.png | bin | 697 -> 695 bytes | |||
-rw-r--r-- | tools/editor/icons/2x/icon_mini_transform.png | bin | 431 -> 539 bytes | |||
-rw-r--r-- | tools/editor/icons/2x/icon_open.png | bin | 228 -> 0 bytes | |||
-rw-r--r-- | tools/editor/icons/2x/icon_remote_transform.png | bin | 0 -> 1140 bytes | |||
-rw-r--r-- | tools/editor/icons/SCsub | 8 | ||||
-rw-r--r-- | tools/editor/icons/icon_color_frame.png | bin | 0 -> 360 bytes | |||
-rw-r--r-- | tools/editor/icons/icon_distraction_free.png | bin | 0 -> 397 bytes | |||
-rw-r--r-- | tools/editor/icons/icon_load.png | bin | 170 -> 301 bytes | |||
-rw-r--r-- | tools/editor/icons/icon_mini_aabb.png | bin | 367 -> 360 bytes | |||
-rw-r--r-- | tools/editor/icons/icon_mini_transform.png | bin | 264 -> 321 bytes | |||
-rw-r--r-- | tools/editor/icons/icon_open.png | bin | 170 -> 0 bytes | |||
-rw-r--r-- | tools/editor/icons/icon_remote_transform.png | bin | 0 -> 530 bytes | |||
-rw-r--r-- | tools/editor/icons/source/icon_distraction_free.svg | 104 | ||||
-rw-r--r-- | tools/editor/icons/source/icon_load.svg | 85 | ||||
-rw-r--r-- | tools/editor/icons/source/icon_mini_aabb.svg | 8 | ||||
-rw-r--r-- | tools/editor/icons/source/icon_mini_transform.svg | 34 | ||||
-rw-r--r-- | tools/editor/icons/source/icon_remote_transform.svg | 124 | ||||
-rw-r--r-- | tools/editor/io_plugins/SCsub | 2 | ||||
-rw-r--r-- | tools/editor/io_plugins/editor_bitmask_import_plugin.cpp | 2 | ||||
-rw-r--r-- | tools/editor/io_plugins/editor_sample_import_plugin.cpp | 2 | ||||
-rw-r--r-- | tools/editor/io_plugins/editor_scene_import_plugin.cpp | 27 | ||||
-rw-r--r-- | tools/editor/io_plugins/editor_texture_import_plugin.cpp | 53 | ||||
-rw-r--r-- | tools/editor/io_plugins/editor_texture_import_plugin.h | 2 | ||||
-rw-r--r-- | tools/editor/multi_node_edit.cpp | 9 | ||||
-rw-r--r-- | tools/editor/plugins/SCsub | 2 | ||||
-rw-r--r-- | tools/editor/plugins/animation_player_editor_plugin.cpp | 2 | ||||
-rw-r--r-- | tools/editor/plugins/baked_light_baker.cpp | 4 | ||||
-rw-r--r-- | tools/editor/plugins/canvas_item_editor_plugin.cpp | 155 | ||||
-rw-r--r-- | tools/editor/plugins/canvas_item_editor_plugin.h | 3 | ||||
-rw-r--r-- | tools/editor/plugins/collision_polygon_2d_editor_plugin.h | 2 | ||||
-rw-r--r-- | tools/editor/plugins/collision_shape_2d_editor_plugin.h | 2 | ||||
-rw-r--r-- | tools/editor/plugins/light_occluder_2d_editor_plugin.h | 2 | ||||
-rw-r--r-- | tools/editor/plugins/navigation_polygon_editor_plugin.h | 2 | ||||
-rw-r--r-- | tools/editor/plugins/path_2d_editor_plugin.h | 2 | ||||
-rw-r--r-- | tools/editor/plugins/polygon_2d_editor_plugin.h | 2 | ||||
-rw-r--r-- | tools/editor/plugins/script_editor_plugin.cpp | 149 | ||||
-rw-r--r-- | tools/editor/plugins/script_editor_plugin.h | 8 | ||||
-rw-r--r-- | tools/editor/plugins/script_text_editor.cpp | 355 | ||||
-rw-r--r-- | tools/editor/plugins/script_text_editor.h | 17 | ||||
-rw-r--r-- | tools/editor/plugins/shader_editor_plugin.cpp | 40 | ||||
-rw-r--r-- | tools/editor/plugins/shader_graph_editor_plugin.cpp | 11 | ||||
-rw-r--r-- | tools/editor/plugins/spatial_editor_plugin.cpp | 20 | ||||
-rw-r--r-- | tools/editor/plugins/spatial_editor_plugin.h | 1 | ||||
-rw-r--r-- | tools/editor/plugins/texture_region_editor_plugin.cpp | 7 | ||||
-rw-r--r-- | tools/editor/plugins/texture_region_editor_plugin.h | 2 | ||||
-rw-r--r-- | tools/editor/plugins/theme_editor_plugin.cpp | 2 | ||||
-rw-r--r-- | tools/editor/plugins/tile_map_editor_plugin.cpp | 47 | ||||
-rw-r--r-- | tools/editor/plugins/tile_map_editor_plugin.h | 4 | ||||
-rw-r--r-- | tools/editor/project_manager.cpp | 32 | ||||
-rw-r--r-- | tools/editor/property_editor.cpp | 48 | ||||
-rw-r--r-- | tools/editor/property_editor.h | 1 | ||||
-rw-r--r-- | tools/editor/scene_tree_dock.cpp | 92 | ||||
-rw-r--r-- | tools/editor/scene_tree_dock.h | 2 | ||||
-rw-r--r-- | tools/editor/scene_tree_editor.cpp | 2 | ||||
-rw-r--r-- | tools/editor/script_create_dialog.cpp | 14 | ||||
-rw-r--r-- | tools/editor/script_create_dialog.h | 2 | ||||
-rw-r--r-- | tools/editor/script_editor_debugger.cpp | 5 | ||||
-rw-r--r-- | tools/editor/spatial_editor_gizmos.cpp | 2 | ||||
-rw-r--r-- | tools/glwrapper/makewrapper.py | 183 | ||||
-rw-r--r-- | tools/ios_xcode_template/data.pck | 0 | ||||
-rw-r--r-- | tools/ios_xcode_template/godot_ios.xcodeproj/project.pbxproj | 469 | ||||
-rw-r--r-- | tools/ios_xcode_template/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata | 7 | ||||
-rw-r--r-- | tools/ios_xcode_template/godot_ios.xcodeproj/project.xcworkspace/xcuserdata/punto.xcuserdatad/UserInterfaceState.xcuserstate | bin | 13553 -> 0 bytes | |||
-rw-r--r-- | tools/ios_xcode_template/godot_ios.xcodeproj/xcuserdata/punto.xcuserdatad/xcschemes/godot_ios.xcscheme | 96 | ||||
-rw-r--r-- | tools/ios_xcode_template/godot_ios.xcodeproj/xcuserdata/punto.xcuserdatad/xcschemes/xcschememanagement.plist | 27 | ||||
-rw-r--r-- | tools/ios_xcode_template/godot_ios/en.lproj/InfoPlist.strings | 2 | ||||
-rw-r--r-- | tools/ios_xcode_template/godot_ios/godot_ios-Info.plist | 47 | ||||
-rw-r--r-- | tools/ios_xcode_template/godot_ios/godot_ios-Prefix.pch | 16 | ||||
-rw-r--r-- | tools/ios_xcode_template/godot_ios/main.m | 39 | ||||
-rw-r--r-- | tools/ios_xcode_template/godot_iosTests/en.lproj/InfoPlist.strings | 2 | ||||
-rw-r--r-- | tools/ios_xcode_template/godot_iosTests/godot_iosTests-Info.plist | 22 | ||||
-rw-r--r-- | tools/ios_xcode_template/godot_iosTests/godot_iosTests.m | 55 | ||||
-rw-r--r-- | tools/pck/SCsub | 4 | ||||
-rw-r--r-- | tools/script_plugins/terrain/plugin.cfg | 16 | ||||
-rw-r--r-- | tools/script_plugins/terrain/terrain.gd | 17 | ||||
-rw-r--r-- | tools/script_plugins/terrain/terrain.png | bin | 762 -> 0 bytes | |||
-rw-r--r-- | tools/script_plugins/terrain/terrain_node.gd | 3 | ||||
-rw-r--r-- | tools/script_plugins/time/plugin.cfg | 14 | ||||
-rw-r--r-- | tools/script_plugins/time/time.gd | 32 | ||||
-rw-r--r-- | tools/scripts/addheader.py (renamed from tools/addheader/addheader.py) | 0 | ||||
-rw-r--r-- | tools/scripts/make_bmfhdr.py (renamed from tools/bmfhdr/makehdr.py) | 0 | ||||
-rw-r--r-- | tools/scripts/make_glwrapper.py | 183 | ||||
-rw-r--r-- | tools/scripts/make_icons.sh (renamed from tools/steam/make_icons.sh) | 0 | ||||
-rw-r--r-- | tools/scripts/memsort.py (renamed from tools/memsort.py) | 0 | ||||
-rw-r--r-- | tools/translations/ar.po | 213 | ||||
-rw-r--r-- | tools/translations/bg.po | 220 | ||||
-rw-r--r-- | tools/translations/bn.po | 262 | ||||
-rw-r--r-- | tools/translations/ca.po | 865 | ||||
-rw-r--r-- | tools/translations/cs.po | 222 | ||||
-rw-r--r-- | tools/translations/da.po | 220 | ||||
-rw-r--r-- | tools/translations/de.po | 342 | ||||
-rw-r--r-- | tools/translations/de_CH.po | 217 | ||||
-rw-r--r-- | tools/translations/es.po | 387 | ||||
-rw-r--r-- | tools/translations/es_AR.po | 276 | ||||
-rwxr-xr-x | tools/translations/extract.py | 1 | ||||
-rw-r--r-- | tools/translations/fa.po | 222 | ||||
-rw-r--r-- | tools/translations/fr.po | 253 | ||||
-rw-r--r-- | tools/translations/id.po | 224 | ||||
-rw-r--r-- | tools/translations/is.po | 6667 | ||||
-rw-r--r-- | tools/translations/it.po | 268 | ||||
-rw-r--r-- | tools/translations/ja.po | 221 | ||||
-rw-r--r-- | tools/translations/ko.po | 254 | ||||
-rw-r--r-- | tools/translations/nb.po | 213 | ||||
-rw-r--r-- | tools/translations/pl.po | 231 | ||||
-rw-r--r-- | tools/translations/pt_BR.po | 246 | ||||
-rw-r--r-- | tools/translations/pt_PT.po | 215 | ||||
-rw-r--r-- | tools/translations/ro.po | 213 | ||||
-rw-r--r-- | tools/translations/ru.po | 270 | ||||
-rw-r--r-- | tools/translations/sk.po | 214 | ||||
-rw-r--r-- | tools/translations/sl.po | 215 | ||||
-rw-r--r-- | tools/translations/tools.pot | 213 | ||||
-rw-r--r-- | tools/translations/tr.po | 219 | ||||
-rw-r--r-- | tools/translations/ur_PK.po | 214 | ||||
-rw-r--r-- | tools/translations/zh_CN.po | 337 | ||||
-rw-r--r-- | tools/translations/zh_HK.po | 287 | ||||
-rw-r--r-- | tools/translations/zh_TW.po | 213 |
3328 files changed, 126548 insertions, 142371 deletions
diff --git a/.travis.yml b/.travis.yml index 3c7ee5c102..d76fcca791 100644 --- a/.travis.yml +++ b/.travis.yml @@ -69,8 +69,8 @@ addons: before_script: - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; brew install scons; fi - if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$GODOT_TARGET" = "android" ]; then - brew update; brew install -v android-sdk; - brew install -v android-ndk | grep -v "inflating:" | grep -v "creating:"; + brew update; travis_wait 20 brew install -v android-sdk; + travis_wait 20 brew install -v android-ndk | grep -v "inflating:" | grep -v "creating:"; export ANDROID_HOME=/usr/local/opt/android-sdk; export ANDROID_NDK_ROOT=/usr/local/opt/android-ndk; fi diff --git a/SConstruct b/SConstruct index d168820f66..365463ebad 100644 --- a/SConstruct +++ b/SConstruct @@ -1,3 +1,5 @@ +#!/usr/bin/env python + EnsureSConsVersion(0,14); @@ -16,7 +18,6 @@ platform_list = [] # list of platforms platform_opts = {} # options for each platform platform_flags = {} # flags for each platform - active_platforms=[] active_platform_ids=[] platform_exporters=[] @@ -55,15 +56,17 @@ methods.save_active_platforms(active_platforms,active_platform_ids) custom_tools=['default'] -platform_arg = ARGUMENTS.get("platform", False) +platform_arg = ARGUMENTS.get("platform", ARGUMENTS.get("p", False)) if (os.name=="posix"): pass elif (os.name=="nt"): - if (os.getenv("VSINSTALLDIR")==None or platform_arg=="android"): + if ( os.getenv("VCINSTALLDIR")==None or platform_arg=="android"): custom_tools=['mingw'] env_base=Environment(tools=custom_tools); +if 'TERM' in os.environ: + env_base['ENV']['TERM'] = os.environ['TERM'] env_base.AppendENVPath('PATH', os.getenv('PATH')) env_base.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH')) env_base.global_defaults=global_defaults @@ -98,9 +101,8 @@ env_base.__class__.disable_module = methods.disable_module env_base.__class__.add_source_files = methods.add_source_files env_base.__class__.use_windows_spawn_fix = methods.use_windows_spawn_fix -env_base["x86_opt_gcc"]=False -env_base["x86_opt_vc"]=False -env_base["armv7_opt_gcc"]=False +env_base["x86_libtheora_opt_gcc"]=False +env_base["x86_libtheora_opt_vc"]=False customs = ['custom.py'] @@ -120,32 +122,30 @@ opts.Add('platform','Platform: '+str(platform_list)+'.',"") opts.Add('p','Platform (same as platform=).',"") opts.Add('tools','Build Tools (Including Editor): (yes/no)','yes') opts.Add('gdscript','Build GDSCript support: (yes/no)','yes') -opts.Add('vorbis','Build Ogg Vorbis Support: (yes/no)','yes') -opts.Add('opus','Build Opus Audio Format Support: (yes/no)','yes') +opts.Add('libogg','Ogg library for ogg container support (system/builtin)','builtin') +opts.Add('libvorbis','Ogg Vorbis library for vorbis support (system/builtin)','builtin') +opts.Add('libtheora','Theora library for theora module (system/builtin)','builtin') +opts.Add('opus','Opus and opusfile library for Opus format support: (system/builtin)','builtin') opts.Add('minizip','Build Minizip Archive Support: (yes/no)','yes') -opts.Add('squish','Squish BC Texture Compression in editor (yes/no)','yes') -opts.Add('theora','Theora Video (yes/no)','yes') -opts.Add('theoralib','Theora Video (yes/no)','no') -opts.Add('freetype','Freetype support in editor','builtin') -opts.Add('speex','Speex Audio (yes/no)','yes') +opts.Add('squish','Squish library for BC Texture Compression in editor (system/builtin)','builtin') +opts.Add('freetype','Freetype library for TTF support via freetype module (system/builtin)','builtin') opts.Add('xml','XML Save/Load support (yes/no)','yes') -opts.Add('png','PNG Image loader support (yes/no)','yes') -opts.Add('jpg','JPG Image loader support (yes/no)','yes') -opts.Add('webp','WEBP Image loader support (yes/no)','yes') -opts.Add('dds','DDS Texture loader support (yes/no)','yes') -opts.Add('pvr','PVR (PowerVR) Texture loader support (yes/no)','yes') -opts.Add('etc1','etc1 Texture compression support (yes/no)','yes') -opts.Add('builtin_zlib','Use built-in zlib (yes/no)','yes') -opts.Add('openssl','Use OpenSSL (yes/no/builtin)','no') -opts.Add('musepack','Musepack Audio (yes/no)','yes') -opts.Add("CXX", "Compiler"); -opts.Add("CCFLAGS", "Custom flags for the C++ compiler"); +opts.Add('libpng','libpng library for image loader support (system/builtin)','builtin') +opts.Add('libwebp','libwebp library for webp module (system/builtin)','builtin') +opts.Add('openssl','OpenSSL library for openssl module (system/builtin)','builtin') +opts.Add('libmpcdec','libmpcdec library for mpc module (system/builtin)','builtin') +opts.Add('enet','ENet library (system/builtin)','builtin') +opts.Add('glew','GLEW library for the gl_context (system/builtin)','builtin') +opts.Add('xaudio2','XAudio2 audio driver (yes/no)','no') +opts.Add("CXX", "C++ Compiler") +opts.Add("CC", "C Compiler") +opts.Add("CCFLAGS", "Custom flags for the C/C++ compiler"); opts.Add("CFLAGS", "Custom flags for the C compiler"); opts.Add("LINKFLAGS", "Custom flags for the linker"); opts.Add('unix_global_settings_path', 'unix-specific path to system-wide settings. Currently only used by templates.','') opts.Add('disable_3d', 'Disable 3D nodes for smaller executable (yes/no)', "no") opts.Add('disable_advanced_gui', 'Disable advance 3D gui nodes and behaviors (yes/no)', "no") -opts.Add('colored', 'Enable colored output for the compilation (yes/no)', 'no') +opts.Add('verbose', 'Enable verbose output for the compilation (yes/no)', 'yes') opts.Add('deprecated','Enable deprecated features (yes/no)','yes') opts.Add('extra_suffix', 'Custom extra suffix added to the base filename of all generated binary files.', '') opts.Add('vsproj', 'Generate Visual Studio Project. (yes/no)', 'no') @@ -158,7 +158,7 @@ for k in platform_opts.keys(): opts.Add(o[0],o[1],o[2]) for x in module_list: - opts.Add('module_'+x+'_enabled', "Enable module '"+x+"'.", "yes") + opts.Add('module_'+x+'_enabled', "Enable module '"+x+"' (yes/no)", "yes") opts.Update(env_base) # update environment Help(opts.GenerateHelpText(env_base)) # generate help @@ -254,14 +254,6 @@ if selected_platform in platform_list: #must happen after the flags, so when flags are used by configure, stuff happens (ie, ssl on x11) detect.configure(env) - - if (env["freetype"]!="no"): - env.Append(CCFLAGS=['-DFREETYPE_ENABLED']) - if (env["freetype"]=="builtin"): - env.Append(CPPPATH=['#drivers/freetype']) - env.Append(CPPPATH=['#drivers/freetype/freetype/include']) - - #env['platform_libsuffix'] = env['LIBSUFFIX'] suffix="."+selected_platform @@ -272,6 +264,8 @@ if selected_platform in platform_list: sys.exit(255) suffix+=".opt" + env.Append(CCFLAGS=['-DNDEBUG']); + elif (env["target"]=="release_debug"): if (env["tools"]=="yes"): suffix+=".opt.tools" @@ -322,49 +316,9 @@ if selected_platform in platform_list: if (env.use_ptrcall): env.Append(CPPFLAGS=['-DPTRCALL_ENABLED']); - if (env['musepack']=='yes'): - env.Append(CPPFLAGS=['-DMUSEPACK_ENABLED']); - - #if (env['openssl']!='no'): - # env.Append(CPPFLAGS=['-DOPENSSL_ENABLED']); - # if (env['openssl']=="builtin"): - # env.Append(CPPPATH=['#drivers/builtin_openssl2']) - - if (env["builtin_zlib"]=='yes'): - env.Append(CPPPATH=['#drivers/builtin_zlib/zlib']) - # to test 64 bits compiltion # env.Append(CPPFLAGS=['-m64']) - if (env_base['squish']=='yes'): - env.Append(CPPFLAGS=['-DSQUISH_ENABLED']); - - if (env['vorbis']=='yes'): - env.Append(CPPFLAGS=['-DVORBIS_ENABLED']); - if (env['opus']=='yes'): - env.Append(CPPFLAGS=['-DOPUS_ENABLED']); - - - if (env['theora']=='yes'): - env['theoralib']='yes' - env.Append(CPPFLAGS=['-DTHEORA_ENABLED']); - if (env['theoralib']=='yes'): - env.Append(CPPFLAGS=['-DTHEORALIB_ENABLED']); - - if (env['png']=='yes'): - env.Append(CPPFLAGS=['-DPNG_ENABLED']); - if (env['dds']=='yes'): - env.Append(CPPFLAGS=['-DDDS_ENABLED']); - if (env['pvr']=='yes'): - env.Append(CPPFLAGS=['-DPVR_ENABLED']); - if (env['jpg']=='yes'): - env.Append(CPPFLAGS=['-DJPG_ENABLED']); - if (env['webp']=='yes'): - env.Append(CPPFLAGS=['-DWEBP_ENABLED']); - - if (env['speex']=='yes'): - env.Append(CPPFLAGS=['-DSPEEX_ENABLED']); - if (env['tools']=='yes'): env.Append(CPPFLAGS=['-DTOOLS_ENABLED']) if (env['disable_3d']=='yes'): @@ -380,11 +334,8 @@ if selected_platform in platform_list: if (env['xml']=='yes'): env.Append(CPPFLAGS=['-DXML_ENABLED']) - if (env['colored']=='yes'): - methods.colored(sys,env) - - if (env['etc1']=='yes'): - env.Append(CPPFLAGS=['-DETC1_ENABLED']) + if (env['verbose']=='no'): + methods.no_verbose(sys,env) Export('env') @@ -432,9 +383,9 @@ if selected_platform in platform_list: release_variants = ['release|Win32']+['release|x64'] release_debug_variants = ['release_debug|Win32']+['release_debug|x64'] variants = debug_variants + release_variants + release_debug_variants - debug_targets = ['Debug']+['Debug'] - release_targets = ['Release']+['Release'] - release_debug_targets = ['ReleaseDebug']+['ReleaseDebug'] + debug_targets = ['bin\\godot.windows.tools.32.exe']+['bin\\godot.windows.tools.64.exe'] + release_targets = ['bin\\godot.windows.opt.32.exe']+['bin\\godot.windows.opt.64.exe'] + release_debug_targets = ['bin\\godot.windows.opt.tools.32.exe']+['bin\\godot.windows.opt.tools.64.exe'] targets = debug_targets + release_targets + release_debug_targets msvproj = env.MSVSProject(target = ['#godot' + env['MSVSPROJECTSUFFIX'] ], incs = env.vs_incs, @@ -1,3 +1,5 @@ +#!/usr/bin/python + Import('env') Export('env') diff --git a/bin/tests/SCsub b/bin/tests/SCsub index 57c9bc63b2..26687599e1 100644 --- a/bin/tests/SCsub +++ b/bin/tests/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/python + Import('env') env.tests_sources=[] diff --git a/bin/tests/test_gdscript.cpp b/bin/tests/test_gdscript.cpp index 4457d70b38..43d65f782b 100644 --- a/bin/tests/test_gdscript.cpp +++ b/bin/tests/test_gdscript.cpp @@ -222,6 +222,7 @@ static String _parser_expr(const GDParser::Node *p_expr) { case GDParser::OperatorNode::OP_BIT_AND: { txt=_parser_expr(c_node->arguments[0])+"&"+_parser_expr(c_node->arguments[1]); } break;; case GDParser::OperatorNode::OP_BIT_OR: { txt=_parser_expr(c_node->arguments[0])+"|"+_parser_expr(c_node->arguments[1]); } break; case GDParser::OperatorNode::OP_BIT_XOR: { txt=_parser_expr(c_node->arguments[0])+"^"+_parser_expr(c_node->arguments[1]); } break; + default: {} } diff --git a/bin/tests/test_math.cpp b/bin/tests/test_math.cpp index 4b686e8af8..9329002f76 100644 --- a/bin/tests/test_math.cpp +++ b/bin/tests/test_math.cpp @@ -40,12 +40,376 @@ #include "scene/resources/texture.h" #include "vmap.h" #include "os/os.h" +#include "os/file_access.h" #include "method_ptrcall.h" namespace TestMath { +class GetClassAndNamespace { + + String code; + int idx; + int line; + String error_str; + bool error; + Variant value; + + String class_name; + + enum Token { + TK_BRACKET_OPEN, + TK_BRACKET_CLOSE, + TK_CURLY_BRACKET_OPEN, + TK_CURLY_BRACKET_CLOSE, + TK_PERIOD, + TK_COLON, + TK_COMMA, + TK_SYMBOL, + TK_IDENTIFIER, + TK_STRING, + TK_NUMBER, + TK_EOF, + TK_ERROR + }; + + + Token get_token() { + + while (true) { + switch(code[idx]) { + + case '\n': { + + line++; + idx++; + break; + }; + case 0: { + return TK_EOF; + + } break; + case '{': { + + idx++; + return TK_CURLY_BRACKET_OPEN; + }; + case '}': { + + idx++; + return TK_CURLY_BRACKET_CLOSE; + }; + case '[': { + + idx++; + return TK_BRACKET_OPEN; + }; + case ']': { + + idx++; + return TK_BRACKET_CLOSE; + }; + case ':': { + + idx++; + return TK_COLON; + }; + case ',': { + + idx++; + return TK_COMMA; + }; + case '.': { + + idx++; + return TK_PERIOD; + }; + case '#': { + //compiler directive + while(code[idx]!='\n' && code[idx]!=0) { + idx++; + } + continue; + } break; + case '/': { + + + switch(code[idx+1]) { + case '*': { // block comment + + idx+=2; + while(true) { + if (code[idx]==0) { + error_str="Unterminated comment"; + error=true; + return TK_ERROR; + } if (code[idx]=='*' &&code[idx+1]=='/') { + + idx+=2; + break; + } if (code[idx]=='\n') { + line++; + } + + idx++; + } + + } break; + case '/': { // line comment skip + + while(code[idx]!='\n' && code[idx]!=0) { + idx++; + } + + } break; + default: { + value="/"; + idx++; + return TK_SYMBOL; + } + + } + + continue; // a comment + } break; + case '\'': + case '"': { + + CharType begin_str = code[idx]; + idx++; + String tk_string=String(); + while(true) { + if (code[idx]==0) { + error_str="Unterminated String"; + error=true; + return TK_ERROR; + } else if (code[idx]==begin_str) { + idx++; + break; + } else if (code[idx]=='\\') { + //escaped characters... + idx++; + CharType next = code[idx]; + if (next==0) { + error_str="Unterminated String"; + error=true; + return TK_ERROR; + } + CharType res=0; + + switch(next) { + + case 'b': res=8; break; + case 't': res=9; break; + case 'n': res=10; break; + case 'f': res=12; break; + case 'r': res=13; break; + /* too much, not needed for now + case 'u': { + //hexnumbarh - oct is deprecated + + + for(int j=0;j<4;j++) { + CharType c = code[idx+j+1]; + if (c==0) { + r_err_str="Unterminated String"; + return ERR_PARSE_ERROR; + } + if (!((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'))) { + + r_err_str="Malformed hex constant in string"; + return ERR_PARSE_ERROR; + } + CharType v; + if (c>='0' && c<='9') { + v=c-'0'; + } else if (c>='a' && c<='f') { + v=c-'a'; + v+=10; + } else if (c>='A' && c<='F') { + v=c-'A'; + v+=10; + } else { + ERR_PRINT("BUG"); + v=0; + } + + res<<=4; + res|=v; + + + } + idx+=4; //will add at the end anyway + + + } break;*/ + case '\"': res='\"'; break; + case '\\': res='\\'; break; + //case '/': res='/'; break; + default: { + res = next; + //r_err_str="Invalid escape sequence"; + //return ERR_PARSE_ERROR; + } break; + } + + tk_string+=res; + + } else { + if (code[idx]=='\n') + line++; + tk_string+=code[idx]; + } + idx++; + } + + value=tk_string; + + return TK_STRING; + + } break; + default: { + + if (code[idx]<=32) { + idx++; + break; + } + + if ( (code[idx]>=33 && code[idx]<=47) || (code[idx]>=58 && code[idx]<=64) || (code[idx]>=91 && code[idx]<=96) || (code[idx]>=123 && code[idx]<=127)){ + value=String::chr(code[idx]); + idx++; + return TK_SYMBOL; + } + + if (code[idx]=='-' || (code[idx]>='0' && code[idx]<='9')) { + //a number + const CharType *rptr; + double number = String::to_double(&code[idx],&rptr); + idx+=(rptr - &code[idx]); + value=number; + return TK_NUMBER; + + } else if ((code[idx]>='A' && code[idx]<='Z') || (code[idx]>='a' && code[idx]<='z') || code[idx]>127) { + + String id; + + while((code[idx]>='A' && code[idx]<='Z') || (code[idx]>='a' && code[idx]<='z') || code[idx]>127) { + + id+=code[idx]; + idx++; + } + + value=id; + return TK_IDENTIFIER; + } else { + error_str="Unexpected character."; + error=true; + return TK_ERROR; + } + } + + } + } + } + +public: + Error parse(const String& p_code,const String& p_known_class_name=String()) { + + code=p_code; + idx=0; + line=0; + error_str=String(); + error=false; + value=Variant(); + class_name=String(); + + bool use_next_class=false; + Token tk = get_token(); + + Map<int,String> namespace_stack; + int curly_stack=0; + + + while(!error || tk!=TK_EOF) { + + if (tk==TK_BRACKET_OPEN) { + tk = get_token(); + if (tk==TK_IDENTIFIER && String(value)=="ScriptClass") { + if (get_token()==TK_BRACKET_CLOSE) { + use_next_class=true; + } + } + } else if (tk==TK_IDENTIFIER && String(value)=="class") { + tk = get_token(); + if (tk==TK_IDENTIFIER) { + String name = value; + if (use_next_class || p_known_class_name==name) { + for (Map<int,String>::Element *E=namespace_stack.front();E;E=E->next()) { + class_name+=E->get()+"."; + } + class_name+=String(value); + break; + } + } + + } else if (tk==TK_IDENTIFIER && String(value)=="namespace") { + String name; + int at_level = curly_stack; + while(true) { + tk = get_token(); + if (tk==TK_IDENTIFIER) { + name+=String(value); + } + + tk = get_token(); + if (tk==TK_PERIOD) { + name+="."; + } else if (tk==TK_CURLY_BRACKET_OPEN) { + curly_stack++; + break; + } else { + break; //whathever else + } + + } + + if (name!=String()) { + namespace_stack[at_level]=name; + } + + } else if (tk==TK_CURLY_BRACKET_OPEN) { + curly_stack++; + } else if (tk==TK_CURLY_BRACKET_CLOSE) { + curly_stack--; + if (namespace_stack.has(curly_stack)) { + namespace_stack.erase(curly_stack); + } + } + + tk = get_token(); + } + + if (error) + return ERR_PARSE_ERROR; + + + + return OK; + + } + + String get_error() { + return error_str; + } + + String get_class() { + return class_name; + } + +}; + + void test_vec(Plane p_vec) { @@ -113,12 +477,46 @@ uint32_t ihash3( uint32_t a) MainLoop* test() { - print_line(itos(Math::step_decimals( 0.0001 ))); + + List<String> cmdlargs = OS::get_singleton()->get_cmdline_args(); + + if (cmdlargs.empty()) { + //try editor! + return NULL; + } + + String test = cmdlargs.back()->get(); + + FileAccess *fa = FileAccess::open(test,FileAccess::READ); + + if (!fa) { + ERR_EXPLAIN("Could not open file: "+test); + ERR_FAIL_V(NULL); + } + + + Vector<uint8_t> buf; + int flen = fa->get_len(); + buf.resize(fa->get_len()+1); + fa->get_buffer(&buf[0],flen); + buf[flen]=0; + + + String code; + code.parse_utf8((const char*)&buf[0]); + + GetClassAndNamespace getclass; + if (getclass.parse(code)) { + print_line("Parse error: "+getclass.get_error()); + } else { + print_line("Found class: "+getclass.get_class()); + } + return NULL; { - Vector<int32_t> hashes; + Vector<int> hashes; List<StringName> tl; ObjectTypeDB::get_type_list(&tl); diff --git a/bin/tests/test_misc.cpp b/bin/tests/test_misc.cpp index 68564c62b0..9d7adc3573 100644 --- a/bin/tests/test_misc.cpp +++ b/bin/tests/test_misc.cpp @@ -431,7 +431,7 @@ public: RID lightaux = vs->light_create( VisualServer::LIGHT_DIRECTIONAL ); //vs->light_set_color( lightaux, VisualServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,0.0) ); //vs->light_set_shadow( lightaux, true ); - RID light = vs->instance_create2( lightaux,scenario ); + vs->instance_create2( lightaux,scenario ); //rot_a=Transform(Matrix3(Vector3(1,0,0),Math_PI/2.0),Vector3()); rot_b=Transform(Matrix3(),Vector3(2,0,0)); diff --git a/bin/tests/test_physics.cpp b/bin/tests/test_physics.cpp index ecd90a13d4..f202d0dda1 100644 --- a/bin/tests/test_physics.cpp +++ b/bin/tests/test_physics.cpp @@ -609,7 +609,7 @@ public: //t.basis.rotate(Vector3(-1,0,0),Math_PI/4*i); - RID b = create_body(type,PhysicsServer::BODY_MODE_RIGID,t); + create_body(type,PhysicsServer::BODY_MODE_RIGID,t); //RID b = create_body(type,i==0?PhysicsServer::BODY_MODE_STATIC:PhysicsServer::BODY_MODE_RIGID,t); } diff --git a/bin/tests/test_physics_2d.cpp b/bin/tests/test_physics_2d.cpp index c5fb734999..845e20b6c3 100644 --- a/bin/tests/test_physics_2d.cpp +++ b/bin/tests/test_physics_2d.cpp @@ -410,7 +410,7 @@ public: Physics2DServer::ShapeType type = types[i%4]; // type=Physics2DServer::SHAPE_SEGMENT; - RID b = _add_body(type,Matrix32(i*0.8,Point2(152+i*40,100-40*i))); + _add_body(type,Matrix32(i*0.8,Point2(152+i*40,100-40*i))); //if (i==0) // ps->body_set_mode(b,Physics2DServer::BODY_MODE_STATIC); } diff --git a/bin/tests/test_string.cpp b/bin/tests/test_string.cpp index be37ce118f..2e8f5c3494 100644 --- a/bin/tests/test_string.cpp +++ b/bin/tests/test_string.cpp @@ -32,6 +32,7 @@ #include <stdio.h> #include "os/os.h" #include "drivers/nrex/regex.h" +#include "core/io/ip_address.h" #include "test_string.h" @@ -843,6 +844,62 @@ bool test_28() { return state; } +bool test_29() { + + bool error = false; + bool state = true; + bool success = false; + + IP_Address ip0("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + OS::get_singleton()->print("ip0 is %ls\n", String(ip0).c_str()); + + IP_Address ip(0x0123, 0x4567, 0x89ab, 0xcdef, IP_Address::TYPE_IPV6); + OS::get_singleton()->print("ip6 is %ls\n", String(ip).c_str()); + + IP_Address ip2("fe80::52e5:49ff:fe93:1baf"); + OS::get_singleton()->print("ip6 is %ls\n", String(ip2).c_str()); + + IP_Address ip3("::ffff:192.168.0.1"); + OS::get_singleton()->print("ip6 is %ls\n", String(ip3).c_str()); + + String ip4 = "192.168.0.1"; + success = ip4.is_valid_ip_address(); + OS::get_singleton()->print("Is valid ipv4: %ls, %s\n", ip4.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + ip4 = "192.368.0.1"; + success = (!ip4.is_valid_ip_address()); + OS::get_singleton()->print("Is invalid ipv4: %ls, %s\n", ip4.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + String ip6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; + success = ip6.is_valid_ip_address(); + OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + ip6 = "2001:0db8:85j3:0000:0000:8a2e:0370:7334"; + success = (!ip6.is_valid_ip_address()); + OS::get_singleton()->print("Is invalid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + ip6 = "2001:0db8:85f345:0000:0000:8a2e:0370:7334"; + success = (!ip6.is_valid_ip_address()); + OS::get_singleton()->print("Is invalid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + ip6 = "2001:0db8::0:8a2e:370:7334"; + success = (ip6.is_valid_ip_address()); + OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + ip6 = "::ffff:192.168.0.1"; + success = (ip6.is_valid_ip_address()); + OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + return state; +}; + typedef bool (*TestFunc)(void); TestFunc test_funcs[] = { @@ -875,6 +932,7 @@ TestFunc test_funcs[] = { test_26, test_27, test_28, + test_29, 0 }; diff --git a/core/SCsub b/core/SCsub index 4ce91c794f..cbed2e4f35 100644 --- a/core/SCsub +++ b/core/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.core_sources=[] diff --git a/core/array.cpp b/core/array.cpp index 23792f90fc..683a43e3d0 100644 --- a/core/array.cpp +++ b/core/array.cpp @@ -276,16 +276,26 @@ void Array::push_front(const Variant& p_value) { _p->array.insert(0,p_value); } -void Array::pop_back(){ +Variant Array::pop_back(){ - if (!_p->array.empty()) - _p->array.resize( _p->array.size() -1 ); + if (!_p->array.empty()) { + int n = _p->array.size() - 1; + Variant ret = _p->array.get(n); + _p->array.resize(n); + return ret; + } + return Variant(); } -void Array::pop_front(){ - if (!_p->array.empty()) +Variant Array::pop_front(){ + + if (!_p->array.empty()) { + Variant ret = _p->array.get(0); _p->array.remove(0); + return ret; + } + return Variant(); } diff --git a/core/array.h b/core/array.h index dfc902525c..eb79b0cf33 100644 --- a/core/array.h +++ b/core/array.h @@ -80,8 +80,8 @@ public: void erase(const Variant& p_value); void push_front(const Variant& p_value); - void pop_back(); - void pop_front(); + Variant pop_back(); + Variant pop_front(); Array(const Array& p_from); Array(bool p_shared=false); diff --git a/core/bind/SCsub b/core/bind/SCsub index 7b4a6acbc0..c2731d60e6 100644 --- a/core/bind/SCsub +++ b/core/bind/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.core_sources,"*.cpp") diff --git a/core/dvector.h b/core/dvector.h index a5519ed604..9a54641617 100644 --- a/core/dvector.h +++ b/core/dvector.h @@ -262,6 +262,34 @@ public: w[bs+i]=r[i]; } + DVector<T> subarray(int p_from, int p_to) { + + if (p_from<0) { + p_from=size()+p_from; + } + if (p_to<0) { + p_to=size()+p_to; + } + if (p_from<0 || p_from>=size()) { + DVector<T>& aux=*((DVector<T>*)0); // nullreturn + ERR_FAIL_COND_V(p_from<0 || p_from>=size(),aux) + } + if (p_to<0 || p_to>=size()) { + DVector<T>& aux=*((DVector<T>*)0); // nullreturn + ERR_FAIL_COND_V(p_to<0 || p_to>=size(),aux) + } + + DVector<T> slice; + int span=1 + p_to - p_from; + slice.resize(span); + Read r = read(); + Write w = slice.write(); + for (int i=0; i<span; ++i) { + w[i] = r[p_from+i]; + } + + return slice; + } Error insert(int p_pos,const T& p_val) { diff --git a/core/func_ref.cpp b/core/func_ref.cpp index 644d8b5b63..ca890111be 100644 --- a/core/func_ref.cpp +++ b/core/func_ref.cpp @@ -61,11 +61,7 @@ void FuncRef::_bind_methods() { MethodInfo mi; mi.name="call_func"; Vector<Variant> defargs; - for(int i=0;i<10;i++) { - mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); - defargs.push_back(Variant()); - } - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_func:Variant",&FuncRef::call_func,mi,defargs); + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_func:Variant",&FuncRef::call_func,mi,defargs); } diff --git a/core/globals.cpp b/core/globals.cpp index b822f52f15..bef40ff330 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -54,7 +54,7 @@ String Globals::localize_path(const String& p_path) const { if (resource_path=="") return p_path; //not initialied yet - if (p_path.begins_with("res://") || p_path.begins_with("user://")) + if (p_path.begins_with("res://") || p_path.begins_with("user://") || p_path.is_abs_path()) return p_path.simplify_path(); diff --git a/core/hashfuncs.h b/core/hashfuncs.h index a917ee5edb..6c029a3458 100644 --- a/core/hashfuncs.h +++ b/core/hashfuncs.h @@ -74,7 +74,10 @@ static inline uint32_t hash_djb2_one_float(float p_in,uint32_t p_prev=5381) { float f; uint32_t i; } u; - u.f=p_in; + + // handle -0 case + if (p_in==0.0f) u.f=0.0f; + else u.f=p_in; return ((p_prev<<5)+p_prev)+u.i; } diff --git a/core/image.cpp b/core/image.cpp index d6ac3f28ea..90051d7d0d 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -2052,6 +2052,7 @@ Error Image::_decompress_bc() { ht/=2; } break; + default: {} } } diff --git a/core/input_map.cpp b/core/input_map.cpp index 3a0f9596f5..09cb7ce426 100644 --- a/core/input_map.cpp +++ b/core/input_map.cpp @@ -232,64 +232,6 @@ bool InputMap::event_is_action(const InputEvent& p_event, const StringName& p_ac return _find_event(E->get().inputs,p_event)!=NULL; } -bool InputMap::event_is_joy_motion_action_pressed(const InputEvent& p_event) const { - - ERR_FAIL_COND_V(p_event.type!=InputEvent::JOYSTICK_MOTION,false); - bool pressed=false; - - //this could be optimized by having a separate list of joymotions? - - for (Map<StringName, Action>::Element *A=input_map.front();A;A=A->next()) { - - for (List<InputEvent>::Element *E=A->get().inputs.front();E;E=E->next()) { - - const InputEvent& e=E->get(); - if(e.type!=p_event.type) - continue; - if (e.type!=InputEvent::KEY && e.device!=p_event.device) - continue; - - switch(p_event.type) { - - case InputEvent::KEY: { - - if (e.key.scancode==p_event.key.scancode && e.key.mod == p_event.key.mod) - return e.key.pressed; - - } break; - case InputEvent::JOYSTICK_BUTTON: { - - if (e.joy_button.button_index==p_event.joy_button.button_index) { - return e.joy_button.pressed; - } - - } break; - case InputEvent::MOUSE_BUTTON: { - - if (e.mouse_button.button_index==p_event.mouse_button.button_index) { - return e.mouse_button.pressed; - } - - } break; - case InputEvent::JOYSTICK_MOTION: { - - if (e.joy_motion.axis==p_event.joy_motion.axis) { - if ( - (e.joy_motion.axis_value * p_event.joy_motion.axis_value >0) && //same axis - ABS(e.joy_motion.axis_value)>0.5 && ABS(p_event.joy_motion.axis_value)>0.5 ) - pressed=true; - } - - } break; - } - - } - } - - return pressed; - -} - const Map<StringName, InputMap::Action>& InputMap::get_action_map() const { return input_map; } diff --git a/core/input_map.h b/core/input_map.h index a224765d8c..21c479588d 100644 --- a/core/input_map.h +++ b/core/input_map.h @@ -72,7 +72,6 @@ public: const List<InputEvent> *get_action_list(const StringName& p_action); bool event_is_action(const InputEvent& p_event, const StringName& p_action) const; - bool event_is_joy_motion_action_pressed(const InputEvent& p_event) const; const Map<StringName, Action>& get_action_map() const; void load_from_globals(); diff --git a/core/io/SCsub b/core/io/SCsub index 3ff9b355a4..48cc9a5275 100644 --- a/core/io/SCsub +++ b/core/io/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.core_sources,"*.cpp") diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 5c8c741f28..1632b841c6 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -409,6 +409,8 @@ Error DirAccessPack::change_dir(String p_dir) { nd=nd.simplify_path(); + if (nd == "") nd = "."; + if (nd.begins_with("/")) { nd=nd.replace_first("/","") ; absolute=true; diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 2a831dd992..e3289b452c 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -29,8 +29,9 @@ #include "http_client.h" #include "io/stream_peer_ssl.h" +VARIANT_ENUM_CAST(IP_Address::AddrType); -Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_verify_host){ +Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_verify_host, IP_Address::AddrType p_addr_type){ close(); conn_port=p_port; @@ -62,7 +63,7 @@ Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_ve status=STATUS_CONNECTING; } else { //is hostname - resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host); + resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host, p_addr_type); status=STATUS_RESOLVING; } @@ -635,7 +636,7 @@ Error HTTPClient::_get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received) void HTTPClient::_bind_methods() { - ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true)); + ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true),DEFVAL(IP_Address::TYPE_ANY)); ObjectTypeDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection); ObjectTypeDB::bind_method(_MD("get_connection:StreamPeer"),&HTTPClient::get_connection); ObjectTypeDB::bind_method(_MD("request_raw","method","url","headers","body"),&HTTPClient::request_raw); diff --git a/core/io/http_client.h b/core/io/http_client.h index 32d2e72101..ba464c34c7 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -165,7 +165,7 @@ public: //Error connect_and_get(const String& p_url,bool p_verify_host=true); //connects to a full url and perform request - Error connect(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true); + Error connect(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true, IP_Address::AddrType p_addr_type = IP_Address::TYPE_ANY); void set_connection(const Ref<StreamPeer>& p_connection); Ref<StreamPeer> get_connection() const; diff --git a/core/io/ip.cpp b/core/io/ip.cpp index a77aace07f..4ee1b281c4 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -32,6 +32,7 @@ #include "hash_map.h" VARIANT_ENUM_CAST(IP::ResolverStatus); +VARIANT_ENUM_CAST(IP_Address::AddrType); /************* RESOLVER ******************/ @@ -43,10 +44,12 @@ struct _IP_ResolverPrivate { volatile IP::ResolverStatus status; IP_Address response; String hostname; + IP_Address::AddrType type; void clear() { status = IP::RESOLVER_STATUS_NONE; response = IP_Address(); + type = IP_Address::TYPE_NONE; hostname=""; }; @@ -78,9 +81,9 @@ struct _IP_ResolverPrivate { if (queue[i].status!=IP::RESOLVER_STATUS_WAITING) continue; - queue[i].response=IP::get_singleton()->resolve_hostname(queue[i].hostname); + queue[i].response=IP::get_singleton()->resolve_hostname(queue[i].hostname, queue[i].type); - if (queue[i].response.host==0) + if (queue[i].response.type==IP_Address::TYPE_NONE) queue[i].status=IP::RESOLVER_STATUS_ERROR; else queue[i].status=IP::RESOLVER_STATUS_DONE; @@ -109,21 +112,23 @@ struct _IP_ResolverPrivate { -IP_Address IP::resolve_hostname(const String& p_hostname) { +IP_Address IP::resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type) { - GLOBAL_LOCK_FUNCTION + GLOBAL_LOCK_FUNCTION; if (resolver->cache.has(p_hostname)) - return resolver->cache[p_hostname]; + if (resolver->cache[p_hostname].type & p_type != 0) + return resolver->cache[p_hostname]; + // requested type is different from type in cache. continue resolution, if successful it'll overwrite cache - IP_Address res = _resolve_hostname(p_hostname); + IP_Address res = _resolve_hostname(p_hostname, p_type); resolver->cache[p_hostname]=res; return res; } -IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname) { +IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname, IP_Address::AddrType p_type) { - GLOBAL_LOCK_FUNCTION + GLOBAL_LOCK_FUNCTION; ResolverID id = resolver->find_empty_id(); @@ -133,7 +138,8 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname) { } resolver->queue[id].hostname=p_hostname; - if (resolver->cache.has(p_hostname)) { + resolver->queue[id].type = p_type; + if (resolver->cache.has(p_hostname) && (resolver->cache[p_hostname].type & p_type) != 0) { resolver->queue[id].response=resolver->cache[p_hostname]; resolver->queue[id].status=IP::RESOLVER_STATUS_DONE; } else { @@ -145,10 +151,6 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname) { resolver->resolve_queues(); } - - - - return id; } @@ -187,6 +189,14 @@ void IP::erase_resolve_item(ResolverID p_id) { } +void IP::clear_cache(const String &p_hostname) { + + if (p_hostname.empty()) { + resolver->cache.clear(); + } else { + resolver->cache.erase(p_hostname); + } +}; Array IP::_get_local_addresses() const { @@ -208,6 +218,7 @@ void IP::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_resolve_item_address","id"),&IP::get_resolve_item_address); ObjectTypeDB::bind_method(_MD("erase_resolve_item","id"),&IP::erase_resolve_item); ObjectTypeDB::bind_method(_MD("get_local_addresses"),&IP::_get_local_addresses); + ObjectTypeDB::bind_method(_MD("clear_cache"),&IP::clear_cache, DEFVAL("")); BIND_CONSTANT( RESOLVER_STATUS_NONE ); BIND_CONSTANT( RESOLVER_STATUS_WAITING ); diff --git a/core/io/ip.h b/core/io/ip.h index 38c86e7ba3..742dd0e740 100644 --- a/core/io/ip.h +++ b/core/io/ip.h @@ -48,6 +48,14 @@ public: RESOLVER_STATUS_ERROR, }; + enum AddressType { + + ADDRESS_IPV4 = 1, + ADDRESS_IPV6 = 2, + + ADDRESS_ANY = 3, + }; + enum { RESOLVER_MAX_QUERIES = 32, RESOLVER_INVALID_ID=-1 @@ -65,7 +73,7 @@ protected: static IP*singleton; static void _bind_methods(); - virtual IP_Address _resolve_hostname(const String& p_hostname)=0; + virtual IP_Address _resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type = IP_Address::TYPE_ANY)=0; Array _get_local_addresses() const; static IP* (*_create)(); @@ -73,14 +81,16 @@ public: - IP_Address resolve_hostname(const String& p_hostname); + IP_Address resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type = IP_Address::TYPE_ANY); // async resolver hostname - ResolverID resolve_hostname_queue_item(const String& p_hostname); + ResolverID resolve_hostname_queue_item(const String& p_hostname, IP_Address::AddrType p_type = IP_Address::TYPE_ANY); ResolverStatus get_resolve_item_status(ResolverID p_id) const; IP_Address get_resolve_item_address(ResolverID p_id) const; virtual void get_local_addresses(List<IP_Address> *r_addresses) const=0; void erase_resolve_item(ResolverID p_id); + void clear_cache(const String& p_hostname = ""); + static IP* get_singleton(); static IP* create(); diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index 7a51bce7c6..9887cd132b 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -32,29 +32,191 @@ IP_Address::operator Variant() const { return operator String(); }*/ + +#include <string.h> +#include <stdio.h> + IP_Address::operator String() const { - return itos(field[0])+"."+itos(field[1])+"."+itos(field[2])+"."+itos(field[3]); + if (type == TYPE_NONE) + return "0.0.0.0"; + if (type == TYPE_IPV4) + return itos(field8[0])+"."+itos(field8[1])+"."+itos(field8[2])+"."+itos(field8[3]); + else { + String ret; + for (int i=0; i<8; i++) { + if (i > 0) + ret = ret + ":"; + uint16_t num = (field8[i*2] << 8) + field8[i*2+1]; + ret = ret + String::num_int64(num, 16); + }; + + return ret; + }; } -IP_Address::IP_Address(const String& p_string) { +static void _parse_hex(const String& p_string, int p_start, uint8_t* p_dst) { + + uint16_t ret = 0; + for (int i=p_start; i<p_start + 4; i++) { + + if (i >= p_string.length()) { + break; + }; + + int n = 0; + CharType c = p_string[i]; + if (c >= '0' && c <= '9') { + + n = c - '0'; + } else if (c >= 'a' && c <= 'f') { + n = 10 + (c - 'a'); + } else if (c >= 'A' && c <= 'F') { + n = 10 + (c - 'A'); + } else if (c == ':') { + break; + } else { + ERR_EXPLAIN("Invalid character in ipv6 address: " + p_string); + ERR_FAIL(); + }; + ret = ret << 4; + ret += n; + }; + + p_dst[0] = ret >> 8; + p_dst[1] = ret & 0xff; +}; + +void IP_Address::_parse_ipv6(const String& p_string) { + + static const int parts_total = 8; + int parts[parts_total] = {0}; + int parts_count = 0; + bool part_found = false; + bool part_skip = false; + bool part_ipv4 = false; + int parts_idx = 0; + + for (int i=0; i<p_string.length(); i++) { + + CharType c = p_string[i]; + if (c == ':') { + + if (i == 0) { + continue; // next must be a ":" + }; + if (!part_found) { + part_skip = true; + parts[parts_idx++] = -1; + }; + part_found = false; + } else if (c == '.') { + + part_ipv4 = true; + + } else if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { + if (!part_found) { + parts[parts_idx++] = i; + part_found = true; + ++parts_count; + }; + } else { + + ERR_EXPLAIN("Invalid character in IPv6 address: " + p_string); + ERR_FAIL(); + }; + }; + + int parts_extra = 0; + if (part_skip) { + parts_extra = parts_total - parts_count; + }; + + int idx = 0; + for (int i=0; i<parts_idx; i++) { - host=0; - int slices = p_string.get_slice_count("."); + if (parts[i] == -1) { + + for (int j=0; j<parts_extra; j++) { + field16[idx++] = 0; + }; + continue; + }; + + if (part_ipv4 && i == parts_idx - 1) { + _parse_ipv4(p_string, parts[i], (uint8_t*)&field16[idx]); // should be the last one + } else { + _parse_hex(p_string, parts[i], (uint8_t*)&(field16[idx++])); + }; + }; + +}; + +void IP_Address::_parse_ipv4(const String& p_string, int p_start, uint8_t* p_ret) { + + String ip; + if (p_start != 0) { + ip = p_string.substr(p_start, p_string.length() - p_start); + } else { + ip = p_string; + }; + + int slices = ip.get_slice_count("."); if (slices!=4) { - ERR_EXPLAIN("Invalid IP Address String: "+p_string); + ERR_EXPLAIN("Invalid IP Address String: "+ip); ERR_FAIL(); } for(int i=0;i<4;i++) { - - field[i]=p_string.get_slicec('.',i).to_int(); + p_ret[i]=ip.get_slicec('.',i).to_int(); } +}; + +void IP_Address::clear() { + + memset(&field8[0], 0, sizeof(field8)); +}; + +IP_Address::IP_Address(const String& p_string) { + + clear(); + if (p_string.find(":") >= 0) { + + _parse_ipv6(p_string); + type = TYPE_IPV6; + } else { + + _parse_ipv4(p_string, 0, &field8[0]); + type = TYPE_IPV4; + }; } -IP_Address::IP_Address(uint8_t p_a,uint8_t p_b,uint8_t p_c,uint8_t p_d) { +_FORCE_INLINE_ static void _32_to_buf(uint8_t* p_dst, uint32_t p_n) { + + p_dst[0] = (p_n >> 24) & 0xff; + p_dst[1] = (p_n >> 16) & 0xff; + p_dst[2] = (p_n >> 8) & 0xff; + p_dst[3] = (p_n >> 0) & 0xff; +}; + +IP_Address::IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, IP_Address::AddrType p_type) { + + type = p_type; + memset(&field8[0], 0, sizeof(field8)); + if (p_type == TYPE_IPV4) { + field8[0]=p_a; + field8[1]=p_b; + field8[2]=p_c; + field8[3]=p_d; + } else if (type == TYPE_IPV6) { + + _32_to_buf(&field8[0], p_a); + _32_to_buf(&field8[4], p_b); + _32_to_buf(&field8[8], p_c); + _32_to_buf(&field8[12], p_d); + } else { + type = TYPE_NONE; + ERR_EXPLAIN("Invalid type specified for IP_Address (use TYPE_IPV4 or TYPE_IPV6"); + ERR_FAIL(); + }; - field[0]=p_a; - field[1]=p_b; - field[2]=p_c; - field[3]=p_d; } diff --git a/core/io/ip_address.h b/core/io/ip_address.h index 1292311729..fe13d70611 100644 --- a/core/io/ip_address.h +++ b/core/io/ip_address.h @@ -33,22 +33,48 @@ struct IP_Address { +public: + enum AddrType { + TYPE_NONE = 0, + TYPE_IPV4 = 1, + TYPE_IPV6 = 2, + + TYPE_ANY = 3, + }; + + AddrType type; + union { - uint8_t field[4]; - uint32_t host; + uint8_t field8[16]; + uint16_t field16[8]; + uint32_t field32[4]; }; +protected: + void _parse_ipv6(const String& p_string); + void _parse_ipv4(const String& p_string, int p_start, uint8_t* p_ret); + +public: //operator Variant() const; bool operator==(const IP_Address& p_ip) const { - return host==p_ip.host; + for (int i=0; i<4; i++) + if (field32[i] != p_ip.field32[i]) + return false; + return true; } bool operator!=(const IP_Address& p_ip) const { - return host!=p_ip.host; + for (int i=0; i<4; i++) + if (field32[i] != p_ip.field32[i]) + return true; + return false; } + + void clear(); + operator String() const; IP_Address(const String& p_string); - IP_Address(uint8_t p_a,uint8_t p_b,uint8_t p_c,uint8_t p_d); - IP_Address() { host=0; } + IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, AddrType p_type=TYPE_IPV4); + IP_Address() { clear(); type=TYPE_NONE; } }; diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index efc619e414..018dc77d91 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -29,14 +29,9 @@ #include "packet_peer_udp.h" #include "io/ip.h" - PacketPeerUDP* (*PacketPeerUDP::_create)()=NULL; -int PacketPeerUDP::_get_packet_address() const { - - IP_Address ip = get_packet_address(); - return ip.host; -} +VARIANT_ENUM_CAST(IP_Address::AddrType); String PacketPeerUDP::_get_packet_ip() const { @@ -65,7 +60,7 @@ void PacketPeerUDP::_bind_methods() { ObjectTypeDB::bind_method(_MD("wait:Error"),&PacketPeerUDP::wait); ObjectTypeDB::bind_method(_MD("is_listening"),&PacketPeerUDP::is_listening); ObjectTypeDB::bind_method(_MD("get_packet_ip"),&PacketPeerUDP::_get_packet_ip); - ObjectTypeDB::bind_method(_MD("get_packet_address"),&PacketPeerUDP::_get_packet_address); + //ObjectTypeDB::bind_method(_MD("get_packet_address"),&PacketPeerUDP::_get_packet_address); ObjectTypeDB::bind_method(_MD("get_packet_port"),&PacketPeerUDP::get_packet_port); ObjectTypeDB::bind_method(_MD("set_send_address","host","port"),&PacketPeerUDP::_set_send_address); diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index 70d92834fc..c0806a9e6a 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -40,14 +40,13 @@ protected: static PacketPeerUDP* (*_create)(); static void _bind_methods(); - int _get_packet_address() const; String _get_packet_ip() const; virtual Error _set_send_address(const String& p_address,int p_port); public: - virtual Error listen(int p_port,int p_recv_buffer_size=65536)=0; + virtual Error listen(int p_port, IP_Address::AddrType p_address_type = IP_Address::TYPE_IPV4, int p_recv_buffer_size=65536)=0; virtual void close()=0; virtual Error wait()=0; virtual bool is_listening() const=0; diff --git a/tools/pck/pck_packer.cpp b/core/io/pck_packer.cpp index 04b88ea028..04b88ea028 100644 --- a/tools/pck/pck_packer.cpp +++ b/core/io/pck_packer.cpp diff --git a/tools/pck/pck_packer.h b/core/io/pck_packer.h index b1182335e2..b1182335e2 100644 --- a/tools/pck/pck_packer.h +++ b/core/io/pck_packer.h diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp index 274d20a48a..53d6e900f3 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -30,6 +30,8 @@ TCP_Server* (*TCP_Server::_create)()=NULL; +VARIANT_ENUM_CAST(IP_Address::AddrType); + Ref<TCP_Server> TCP_Server::create_ref() { if (!_create) @@ -44,19 +46,19 @@ TCP_Server* TCP_Server::create() { return _create(); } -Error TCP_Server::_listen(uint16_t p_port,DVector<String> p_accepted_hosts) { +Error TCP_Server::_listen(uint16_t p_port, IP_Address::AddrType p_type, DVector<String> p_accepted_hosts) { List<String> hosts; for(int i=0;i<p_accepted_hosts.size();i++) hosts.push_back(p_accepted_hosts.get(i)); - return listen(p_port,hosts.size()?&hosts:NULL); + return listen(p_port,p_type, hosts.size()?&hosts:NULL); } void TCP_Server::_bind_methods() { - ObjectTypeDB::bind_method(_MD("listen","port","accepted_hosts"),&TCP_Server::_listen,DEFVAL(DVector<String>())); + ObjectTypeDB::bind_method(_MD("listen","port","accepted_hosts"),&TCP_Server::_listen,DEFVAL(IP_Address::TYPE_IPV4), DEFVAL(DVector<String>())); ObjectTypeDB::bind_method(_MD("is_connection_available"),&TCP_Server::is_connection_available); ObjectTypeDB::bind_method(_MD("take_connection"),&TCP_Server::take_connection); ObjectTypeDB::bind_method(_MD("stop"),&TCP_Server::stop); diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h index 512a7e640a..883a3ef2f6 100644 --- a/core/io/tcp_server.h +++ b/core/io/tcp_server.h @@ -41,11 +41,11 @@ protected: static TCP_Server* (*_create)(); //bind helper - Error _listen(uint16_t p_port,DVector<String> p_accepted_hosts=DVector<String>()); + Error _listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_IPV4 ,DVector<String> p_accepted_hosts=DVector<String>()); static void _bind_methods(); public: - virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL)=0; + virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_IPV4, const List<String> *p_accepted_hosts=NULL)=0; virtual bool is_connection_available() const=0; virtual Ref<StreamPeerTCP> take_connection()=0; diff --git a/core/math/SCsub b/core/math/SCsub index 7b4a6acbc0..c2731d60e6 100644 --- a/core/math/SCsub +++ b/core/math/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.core_sources,"*.cpp") diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp new file mode 100644 index 0000000000..5bbbbdaa5a --- /dev/null +++ b/core/math/a_star.cpp @@ -0,0 +1,412 @@ +#include "a_star.h" +#include "geometry.h" + + +int AStar::get_available_point_id() const { + + if (points.empty()) { + return 1; + } + + return points.back()->key()+1; +} + +void AStar::add_point(int p_id, const Vector3 &p_pos, float p_weight_scale) { + ERR_FAIL_COND(p_id<0); + if (!points.has(p_id)) { + Point *pt = memnew( Point ); + pt->id=p_id; + pt->pos=p_pos; + pt->weight_scale=p_weight_scale; + pt->prev_point=NULL; + pt->last_pass=0; + points[p_id]=pt; + } else { + points[p_id]->pos=p_pos; + points[p_id]->weight_scale=p_weight_scale; + } +} + +Vector3 AStar::get_point_pos(int p_id) const{ + + ERR_FAIL_COND_V(!points.has(p_id),Vector3()); + + return points[p_id]->pos; + +} +float AStar::get_point_weight_scale(int p_id) const{ + + ERR_FAIL_COND_V(!points.has(p_id),0); + + return points[p_id]->weight_scale; + +} +void AStar::remove_point(int p_id){ + + ERR_FAIL_COND(!points.has(p_id)); + + Point* p = points[p_id]; + + for(int i=0;i<p->neighbours.size();i++) { + + Segment s(p_id,p->neighbours[i]->id); + segments.erase(s); + p->neighbours[i]->neighbours.erase(p); + } + + memdelete(p); + points.erase(p_id); +} + +void AStar::connect_points(int p_id,int p_with_id){ + + ERR_FAIL_COND(!points.has(p_id)); + ERR_FAIL_COND(!points.has(p_with_id)); + ERR_FAIL_COND(p_id==p_with_id); + + + Point* a = points[p_id]; + Point* b = points[p_with_id]; + a->neighbours.push_back(b); + b->neighbours.push_back(a); + + Segment s(p_id,p_with_id); + if (s.from==p_id) { + s.from_point=a; + s.to_point=b; + } else { + s.from_point=b; + s.to_point=a; + } + + segments.insert(s); + + +} +void AStar::disconnect_points(int p_id,int p_with_id){ + + Segment s(p_id,p_with_id); + ERR_FAIL_COND(!segments.has(s)); + + + segments.erase(s); + + Point *a = points[p_id]; + Point *b = points[p_with_id]; + a->neighbours.erase(b); + b->neighbours.erase(a); + +} +bool AStar::are_points_connected(int p_id,int p_with_id) const{ + + Segment s(p_id,p_with_id); + return segments.has(s); +} + +void AStar::clear(){ + + for (const Map<int,Point*>::Element *E=points.front();E;E=E->next()) { + + memdelete(E->get()); + } + segments.clear(); + points.clear(); +} + + +int AStar::get_closest_point(const Vector3& p_point) const{ + + int closest_id=-1; + float closest_dist=1e20; + + for (const Map<int,Point*>::Element *E=points.front();E;E=E->next()) { + + float d = p_point.distance_squared_to(E->get()->pos); + if (closest_id<0 || d<closest_dist) { + closest_dist=d; + closest_id=E->key(); + } + } + + return closest_id; + + +} +Vector3 AStar::get_closest_pos_in_segment(const Vector3& p_point) const { + + float closest_dist = 1e20; + bool found=false; + Vector3 closest_point; + + + for (const Set<Segment>::Element *E=segments.front();E;E=E->next()) { + + Vector3 segment[2]={ + E->get().from_point->pos, + E->get().to_point->pos, + }; + + Vector3 p = Geometry::get_closest_point_to_segment(p_point,segment); + float d = p_point.distance_squared_to(p); + if (!found || d<closest_dist) { + + closest_point=p; + closest_dist=d; + found=true; + } + } + + return closest_point; +} + +bool AStar::_solve(Point* begin_point, Point* end_point) { + + pass++; + + SelfList<Point>::List open_list; + + bool found_route=false; + + + for(int i=0;i<begin_point->neighbours.size();i++) { + + Point *n = begin_point->neighbours[i]; + n->prev_point=begin_point; + n->distance=n->pos.distance_to(begin_point->pos); + n->distance*=n->weight_scale; + n->last_pass=pass; + open_list.add(&n->list); + + if (end_point==n) { + found_route=true; + break; + } + } + + while(!found_route) { + + if (open_list.first()==NULL) { + //could not find path sadly + break; + } + //check open list + + SelfList<Point> *least_cost_point=NULL; + float least_cost=1e30; + + //this could be faster (cache previous results) + for (SelfList<Point> *E=open_list.first();E;E=E->next()) { + + Point *p=E->self(); + + float cost=p->distance; + cost+=p->pos.distance_to(end_point->pos); + cost*=p->weight_scale; + + if (cost<least_cost) { + + least_cost_point=E; + least_cost=cost; + } + } + + + Point *p=least_cost_point->self(); + //open the neighbours for search + int es = p->neighbours.size(); + + for(int i=0;i<es;i++) { + + + Point* e=p->neighbours[i]; + + + float distance = p->pos.distance_to(e->pos) + p->distance; + distance*=e->weight_scale; + + + + if (e->last_pass==pass) { + //oh this was visited already, can we win the cost? + + if (e->distance>distance) { + + e->prev_point=p; + e->distance=distance; + } + } else { + //add to open neighbours + + e->prev_point=p; + e->distance=distance; + e->last_pass=pass; //mark as used + open_list.add(&e->list); + + if (e==end_point) { + //oh my reached end! stop algorithm + found_route=true; + break; + + } + + } + } + + if (found_route) + break; + + open_list.remove(least_cost_point); + } + + //clear the openf list + while(open_list.first()) { + open_list.remove( open_list.first() ); + } + + return found_route; + +} + +DVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { + + ERR_FAIL_COND_V(!points.has(p_from_id),DVector<Vector3>()); + ERR_FAIL_COND_V(!points.has(p_to_id),DVector<Vector3>()); + + + pass++; + + Point* a = points[p_from_id]; + Point* b = points[p_to_id]; + + if (a==b) { + DVector<Vector3> ret; + ret.push_back(a->pos); + return ret; + } + + + Point *begin_point=a; + Point *end_point=b; + + bool found_route=_solve(begin_point,end_point); + + if (!found_route) + return DVector<Vector3>(); + + //midpoints + Point *p=end_point; + int pc=1; //begin point + while(p!=begin_point) { + pc++; + p=p->prev_point; + } + + DVector<Vector3> path; + path.resize(pc); + + { + DVector<Vector3>::Write w = path.write(); + + Point *p=end_point; + int idx=pc-1; + while(p!=begin_point) { + w[idx--]=p->pos; + p=p->prev_point; + } + + w[0]=p->pos; //assign first + + } + + return path; + +} + + +DVector<int> AStar::get_id_path(int p_from_id, int p_to_id) { + + ERR_FAIL_COND_V(!points.has(p_from_id),DVector<int>()); + ERR_FAIL_COND_V(!points.has(p_to_id),DVector<int>()); + + + pass++; + + Point* a = points[p_from_id]; + Point* b = points[p_to_id]; + + if (a==b) { + DVector<int> ret; + ret.push_back(a->id); + return ret; + } + + + Point *begin_point=a; + Point *end_point=b; + + bool found_route=_solve(begin_point,end_point); + + if (!found_route) + return DVector<int>(); + + //midpoints + Point *p=end_point; + int pc=1; //begin point + while(p!=begin_point) { + pc++; + p=p->prev_point; + } + + DVector<int> path; + path.resize(pc); + + { + DVector<int>::Write w = path.write(); + + p=end_point; + int idx=pc-1; + while(p!=begin_point) { + w[idx--]=p->id; + p=p->prev_point; + } + + w[0]=p->id; //assign first + + } + + return path; +} + +void AStar::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("get_available_point_id"),&AStar::get_available_point_id); + ObjectTypeDB::bind_method(_MD("add_point","id","pos","weight_scale"),&AStar::add_point,DEFVAL(1.0)); + ObjectTypeDB::bind_method(_MD("get_point_pos","id"),&AStar::get_point_pos); + ObjectTypeDB::bind_method(_MD("get_point_weight_scale","id"),&AStar::get_point_weight_scale); + ObjectTypeDB::bind_method(_MD("remove_point","id"),&AStar::remove_point); + + ObjectTypeDB::bind_method(_MD("connect_points","id","to_id"),&AStar::connect_points); + ObjectTypeDB::bind_method(_MD("disconnect_points","id","to_id"),&AStar::disconnect_points); + ObjectTypeDB::bind_method(_MD("are_points_connected","id","to_id"),&AStar::are_points_connected); + + ObjectTypeDB::bind_method(_MD("clear"),&AStar::clear); + + ObjectTypeDB::bind_method(_MD("get_closest_point","to_pos"),&AStar::get_closest_point); + ObjectTypeDB::bind_method(_MD("get_closest_pos_in_segment","to_pos"),&AStar::get_closest_pos_in_segment); + + ObjectTypeDB::bind_method(_MD("get_point_path","from_id","to_id"),&AStar::get_point_path); + ObjectTypeDB::bind_method(_MD("get_id_path","from_id","to_id"),&AStar::get_id_path); + +} + + +AStar::AStar() { + + pass=1; +} + + +AStar::~AStar() { + + pass=1; +} diff --git a/core/math/a_star.h b/core/math/a_star.h new file mode 100644 index 0000000000..a0517b5941 --- /dev/null +++ b/core/math/a_star.h @@ -0,0 +1,92 @@ +#ifndef ASTAR_H +#define ASTAR_H + +#include "reference.h" +#include "self_list.h" + +class AStar: public Reference { + + OBJ_TYPE(AStar,Reference) + + + uint64_t pass; + + struct Point { + + SelfList<Point> list; + + int id; + Vector3 pos; + float weight_scale; + uint64_t last_pass; + + Vector<Point*> neighbours; + + //used for pathfinding + Point *prev_point; + float distance; + + Point() : list(this) {} + }; + + Map<int,Point*> points; + + struct Segment { + union { + struct { + int32_t from; + int32_t to; + }; + uint64_t key; + }; + + Point *from_point; + Point *to_point; + + bool operator<(const Segment& p_s) const { return key<p_s.key; } + Segment() { key=0; } + Segment(int p_from,int p_to) { + if (p_from > p_to) { + SWAP(p_from,p_to); + } + + from=p_from; + to=p_to; + } + }; + + + Set<Segment> segments; + + bool _solve(Point *begin_point, Point *end_point); + +protected: + + static void _bind_methods(); +public: + + int get_available_point_id() const; + + void add_point(int p_id,const Vector3& p_pos,float p_weight_scale=1); + Vector3 get_point_pos(int p_id) const; + float get_point_weight_scale(int p_id) const; + void remove_point(int p_id); + + void connect_points(int p_id,int p_with_id); + void disconnect_points(int p_id,int p_with_id); + bool are_points_connected(int p_id,int p_with_id) const; + + void clear(); + + + int get_closest_point(const Vector3& p_point) const; + Vector3 get_closest_pos_in_segment(const Vector3& p_point) const; + + DVector<Vector3> get_point_path(int p_from_id, int p_to_id); + DVector<int> get_id_path(int p_from_id, int p_to_id); + + AStar(); + ~AStar(); +}; + +#endif // ASTAR_H diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp index 0e2060008c..e616f05914 100644 --- a/core/math/math_2d.cpp +++ b/core/math/math_2d.cpp @@ -424,7 +424,7 @@ Matrix32 Matrix32::inverse() const { void Matrix32::affine_invert() { - float det = elements[0][0]*elements[1][1] - elements[1][0]*elements[0][1]; + float det = basis_determinant(); ERR_FAIL_COND(det==0); float idet = 1.0 / det; @@ -475,18 +475,18 @@ Matrix32::Matrix32(real_t p_rot, const Vector2& p_pos) { elements[2]=p_pos; } -Vector2 Matrix32::get_scale() const { +Size2 Matrix32::get_scale() const { - return Vector2( elements[0].length(), elements[1].length() ); + return Size2( elements[0].length(), elements[1].length() ); } -void Matrix32::scale(const Vector2& p_scale) { +void Matrix32::scale(const Size2& p_scale) { elements[0]*=p_scale; elements[1]*=p_scale; elements[2]*=p_scale; } -void Matrix32::scale_basis(const Vector2& p_scale) { +void Matrix32::scale_basis(const Size2& p_scale) { elements[0]*=p_scale; elements[1]*=p_scale; @@ -501,7 +501,6 @@ void Matrix32::translate( const Vector2& p_translation ) { elements[2]+=basis_xform(p_translation); } - void Matrix32::orthonormalize() { // Gram-Schmidt Process @@ -550,11 +549,6 @@ void Matrix32::operator*=(const Matrix32& p_transform) { elements[2] = xform(p_transform.elements[2]); float x0,x1,y0,y1; -/* - x0 = p_transform.tdotx(elements[0]); - x1 = p_transform.tdoty(elements[0]); - y0 = p_transform.tdotx(elements[1]); - y1 = p_transform.tdoty(elements[1]);*/ x0 = tdotx(p_transform.elements[0]); x1 = tdoty(p_transform.elements[0]); @@ -576,7 +570,7 @@ Matrix32 Matrix32::operator*(const Matrix32& p_transform) const { } -Matrix32 Matrix32::scaled(const Vector2& p_scale) const { +Matrix32 Matrix32::scaled(const Size2& p_scale) const { Matrix32 copy=*this; copy.scale(p_scale); @@ -584,7 +578,7 @@ Matrix32 Matrix32::scaled(const Vector2& p_scale) const { } -Matrix32 Matrix32::basis_scaled(const Vector2& p_scale) const { +Matrix32 Matrix32::basis_scaled(const Size2& p_scale) const { Matrix32 copy=*this; copy.scale_basis(p_scale); @@ -629,8 +623,8 @@ Matrix32 Matrix32::interpolate_with(const Matrix32& p_transform, float p_c) cons real_t r1 = get_rotation(); real_t r2 = p_transform.get_rotation(); - Vector2 s1 = get_scale(); - Vector2 s2 = p_transform.get_scale(); + Size2 s1 = get_scale(); + Size2 s2 = p_transform.get_scale(); //slerp rotation Vector2 v1(Math::cos(r1), Math::sin(r1)); diff --git a/core/math/math_2d.h b/core/math/math_2d.h index 90aae9fe50..38c1ac9656 100644 --- a/core/math/math_2d.h +++ b/core/math/math_2d.h @@ -553,10 +553,8 @@ struct Rect2i { struct Matrix32 { - Vector2 elements[3]; - _FORCE_INLINE_ float tdotx(const Vector2& v) const { return elements[0][0] * v.x + elements[1][0] * v.y; } _FORCE_INLINE_ float tdoty(const Vector2& v) const { return elements[0][1] * v.x + elements[1][1] * v.y; } @@ -577,26 +575,25 @@ struct Matrix32 { _FORCE_INLINE_ void set_rotation_and_scale(real_t p_phi,const Size2& p_scale); void rotate(real_t p_phi); - void scale(const Vector2& p_scale); - void scale_basis(const Vector2& p_scale); + void scale(const Size2& p_scale); + void scale_basis(const Size2& p_scale); void translate( real_t p_tx, real_t p_ty); void translate( const Vector2& p_translation ); float basis_determinant() const; - Vector2 get_scale() const; + Size2 get_scale() const; _FORCE_INLINE_ const Vector2& get_origin() const { return elements[2]; } _FORCE_INLINE_ void set_origin(const Vector2& p_origin) { elements[2]=p_origin; } - Matrix32 scaled(const Vector2& p_scale) const; - Matrix32 basis_scaled(const Vector2& p_scale) const; + Matrix32 scaled(const Size2& p_scale) const; + Matrix32 basis_scaled(const Size2& p_scale) const; Matrix32 translated(const Vector2& p_offset) const; Matrix32 rotated(float p_phi) const; Matrix32 untranslated() const; - void orthonormalize(); Matrix32 orthonormalized() const; @@ -615,7 +612,6 @@ struct Matrix32 { _FORCE_INLINE_ Rect2 xform(const Rect2& p_vec) const; _FORCE_INLINE_ Rect2 xform_inv(const Rect2& p_vec) const; - operator String() const; Matrix32(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) { @@ -630,7 +626,6 @@ struct Matrix32 { Matrix32(real_t p_rot, const Vector2& p_pos); Matrix32() { elements[0][0]=1.0; elements[1][1]=1.0; } - }; bool Rect2::intersects_transformed(const Matrix32& p_xform, const Rect2& p_rect) const { diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp index 27b7c86675..1f5d5ed6b3 100644 --- a/core/math/triangulate.cpp +++ b/core/math/triangulate.cpp @@ -157,7 +157,10 @@ bool Triangulate::triangulate(const Vector<Vector2> &contour,Vector<int> &result m++; /* remove v from remaining polygon */ - for(s=v,t=v+1;t<nv;s++,t++) V[s] = V[t]; nv--; + for(s=v,t=v+1;t<nv;s++,t++) + V[s] = V[t]; + + nv--; /* resest error detection counter */ count = 2*nv; diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index 8afd73f482..fae3831dd6 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -49,13 +49,13 @@ void Vector3::set_axis(int p_axis,real_t p_value) { } real_t Vector3::get_axis(int p_axis) const { - ERR_FAIL_INDEX_V(p_axis,3,0); - return operator[](p_axis); + ERR_FAIL_INDEX_V(p_axis,3,0); + return operator[](p_axis); } int Vector3::min_axis() const { - return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2); + return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2); } int Vector3::max_axis() const { @@ -65,19 +65,15 @@ int Vector3::max_axis() const { void Vector3::snap(float p_val) { - x+=p_val/2.0; - x-=Math::fmod(x,p_val); - y+=p_val/2.0; - y-=Math::fmod(y,p_val); - z+=p_val/2.0; - z-=Math::fmod(z,p_val); - + x=Math::stepify(x,p_val); + y=Math::stepify(y,p_val); + z=Math::stepify(z,p_val); } Vector3 Vector3::snapped(float p_val) const { - Vector3 v=*this; - v.snap(p_val); - return v; + Vector3 v=*this; + v.snap(p_val); + return v; } diff --git a/core/math/vector3.h b/core/math/vector3.h index 910446023a..06840be5e7 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -63,77 +63,78 @@ struct Vector3 { return coord[p_axis]; } - void set_axis(int p_axis,real_t p_value); - real_t get_axis(int p_axis) const; + void set_axis(int p_axis,real_t p_value); + real_t get_axis(int p_axis) const; - int min_axis() const; - int max_axis() const; + int min_axis() const; + int max_axis() const; - _FORCE_INLINE_ real_t length() const; - _FORCE_INLINE_ real_t length_squared() const; + _FORCE_INLINE_ real_t length() const; + _FORCE_INLINE_ real_t length_squared() const; - _FORCE_INLINE_ void normalize(); - _FORCE_INLINE_ Vector3 normalized() const; - _FORCE_INLINE_ Vector3 inverse() const; + _FORCE_INLINE_ void normalize(); + _FORCE_INLINE_ Vector3 normalized() const; + _FORCE_INLINE_ Vector3 inverse() const; _FORCE_INLINE_ void zero(); - void snap(float p_val); - Vector3 snapped(float p_val) const; + void snap(float p_val); + Vector3 snapped(float p_val) const; void rotate(const Vector3& p_axis,float p_phi); Vector3 rotated(const Vector3& p_axis,float p_phi) const; - /* Static Methods between 2 vector3s */ + /* Static Methods between 2 vector3s */ - _FORCE_INLINE_ Vector3 linear_interpolate(const Vector3& p_b,float p_t) const; + _FORCE_INLINE_ Vector3 linear_interpolate(const Vector3& p_b,float p_t) const; Vector3 cubic_interpolate(const Vector3& p_b,const Vector3& p_pre_a, const Vector3& p_post_b,float p_t) const; Vector3 cubic_interpolaten(const Vector3& p_b,const Vector3& p_pre_a, const Vector3& p_post_b,float p_t) const; - _FORCE_INLINE_ Vector3 cross(const Vector3& p_b) const; - _FORCE_INLINE_ real_t dot(const Vector3& p_b) const; + _FORCE_INLINE_ Vector3 cross(const Vector3& p_b) const; + _FORCE_INLINE_ real_t dot(const Vector3& p_b) const; - _FORCE_INLINE_ Vector3 abs() const; - _FORCE_INLINE_ Vector3 floor() const; - _FORCE_INLINE_ Vector3 ceil() const; + _FORCE_INLINE_ Vector3 abs() const; + _FORCE_INLINE_ Vector3 floor() const; + _FORCE_INLINE_ Vector3 ceil() const; - _FORCE_INLINE_ real_t distance_to(const Vector3& p_b) const; - _FORCE_INLINE_ real_t distance_squared_to(const Vector3& p_b) const; + _FORCE_INLINE_ real_t distance_to(const Vector3& p_b) const; + _FORCE_INLINE_ real_t distance_squared_to(const Vector3& p_b) const; + _FORCE_INLINE_ real_t angle_to(const Vector3& p_b) const; _FORCE_INLINE_ Vector3 slide(const Vector3& p_vec) const; _FORCE_INLINE_ Vector3 reflect(const Vector3& p_vec) const; - /* Operators */ + /* Operators */ - _FORCE_INLINE_ Vector3& operator+=(const Vector3& p_v); - _FORCE_INLINE_ Vector3 operator+(const Vector3& p_v) const; - _FORCE_INLINE_ Vector3& operator-=(const Vector3& p_v); - _FORCE_INLINE_ Vector3 operator-(const Vector3& p_v) const; - _FORCE_INLINE_ Vector3& operator*=(const Vector3& p_v); - _FORCE_INLINE_ Vector3 operator*(const Vector3& p_v) const; - _FORCE_INLINE_ Vector3& operator/=(const Vector3& p_v); - _FORCE_INLINE_ Vector3 operator/(const Vector3& p_v) const; + _FORCE_INLINE_ Vector3& operator+=(const Vector3& p_v); + _FORCE_INLINE_ Vector3 operator+(const Vector3& p_v) const; + _FORCE_INLINE_ Vector3& operator-=(const Vector3& p_v); + _FORCE_INLINE_ Vector3 operator-(const Vector3& p_v) const; + _FORCE_INLINE_ Vector3& operator*=(const Vector3& p_v); + _FORCE_INLINE_ Vector3 operator*(const Vector3& p_v) const; + _FORCE_INLINE_ Vector3& operator/=(const Vector3& p_v); + _FORCE_INLINE_ Vector3 operator/(const Vector3& p_v) const; - _FORCE_INLINE_ Vector3& operator*=(real_t p_scalar); - _FORCE_INLINE_ Vector3 operator*(real_t p_scalar) const; - _FORCE_INLINE_ Vector3& operator/=(real_t p_scalar); - _FORCE_INLINE_ Vector3 operator/(real_t p_scalar) const; + _FORCE_INLINE_ Vector3& operator*=(real_t p_scalar); + _FORCE_INLINE_ Vector3 operator*(real_t p_scalar) const; + _FORCE_INLINE_ Vector3& operator/=(real_t p_scalar); + _FORCE_INLINE_ Vector3 operator/(real_t p_scalar) const; - _FORCE_INLINE_ Vector3 operator-() const; + _FORCE_INLINE_ Vector3 operator-() const; - _FORCE_INLINE_ bool operator==(const Vector3& p_v) const; - _FORCE_INLINE_ bool operator!=(const Vector3& p_v) const; - _FORCE_INLINE_ bool operator<(const Vector3& p_v) const; + _FORCE_INLINE_ bool operator==(const Vector3& p_v) const; + _FORCE_INLINE_ bool operator!=(const Vector3& p_v) const; + _FORCE_INLINE_ bool operator<(const Vector3& p_v) const; _FORCE_INLINE_ bool operator<=(const Vector3& p_v) const; operator String() const; - _FORCE_INLINE_ Vector3() { x=y=z=0; } - _FORCE_INLINE_ Vector3(real_t p_x,real_t p_y,real_t p_z) { x=p_x; y=p_y; z=p_z; } + _FORCE_INLINE_ Vector3() { x=y=z=0; } + _FORCE_INLINE_ Vector3(real_t p_x,real_t p_y,real_t p_z) { x=p_x; y=p_y; z=p_z; } }; @@ -151,11 +152,12 @@ Vector3 Vector3::cross(const Vector3& p_b) const { (x * p_b.y) - (y * p_b.x) ); - return ret; + return ret; } + real_t Vector3::dot(const Vector3& p_b) const { - return x*p_b.x + y*p_b.y + z*p_b.z; + return x*p_b.x + y*p_b.y + z*p_b.z; } Vector3 Vector3::abs() const { @@ -180,115 +182,119 @@ Vector3 Vector3::linear_interpolate(const Vector3& p_b,float p_t) const { y+(p_t * (p_b.y-y)), z+(p_t * (p_b.z-z)) ); - } - - real_t Vector3::distance_to(const Vector3& p_b) const { + return (p_b-*this).length(); } + real_t Vector3::distance_squared_to(const Vector3& p_b) const { - return (p_b-*this).length_squared(); + return (p_b-*this).length_squared(); +} + +real_t Vector3::angle_to(const Vector3& p_b) const { + + return Math::acos(this->dot(p_b) / Math::sqrt(this->length_squared() * p_b.length_squared())); } /* Operators */ Vector3& Vector3::operator+=(const Vector3& p_v) { - x+=p_v.x; - y+=p_v.y; - z+=p_v.z; - return *this; + x+=p_v.x; + y+=p_v.y; + z+=p_v.z; + return *this; } + Vector3 Vector3::operator+(const Vector3& p_v) const { - return Vector3(x+p_v.x, y+p_v.y, z+ p_v.z); + return Vector3(x+p_v.x, y+p_v.y, z+ p_v.z); } Vector3& Vector3::operator-=(const Vector3& p_v) { - x-=p_v.x; - y-=p_v.y; - z-=p_v.z; - return *this; + x-=p_v.x; + y-=p_v.y; + z-=p_v.z; + return *this; } Vector3 Vector3::operator-(const Vector3& p_v) const { - return Vector3(x-p_v.x, y-p_v.y, z- p_v.z); + return Vector3(x-p_v.x, y-p_v.y, z- p_v.z); } - - Vector3& Vector3::operator*=(const Vector3& p_v) { - x*=p_v.x; - y*=p_v.y; - z*=p_v.z; - return *this; + x*=p_v.x; + y*=p_v.y; + z*=p_v.z; + return *this; } Vector3 Vector3::operator*(const Vector3& p_v) const { - return Vector3(x*p_v.x, y*p_v.y, z* p_v.z); + return Vector3(x*p_v.x, y*p_v.y, z* p_v.z); } Vector3& Vector3::operator/=(const Vector3& p_v) { - x/=p_v.x; - y/=p_v.y; - z/=p_v.z; - return *this; + x/=p_v.x; + y/=p_v.y; + z/=p_v.z; + return *this; } + Vector3 Vector3::operator/(const Vector3& p_v) const { - return Vector3(x/p_v.x, y/p_v.y, z/ p_v.z); + return Vector3(x/p_v.x, y/p_v.y, z/ p_v.z); } Vector3& Vector3::operator*=(real_t p_scalar) { - x*=p_scalar; - y*=p_scalar; - z*=p_scalar; - return *this; + x*=p_scalar; + y*=p_scalar; + z*=p_scalar; + return *this; } _FORCE_INLINE_ Vector3 operator*(real_t p_scalar, const Vector3& p_vec) { + return p_vec * p_scalar; } Vector3 Vector3::operator*(real_t p_scalar) const { - return Vector3( x*p_scalar, y*p_scalar, z*p_scalar); + return Vector3( x*p_scalar, y*p_scalar, z*p_scalar); } Vector3& Vector3::operator/=(real_t p_scalar) { - x/=p_scalar; - y/=p_scalar; - z/=p_scalar; - return *this; + x/=p_scalar; + y/=p_scalar; + z/=p_scalar; + return *this; } Vector3 Vector3::operator/(real_t p_scalar) const { - return Vector3( x/p_scalar, y/p_scalar, z/p_scalar); + return Vector3( x/p_scalar, y/p_scalar, z/p_scalar); } Vector3 Vector3::operator-() const { - return Vector3( -x, -y, -z ); + return Vector3( -x, -y, -z ); } - bool Vector3::operator==(const Vector3& p_v) const { - return (x==p_v.x && y==p_v.y && z==p_v.z); + return (x==p_v.x && y==p_v.y && z==p_v.z); } bool Vector3::operator!=(const Vector3& p_v) const { - return (x!=p_v.x || y!=p_v.y || z!=p_v.z); + return (x!=p_v.x || y!=p_v.y || z!=p_v.z); } bool Vector3::operator<(const Vector3& p_v) const { @@ -298,9 +304,9 @@ bool Vector3::operator<(const Vector3& p_v) const { return z<p_v.z; else return y<p_v.y; - } else + } else { return x<p_v.x; - + } } bool Vector3::operator<=(const Vector3& p_v) const { @@ -310,9 +316,9 @@ bool Vector3::operator<=(const Vector3& p_v) const { return z<=p_v.z; else return y<p_v.y; - } else + } else { return x<p_v.x; - + } } _FORCE_INLINE_ Vector3 vec3_cross(const Vector3& p_a, const Vector3& p_b) { @@ -333,6 +339,7 @@ real_t Vector3::length() const { return Math::sqrt(x2+y2+z2); } + real_t Vector3::length_squared() const { real_t x2=x*x; @@ -340,27 +347,25 @@ real_t Vector3::length_squared() const { real_t z2=z*z; return x2+y2+z2; - } void Vector3::normalize() { - real_t l=length(); - if (l==0) { - + real_t l=length(); + if (l==0) { x=y=z=0; - } else { - + } else { x/=l; y/=l; z/=l; - } + } } + Vector3 Vector3::normalized() const { - Vector3 v=*this; - v.normalize(); - return v; + Vector3 v=*this; + v.normalize(); + return v; } Vector3 Vector3::inverse() const { @@ -377,10 +382,10 @@ Vector3 Vector3::slide(const Vector3& p_vec) const { return p_vec - *this * this->dot(p_vec); } + Vector3 Vector3::reflect(const Vector3& p_vec) const { return p_vec - *this * this->dot(p_vec) * 2.0; - } #endif diff --git a/core/method_bind.h b/core/method_bind.h index 072953743c..04ff5c22c6 100644 --- a/core/method_bind.h +++ b/core/method_bind.h @@ -52,6 +52,7 @@ enum MethodFlags { METHOD_FLAG_REVERSE=16, // used for events METHOD_FLAG_VIRTUAL=32, METHOD_FLAG_FROM_SCRIPT=64, + METHOD_FLAG_VARARG=128, METHOD_FLAGS_DEFAULT=METHOD_FLAG_NORMAL, }; @@ -229,7 +230,7 @@ public: Vector<StringName> get_argument_names() const; #endif void set_hint_flags(uint32_t p_hint) { hint_flags=p_hint; } - uint32_t get_hint_flags() const { return hint_flags|(is_const()?METHOD_FLAG_CONST:0); } + uint32_t get_hint_flags() const { return hint_flags|(is_const()?METHOD_FLAG_CONST:0)|(is_vararg()?METHOD_FLAG_VARARG:0); } virtual String get_instance_type() const=0; _FORCE_INLINE_ int get_argument_count() const { return argument_count; }; @@ -267,7 +268,7 @@ public: _FORCE_INLINE_ int get_method_id() const { return method_id; } _FORCE_INLINE_ bool is_const() const { return _const; } _FORCE_INLINE_ bool has_return() const { return _returns; } - + virtual bool is_vararg() const { return false; } void set_default_arguments(const Vector<Variant>& p_defargs); @@ -277,7 +278,7 @@ public: template<class T> -class MethodBindNative : public MethodBind { +class MethodBindVarArg : public MethodBind { public: typedef Variant (T::*NativeCall)(const Variant**,int ,Variant::CallError &); protected: @@ -319,7 +320,9 @@ public: } #ifdef PTRCALL_ENABLED - virtual void ptrcall(Object* p_object,const void** p_args,void* r_ret) {} //todo + virtual void ptrcall(Object* p_object,const void** p_args,void* r_ret) { + ERR_FAIL(); //can't call + } //todo #endif @@ -327,14 +330,16 @@ public: virtual bool is_const() const { return false; } virtual String get_instance_type() const { return T::get_type_static(); } - MethodBindNative() { call_method=NULL; _set_returns(true);} + virtual bool is_vararg() const { return true; } + + MethodBindVarArg() { call_method=NULL; _set_returns(true);} }; template<class T > -MethodBind* create_native_method_bind( Variant (T::*p_method)(const Variant**,int ,Variant::CallError &), const MethodInfo& p_info ) { +MethodBind* create_vararg_method_bind( Variant (T::*p_method)(const Variant**,int ,Variant::CallError &), const MethodInfo& p_info ) { - MethodBindNative<T > * a = memnew( (MethodBindNative<T >) ); + MethodBindVarArg<T > * a = memnew( (MethodBindVarArg<T >) ); a->set_method(p_method); a->set_method_info(p_info); return a; diff --git a/core/object.cpp b/core/object.cpp index b036efa501..9a1e9be8d5 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -1215,6 +1215,15 @@ void Object::emit_signal(const StringName& p_name,const Variant** p_args,int p_a Signal *s = signal_map.getptr(p_name); if (!s) { +#ifdef DEBUG_ENABLED + bool signal_is_valid = ObjectTypeDB::has_signal(get_type_name(),p_name); + //check in script + if (!signal_is_valid && !script.is_null() && !Ref<Script>(script)->has_script_signal(p_name)) { + ERR_EXPLAIN("Can't emit non-existing signal " + String("\"")+p_name+"\"."); + ERR_FAIL(); + } +#endif + //not connected? just return return; } @@ -1644,6 +1653,7 @@ void Object::_clear_internal_resource_paths(const Variant &p_var) { _clear_internal_resource_paths(d[E->get()]); } } break; + default: {} } } @@ -1693,42 +1703,26 @@ void Object::_bind_methods() { MethodInfo mi; mi.name="emit_signal"; mi.arguments.push_back( PropertyInfo( Variant::STRING, "signal")); - Vector<Variant> defargs; - for(int i=0;i<VARIANT_ARG_MAX;i++) { - mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); - defargs.push_back(Variant()); - } - - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"emit_signal",&Object::_emit_signal,mi,defargs); + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"emit_signal",&Object::_emit_signal,mi); } { MethodInfo mi; mi.name="call"; mi.arguments.push_back( PropertyInfo( Variant::STRING, "method")); - Vector<Variant> defargs; - for(int i=0;i<10;i++) { - mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); - defargs.push_back(Variant()); - } - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call:Variant",&Object::_call_bind,mi,defargs); + + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call:Variant",&Object::_call_bind,mi); } { MethodInfo mi; mi.name="call_deferred"; mi.arguments.push_back( PropertyInfo( Variant::STRING, "method")); - Vector<Variant> defargs; - for(int i=0;i<VARIANT_ARG_MAX;i++) { - mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); - defargs.push_back(Variant()); - } - - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_deferred",&Object::_call_deferred_bind,mi,defargs); + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_deferred",&Object::_call_deferred_bind,mi); } ObjectTypeDB::bind_method(_MD("callv:Variant","method","arg_array"),&Object::callv); diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp index b6a69e3bd4..e121dc9e98 100644 --- a/core/object_type_db.cpp +++ b/core/object_type_db.cpp @@ -189,6 +189,14 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,co #endif + +ObjectTypeDB::APIType ObjectTypeDB::current_api=API_CORE; + +void ObjectTypeDB::set_current_api(APIType p_api) { + + current_api=p_api; +} + HashMap<StringName,ObjectTypeDB::TypeInfo,StringNameHasher> ObjectTypeDB::types; HashMap<StringName,StringName,StringNameHasher> ObjectTypeDB::resource_base_extensions; HashMap<StringName,StringName,StringNameHasher> ObjectTypeDB::compat_types; @@ -258,6 +266,171 @@ StringName ObjectTypeDB::type_inherits_from(const StringName& p_type) { return ti->inherits; } +ObjectTypeDB::APIType ObjectTypeDB::get_api_type(const StringName &p_type) { + + OBJTYPE_LOCK; + + TypeInfo *ti = types.getptr(p_type); + ERR_FAIL_COND_V(!ti,API_NONE); + return ti->api; +} + +uint64_t ObjectTypeDB::get_api_hash(APIType p_api) { + +#ifdef DEBUG_METHODS_ENABLED + + uint64_t hash = hash_djb2_one_64(HashMapHahserDefault::hash(VERSION_FULL_NAME)); + + List<StringName> names; + + const StringName *k=NULL; + + while((k=types.next(k))) { + + names.push_back(*k); + } + //must be alphabetically sorted for hash to compute + names.sort_custom<StringName::AlphCompare>(); + + for (List<StringName>::Element *E=names.front();E;E=E->next()) { + + TypeInfo *t = types.getptr(E->get()); + ERR_FAIL_COND_V(!t,0); + if (t->api!=p_api) + continue; + hash = hash_djb2_one_64(t->name.hash(),hash); + hash = hash_djb2_one_64(t->inherits.hash(),hash); + + { //methods + + List<StringName> snames; + + k=NULL; + + while((k=t->method_map.next(k))) { + + snames.push_back(*k); + } + + snames.sort_custom<StringName::AlphCompare>(); + + for (List<StringName>::Element *F=snames.front();F;F=F->next()) { + + MethodBind *mb = t->method_map[F->get()]; + hash = hash_djb2_one_64( mb->get_name().hash(), hash); + hash = hash_djb2_one_64( mb->get_argument_count(), hash); + hash = hash_djb2_one_64( mb->get_argument_type(-1), hash); //return + + for(int i=0;i<mb->get_argument_count();i++) { + hash = hash_djb2_one_64( mb->get_argument_info(i).type, hash ); + hash = hash_djb2_one_64( mb->get_argument_info(i).name.hash(), hash ); + hash = hash_djb2_one_64( mb->get_argument_info(i).hint, hash ); + hash = hash_djb2_one_64( mb->get_argument_info(i).hint_string.hash(), hash ); + } + + hash = hash_djb2_one_64( mb->get_default_argument_count(), hash); + + for(int i=0;i<mb->get_default_argument_count();i++) { + //hash should not change, i hope for tis + Variant da = mb->get_default_argument(i); + hash = hash_djb2_one_64( da.hash(), hash ); + } + + hash = hash_djb2_one_64( mb->get_hint_flags(), hash); + + } + } + + + { //constants + + List<StringName> snames; + + k=NULL; + + while((k=t->constant_map.next(k))) { + + snames.push_back(*k); + } + + snames.sort_custom<StringName::AlphCompare>(); + + for (List<StringName>::Element *F=snames.front();F;F=F->next()) { + + hash = hash_djb2_one_64(F->get().hash(), hash); + hash = hash_djb2_one_64( t->constant_map[F->get()], hash); + } + } + + + { //signals + + List<StringName> snames; + + k=NULL; + + while((k=t->signal_map.next(k))) { + + snames.push_back(*k); + } + + snames.sort_custom<StringName::AlphCompare>(); + + for (List<StringName>::Element *F=snames.front();F;F=F->next()) { + + MethodInfo &mi = t->signal_map[F->get()]; + hash = hash_djb2_one_64( F->get().hash(), hash); + for(int i=0;i<mi.arguments.size();i++) { + hash = hash_djb2_one_64( mi.arguments[i].type, hash); + } + } + } + + { //properties + + List<StringName> snames; + + k=NULL; + + while((k=t->property_setget.next(k))) { + + snames.push_back(*k); + } + + snames.sort_custom<StringName::AlphCompare>(); + + for (List<StringName>::Element *F=snames.front();F;F=F->next()) { + + PropertySetGet *psg=t->property_setget.getptr(F->get()); + + hash = hash_djb2_one_64( F->get().hash(), hash); + hash = hash_djb2_one_64( psg->setter.hash(), hash); + hash = hash_djb2_one_64( psg->getter.hash(), hash); + + } + } + + //property list + for (List<PropertyInfo>::Element *F=t->property_list.front();F;F=F->next()) { + + hash = hash_djb2_one_64( F->get().name.hash(), hash); + hash = hash_djb2_one_64( F->get().type, hash); + hash = hash_djb2_one_64( F->get().hint, hash); + hash = hash_djb2_one_64( F->get().hint_string.hash(), hash); + hash = hash_djb2_one_64( F->get().usage, hash); + } + + + } + + + return hash; +#else + return 0; +#endif + +} + bool ObjectTypeDB::type_exists(const StringName &p_type) { OBJTYPE_LOCK; @@ -309,6 +482,7 @@ void ObjectTypeDB::_add_type2(const StringName& p_type, const StringName& p_inhe TypeInfo &ti=types[name]; ti.name=name; ti.inherits=p_inherits; + ti.api=current_api; if (ti.inherits) { @@ -866,21 +1040,14 @@ MethodBind* ObjectTypeDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind , c Vector<Variant> defvals; -#define PARSE_DEFVAL(m_defval)\ -if (d##m_defval.used) defvals.insert(0,d##m_defval.val);\ -else goto set_defvals; - defvals.resize(p_defcount); for(int i=0;i<p_defcount;i++) { defvals[i]=*p_defs[p_defcount-i-1]; } - set_defvals: - p_bind->set_default_arguments(defvals); p_bind->set_hint_flags(p_flags); -#undef PARSE_DEFVAL return p_bind; } diff --git a/core/object_type_db.h b/core/object_type_db.h index 3fcd38aa31..9e9029ff2f 100644 --- a/core/object_type_db.h +++ b/core/object_type_db.h @@ -109,7 +109,13 @@ static _FORCE_INLINE_ const char* _MD(const char* m_name, ...) { return m_name; #endif class ObjectTypeDB { - +public: + enum APIType { + API_CORE, + API_EDITOR, + API_NONE + }; +public: struct PropertySetGet { int index; @@ -122,6 +128,7 @@ class ObjectTypeDB { struct TypeInfo { + APIType api; TypeInfo *inherits_ptr; HashMap<StringName,MethodBind*,StringNameHasher> method_map; HashMap<StringName,int,StringNameHasher> constant_map; @@ -161,6 +168,7 @@ class ObjectTypeDB { #endif + static APIType current_api; static void _add_type2(const StringName& p_type, const StringName& p_inherits); public: @@ -236,6 +244,9 @@ public: static bool is_type(const StringName &p_type,const StringName& p_inherits); static bool can_instance(const StringName &p_type); static Object *instance(const StringName &p_type); + static APIType get_api_type(const StringName &p_type); + + static uint64_t get_api_hash(APIType p_api); #if 0 template<class N, class M> @@ -415,13 +426,13 @@ public: #endif template<class M> - static MethodBind* bind_native_method(uint32_t p_flags, StringName p_name, M p_method,const MethodInfo& p_info=MethodInfo(),const Vector<Variant>& p_default_args=Vector<Variant>()) { + static MethodBind* bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method,const MethodInfo& p_info=MethodInfo(),const Vector<Variant>& p_default_args=Vector<Variant>()) { GLOBAL_LOCK_FUNCTION; - MethodBind *bind = create_native_method_bind(p_method,p_info); + MethodBind *bind = create_vararg_method_bind(p_method,p_info); ERR_FAIL_COND_V(!bind,NULL); String rettype; @@ -499,6 +510,8 @@ public: static void add_compatibility_type(const StringName& p_type,const StringName& p_fallback); static void init(); + + static void set_current_api(APIType p_api); static void cleanup(); }; diff --git a/core/os/SCsub b/core/os/SCsub index 7b4a6acbc0..c2731d60e6 100644 --- a/core/os/SCsub +++ b/core/os/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.core_sources,"*.cpp") diff --git a/core/os/input.cpp b/core/os/input.cpp index 401ab7ffe2..4ab57a84ea 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -64,6 +64,10 @@ void Input::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_connected_joysticks"),&Input::get_connected_joysticks); ObjectTypeDB::bind_method(_MD("get_joy_vibration_strength", "device"), &Input::get_joy_vibration_strength); ObjectTypeDB::bind_method(_MD("get_joy_vibration_duration", "device"), &Input::get_joy_vibration_duration); + ObjectTypeDB::bind_method(_MD("get_joy_button_string", "button_index"), &Input::get_joy_button_string); + ObjectTypeDB::bind_method(_MD("get_joy_button_index_from_string", "button"), &Input::get_joy_button_index_from_string); + ObjectTypeDB::bind_method(_MD("get_joy_axis_string", "axis_index"), &Input::get_joy_axis_string); + ObjectTypeDB::bind_method(_MD("get_joy_axis_index_from_string", "axis"), &Input::get_joy_axis_index_from_string); ObjectTypeDB::bind_method(_MD("start_joy_vibration", "device", "weak_magnitude", "strong_magnitude", "duration"), &Input::start_joy_vibration, DEFVAL(0)); ObjectTypeDB::bind_method(_MD("stop_joy_vibration", "device"), &Input::stop_joy_vibration); ObjectTypeDB::bind_method(_MD("get_accelerometer"),&Input::get_accelerometer); @@ -90,7 +94,7 @@ void Input::get_argument_options(const StringName& p_function,int p_idx,List<Str #ifdef TOOLS_ENABLED String pf=p_function; - if (p_idx==0 && (pf=="is_action_pressed" || pf=="action_press" || pf=="action_release")) { + if (p_idx==0 && (pf=="is_action_pressed" || pf=="action_press" || pf=="action_release" || pf=="is_action_just_pressed" || pf=="is_action_just_released")) { List<PropertyInfo> pinfo; Globals::get_singleton()->get_property_list(&pinfo); diff --git a/core/os/input.h b/core/os/input.h index 665fb4ad99..d8f3be09df 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -96,6 +96,11 @@ public: virtual void set_custom_mouse_cursor(const RES& p_cursor,const Vector2& p_hotspot=Vector2())=0; virtual void set_mouse_in_window(bool p_in_window)=0; + virtual String get_joy_button_string(int p_button)=0; + virtual String get_joy_axis_string(int p_axis)=0; + virtual int get_joy_button_index_from_string(String p_button)=0; + virtual int get_joy_axis_index_from_string(String p_axis)=0; + Input(); }; diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp index 9d920724e1..7350be824a 100644 --- a/core/os/input_event.cpp +++ b/core/os/input_event.cpp @@ -50,7 +50,8 @@ bool InputEvent::operator==(const InputEvent &p_event) const { case MOUSE_MOTION: return mouse_motion.x == p_event.mouse_motion.x && mouse_motion.y == p_event.mouse_motion.y - && mouse_motion.relative_x == p_event.mouse_motion.relative_y + && mouse_motion.relative_x == p_event.mouse_motion.relative_x + && mouse_motion.relative_y == p_event.mouse_motion.relative_y && mouse_motion.button_mask == p_event.mouse_motion.button_mask && key.mod == p_event.key.mod; case MOUSE_BUTTON: @@ -204,7 +205,7 @@ bool InputEvent::is_pressed() const { case MOUSE_BUTTON: return mouse_button.pressed; case JOYSTICK_BUTTON: return joy_button.pressed; case SCREEN_TOUCH: return screen_touch.pressed; - case JOYSTICK_MOTION: return InputMap::get_singleton()->event_is_joy_motion_action_pressed(*this); + case JOYSTICK_MOTION: return ABS(joy_motion.axis_value) > 0.5; case ACTION: return action.pressed; default: {} } diff --git a/core/os/os.h b/core/os/os.h index 8e9293b3c8..c2b46a5420 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -372,6 +372,7 @@ public: virtual void set_screen_orientation(ScreenOrientation p_orientation); ScreenOrientation get_screen_orientation() const; + virtual void enable_for_stealing_focus(ProcessID pid) {} virtual void move_window_to_foreground() {} virtual void debug_break(); diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 3de26573f4..c3a127afb9 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -33,6 +33,7 @@ #include "io/config_file.h" #include "os/main_loop.h" #include "io/packet_peer.h" +#include "math/a_star.h" #include "globals.h" #include "object_type_db.h" #include "geometry.h" @@ -48,6 +49,7 @@ #include "os/input.h" #include "core/io/xml_parser.h" #include "io/http_client.h" +#include "io/pck_packer.h" #include "packed_data_container.h" #include "func_ref.h" #include "input_map.h" @@ -145,8 +147,11 @@ void register_core_types() { ObjectTypeDB::register_type<ConfigFile>(); + ObjectTypeDB::register_type<PCKPacker>(); + ObjectTypeDB::register_type<PackedDataContainer>(); ObjectTypeDB::register_virtual_type<PackedDataContainerRef>(); + ObjectTypeDB::register_type<AStar>(); ip = IP::create(); diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index 99d1e22c07..6d685d3c43 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -134,6 +134,8 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { ERR_FAIL(); } + OS::get_singleton()->enable_for_stealing_focus(Globals::get_singleton()->get("editor_pid")); + packet_peer_stream->put_var("debug_enter"); packet_peer_stream->put_var(2); packet_peer_stream->put_var(p_can_continue); @@ -219,7 +221,8 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { if (F->get().get_type()==Variant::OBJECT) { packet_peer_stream->put_var("*"+E->get()); - packet_peer_stream->put_var(safe_get_instance_id(F->get())); + String pretty_print = F->get().operator String(); + packet_peer_stream->put_var(pretty_print.ascii().get_data()); } else { packet_peer_stream->put_var(E->get()); packet_peer_stream->put_var(F->get()); @@ -242,7 +245,8 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { if (F->get().get_type()==Variant::OBJECT) { packet_peer_stream->put_var("*"+E->get()); - packet_peer_stream->put_var(safe_get_instance_id(F->get())); + String pretty_print = F->get().operator String(); + packet_peer_stream->put_var(pretty_print.ascii().get_data()); } else { packet_peer_stream->put_var(E->get()); packet_peer_stream->put_var(F->get()); @@ -271,6 +275,7 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { set_depth(-1); set_lines_left(-1); + OS::get_singleton()->move_window_to_foreground(); break; } else if (command=="break") { ERR_PRINT("Got break when already broke!"); diff --git a/core/script_language.h b/core/script_language.h index 1b037e908c..53af4c74d1 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -122,6 +122,7 @@ public: virtual void get_script_method_list(List<MethodInfo> *p_list) const=0; virtual void get_script_property_list(List<PropertyInfo> *p_list) const=0; + virtual int get_member_line(const StringName& p_member) const { return 0; } Script() {} }; @@ -207,7 +208,26 @@ public: virtual bool has_named_classes() const=0; virtual int find_function(const String& p_function,const String& p_code) const=0; virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const=0; + virtual Error complete_code(const String& p_code, const String& p_base_path, Object*p_owner,List<String>* r_options,String& r_call_hint) { return ERR_UNAVAILABLE; } + + struct LookupResult { + enum Type { + RESULT_SCRIPT_LOCATION, + RESULT_CLASS, + RESULT_CLASS_CONSTANT, + RESULT_CLASS_PROPERTY, + RESULT_CLASS_METHOD + }; + Type type; + Ref<Script> script; + String class_name; + String class_member; + int location; + }; + + virtual Error lookup_code(const String& p_code, const String& p_symbol,const String& p_base_path, Object*p_owner,LookupResult& r_result) { return ERR_UNAVAILABLE; } + virtual void auto_indent_code(String& p_code,int p_from_line,int p_to_line) const=0; virtual void add_global_constant(const StringName& p_variable,const Variant& p_value)=0; diff --git a/core/translation.cpp b/core/translation.cpp index 4592d00598..4d81073fe6 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -779,6 +779,11 @@ Vector<String> TranslationServer::get_all_locale_names(){ } +static String get_trimmed_locale(const String& p_locale) { + + return p_locale.substr(0,2); +} + static bool is_valid_locale(const String& p_locale) { const char **ptr=locale_list; @@ -839,9 +844,20 @@ void Translation::_set_messages(const DVector<String>& p_messages){ void Translation::set_locale(const String& p_locale) { - ERR_EXPLAIN("Invalid Locale: "+p_locale); - ERR_FAIL_COND(!is_valid_locale(p_locale)); - locale=p_locale; + // replaces '-' with '_' for macOS Sierra-style locales + String univ_locale = p_locale.replace("-", "_"); + + if(!is_valid_locale(univ_locale)) { + String trimmed_locale = get_trimmed_locale(univ_locale); + + ERR_EXPLAIN("Invalid Locale: "+trimmed_locale); + ERR_FAIL_COND(!is_valid_locale(trimmed_locale)); + + locale=trimmed_locale; + } + else { + locale=univ_locale; + } } void Translation::add_message( const StringName& p_src_text, const StringName& p_xlated_text ) { @@ -906,9 +922,20 @@ Translation::Translation() { void TranslationServer::set_locale(const String& p_locale) { - ERR_EXPLAIN("Invalid Locale: "+p_locale); - ERR_FAIL_COND(!is_valid_locale(p_locale)); - locale=p_locale; + // replaces '-' with '_' for macOS Sierra-style locales + String univ_locale = p_locale.replace("-", "_"); + + if(!is_valid_locale(univ_locale)) { + String trimmed_locale = get_trimmed_locale(univ_locale); + + ERR_EXPLAIN("Invalid Locale: "+trimmed_locale); + ERR_FAIL_COND(!is_valid_locale(trimmed_locale)); + + locale=trimmed_locale; + } + else { + locale=univ_locale; + } } String TranslationServer::get_locale() const { diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index 99740b365c..e8a71d4991 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -490,13 +490,9 @@ void UndoRedo::_bind_methods() { mi.name="add_do_method"; mi.arguments.push_back( PropertyInfo( Variant::OBJECT, "object")); mi.arguments.push_back( PropertyInfo( Variant::STRING, "method")); - Vector<Variant> defargs; - for(int i=0;i<VARIANT_ARG_MAX;++i) { - mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); - defargs.push_back(Variant()); - } - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"add_do_method",&UndoRedo::_add_do_method,mi,defargs); + + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"add_do_method",&UndoRedo::_add_do_method,mi); } { @@ -504,13 +500,9 @@ void UndoRedo::_bind_methods() { mi.name="add_undo_method"; mi.arguments.push_back( PropertyInfo( Variant::OBJECT, "object")); mi.arguments.push_back( PropertyInfo( Variant::STRING, "method")); - Vector<Variant> defargs; - for(int i=0;i<VARIANT_ARG_MAX;++i) { - mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); - defargs.push_back(Variant()); - } - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"add_undo_method",&UndoRedo::_add_undo_method,mi,defargs); + + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"add_undo_method",&UndoRedo::_add_undo_method,mi); } ObjectTypeDB::bind_method(_MD("add_do_property","object", "property", "value:Variant"),&UndoRedo::add_do_property); diff --git a/core/ustring.cpp b/core/ustring.cpp index 0d887210c3..f9c10615b3 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -1543,11 +1543,11 @@ String::String(const StrRange& p_range) { copy_from(p_range.c_str,p_range.len); } -int String::hex_to_int() const { +int String::hex_to_int(bool p_with_prefix) const { int l = length(); - if (l<3) - return 0; + if (p_with_prefix && l<3) + return 0; const CharType *s=ptr(); @@ -1556,15 +1556,16 @@ int String::hex_to_int() const { if (sign<0) { s++; l--; - if (l<2) + if (p_with_prefix && l<2) return 0; } - if (s[0]!='0' || s[1]!='x') - return 0; - - s+=2; - l-=2; + if (p_with_prefix) { + if (s[0]!='0' || s[1]!='x') + return 0; + s+=2; + l-=2; + }; int hex=0; @@ -3073,6 +3074,11 @@ String String::simplify_path() const { } s =s.replace("\\","/"); + while(true){ // in case of using 2 or more slash + String compare = s.replace("//","/"); + if (s==compare) break; + else s=compare; + } Vector<String> dirs = s.split("/",false); for(int i=0;i<dirs.size();i++) { @@ -3173,7 +3179,7 @@ bool String::is_valid_identifier() const { //kind of poor should be rewritten properly -String String::world_wrap(int p_chars_per_line) const { +String String::word_wrap(int p_chars_per_line) const { int from=0; int last_space=0; @@ -3505,6 +3511,36 @@ bool String::is_valid_integer() const { } +bool String::is_valid_hex_number(bool p_with_prefix) const { + + int from = 0; + int len = length(); + + if (len!=1 && (operator[](0)=='+' || operator[](0)=='-')) + from++; + + if (p_with_prefix) { + + if (len < 2) + return false; + if (operator[](from) != '0' || operator[](from+1) != 'x') { + return false; + }; + from += 2; + }; + + for (int i=from; i<len; i++) { + + CharType c = operator[](i); + if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) + continue; + return false; + }; + + return true; +}; + + bool String::is_valid_float() const { int len = length(); @@ -3641,20 +3677,41 @@ bool String::is_valid_html_color() const { } + bool String::is_valid_ip_address() const { - Vector<String> ip = split("."); - if (ip.size()!=4) - return false; - for(int i=0;i<ip.size();i++) { + if (find(":") >= 0) { - String n = ip[i]; - if (!n.is_valid_integer()) - return false; - int val = n.to_int(); - if (val<0 || val>255) + Vector<String> ip = split(":"); + for (int i=0; i<ip.size(); i++) { + + String n = ip[i]; + if (n.empty()) + continue; + if (n.is_valid_hex_number(false)) { + int nint = n.hex_to_int(false); + if (nint < 0 || nint > 0xffff) + return false; + continue; + }; + if (!n.is_valid_ip_address()) + return false; + }; + + } else { + Vector<String> ip = split("."); + if (ip.size()!=4) return false; - } + for(int i=0;i<ip.size();i++) { + + String n = ip[i]; + if (!n.is_valid_integer()) + return false; + int val = n.to_int(); + if (val<0 || val>255) + return false; + } + }; return true; } diff --git a/core/ustring.h b/core/ustring.h index bb57b11d88..452f252857 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -144,7 +144,7 @@ public: bool is_numeric() const; double to_double() const; float to_float() const; - int hex_to_int() const; + int hex_to_int(bool p_with_prefix = true) const; int to_int() const; int64_t to_int64() const; @@ -218,7 +218,7 @@ public: String c_escape() const; String c_unescape() const; String json_escape() const; - String world_wrap(int p_chars_per_line) const; + String word_wrap(int p_chars_per_line) const; String percent_encode() const; String percent_decode() const; @@ -226,6 +226,7 @@ public: bool is_valid_identifier() const; bool is_valid_integer() const; bool is_valid_float() const; + bool is_valid_hex_number(bool p_with_prefix) const; bool is_valid_html_color() const; bool is_valid_ip_address() const; diff --git a/core/variant.cpp b/core/variant.cpp index a78c07d819..b2afc9d080 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -429,6 +429,7 @@ bool Variant::can_convert(Variant::Type p_type_from,Variant::Type p_type_to) { return true; i++; } + } else if (invalid_types) { @@ -439,6 +440,8 @@ bool Variant::can_convert(Variant::Type p_type_from,Variant::Type p_type_to) { return false; i++; } + + return true; } return false; @@ -457,7 +460,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from,Variant::Type p_type_ }; const Type *valid_types=NULL; - const Type *invalid_types=NULL; switch(p_type_to) { case BOOL: { @@ -679,16 +681,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from,Variant::Type p_type_ return true; i++; } - } else if (invalid_types) { - - - int i=0; - while(invalid_types[i]!=NIL) { - - if (p_type_from==invalid_types[i]) - return false; - i++; - } } return false; diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 5337b6ba04..9b6fa27cf4 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -54,10 +54,10 @@ struct _VariantCall { int arg_count; Vector<Variant> default_args; Vector<Variant::Type> arg_types; - -#ifdef DEBUG_ENABLED Vector<StringName> arg_names; Variant::Type return_type; + +#ifdef DEBUG_ENABLED bool returns; #endif VariantFunc func; @@ -346,6 +346,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var VCALL_LOCALMEM0R(Vector2,angle); // VCALL_LOCALMEM1R(Vector2,cross); VCALL_LOCALMEM0R(Vector2,abs); + VCALL_LOCALMEM1R(Vector2,clamped); VCALL_LOCALMEM0R(Rect2,get_area); VCALL_LOCALMEM1R(Rect2,intersects); @@ -374,6 +375,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var VCALL_LOCALMEM0R(Vector3, ceil); VCALL_LOCALMEM1R(Vector3, distance_to); VCALL_LOCALMEM1R(Vector3, distance_squared_to); + VCALL_LOCALMEM1R(Vector3, angle_to); VCALL_LOCALMEM1R(Vector3, slide); VCALL_LOCALMEM1R(Vector3, reflect); @@ -464,8 +466,8 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var VCALL_LOCALMEM0R(Array,hash); VCALL_LOCALMEM1(Array,push_back); VCALL_LOCALMEM1(Array,push_front); - VCALL_LOCALMEM0(Array,pop_back); - VCALL_LOCALMEM0(Array,pop_front); + VCALL_LOCALMEM0R(Array,pop_back); + VCALL_LOCALMEM0R(Array,pop_front); VCALL_LOCALMEM1(Array,append); VCALL_LOCALMEM1(Array,resize); VCALL_LOCALMEM2(Array,insert); @@ -518,6 +520,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var VCALL_LOCALMEM1(ByteArray,append); VCALL_LOCALMEM1(ByteArray,append_array); VCALL_LOCALMEM0(ByteArray,invert); + VCALL_LOCALMEM2R(ByteArray,subarray); VCALL_LOCALMEM0R(IntArray,size); VCALL_LOCALMEM2(IntArray,set); @@ -1456,6 +1459,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC1(VECTOR2,VECTOR2,Vector2,reflect,VECTOR2,"vec",varray()); //ADDFUNC1(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray()); ADDFUNC0(VECTOR2,VECTOR2,Vector2,abs,varray()); + ADDFUNC1(VECTOR2,VECTOR2,Vector2,clamped,REAL,"length",varray()); ADDFUNC0(RECT2,REAL,Rect2,get_area,varray()); ADDFUNC1(RECT2,BOOL,Rect2,intersects,RECT2,"b",varray()); @@ -1484,6 +1488,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC0(VECTOR3,VECTOR3,Vector3,ceil,varray()); ADDFUNC1(VECTOR3,REAL,Vector3,distance_to,VECTOR3,"b",varray()); ADDFUNC1(VECTOR3,REAL,Vector3,distance_squared_to,VECTOR3,"b",varray()); + ADDFUNC1(VECTOR3,REAL,Vector3,angle_to,VECTOR3,"to",varray()); ADDFUNC1(VECTOR3,VECTOR3,Vector3,slide,VECTOR3,"by",varray()); ADDFUNC1(VECTOR3,VECTOR3,Vector3,reflect,VECTOR3,"by",varray()); @@ -1592,6 +1597,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC2(RAW_ARRAY,INT,ByteArray,insert,INT,"idx",INT,"byte",varray()); ADDFUNC1(RAW_ARRAY,NIL,ByteArray,resize,INT,"idx",varray()); ADDFUNC0(RAW_ARRAY,NIL,ByteArray,invert,varray()); + ADDFUNC2(RAW_ARRAY,RAW_ARRAY,ByteArray,subarray,INT,"from",INT,"to",varray()); ADDFUNC0(RAW_ARRAY,STRING,ByteArray,get_string_from_ascii,varray()); ADDFUNC0(RAW_ARRAY,STRING,ByteArray,get_string_from_utf8,varray()); @@ -1814,6 +1820,11 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl _VariantCall::add_constant(Variant::IMAGE,"INTERPOLATE_NEAREST",Image::INTERPOLATE_NEAREST); _VariantCall::add_constant(Variant::IMAGE,"INTERPOLATE_BILINEAR",Image::INTERPOLATE_BILINEAR); _VariantCall::add_constant(Variant::IMAGE,"INTERPOLATE_CUBIC",Image::INTERPOLATE_CUBIC); + + _VariantCall::add_constant(Variant::INT, "IP_TYPE_NONE", IP_Address::TYPE_NONE); + _VariantCall::add_constant(Variant::INT, "IP_TYPE_IPV4", IP_Address::TYPE_IPV4); + _VariantCall::add_constant(Variant::INT, "IP_TYPE_IPV6", IP_Address::TYPE_IPV6); + _VariantCall::add_constant(Variant::INT, "IP_TYPE_ANY", IP_Address::TYPE_ANY); } void unregister_variant_methods() { diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index 023605a952..5ed2415e36 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -986,7 +986,18 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in InputEvent ie; - if (id=="KEY") { + if (id=="NONE") { + + ie.type=InputEvent::NONE; + + get_token(p_stream,token,line,r_err_str); + + if (token.type!=TK_PARENTHESIS_CLOSE) { + r_err_str="Expected ')'"; + return ERR_PARSE_ERROR; + } + + } else if (id=="KEY") { get_token(p_stream,token,line,r_err_str); if (token.type!=TK_COMMA) { @@ -1166,16 +1177,16 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } else if (id=="IntArray") { - Vector<int32_t> args; - Error err = _parse_construct<int32_t>(p_stream,args,line,r_err_str); + Vector<int> args; + Error err = _parse_construct<int>(p_stream,args,line,r_err_str); if (err) return err; - DVector<int32_t> arr; + DVector<int> arr; { int len=args.size(); arr.resize(len); - DVector<int32_t>::Write w = arr.write(); + DVector<int>::Write w = arr.write(); for(int i=0;i<len;i++) { w[i]=int(args[i]); } @@ -2093,6 +2104,9 @@ Error VariantWriter::write(const Variant& p_variant, StoreStringFunc p_store_str case InputEvent::JOYSTICK_MOTION: { str+="JAXIS,"+itos(ev.joy_motion.axis)+","+itos(ev.joy_motion.axis_value); } break; + case InputEvent::NONE: { + str+="NONE"; + } break; default: {} } diff --git a/doc/base/classes.xml b/doc/base/classes.xml index 07fd9980e0..5eb021f6c0 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -2153,6 +2153,120 @@ <constants> </constants> </class> +<class name="AStar" inherits="Reference" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="add_point"> + <argument index="0" name="id" type="int"> + </argument> + <argument index="1" name="pos" type="Vector3"> + </argument> + <argument index="2" name="weight_scale" type="float" default="1"> + </argument> + <description> + </description> + </method> + <method name="are_points_connected" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <argument index="1" name="to_id" type="int"> + </argument> + <description> + </description> + </method> + <method name="clear"> + <description> + </description> + </method> + <method name="connect_points"> + <argument index="0" name="id" type="int"> + </argument> + <argument index="1" name="to_id" type="int"> + </argument> + <description> + </description> + </method> + <method name="disconnect_points"> + <argument index="0" name="id" type="int"> + </argument> + <argument index="1" name="to_id" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_available_point_id" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_closest_point" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="to_pos" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="get_closest_pos_in_segment" qualifiers="const"> + <return type="Vector3"> + </return> + <argument index="0" name="to_pos" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="get_id_path"> + <return type="IntArray"> + </return> + <argument index="0" name="from_id" type="int"> + </argument> + <argument index="1" name="to_id" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_point_path"> + <return type="Vector3Array"> + </return> + <argument index="0" name="from_id" type="int"> + </argument> + <argument index="1" name="to_id" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_point_pos" qualifiers="const"> + <return type="Vector3"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_point_weight_scale" qualifiers="const"> + <return type="float"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + </description> + </method> + <method name="remove_point"> + <argument index="0" name="id" type="int"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="AcceptDialog" inherits="WindowDialog" category="Core"> <brief_description> Base dialog for user notification. @@ -2221,6 +2335,12 @@ Register a [LineEdit] in the dialog. When the enter key is pressed, the dialog will be accepted. </description> </method> + <method name="set_child_rect"> + <argument index="0" name="child" type="Control"> + </argument> + <description> + </description> + </method> <method name="set_hide_on_ok"> <argument index="0" name="enabled" type="bool"> </argument> @@ -4018,7 +4138,7 @@ </argument> <argument index="2" name="area_shape" type="int"> </argument> - <argument index="3" name="area_shape" type="int"> + <argument index="3" name="self_shape" type="int"> </argument> <description> This signal triggers only once when an area enters this area. The first parameter is the area's [RID]. The second one is the area as an object. The third one is the index of the shape entering this area, and the fourth one is the index of the shape in this area that reported the entering. @@ -4038,7 +4158,7 @@ </argument> <argument index="2" name="area_shape" type="int"> </argument> - <argument index="3" name="area_shape" type="int"> + <argument index="3" name="self_shape" type="int"> </argument> <description> This signal triggers only once when an area exits this area. The first parameter is the area's [RID]. The second one is the area as an object. The third one is the index of the shape entering this area, and the fourth one is the index of the shape in this area that reported the entering. @@ -4360,7 +4480,7 @@ </argument> <argument index="2" name="area_shape" type="int"> </argument> - <argument index="3" name="area_shape" type="int"> + <argument index="3" name="self_shape" type="int"> </argument> <description> This signal triggers only once when an area enters this area. The first parameter is the area's [RID]. The second one is the area as an object. The third one is the index of the shape entering this area, and the fourth one is the index of the shape in this area that reported the entering. @@ -4380,7 +4500,7 @@ </argument> <argument index="2" name="area_shape" type="int"> </argument> - <argument index="3" name="area_shape" type="int"> + <argument index="3" name="self_shape" type="int"> </argument> <description> This signal triggers only once when an area exits this area. The first parameter is the area's [RID]. The second one is the area as an object. The third one is the index of the shape entering this area, and the fourth one is the index of the shape in this area that reported the entering. @@ -5339,18 +5459,6 @@ <constants> </constants> </class> -<class name="AudioStreamSpeex" inherits="AudioStream" category="Core"> - <brief_description> - Speex audio stream driver. - </brief_description> - <description> - Speex audio stream driver. Speex is very useful for compressed speech. It allows loading a very large amount of speech in memory at little IO/latency cost. - </description> - <methods> - </methods> - <constants> - </constants> -</class> <class name="BackBufferCopy" inherits="Node2D" category="Core"> <brief_description> Copies a region of the screen (or the whole screen) to a buffer so it can be accessed with the texscreen() shader instruction. @@ -6749,6 +6857,12 @@ <description> </description> </method> + <method name="get_custom_viewport" qualifiers="const"> + <return type="Viewport"> + </return> + <description> + </description> + </method> <method name="get_drag_margin" qualifiers="const"> <return type="float"> </return> @@ -6852,6 +6966,12 @@ <description> </description> </method> + <method name="set_custom_viewport"> + <argument index="0" name="viewport" type="Viewport"> + </argument> + <description> + </description> + </method> <method name="set_drag_margin"> <argument index="0" name="margin" type="int"> </argument> @@ -7554,6 +7674,12 @@ Canvas Item layer. [CanvasItem] nodes that are direct or indirect children of a [CanvasLayer] will be drawn in that layer. The layer is a numeric index that defines the draw order. The default 2D scene renders with index 0, so a [CanvasLayer] with index -1 will be drawn below, and one with index 1 will be drawn above. This is very useful for HUDs (in layer 1+ or above), or backgrounds (in layer -1 or below). </description> <methods> + <method name="get_custom_viewport" qualifiers="const"> + <return type="Viewport"> + </return> + <description> + </description> + </method> <method name="get_layer" qualifiers="const"> <return type="int"> </return> @@ -7596,13 +7722,6 @@ Return the base transform for this layer. </description> </method> - <method name="get_viewport" qualifiers="const"> - <return type="RID"> - </return> - <description> - Return the viewport RID for this layer. - </description> - </method> <method name="get_world_2d" qualifiers="const"> <return type="World2D"> </return> @@ -7610,6 +7729,12 @@ Return the [World2D] used by this layer. </description> </method> + <method name="set_custom_viewport"> + <argument index="0" name="viewport" type="Viewport"> + </argument> + <description> + </description> + </method> <method name="set_layer"> <argument index="0" name="layer" type="int"> </argument> @@ -8672,6 +8797,28 @@ <constants> </constants> </class> +<class name="ColorFrame" inherits="Control" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="get_frame_color" qualifiers="const"> + <return type="Color"> + </return> + <description> + </description> + </method> + <method name="set_frame_color"> + <argument index="0" name="color" type="Color"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="ColorPicker" inherits="BoxContainer" category="Core"> <brief_description> Color picker control. @@ -10871,7 +11018,7 @@ </return> <description> Initialise the stream used to list all files and directories using the [method get_next] function, closing the current opened stream if needed. Once the stream has been processed, it should typically be closed with [method list_dir_end]. - Return false if the stream could not be initialised. + Return true if the stream could not be initialised. </description> </method> <method name="list_dir_end"> @@ -11261,6 +11408,184 @@ </constant> </constants> </class> +<class name="EditorFileSystem" inherits="Node" category="Core"> + <brief_description> + Resource filesystem, as the editor sees it. + </brief_description> + <description> + This object holds information of all resources in the filesystem, their types, etc. + </description> + <methods> + <method name="get_file_type" qualifiers="const"> + <return type="String"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <description> + Get the type of the file, given the full path. + </description> + </method> + <method name="get_filesystem"> + <return type="EditorFileSystemDirectory"> + </return> + <description> + Get the root directory object. + </description> + </method> + <method name="get_path"> + <return type="EditorFileSystemDirectory"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <description> + </description> + </method> + <method name="get_scanning_progress" qualifiers="const"> + <return type="float"> + </return> + <description> + Return the scan progress for 0 to 1 if the FS is being scanned. + </description> + </method> + <method name="is_scanning" qualifiers="const"> + <return type="bool"> + </return> + <description> + Return true of the filesystem is being scanned. + </description> + </method> + <method name="scan"> + <description> + Scan the filesystem for changes. + </description> + </method> + <method name="scan_sources"> + <description> + Check if the source of any imported resource changed. + </description> + </method> + <method name="update_file"> + <argument index="0" name="path" type="String"> + </argument> + <description> + Update a file information. Call this if an external program (not Godot) modified the file. + </description> + </method> + </methods> + <signals> + <signal name="filesystem_changed"> + <description> + Emitted if the filesystem changed. + </description> + </signal> + <signal name="sources_changed"> + <argument index="0" name="exist" type="bool"> + </argument> + <description> + Emitted if the source of any imported file changed. + </description> + </signal> + </signals> + <constants> + </constants> +</class> +<class name="EditorFileSystemDirectory" inherits="Object" category="Core"> + <brief_description> + A diretory for the resource filesystem. + </brief_description> + <description> + </description> + <methods> + <method name="find_dir_index" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="name" type="String"> + </argument> + <description> + </description> + </method> + <method name="find_file_index" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="name" type="String"> + </argument> + <description> + </description> + </method> + <method name="get_file" qualifiers="const"> + <return type="String"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_file_count" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_file_path" qualifiers="const"> + <return type="String"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_file_type" qualifiers="const"> + <return type="String"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_name"> + <return type="String"> + </return> + <description> + </description> + </method> + <method name="get_parent"> + <return type="EditorFileSystemDirectory"> + </return> + <description> + </description> + </method> + <method name="get_path" qualifiers="const"> + <return type="String"> + </return> + <description> + </description> + </method> + <method name="get_subdir"> + <return type="Object"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_subdir_count" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="is_missing_sources" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="EditorImportPlugin" inherits="Reference" category="Core"> <brief_description> Import plugin for editor @@ -11459,14 +11784,24 @@ This function is used for plugins that edit specific object types (nodes or resources). It requests the editor to edit the given object. </description> </method> - <method name="forward_input_event" qualifiers="virtual"> + <method name="forward_canvas_input_event" qualifiers="virtual"> <return type="bool"> </return> - <argument index="0" name="event" type="InputEvent"> + <argument index="0" name="canvas_xform" type="Matrix32"> + </argument> + <argument index="1" name="event" type="InputEvent"> </argument> <description> - This is a low level function for plugins that edit a given object type derived from CanvasItem to capture the input in the 2D editor viewport. The function is only being called if your object is being edited. - Return true if you want to capture the input, otherwise false. + If your plugin is active (because handles() returned true to the object), any input interaction with the 2D canvas editor will be first forwarded here. The canvas transform (containing zoom and offset to transform to edited world coordinates) is provided, but the input supplied is in untransformed coordinates to the canvas editor. Return true if you want to eat this event and not pass it to the canvas editor. + </description> + </method> + <method name="forward_draw_over_canvas" qualifiers="virtual"> + <argument index="0" name="canvas_xform" type="Matrix32"> + </argument> + <argument index="1" name="canvas" type="Control"> + </argument> + <description> + This function is called every time the 2D canvas editor draws (which overlays over the edited scene). Drawing over the supplied control will draw over the edited scene. To convert from control coordinates to edited scene coordinates (including zoom and offset), a transform is also provided. If you require this control to be redraw, call [method update_canvas]. </description> </method> <method name="forward_spatial_input_event" qualifiers="virtual"> @@ -11503,6 +11838,13 @@ Get the general settings for the editor (the same window that appears in the Settings menu). </description> </method> + <method name="get_editor_viewport"> + <return type="Control"> + </return> + <description> + Get the main editor control. Use this as a parent for main screens. + </description> + </method> <method name="get_name" qualifiers="virtual"> <return type="String"> </return> @@ -11510,6 +11852,20 @@ Get the name of the editor plugin. For main scren plugins this is what will appear in the selector (which by default is 2D, 3D, Script). </description> </method> + <method name="get_resource_filesystem"> + <return type="EditorFileSystem"> + </return> + <description> + Get the filesystem cache for all resources in the project. + </description> + </method> + <method name="get_resource_previewer"> + <return type="EditorResourcePreview"> + </return> + <description> + Get tool for generating resource previews. + </description> + </method> <method name="get_selection"> <return type="EditorSelection"> </return> @@ -11554,6 +11910,25 @@ Return true if this is a main screen editor plugin (it goes in the main screen selector together with 2D, 3D, Script). </description> </method> + <method name="hide_bottom_panel"> + <description> + </description> + </method> + <method name="inspect_object"> + <argument index="0" name="object" type="Object"> + </argument> + <argument index="1" name="for_property" type="String" default=""""> + </argument> + <description> + Inspect an object in the inspector. + </description> + </method> + <method name="make_bottom_panel_item_visible"> + <argument index="0" name="item" type="Control"> + </argument> + <description> + </description> + </method> <method name="make_visible" qualifiers="virtual"> <argument index="0" name="visible" type="bool"> </argument> @@ -11621,6 +11996,11 @@ Restore the plugin GUI layout saved by [method EditorPlugin.get_window_layout]. </description> </method> + <method name="update_canvas"> + <description> + Updates the control used to draw the edited scene over the 2D canvas. This is used together with [method forward_canvas_input_event]. + </description> + </method> </methods> <constants> <constant name="CONTAINER_TOOLBAR" value="0"> @@ -11657,6 +12037,117 @@ </constant> </constants> </class> +<class name="EditorResourcePreview" inherits="Node" category="Core"> + <brief_description> + Helper to generate previews of reources or files. + </brief_description> + <description> + This object is used to generate previews for resources of files. + </description> + <methods> + <method name="add_preview_generator"> + <argument index="0" name="generator" type="EditorResourcePreviewGenerator"> + </argument> + <description> + Create an own, custom preview generator. + </description> + </method> + <method name="check_for_invalidation"> + <argument index="0" name="path" type="String"> + </argument> + <description> + Check if the resource changed, if so it will be invalidated and the corresponding signal emitted. + </description> + </method> + <method name="queue_edited_resource_preview"> + <argument index="0" name="resource" type="Resource"> + </argument> + <argument index="1" name="receiver" type="Object"> + </argument> + <argument index="2" name="receiver_func" type="String"> + </argument> + <argument index="3" name="userdata" type="Variant"> + </argument> + <description> + Queue a resource being edited for preview (using an instance). Once the preview is ready, your receiver.receiver_func will be called either containing the preview texture or an empty texure (if no preview was possible). Callback must have the format: (path,texture,userdata). Userdata can be anything. + </description> + </method> + <method name="queue_resource_preview"> + <argument index="0" name="path" type="String"> + </argument> + <argument index="1" name="receiver" type="Object"> + </argument> + <argument index="2" name="receiver_func" type="String"> + </argument> + <argument index="3" name="userdata" type="Variant"> + </argument> + <description> + Queue a resource file for preview (using a path). Once the preview is ready, your receiver.receiver_func will be called either containing the preview texture or an empty texure (if no preview was possible). Callback must have the format: (path,texture,userdata). Userdata can be anything. + </description> + </method> + <method name="remove_preview_generator"> + <argument index="0" name="generator" type="EditorResourcePreviewGenerator"> + </argument> + <description> + Remove a custom preview generator. + </description> + </method> + </methods> + <signals> + <signal name="preview_invalidated"> + <argument index="0" name="path" type="String"> + </argument> + <description> + If a preview was invalidated (changed) this signal will emit (using the path of the preview) + </description> + </signal> + </signals> + <constants> + </constants> +</class> +<class name="EditorResourcePreviewGenerator" inherits="Reference" category="Core"> + <brief_description> + Custom generator of previews. + </brief_description> + <description> + Custom code to generate previews. Please check "file_dialog/thumbnail_size" in EditorSettings to find out the right size to do previews at. + </description> + <methods> + <method name="generate" qualifiers="virtual"> + <return type="Texture"> + </return> + <argument index="0" name="from" type="Resource"> + </argument> + <description> + Generate a preview from a given resource. This must be always implemented. + Returning an empty texture is an OK way to fail and let another generator take care. + Care must be taken because this function is always called from a thread (not the main thread). + </description> + </method> + <method name="generate_from_path" qualifiers="virtual"> + <return type="Texture"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <description> + Generate a preview directly from a path, implementing this is optional, as default code will load and call generate() + Returning an empty texture is an OK way to fail and let another generator take care. + Care must be taken because this function is always called from a thread (not the main thread). + </description> + </method> + <method name="handles" qualifiers="virtual"> + <return type="bool"> + </return> + <argument index="0" name="type" type="String"> + </argument> + <description> + Return if your generator supports this resource type. + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="EditorScenePostImport" inherits="Reference" category="Core"> <brief_description> Base script for post-processing scenes being imported. @@ -11732,6 +12223,13 @@ Get the list of selectes nodes. </description> </method> + <method name="get_transformable_selected_nodes"> + <return type="Array"> + </return> + <description> + Get the list of selected nodes, optimized for transform operations (ie, moving them, rotating, etc). This list avoids situations where a node is selected and also chid/grandchild. + </description> + </method> <method name="remove_node"> <argument index="0" name="node" type="Node"> </argument> @@ -13189,31 +13687,10 @@ However, by creating a [FuncRef] using the [method @GDScript.funcref] function, a reference to a function in a given object can be created, passed around and called. </description> <methods> - <method name="call_func"> + <method name="call_func" qualifiers="vararg"> <return type="Variant"> </return> - <argument index="0" name="arg0" type="Variant" default="NULL"> - </argument> - <argument index="1" name="arg1" type="Variant" default="NULL"> - </argument> - <argument index="2" name="arg2" type="Variant" default="NULL"> - </argument> - <argument index="3" name="arg3" type="Variant" default="NULL"> - </argument> - <argument index="4" name="arg4" type="Variant" default="NULL"> - </argument> - <argument index="5" name="arg5" type="Variant" default="NULL"> - </argument> - <argument index="6" name="arg6" type="Variant" default="NULL"> - </argument> - <argument index="7" name="arg7" type="Variant" default="NULL"> - </argument> - <argument index="8" name="arg8" type="Variant" default="NULL"> - </argument> - <argument index="9" name="arg9" type="Variant" default="NULL"> - </argument> <description> - Call the referenced function with the given arguments. The argument count must correspond to the required number of arguments in the function. Returns the return value of the function call. </description> </method> <method name="set_function"> @@ -13290,7 +13767,7 @@ <description> </description> </method> - <method name="new"> + <method name="new" qualifiers="vararg"> <return type="Object"> </return> <description> @@ -14465,6 +14942,8 @@ </theme_item> <theme_item name="comment" type="StyleBox"> </theme_item> + <theme_item name="commentfocus" type="StyleBox"> + </theme_item> <theme_item name="defaultfocus" type="StyleBox"> </theme_item> <theme_item name="defaultframe" type="StyleBox"> @@ -15390,10 +15869,11 @@ </argument> <argument index="2" name="ssl_validate_domain" type="bool" default="true"> </argument> + <argument index="3" name="method" type="int" default="0"> + </argument> + <argument index="4" name="request_data" type="String" default=""""> + </argument> <description> - Make a HTTP GET request. The url is the complete url including "http://" or "https://" which will be parsed for a host and a port. - The custom_headers are HTTP request headers which will be used. If User-Agent is not specified a Godot specific will be used. - The ssl_validate_domain specifies if in case of HTTPS the server certificate should be verified. </description> </method> <method name="set_body_size_limit"> @@ -16023,6 +16503,8 @@ </argument> <argument index="2" name="radius" type="float"> </argument> + <argument index="3" name="add_uv" type="bool" default="true"> + </argument> <description> Simple helper to draw an uvsphere, with given latitudes, longitude and radius. </description> @@ -16124,7 +16606,7 @@ Add a new mapping entry (in SDL2 format) to the mapping database. Optionally update already connected devices. </description> </method> - <method name="get_accelerometer"> + <method name="get_accelerometer" qualifiers="const"> <return type="Vector3"> </return> <description> @@ -16138,14 +16620,14 @@ Returns an [Array] containing the device IDs of all currently connected joysticks. </description> </method> - <method name="get_gyroscope"> + <method name="get_gyroscope" qualifiers="const"> <return type="Vector3"> </return> <description> If the device has a gyroscope, this will return the rate of rotation in rad/s around a device's x, y, and z axis. </description> </method> - <method name="get_joy_axis"> + <method name="get_joy_axis" qualifiers="const"> <return type="float"> </return> <argument index="0" name="device" type="int"> @@ -16156,6 +16638,38 @@ Returns the current value of the joystick axis at given index (see JOY_* constants in [@Global Scope]) </description> </method> + <method name="get_joy_axis_index_from_string"> + <return type="int"> + </return> + <argument index="0" name="axis" type="String"> + </argument> + <description> + </description> + </method> + <method name="get_joy_axis_string"> + <return type="String"> + </return> + <argument index="0" name="axis_index" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_joy_button_index_from_string"> + <return type="int"> + </return> + <argument index="0" name="button" type="String"> + </argument> + <description> + </description> + </method> + <method name="get_joy_button_string"> + <return type="String"> + </return> + <argument index="0" name="button_index" type="int"> + </argument> + <description> + </description> + </method> <method name="get_joy_guid" qualifiers="const"> <return type="String"> </return> @@ -16192,7 +16706,7 @@ Returns the strength of the joystick vibration: x is the strength of the weak motor, and y is the strength of the strong motor. </description> </method> - <method name="get_magnetometer"> + <method name="get_magnetometer" qualifiers="const"> <return type="Vector3"> </return> <description> @@ -16220,7 +16734,23 @@ Returns the mouse speed for the last time the cursor was moved, and this until the next frame where the mouse moves. This means that even if the mouse is not moving, this function will still return the value of the last motion. </description> </method> - <method name="is_action_pressed"> + <method name="is_action_just_pressed" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="action" type="String"> + </argument> + <description> + </description> + </method> + <method name="is_action_just_released" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="action" type="String"> + </argument> + <description> + </description> + </method> + <method name="is_action_pressed" qualifiers="const"> <return type="bool"> </return> <argument index="0" name="action" type="String"> @@ -16229,7 +16759,7 @@ Returns true or false depending on whether the action event is pressed. Actions and their events can be set in the Project Settings / Input Map tab. Or be set with [InputMap]. </description> </method> - <method name="is_joy_button_pressed"> + <method name="is_joy_button_pressed" qualifiers="const"> <return type="bool"> </return> <argument index="0" name="device" type="int"> @@ -16249,7 +16779,7 @@ Returns if the specified device is known by the system. This means that it sets all button and axis indices exactly as defined in the JOY_* constants (see [@Global Scope]). Unknown joysticks are not expected to match these constants, but you can still retrieve events from them. </description> </method> - <method name="is_key_pressed"> + <method name="is_key_pressed" qualifiers="const"> <return type="bool"> </return> <argument index="0" name="scancode" type="int"> @@ -16258,7 +16788,7 @@ Returns true or false depending on whether the key is pressed or not. You can pass KEY_*, which are pre-defined constants listed in [@Global Scope]. </description> </method> - <method name="is_mouse_button_pressed"> + <method name="is_mouse_button_pressed" qualifiers="const"> <return type="bool"> </return> <argument index="0" name="button" type="int"> @@ -16300,7 +16830,8 @@ <argument index="3" name="duration" type="float" default="0"> </argument> <description> - Starts to vibrate the joystick. Joysticks usually come with two rumble motors, a strong and a weak one. weak_magnitude is the strength of the weak motor (between 0 and 1) and strong_magnitude is the strength of the strong motor (between 0 and 1). duration is the duration of the effect in seconds (a duration of 0 will play the vibration indefinitely). + Starts to vibrate the joystick. Joysticks usually come with two rumble motors, a strong and a weak one. weak_magnitude is the strength of the weak motor (between 0 and 1) and strong_magnitude is the strength of the strong motor (between 0 and 1). duration is the duration of the effect in seconds (a duration of 0 will try to play the vibration indefinitely). + Note that not every hardware is compatible with long effect durations, it is recommended to restart an effect if in need to play it for more than a few seconds. </description> </method> <method name="stop_joy_vibration"> @@ -17947,6 +18478,13 @@ Returns the list of selected indexes. </description> </method> + <method name="get_v_scroll"> + <return type="Object"> + </return> + <description> + Returns the current vertical scroll bar for the List. + </description> + </method> <method name="is_item_disabled" qualifiers="const"> <return type="bool"> </return> @@ -17965,6 +18503,15 @@ Returns whether or not the item at the specified index is selectable. </description> </method> + <method name="is_item_tooltip_enabled" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <description> + Returns whether the tooptip is enabled for specified item index. + </description> + </method> <method name="is_same_column_width" qualifiers="const"> <return type="int"> </return> @@ -18101,6 +18648,15 @@ Sets tooltip hint for item at specified index. </description> </method> + <method name="set_item_tooltip_enabled"> + <argument index="0" name="idx" type="int"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <description> + Sets whether the tooltip is enabled for specified item index. + </description> + </method> <method name="set_max_columns"> <argument index="0" name="amount" type="int"> </argument> @@ -18606,7 +19162,9 @@ </argument> <argument index="1" name="floor_normal" type="Vector2" default="Vector2(0, 0)"> </argument> - <argument index="2" name="max_bounces" type="int" default="4"> + <argument index="2" name="slope_stop_min_velocity" type="float" default="5"> + </argument> + <argument index="3" name="max_bounces" type="int" default="4"> </argument> <description> </description> @@ -18635,10 +19193,12 @@ <method name="test_move"> <return type="bool"> </return> - <argument index="0" name="rel_vec" type="Vector2"> + <argument index="0" name="from" type="Matrix32"> + </argument> + <argument index="1" name="rel_vec" type="Vector2"> </argument> <description> - Return true if there would be a collision if the body moved in the given direction. + Return true if there would be a collision if the body moved from the given point in the given direction. </description> </method> </methods> @@ -19436,7 +19996,7 @@ </description> </method> <method name="cursor_set_blink_enabled"> - <argument index="0" name="enable" type="bool"> + <argument index="0" name="enabled" type="bool"> </argument> <description> Set the line edit caret to blink. @@ -19462,6 +20022,12 @@ Return the cursor position inside the [LineEdit]. </description> </method> + <method name="get_expand_to_text_length" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> <method name="get_max_length" qualifiers="const"> <return type="int"> </return> @@ -19547,6 +20113,12 @@ Set the [i]editable[/i] status of the [LineEdit]. When disabled, existing text can't be modified and new text can't be added. </description> </method> + <method name="set_expand_to_text_length"> + <argument index="0" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> <method name="set_max_length"> <argument index="0" name="chars" type="int"> </argument> @@ -21690,8 +22262,10 @@ </class> <class name="NetworkedMultiplayerENet" inherits="NetworkedMultiplayerPeer" category="Core"> <brief_description> + PacketPeer implementation using the ENet library. </brief_description> <description> + A connection (or a listening server) that should be passed to [method SceneTree.set_network_peer]. Socket events can be handled by connecting to [SceneTree] signals. </description> <methods> <method name="close_connection"> @@ -22046,6 +22620,7 @@ Nodes can also process input events. When set, the [method _input] function will be called for each input that the program receives. In many cases, this can be overkill (unless used for simple projects), and the [method _unhandled_input] function might be preferred; it is called when the input event was not handled by anyone else (typically, GUI [Control] nodes), ensuring that the node only receives the events that were meant for it. To keep track of the scene hierarchy (especially when instancing scenes into other scenes), an "owner" can be set for the node with [method set_owner]. This keeps track of who instanced what. This is mostly useful when writing editors and tools, though. Finally, when a node is freed with [method free] or [method queue_free], it will also free all its children. + [b]Networking with nodes:[/b] After connecting to a server (or making one, see [NetworkedMultiplayerENet]) it is possible to use the built-in RPC (remote procedure call) system to easily communicate over the network. By calling [method rpc] with a method name, it will be called locally, and in all connected peers (peers = clients and the server that accepts connections), with behaviour varying depending on the network mode ([method set_network_mode]) on the receiving peer. To identify which [Node] receives the RPC call Godot will use it's [NodePath] (make sure node names are the same on all peers). </description> <methods> <method name="_enter_tree" qualifiers="virtual"> @@ -22479,10 +23054,11 @@ Replace a node in a scene by a given one. Subscriptions that pass through this node will be lost. </description> </method> - <method name="rpc"> + <method name="rpc" qualifiers="vararg"> <argument index="0" name="method" type="String"> </argument> <description> + Send a remote procedure call request to all peers on the network (and locally), optionally sending additional data as arguments. Call request will be received by nodes with the same [NodePath]. </description> </method> <method name="rpc_config"> @@ -22491,28 +23067,32 @@ <argument index="1" name="mode" type="int"> </argument> <description> + Change the method's RPC mode (one of RPC_MODE_* constants). </description> </method> - <method name="rpc_id"> - <argument index="0" name="peer_" type="int"> + <method name="rpc_id" qualifiers="vararg"> + <argument index="0" name="peer_id" type="int"> </argument> <argument index="1" name="method" type="String"> </argument> <description> + Send a [method rpc] to a specific peer identified by [i]peer_id[/i]. </description> </method> - <method name="rpc_unreliable"> + <method name="rpc_unreliable" qualifiers="vararg"> <argument index="0" name="method" type="String"> </argument> <description> + Send a [method rpc] using an unreliable protocol. </description> </method> - <method name="rpc_unreliable_id"> - <argument index="0" name="peer_" type="int"> + <method name="rpc_unreliable_id" qualifiers="vararg"> + <argument index="0" name="peer_id" type="int"> </argument> <argument index="1" name="method" type="String"> </argument> <description> + Send a [method rpc] to a specific peer identified by [i]peer_id[/i] using an unreliable protocol. </description> </method> <method name="rset"> @@ -22521,6 +23101,7 @@ <argument index="1" name="value" type="Variant"> </argument> <description> + Remotely change property's value on other peers (and locally). </description> </method> <method name="rset_config"> @@ -22529,6 +23110,7 @@ <argument index="1" name="mode" type="int"> </argument> <description> + Change the property's RPC mode (one of RPC_MODE_* constants). </description> </method> <method name="rset_id"> @@ -22539,6 +23121,7 @@ <argument index="2" name="value" type="Variant"> </argument> <description> + Remotely change property's value on a specific peer identified by [i]peer_id[/i]. </description> </method> <method name="rset_unreliable"> @@ -22547,6 +23130,7 @@ <argument index="1" name="value" type="Variant"> </argument> <description> + Remotely change property's value on other peers (and locally) using an unreliable protocol. </description> </method> <method name="rset_unreliable_id"> @@ -22557,6 +23141,7 @@ <argument index="2" name="value" type="Variant"> </argument> <description> + Remotely change property's value on a specific peer identified by [i]peer_id[/i] using an unreliable protocol. </description> </method> <method name="set_display_folded"> @@ -22590,6 +23175,7 @@ <argument index="0" name="mode" type="int"> </argument> <description> + Change the networking mode of the [Node], where [i]mode[/i] is one of the constants NETWORK_MODE_*. Master nodes will only call gdscript methods defined as [i]master func[/i] if a RPC call is received (slave nodes will only call [i]slave func[/i]; both will call [i]remote func[/i] if the call is not local, and [i]sync func[/i] in any case). Inherit mode looks at the parent node to determine the value (root node depends on the [SceneTree] having a networking peer set with [method SceneTree.set_network_peer]) </description> </method> <method name="set_owner"> @@ -23960,50 +24546,18 @@ Add a user signal (can be added anytime). Arguments are optional, but can be added as an array of dictionaries, each containing "name" and "type" (from [@Global Scope] TYPE_*). </description> </method> - <method name="call"> + <method name="call" qualifiers="vararg"> <return type="Variant"> </return> <argument index="0" name="method" type="String"> </argument> - <argument index="1" name="arg0" type="Variant" default="NULL"> - </argument> - <argument index="2" name="arg1" type="Variant" default="NULL"> - </argument> - <argument index="3" name="arg2" type="Variant" default="NULL"> - </argument> - <argument index="4" name="arg3" type="Variant" default="NULL"> - </argument> - <argument index="5" name="arg4" type="Variant" default="NULL"> - </argument> - <argument index="6" name="arg5" type="Variant" default="NULL"> - </argument> - <argument index="7" name="arg6" type="Variant" default="NULL"> - </argument> - <argument index="8" name="arg7" type="Variant" default="NULL"> - </argument> - <argument index="9" name="arg8" type="Variant" default="NULL"> - </argument> - <argument index="10" name="arg9" type="Variant" default="NULL"> - </argument> <description> - Call a function in the object, result is returned. </description> </method> - <method name="call_deferred"> + <method name="call_deferred" qualifiers="vararg"> <argument index="0" name="method" type="String"> </argument> - <argument index="1" name="arg0" type="Variant" default="NULL"> - </argument> - <argument index="2" name="arg1" type="Variant" default="NULL"> - </argument> - <argument index="3" name="arg2" type="Variant" default="NULL"> - </argument> - <argument index="4" name="arg3" type="Variant" default="NULL"> - </argument> - <argument index="5" name="arg4" type="Variant" default="NULL"> - </argument> <description> - Create and store a function in the object. The call will take place on idle time. </description> </method> <method name="callv"> @@ -24051,21 +24605,10 @@ Disconnect a signal from a method. </description> </method> - <method name="emit_signal"> + <method name="emit_signal" qualifiers="vararg"> <argument index="0" name="signal" type="String"> </argument> - <argument index="1" name="arg0" type="Variant" default="NULL"> - </argument> - <argument index="2" name="arg1" type="Variant" default="NULL"> - </argument> - <argument index="3" name="arg2" type="Variant" default="NULL"> - </argument> - <argument index="4" name="arg3" type="Variant" default="NULL"> - </argument> - <argument index="5" name="arg4" type="Variant" default="NULL"> - </argument> <description> - Emit a signal. Arguments are passed in an array. </description> </method> <method name="free"> @@ -25724,7 +26267,7 @@ </methods> <constants> <constant name="PARAM_DIRECTION" value="0"> - Direction in radians at which the particles will be launched, Notice that when the direction is set to 0 the particles will be launched to the negative + Direction in degrees at which the particles will be launched, Notice that when the direction is set to 0 the particles will be launched to the negative </constant> <constant name="PARAM_SPREAD" value="1"> </constant> @@ -25738,7 +26281,7 @@ Velocity at which the particles will orbit around the emitter center </constant> <constant name="PARAM_GRAVITY_DIRECTION" value="5"> - Direction in radians at which the particles will be attracted + Direction in degrees at which the particles will be attracted </constant> <constant name="PARAM_GRAVITY_STRENGTH" value="6"> Strength of the gravitation attraction for each particle @@ -27280,14 +27823,16 @@ </return> <argument index="0" name="body" type="RID"> </argument> - <argument index="1" name="motion" type="Vector2"> + <argument index="1" name="from" type="Matrix32"> </argument> - <argument index="2" name="margin" type="float" default="0.08"> + <argument index="2" name="motion" type="Vector2"> </argument> - <argument index="3" name="result" type="Physics2DTestMotionResult" default="NULL"> + <argument index="3" name="margin" type="float" default="0.08"> + </argument> + <argument index="4" name="result" type="Physics2DTestMotionResult" default="NULL"> </argument> <description> - Return whether a body can move in a given direction. Apart from the boolean return value, a [Physics2DTestMotionResult] can be passed to return additional information in. + Return whether a body can move from a given point in a given direction. Apart from the boolean return value, a [Physics2DTestMotionResult] can be passed to return additional information in. </description> </method> <method name="damped_spring_joint_create"> @@ -31301,20 +31846,40 @@ Return the size of the array. </description> </method> + <method name="subarray"> + <return type="RawArray"> + </return> + <argument index="0" name="from" type="int"> + </argument> + <argument index="1" name="to" type="int"> + </argument> + <description> + Returns the slice of the [RawArray] between indices (inclusive) as a new [RawArray]. Any negative index is considered to be from the end of the array. + </description> + </method> </methods> <constants> </constants> </class> <class name="RayCast" inherits="Spatial" category="Core"> <brief_description> + Query the closest object intersecting a ray. </brief_description> <description> + A RayCast represents a line from its origin to its destination position [code]cast_to[/code], it is used to query the 3D space in order to find the closest object intersecting with the ray. + + RayCast can ignore some objects by adding them to the exception list via [code]add_exception[/code], setting proper filtering with layers, or by filtering object types with type masks. + + Only enabled raycasts will be able to query the space and report collisions! + + RayCast calculates intersection every fixed frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between fixed frames (or during the same frame) use [method force_raycast_update] after adjusting the raycast. </description> <methods> <method name="add_exception"> <argument index="0" name="node" type="Object"> </argument> <description> + Adds a collision exception so the ray does not report collisions with the specified [code]node[/code]. </description> </method> <method name="add_exception_rid"> @@ -31325,30 +31890,40 @@ </method> <method name="clear_exceptions"> <description> + Removes all collision exception for this ray. + </description> + </method> + <method name="force_raycast_update"> + <description> + Updates the collision information in case if this object's properties changed during the current frame (for example position, rotation or the cast_point). Note, [code]set_enabled[/code] is not required for this to work. </description> </method> <method name="get_cast_to" qualifiers="const"> <return type="Vector3"> </return> <description> + Return the destination point of this ray object. </description> </method> <method name="get_collider" qualifiers="const"> <return type="Object"> </return> <description> + Return the closest object the ray is pointing to. Note that this does not consider the length of the vector, so you must also use [method is_colliding] to check if the object returned is actually colliding with the ray. </description> </method> <method name="get_collider_shape" qualifiers="const"> <return type="int"> </return> <description> + Returns the collision shape of the closest object the ray is pointing to. </description> </method> <method name="get_collision_normal" qualifiers="const"> <return type="Vector3"> </return> <description> + Returns the normal of the intersecting object shape face containing the collision point. </description> </method> <method name="get_collision_point" qualifiers="const"> @@ -31362,30 +31937,35 @@ <return type="int"> </return> <description> + Returns the layer mask for this ray. </description> </method> <method name="get_type_mask" qualifiers="const"> <return type="int"> </return> <description> + Returns the type mask (types of objects to detect) for this ray. The value is a sum (bitwise OR'd) of constants available for [PhysicsDirectSpaceState]. </description> </method> <method name="is_colliding" qualifiers="const"> <return type="bool"> </return> <description> + Return whether the closest object the ray is pointing to is colliding with the vector (considering the vector length). </description> </method> <method name="is_enabled" qualifiers="const"> <return type="bool"> </return> <description> + Returns whether this raycast is enabled or not. </description> </method> <method name="remove_exception"> <argument index="0" name="node" type="Object"> </argument> <description> + Removes a collision exception so the ray does report collisions with the specified [code]node[/code]. </description> </method> <method name="remove_exception_rid"> @@ -31405,18 +31985,21 @@ <argument index="0" name="enabled" type="bool"> </argument> <description> + Enables the RayCast2D. Only enabled raycasts will be able to query the space and report collisions. </description> </method> <method name="set_layer_mask"> <argument index="0" name="mask" type="int"> </argument> <description> + Set the mask to filter objects. Only objects with at least the same mask element set will be detected. </description> </method> <method name="set_type_mask"> <argument index="0" name="mask" type="int"> </argument> <description> + Set the types of objects to detect. For [code]mask[/code] use a logic sum (OR operation) of constants defined in [PhysicsDirectSpaceState], eg. [code]PhysicsDirectSpaceState.TYPE_MASK_STATIC_BODY | PhysicsDirectSpaceState.TYPE_MASK_KINEMATIC_BODY[/code] to detect only those two types. </description> </method> </methods> @@ -31425,10 +32008,16 @@ </class> <class name="RayCast2D" inherits="Node2D" category="Core"> <brief_description> - Query the closest object intersecting a ray + Query the closest object intersecting a ray. </brief_description> <description> A RayCast2D represents a line from its origin to its destination position [code]cast_to[/code], it is used to query the 2D space in order to find the closest object intersecting with the ray. + + RayCast2D can ignore some objects by adding them to the exception list via [code]add_exception[/code], setting proper filtering with layers, or by filtering object types with type masks. + + Only enabled raycasts will be able to query the space and report collisions! + + RayCast2D calculates intersection every fixed frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between fixed frames (or during the same frame) use [method force_raycast_update] after adjusting the raycast. </description> <methods> <method name="add_exception"> @@ -31449,11 +32038,16 @@ Removes all collision exception for this ray. </description> </method> + <method name="force_raycast_update"> + <description> + Updates the collision information in case if this object's properties changed during the current frame (for example position, rotation or the cast_point). Note, [code]set_enabled[/code] is not required for this to work. + </description> + </method> <method name="get_cast_to" qualifiers="const"> <return type="Vector2"> </return> <description> - Return the destination point of this ray object + Return the destination point of this ray object. </description> </method> <method name="get_collider" qualifiers="const"> @@ -31481,7 +32075,14 @@ <return type="Vector2"> </return> <description> - Returns the collision point in which the ray intersects the closest object. + Returns the collision point in which the ray intersects the closest object. This point is in [b]global[/b] coordinate system. + </description> + </method> + <method name="get_exclude_parent_body" qualifiers="const"> + <return type="bool"> + </return> + <description> + Returns whether this ray should hit your parent node, if it's a body. </description> </method> <method name="get_layer_mask" qualifiers="const"> @@ -31495,6 +32096,7 @@ <return type="int"> </return> <description> + Returns the type mask (types of objects to detect) for this ray. The value is a sum (bitwise OR'd) of constants available for [Physics2DDirectSpaceState]. </description> </method> <method name="is_colliding" qualifiers="const"> @@ -31508,7 +32110,7 @@ <return type="bool"> </return> <description> - Returns whether this raycast is enabled or not + Returns whether this raycast is enabled or not. </description> </method> <method name="remove_exception"> @@ -31538,16 +32140,25 @@ Enables the RayCast2D. Only enabled raycasts will be able to query the space and report collisions. </description> </method> + <method name="set_exclude_parent_body"> + <argument index="0" name="mask" type="bool"> + </argument> + <description> + Toggle whether this ray should hit your parent node, if it's a body. + </description> + </method> <method name="set_layer_mask"> <argument index="0" name="mask" type="int"> </argument> <description> + Set the mask to filter objects. Only objects with at least the same mask element set will be detected. </description> </method> <method name="set_type_mask"> <argument index="0" name="mask" type="int"> </argument> <description> + Set the types of objects to detect. For [code]mask[/code] use a logic sum (OR operation) of constants defined in [Physics2DDirectSpaceState], eg. [code]Physics2DDirectSpaceState.TYPE_MASK_STATIC_BODY | Physics2DDirectSpaceState.TYPE_MASK_KINEMATIC_BODY[/code] to detect only those two types. </description> </method> </methods> @@ -31989,6 +32600,28 @@ <constants> </constants> </class> +<class name="RemoteTransform" inherits="Spatial" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="get_remote_node" qualifiers="const"> + <return type="NodePath"> + </return> + <description> + </description> + </method> + <method name="set_remote_node"> + <argument index="0" name="path" type="NodePath"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="RemoteTransform2D" inherits="Node2D" category="Core"> <brief_description> </brief_description> @@ -34548,23 +35181,13 @@ <description> </description> <methods> - <method name="call_group"> + <method name="call_group" qualifiers="vararg"> <argument index="0" name="flags" type="int"> </argument> <argument index="1" name="group" type="String"> </argument> <argument index="2" name="method" type="String"> </argument> - <argument index="3" name="arg0" type="Variant" default="NULL"> - </argument> - <argument index="4" name="arg1" type="Variant" default="NULL"> - </argument> - <argument index="5" name="arg2" type="Variant" default="NULL"> - </argument> - <argument index="6" name="arg3" type="Variant" default="NULL"> - </argument> - <argument index="7" name="arg4" type="Variant" default="NULL"> - </argument> <description> </description> </method> @@ -34666,6 +35289,7 @@ <return type="bool"> </return> <description> + Returns true if this SceneTree's [NetworkedMultiplayerPeer] is in server mode (listening for connections). </description> </method> <method name="is_paused" qualifiers="const"> @@ -34762,6 +35386,7 @@ <argument index="0" name="peer" type="NetworkedMultiplayerPeer"> </argument> <description> + Set the peer object to handle the RPC system (effectively enabling networking). Depending on the peer itself, the SceneTree will become a network server (check with [method is_network_server()]) and will set root node's network mode to master (see NETWORK_MODE_* constants in [Node]), or it will become a regular peer with root node set to slave. All child nodes are set to inherit the network mode by default. Handling of networking-related events (connection, disconnection, new clients) is done by connecting to SceneTree's signals. </description> </method> <method name="set_pause"> @@ -34988,7 +35613,7 @@ A helper node for displaying scrollable elements (e.g. lists). </brief_description> <description> - A ScrollContainer node with a [Control] child and scrollbar child ([HScrollbar], [VScrollBar], or both) will only draw the Control within the ScrollContainer area. Scrollbars will automatically be drawn at the right (for vertical) or bottom (for horizontal) and will enable dragging to move the viewable Control (and its children) within the ScrollContainer. Scrollbars will also automatically resize the grabber based on the minimum_size of the Control relative to the ScrollContainer. Works great with a [Panel] control. + A ScrollContainer node with a [Control] child and scrollbar child ([HScrollbar], [VScrollBar], or both) will only draw the Control within the ScrollContainer area. Scrollbars will automatically be drawn at the right (for vertical) or bottom (for horizontal) and will enable dragging to move the viewable Control (and its children) within the ScrollContainer. Scrollbars will also automatically resize the grabber based on the minimum_size of the Control relative to the ScrollContainer. Works great with a [Panel] control. You can set EXPAND on children size flags, so they will upscale to ScrollContainer size if ScrollContainer size is bigger (scroll is invisible for chosen dimension). </description> <methods> <method name="get_h_scroll" qualifiers="const"> @@ -40527,6 +41152,16 @@ <description> </description> </signal> + <signal name="symbol_lookup"> + <argument index="0" name="symbol" type="String"> + </argument> + <argument index="1" name="row" type="int"> + </argument> + <argument index="2" name="column" type="int"> + </argument> + <description> + </description> + </signal> <signal name="text_changed"> <description> Emitted when the text changes. @@ -42537,18 +43172,33 @@ </class> <class name="Tree" inherits="Control" category="Core"> <brief_description> + Control to show a tree of items. </brief_description> <description> + This shows a tree of items that can be selected, expanded and collapsed. The tree can have multiple columns with custom controls like text editing, buttons and popups. It can be useful for structural displaying and interactions. + Trees are built via code, using [TreeItem] objects to create the structure. They have a single root but multiple root can be simulated if a dummy hidden root is added. + [codeblock] + func _ready(): + var tree = Tree.new() + var root = tree.create_item() + tree.set_hide_root(true) + var child1 = tree.create_item(root) + var child2 = tree.create_item(root) + var subchild1 = tree.create_item(child1) + subchild1.set_text(0, "Subchild1") + [/codeblock] </description> <methods> <method name="are_column_titles_visible" qualifiers="const"> <return type="bool"> </return> <description> + Get whether the column titles are being shown. </description> </method> <method name="clear"> <description> + Clear the tree. This erases all of the items. </description> </method> <method name="create_item"> @@ -42557,16 +43207,19 @@ <argument index="0" name="parent" type="TreeItem" default="NULL"> </argument> <description> + Create an item in the tree and add it as the last child of [code]parent[/code]. If parent is not given, it will be added as the last child of the root, or it'll the be the root itself if the tree is empty. </description> </method> <method name="ensure_cursor_is_visible"> <description> + Make the current selected item visible. This will scroll the tree to make sure the selected item is in sight. </description> </method> <method name="get_allow_rmb_select" qualifiers="const"> <return type="bool"> </return> <description> + Get whether a right click can select items. </description> </method> <method name="get_column_at_pos" qualifiers="const"> @@ -42575,6 +43228,7 @@ <argument index="0" name="pos" type="Vector2"> </argument> <description> + Get the column index under the given point. </description> </method> <method name="get_column_title" qualifiers="const"> @@ -42583,6 +43237,7 @@ <argument index="0" name="column" type="int"> </argument> <description> + Get the title of the given column. </description> </method> <method name="get_column_width" qualifiers="const"> @@ -42591,36 +43246,42 @@ <argument index="0" name="column" type="int"> </argument> <description> + Get the width of the given column in pixels. </description> </method> <method name="get_columns" qualifiers="const"> <return type="int"> </return> <description> + Get the amount of columns. </description> </method> <method name="get_custom_popup_rect" qualifiers="const"> <return type="Rect2"> </return> <description> + Get the rectangle for custom popups. Helper to create custom cell controls that display a popup. See [method TreeItem.set_cell_mode]. </description> </method> <method name="get_drop_mode_flags" qualifiers="const"> <return type="int"> </return> <description> + Get the flags of the current drop mode. </description> </method> <method name="get_edited" qualifiers="const"> <return type="TreeItem"> </return> <description> + Get the current edited item. This is only available for custom cell mode. </description> </method> <method name="get_edited_column" qualifiers="const"> <return type="int"> </return> <description> + Get the column of the cell for the current edited icon. This is only available for custom cell mode. </description> </method> <method name="get_item_area_rect" qualifiers="const"> @@ -42631,6 +43292,7 @@ <argument index="1" name="column" type="int" default="-1"> </argument> <description> + Get the rectangle area of the the specified item. If column is specified, only get the position and size of that column, otherwise get the rectangle containing all columns. </description> </method> <method name="get_item_at_pos" qualifiers="const"> @@ -42639,6 +43301,7 @@ <argument index="0" name="pos" type="Vector2"> </argument> <description> + Get the tree item at the specified position (relative to the tree origin position). </description> </method> <method name="get_next_selected"> @@ -42647,42 +43310,49 @@ <argument index="0" name="from" type="TreeItem"> </argument> <description> + Get the next selected item after the given one. </description> </method> <method name="get_pressed_button" qualifiers="const"> <return type="int"> </return> <description> + Get the index of the last pressed button. </description> </method> <method name="get_root"> <return type="TreeItem"> </return> <description> + Get the root item of the tree. </description> </method> <method name="get_scroll" qualifiers="const"> <return type="Vector2"> </return> <description> + Get the current scrolling position. </description> </method> <method name="get_selected" qualifiers="const"> <return type="TreeItem"> </return> <description> + Get the currently selected item. </description> </method> <method name="get_selected_column" qualifiers="const"> <return type="int"> </return> <description> + Get the column number of the current selection. </description> </method> <method name="get_single_select_cell_editing_only_when_already_selected" qualifiers="const"> <return type="bool"> </return> <description> + Get whether the editing of a cell should only happen when it is already selected. </description> </method> <method name="is_delayed_text_editor_enabled" qualifiers="const"> @@ -42695,12 +43365,14 @@ <return type="bool"> </return> <description> + Get whether the folding arrow is hidden. </description> </method> <method name="set_allow_rmb_select"> <argument index="0" name="allow" type="bool"> </argument> <description> + Set whether or not a right mouse button click can select items. </description> </method> <method name="set_column_expand"> @@ -42709,6 +43381,7 @@ <argument index="1" name="expand" type="bool"> </argument> <description> + Set whether a column will have the "Expand" flag of [Control]. </description> </method> <method name="set_column_min_width"> @@ -42717,6 +43390,7 @@ <argument index="1" name="min_width" type="int"> </argument> <description> + Set the minimum width of a column. </description> </method> <method name="set_column_title"> @@ -42725,18 +43399,21 @@ <argument index="1" name="title" type="String"> </argument> <description> + Set the title of a column. </description> </method> <method name="set_column_titles_visible"> <argument index="0" name="visible" type="bool"> </argument> <description> + Set whether the column titles visibility. </description> </method> <method name="set_columns"> <argument index="0" name="amount" type="int"> </argument> <description> + Set the amount of columns. </description> </method> <method name="set_delayed_text_editor"> @@ -42749,30 +43426,35 @@ <argument index="0" name="flags" type="int"> </argument> <description> + Set the drop mode as an OR combination of flags. See [code]DROP_MODE_*[/code] constants. </description> </method> <method name="set_hide_folding"> <argument index="0" name="hide" type="bool"> </argument> <description> + Set whether the folding arrow should be hidden. </description> </method> <method name="set_hide_root"> <argument index="0" name="enable" type="bool"> </argument> <description> + Set whether the root of the tree should be hidden. </description> </method> <method name="set_select_mode"> <argument index="0" name="mode" type="int"> </argument> <description> + Set the selection mode. Use one of the [code]SELECT_*[/code] constants. </description> </method> <method name="set_single_select_cell_editing_only_when_already_selected"> <argument index="0" name="enable" type="bool"> </argument> <description> + Set whether the editing of a cell should only happen when it is already selected. </description> </method> </methods> @@ -42785,32 +43467,38 @@ <argument index="2" name="id" type="int"> </argument> <description> + Emitted when a button on the tree was pressed (see [method TreeItem.add_button]). </description> </signal> <signal name="cell_selected"> <description> + Emitted when a cell is selected. </description> </signal> <signal name="custom_popup_edited"> <argument index="0" name="arrow_clicked" type="bool"> </argument> <description> + Emitted when a cell with the [code]CELL_MODE_CUSTOM[/code] is clicked to be edited. </description> </signal> <signal name="empty_tree_rmb_selected"> <argument index="0" name="pos" type="Vector2"> </argument> <description> + Emitted when the right mouse button is pressed if RMB selection is active and the tree is empty. </description> </signal> <signal name="item_activated"> <description> + Emitted when an item is activated (double-clicked). </description> </signal> <signal name="item_collapsed"> <argument index="0" name="item" type="Object"> </argument> <description> + Emitted when an item is collapsed by a click on the folding arrow. </description> </signal> <signal name="item_double_clicked"> @@ -42819,16 +43507,19 @@ </signal> <signal name="item_edited"> <description> + Emitted when an item is editted. </description> </signal> <signal name="item_rmb_selected"> <argument index="0" name="pos" type="Vector2"> </argument> <description> + Emitted when an item is selected with right mouse button. </description> </signal> <signal name="item_selected"> <description> + Emitted when an item is selected with right mouse button. </description> </signal> <signal name="multi_selected"> @@ -43533,10 +44224,10 @@ </return> <argument index="0" name="object" type="Object"> </argument> - <argument index="1" name="key" type="String"> + <argument index="1" name="key" type="String" default=""""> </argument> <description> - Stop animating and completely remove a tween, given its object and property/method pair. + Stop animating and completely remove a tween, given its object and property/method pair. Passing empty String as key will remove all tweens for given object. </description> </method> <method name="remove_all"> @@ -43551,10 +44242,10 @@ </return> <argument index="0" name="object" type="Object"> </argument> - <argument index="1" name="key" type="String"> + <argument index="1" name="key" type="String" default=""""> </argument> <description> - Resets a tween to the initial value (the one given, not the one before the tween), given its object and property/method pair. + Resets a tween to the initial value (the one given, not the one before the tween), given its object and property/method pair. Passing empty String as key will reset all tweens for given object. </description> </method> <method name="reset_all"> @@ -43569,10 +44260,10 @@ </return> <argument index="0" name="object" type="Object"> </argument> - <argument index="1" name="key" type="String"> + <argument index="1" name="key" type="String" default=""""> </argument> <description> - Continue animating a stopped tween, given its object and property/method pair. + Continue animating a stopped tween, given its object and property/method pair. Passing empty String as key will resume all tweens for given object. </description> </method> <method name="resume_all"> @@ -43631,10 +44322,10 @@ </return> <argument index="0" name="object" type="Object"> </argument> - <argument index="1" name="key" type="String"> + <argument index="1" name="key" type="String" default=""""> </argument> <description> - Stop animating a tween, given its object and property/method pair. + Stop animating a tween, given its object and property/method pair. Passing empty String as key will stop all tweens for given object. </description> </method> <method name="stop_all"> @@ -43800,24 +44491,12 @@ Common behavior is to create an action, then add do/undo calls to functions or property changes, then commiting the action. </description> <methods> - <method name="add_do_method"> + <method name="add_do_method" qualifiers="vararg"> <argument index="0" name="object" type="Object"> </argument> <argument index="1" name="method" type="String"> </argument> - <argument index="2" name="arg0" type="Variant" default="NULL"> - </argument> - <argument index="3" name="arg1" type="Variant" default="NULL"> - </argument> - <argument index="4" name="arg2" type="Variant" default="NULL"> - </argument> - <argument index="5" name="arg3" type="Variant" default="NULL"> - </argument> - <argument index="6" name="arg4" type="Variant" default="NULL"> - </argument> <description> - Add a call to a method in a given object with custom - arguments. </description> </method> <method name="add_do_property"> @@ -43838,23 +44517,12 @@ Add a 'do' reference that will be erased if the 'do' history is lost. This is useful mostly for new nodes created for the 'do' call. Do not use for resources. </description> </method> - <method name="add_undo_method"> + <method name="add_undo_method" qualifiers="vararg"> <argument index="0" name="object" type="Object"> </argument> <argument index="1" name="method" type="String"> </argument> - <argument index="2" name="arg0" type="Variant" default="NULL"> - </argument> - <argument index="3" name="arg1" type="Variant" default="NULL"> - </argument> - <argument index="4" name="arg2" type="Variant" default="NULL"> - </argument> - <argument index="5" name="arg3" type="Variant" default="NULL"> - </argument> - <argument index="6" name="arg4" type="Variant" default="NULL"> - </argument> <description> - Add a call to an undo method in a given object with custom arguments. Undo calls are used to revert 'do' calls. </description> </method> <method name="add_undo_property"> @@ -44125,6 +44793,14 @@ do_property]. Returns the angle in radians between the line connecting the two points and the x coordinate. </description> </method> + <method name="clamped"> + <return type="Vector2"> + </return> + <argument index="0" name="length" type="float"> + </argument> + <description> + </description> + </method> <method name="cubic_interpolate"> <return type="Vector2"> </return> @@ -44878,136 +45554,160 @@ do_property]. </class> <class name="VideoPlayer" inherits="Control" category="Core"> <brief_description> + Control to play video files. </brief_description> <description> + This control has the ability to play video streams. The only format accepted is the OGV Theora, so any other format must be converted before using in a project. </description> <methods> <method name="get_audio_track" qualifiers="const"> <return type="int"> </return> <description> + Get the selected audio track (for multitrack videos). </description> </method> <method name="get_buffering_msec" qualifiers="const"> <return type="int"> </return> <description> + Get the amount of miliseconds to store in buffer while playing. </description> </method> <method name="get_stream" qualifiers="const"> <return type="VideoStream"> </return> <description> + Get the video stream. </description> </method> <method name="get_stream_name" qualifiers="const"> <return type="String"> </return> <description> + Get the name of the video stream. </description> </method> <method name="get_stream_pos" qualifiers="const"> <return type="float"> </return> <description> + Get the current position of the stream, in seconds. </description> </method> <method name="get_video_texture"> <return type="Texture"> </return> <description> + Get the current frame of the video as a [Texture]. </description> </method> <method name="get_volume" qualifiers="const"> <return type="float"> </return> <description> + Get the volume of the audio track as a linear value. </description> </method> <method name="get_volume_db" qualifiers="const"> <return type="float"> </return> <description> + Get the volume of the audio track in decibels. </description> </method> <method name="has_autoplay" qualifiers="const"> <return type="bool"> </return> <description> + Get whether or not the video is set as autoplay. </description> </method> <method name="has_expand" qualifiers="const"> <return type="bool"> </return> <description> + Get whether or not the expand property is set. </description> </method> <method name="is_paused" qualifiers="const"> <return type="bool"> </return> <description> + Get whether or not the video is paused. </description> </method> <method name="is_playing" qualifiers="const"> <return type="bool"> </return> <description> + Get whether or not the video is playing. </description> </method> <method name="play"> <description> + Start the video playback. </description> </method> <method name="set_audio_track"> <argument index="0" name="track" type="int"> </argument> <description> + Set the audio track (for multitrack videos). </description> </method> <method name="set_autoplay"> <argument index="0" name="enabled" type="bool"> </argument> <description> + Set whether this node should start playing automatically. </description> </method> <method name="set_buffering_msec"> <argument index="0" name="msec" type="int"> </argument> <description> + Set the amount of miliseconds to buffer during playback. </description> </method> <method name="set_expand"> <argument index="0" name="enable" type="bool"> </argument> <description> + Set the expand property. If enabled, the video will grow or shrink to fit the player size, otherwise it will play at the stream resolution. </description> </method> <method name="set_paused"> <argument index="0" name="paused" type="bool"> </argument> <description> + Set whether the video should pause the playback. </description> </method> <method name="set_stream"> <argument index="0" name="stream" type="VideoStream"> </argument> <description> + Set the video stream for this player. </description> </method> <method name="set_volume"> <argument index="0" name="volume" type="float"> </argument> <description> + Set the audio volume as a linear value. </description> </method> <method name="set_volume_db"> <argument index="0" name="db" type="float"> </argument> <description> + Set the audio volume in decibels. </description> </method> <method name="stop"> <description> + Stop the video playback. </description> </method> </methods> @@ -45187,6 +45887,12 @@ do_property]. Return the 3D world of the viewport. </description> </method> + <method name="get_world_2d" qualifiers="const"> + <return type="World2D"> + </return> + <description> + </description> + </method> <method name="gui_get_drag_data" qualifiers="const"> <return type="Variant"> </return> @@ -45410,6 +46116,12 @@ do_property]. Change the 3D world of the viewport. </description> </method> + <method name="set_world_2d"> + <argument index="0" name="world_2d" type="World2D"> + </argument> + <description> + </description> + </method> <method name="unhandled_input"> <argument index="0" name="local_event" type="InputEvent"> </argument> @@ -45730,12 +46442,24 @@ do_property]. <description> </description> <methods> + <method name="get_aabb" qualifiers="const"> + <return type="AABB"> + </return> + <description> + </description> + </method> <method name="get_layer_mask" qualifiers="const"> <return type="int"> </return> <description> </description> </method> + <method name="get_transformed_aabb" qualifiers="const"> + <return type="AABB"> + </return> + <description> + </description> + </method> <method name="set_base"> <argument index="0" name="base" type="RID"> </argument> @@ -46156,6 +46880,40 @@ do_property]. <constants> </constants> </class> +<class name="VisualScriptBasicTypeConstant" inherits="VisualScriptNode" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="get_basic_type" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_basic_type_constant" qualifiers="const"> + <return type="String"> + </return> + <description> + </description> + </method> + <method name="set_basic_type"> + <argument index="0" name="name" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_basic_type_constant"> + <argument index="0" name="name" type="String"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="VisualScriptBuiltinFunc" inherits="VisualScriptNode" category="Core"> <brief_description> </brief_description> @@ -46178,6 +46936,40 @@ do_property]. <constants> </constants> </class> +<class name="VisualScriptClassConstant" inherits="VisualScriptNode" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="get_base_type"> + <return type="String"> + </return> + <description> + </description> + </method> + <method name="get_class_constant"> + <return type="String"> + </return> + <description> + </description> + </method> + <method name="set_base_type"> + <argument index="0" name="name" type="String"> + </argument> + <description> + </description> + </method> + <method name="set_class_constant"> + <argument index="0" name="name" type="String"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="VisualScriptComment" inherits="VisualScriptNode" category="Core"> <brief_description> </brief_description> @@ -46506,6 +47298,16 @@ do_property]. <constants> </constants> </class> +<class name="VisualScriptExpression" inherits="VisualScriptNode" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + </methods> + <constants> + </constants> +</class> <class name="VisualScriptFunction" inherits="VisualScriptNode" category="Core"> <brief_description> </brief_description> @@ -46576,6 +47378,12 @@ do_property]. <description> </description> </method> + <method name="get_validate" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> <method name="set_base_path"> <argument index="0" name="base_path" type="NodePath"> </argument> @@ -46630,6 +47438,12 @@ do_property]. <description> </description> </method> + <method name="set_validate"> + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> </methods> <constants> <constant name="CALL_MODE_SELF" value="0"> @@ -46724,12 +47538,24 @@ do_property]. <description> </description> <methods> + <method name="get_action_mode" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> <method name="get_action_name" qualifiers="const"> <return type="String"> </return> <description> </description> </method> + <method name="set_action_mode"> + <argument index="0" name="mode" type="int"> + </argument> + <description> + </description> + </method> <method name="set_action_name"> <argument index="0" name="name" type="String"> </argument> @@ -46750,16 +47576,6 @@ do_property]. <constants> </constants> </class> -<class name="VisualScriptInputSelector" inherits="VisualScriptNode" category="Core"> - <brief_description> - </brief_description> - <description> - </description> - <methods> - </methods> - <constants> - </constants> -</class> <class name="VisualScriptIterator" inherits="VisualScriptNode" category="Core"> <brief_description> </brief_description> @@ -47290,6 +48106,16 @@ do_property]. <constants> </constants> </class> +<class name="VisualScriptSwitch" inherits="VisualScriptNode" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + </methods> + <constants> + </constants> +</class> <class name="VisualScriptTypeCast" inherits="VisualScriptNode" category="Core"> <brief_description> </brief_description> @@ -49305,14 +50131,17 @@ do_property]. </class> <class name="XMLParser" inherits="Reference" category="Core"> <brief_description> + Low-level class for creating parsers for XML files. </brief_description> <description> + This class can serve as base to make custom XML parsers. Since XML is a very flexible standard, this interface is low level so it can be applied to any possible schema. </description> <methods> <method name="get_attribute_count" qualifiers="const"> <return type="int"> </return> <description> + Get the amount of attributes in the current element. </description> </method> <method name="get_attribute_name" qualifiers="const"> @@ -49321,6 +50150,7 @@ do_property]. <argument index="0" name="idx" type="int"> </argument> <description> + Get the name of the attribute specified by the index in [code]idx[/code] argument. </description> </method> <method name="get_attribute_value" qualifiers="const"> @@ -49329,12 +50159,14 @@ do_property]. <argument index="0" name="idx" type="int"> </argument> <description> + Get the value of the attribute specified by the index in [code]idx[/code] argument. </description> </method> <method name="get_current_line" qualifiers="const"> <return type="int"> </return> <description> + Get the current line in the parsed file (currently not implemented). </description> </method> <method name="get_named_attribute_value" qualifiers="const"> @@ -49343,6 +50175,7 @@ do_property]. <argument index="0" name="name" type="String"> </argument> <description> + Get the value of a certain attribute of the current element by name. This will raise an error if the element has no such attribute. </description> </method> <method name="get_named_attribute_value_safe" qualifiers="const"> @@ -49351,30 +50184,35 @@ do_property]. <argument index="0" name="name" type="String"> </argument> <description> + Get the value of a certain attribute of the current element by name. This will return an empty [String] if the attribute is not found. </description> </method> <method name="get_node_data" qualifiers="const"> <return type="String"> </return> <description> + Get the contents of a text node. This will raise an error in any other type of node. </description> </method> <method name="get_node_name" qualifiers="const"> <return type="String"> </return> <description> + Get the name of the current element node. This will raise an error if the current node type is not [code]NODE_ELEMENT[/code] nor [code]NODE_ELEMENT_END[/code] </description> </method> <method name="get_node_offset" qualifiers="const"> <return type="int"> </return> <description> + Get the byte offset of the current node since the beginning of the file or buffer. </description> </method> <method name="get_node_type"> <return type="int"> </return> <description> + Get the type of the current node. Compare with [code]NODE_*[/code] constants. </description> </method> <method name="has_attribute" qualifiers="const"> @@ -49383,12 +50221,14 @@ do_property]. <argument index="0" name="name" type="String"> </argument> <description> + Check whether or not the current element has a certain attribute. </description> </method> <method name="is_empty" qualifiers="const"> <return type="bool"> </return> <description> + Check whether the current element is empty (this only works for completely empty tags, e.g. <element \>). </description> </method> <method name="open"> @@ -49397,6 +50237,7 @@ do_property]. <argument index="0" name="file" type="String"> </argument> <description> + Open a XML file for parsing. This returns an error code. </description> </method> <method name="open_buffer"> @@ -49405,12 +50246,14 @@ do_property]. <argument index="0" name="buffer" type="RawArray"> </argument> <description> + Open a XML raw buffer for parsing. This returns an error code. </description> </method> <method name="read"> <return type="int"> </return> <description> + Read the next node of the file. This returns an error code. </description> </method> <method name="seek"> @@ -49419,27 +50262,36 @@ do_property]. <argument index="0" name="pos" type="int"> </argument> <description> + Move the buffer cursor to a certain offset (since the beginning) and read the next node there. This returns an error code. </description> </method> <method name="skip_section"> <description> + Skips the current section. If the node contains other elements, they will be ignored and the cursor will go to the closing of the current element. </description> </method> </methods> <constants> <constant name="NODE_NONE" value="0"> + There's no node (no file or buffer opened) </constant> <constant name="NODE_ELEMENT" value="1"> + Element (tag) </constant> <constant name="NODE_ELEMENT_END" value="2"> + End of element </constant> <constant name="NODE_TEXT" value="3"> + Text node </constant> <constant name="NODE_COMMENT" value="4"> + Comment node </constant> <constant name="NODE_CDATA" value="5"> + CDATA content </constant> <constant name="NODE_UNKNOWN" value="6"> + Unknown node </constant> </constants> </class> diff --git a/doc/tools/doc_merge.py b/doc/tools/doc_merge.py index b55902ce4f..536770bee4 100644 --- a/doc/tools/doc_merge.py +++ b/doc/tools/doc_merge.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: utf-8 -*- import sys diff --git a/doc/tools/doc_status.py b/doc/tools/doc_status.py index 35a6bc8bc4..f0ede405ce 100755 --- a/doc/tools/doc_status.py +++ b/doc/tools/doc_status.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 import sys import re diff --git a/doc/tools/makedocs.py b/doc/tools/makedocs.py index 063ee29002..731e04f6fc 100644 --- a/doc/tools/makedocs.py +++ b/doc/tools/makedocs.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # diff --git a/doc/tools/makedoku.py b/doc/tools/makedoku.py index 97819d7da3..7c3ca29af8 100644 --- a/doc/tools/makedoku.py +++ b/doc/tools/makedoku.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: utf-8 -*- import sys diff --git a/doc/tools/makehtml.py b/doc/tools/makehtml.py index 26edda0935..b0a8cbda88 100644 --- a/doc/tools/makehtml.py +++ b/doc/tools/makehtml.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: utf-8 -*- import sys diff --git a/doc/tools/makemd.py b/doc/tools/makemd.py index 38b493b0bf..e0fbe9af03 100644 --- a/doc/tools/makemd.py +++ b/doc/tools/makemd.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: utf-8 -*- import sys diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py index 45e690cb65..718cf4a275 100644 --- a/doc/tools/makerst.py +++ b/doc/tools/makerst.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: utf-8 -*- import codecs diff --git a/drivers/SCsub b/drivers/SCsub index 79cbe50685..1f1509efa8 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -1,80 +1,51 @@ -Import('env') +#!/usr/bin/env python -env_drivers = env.Clone() +Import('env') env.drivers_sources=[] -#env.add_source_files(env.drivers_sources,"*.cpp") -env_drivers.Append(CPPPATH=["vorbis"]) -Export('env_drivers') +if ("builtin_zlib" in env and env["builtin_zlib"] == "yes"): + SConscript("zlib/SCsub"); +# OS drivers SConscript('unix/SCsub'); +SConscript('windows/SCsub'); + +# Sounds drivers SConscript('alsa/SCsub'); SConscript('pulseaudio/SCsub'); -SConscript('windows/SCsub'); +if (env["platform"] == "windows"): + SConscript("rtaudio/SCsub"); +if (env["xaudio2"] == "yes"): + SConscript("xaudio2/SCsub"); + +# Graphics drivers SConscript('gles2/SCsub'); SConscript('gl_context/SCsub'); -SConscript('pnm/SCsub'); - -if (env['openssl']!='no'): - env_drivers.Append(CPPFLAGS=['-DOPENSSL_ENABLED']); - if (env['openssl']=="builtin"): - env_drivers.Append(CPPPATH=['#drivers/builtin_openssl2']) - SConscript("builtin_openssl2/SCsub"); - - SConscript('openssl/SCsub') - - -if (env["png"]=="yes"): - SConscript("png/SCsub"); -if (env["jpg"]=="yes"): - #SConscript("jpg/SCsub"); - SConscript("jpegd/SCsub"); -if (env["webp"]=="yes"): - SConscript("webp/SCsub"); -SConscript("dds/SCsub"); -SConscript("pvr/SCsub"); -SConscript("etc1/SCsub") -if (env["builtin_zlib"]=="yes"): - SConscript("builtin_zlib/SCsub"); - -SConscript("rtaudio/SCsub"); -SConscript("nedmalloc/SCsub"); + +# Core dependencies +SConscript("png/SCsub"); SConscript("nrex/SCsub"); -SConscript("chibi/SCsub"); -if (env["vorbis"]=="yes" or env["speex"]=="yes" or env["theoralib"]=="yes" or env["opus"]=="yes"): - SConscript("ogg/SCsub"); -if (env["vorbis"]=="yes"): - SConscript("vorbis/SCsub"); -if (env["opus"]=="yes"): - SConscript('opus/SCsub'); + +# Tools override +# FIXME: Should likely be integrated in the tools/ codebase if (env["tools"]=="yes"): SConscript("convex_decomp/SCsub"); -if (env["theoralib"]=="yes"): - SConscript("theora/SCsub"); -if (env['speex']=='yes'): - SConscript("speex/SCsub"); -if (env['musepack']=='yes'): - SConscript("mpc/SCsub"); -if (env["squish"]=="yes" and env["tools"]=="yes"): - SConscript("squish/SCsub"); -if (env["freetype"]!="no"): - SConscript("freetype/SCsub"); - -num = 0 -cur_base = "" -total = len(env.drivers_sources) -max_src = 64 -list = [] -lib_list = [] - -import string - if env['vsproj']=="yes": env.AddToVSProject(env.drivers_sources) -if (env.split_drivers): #split drivers, this used to be needed for windows until separate builders for windows were created + +# Split drivers, this used to be needed for windows until separate builders for windows were created +# FIXME: Check if still needed now that the drivers were made more lightweight +if (env.split_drivers): + import string + + num = 0 + cur_base = "" + max_src = 64 + list = [] + lib_list = [] for f in env.drivers_sources: fname = "" @@ -86,14 +57,14 @@ if (env.split_drivers): #split drivers, this used to be needed for windows until base = string.join(fname.split("/")[:2], "/") if base != cur_base and len(list) > max_src: if num > 0: - lib = env_drivers.Library("drivers"+str(num), list) + lib = env.Library("drivers"+str(num), list) lib_list.append(lib) list = [] num = num+1 cur_base = base list.append(f) - lib = env_drivers.Library("drivers"+str(num), list) + lib = env.Library("drivers"+str(num), list) lib_list.append(lib) if len(lib_list) > 0: @@ -101,15 +72,15 @@ if (env.split_drivers): #split drivers, this used to be needed for windows until if os.name=='posix' and sys.platform=='msys': env.Replace(ARFLAGS=['rcsT']) - lib = env_drivers.Library("drivers_collated", lib_list) + lib = env.Library("drivers_collated", lib_list) lib_list = [lib] drivers_base=[] - env_drivers.add_source_files(drivers_base,"*.cpp") - lib_list.insert(0, env_drivers.Library("drivers", drivers_base)) + env.add_source_files(drivers_base,"*.cpp") + lib_list.insert(0, env.Library("drivers", drivers_base)) env.Prepend(LIBS=lib_list) else: - env_drivers.add_source_files(env.drivers_sources,"*.cpp") - lib = env_drivers.Library("drivers",env.drivers_sources) + env.add_source_files(env.drivers_sources,"*.cpp") + lib = env.Library("drivers",env.drivers_sources) env.Prepend(LIBS=[lib]) diff --git a/drivers/alsa/SCsub b/drivers/alsa/SCsub index 9fbb467baa..ee39fd2631 100644 --- a/drivers/alsa/SCsub +++ b/drivers/alsa/SCsub @@ -1,5 +1,7 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.drivers_sources,"*.cpp") +env.add_source_files(env.drivers_sources, "*.cpp") Export('env') diff --git a/drivers/builtin_openssl2/SCsub b/drivers/builtin_openssl2/SCsub deleted file mode 100644 index bd0f428cfc..0000000000 --- a/drivers/builtin_openssl2/SCsub +++ /dev/null @@ -1,658 +0,0 @@ -Import('env') -Import('env_drivers') - -openssl_sources = [ -"ssl/t1_lib.c", -"ssl/t1_ext.c", -"ssl/s3_srvr.c", -"ssl/t1_enc.c", -"ssl/t1_meth.c", -"ssl/s23_clnt.c", -"ssl/ssl_asn1.c", -"ssl/tls_srp.c", -"ssl/kssl.c", -"ssl/d1_both.c", -"ssl/t1_clnt.c", -"ssl/bio_ssl.c", -"ssl/d1_srtp.c", -"ssl/t1_reneg.c", -"ssl/ssl_cert.c", -"ssl/s3_lib.c", -"ssl/d1_srvr.c", -"ssl/s23_meth.c", -"ssl/ssl_stat.c", -"ssl/ssl_err.c", -"ssl/ssl_algs.c", -"ssl/s3_cbc.c", -"ssl/d1_clnt.c", -"ssl/s3_pkt.c", -"ssl/d1_meth.c", -"ssl/s3_both.c", -"ssl/s2_enc.c", -"ssl/s3_meth.c", -"ssl/s3_enc.c", -"ssl/s23_pkt.c", -"ssl/s2_pkt.c", -"ssl/d1_pkt.c", -"ssl/ssl_rsa.c", -"ssl/s23_srvr.c", -"ssl/s2_meth.c", -"ssl/s3_clnt.c", -"ssl/s23_lib.c", -"ssl/t1_srvr.c", -"ssl/ssl_lib.c", -"ssl/ssl_txt.c", -"ssl/s2_srvr.c", -"ssl/ssl_sess.c", -"ssl/s2_clnt.c", -"ssl/d1_lib.c", -"ssl/s2_lib.c", -"ssl/ssl_err2.c", -"ssl/ssl_ciph.c", -"crypto/dsa/dsa_lib.c", -"crypto/dsa/dsa_pmeth.c", -"crypto/dsa/dsa_ossl.c", -"crypto/dsa/dsa_gen.c", -"crypto/dsa/dsa_asn1.c", -"crypto/dsa/dsa_prn.c", -"crypto/dsa/dsa_sign.c", -"crypto/dsa/dsa_key.c", -"crypto/dsa/dsa_vrf.c", -"crypto/dsa/dsa_err.c", -"crypto/dsa/dsa_ameth.c", -"crypto/dsa/dsa_depr.c", -"crypto/x509/x509_lu.c", -"crypto/x509/x509cset.c", -"crypto/x509/x509_set.c", -"crypto/x509/x509_d2.c", -"crypto/x509/x509_txt.c", -"crypto/x509/x509rset.c", -"crypto/x509/by_dir.c", -"crypto/x509/x509_vpm.c", -"crypto/x509/x509_vfy.c", -"crypto/x509/x509_trs.c", -"crypto/x509/by_file.c", -"crypto/x509/x509_obj.c", -"crypto/x509/x509spki.c", -"crypto/x509/x509_v3.c", -"crypto/x509/x509_req.c", -"crypto/x509/x509_att.c", -"crypto/x509/x_all.c", -"crypto/x509/x509_ext.c", -"crypto/x509/x509type.c", -"crypto/x509/x509_def.c", -"crypto/x509/x509_err.c", -"crypto/x509/x509name.c", -"crypto/x509/x509_r2x.c", -"crypto/x509/x509_cmp.c", -"crypto/asn1/x_pkey.c", -"crypto/asn1/a_gentm.c", -"crypto/asn1/x_sig.c", -"crypto/asn1/t_req.c", -"crypto/asn1/t_pkey.c", -"crypto/asn1/p8_pkey.c", -"crypto/asn1/a_i2d_fp.c", -"crypto/asn1/x_val.c", -"crypto/asn1/f_string.c", -"crypto/asn1/p5_pbe.c", -"crypto/asn1/bio_ndef.c", -"crypto/asn1/a_bool.c", -"crypto/asn1/asn1_gen.c", -"crypto/asn1/x_algor.c", -"crypto/asn1/bio_asn1.c", -"crypto/asn1/asn_mime.c", -"crypto/asn1/t_x509.c", -"crypto/asn1/a_strex.c", -"crypto/asn1/x_nx509.c", -"crypto/asn1/asn1_err.c", -"crypto/asn1/x_crl.c", -"crypto/asn1/a_print.c", -"crypto/asn1/a_type.c", -"crypto/asn1/tasn_new.c", -"crypto/asn1/n_pkey.c", -"crypto/asn1/x_bignum.c", -"crypto/asn1/asn_pack.c", -"crypto/asn1/evp_asn1.c", -"crypto/asn1/t_bitst.c", -"crypto/asn1/x_req.c", -"crypto/asn1/a_time.c", -"crypto/asn1/x_name.c", -"crypto/asn1/x_pubkey.c", -"crypto/asn1/tasn_typ.c", -"crypto/asn1/asn_moid.c", -"crypto/asn1/a_utctm.c", -"crypto/asn1/asn1_lib.c", -"crypto/asn1/x_x509a.c", -"crypto/asn1/a_set.c", -"crypto/asn1/t_crl.c", -"crypto/asn1/p5_pbev2.c", -"crypto/asn1/tasn_enc.c", -"crypto/asn1/a_mbstr.c", -"crypto/asn1/tasn_dec.c", -"crypto/asn1/x_x509.c", -"crypto/asn1/a_octet.c", -"crypto/asn1/x_long.c", -"crypto/asn1/a_bytes.c", -"crypto/asn1/t_x509a.c", -"crypto/asn1/a_enum.c", -"crypto/asn1/a_int.c", -"crypto/asn1/tasn_prn.c", -"crypto/asn1/i2d_pr.c", -"crypto/asn1/a_utf8.c", -"crypto/asn1/t_spki.c", -"crypto/asn1/a_digest.c", -"crypto/asn1/a_dup.c", -"crypto/asn1/i2d_pu.c", -"crypto/asn1/a_verify.c", -"crypto/asn1/f_enum.c", -"crypto/asn1/a_sign.c", -"crypto/asn1/d2i_pr.c", -"crypto/asn1/asn1_par.c", -"crypto/asn1/x_spki.c", -"crypto/asn1/a_d2i_fp.c", -"crypto/asn1/f_int.c", -"crypto/asn1/x_exten.c", -"crypto/asn1/tasn_utl.c", -"crypto/asn1/nsseq.c", -"crypto/asn1/a_bitstr.c", -"crypto/asn1/x_info.c", -"crypto/asn1/a_strnid.c", -"crypto/asn1/a_object.c", -"crypto/asn1/tasn_fre.c", -"crypto/asn1/d2i_pu.c", -"crypto/asn1/ameth_lib.c", -"crypto/asn1/x_attrib.c", -"crypto/evp/m_sha.c", -"crypto/evp/e_camellia.c", -"crypto/evp/e_aes.c", -"crypto/evp/bio_b64.c", -"crypto/evp/m_sigver.c", -"crypto/evp/m_wp.c", -"crypto/evp/m_sha1.c", -"crypto/evp/p_seal.c", -"crypto/evp/c_alld.c", -"crypto/evp/p5_crpt.c", -"crypto/evp/e_rc4.c", -"crypto/evp/m_ecdsa.c", -"crypto/evp/bio_enc.c", -"crypto/evp/e_des3.c", -"crypto/evp/m_null.c", -"crypto/evp/bio_ok.c", -"crypto/evp/pmeth_gn.c", -"crypto/evp/e_rc5.c", -"crypto/evp/e_rc2.c", -"crypto/evp/p_dec.c", -"crypto/evp/p_verify.c", -"crypto/evp/e_rc4_hmac_md5.c", -"crypto/evp/pmeth_lib.c", -"crypto/evp/m_ripemd.c", -"crypto/evp/m_md5.c", -"crypto/evp/e_bf.c", -"crypto/evp/p_enc.c", -"crypto/evp/m_dss.c", -"crypto/evp/bio_md.c", -"crypto/evp/evp_pbe.c", -"crypto/evp/e_seed.c", -"crypto/evp/e_cast.c", -"crypto/evp/p_open.c", -"crypto/evp/p5_crpt2.c", -"crypto/evp/m_dss1.c", -"crypto/evp/names.c", -"crypto/evp/evp_acnf.c", -"crypto/evp/e_des.c", -"crypto/evp/evp_cnf.c", -"crypto/evp/evp_lib.c", -"crypto/evp/digest.c", -"crypto/evp/evp_err.c", -"crypto/evp/evp_enc.c", -"crypto/evp/e_old.c", -"crypto/evp/c_all.c", -"crypto/evp/m_md2.c", -"crypto/evp/e_xcbc_d.c", -"crypto/evp/pmeth_fn.c", -"crypto/evp/p_lib.c", -"crypto/evp/evp_key.c", -"crypto/evp/encode.c", -"crypto/evp/e_aes_cbc_hmac_sha1.c", -"crypto/evp/e_aes_cbc_hmac_sha256.c", -"crypto/evp/m_mdc2.c", -"crypto/evp/e_null.c", -"crypto/evp/p_sign.c", -"crypto/evp/e_idea.c", -"crypto/evp/c_allc.c", -"crypto/evp/evp_pkey.c", -"crypto/evp/m_md4.c", -"crypto/ex_data.c", -"crypto/pkcs12/p12_p8e.c", -"crypto/pkcs12/p12_crt.c", -"crypto/pkcs12/p12_utl.c", -"crypto/pkcs12/p12_attr.c", -"crypto/pkcs12/p12_npas.c", -"crypto/pkcs12/p12_decr.c", -"crypto/pkcs12/p12_init.c", -"crypto/pkcs12/p12_kiss.c", -"crypto/pkcs12/p12_add.c", -"crypto/pkcs12/p12_p8d.c", -"crypto/pkcs12/p12_mutl.c", -"crypto/pkcs12/p12_crpt.c", -"crypto/pkcs12/pk12err.c", -"crypto/pkcs12/p12_asn.c", -"crypto/pkcs12/p12_key.c", -"crypto/ecdh/ech_key.c", -"crypto/ecdh/ech_ossl.c", -"crypto/ecdh/ech_lib.c", -"crypto/ecdh/ech_err.c", -"crypto/ecdh/ech_kdf.c", -"crypto/o_str.c", -"crypto/conf/conf_api.c", -"crypto/conf/conf_err.c", -"crypto/conf/conf_def.c", -"crypto/conf/conf_lib.c", -"crypto/conf/conf_mall.c", -"crypto/conf/conf_sap.c", -"crypto/conf/conf_mod.c", -"crypto/ebcdic.c", -"crypto/ecdsa/ecs_lib.c", -"crypto/ecdsa/ecs_asn1.c", -"crypto/ecdsa/ecs_ossl.c", -"crypto/ecdsa/ecs_vrf.c", -"crypto/ecdsa/ecs_sign.c", -"crypto/ecdsa/ecs_err.c", -"crypto/dso/dso_win32.c", -"crypto/dso/dso_lib.c", -"crypto/dso/dso_dlfcn.c", -"crypto/dso/dso_dl.c", -"crypto/dso/dso_beos.c", -"crypto/dso/dso_null.c", -"crypto/dso/dso_vms.c", -"crypto/dso/dso_err.c", -"crypto/dso/dso_openssl.c", -"crypto/cryptlib.c", -"crypto/md5/md5_one.c", -"crypto/md5/md5_dgst.c", -"crypto/pkcs7/pkcs7err.c", -"crypto/pkcs7/pk7_smime.c", -"crypto/pkcs7/bio_pk7.c", -"crypto/pkcs7/pk7_mime.c", -"crypto/pkcs7/pk7_lib.c", -"crypto/pkcs7/pk7_asn1.c", -"crypto/pkcs7/pk7_doit.c", -"crypto/pkcs7/pk7_attr.c", -"crypto/md4/md4_one.c", -"crypto/md4/md4_dgst.c", -"crypto/o_dir.c", -"crypto/buffer/buf_err.c", -"crypto/buffer/buf_str.c", -"crypto/buffer/buffer.c", -"crypto/cms/cms_lib.c", -"crypto/cms/cms_io.c", -"crypto/cms/cms_err.c", -"crypto/cms/cms_dd.c", -"crypto/cms/cms_smime.c", -"crypto/cms/cms_att.c", -"crypto/cms/cms_pwri.c", -"crypto/cms/cms_cd.c", -"crypto/cms/cms_sd.c", -"crypto/cms/cms_asn1.c", -"crypto/cms/cms_env.c", -"crypto/cms/cms_enc.c", -"crypto/cms/cms_ess.c", -"crypto/cms/cms_kari.c", -"crypto/mem_dbg.c", -"crypto/uid.c", -"crypto/stack/stack.c", -"crypto/ec/ec_ameth.c", -"crypto/ec/ec_err.c", -"crypto/ec/ec_lib.c", -"crypto/ec/ec_curve.c", -"crypto/ec/ec_oct.c", -"crypto/ec/ec_asn1.c", -"crypto/ec/ecp_oct.c", -"crypto/ec/ec_print.c", -"crypto/ec/ec2_smpl.c", -"crypto/ec/ecp_nistp224.c", -"crypto/ec/ec2_oct.c", -"crypto/ec/eck_prn.c", -"crypto/ec/ec_key.c", -"crypto/ec/ecp_nist.c", -"crypto/ec/ec_check.c", -"crypto/ec/ecp_smpl.c", -"crypto/ec/ec2_mult.c", -"crypto/ec/ecp_mont.c", -"crypto/ec/ecp_nistp521.c", -"crypto/ec/ec_mult.c", -"crypto/ec/ecp_nistputil.c", -"crypto/ec/ec_pmeth.c", -"crypto/ec/ec_cvt.c", -"crypto/ec/ecp_nistp256.c", -"crypto/krb5/krb5_asn.c", -"crypto/hmac/hmac.c", -"crypto/hmac/hm_ameth.c", -"crypto/hmac/hm_pmeth.c", -"crypto/comp/c_rle.c", -"crypto/comp/c_zlib.c", -"crypto/comp/comp_lib.c", -"crypto/comp/comp_err.c", -"crypto/des/fcrypt.c", -"crypto/des/str2key.c", -"crypto/des/cbc_cksm.c", -"crypto/des/des_enc.c", -"crypto/des/ofb_enc.c", -"crypto/des/read2pwd.c", -"crypto/des/ecb3_enc.c", -"crypto/des/rand_key.c", -"crypto/des/cfb64ede.c", -"crypto/des/rpc_enc.c", -"crypto/des/ofb64ede.c", -"crypto/des/qud_cksm.c", -"crypto/des/enc_writ.c", -"crypto/des/set_key.c", -"crypto/des/xcbc_enc.c", -"crypto/des/fcrypt_b.c", -"crypto/des/ede_cbcm_enc.c", -"crypto/des/des_old2.c", -"crypto/des/cfb_enc.c", -"crypto/des/ecb_enc.c", -"crypto/des/enc_read.c", -"crypto/des/des_old.c", -"crypto/des/ofb64enc.c", -"crypto/des/pcbc_enc.c", -"crypto/des/cbc_enc.c", -"crypto/des/cfb64enc.c", -"crypto/lhash/lh_stats.c", -"crypto/lhash/lhash.c", -"crypto/x509v3/v3_genn.c", -"crypto/x509v3/pcy_cache.c", -"crypto/x509v3/v3_sxnet.c", -"crypto/x509v3/v3_scts.c", -"crypto/x509v3/v3err.c", -"crypto/x509v3/v3_conf.c", -"crypto/x509v3/v3_utl.c", -"crypto/x509v3/v3_akeya.c", -"crypto/x509v3/v3_lib.c", -"crypto/x509v3/pcy_lib.c", -"crypto/x509v3/v3_cpols.c", -"crypto/x509v3/v3_ia5.c", -"crypto/x509v3/v3_bitst.c", -"crypto/x509v3/v3_skey.c", -"crypto/x509v3/v3_info.c", -"crypto/x509v3/v3_asid.c", -"crypto/x509v3/pcy_tree.c", -"crypto/x509v3/v3_pcons.c", -"crypto/x509v3/v3_bcons.c", -"crypto/x509v3/v3_pku.c", -"crypto/x509v3/v3_ocsp.c", -"crypto/x509v3/pcy_map.c", -"crypto/x509v3/v3_ncons.c", -"crypto/x509v3/v3_purp.c", -"crypto/x509v3/v3_enum.c", -"crypto/x509v3/v3_pmaps.c", -"crypto/x509v3/pcy_node.c", -"crypto/x509v3/v3_pcia.c", -"crypto/x509v3/v3_crld.c", -"crypto/x509v3/v3_pci.c", -"crypto/x509v3/v3_akey.c", -"crypto/x509v3/v3_addr.c", -"crypto/x509v3/v3_int.c", -"crypto/x509v3/v3_alt.c", -"crypto/x509v3/v3_extku.c", -"crypto/x509v3/v3_prn.c", -"crypto/x509v3/pcy_data.c", -"crypto/aes/aes_ofb.c", -"crypto/aes/aes_ctr.c", -"crypto/aes/aes_ecb.c", -"crypto/aes/aes_cfb.c", -"crypto/aes/aes_wrap.c", -"crypto/aes/aes_ige.c", -"crypto/aes/aes_misc.c", -"crypto/pqueue/pqueue.c", -"crypto/sha/sha_one.c", -"crypto/sha/sha_dgst.c", -"crypto/sha/sha512.c", -"crypto/sha/sha1_one.c", -"crypto/sha/sha1dgst.c", -"crypto/sha/sha256.c", -"crypto/whrlpool/wp_dgst.c", -"crypto/objects/obj_xref.c", -"crypto/objects/o_names.c", -"crypto/objects/obj_err.c", -"crypto/objects/obj_dat.c", -"crypto/objects/obj_lib.c", -"crypto/mem.c", -"crypto/fips_ers.c", -"crypto/o_fips.c", -"crypto/engine/eng_rdrand.c", -"crypto/engine/eng_err.c", -"crypto/engine/tb_ecdsa.c", -"crypto/engine/tb_rsa.c", -"crypto/engine/tb_cipher.c", -"crypto/engine/tb_dsa.c", -"crypto/engine/eng_lib.c", -"crypto/engine/tb_asnmth.c", -"crypto/engine/tb_ecdh.c", -"crypto/engine/tb_dh.c", -"crypto/engine/tb_store.c", -"crypto/engine/eng_init.c", -"crypto/engine/eng_cnf.c", -"crypto/engine/eng_all.c", -"crypto/engine/tb_digest.c", -"crypto/engine/tb_pkmeth.c", -"crypto/engine/eng_table.c", -"crypto/engine/eng_ctrl.c", -"crypto/engine/eng_list.c", -"crypto/engine/eng_cryptodev.c", -"crypto/engine/eng_pkey.c", -"crypto/engine/tb_rand.c", -"crypto/engine/eng_openssl.c", -"crypto/engine/eng_fat.c", -"crypto/engine/eng_dyn.c", -"crypto/ts/ts_rsp_verify.c", -"crypto/ts/ts_req_print.c", -"crypto/ts/ts_verify_ctx.c", -"crypto/ts/ts_req_utils.c", -"crypto/ts/ts_err.c", -"crypto/ts/ts_rsp_print.c", -"crypto/ts/ts_rsp_utils.c", -"crypto/ts/ts_lib.c", -"crypto/ts/ts_conf.c", -"crypto/ts/ts_asn1.c", -"crypto/ts/ts_rsp_sign.c", -"crypto/ocsp/ocsp_ext.c", -"crypto/ocsp/ocsp_cl.c", -"crypto/ocsp/ocsp_ht.c", -"crypto/ocsp/ocsp_lib.c", -"crypto/ocsp/ocsp_srv.c", -"crypto/ocsp/ocsp_vfy.c", -"crypto/ocsp/ocsp_err.c", -"crypto/ocsp/ocsp_prn.c", -"crypto/ocsp/ocsp_asn.c", -"crypto/bf/bf_cfb64.c", -"crypto/bf/bf_ecb.c", -"crypto/bf/bf_enc.c", -"crypto/bf/bf_skey.c", -"crypto/bf/bf_ofb64.c", -"crypto/idea/i_skey.c", -"crypto/idea/i_ofb64.c", -"crypto/idea/i_cbc.c", -"crypto/idea/i_ecb.c", -"crypto/idea/i_cfb64.c", -"crypto/cmac/cm_ameth.c", -"crypto/cmac/cmac.c", -"crypto/cmac/cm_pmeth.c", -"crypto/dh/dh_lib.c", -"crypto/dh/dh_key.c", -"crypto/dh/dh_asn1.c", -"crypto/dh/dh_depr.c", -"crypto/dh/dh_pmeth.c", -"crypto/dh/dh_prn.c", -"crypto/dh/dh_gen.c", -"crypto/dh/dh_ameth.c", -"crypto/dh/dh_check.c", -"crypto/dh/dh_err.c", -"crypto/dh/dh_kdf.c", -"crypto/dh/dh_rfc5114.c", -"crypto/modes/ccm128.c", -"crypto/modes/ofb128.c", -"crypto/modes/cts128.c", -"crypto/modes/ctr128.c", -"crypto/modes/gcm128.c", -"crypto/modes/cbc128.c", -"crypto/modes/cfb128.c", -"crypto/modes/xts128.c", -"crypto/modes/wrap128.c", -"crypto/camellia/cmll_cfb.c", -"crypto/camellia/cmll_ecb.c", -"crypto/camellia/cmll_utl.c", -"crypto/camellia/cmll_misc.c", -"crypto/camellia/cmll_ofb.c", -"crypto/camellia/cmll_ctr.c", -"crypto/seed/seed_ecb.c", -"crypto/seed/seed_cbc.c", -"crypto/seed/seed.c", -"crypto/seed/seed_ofb.c", -"crypto/seed/seed_cfb.c", -"crypto/txt_db/txt_db.c", -"crypto/cpt_err.c", -"crypto/pem/pem_pk8.c", -"crypto/pem/pem_lib.c", -"crypto/pem/pem_sign.c", -"crypto/pem/pem_all.c", -"crypto/pem/pem_info.c", -"crypto/pem/pem_pkey.c", -"crypto/pem/pem_seal.c", -"crypto/pem/pem_err.c", -"crypto/pem/pem_xaux.c", -"crypto/pem/pvkfmt.c", -"crypto/pem/pem_x509.c", -"crypto/pem/pem_oth.c", -"crypto/rand/rand_lib.c", -"crypto/rand/randfile.c", -"crypto/rand/rand_os2.c", -"crypto/rand/rand_unix.c", -"crypto/rand/rand_nw.c", -"crypto/rand/md_rand.c", -"crypto/rand/rand_err.c", -"crypto/rand/rand_win.c", -"crypto/rand/rand_egd.c", -"crypto/cversion.c", -"crypto/cast/c_ecb.c", -"crypto/cast/c_skey.c", -"crypto/cast/c_ofb64.c", -"crypto/cast/c_enc.c", -"crypto/cast/c_cfb64.c", -"crypto/o_time.c", -"crypto/mdc2/mdc2dgst.c", -"crypto/mdc2/mdc2_one.c", -"crypto/rc4/rc4_utl.c", -"crypto/ui/ui_compat.c", -"crypto/ui/ui_util.c", -"crypto/ui/ui_lib.c", -"crypto/ui/ui_err.c", -"crypto/ui/ui_openssl.c", -"crypto/bio/bf_buff.c", -"crypto/bio/bss_null.c", -"crypto/bio/bss_acpt.c", -"crypto/bio/bss_conn.c", -"crypto/bio/bss_fd.c", -"crypto/bio/bf_null.c", -"crypto/bio/bio_err.c", -"crypto/bio/bss_sock.c", -"crypto/bio/bss_mem.c", -"crypto/bio/b_dump.c", -"crypto/bio/b_print.c", -"crypto/bio/b_sock.c", -"crypto/bio/bss_dgram.c", -"crypto/bio/bf_nbio.c", -"crypto/bio/bio_lib.c", -"crypto/bio/bss_file.c", -"crypto/bio/bss_bio.c", -"crypto/bio/bss_log.c", -"crypto/bio/bio_cb.c", -"crypto/o_init.c", -"crypto/rc2/rc2_skey.c", -"crypto/rc2/rc2_cbc.c", -"crypto/rc2/rc2cfb64.c", -"crypto/rc2/rc2_ecb.c", -"crypto/rc2/rc2ofb64.c", -"crypto/bn/bn_x931p.c", -"crypto/bn/bn_blind.c", -"crypto/bn/bn_gf2m.c", -"crypto/bn/bn_const.c", -"crypto/bn/bn_sqr.c", -"crypto/bn/bn_nist.c", -"crypto/bn/bn_rand.c", -"crypto/bn/bn_err.c", -"crypto/bn/bn_div.c", -"crypto/bn/bn_kron.c", -"crypto/bn/bn_ctx.c", -"crypto/bn/bn_shift.c", -"crypto/bn/bn_mod.c", -"crypto/bn/bn_exp2.c", -"crypto/bn/bn_word.c", -"crypto/bn/bn_add.c", -"crypto/bn/bn_exp.c", -"crypto/bn/bn_mont.c", -"crypto/bn/bn_print.c", -"crypto/bn/bn_mul.c", -"crypto/bn/bn_prime.c", -"crypto/bn/bn_depr.c", -"crypto/bn/bn_gcd.c", -"crypto/bn/bn_mpi.c", -"crypto/bn/bn_sqrt.c", -"crypto/bn/bn_recp.c", -"crypto/bn/bn_lib.c", -"crypto/ripemd/rmd_dgst.c", -"crypto/ripemd/rmd_one.c", -"crypto/rsa/rsa_x931.c", -"crypto/rsa/rsa_depr.c", -"crypto/rsa/rsa_saos.c", -"crypto/rsa/rsa_crpt.c", -"crypto/rsa/rsa_pss.c", -"crypto/rsa/rsa_oaep.c", -"crypto/rsa/rsa_null.c", -"crypto/rsa/rsa_gen.c", -"crypto/rsa/rsa_prn.c", -"crypto/rsa/rsa_pmeth.c", -"crypto/rsa/rsa_asn1.c", -"crypto/rsa/rsa_ssl.c", -"crypto/rsa/rsa_ameth.c", -"crypto/rsa/rsa_pk1.c", -"crypto/rsa/rsa_err.c", -"crypto/rsa/rsa_lib.c", -"crypto/rsa/rsa_none.c", -"crypto/rsa/rsa_chk.c", -"crypto/rsa/rsa_eay.c", -"crypto/rsa/rsa_sign.c", -"crypto/srp/srp_lib.c", -"crypto/srp/srp_vfy.c", -"crypto/err/err.c", -"crypto/err/err_prn.c", -"crypto/err/err_all.c", -"crypto/mem_clr.c", -"crypto/rc4/rc4_skey.c", -"crypto/rc4/rc4_enc.c", -"crypto/camellia/camellia.c", -"crypto/camellia/cmll_cbc.c", -#"crypto/aes/aes_x86core.c", -"crypto/aes/aes_core.c", -"crypto/aes/aes_cbc.c", -"crypto/whrlpool/wp_block.c", -"crypto/bn/bn_asm.c", -] - -#env.drivers_sources+=openssl_sources - -env_drivers.Append(CPPPATH=["#drivers/builtin_openssl2/crypto"]) -env_drivers.Append(CPPPATH=["#drivers/builtin_openssl2/openssl"]) -env_drivers.Append(CPPPATH=["#drivers/builtin_openssl2/crypto/evp"]) -env_drivers.Append(CPPPATH=["#drivers/builtin_openssl2/crypto/asn1"]) -env_drivers.Append(CPPPATH=["#drivers/builtin_openssl2/crypto/modes"]) -#env_ssl.Append(CPPPATH=["#drivers/builtin_openssl2/crypto/store"]) -env_drivers.Append(CPPFLAGS=["-DOPENSSL_NO_ASM","-DOPENSSL_THREADS","-DL_ENDIAN"]) - -# Workaround for compilation error with GCC/Clang when -Werror is too greedy (GH-4517) -import os -if not (os.name=="nt" and os.getenv("VSINSTALLDIR")!=None): # not Windows and not MSVC - env_drivers.Append(CFLAGS=["-Wno-error=implicit-function-declaration"]) - -env_drivers.add_source_files(env.drivers_sources,openssl_sources) diff --git a/drivers/builtin_openssl2/crypto/rand/rand_win.c b/drivers/builtin_openssl2/crypto/rand/rand_win.c deleted file mode 100644 index 06670ae017..0000000000 --- a/drivers/builtin_openssl2/crypto/rand/rand_win.c +++ /dev/null @@ -1,752 +0,0 @@ -/* crypto/rand/rand_win.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * 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 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF 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. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. - * - * 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. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED 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 OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF 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 product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - -#include "cryptlib.h" -#include <openssl/rand.h> -#include "rand_lcl.h" - -#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) -# include <windows.h> -# ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0400 -# endif -# include <wincrypt.h> -# include <tlhelp32.h> - -/* - * Limit the time spent walking through the heap, processes, threads and - * modules to a maximum of 1000 miliseconds each, unless CryptoGenRandom - * failed - */ -# define MAXDELAY 1000 - -/* - * Intel hardware RNG CSP -- available from - * http://developer.intel.com/design/security/rng/redist_license.htm - */ -# define PROV_INTEL_SEC 22 -# define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider" - -static void readtimer(void); -static void readscreen(void); - -/* - * It appears like CURSORINFO, PCURSORINFO and LPCURSORINFO are only defined - * when WINVER is 0x0500 and up, which currently only happens on Win2000. - * Unfortunately, those are typedefs, so they're a little bit difficult to - * detect properly. On the other hand, the macro CURSOR_SHOWING is defined - * within the same conditional, so it can be use to detect the absence of - * said typedefs. - */ - -# ifndef CURSOR_SHOWING -/* - * Information about the global cursor. - */ -typedef struct tagCURSORINFO { - DWORD cbSize; - DWORD flags; - HCURSOR hCursor; - POINT ptScreenPos; -} CURSORINFO, *PCURSORINFO, *LPCURSORINFO; - -# define CURSOR_SHOWING 0x00000001 -# endif /* CURSOR_SHOWING */ - -# if !defined(OPENSSL_SYS_WINCE) -typedef BOOL(WINAPI *CRYPTACQUIRECONTEXTW) (HCRYPTPROV *, LPCWSTR, LPCWSTR, - DWORD, DWORD); -typedef BOOL(WINAPI *CRYPTGENRANDOM) (HCRYPTPROV, DWORD, BYTE *); -typedef BOOL(WINAPI *CRYPTRELEASECONTEXT) (HCRYPTPROV, DWORD); - -typedef HWND(WINAPI *GETFOREGROUNDWINDOW) (VOID); -typedef BOOL(WINAPI *GETCURSORINFO) (PCURSORINFO); -typedef DWORD(WINAPI *GETQUEUESTATUS) (UINT); - -typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD); -typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE); -typedef BOOL(WINAPI *HEAP32FIRST) (LPHEAPENTRY32, DWORD, size_t); -typedef BOOL(WINAPI *HEAP32NEXT) (LPHEAPENTRY32); -typedef BOOL(WINAPI *HEAP32LIST) (HANDLE, LPHEAPLIST32); -typedef BOOL(WINAPI *PROCESS32) (HANDLE, LPPROCESSENTRY32); -typedef BOOL(WINAPI *THREAD32) (HANDLE, LPTHREADENTRY32); -typedef BOOL(WINAPI *MODULE32) (HANDLE, LPMODULEENTRY32); - -# include <lmcons.h> -# include <lmstats.h> -# if 1 -/* - * The NET API is Unicode only. It requires the use of the UNICODE macro. - * When UNICODE is defined LPTSTR becomes LPWSTR. LMSTR was was added to the - * Platform SDK to allow the NET API to be used in non-Unicode applications - * provided that Unicode strings were still used for input. LMSTR is defined - * as LPWSTR. - */ -typedef NET_API_STATUS(NET_API_FUNCTION *NETSTATGET) - (LPWSTR, LPWSTR, DWORD, DWORD, LPBYTE *); -typedef NET_API_STATUS(NET_API_FUNCTION *NETFREE) (LPBYTE); -# endif /* 1 */ -# endif /* !OPENSSL_SYS_WINCE */ - -int RAND_poll(void) -{ - MEMORYSTATUS m; - HCRYPTPROV hProvider = 0; - DWORD w; - int good = 0; - -# if defined(OPENSSL_SYS_WINCE) -# if defined(_WIN32_WCE) && _WIN32_WCE>=300 - /* - * Even though MSDN says _WIN32_WCE>=210, it doesn't seem to be available - * in commonly available implementations prior 300... - */ - { - BYTE buf[64]; - /* poll the CryptoAPI PRNG */ - /* The CryptoAPI returns sizeof(buf) bytes of randomness */ - if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) { - if (CryptGenRandom(hProvider, sizeof(buf), buf)) - RAND_add(buf, sizeof(buf), sizeof(buf)); - CryptReleaseContext(hProvider, 0); - } - } -# endif -# else /* OPENSSL_SYS_WINCE */ - /* - * None of below libraries are present on Windows CE, which is - * why we #ifndef the whole section. This also excuses us from - * handling the GetProcAddress issue. The trouble is that in - * real Win32 API GetProcAddress is available in ANSI flavor - * only. In WinCE on the other hand GetProcAddress is a macro - * most commonly defined as GetProcAddressW, which accepts - * Unicode argument. If we were to call GetProcAddress under - * WinCE, I'd recommend to either redefine GetProcAddress as - * GetProcAddressA (there seem to be one in common CE spec) or - * implement own shim routine, which would accept ANSI argument - * and expand it to Unicode. - */ - { - /* load functions dynamically - not available on all systems */ - HMODULE advapi = LoadLibrary(TEXT("ADVAPI32.DLL")); - HMODULE kernel = LoadLibrary(TEXT("KERNEL32.DLL")); - HMODULE user = NULL; - HMODULE netapi = LoadLibrary(TEXT("NETAPI32.DLL")); - CRYPTACQUIRECONTEXTW acquire = NULL; - CRYPTGENRANDOM gen = NULL; - CRYPTRELEASECONTEXT release = NULL; - NETSTATGET netstatget = NULL; - NETFREE netfree = NULL; - BYTE buf[64]; - - if (netapi) { - netstatget = - (NETSTATGET) GetProcAddress(netapi, "NetStatisticsGet"); - netfree = (NETFREE) GetProcAddress(netapi, "NetApiBufferFree"); - } - - if (netstatget && netfree) { - LPBYTE outbuf; - /* - * NetStatisticsGet() is a Unicode only function - * STAT_WORKSTATION_0 contains 45 fields and STAT_SERVER_0 - * contains 17 fields. We treat each field as a source of one - * byte of entropy. - */ - - if (netstatget(NULL, L"LanmanWorkstation", 0, 0, &outbuf) == 0) { - RAND_add(outbuf, sizeof(STAT_WORKSTATION_0), 45); - netfree(outbuf); - } - if (netstatget(NULL, L"LanmanServer", 0, 0, &outbuf) == 0) { - RAND_add(outbuf, sizeof(STAT_SERVER_0), 17); - netfree(outbuf); - } - } - - if (netapi) - FreeLibrary(netapi); - - /* - * It appears like this can cause an exception deep within - * ADVAPI32.DLL at random times on Windows 2000. Reported by Jeffrey - * Altman. Only use it on NT. - */ - - if (advapi) { - /* - * If it's available, then it's available in both ANSI - * and UNICODE flavors even in Win9x, documentation says. - * We favor Unicode... - */ - acquire = (CRYPTACQUIRECONTEXTW) GetProcAddress(advapi, - "CryptAcquireContextW"); - gen = (CRYPTGENRANDOM) GetProcAddress(advapi, "CryptGenRandom"); - release = (CRYPTRELEASECONTEXT) GetProcAddress(advapi, - "CryptReleaseContext"); - } - - if (acquire && gen && release) { - /* poll the CryptoAPI PRNG */ - /* The CryptoAPI returns sizeof(buf) bytes of randomness */ - if (acquire(&hProvider, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) { - if (gen(hProvider, sizeof(buf), buf) != 0) { - RAND_add(buf, sizeof(buf), 0); - good = 1; -# if 0 - printf("randomness from PROV_RSA_FULL\n"); -# endif - } - release(hProvider, 0); - } - - /* poll the Pentium PRG with CryptoAPI */ - if (acquire(&hProvider, 0, INTEL_DEF_PROV, PROV_INTEL_SEC, 0)) { - if (gen(hProvider, sizeof(buf), buf) != 0) { - RAND_add(buf, sizeof(buf), sizeof(buf)); - good = 1; -# if 0 - printf("randomness from PROV_INTEL_SEC\n"); -# endif - } - release(hProvider, 0); - } - } - - if (advapi) - FreeLibrary(advapi); - - if ((!check_winnt() || - !OPENSSL_isservice()) && - (user = LoadLibrary(TEXT("USER32.DLL")))) { - GETCURSORINFO cursor; - GETFOREGROUNDWINDOW win; - GETQUEUESTATUS queue; - - win = - (GETFOREGROUNDWINDOW) GetProcAddress(user, - "GetForegroundWindow"); - cursor = (GETCURSORINFO) GetProcAddress(user, "GetCursorInfo"); - queue = (GETQUEUESTATUS) GetProcAddress(user, "GetQueueStatus"); - - if (win) { - /* window handle */ - HWND h = win(); - RAND_add(&h, sizeof(h), 0); - } - if (cursor) { - /* - * unfortunately, its not safe to call GetCursorInfo() on NT4 - * even though it exists in SP3 (or SP6) and higher. - */ - if (check_winnt() && !check_win_minplat(5)) - cursor = 0; - } - if (cursor) { - /* cursor position */ - /* assume 2 bytes of entropy */ - CURSORINFO ci; - ci.cbSize = sizeof(CURSORINFO); - if (cursor(&ci)) - RAND_add(&ci, ci.cbSize, 2); - } - - if (queue) { - /* message queue status */ - /* assume 1 byte of entropy */ - w = queue(QS_ALLEVENTS); - RAND_add(&w, sizeof(w), 1); - } - - FreeLibrary(user); - } - - /*- - * Toolhelp32 snapshot: enumerate processes, threads, modules and heap - * http://msdn.microsoft.com/library/psdk/winbase/toolhelp_5pfd.htm - * (Win 9x and 2000 only, not available on NT) - * - * This seeding method was proposed in Peter Gutmann, Software - * Generation of Practically Strong Random Numbers, - * http://www.usenix.org/publications/library/proceedings/sec98/gutmann.html - * revised version at http://www.cryptoengines.com/~peter/06_random.pdf - * (The assignment of entropy estimates below is arbitrary, but based - * on Peter's analysis the full poll appears to be safe. Additional - * interactive seeding is encouraged.) - */ - - if (kernel) { - CREATETOOLHELP32SNAPSHOT snap; - CLOSETOOLHELP32SNAPSHOT close_snap; - HANDLE handle; - - HEAP32FIRST heap_first; - HEAP32NEXT heap_next; - HEAP32LIST heaplist_first, heaplist_next; - PROCESS32 process_first, process_next; - THREAD32 thread_first, thread_next; - MODULE32 module_first, module_next; - - HEAPLIST32 hlist; - HEAPENTRY32 hentry; - PROCESSENTRY32 p; - THREADENTRY32 t; - MODULEENTRY32 m; - DWORD starttime = 0; - - snap = (CREATETOOLHELP32SNAPSHOT) - GetProcAddress(kernel, "CreateToolhelp32Snapshot"); - close_snap = (CLOSETOOLHELP32SNAPSHOT) - GetProcAddress(kernel, "CloseToolhelp32Snapshot"); - heap_first = (HEAP32FIRST) GetProcAddress(kernel, "Heap32First"); - heap_next = (HEAP32NEXT) GetProcAddress(kernel, "Heap32Next"); - heaplist_first = - (HEAP32LIST) GetProcAddress(kernel, "Heap32ListFirst"); - heaplist_next = - (HEAP32LIST) GetProcAddress(kernel, "Heap32ListNext"); - process_first = - (PROCESS32) GetProcAddress(kernel, "Process32First"); - process_next = - (PROCESS32) GetProcAddress(kernel, "Process32Next"); - thread_first = (THREAD32) GetProcAddress(kernel, "Thread32First"); - thread_next = (THREAD32) GetProcAddress(kernel, "Thread32Next"); - module_first = (MODULE32) GetProcAddress(kernel, "Module32First"); - module_next = (MODULE32) GetProcAddress(kernel, "Module32Next"); - - if (snap && heap_first && heap_next && heaplist_first && - heaplist_next && process_first && process_next && - thread_first && thread_next && module_first && - module_next && (handle = snap(TH32CS_SNAPALL, 0)) - != INVALID_HANDLE_VALUE) { - /* heap list and heap walking */ - /* - * HEAPLIST32 contains 3 fields that will change with each - * entry. Consider each field a source of 1 byte of entropy. - * HEAPENTRY32 contains 5 fields that will change with each - * entry. Consider each field a source of 1 byte of entropy. - */ - ZeroMemory(&hlist, sizeof(HEAPLIST32)); - hlist.dwSize = sizeof(HEAPLIST32); - if (good) - starttime = GetTickCount(); -# ifdef _MSC_VER - if (heaplist_first(handle, &hlist)) { - /* - * following discussion on dev ML, exception on WinCE (or - * other Win platform) is theoretically of unknown - * origin; prevent infinite loop here when this - * theoretical case occurs; otherwise cope with the - * expected (MSDN documented) exception-throwing - * behaviour of Heap32Next() on WinCE. - * - * based on patch in original message by Tanguy Fautré - * (2009/03/02) Subject: RAND_poll() and - * CreateToolhelp32Snapshot() stability - */ - int ex_cnt_limit = 42; - do { - RAND_add(&hlist, hlist.dwSize, 3); - __try { - ZeroMemory(&hentry, sizeof(HEAPENTRY32)); - hentry.dwSize = sizeof(HEAPENTRY32); - if (heap_first(&hentry, - hlist.th32ProcessID, - hlist.th32HeapID)) { - int entrycnt = 80; - do - RAND_add(&hentry, hentry.dwSize, 5); - while (heap_next(&hentry) - && (!good - || (GetTickCount() - starttime) < - MAXDELAY) - && --entrycnt > 0); - } - } - __except(EXCEPTION_EXECUTE_HANDLER) { - /* - * ignore access violations when walking the heap - * list - */ - ex_cnt_limit--; - } - } while (heaplist_next(handle, &hlist) - && (!good - || (GetTickCount() - starttime) < MAXDELAY) - && ex_cnt_limit > 0); - } -# else - if (heaplist_first(handle, &hlist)) { - do { - RAND_add(&hlist, hlist.dwSize, 3); - hentry.dwSize = sizeof(HEAPENTRY32); - if (heap_first(&hentry, - hlist.th32ProcessID, - hlist.th32HeapID)) { - int entrycnt = 80; - do - RAND_add(&hentry, hentry.dwSize, 5); - while (heap_next(&hentry) - && --entrycnt > 0); - } - } while (heaplist_next(handle, &hlist) - && (!good - || (GetTickCount() - starttime) < MAXDELAY)); - } -# endif - - /* process walking */ - /* - * PROCESSENTRY32 contains 9 fields that will change with - * each entry. Consider each field a source of 1 byte of - * entropy. - */ - p.dwSize = sizeof(PROCESSENTRY32); - - if (good) - starttime = GetTickCount(); - if (process_first(handle, &p)) - do - RAND_add(&p, p.dwSize, 9); - while (process_next(handle, &p) - && (!good - || (GetTickCount() - starttime) < MAXDELAY)); - - /* thread walking */ - /* - * THREADENTRY32 contains 6 fields that will change with each - * entry. Consider each field a source of 1 byte of entropy. - */ - t.dwSize = sizeof(THREADENTRY32); - if (good) - starttime = GetTickCount(); - if (thread_first(handle, &t)) - do - RAND_add(&t, t.dwSize, 6); - while (thread_next(handle, &t) - && (!good - || (GetTickCount() - starttime) < MAXDELAY)); - - /* module walking */ - /* - * MODULEENTRY32 contains 9 fields that will change with each - * entry. Consider each field a source of 1 byte of entropy. - */ - m.dwSize = sizeof(MODULEENTRY32); - if (good) - starttime = GetTickCount(); - if (module_first(handle, &m)) - do - RAND_add(&m, m.dwSize, 9); - while (module_next(handle, &m) - && (!good - || (GetTickCount() - starttime) < MAXDELAY)); - if (close_snap) - close_snap(handle); - else - CloseHandle(handle); - - } - - FreeLibrary(kernel); - } - } -# endif /* !OPENSSL_SYS_WINCE */ - - /* timer data */ - readtimer(); - - /* memory usage statistics */ - GlobalMemoryStatus(&m); - RAND_add(&m, sizeof(m), 1); - - /* process ID */ - w = GetCurrentProcessId(); - RAND_add(&w, sizeof(w), 1); - -# if 0 - printf("Exiting RAND_poll\n"); -# endif - - return (1); -} - -int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam) -{ - double add_entropy = 0; - - switch (iMsg) { - case WM_KEYDOWN: - { - static WPARAM key; - if (key != wParam) - add_entropy = 0.05; - key = wParam; - } - break; - case WM_MOUSEMOVE: - { - static int lastx, lasty, lastdx, lastdy; - int x, y, dx, dy; - - x = LOWORD(lParam); - y = HIWORD(lParam); - dx = lastx - x; - dy = lasty - y; - if (dx != 0 && dy != 0 && dx - lastdx != 0 && dy - lastdy != 0) - add_entropy = .2; - lastx = x, lasty = y; - lastdx = dx, lastdy = dy; - } - break; - } - - readtimer(); - RAND_add(&iMsg, sizeof(iMsg), add_entropy); - RAND_add(&wParam, sizeof(wParam), 0); - RAND_add(&lParam, sizeof(lParam), 0); - - return (RAND_status()); -} - -void RAND_screen(void) -{ /* function available for backward - * compatibility */ - RAND_poll(); - readscreen(); -} - -/* feed timing information to the PRNG */ -static void readtimer(void) -{ - DWORD w; - LARGE_INTEGER l; - static int have_perfc = 1; -# if defined(_MSC_VER) && defined(_M_X86) - static int have_tsc = 1; - DWORD cyclecount; - - if (have_tsc) { - __try { - __asm { - _emit 0x0f _emit 0x31 mov cyclecount, eax} - RAND_add(&cyclecount, sizeof(cyclecount), 1); - } - __except(EXCEPTION_EXECUTE_HANDLER) { - have_tsc = 0; - } - } -# else -# define have_tsc 0 -# endif - - if (have_perfc) { - if (QueryPerformanceCounter(&l) == 0) - have_perfc = 0; - else - RAND_add(&l, sizeof(l), 0); - } - - if (!have_tsc && !have_perfc) { - w = GetTickCount(); - RAND_add(&w, sizeof(w), 0); - } -} - -/* feed screen contents to PRNG */ -/***************************************************************************** - * - * Created 960901 by Gertjan van Oosten, gertjan@West.NL, West Consulting B.V. - * - * Code adapted from - * <URL:http://support.microsoft.com/default.aspx?scid=kb;[LN];97193>; - * the original copyright message is: - * - * (C) Copyright Microsoft Corp. 1993. All rights reserved. - * - * You have a royalty-free right to use, modify, reproduce and - * distribute the Sample Files (and/or any modified version) in - * any way you find useful, provided that you agree that - * Microsoft has no warranty obligations or liability for any - * Sample Application Files which are modified. - */ - -static void readscreen(void) -{ -# if !defined(OPENSSL_SYS_WINCE) && !defined(OPENSSL_SYS_WIN32_CYGWIN) - HDC hScrDC; /* screen DC */ - HBITMAP hBitmap; /* handle for our bitmap */ - BITMAP bm; /* bitmap properties */ - unsigned int size; /* size of bitmap */ - char *bmbits; /* contents of bitmap */ - int w; /* screen width */ - int h; /* screen height */ - int y; /* y-coordinate of screen lines to grab */ - int n = 16; /* number of screen lines to grab at a time */ - BITMAPINFOHEADER bi; /* info about the bitmap */ - - if (check_winnt() && OPENSSL_isservice() > 0) - return; - - /* Get a reference to the screen DC */ - hScrDC = GetDC(NULL); - - /* Get screen resolution */ - w = GetDeviceCaps(hScrDC, HORZRES); - h = GetDeviceCaps(hScrDC, VERTRES); - - /* Create a bitmap compatible with the screen DC */ - hBitmap = CreateCompatibleBitmap(hScrDC, w, n); - - /* Get bitmap properties */ - GetObject(hBitmap, sizeof(BITMAP), (LPSTR) & bm); - size = (unsigned int)bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes; - - bi.biSize = sizeof(BITMAPINFOHEADER); - bi.biWidth = bm.bmWidth; - bi.biHeight = bm.bmHeight; - bi.biPlanes = bm.bmPlanes; - bi.biBitCount = bm.bmBitsPixel; - bi.biCompression = BI_RGB; - bi.biSizeImage = 0; - bi.biXPelsPerMeter = 0; - bi.biYPelsPerMeter = 0; - bi.biClrUsed = 0; - bi.biClrImportant = 0; - - bmbits = OPENSSL_malloc(size); - if (bmbits) { - /* Now go through the whole screen, repeatedly grabbing n lines */ - for (y = 0; y < h - n; y += n) { - unsigned char md[MD_DIGEST_LENGTH]; - - /* Copy the bits of the current line range into the buffer */ - GetDIBits(hScrDC, hBitmap, y, n, - bmbits, (BITMAPINFO *) & bi, DIB_RGB_COLORS); - - /* Get the hash of the bitmap */ - MD(bmbits, size, md); - - /* Seed the random generator with the hash value */ - RAND_add(md, MD_DIGEST_LENGTH, 0); - } - - OPENSSL_free(bmbits); - } - - /* Clean up */ - DeleteObject(hBitmap); - ReleaseDC(NULL, hScrDC); -# endif /* !OPENSSL_SYS_WINCE */ -} - -#endif diff --git a/drivers/builtin_openssl2/openssl/dtls1.h b/drivers/builtin_openssl2/openssl/dtls1.h deleted file mode 100644 index 64ad3c87d0..0000000000 --- a/drivers/builtin_openssl2/openssl/dtls1.h +++ /dev/null @@ -1,275 +0,0 @@ -/* ssl/dtls1.h */ -/* - * DTLS implementation written by Nagendra Modadugu - * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. - */ -/* ==================================================================== - * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. - * - * 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. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED 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 OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF 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 product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - -#ifndef HEADER_DTLS1_H -# define HEADER_DTLS1_H - -# include <openssl/buffer.h> -# include <openssl/pqueue.h> -# ifdef OPENSSL_SYS_VMS -# include <resource.h> -# include <sys/timeb.h> -# endif -# ifdef OPENSSL_SYS_WIN32 -/* Needed for struct timeval */ -# include <winsock.h> -#ifdef X509_NAME -#undef X509_NAME -#endif -# elif defined(OPENSSL_SYS_NETWARE) && !defined(_WINSOCK2API_) -# include <sys/timeval.h> -# else -# if defined(OPENSSL_SYS_VXWORKS) -# include <sys/times.h> -# else -# include <sys/time.h> -# endif -# endif - -#ifdef __cplusplus -extern "C" { -#endif - -# define DTLS1_VERSION 0xFEFF -# define DTLS1_2_VERSION 0xFEFD -# define DTLS_MAX_VERSION DTLS1_2_VERSION -# define DTLS1_VERSION_MAJOR 0xFE - -# define DTLS1_BAD_VER 0x0100 - -/* Special value for method supporting multiple versions */ -# define DTLS_ANY_VERSION 0x1FFFF - -# if 0 -/* this alert description is not specified anywhere... */ -# define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE 110 -# endif - -/* lengths of messages */ -# define DTLS1_COOKIE_LENGTH 256 - -# define DTLS1_RT_HEADER_LENGTH 13 - -# define DTLS1_HM_HEADER_LENGTH 12 - -# define DTLS1_HM_BAD_FRAGMENT -2 -# define DTLS1_HM_FRAGMENT_RETRY -3 - -# define DTLS1_CCS_HEADER_LENGTH 1 - -# ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE -# define DTLS1_AL_HEADER_LENGTH 7 -# else -# define DTLS1_AL_HEADER_LENGTH 2 -# endif - -# ifndef OPENSSL_NO_SSL_INTERN - -# ifndef OPENSSL_NO_SCTP -# define DTLS1_SCTP_AUTH_LABEL "EXPORTER_DTLS_OVER_SCTP" -# endif - -/* Max MTU overhead we know about so far is 40 for IPv6 + 8 for UDP */ -# define DTLS1_MAX_MTU_OVERHEAD 48 - -typedef struct dtls1_bitmap_st { - unsigned long map; /* track 32 packets on 32-bit systems and 64 - * - on 64-bit systems */ - unsigned char max_seq_num[8]; /* max record number seen so far, 64-bit - * value in big-endian encoding */ -} DTLS1_BITMAP; - -struct dtls1_retransmit_state { - EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */ - EVP_MD_CTX *write_hash; /* used for mac generation */ -# ifndef OPENSSL_NO_COMP - COMP_CTX *compress; /* compression */ -# else - char *compress; -# endif - SSL_SESSION *session; - unsigned short epoch; -}; - -struct hm_header_st { - unsigned char type; - unsigned long msg_len; - unsigned short seq; - unsigned long frag_off; - unsigned long frag_len; - unsigned int is_ccs; - struct dtls1_retransmit_state saved_retransmit_state; -}; - -struct ccs_header_st { - unsigned char type; - unsigned short seq; -}; - -struct dtls1_timeout_st { - /* Number of read timeouts so far */ - unsigned int read_timeouts; - /* Number of write timeouts so far */ - unsigned int write_timeouts; - /* Number of alerts received so far */ - unsigned int num_alerts; -}; - -typedef struct record_pqueue_st { - unsigned short epoch; - pqueue q; -} record_pqueue; - -typedef struct hm_fragment_st { - struct hm_header_st msg_header; - unsigned char *fragment; - unsigned char *reassembly; -} hm_fragment; - -typedef struct dtls1_state_st { - unsigned int send_cookie; - unsigned char cookie[DTLS1_COOKIE_LENGTH]; - unsigned char rcvd_cookie[DTLS1_COOKIE_LENGTH]; - unsigned int cookie_len; - /* - * The current data and handshake epoch. This is initially - * undefined, and starts at zero once the initial handshake is - * completed - */ - unsigned short r_epoch; - unsigned short w_epoch; - /* records being received in the current epoch */ - DTLS1_BITMAP bitmap; - /* renegotiation starts a new set of sequence numbers */ - DTLS1_BITMAP next_bitmap; - /* handshake message numbers */ - unsigned short handshake_write_seq; - unsigned short next_handshake_write_seq; - unsigned short handshake_read_seq; - /* save last sequence number for retransmissions */ - unsigned char last_write_sequence[8]; - /* Received handshake records (processed and unprocessed) */ - record_pqueue unprocessed_rcds; - record_pqueue processed_rcds; - /* Buffered handshake messages */ - pqueue buffered_messages; - /* Buffered (sent) handshake records */ - pqueue sent_messages; - /* - * Buffered application records. Only for records between CCS and - * Finished to prevent either protocol violation or unnecessary message - * loss. - */ - record_pqueue buffered_app_data; - /* Is set when listening for new connections with dtls1_listen() */ - unsigned int listen; - unsigned int link_mtu; /* max on-the-wire DTLS packet size */ - unsigned int mtu; /* max DTLS packet size */ - struct hm_header_st w_msg_hdr; - struct hm_header_st r_msg_hdr; - struct dtls1_timeout_st timeout; - /* - * Indicates when the last handshake msg or heartbeat sent will timeout - */ - struct timeval next_timeout; - /* Timeout duration */ - unsigned short timeout_duration; - /* - * storage for Alert/Handshake protocol data received but not yet - * processed by ssl3_read_bytes: - */ - unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH]; - unsigned int alert_fragment_len; - unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH]; - unsigned int handshake_fragment_len; - unsigned int retransmitting; - /* - * Set when the handshake is ready to process peer's ChangeCipherSpec message. - * Cleared after the message has been processed. - */ - unsigned int change_cipher_spec_ok; -# ifndef OPENSSL_NO_SCTP - /* used when SSL_ST_XX_FLUSH is entered */ - int next_state; - int shutdown_received; -# endif -} DTLS1_STATE; - -typedef struct dtls1_record_data_st { - unsigned char *packet; - unsigned int packet_length; - SSL3_BUFFER rbuf; - SSL3_RECORD rrec; -# ifndef OPENSSL_NO_SCTP - struct bio_dgram_sctp_rcvinfo recordinfo; -# endif -} DTLS1_RECORD_DATA; - -# endif - -/* Timeout multipliers (timeout slice is defined in apps/timeouts.h */ -# define DTLS1_TMO_READ_COUNT 2 -# define DTLS1_TMO_WRITE_COUNT 2 - -# define DTLS1_TMO_ALERT_COUNT 12 - -#ifdef __cplusplus -} -#endif -#endif diff --git a/drivers/builtin_zlib/SCsub b/drivers/builtin_zlib/SCsub deleted file mode 100644 index e5c81c0b3b..0000000000 --- a/drivers/builtin_zlib/SCsub +++ /dev/null @@ -1,22 +0,0 @@ -Import('env') - -zlib_sources = [ - - "builtin_zlib/zlib/adler32.c", - "builtin_zlib/zlib/compress.c", - "builtin_zlib/zlib/crc32.c", - "builtin_zlib/zlib/deflate.c", - "builtin_zlib/zlib/infback.c", - "builtin_zlib/zlib/inffast.c", - "builtin_zlib/zlib/inflate.c", - "builtin_zlib/zlib/inftrees.c", - "builtin_zlib/zlib/trees.c", - "builtin_zlib/zlib/uncompr.c", - "builtin_zlib/zlib/zutil.c", - ] - - -env.drivers_sources+=zlib_sources - -#env.add_source_files("core", png_sources) -Export('env') diff --git a/drivers/chibi/SCsub b/drivers/chibi/SCsub deleted file mode 100644 index 9fbb467baa..0000000000 --- a/drivers/chibi/SCsub +++ /dev/null @@ -1,5 +0,0 @@ -Import('env') - -env.add_source_files(env.drivers_sources,"*.cpp") - -Export('env') diff --git a/drivers/convex_decomp/SCsub b/drivers/convex_decomp/SCsub index 6699efef75..ee39fd2631 100644 --- a/drivers/convex_decomp/SCsub +++ b/drivers/convex_decomp/SCsub @@ -1,4 +1,7 @@ +#!/usr/bin/env python + Import('env') -Export('env'); -env.add_source_files(env.drivers_sources,"*.cpp") +env.add_source_files(env.drivers_sources, "*.cpp") + +Export('env') diff --git a/drivers/dds/SCsub b/drivers/dds/SCsub deleted file mode 100644 index 159829384f..0000000000 --- a/drivers/dds/SCsub +++ /dev/null @@ -1,10 +0,0 @@ -Import('env') - - -dds_sources = [ - "dds/texture_loader_dds.cpp" - ] - -env.drivers_sources+=dds_sources - -#env.add_source_files(env.drivers_sources, dds_sources) diff --git a/drivers/etc1/SCsub b/drivers/etc1/SCsub deleted file mode 100644 index 2b9dc1b31c..0000000000 --- a/drivers/etc1/SCsub +++ /dev/null @@ -1,15 +0,0 @@ -Import('env') - - -etc_sources = [ - "etc1/image_etc.cpp", - "etc1/rg_etc1.cpp", - "etc1/texture_loader_pkm.cpp" -] - -if (env["etc1"] != "no"): - env.drivers_sources+=etc_sources - -#env.add_source_files(env.drivers_sources, etc_sources) - -Export('env') diff --git a/drivers/freetype/SCsub b/drivers/freetype/SCsub deleted file mode 100644 index 0c7ab91ba2..0000000000 --- a/drivers/freetype/SCsub +++ /dev/null @@ -1,68 +0,0 @@ -Import('env') - -ft_sources=[\ -"src/autofit/autofit.c",\ -"src/base/ftapi.c",\ -"src/base/ftbase.c",\ -"src/base/ftbbox.c",\ -"src/base/ftbdf.c",\ -"src/base/ftbitmap.c",\ -"src/base/ftcid.c",\ -"src/base/ftdebug.c",\ -"src/base/ftfntfmt.c",\ -"src/base/ftfstype.c",\ -"src/base/ftgasp.c",\ -"src/base/ftglyph.c",\ -"src/base/ftgxval.c",\ -"src/base/ftinit.c",\ -"src/base/ftlcdfil.c",\ -"src/base/ftmm.c",\ -"src/base/ftotval.c",\ -"src/base/ftpatent.c",\ -"src/base/ftpfr.c",\ -"src/base/ftpic.c",\ -"src/base/ftstroke.c",\ -"src/base/ftsynth.c",\ -"src/base/ftsystem.c",\ -"src/base/fttype1.c",\ -"src/base/ftwinfnt.c",\ -"src/bdf/bdf.c",\ -"src/cache/ftcache.c",\ -"src/cff/cff.c",\ -"src/cid/type1cid.c",\ -"src/gxvalid/gxvalid.c",\ -"src/otvalid/otvalid.c",\ -"src/pcf/pcf.c",\ -"src/pfr/pfr.c",\ -"src/psaux/psaux.c",\ -"src/pshinter/pshinter.c",\ -"src/psnames/psnames.c",\ -"src/raster/raster.c",\ -"src/sfnt/sfnt.c",\ -"src/smooth/smooth.c",\ -"src/truetype/truetype.c",\ -"src/type1/type1.c",\ -"src/type42/type42.c",\ -"src/winfonts/winfnt.c",\ -] - - -if (env["freetype"]=="builtin"): - # fix for Windows' shell miserably failing on long lines, split in two libraries - half1=[] - half2=[] - for x in ft_sources: - if (x.find("src/base")==0 or x.find("src/sfnt")==0): - half2.append(x) - else: - half1.append(x) - - lib = env.Library("freetype_builtin1",half2) - env.Append(LIBS=[lib]) - lib = env.Library("freetype_builtin2",half1) - env.Append(LIBS=[lib]) - - env.Append(CPPPATH=["#drivers/freetype/include"]) - - -Export('env') diff --git a/drivers/freetype/src/Jamfile b/drivers/freetype/src/Jamfile deleted file mode 100644 index ebc036983e..0000000000 --- a/drivers/freetype/src/Jamfile +++ /dev/null @@ -1,19 +0,0 @@ -# FreeType 2 src Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) ; - -for xx in $(FT2_COMPONENTS) -{ - SubInclude FT2_TOP $(FT2_SRC_DIR) $(xx) ; -} - -# end of src Jamfile diff --git a/drivers/freetype/src/autofit/Jamfile b/drivers/freetype/src/autofit/Jamfile deleted file mode 100644 index 638b229724..0000000000 --- a/drivers/freetype/src/autofit/Jamfile +++ /dev/null @@ -1,53 +0,0 @@ -# FreeType 2 src/autofit Jamfile -# -# Copyright 2003-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP src autofit ; - -{ - local _sources ; - - # define FT2_AUTOFIT2 to enable experimental latin hinter replacement - if $(FT2_AUTOFIT2) - { - CCFLAGS += FT_OPTION_AUTOFIT2 ; - } - if $(FT2_MULTI) - { - _sources = afangles - afblue - afcjk - afdummy - afglobal - afhints - afindic - aflatin - afloader - afmodule - afpic - afranges - afshaper - afwarp - ; - - if $(FT2_AUTOFIT2) - { - _sources += aflatin2 ; - } - } - else - { - _sources = autofit ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/autofit Jamfile diff --git a/drivers/freetype/src/base/Jamfile b/drivers/freetype/src/base/Jamfile deleted file mode 100644 index cfc69657fe..0000000000 --- a/drivers/freetype/src/base/Jamfile +++ /dev/null @@ -1,88 +0,0 @@ -# FreeType 2 src/base Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) base ; - - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = basepic - ftadvanc - ftcalc - ftdbgmem - ftgloadr - fthash - ftobjs - ftoutln - ftpic - ftrfork - ftsnames - ftstream - fttrigon - ftutil - ; - } - else - { - _sources = ftbase ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# Add the optional/replaceable files. -# -{ - local _sources = ftapi - ftbbox - ftbdf - ftbitmap - ftcid - ftdebug - ftfntfmt - ftfstype - ftgasp - ftglyph - ftgxval - ftinit - ftlcdfil - ftmm - ftotval - ftpatent - ftpfr - ftstroke - ftsynth - ftsystem - fttype1 - ftwinfnt - ; - - Library $(FT2_LIB) : $(_sources).c ; -} - -# Add Macintosh-specific file to the library when necessary. -# -if $(MAC) -{ - Library $(FT2_LIB) : ftmac.c ; -} -else if $(OS) = MACOSX -{ - if $(FT2_MULTI) - { - Library $(FT2_LIB) : ftmac.c ; - } -} - -# end of src/base Jamfile diff --git a/drivers/freetype/src/bdf/Jamfile b/drivers/freetype/src/bdf/Jamfile deleted file mode 100644 index 2f0147bbba..0000000000 --- a/drivers/freetype/src/bdf/Jamfile +++ /dev/null @@ -1,31 +0,0 @@ -# FreeType 2 src/bdf Jamfile -# -# Copyright 2002-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) bdf ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = bdfdrivr - bdflib - ; - } - else - { - _sources = bdf ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/bdf Jamfile diff --git a/drivers/freetype/src/cache/Jamfile b/drivers/freetype/src/cache/Jamfile deleted file mode 100644 index da6551015b..0000000000 --- a/drivers/freetype/src/cache/Jamfile +++ /dev/null @@ -1,37 +0,0 @@ -# FreeType 2 src/cache Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) cache ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = ftcbasic - ftccache - ftcglyph - ftcimage - ftcmanag - ftccmap - ftcmru - ftcsbits - ; - } - else - { - _sources = ftcache ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/cache Jamfile diff --git a/drivers/freetype/src/cff/Jamfile b/drivers/freetype/src/cff/Jamfile deleted file mode 100644 index 8067e6b29c..0000000000 --- a/drivers/freetype/src/cff/Jamfile +++ /dev/null @@ -1,45 +0,0 @@ -# FreeType 2 src/cff Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) cff ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = cffcmap - cffdrivr - cffgload - cffload - cffobjs - cffparse - cffpic - cf2arrst - cf2blues - cf2error - cf2font - cf2ft - cf2hints - cf2intrp - cf2read - cf2stack - ; - } - else - { - _sources = cff ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/cff Jamfile diff --git a/drivers/freetype/src/cid/Jamfile b/drivers/freetype/src/cid/Jamfile deleted file mode 100644 index 4b4eea17d9..0000000000 --- a/drivers/freetype/src/cid/Jamfile +++ /dev/null @@ -1,34 +0,0 @@ -# FreeType 2 src/cid Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) cid ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = cidgload - cidload - cidobjs - cidparse - cidriver - ; - } - else - { - _sources = type1cid ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/cid Jamfile diff --git a/drivers/freetype/src/gxvalid/Jamfile b/drivers/freetype/src/gxvalid/Jamfile deleted file mode 100644 index 9738677e05..0000000000 --- a/drivers/freetype/src/gxvalid/Jamfile +++ /dev/null @@ -1,52 +0,0 @@ -# FreeType 2 src/gxvalid Jamfile -# -# Copyright 2005-2016 by -# suzuki toshiya, Masatake YAMATO and Red Hat K.K. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) gxvalid ; - - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = gxvbsln - gxvcommn - gxvfeat - gxvjust - gxvkern - gxvlcar - gxvmod - gxvmort - gxvmort0 - gxvmort1 - gxvmort2 - gxvmort4 - gxvmort5 - gxvmorx - gxvmorx0 - gxvmorx1 - gxvmorx2 - gxvmorx4 - gxvmorx5 - gxvopbd - gxvprop - gxvtrak - ; - } - else - { - _sources = gxvalid ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/gxvalid Jamfile diff --git a/drivers/freetype/src/otvalid/Jamfile b/drivers/freetype/src/otvalid/Jamfile deleted file mode 100644 index eded89ab9f..0000000000 --- a/drivers/freetype/src/otvalid/Jamfile +++ /dev/null @@ -1,37 +0,0 @@ -# FreeType 2 src/otvalid Jamfile -# -# Copyright 2004-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) otvalid ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = otvbase - otvcommn - otvgdef - otvgpos - otvgsub - otvjstf - otvmath - otvmod - ; - } - else - { - _sources = otvalid ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/otvalid Jamfile diff --git a/drivers/freetype/src/pcf/Jamfile b/drivers/freetype/src/pcf/Jamfile deleted file mode 100644 index 9ebe6a2cbd..0000000000 --- a/drivers/freetype/src/pcf/Jamfile +++ /dev/null @@ -1,32 +0,0 @@ -# FreeType 2 src/pcf Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) pcf ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = pcfdrivr - pcfread - pcfutil - ; - } - else - { - _sources = pcf ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/pcf Jamfile diff --git a/drivers/freetype/src/pfr/Jamfile b/drivers/freetype/src/pfr/Jamfile deleted file mode 100644 index a5b294b79a..0000000000 --- a/drivers/freetype/src/pfr/Jamfile +++ /dev/null @@ -1,35 +0,0 @@ -# FreeType 2 src/pfr Jamfile -# -# Copyright 2002-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) pfr ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = pfrcmap - pfrdrivr - pfrgload - pfrload - pfrobjs - pfrsbit - ; - } - else - { - _sources = pfr ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/pfr Jamfile diff --git a/drivers/freetype/src/psaux/Jamfile b/drivers/freetype/src/psaux/Jamfile deleted file mode 100644 index 9270eec687..0000000000 --- a/drivers/freetype/src/psaux/Jamfile +++ /dev/null @@ -1,35 +0,0 @@ -# FreeType 2 src/psaux Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) psaux ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = afmparse - psauxmod - psconv - psobjs - t1cmap - t1decode - ; - } - else - { - _sources = psaux ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/psaux Jamfile diff --git a/drivers/freetype/src/pshinter/Jamfile b/drivers/freetype/src/pshinter/Jamfile deleted file mode 100644 index fcb225811e..0000000000 --- a/drivers/freetype/src/pshinter/Jamfile +++ /dev/null @@ -1,34 +0,0 @@ -# FreeType 2 src/pshinter Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) pshinter ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = pshalgo - pshglob - pshmod - pshpic - pshrec - ; - } - else - { - _sources = pshinter ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/pshinter Jamfile diff --git a/drivers/freetype/src/psnames/Jamfile b/drivers/freetype/src/psnames/Jamfile deleted file mode 100644 index 35b8a99c8f..0000000000 --- a/drivers/freetype/src/psnames/Jamfile +++ /dev/null @@ -1,31 +0,0 @@ -# FreeType 2 src/psnames Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) psnames ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = psmodule - pspic - ; - } - else - { - _sources = psnames ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/psnames Jamfile diff --git a/drivers/freetype/src/raster/Jamfile b/drivers/freetype/src/raster/Jamfile deleted file mode 100644 index 2ec88f5601..0000000000 --- a/drivers/freetype/src/raster/Jamfile +++ /dev/null @@ -1,32 +0,0 @@ -# FreeType 2 src/raster Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) raster ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = ftraster - ftrend1 - rastpic - ; - } - else - { - _sources = raster ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/raster Jamfile diff --git a/drivers/freetype/src/sfnt/Jamfile b/drivers/freetype/src/sfnt/Jamfile deleted file mode 100644 index 089cc269ba..0000000000 --- a/drivers/freetype/src/sfnt/Jamfile +++ /dev/null @@ -1,40 +0,0 @@ -# FreeType 2 src/sfnt Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) sfnt ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = pngshim - sfdriver - sfntpic - sfobjs - ttbdf - ttcmap - ttkern - ttload - ttmtx - ttpost - ttsbit - ; - } - else - { - _sources = sfnt ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/sfnt Jamfile diff --git a/drivers/freetype/src/smooth/Jamfile b/drivers/freetype/src/smooth/Jamfile deleted file mode 100644 index a388c11d91..0000000000 --- a/drivers/freetype/src/smooth/Jamfile +++ /dev/null @@ -1,32 +0,0 @@ -# FreeType 2 src/smooth Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) smooth ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = ftgrays - ftsmooth - ftspic - ; - } - else - { - _sources = smooth ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/smooth Jamfile diff --git a/drivers/freetype/src/truetype/Jamfile b/drivers/freetype/src/truetype/Jamfile deleted file mode 100644 index ecbb2dbdd2..0000000000 --- a/drivers/freetype/src/truetype/Jamfile +++ /dev/null @@ -1,37 +0,0 @@ -# FreeType 2 src/truetype Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) truetype ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = ttdriver - ttgload - ttgxvar - ttinterp - ttobjs - ttpic - ttpload - ttsubpix - ; - } - else - { - _sources = truetype ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/truetype Jamfile diff --git a/drivers/freetype/src/type1/Jamfile b/drivers/freetype/src/type1/Jamfile deleted file mode 100644 index 948b40854a..0000000000 --- a/drivers/freetype/src/type1/Jamfile +++ /dev/null @@ -1,35 +0,0 @@ -# FreeType 2 src/type1 Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) type1 ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = t1afm - t1driver - t1gload - t1load - t1objs - t1parse - ; - } - else - { - _sources = type1 ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/type1 Jamfile diff --git a/drivers/freetype/src/type42/Jamfile b/drivers/freetype/src/type42/Jamfile deleted file mode 100644 index a504ad17d3..0000000000 --- a/drivers/freetype/src/type42/Jamfile +++ /dev/null @@ -1,32 +0,0 @@ -# FreeType 2 src/type42 Jamfile -# -# Copyright 2002-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) type42 ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = t42drivr - t42objs - t42parse - ; - } - else - { - _sources = type42 ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/type42 Jamfile diff --git a/drivers/freetype/src/winfonts/Jamfile b/drivers/freetype/src/winfonts/Jamfile deleted file mode 100644 index d81165e921..0000000000 --- a/drivers/freetype/src/winfonts/Jamfile +++ /dev/null @@ -1,16 +0,0 @@ -# FreeType 2 src/winfonts Jamfile -# -# Copyright 2001-2016 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) winfonts ; - -Library $(FT2_LIB) : winfnt.c ; - -# end of src/winfonts Jamfile diff --git a/drivers/gl_context/SCsub b/drivers/gl_context/SCsub index dac27c0125..cf37e9fe36 100644 --- a/drivers/gl_context/SCsub +++ b/drivers/gl_context/SCsub @@ -1,11 +1,23 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.drivers_sources,"*.cpp") +if (env["platform"] in ["haiku","osx","windows","x11"]): + # Thirdparty source files + if (env["glew"] != "system"): # builtin + thirdparty_dir = "#thirdparty/glew/" + thirdparty_sources = [ + "glew.c", + ] + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + + env.add_source_files(env.drivers_sources, thirdparty_sources) + env.Append(CPPFLAGS = ['-DGLEW_STATIC']) + env.Append(CPPPATH = [thirdparty_dir]) -if (env.get('glew') == 'yes'): - env.add_source_files(env.drivers_sources,"glew.c") env.Append(CPPFLAGS = ['-DGLEW_ENABLED']) - env.Append(CPPFLAGS = ['-DGLEW_STATIC']) - env.Append(CPPPATH = ['.']) + +# Godot source files +env.add_source_files(env.drivers_sources, "*.cpp") Export('env') diff --git a/drivers/gles2/SCsub b/drivers/gles2/SCsub index a17335b41b..dedd794dba 100644 --- a/drivers/gles2/SCsub +++ b/drivers/gles2/SCsub @@ -1,5 +1,9 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.drivers_sources,"*.cpp") +env.add_source_files(env.drivers_sources, "*.cpp") SConscript("shaders/SCsub") + +Export('env') diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 3809f4c7b9..a7edc8d935 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -36,6 +36,7 @@ #include "servers/visual/particle_system_sw.h" #include "gl_context/context_gl.h" #include <string.h> +#include <stdlib.h> #ifdef GLEW_ENABLED #define _GL_HALF_FLOAT_OES 0x140B @@ -1998,7 +1999,6 @@ void RasterizerGLES2::mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive, if (use_VBO) { elem_size=VS::ARRAY_WEIGHTS_SIZE*sizeof(GLushort); - elem_count=VS::ARRAY_WEIGHTS_SIZE; valid_local=false; bind=true; normalize=true; @@ -2007,7 +2007,6 @@ void RasterizerGLES2::mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive, } else { elem_size=VS::ARRAY_WEIGHTS_SIZE*sizeof(GLfloat); - elem_count=VS::ARRAY_WEIGHTS_SIZE; valid_local=false; bind=false; datatype=GL_FLOAT; @@ -2019,7 +2018,6 @@ void RasterizerGLES2::mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive, if (use_VBO) { elem_size=VS::ARRAY_WEIGHTS_SIZE*sizeof(GLubyte); - elem_count=VS::ARRAY_WEIGHTS_SIZE; valid_local=false; bind=true; datatype=GL_UNSIGNED_BYTE; @@ -2027,7 +2025,6 @@ void RasterizerGLES2::mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive, } else { elem_size=VS::ARRAY_WEIGHTS_SIZE*sizeof(GLushort); - elem_count=VS::ARRAY_WEIGHTS_SIZE; valid_local=false; bind=false; datatype=GL_UNSIGNED_SHORT; @@ -4666,7 +4663,7 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { enablers.push_back("#define USE_LIGHT_SHADER_CODE\n"); } if (light_flags.uses_shadow_color) { - enablers.push_back("#define USE_LIGHT_SHADOW_COLOR\n"); + enablers.push_back("#define USE_OUTPUT_SHADOW_COLOR\n"); } if (light_flags.uses_time || fragment_flags.uses_time || vertex_flags.uses_time) { enablers.push_back("#define USE_TIME\n"); @@ -4709,7 +4706,7 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { enablers.push_back("#define USE_TEXPIXEL_SIZE\n"); } if (light_flags.uses_shadow_color) { - enablers.push_back("#define USE_LIGHT_SHADOW_COLOR\n"); + enablers.push_back("#define USE_OUTPUT_SHADOW_COLOR\n"); } if (vertex_flags.uses_worldvec) { @@ -5210,7 +5207,6 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material material_shader.set_conditional(MaterialShaderGLES2::USE_FOG,current_env && current_env->fx_enabled[VS::ENV_FX_FOG]); //glDepthMask( true ); - } @@ -5460,9 +5456,16 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) { } - light_data[VL_LIGHT_ATTENUATION][0]=l->vars[VS::LIGHT_PARAM_ENERGY]; - light_data[VL_LIGHT_ATTENUATION][1]=l->vars[VS::LIGHT_PARAM_RADIUS]; - light_data[VL_LIGHT_ATTENUATION][2]=l->vars[VS::LIGHT_PARAM_ATTENUATION]; + light_data[VL_LIGHT_ATTENUATION][0] = l->vars[VS::LIGHT_PARAM_ENERGY]; + + if (l->type == VS::LIGHT_DIRECTIONAL) { + light_data[VL_LIGHT_ATTENUATION][1] = l->directional_shadow_param[VS::LIGHT_DIRECTIONAL_SHADOW_PARAM_MAX_DISTANCE]; + } + else{ + light_data[VL_LIGHT_ATTENUATION][1] = l->vars[VS::LIGHT_PARAM_RADIUS]; + } + + light_data[VL_LIGHT_ATTENUATION][2] = l->vars[VS::LIGHT_PARAM_ATTENUATION]; light_data[VL_LIGHT_SPOT_ATTENUATION][0]=Math::cos(Math::deg2rad(l->vars[VS::LIGHT_PARAM_SPOT_ANGLE])); light_data[VL_LIGHT_SPOT_ATTENUATION][1]=l->vars[VS::LIGHT_PARAM_SPOT_ATTENUATION]; @@ -6778,7 +6781,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans } } - if (e->instance->billboard || e->instance->depth_scale) { + if (e->instance->billboard || e->instance->billboard_y || e->instance->depth_scale) { Transform xf=e->instance->transform; if (e->instance->depth_scale) { @@ -6809,6 +6812,21 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans xf.basis.scale(scale); } + + if (e->instance->billboard_y) { + + Vector3 scale = xf.basis.get_scale(); + Vector3 look_at = p_view_transform.get_origin(); + look_at.y = 0.0; + Vector3 look_at_norm = look_at.normalized(); + + if (current_rt && current_rt_vflip) { + xf.set_look_at(xf.origin,xf.origin + look_at_norm, Vector3(0.0, -1.0, 0.0)); + } else { + xf.set_look_at(xf.origin,xf.origin + look_at_norm, Vector3(0.0, 1.0, 0.0)); + } + xf.basis.scale(scale); + } material_shader.set_uniform(MaterialShaderGLES2::WORLD_TRANSFORM, xf); } else { @@ -7008,6 +7026,10 @@ void RasterizerGLES2::_process_glow_bloom() { void RasterizerGLES2::_process_hdr() { + if (framebuffer.luminance.empty()) { + return; + } + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.luminance[0].fbo); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, framebuffer.color ); @@ -10799,14 +10821,52 @@ void RasterizerGLES2::init() { print_line(String("GLES2: Using GLEW ") + (const char*) glewGetString(GLEW_VERSION)); } + // Godot makes use of functions from ARB_framebuffer_object extension which is not implemented by all drivers. + // On the other hand, these drivers might implement the older EXT_framebuffer_object extension + // with which current source code is backward compatible. + + bool framebuffer_object_is_supported = glewIsSupported("GL_ARB_framebuffer_object"); + + if ( !framebuffer_object_is_supported ) { + WARN_PRINT("GL_ARB_framebuffer_object not supported by your graphics card."); + + if ( glewIsSupported("GL_EXT_framebuffer_object") ) { + // falling-back to the older EXT function if present + WARN_PRINT("Falling-back to GL_EXT_framebuffer_object."); + + glIsRenderbuffer = glIsRenderbufferEXT; + glBindRenderbuffer = glBindRenderbufferEXT; + glDeleteRenderbuffers = glDeleteRenderbuffersEXT; + glGenRenderbuffers = glGenRenderbuffersEXT; + glRenderbufferStorage = glRenderbufferStorageEXT; + glGetRenderbufferParameteriv = glGetRenderbufferParameterivEXT; + glIsFramebuffer = glIsFramebufferEXT; + glBindFramebuffer = glBindFramebufferEXT; + glDeleteFramebuffers = glDeleteFramebuffersEXT; + glGenFramebuffers = glGenFramebuffersEXT; + glCheckFramebufferStatus = glCheckFramebufferStatusEXT; + glFramebufferTexture1D = glFramebufferTexture1DEXT; + glFramebufferTexture2D = glFramebufferTexture2DEXT; + glFramebufferTexture3D = glFramebufferTexture3DEXT; + glFramebufferRenderbuffer = glFramebufferRenderbufferEXT; + glGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameterivEXT; + glGenerateMipmap = glGenerateMipmapEXT; + + framebuffer_object_is_supported = true; + } + else { + ERR_PRINT("Framebuffer Object is not supported by your graphics card."); + } + } + // Check for GL 2.1 compatibility, if not bail out - if (!glewIsSupported("GL_VERSION_2_1")) { + if (!(glewIsSupported("GL_VERSION_2_1") && framebuffer_object_is_supported)) { ERR_PRINT("Your system's graphic drivers seem not to support OpenGL 2.1 / GLES 2.0, sorry :(\n" - "Try a drivers update, buy a new GPU or try software rendering on Linux; Godot will now crash with a segmentation fault."); + "Try a drivers update, buy a new GPU or try software rendering on Linux; Godot is now going to terminate."); OS::get_singleton()->alert("Your system's graphic drivers seem not to support OpenGL 2.1 / GLES 2.0, sorry :(\n" "Godot Engine will self-destruct as soon as you acknowledge this error message.", "Fatal error: Insufficient OpenGL / GLES drivers"); - // TODO: If it's even possible, we should stop the execution without segfault and memory leaks :) + exit(1); } #endif @@ -10843,6 +10903,11 @@ void RasterizerGLES2::init() { copy_shader.set_conditional(CopyShaderGLES2::USE_GLES_OVER_GL,true); #endif +#ifdef ANGLE_ENABLED + // Fix for ANGLE + material_shader.set_conditional(MaterialShaderGLES2::DISABLE_FRONT_FACING, true); +#endif + shadow=NULL; shadow_pass=0; @@ -10930,7 +10995,11 @@ void RasterizerGLES2::init() { srgb_supported=extensions.has("GL_EXT_sRGB"); +#ifndef ANGLE_ENABLED s3tc_srgb_supported = s3tc_supported && extensions.has("GL_EXT_texture_compression_s3tc"); +#else + s3tc_srgb_supported = s3tc_supported; +#endif latc_supported = extensions.has("GL_EXT_texture_compression_latc"); anisotropic_level=1.0; use_anisotropic_filter=extensions.has("GL_EXT_texture_filter_anisotropic"); diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 3be0fdab17..d4636ed444 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -904,6 +904,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_VEC"]="light_vec"; mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_HEIGHT"]="light_height"; mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_COLOR"]="light"; + mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_SHADOW"]="light_shadow_color"; mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_UV"]="light_uv"; mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT"]="light_out"; mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["SHADOW"]="shadow_color"; diff --git a/drivers/gles2/shaders/SCsub b/drivers/gles2/shaders/SCsub index 38177d725f..1de5604321 100644 --- a/drivers/gles2/shaders/SCsub +++ b/drivers/gles2/shaders/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') if env['BUILDERS'].has_key('GLSL120GLES'): @@ -6,3 +8,5 @@ if env['BUILDERS'].has_key('GLSL120GLES'): env.GLSL120GLES('canvas_shadow.glsl'); env.GLSL120GLES('blur.glsl'); env.GLSL120GLES('copy.glsl'); + +Export('env') diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index 285abd30ff..5f4767940d 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -244,7 +244,7 @@ FRAGMENT_SHADER_CODE vec2 light_uv = light_uv_interp.xy; vec4 light = texture2D(light_texture,light_uv) * light_color; -#if defined(USE_LIGHT_SHADOW_COLOR) +#if defined(USE_OUTPUT_SHADOW_COLOR) vec4 shadow_color=vec4(0.0,0.0,0.0,0.0); #endif @@ -380,7 +380,7 @@ LIGHT_SHADER_CODE #endif -#if defined(USE_LIGHT_SHADOW_COLOR) +#if defined(USE_OUTPUT_SHADOW_COLOR) color=mix(shadow_color,color,shadow_attenuation); #else //color*=shadow_attenuation; diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl index e68949b056..e5be25757d 100644 --- a/drivers/gles2/shaders/material.glsl +++ b/drivers/gles2/shaders/material.glsl @@ -811,7 +811,11 @@ void main() { float specular_exp=1.0; float glow=0.0; float shade_param=0.0; +#ifdef DISABLE_FRONT_FACING + float side=float(1)*2.0-1.0; +#else float side=float(gl_FrontFacing)*2.0-1.0; +#endif #if defined(ENABLE_TANGENT_INTERP) vec3 binormal = normalize(binormal_interp)*side; vec3 tangent = normalize(tangent_interp)*side; @@ -976,6 +980,12 @@ FRAGMENT_SHADER_CODE #ifdef LIGHT_USE_SHADOW #ifdef LIGHT_TYPE_DIRECTIONAL + float shadow_fade_exponent=5.0; //hardcoded for now + float shadow_fade=pow(length(vertex_interp)/light_attenuation.g,shadow_fade_exponent); + +// optimization - skip shadows outside visible range + if(shadow_fade<1.0){ + #ifdef LIGHT_USE_PSSM @@ -1101,6 +1111,12 @@ FRAGMENT_SHADER_CODE shadow_attenuation=SAMPLE_SHADOW_TEX(shadow_coord.xy,shadow_coord.z); #endif + + shadow_attenuation=mix(shadow_attenuation,1.0,shadow_fade); + }else{ + shadow_attenuation=1.0; + }; + #endif #ifdef LIGHT_TYPE_OMNI @@ -1181,7 +1197,7 @@ FRAGMENT_SHADER_CODE vec3 mdiffuse = diffuse.rgb; vec3 light; -#if defined(USE_LIGHT_SHADOW_COLOR) +#if defined(USE_OUTPUT_SHADOW_COLOR) vec3 shadow_color=vec3(0.0,0.0,0.0); #endif @@ -1205,7 +1221,7 @@ LIGHT_SHADER_CODE #endif diffuse.rgb = const_light_mult * ambient_light *diffuse.rgb + light * attenuation * shadow_attenuation; -#if defined(USE_LIGHT_SHADOW_COLOR) +#if defined(USE_OUTPUT_SHADOW_COLOR) diffuse.rgb += light * shadow_color * attenuation * (1.0 - shadow_attenuation); #endif diff --git a/drivers/jpegd/SCsub b/drivers/jpegd/SCsub deleted file mode 100644 index dfdb19402e..0000000000 --- a/drivers/jpegd/SCsub +++ /dev/null @@ -1,11 +0,0 @@ -Import('env') - - -jpg_sources = [ - "jpegd/jpgd.cpp", - "jpegd/image_loader_jpegd.cpp" - ] - -env.drivers_sources+=jpg_sources - -#env.add_source_files(env.drivers_sources, jpg_sources) diff --git a/drivers/jpegd/image_loader_jpegd.cpp b/drivers/jpegd/image_loader_jpegd.cpp deleted file mode 100644 index 496334605d..0000000000 --- a/drivers/jpegd/image_loader_jpegd.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/*************************************************************************/ -/* image_loader_jpegd.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "image_loader_jpegd.h" - -#include "print_string.h" -#include "os/os.h" -#include "jpgd.h" -#include <string.h> - - -Error jpeg_load_image_from_buffer(Image *p_image,const uint8_t* p_buffer, int p_buffer_len) { - - jpgd::jpeg_decoder_mem_stream mem_stream(p_buffer,p_buffer_len); - - jpgd::jpeg_decoder decoder(&mem_stream); - - if (decoder.get_error_code() != jpgd::JPGD_SUCCESS) { - return ERR_CANT_OPEN; - } - - const int image_width = decoder.get_width(); - const int image_height = decoder.get_height(); - int comps = decoder.get_num_components(); - if (comps==3) - comps=4; //weird - - if (decoder.begin_decoding() != jpgd::JPGD_SUCCESS) - return ERR_FILE_CORRUPT; - - const int dst_bpl = image_width * comps; - - DVector<uint8_t> data; - - data.resize(dst_bpl * image_height); - - DVector<uint8_t>::Write dw = data.write(); - - jpgd::uint8 *pImage_data = (jpgd::uint8*)dw.ptr(); - - for (int y = 0; y < image_height; y++) - { - const jpgd::uint8* pScan_line; - jpgd::uint scan_line_len; - if (decoder.decode((const void**)&pScan_line, &scan_line_len) != jpgd::JPGD_SUCCESS) - { - return ERR_FILE_CORRUPT; - } - - jpgd::uint8 *pDst = pImage_data + y * dst_bpl; - memcpy(pDst, pScan_line, dst_bpl); - - - } - - - //all good - - Image::Format fmt; - if (comps==1) - fmt=Image::FORMAT_GRAYSCALE; - else - fmt=Image::FORMAT_RGBA; - - dw = DVector<uint8_t>::Write(); - p_image->create(image_width,image_height,0,fmt,data); - - return OK; - -} - - -Error ImageLoaderJPG::load_image(Image *p_image,FileAccess *f) { - - - DVector<uint8_t> src_image; - int src_image_len = f->get_len(); - ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); - src_image.resize(src_image_len); - - DVector<uint8_t>::Write w = src_image.write(); - - f->get_buffer(&w[0],src_image_len); - - f->close(); - - - Error err = jpeg_load_image_from_buffer(p_image,w.ptr(),src_image_len); - - w = DVector<uint8_t>::Write(); - - return err; - -} - -void ImageLoaderJPG::get_recognized_extensions(List<String> *p_extensions) const { - - p_extensions->push_back("jpg"); - p_extensions->push_back("jpeg"); -} - - -static Image _jpegd_mem_loader_func(const uint8_t* p_png,int p_size) { - - Image img; - Error err = jpeg_load_image_from_buffer(&img,p_png,p_size); - if (err) - ERR_PRINT("Couldn't initialize ImageLoaderJPG with the given resource."); - - return img; -} - -ImageLoaderJPG::ImageLoaderJPG() { - - Image::_jpg_mem_loader_func=_jpegd_mem_loader_func; -} - - diff --git a/drivers/mpc/SCsub b/drivers/mpc/SCsub deleted file mode 100644 index 32ffdb863f..0000000000 --- a/drivers/mpc/SCsub +++ /dev/null @@ -1,21 +0,0 @@ -Import('env') - - -mpc_sources = [ - "mpc/huffman.c", - "mpc/mpc_bits_reader.c", - "mpc/mpc_decoder.c", - "mpc/mpc_demux.c", - "mpc/mpc_reader.c", - "mpc/requant.c", - "mpc/streaminfo.c", - "mpc/synth_filter.c", -] - -env.drivers_sources+=mpc_sources - -env.add_source_files(env.drivers_sources,"*.cpp") - -#env.add_source_files(env.drivers_sources, mpc_sources) - -Export('env') diff --git a/drivers/mpc/audio_stream_mpc.h b/drivers/mpc/audio_stream_mpc.h deleted file mode 100644 index 27f55777d6..0000000000 --- a/drivers/mpc/audio_stream_mpc.h +++ /dev/null @@ -1,147 +0,0 @@ -/*************************************************************************/ -/* audio_stream_mpc.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef AUDIO_STREAM_MPC_H -#define AUDIO_STREAM_MPC_H - -#include "scene/resources/audio_stream.h" -#include "os/file_access.h" -#include "mpc/mpcdec.h" -#include "os/thread_safe.h" -#include "io/resource_loader.h" -//#include "../libmpcdec/decoder.h" -//#include "../libmpcdec/internal.h" - -class AudioStreamPlaybackMPC : public AudioStreamPlayback { - - OBJ_TYPE( AudioStreamPlaybackMPC, AudioStreamPlayback ); - - bool preload; - FileAccess *f; - String file; - DVector<uint8_t> data; - int data_ofs; - int streamlen; - - - bool active; - bool paused; - bool loop; - int loops; - - // mpc - mpc_reader reader; - mpc_demux* demux; - mpc_streaminfo si; - MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH]; - - static mpc_int32_t _mpc_read(mpc_reader *p_reader,void *p_dst, mpc_int32_t p_bytes); - static mpc_bool_t _mpc_seek(mpc_reader *p_reader,mpc_int32_t p_offset); - static mpc_int32_t _mpc_tell(mpc_reader *p_reader); - static mpc_int32_t _mpc_get_size(mpc_reader *p_reader); - static mpc_bool_t _mpc_canseek(mpc_reader *p_reader); - - int stream_min_size; - int stream_rate; - int stream_channels; - -protected: - Error _open_file(); - void _close_file(); - int _read_file(void *p_dst,int p_bytes); - bool _seek_file(int p_pos); - int _tell_file() const; - int _sizeof_file() const; - bool _canseek_file() const; - - - Error _reload(); - static void _bind_methods(); - -public: - - void set_file(const String& p_file); - String get_file() const; - - virtual void play(float p_offset=0); - virtual void stop(); - virtual bool is_playing() const; - - - virtual void set_loop(bool p_enable); - virtual bool has_loop() const; - - virtual float get_length() const; - - virtual String get_stream_name() const; - - virtual int get_loop_count() const; - - virtual float get_pos() const; - virtual void seek_pos(float p_time); - - virtual int get_channels() const { return stream_channels; } - virtual int get_mix_rate() const { return stream_rate; } - - virtual int get_minimum_buffer_size() const { return stream_min_size; } - virtual int mix(int16_t* p_bufer,int p_frames); - - virtual void set_loop_restart_time(float p_time) { } - - AudioStreamPlaybackMPC(); - ~AudioStreamPlaybackMPC(); -}; - -class AudioStreamMPC : public AudioStream { - - OBJ_TYPE( AudioStreamMPC, AudioStream ); - - String file; -public: - - Ref<AudioStreamPlayback> instance_playback() { - Ref<AudioStreamPlaybackMPC> pb = memnew( AudioStreamPlaybackMPC ); - pb->set_file(file); - return pb; - } - - void set_file(const String& p_file) { file=p_file; } - - -}; - -class ResourceFormatLoaderAudioStreamMPC : public ResourceFormatLoader { -public: - virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); - virtual void get_recognized_extensions(List<String> *p_extensions) const; - virtual bool handles_type(const String& p_type) const; - virtual String get_resource_type(const String &p_path) const; - -}; - -#endif // AUDIO_STREAM_MPC_H diff --git a/drivers/nedmalloc/License.txt b/drivers/nedmalloc/License.txt deleted file mode 100644 index 1dad8e9349..0000000000 --- a/drivers/nedmalloc/License.txt +++ /dev/null @@ -1,23 +0,0 @@ -Boost Software License - Version 1.0 - August 17th, 2003
-
-Permission is hereby granted, free of charge, to any person or organization
-obtaining a copy of the software and accompanying documentation covered by
-this license (the "Software") to use, reproduce, display, distribute,
-execute, and transmit the Software, and to prepare derivative works of the
-Software, and to permit third-parties to whom the Software is furnished to
-do so, all subject to the following:
-
-The copyright notices in the Software and this entire statement, including
-the above license grant, this restriction and the following disclaimer,
-must be included in all copies of the Software, in whole or in part, and
-all derivative works of the Software, unless such copies or derivative
-works are solely in the form of machine-executable object code generated by
-a source language processor.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
-SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
-FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/drivers/nedmalloc/Readme.txt b/drivers/nedmalloc/Readme.txt deleted file mode 100644 index 85f9b6a0f1..0000000000 --- a/drivers/nedmalloc/Readme.txt +++ /dev/null @@ -1,136 +0,0 @@ -nedalloc v1.05 15th June 2008:
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-by Niall Douglas (http://www.nedprod.com/programs/portable/nedmalloc/)
-
-Enclosed is nedalloc, an alternative malloc implementation for multiple
-threads without lock contention based on dlmalloc v2.8.4. It is more
-or less a newer implementation of ptmalloc2, the standard allocator in
-Linux (which is based on dlmalloc v2.7.0) but also contains a per-thread
-cache for maximum CPU scalability.
-
-It is licensed under the Boost Software License which basically means
-you can do anything you like with it. This does not apply to the malloc.c.h
-file which remains copyright to others.
-
-It has been tested on win32 (x86), win64 (x64), Linux (x64), FreeBSD (x64)
-and Apple MacOS X (x86). It works very well on all of these and is very
-significantly faster than the system allocator on all of these platforms.
-
-By literally dropping in this allocator as a replacement for your system
-allocator, you can see real world improvements of up to three times in normal
-code!
-
-To use:
--=-=-=-
-Drop in nedmalloc.h, nedmalloc.c and malloc.c.h into your project.
-Configure using the instructions in nedmalloc.h. Run and enjoy.
-
-To test, compile test.c. It will run a comparison between your system
-allocator and nedalloc and tell you how much faster nedalloc is. It also
-serves as an example of usage.
-
-Notes:
--=-=-=
-If you want the very latest version of this allocator, get it from the
-TnFOX SVN repository at svn://svn.berlios.de/viewcvs/tnfox/trunk/src/nedmalloc
-
-Because of how nedalloc allocates an mspace per thread, it can cause
-severe bloating of memory usage under certain allocation patterns.
-You can substantially reduce this wastage by setting MAXTHREADSINPOOL
-or the threads parameter to nedcreatepool() to a fraction of the number of
-threads which would normally be in a pool at once. This will reduce
-bloating at the cost of an increase in lock contention. If allocated size
-is less than THREADCACHEMAX, locking is avoided 90-99% of the time and
-if most of your allocations are below this value, you can safely set
-MAXTHREADSINPOOL to one.
-
-You will suffer memory leakage unless you call neddisablethreadcache()
-per pool for every thread which exits. This is because nedalloc cannot
-portably know when a thread exits and thus when its thread cache can
-be returned for use by other code. Don't forget pool zero, the system pool.
-
-For C++ type allocation patterns (where the same sizes of memory are
-regularly allocated and deallocated as objects are created and destroyed),
-the threadcache always benefits performance. If however your allocation
-patterns are different, searching the threadcache may significantly slow
-down your code - as a rule of thumb, if cache utilisation is below 80%
-(see the source for neddisablethreadcache() for how to enable debug
-printing in release mode) then you should disable the thread cache for
-that thread. You can compile out the threadcache code by setting
-THREADCACHEMAX to zero.
-
-Speed comparisons:
--=-=-=-=-=-=-=-=-=
-See Benchmarks.xls for details.
-
-The enclosed test.c can do two things: it can be a torture test or a speed
-test. The speed test is designed to be a representative synthetic
-memory allocator test. It works by randomly mixing allocations with frees
-with half of the allocation sizes being a two power multiple less than
-512 bytes (to mimic C++ stack instantiated objects) and the other half
-being a simple random value less than 16Kb.
-
-The real world code results are from Tn's TestIO benchmark. This is a
-heavily multithreaded and memory intensive benchmark with a lot of branching
-and other stuff modern processors don't like so much. As you'll note, the
-test doesn't show the benefits of the threadcache mostly due to the saturation
-of the memory bus being the limiting factor.
-
-ChangeLog:
--=-=-=-=-=
-v1.05 15th June 2008:
- * { 1042 } Added error check for TLSSET() and TLSFREE() macros. Thanks to
-Markus Elfring for reporting this.
- * { 1043 } Fixed a segfault when freeing memory allocated using
-nedindependent_comalloc(). Thanks to Pavel Vozenilek for reporting this.
-
-v1.04 14th July 2007:
- * Fixed a bug with the new optimised implementation that failed to lock
-on a realloc under certain conditions.
- * Fixed lack of thread synchronisation in InitPool() causing pool corruption
- * Fixed a memory leak of thread cache contents on disabling. Thanks to Earl
-Chew for reporting this.
- * Added a sanity check for freed blocks being valid.
- * Reworked test.c into being a torture test.
- * Fixed GCC assembler optimisation misspecification
-
-v1.04alpha_svn915 7th October 2006:
- * Fixed failure to unlock thread cache list if allocating a new list failed.
-Thanks to Dmitry Chichkov for reporting this. Futher thanks to Aleksey Sanin.
- * Fixed realloc(0, <size>) segfaulting. Thanks to Dmitry Chichkov for
-reporting this.
- * Made config defines #ifndef so they can be overriden by the build system.
-Thanks to Aleksey Sanin for suggesting this.
- * Fixed deadlock in nedprealloc() due to unnecessary locking of preferred
-thread mspace when mspace_realloc() always uses the original block's mspace
-anyway. Thanks to Aleksey Sanin for reporting this.
- * Made some speed improvements by hacking mspace_malloc() to no longer lock
-its mspace, thus allowing the recursive mutex implementation to be removed
-with an associated speed increase. Thanks to Aleksey Sanin for suggesting this.
- * Fixed a bug where allocating mspaces overran its max limit. Thanks to
-Aleksey Sanin for reporting this.
-
-v1.03 10th July 2006:
- * Fixed memory corruption bug in threadcache code which only appeared with >4
-threads and in heavy use of the threadcache.
-
-v1.02 15th May 2006:
- * Integrated dlmalloc v2.8.4, fixing the win32 memory release problem and
-improving performance still further. Speed is now up to twice the speed of v1.01
-(average is 67% faster).
- * Fixed win32 critical section implementation. Thanks to Pavel Kuznetsov
-for reporting this.
- * Wasn't locking mspace if all mspaces were locked. Thanks to Pavel Kuznetsov
-for reporting this.
- * Added Apple Mac OS X support.
-
-v1.01 24th February 2006:
- * Fixed multiprocessor scaling problems by removing sources of cache sloshing
- * Earl Chew <earl_chew <at> agilent <dot> com> sent patches for the following:
- 1. size2binidx() wasn't working for default code path (non x86)
- 2. Fixed failure to release mspace lock under certain circumstances which
- caused a deadlock
-
-v1.00 1st January 2006:
- * First release
diff --git a/drivers/nedmalloc/SCsub b/drivers/nedmalloc/SCsub deleted file mode 100644 index 6699efef75..0000000000 --- a/drivers/nedmalloc/SCsub +++ /dev/null @@ -1,4 +0,0 @@ -Import('env') -Export('env'); - -env.add_source_files(env.drivers_sources,"*.cpp") diff --git a/drivers/nedmalloc/malloc.c.h b/drivers/nedmalloc/malloc.c.h deleted file mode 100644 index 4fec5cc9d4..0000000000 --- a/drivers/nedmalloc/malloc.c.h +++ /dev/null @@ -1,5814 +0,0 @@ -#ifdef NEDMALLOC_ENABLED -/* - This is a version (aka dlmalloc) of malloc/free/realloc written by - Doug Lea and released to the public domain, as explained at - http://creativecommons.org/licenses/publicdomain. Send questions, - comments, complaints, performance data, etc to dl@cs.oswego.edu - -* Version 2.8.4 Wed May 27 09:56:23 2009 Doug Lea (dl at gee) - - Note: There may be an updated version of this malloc obtainable at - ftp://gee.cs.oswego.edu/pub/misc/malloc.c - Check before installing! - -* Quickstart - - This library is all in one file to simplify the most common usage: - ftp it, compile it (-O3), and link it into another program. All of - the compile-time options default to reasonable values for use on - most platforms. You might later want to step through various - compile-time and dynamic tuning options. - - For convenience, an include file for code using this malloc is at: - ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.4.h - You don't really need this .h file unless you call functions not - defined in your system include files. The .h file contains only the - excerpts from this file needed for using this malloc on ANSI C/C++ - systems, so long as you haven't changed compile-time options about - naming and tuning parameters. If you do, then you can create your - own malloc.h that does include all settings by cutting at the point - indicated below. Note that you may already by default be using a C - library containing a malloc that is based on some version of this - malloc (for example in linux). You might still want to use the one - in this file to customize settings or to avoid overheads associated - with library versions. - -* Vital statistics: - - Supported pointer/size_t representation: 4 or 8 bytes - size_t MUST be an unsigned type of the same width as - pointers. (If you are using an ancient system that declares - size_t as a signed type, or need it to be a different width - than pointers, you can use a previous release of this malloc - (e.g. 2.7.2) supporting these.) - - Alignment: 8 bytes (default) - This suffices for nearly all current machines and C compilers. - However, you can define MALLOC_ALIGNMENT to be wider than this - if necessary (up to 128bytes), at the expense of using more space. - - Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes) - 8 or 16 bytes (if 8byte sizes) - Each malloced chunk has a hidden word of overhead holding size - and status information, and additional cross-check word - if FOOTERS is defined. - - Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead) - 8-byte ptrs: 32 bytes (including overhead) - - Even a request for zero bytes (i.e., malloc(0)) returns a - pointer to something of the minimum allocatable size. - The maximum overhead wastage (i.e., number of extra bytes - allocated than were requested in malloc) is less than or equal - to the minimum size, except for requests >= mmap_threshold that - are serviced via mmap(), where the worst case wastage is about - 32 bytes plus the remainder from a system page (the minimal - mmap unit); typically 4096 or 8192 bytes. - - Security: static-safe; optionally more or less - The "security" of malloc refers to the ability of malicious - code to accentuate the effects of errors (for example, freeing - space that is not currently malloc'ed or overwriting past the - ends of chunks) in code that calls malloc. This malloc - guarantees not to modify any memory locations below the base of - heap, i.e., static variables, even in the presence of usage - errors. The routines additionally detect most improper frees - and reallocs. All this holds as long as the static bookkeeping - for malloc itself is not corrupted by some other means. This - is only one aspect of security -- these checks do not, and - cannot, detect all possible programming errors. - - If FOOTERS is defined nonzero, then each allocated chunk - carries an additional check word to verify that it was malloced - from its space. These check words are the same within each - execution of a program using malloc, but differ across - executions, so externally crafted fake chunks cannot be - freed. This improves security by rejecting frees/reallocs that - could corrupt heap memory, in addition to the checks preventing - writes to statics that are always on. This may further improve - security at the expense of time and space overhead. (Note that - FOOTERS may also be worth using with MSPACES.) - - By default detected errors cause the program to abort (calling - "abort()"). You can override this to instead proceed past - errors by defining PROCEED_ON_ERROR. In this case, a bad free - has no effect, and a malloc that encounters a bad address - caused by user overwrites will ignore the bad address by - dropping pointers and indices to all known memory. This may - be appropriate for programs that should continue if at all - possible in the face of programming errors, although they may - run out of memory because dropped memory is never reclaimed. - - If you don't like either of these options, you can define - CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything - else. And if if you are sure that your program using malloc has - no errors or vulnerabilities, you can define INSECURE to 1, - which might (or might not) provide a small performance improvement. - - Thread-safety: NOT thread-safe unless USE_LOCKS defined - When USE_LOCKS is defined, each public call to malloc, free, - etc is surrounded with either a pthread mutex or a win32 - spinlock (depending on WIN32). This is not especially fast, and - can be a major bottleneck. It is designed only to provide - minimal protection in concurrent environments, and to provide a - basis for extensions. If you are using malloc in a concurrent - program, consider instead using nedmalloc - (http://www.nedprod.com/programs/portable/nedmalloc/) or - ptmalloc (See http://www.malloc.de), which are derived - from versions of this malloc. - - System requirements: Any combination of MORECORE and/or MMAP/MUNMAP - This malloc can use unix sbrk or any emulation (invoked using - the CALL_MORECORE macro) and/or mmap/munmap or any emulation - (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system - memory. On most unix systems, it tends to work best if both - MORECORE and MMAP are enabled. On Win32, it uses emulations - based on VirtualAlloc. It also uses common C library functions - like memset. - - Compliance: I believe it is compliant with the Single Unix Specification - (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably - others as well. - -* Overview of algorithms - - This is not the fastest, most space-conserving, most portable, or - most tunable malloc ever written. However it is among the fastest - while also being among the most space-conserving, portable and - tunable. Consistent balance across these factors results in a good - general-purpose allocator for malloc-intensive programs. - - In most ways, this malloc is a best-fit allocator. Generally, it - chooses the best-fitting existing chunk for a request, with ties - broken in approximately least-recently-used order. (This strategy - normally maintains low fragmentation.) However, for requests less - than 256bytes, it deviates from best-fit when there is not an - exactly fitting available chunk by preferring to use space adjacent - to that used for the previous small request, as well as by breaking - ties in approximately most-recently-used order. (These enhance - locality of series of small allocations.) And for very large requests - (>= 256Kb by default), it relies on system memory mapping - facilities, if supported. (This helps avoid carrying around and - possibly fragmenting memory used only for large chunks.) - - All operations (except malloc_stats and mallinfo) have execution - times that are bounded by a constant factor of the number of bits in - a size_t, not counting any clearing in calloc or copying in realloc, - or actions surrounding MORECORE and MMAP that have times - proportional to the number of non-contiguous regions returned by - system allocation routines, which is often just 1. In real-time - applications, you can optionally suppress segment traversals using - NO_SEGMENT_TRAVERSAL, which assures bounded execution even when - system allocators return non-contiguous spaces, at the typical - expense of carrying around more memory and increased fragmentation. - - The implementation is not very modular and seriously overuses - macros. Perhaps someday all C compilers will do as good a job - inlining modular code as can now be done by brute-force expansion, - but now, enough of them seem not to. - - Some compilers issue a lot of warnings about code that is - dead/unreachable only on some platforms, and also about intentional - uses of negation on unsigned types. All known cases of each can be - ignored. - - For a longer but out of date high-level description, see - http://gee.cs.oswego.edu/dl/html/malloc.html - -* MSPACES - If MSPACES is defined, then in addition to malloc, free, etc., - this file also defines mspace_malloc, mspace_free, etc. These - are versions of malloc routines that take an "mspace" argument - obtained using create_mspace, to control all internal bookkeeping. - If ONLY_MSPACES is defined, only these versions are compiled. - So if you would like to use this allocator for only some allocations, - and your system malloc for others, you can compile with - ONLY_MSPACES and then do something like... - static mspace mymspace = create_mspace(0,0); // for example - #define mymalloc(bytes) mspace_malloc(mymspace, bytes) - - (Note: If you only need one instance of an mspace, you can instead - use "USE_DL_PREFIX" to relabel the global malloc.) - - You can similarly create thread-local allocators by storing - mspaces as thread-locals. For example: - static __thread mspace tlms = 0; - void* tlmalloc(size_t bytes) { - if (tlms == 0) tlms = create_mspace(0, 0); - return mspace_malloc(tlms, bytes); - } - void tlfree(void* mem) { mspace_free(tlms, mem); } - - Unless FOOTERS is defined, each mspace is completely independent. - You cannot allocate from one and free to another (although - conformance is only weakly checked, so usage errors are not always - caught). If FOOTERS is defined, then each chunk carries around a tag - indicating its originating mspace, and frees are directed to their - originating spaces. - - ------------------------- Compile-time options --------------------------- - -Be careful in setting #define values for numerical constants of type -size_t. On some systems, literal values are not automatically extended -to size_t precision unless they are explicitly casted. You can also -use the symbolic values MAX_SIZE_T, SIZE_T_ONE, etc below. - -WIN32 default: defined if _WIN32 defined - Defining WIN32 sets up defaults for MS environment and compilers. - Otherwise defaults are for unix. Beware that there seem to be some - cases where this malloc might not be a pure drop-in replacement for - Win32 malloc: Random-looking failures from Win32 GDI API's (eg; - SetDIBits()) may be due to bugs in some video driver implementations - when pixel buffers are malloc()ed, and the region spans more than - one VirtualAlloc()ed region. Because dlmalloc uses a small (64Kb) - default granularity, pixel buffers may straddle virtual allocation - regions more often than when using the Microsoft allocator. You can - avoid this by using VirtualAlloc() and VirtualFree() for all pixel - buffers rather than using malloc(). If this is not possible, - recompile this malloc with a larger DEFAULT_GRANULARITY. - -MALLOC_ALIGNMENT default: (size_t)8 - Controls the minimum alignment for malloc'ed chunks. It must be a - power of two and at least 8, even on machines for which smaller - alignments would suffice. It may be defined as larger than this - though. Note however that code and data structures are optimized for - the case of 8-byte alignment. - -MSPACES default: 0 (false) - If true, compile in support for independent allocation spaces. - This is only supported if HAVE_MMAP is true. - -ONLY_MSPACES default: 0 (false) - If true, only compile in mspace versions, not regular versions. - -USE_LOCKS default: 0 (false) - Causes each call to each public routine to be surrounded with - pthread or WIN32 mutex lock/unlock. (If set true, this can be - overridden on a per-mspace basis for mspace versions.) If set to a - non-zero value other than 1, locks are used, but their - implementation is left out, so lock functions must be supplied manually, - as described below. - -USE_SPIN_LOCKS default: 1 iff USE_LOCKS and on x86 using gcc or MSC - If true, uses custom spin locks for locking. This is currently - supported only for x86 platforms using gcc or recent MS compilers. - Otherwise, posix locks or win32 critical sections are used. - -FOOTERS default: 0 - If true, provide extra checking and dispatching by placing - information in the footers of allocated chunks. This adds - space and time overhead. - -INSECURE default: 0 - If true, omit checks for usage errors and heap space overwrites. - -USE_DL_PREFIX default: NOT defined - Causes compiler to prefix all public routines with the string 'dl'. - This can be useful when you only want to use this malloc in one part - of a program, using your regular system malloc elsewhere. - -ABORT default: defined as abort() - Defines how to abort on failed checks. On most systems, a failed - check cannot die with an "assert" or even print an informative - message, because the underlying print routines in turn call malloc, - which will fail again. Generally, the best policy is to simply call - abort(). It's not very useful to do more than this because many - errors due to overwriting will show up as address faults (null, odd - addresses etc) rather than malloc-triggered checks, so will also - abort. Also, most compilers know that abort() does not return, so - can better optimize code conditionally calling it. - -PROCEED_ON_ERROR default: defined as 0 (false) - Controls whether detected bad addresses cause them to bypassed - rather than aborting. If set, detected bad arguments to free and - realloc are ignored. And all bookkeeping information is zeroed out - upon a detected overwrite of freed heap space, thus losing the - ability to ever return it from malloc again, but enabling the - application to proceed. If PROCEED_ON_ERROR is defined, the - static variable malloc_corruption_error_count is compiled in - and can be examined to see if errors have occurred. This option - generates slower code than the default abort policy. - -DEBUG default: NOT defined - The DEBUG setting is mainly intended for people trying to modify - this code or diagnose problems when porting to new platforms. - However, it may also be able to better isolate user errors than just - using runtime checks. The assertions in the check routines spell - out in more detail the assumptions and invariants underlying the - algorithms. The checking is fairly extensive, and will slow down - execution noticeably. Calling malloc_stats or mallinfo with DEBUG - set will attempt to check every non-mmapped allocated and free chunk - in the course of computing the summaries. - -ABORT_ON_ASSERT_FAILURE default: defined as 1 (true) - Debugging assertion failures can be nearly impossible if your - version of the assert macro causes malloc to be called, which will - lead to a cascade of further failures, blowing the runtime stack. - ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(), - which will usually make debugging easier. - -MALLOC_FAILURE_ACTION default: sets errno to ENOMEM, or no-op on win32 - The action to take before "return 0" when malloc fails to be able to - return memory because there is none available. - -HAVE_MORECORE default: 1 (true) unless win32 or ONLY_MSPACES - True if this system supports sbrk or an emulation of it. - -MORECORE default: sbrk - The name of the sbrk-style system routine to call to obtain more - memory. See below for guidance on writing custom MORECORE - functions. The type of the argument to sbrk/MORECORE varies across - systems. It cannot be size_t, because it supports negative - arguments, so it is normally the signed type of the same width as - size_t (sometimes declared as "intptr_t"). It doesn't much matter - though. Internally, we only call it with arguments less than half - the max value of a size_t, which should work across all reasonable - possibilities, although sometimes generating compiler warnings. - -MORECORE_CONTIGUOUS default: 1 (true) if HAVE_MORECORE - If true, take advantage of fact that consecutive calls to MORECORE - with positive arguments always return contiguous increasing - addresses. This is true of unix sbrk. It does not hurt too much to - set it true anyway, since malloc copes with non-contiguities. - Setting it false when definitely non-contiguous saves time - and possibly wasted space it would take to discover this though. - -MORECORE_CANNOT_TRIM default: NOT defined - True if MORECORE cannot release space back to the system when given - negative arguments. This is generally necessary only if you are - using a hand-crafted MORECORE function that cannot handle negative - arguments. - -NO_SEGMENT_TRAVERSAL default: 0 - If non-zero, suppresses traversals of memory segments - returned by either MORECORE or CALL_MMAP. This disables - merging of segments that are contiguous, and selectively - releasing them to the OS if unused, but bounds execution times. - -HAVE_MMAP default: 1 (true) - True if this system supports mmap or an emulation of it. If so, and - HAVE_MORECORE is not true, MMAP is used for all system - allocation. If set and HAVE_MORECORE is true as well, MMAP is - primarily used to directly allocate very large blocks. It is also - used as a backup strategy in cases where MORECORE fails to provide - space from system. Note: A single call to MUNMAP is assumed to be - able to unmap memory that may have be allocated using multiple calls - to MMAP, so long as they are adjacent. - -HAVE_MREMAP default: 1 on linux, else 0 - If true realloc() uses mremap() to re-allocate large blocks and - extend or shrink allocation spaces. - -MMAP_CLEARS default: 1 except on WINCE. - True if mmap clears memory so calloc doesn't need to. This is true - for standard unix mmap using /dev/zero and on WIN32 except for WINCE. - -USE_BUILTIN_FFS default: 0 (i.e., not used) - Causes malloc to use the builtin ffs() function to compute indices. - Some compilers may recognize and intrinsify ffs to be faster than the - supplied C version. Also, the case of x86 using gcc is special-cased - to an asm instruction, so is already as fast as it can be, and so - this setting has no effect. Similarly for Win32 under recent MS compilers. - (On most x86s, the asm version is only slightly faster than the C version.) - -malloc_getpagesize default: derive from system includes, or 4096. - The system page size. To the extent possible, this malloc manages - memory from the system in page-size units. This may be (and - usually is) a function rather than a constant. This is ignored - if WIN32, where page size is determined using getSystemInfo during - initialization. This may be several megabytes if ENABLE_LARGE_PAGES - is enabled. - -ENABLE_LARGE_PAGES default: NOT defined - Causes the system page size to be the value of GetLargePageMinimum() - if that function is available (Windows Server 2003/Vista or later). - This allows the use of large page entries in the MMU which can - significantly improve performance in large working set applications - as TLB cache load is reduced by a factor of three. Note that enabling - this option is equal to locking the process' memory in current - implementations of Windows and requires the SE_LOCK_MEMORY_PRIVILEGE - to be held by the process in order to succeed. - -USE_DEV_RANDOM default: 0 (i.e., not used) - Causes malloc to use /dev/random to initialize secure magic seed for - stamping footers. Otherwise, the current time is used. - -NO_MALLINFO default: 0 - If defined, don't compile "mallinfo". This can be a simple way - of dealing with mismatches between system declarations and - those in this file. - -MALLINFO_FIELD_TYPE default: size_t - The type of the fields in the mallinfo struct. This was originally - defined as "int" in SVID etc, but is more usefully defined as - size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set - -REALLOC_ZERO_BYTES_FREES default: not defined - This should be set if a call to realloc with zero bytes should - be the same as a call to free. Some people think it should. Otherwise, - since this malloc returns a unique pointer for malloc(0), so does - realloc(p, 0). - -LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H -LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H, LACKS_ERRNO_H -LACKS_STDLIB_H default: NOT defined unless on WIN32 - Define these if your system does not have these header files. - You might need to manually insert some of the declarations they provide. - -DEFAULT_GRANULARITY default: page size if MORECORE_CONTIGUOUS, - system_info.dwAllocationGranularity in WIN32, - GetLargePageMinimum() if ENABLE_LARGE_PAGES, - otherwise 64K. - Also settable using mallopt(M_GRANULARITY, x) - The unit for allocating and deallocating memory from the system. On - most systems with contiguous MORECORE, there is no reason to - make this more than a page. However, systems with MMAP tend to - either require or encourage larger granularities. You can increase - this value to prevent system allocation functions to be called so - often, especially if they are slow. The value must be at least one - page and must be a power of two. Setting to 0 causes initialization - to either page size or win32 region size. (Note: In previous - versions of malloc, the equivalent of this option was called - "TOP_PAD") - -DEFAULT_GRANULARITY_ALIGNED default: undefined (which means page size) - Whether to enforce alignment when allocating and deallocating memory - from the system i.e. the base address of all allocations will be - aligned to DEFAULT_GRANULARITY if it is set. Note that enabling this carries - some overhead as multiple calls must now be made when probing for a valid - aligned value, however it does greatly ease the checking for whether - a given memory pointer was allocated by this allocator rather than - some other. - -DEFAULT_TRIM_THRESHOLD default: 2MB - Also settable using mallopt(M_TRIM_THRESHOLD, x) - The maximum amount of unused top-most memory to keep before - releasing via malloc_trim in free(). Automatic trimming is mainly - useful in long-lived programs using contiguous MORECORE. Because - trimming via sbrk can be slow on some systems, and can sometimes be - wasteful (in cases where programs immediately afterward allocate - more large chunks) the value should be high enough so that your - overall system performance would improve by releasing this much - memory. As a rough guide, you might set to a value close to the - average size of a process (program) running on your system. - Releasing this much memory would allow such a process to run in - memory. Generally, it is worth tuning trim thresholds when a - program undergoes phases where several large chunks are allocated - and released in ways that can reuse each other's storage, perhaps - mixed with phases where there are no such chunks at all. The trim - value must be greater than page size to have any useful effect. To - disable trimming completely, you can set to MAX_SIZE_T. Note that the trick - some people use of mallocing a huge space and then freeing it at - program startup, in an attempt to reserve system memory, doesn't - have the intended effect under automatic trimming, since that memory - will immediately be returned to the system. - -DEFAULT_MMAP_THRESHOLD default: 256K - Also settable using mallopt(M_MMAP_THRESHOLD, x) - The request size threshold for using MMAP to directly service a - request. Requests of at least this size that cannot be allocated - using already-existing space will be serviced via mmap. (If enough - normal freed space already exists it is used instead.) Using mmap - segregates relatively large chunks of memory so that they can be - individually obtained and released from the host system. A request - serviced through mmap is never reused by any other request (at least - not directly; the system may just so happen to remap successive - requests to the same locations). Segregating space in this way has - the benefits that: Mmapped space can always be individually released - back to the system, which helps keep the system level memory demands - of a long-lived program low. Also, mapped memory doesn't become - `locked' between other chunks, as can happen with normally allocated - chunks, which means that even trimming via malloc_trim would not - release them. However, it has the disadvantage that the space - cannot be reclaimed, consolidated, and then used to service later - requests, as happens with normal chunks. The advantages of mmap - nearly always outweigh disadvantages for "large" chunks, but the - value of "large" may vary across systems. The default is an - empirically derived value that works well in most systems. You can - disable mmap by setting to MAX_SIZE_T. - -MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP - The number of consolidated frees between checks to release - unused segments when freeing. When using non-contiguous segments, - especially with multiple mspaces, checking only for topmost space - doesn't always suffice to trigger trimming. To compensate for this, - free() will, with a period of MAX_RELEASE_CHECK_RATE (or the - current number of segments, if greater) try to release unused - segments to the OS when freeing chunks that result in - consolidation. The best value for this parameter is a compromise - between slowing down frees with relatively costly checks that - rarely trigger versus holding on to unused memory. To effectively - disable, set to MAX_SIZE_T. This may lead to a very slight speed - improvement at the expense of carrying around more memory. -*/ - -/* Version identifier to allow people to support multiple versions */ -#ifndef DLMALLOC_VERSION -#define DLMALLOC_VERSION 20804 -#endif /* DLMALLOC_VERSION */ - -#ifndef WIN32 -#ifdef _WIN32 -#define WIN32 1 -#endif /* _WIN32 */ -#ifdef _WIN32_WCE -#define LACKS_FCNTL_H -#define WIN32 1 -#endif /* _WIN32_WCE */ -#endif /* WIN32 */ -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <tchar.h> -#define HAVE_MMAP 1 -#define HAVE_MORECORE 0 -#define LACKS_UNISTD_H -#define LACKS_SYS_PARAM_H -#define LACKS_SYS_MMAN_H -#define LACKS_STRING_H -#define LACKS_STRINGS_H -#define LACKS_SYS_TYPES_H -#define LACKS_ERRNO_H -#ifndef MALLOC_FAILURE_ACTION -#define MALLOC_FAILURE_ACTION -#endif /* MALLOC_FAILURE_ACTION */ -#ifdef _WIN32_WCE /* WINCE reportedly does not clear */ -#define MMAP_CLEARS 0 -#else -#define MMAP_CLEARS 1 -#endif /* _WIN32_WCE */ -#endif /* WIN32 */ - -#if defined(DARWIN) || defined(_DARWIN) -/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */ -#ifndef HAVE_MORECORE -#define HAVE_MORECORE 0 -#define HAVE_MMAP 1 -/* OSX allocators provide 16 byte alignment */ -#ifndef MALLOC_ALIGNMENT -#define MALLOC_ALIGNMENT ((size_t)16U) -#endif -#endif /* HAVE_MORECORE */ -#endif /* DARWIN */ - -#ifndef LACKS_SYS_TYPES_H -#include <sys/types.h> /* For size_t */ -#endif /* LACKS_SYS_TYPES_H */ - -#if (defined(__GNUC__) && ((defined(__i386__) || defined(__x86_64__)))) || (defined(_MSC_VER) && _MSC_VER>=1310) -#define SPIN_LOCKS_AVAILABLE 1 -#else -#define SPIN_LOCKS_AVAILABLE 0 -#endif - -/* The maximum possible size_t value has all bits set */ -#define MAX_SIZE_T (~(size_t)0) - -#ifndef ONLY_MSPACES -#define ONLY_MSPACES 0 /* define to a value */ -#else -#define ONLY_MSPACES 1 -#endif /* ONLY_MSPACES */ -#ifndef MSPACES -#if ONLY_MSPACES -#define MSPACES 1 -#else /* ONLY_MSPACES */ -#define MSPACES 0 -#endif /* ONLY_MSPACES */ -#endif /* MSPACES */ -#ifndef MALLOC_ALIGNMENT -#define MALLOC_ALIGNMENT ((size_t)8U) -#endif /* MALLOC_ALIGNMENT */ -#ifndef FOOTERS -#define FOOTERS 0 -#endif /* FOOTERS */ -#ifndef ABORT -#define ABORT abort() -#endif /* ABORT */ -#ifndef ABORT_ON_ASSERT_FAILURE -#define ABORT_ON_ASSERT_FAILURE 1 -#endif /* ABORT_ON_ASSERT_FAILURE */ -#ifndef PROCEED_ON_ERROR -#define PROCEED_ON_ERROR 0 -#endif /* PROCEED_ON_ERROR */ -#ifndef USE_LOCKS -#define USE_LOCKS 0 -#endif /* USE_LOCKS */ -#ifndef USE_SPIN_LOCKS -#if USE_LOCKS && SPIN_LOCKS_AVAILABLE -#define USE_SPIN_LOCKS 1 -#else -#define USE_SPIN_LOCKS 0 -#endif /* USE_LOCKS && SPIN_LOCKS_AVAILABLE. */ -#endif /* USE_SPIN_LOCKS */ -#ifndef INSECURE -#define INSECURE 0 -#endif /* INSECURE */ -#ifndef HAVE_MMAP -#define HAVE_MMAP 1 -#endif /* HAVE_MMAP */ -#ifndef MMAP_CLEARS -#define MMAP_CLEARS 1 -#endif /* MMAP_CLEARS */ -#ifndef HAVE_MREMAP -#ifdef linux -#define HAVE_MREMAP 1 -#else /* linux */ -#define HAVE_MREMAP 0 -#endif /* linux */ -#endif /* HAVE_MREMAP */ -#ifndef MALLOC_FAILURE_ACTION -#define MALLOC_FAILURE_ACTION errno = ENOMEM; -#endif /* MALLOC_FAILURE_ACTION */ -#ifndef HAVE_MORECORE -#if ONLY_MSPACES -#define HAVE_MORECORE 0 -#else /* ONLY_MSPACES */ -#define HAVE_MORECORE 1 -#endif /* ONLY_MSPACES */ -#endif /* HAVE_MORECORE */ -#if !HAVE_MORECORE -#define MORECORE_CONTIGUOUS 0 -#else /* !HAVE_MORECORE */ -#define MORECORE_DEFAULT sbrk -#ifndef MORECORE_CONTIGUOUS -#define MORECORE_CONTIGUOUS 1 -#endif /* MORECORE_CONTIGUOUS */ -#endif /* HAVE_MORECORE */ -#ifndef DEFAULT_GRANULARITY -#if (MORECORE_CONTIGUOUS || defined(WIN32)) -#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */ -#else /* MORECORE_CONTIGUOUS */ -#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U) -#endif /* MORECORE_CONTIGUOUS */ -#endif /* DEFAULT_GRANULARITY */ -#ifndef DEFAULT_TRIM_THRESHOLD -#ifndef MORECORE_CANNOT_TRIM -#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U) -#else /* MORECORE_CANNOT_TRIM */ -#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T -#endif /* MORECORE_CANNOT_TRIM */ -#endif /* DEFAULT_TRIM_THRESHOLD */ -#ifndef DEFAULT_MMAP_THRESHOLD -#if HAVE_MMAP -#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U) -#else /* HAVE_MMAP */ -#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T -#endif /* HAVE_MMAP */ -#endif /* DEFAULT_MMAP_THRESHOLD */ -#ifndef MAX_RELEASE_CHECK_RATE -#if HAVE_MMAP -#define MAX_RELEASE_CHECK_RATE 4095 -#else -#define MAX_RELEASE_CHECK_RATE MAX_SIZE_T -#endif /* HAVE_MMAP */ -#endif /* MAX_RELEASE_CHECK_RATE */ -#ifndef USE_BUILTIN_FFS -#define USE_BUILTIN_FFS 0 -#endif /* USE_BUILTIN_FFS */ -#ifndef USE_DEV_RANDOM -#define USE_DEV_RANDOM 0 -#endif /* USE_DEV_RANDOM */ -#ifndef NO_MALLINFO -#define NO_MALLINFO 0 -#endif /* NO_MALLINFO */ -#ifndef MALLINFO_FIELD_TYPE -#define MALLINFO_FIELD_TYPE size_t -#endif /* MALLINFO_FIELD_TYPE */ -#ifndef NO_SEGMENT_TRAVERSAL -#define NO_SEGMENT_TRAVERSAL 0 -#endif /* NO_SEGMENT_TRAVERSAL */ - -/* - mallopt tuning options. SVID/XPG defines four standard parameter - numbers for mallopt, normally defined in malloc.h. None of these - are used in this malloc, so setting them has no effect. But this - malloc does support the following options. -*/ - -#define M_TRIM_THRESHOLD (-1) -#define M_GRANULARITY (-2) -#define M_MMAP_THRESHOLD (-3) - -/* ------------------------ Mallinfo declarations ------------------------ */ - -#if !NO_MALLINFO -/* - This version of malloc supports the standard SVID/XPG mallinfo - routine that returns a struct containing usage properties and - statistics. It should work on any system that has a - /usr/include/malloc.h defining struct mallinfo. The main - declaration needed is the mallinfo struct that is returned (by-copy) - by mallinfo(). The malloinfo struct contains a bunch of fields that - are not even meaningful in this version of malloc. These fields are - are instead filled by mallinfo() with other numbers that might be of - interest. - - HAVE_USR_INCLUDE_MALLOC_H should be set if you have a - /usr/include/malloc.h file that includes a declaration of struct - mallinfo. If so, it is included; else a compliant version is - declared below. These must be precisely the same for mallinfo() to - work. The original SVID version of this struct, defined on most - systems with mallinfo, declares all fields as ints. But some others - define as unsigned long. If your system defines the fields using a - type of different width than listed here, you MUST #include your - system version and #define HAVE_USR_INCLUDE_MALLOC_H. -*/ - -/* #define HAVE_USR_INCLUDE_MALLOC_H */ - -#ifdef HAVE_USR_INCLUDE_MALLOC_H -#include "/usr/include/malloc.h" -#else /* HAVE_USR_INCLUDE_MALLOC_H */ -#ifndef STRUCT_MALLINFO_DECLARED -#define STRUCT_MALLINFO_DECLARED 1 -struct mallinfo { - MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ - MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ - MALLINFO_FIELD_TYPE smblks; /* always 0 */ - MALLINFO_FIELD_TYPE hblks; /* always 0 */ - MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ - MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ - MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ - MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ - MALLINFO_FIELD_TYPE fordblks; /* total free space */ - MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ -}; -#endif /* STRUCT_MALLINFO_DECLARED */ -#endif /* HAVE_USR_INCLUDE_MALLOC_H */ -#endif /* NO_MALLINFO */ - -/* - Try to persuade compilers to inline. The most critical functions for - inlining are defined as macros, so these aren't used for them. -*/ - -#ifndef FORCEINLINE - #if defined(__GNUC__) -#define FORCEINLINE __inline __attribute__ ((always_inline)) - #elif defined(_MSC_VER) - #define FORCEINLINE __forceinline - #endif -#endif -#ifndef NOINLINE - #if defined(__GNUC__) - #define NOINLINE __attribute__ ((noinline)) - #elif defined(_MSC_VER) - #define NOINLINE __declspec(noinline) - #else - #define NOINLINE - #endif -#endif - -#ifdef __cplusplus -extern "C" { -#ifndef FORCEINLINE - #define FORCEINLINE inline -#endif -#endif /* __cplusplus */ -#ifndef FORCEINLINE - #define FORCEINLINE -#endif - -#if !ONLY_MSPACES - -/* ------------------- Declarations of public routines ------------------- */ - -#ifndef USE_DL_PREFIX -#define dlcalloc calloc -#define dlfree free -#define dlmalloc malloc -#define dlmemalign memalign -#define dlrealloc realloc -#define dlvalloc valloc -#define dlpvalloc pvalloc -#define dlmallinfo mallinfo -#define dlmallopt mallopt -#define dlmalloc_trim malloc_trim -#define dlmalloc_stats malloc_stats -#define dlmalloc_usable_size malloc_usable_size -#define dlmalloc_footprint malloc_footprint -#define dlmalloc_max_footprint malloc_max_footprint -#define dlindependent_calloc independent_calloc -#define dlindependent_comalloc independent_comalloc -#endif /* USE_DL_PREFIX */ - - -/* - malloc(size_t n) - Returns a pointer to a newly allocated chunk of at least n bytes, or - null if no space is available, in which case errno is set to ENOMEM - on ANSI C systems. - - If n is zero, malloc returns a minimum-sized chunk. (The minimum - size is 16 bytes on most 32bit systems, and 32 bytes on 64bit - systems.) Note that size_t is an unsigned type, so calls with - arguments that would be negative if signed are interpreted as - requests for huge amounts of space, which will often fail. The - maximum supported value of n differs across systems, but is in all - cases less than the maximum representable value of a size_t. -*/ -void* dlmalloc(size_t); - -/* - free(void* p) - Releases the chunk of memory pointed to by p, that had been previously - allocated using malloc or a related routine such as realloc. - It has no effect if p is null. If p was not malloced or already - freed, free(p) will by default cause the current program to abort. -*/ -void dlfree(void*); - -/* - calloc(size_t n_elements, size_t element_size); - Returns a pointer to n_elements * element_size bytes, with all locations - set to zero. -*/ -void* dlcalloc(size_t, size_t); - -/* - realloc(void* p, size_t n) - Returns a pointer to a chunk of size n that contains the same data - as does chunk p up to the minimum of (n, p's size) bytes, or null - if no space is available. - - The returned pointer may or may not be the same as p. The algorithm - prefers extending p in most cases when possible, otherwise it - employs the equivalent of a malloc-copy-free sequence. - - If p is null, realloc is equivalent to malloc. - - If space is not available, realloc returns null, errno is set (if on - ANSI) and p is NOT freed. - - if n is for fewer bytes than already held by p, the newly unused - space is lopped off and freed if possible. realloc with a size - argument of zero (re)allocates a minimum-sized chunk. - - The old unix realloc convention of allowing the last-free'd chunk - to be used as an argument to realloc is not supported. -*/ - -void* dlrealloc(void*, size_t); - -/* - memalign(size_t alignment, size_t n); - Returns a pointer to a newly allocated chunk of n bytes, aligned - in accord with the alignment argument. - - The alignment argument should be a power of two. If the argument is - not a power of two, the nearest greater power is used. - 8-byte alignment is guaranteed by normal malloc calls, so don't - bother calling memalign with an argument of 8 or less. - - Overreliance on memalign is a sure way to fragment space. -*/ -void* dlmemalign(size_t, size_t); - -/* - valloc(size_t n); - Equivalent to memalign(pagesize, n), where pagesize is the page - size of the system. If the pagesize is unknown, 4096 is used. -*/ -void* dlvalloc(size_t); - -/* - mallopt(int parameter_number, int parameter_value) - Sets tunable parameters The format is to provide a - (parameter-number, parameter-value) pair. mallopt then sets the - corresponding parameter to the argument value if it can (i.e., so - long as the value is meaningful), and returns 1 if successful else - 0. To workaround the fact that mallopt is specified to use int, - not size_t parameters, the value -1 is specially treated as the - maximum unsigned size_t value. - - SVID/XPG/ANSI defines four standard param numbers for mallopt, - normally defined in malloc.h. None of these are use in this malloc, - so setting them has no effect. But this malloc also supports other - options in mallopt. See below for details. Briefly, supported - parameters are as follows (listed defaults are for "typical" - configurations). - - Symbol param # default allowed param values - M_TRIM_THRESHOLD -1 2*1024*1024 any (-1 disables) - M_GRANULARITY -2 page size any power of 2 >= page size - M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) -*/ -int dlmallopt(int, int); - -/* - malloc_footprint(); - Returns the number of bytes obtained from the system. The total - number of bytes allocated by malloc, realloc etc., is less than this - value. Unlike mallinfo, this function returns only a precomputed - result, so can be called frequently to monitor memory consumption. - Even if locks are otherwise defined, this function does not use them, - so results might not be up to date. -*/ -size_t dlmalloc_footprint(void); - -/* - malloc_max_footprint(); - Returns the maximum number of bytes obtained from the system. This - value will be greater than current footprint if deallocated space - has been reclaimed by the system. The peak number of bytes allocated - by malloc, realloc etc., is less than this value. Unlike mallinfo, - this function returns only a precomputed result, so can be called - frequently to monitor memory consumption. Even if locks are - otherwise defined, this function does not use them, so results might - not be up to date. -*/ -size_t dlmalloc_max_footprint(void); - -#if !NO_MALLINFO -/* - mallinfo() - Returns (by copy) a struct containing various summary statistics: - - arena: current total non-mmapped bytes allocated from system - ordblks: the number of free chunks - smblks: always zero. - hblks: current number of mmapped regions - hblkhd: total bytes held in mmapped regions - usmblks: the maximum total allocated space. This will be greater - than current total if trimming has occurred. - fsmblks: always zero - uordblks: current total allocated space (normal or mmapped) - fordblks: total free space - keepcost: the maximum number of bytes that could ideally be released - back to system via malloc_trim. ("ideally" means that - it ignores page restrictions etc.) - - Because these fields are ints, but internal bookkeeping may - be kept as longs, the reported values may wrap around zero and - thus be inaccurate. -*/ -struct mallinfo dlmallinfo(void); -#endif /* NO_MALLINFO */ - -/* - independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); - - independent_calloc is similar to calloc, but instead of returning a - single cleared space, it returns an array of pointers to n_elements - independent elements that can hold contents of size elem_size, each - of which starts out cleared, and can be independently freed, - realloc'ed etc. The elements are guaranteed to be adjacently - allocated (this is not guaranteed to occur with multiple callocs or - mallocs), which may also improve cache locality in some - applications. - - The "chunks" argument is optional (i.e., may be null, which is - probably the most typical usage). If it is null, the returned array - is itself dynamically allocated and should also be freed when it is - no longer needed. Otherwise, the chunks array must be of at least - n_elements in length. It is filled in with the pointers to the - chunks. - - In either case, independent_calloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and "chunks" - is null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be individually freed when it is no longer - needed. If you'd like to instead be able to free all at once, you - should instead use regular calloc and assign pointers into this - space to represent elements. (In this case though, you cannot - independently free elements.) - - independent_calloc simplifies and speeds up implementations of many - kinds of pools. It may also be useful when constructing large data - structures that initially have a fixed number of fixed-sized nodes, - but the number is not known at compile time, and some of the nodes - may later need to be freed. For example: - - struct Node { int item; struct Node* next; }; - - struct Node* build_list() { - struct Node** pool; - int n = read_number_of_nodes_needed(); - if (n <= 0) return 0; - pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); - if (pool == 0) die(); - // organize into a linked list... - struct Node* first = pool[0]; - for (i = 0; i < n-1; ++i) - pool[i]->next = pool[i+1]; - free(pool); // Can now free the array (or not, if it is needed later) - return first; - } -*/ -void** dlindependent_calloc(size_t, size_t, void**); - -/* - independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); - - independent_comalloc allocates, all at once, a set of n_elements - chunks with sizes indicated in the "sizes" array. It returns - an array of pointers to these elements, each of which can be - independently freed, realloc'ed etc. The elements are guaranteed to - be adjacently allocated (this is not guaranteed to occur with - multiple callocs or mallocs), which may also improve cache locality - in some applications. - - The "chunks" argument is optional (i.e., may be null). If it is null - the returned array is itself dynamically allocated and should also - be freed when it is no longer needed. Otherwise, the chunks array - must be of at least n_elements in length. It is filled in with the - pointers to the chunks. - - In either case, independent_comalloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and chunks is - null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be individually freed when it is no longer - needed. If you'd like to instead be able to free all at once, you - should instead use a single regular malloc, and assign pointers at - particular offsets in the aggregate space. (In this case though, you - cannot independently free elements.) - - independent_comallac differs from independent_calloc in that each - element may have a different size, and also that it does not - automatically clear elements. - - independent_comalloc can be used to speed up allocation in cases - where several structs or objects must always be allocated at the - same time. For example: - - struct Head { ... } - struct Foot { ... } - - void send_message(char* msg) { - int msglen = strlen(msg); - size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; - void* chunks[3]; - if (independent_comalloc(3, sizes, chunks) == 0) - die(); - struct Head* head = (struct Head*)(chunks[0]); - char* body = (char*)(chunks[1]); - struct Foot* foot = (struct Foot*)(chunks[2]); - // ... - } - - In general though, independent_comalloc is worth using only for - larger values of n_elements. For small values, you probably won't - detect enough difference from series of malloc calls to bother. - - Overuse of independent_comalloc can increase overall memory usage, - since it cannot reuse existing noncontiguous small chunks that - might be available for some of the elements. -*/ -void** dlindependent_comalloc(size_t, size_t*, void**); - - -/* - pvalloc(size_t n); - Equivalent to valloc(minimum-page-that-holds(n)), that is, - round up n to nearest pagesize. - */ -void* dlpvalloc(size_t); - -/* - malloc_trim(size_t pad); - - If possible, gives memory back to the system (via negative arguments - to sbrk) if there is unused memory at the `high' end of the malloc - pool or in unused MMAP segments. You can call this after freeing - large blocks of memory to potentially reduce the system-level memory - requirements of a program. However, it cannot guarantee to reduce - memory. Under some allocation patterns, some large free blocks of - memory will be locked between two used chunks, so they cannot be - given back to the system. - - The `pad' argument to malloc_trim represents the amount of free - trailing space to leave untrimmed. If this argument is zero, only - the minimum amount of memory to maintain internal data structures - will be left. Non-zero arguments can be supplied to maintain enough - trailing space to service future expected allocations without having - to re-obtain memory from the system. - - Malloc_trim returns 1 if it actually released any memory, else 0. -*/ -int dlmalloc_trim(size_t); - -/* - malloc_stats(); - Prints on stderr the amount of space obtained from the system (both - via sbrk and mmap), the maximum amount (which may be more than - current if malloc_trim and/or munmap got called), and the current - number of bytes allocated via malloc (or realloc, etc) but not yet - freed. Note that this is the number of bytes allocated, not the - number requested. It will be larger than the number requested - because of alignment and bookkeeping overhead. Because it includes - alignment wastage as being in use, this figure may be greater than - zero even when no user-level chunks are allocated. - - The reported current and maximum system memory can be inaccurate if - a program makes other calls to system memory allocation functions - (normally sbrk) outside of malloc. - - malloc_stats prints only the most commonly interesting statistics. - More information can be obtained by calling mallinfo. -*/ -void dlmalloc_stats(void); - -#endif /* ONLY_MSPACES */ - -/* - malloc_usable_size(void* p); - - Returns the number of bytes you can actually use in - an allocated chunk, which may be more than you requested (although - often not) due to alignment and minimum size constraints. - You can use this many bytes without worrying about - overwriting other allocated objects. This is not a particularly great - programming practice. malloc_usable_size can be more useful in - debugging and assertions, for example: - - p = malloc(n); - assert(malloc_usable_size(p) >= 256); -*/ -size_t dlmalloc_usable_size(void*); - - -#if MSPACES - -/* - mspace is an opaque type representing an independent - region of space that supports mspace_malloc, etc. -*/ -typedef void* mspace; - -/* - create_mspace creates and returns a new independent space with the - given initial capacity, or, if 0, the default granularity size. It - returns null if there is no system memory available to create the - space. If argument locked is non-zero, the space uses a separate - lock to control access. The capacity of the space will grow - dynamically as needed to service mspace_malloc requests. You can - control the sizes of incremental increases of this space by - compiling with a different DEFAULT_GRANULARITY or dynamically - setting with mallopt(M_GRANULARITY, value). -*/ -mspace create_mspace(size_t capacity, int locked); - -/* - destroy_mspace destroys the given space, and attempts to return all - of its memory back to the system, returning the total number of - bytes freed. After destruction, the results of access to all memory - used by the space become undefined. -*/ -size_t destroy_mspace(mspace msp); - -/* - create_mspace_with_base uses the memory supplied as the initial base - of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this - space is used for bookkeeping, so the capacity must be at least this - large. (Otherwise 0 is returned.) When this initial space is - exhausted, additional memory will be obtained from the system. - Destroying this space will deallocate all additionally allocated - space (if possible) but not the initial base. -*/ -mspace create_mspace_with_base(void* base, size_t capacity, int locked); - -/* - mspace_track_large_chunks controls whether requests for large chunks - are allocated in their own untracked mmapped regions, separate from - others in this mspace. By default large chunks are not tracked, - which reduces fragmentation. However, such chunks are not - necessarily released to the system upon destroy_mspace. Enabling - tracking by setting to true may increase fragmentation, but avoids - leakage when relying on destroy_mspace to release all memory - allocated using this space. The function returns the previous - setting. -*/ -int mspace_track_large_chunks(mspace msp, int enable); - - -/* - mspace_malloc behaves as malloc, but operates within - the given space. -*/ -void* mspace_malloc(mspace msp, size_t bytes); - -/* - mspace_free behaves as free, but operates within - the given space. - - If compiled with FOOTERS==1, mspace_free is not actually needed. - free may be called instead of mspace_free because freed chunks from - any space are handled by their originating spaces. -*/ -void mspace_free(mspace msp, void* mem); - -/* - mspace_realloc behaves as realloc, but operates within - the given space. - - If compiled with FOOTERS==1, mspace_realloc is not actually - needed. realloc may be called instead of mspace_realloc because - realloced chunks from any space are handled by their originating - spaces. -*/ -void* mspace_realloc(mspace msp, void* mem, size_t newsize); - -/* - mspace_calloc behaves as calloc, but operates within - the given space. -*/ -void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); - -/* - mspace_memalign behaves as memalign, but operates within - the given space. -*/ -void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); - -/* - mspace_independent_calloc behaves as independent_calloc, but - operates within the given space. -*/ -void** mspace_independent_calloc(mspace msp, size_t n_elements, - size_t elem_size, void* chunks[]); - -/* - mspace_independent_comalloc behaves as independent_comalloc, but - operates within the given space. -*/ -void** mspace_independent_comalloc(mspace msp, size_t n_elements, - size_t sizes[], void* chunks[]); - -/* - mspace_footprint() returns the number of bytes obtained from the - system for this space. -*/ -size_t mspace_footprint(mspace msp); - -/* - mspace_max_footprint() returns the peak number of bytes obtained from the - system for this space. -*/ -size_t mspace_max_footprint(mspace msp); - - -#if !NO_MALLINFO -/* - mspace_mallinfo behaves as mallinfo, but reports properties of - the given space. -*/ -struct mallinfo mspace_mallinfo(mspace msp); -#endif /* NO_MALLINFO */ - -/* - malloc_usable_size(void* p) behaves the same as malloc_usable_size; -*/ - size_t mspace_usable_size(void* mem); - -/* - mspace_malloc_stats behaves as malloc_stats, but reports - properties of the given space. -*/ -void mspace_malloc_stats(mspace msp); - -/* - mspace_trim behaves as malloc_trim, but - operates within the given space. -*/ -int mspace_trim(mspace msp, size_t pad); - -/* - An alias for mallopt. -*/ -int mspace_mallopt(int, int); - -#endif /* MSPACES */ - -#ifdef __cplusplus -} /* end of extern "C" */ -#endif /* __cplusplus */ - -/* - ======================================================================== - To make a fully customizable malloc.h header file, cut everything - above this line, put into file malloc.h, edit to suit, and #include it - on the next line, as well as in programs that use this malloc. - ======================================================================== -*/ - -/* #include "malloc.h" */ - -/*------------------------------ internal #includes ---------------------- */ - -#ifdef WIN32 -#pragma warning( disable : 4146 ) /* no "unsigned" warnings */ -#endif /* WIN32 */ - -#include <stdio.h> /* for printing in malloc_stats */ - -#ifndef LACKS_ERRNO_H -#include <errno.h> /* for MALLOC_FAILURE_ACTION */ -#endif /* LACKS_ERRNO_H */ -#if FOOTERS || DEBUG -#include <time.h> /* for magic initialization */ -#endif /* FOOTERS */ -#ifndef LACKS_STDLIB_H -#include <stdlib.h> /* for abort() */ -#endif /* LACKS_STDLIB_H */ -#ifdef DEBUG -#if ABORT_ON_ASSERT_FAILURE -#undef assert -#define assert(x) if(!(x)) ABORT -#else /* ABORT_ON_ASSERT_FAILURE */ -#include <assert.h> -#endif /* ABORT_ON_ASSERT_FAILURE */ -#else /* DEBUG */ -#ifndef assert -#define assert(x) -#endif -#define DEBUG 0 -#endif /* DEBUG */ -#ifndef LACKS_STRING_H -#include <string.h> /* for memset etc */ -#endif /* LACKS_STRING_H */ -#if USE_BUILTIN_FFS -#ifndef LACKS_STRINGS_H -#include <strings.h> /* for ffs */ -#endif /* LACKS_STRINGS_H */ -#endif /* USE_BUILTIN_FFS */ -#if HAVE_MMAP -#ifndef LACKS_SYS_MMAN_H -/* On some versions of linux, mremap decl in mman.h needs __USE_GNU set */ -#if (defined(linux) && !defined(__USE_GNU)) -#define __USE_GNU 1 -#include <sys/mman.h> /* for mmap */ -#undef __USE_GNU -#else -#include <sys/mman.h> /* for mmap */ -#endif /* linux */ -#endif /* LACKS_SYS_MMAN_H */ -#ifndef LACKS_FCNTL_H -#include <fcntl.h> -#endif /* LACKS_FCNTL_H */ -#endif /* HAVE_MMAP */ -#ifndef LACKS_UNISTD_H -#include <unistd.h> /* for sbrk, sysconf */ -#else /* LACKS_UNISTD_H */ -#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) -extern void* sbrk(ptrdiff_t); -#endif /* FreeBSD etc */ -#endif /* LACKS_UNISTD_H */ - -/* Declarations for locking */ -#if USE_LOCKS -#ifndef WIN32 -#include <pthread.h> -#if defined (__SVR4) && defined (__sun) /* solaris */ -#include <thread.h> -#endif /* solaris */ -#else -#ifndef _M_AMD64 -/* These are already defined on AMD64 builds */ -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ -LONG __cdecl _InterlockedCompareExchange(LONG volatile *Dest, LONG Exchange, LONG Comp); -LONG __cdecl _InterlockedExchange(LONG volatile *Target, LONG Value); -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* _M_AMD64 */ -#pragma intrinsic (_InterlockedCompareExchange) -#pragma intrinsic (_InterlockedExchange) -#define interlockedcompareexchange _InterlockedCompareExchange -#define interlockedexchange _InterlockedExchange -#endif /* Win32 */ -#endif /* USE_LOCKS */ - -/* Declarations for bit scanning on win32 */ -#if defined(_MSC_VER) && _MSC_VER>=1300 -#ifndef BitScanForward /* Try to avoid pulling in WinNT.h */ -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ -unsigned char _BitScanForward(unsigned long *index, unsigned long mask); -unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#define BitScanForward _BitScanForward -#define BitScanReverse _BitScanReverse -#pragma intrinsic(_BitScanForward) -#pragma intrinsic(_BitScanReverse) -#endif /* BitScanForward */ -#endif /* defined(_MSC_VER) && _MSC_VER>=1300 */ - -#ifndef WIN32 -#ifndef malloc_getpagesize -# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */ -# ifndef _SC_PAGE_SIZE -# define _SC_PAGE_SIZE _SC_PAGESIZE -# endif -# endif -# ifdef _SC_PAGE_SIZE -# define malloc_getpagesize sysconf(_SC_PAGE_SIZE) -# else -# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE) - extern size_t getpagesize(); -# define malloc_getpagesize getpagesize() -# else -# ifdef WIN32 /* use supplied emulation of getpagesize */ -# define malloc_getpagesize getpagesize() -# else -# ifndef LACKS_SYS_PARAM_H -# include <sys/param.h> -# endif -# ifdef EXEC_PAGESIZE -# define malloc_getpagesize EXEC_PAGESIZE -# else -# ifdef NBPG -# ifndef CLSIZE -# define malloc_getpagesize NBPG -# else -# define malloc_getpagesize (NBPG * CLSIZE) -# endif -# else -# ifdef NBPC -# define malloc_getpagesize NBPC -# else -# ifdef PAGESIZE -# define malloc_getpagesize PAGESIZE -# else /* just guess */ -# define malloc_getpagesize ((size_t)4096U) -# endif -# endif -# endif -# endif -# endif -# endif -# endif -#endif -#endif - - - -/* ------------------- size_t and alignment properties -------------------- */ - -/* The byte and bit size of a size_t */ -#define SIZE_T_SIZE (sizeof(size_t)) -#define SIZE_T_BITSIZE (sizeof(size_t) << 3) - -/* Some constants coerced to size_t */ -/* Annoying but necessary to avoid errors on some platforms */ -#define SIZE_T_ZERO ((size_t)0) -#define SIZE_T_ONE ((size_t)1) -#define SIZE_T_TWO ((size_t)2) -#define SIZE_T_FOUR ((size_t)4) -#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1) -#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2) -#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES) -#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U) - -/* The bit mask value corresponding to MALLOC_ALIGNMENT */ -#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE) - -/* True if address a has acceptable alignment */ -#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0) - -/* the number of bytes to offset an address to align it */ -#define align_offset(A)\ - ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\ - ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK)) - -/* - malloc_params holds global properties, including those that can be - dynamically set using mallopt. There is a single instance, mparams, - initialized in init_mparams. Note that the non-zeroness of "magic" - also serves as an initialization flag. -*/ -typedef unsigned int flag_t; -struct malloc_params { - volatile size_t magic; - size_t page_size; - size_t granularity; - size_t mmap_threshold; - size_t trim_threshold; - flag_t default_mflags; -}; - -static struct malloc_params mparams; - -/* Ensure mparams initialized */ -#define ensure_initialization() (void)(mparams.magic != 0 || init_mparams()) - -/* -------------------------- MMAP preliminaries ------------------------- */ - -/* - If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and - checks to fail so compiler optimizer can delete code rather than - using so many "#if"s. -*/ - - -/* MORECORE and MMAP must return MFAIL on failure */ -#define MFAIL ((void*)(MAX_SIZE_T)) -#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */ - -#if HAVE_MMAP - -#ifndef WIN32 -#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) -#define MAP_ANONYMOUS MAP_ANON -#endif /* MAP_ANON */ -#ifdef DEFAULT_GRANULARITY_ALIGNED -#define MMAP_IMPL mmap_aligned -static void* lastAlignedmmap; /* Used as a hint */ -static void* mmap_aligned(void *start, size_t length, int prot, int flags, int fd, off_t offset) { - void* baseaddress = 0; - void* ptr = 0; - if(!start) { - baseaddress = lastAlignedmmap; - for(;;) { - if(baseaddress) flags|=MAP_FIXED; - ptr = mmap(baseaddress, length, prot, flags, fd, offset); - if(!ptr) - baseaddress = (void*)((size_t)baseaddress + mparams.granularity); - else if((size_t)ptr & (mparams.granularity - SIZE_T_ONE)) { - munmap(ptr, length); - baseaddress = (void*)(((size_t)ptr + mparams.granularity) & ~(mparams.granularity - SIZE_T_ONE)); - } - else break; - } - } - else ptr = mmap(start, length, prot, flags, fd, offset); - if(ptr) lastAlignedmmap = (void*)((size_t) ptr + mparams.granularity); - return ptr; -} -#else -#define MMAP_IMPL mmap -#endif /* DEFAULT_GRANULARITY_ALIGNED */ -#define MUNMAP_DEFAULT(a, s) munmap((a), (s)) -#define MMAP_PROT (PROT_READ|PROT_WRITE) -#ifdef MAP_ANONYMOUS -#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS) -#define MMAP_DEFAULT(s) MMAP_IMPL(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0) -#else /* MAP_ANONYMOUS */ -/* - Nearly all versions of mmap support MAP_ANONYMOUS, so the following - is unlikely to be needed, but is supplied just in case. -*/ -#define MMAP_FLAGS (MAP_PRIVATE) -static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */ -#define MMAP_DEFAULT(s) ((dev_zero_fd < 0) ? \ - (dev_zero_fd = open("/dev/zero", O_RDWR), \ - MMAP_IMPL(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \ - MMAP_IMPL(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) -#endif /* MAP_ANONYMOUS */ - -#define DIRECT_MMAP_DEFAULT(s) MMAP_DEFAULT(s) - -#else /* WIN32 */ - -/* Win32 MMAP via VirtualAlloc */ -#ifdef DEFAULT_GRANULARITY_ALIGNED -static void* lastWin32mmap; /* Used as a hint */ -#endif /* DEFAULT_GRANULARITY_ALIGNED */ -#ifdef ENABLE_LARGE_PAGES -static int largepagesavailable = 1; -#endif /* ENABLE_LARGE_PAGES */ -static FORCEINLINE void* win32mmap(size_t size) { - void* baseaddress = 0; - void* ptr = 0; -#ifdef ENABLE_LARGE_PAGES - /* Note that large pages are *always* allocated on a large page boundary. - If however granularity is small then don't waste a kernel call if size - isn't around the size of a large page */ - if(largepagesavailable && size >= 1*1024*1024) { - ptr = VirtualAlloc(baseaddress, size, MEM_RESERVE|MEM_COMMIT|MEM_LARGE_PAGES, PAGE_READWRITE); - if(!ptr && ERROR_PRIVILEGE_NOT_HELD==GetLastError()) largepagesavailable=0; - } -#endif - if(!ptr) { -#ifdef DEFAULT_GRANULARITY_ALIGNED - /* We try to avoid overhead by speculatively reserving at aligned - addresses until we succeed */ - baseaddress = lastWin32mmap; - for(;;) { - void* reserveaddr = VirtualAlloc(baseaddress, size, MEM_RESERVE, PAGE_READWRITE); - if(!reserveaddr) - baseaddress = (void*)((size_t)baseaddress + mparams.granularity); - else if((size_t)reserveaddr & (mparams.granularity - SIZE_T_ONE)) { - VirtualFree(reserveaddr, 0, MEM_RELEASE); - baseaddress = (void*)(((size_t)reserveaddr + mparams.granularity) & ~(mparams.granularity - SIZE_T_ONE)); - } - else break; - } -#endif - if(!ptr) ptr = VirtualAlloc(baseaddress, size, baseaddress ? MEM_COMMIT : MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); -#if DEBUG - if(lastWin32mmap && ptr!=lastWin32mmap) printf("Non-contiguous VirtualAlloc between %p and %p\n", ptr, lastWin32mmap); -#endif -#ifdef DEFAULT_GRANULARITY_ALIGNED - if(ptr) lastWin32mmap = (void*)((size_t) ptr + mparams.granularity); -#endif - } -#if DEBUG -#ifdef ENABLE_LARGE_PAGES - printf("VirtualAlloc returns %p size %u. LargePagesAvailable=%d\n", ptr, size, largepagesavailable); -#else - printf("VirtualAlloc returns %p size %u\n", ptr, size); -#endif -#endif - return (ptr != 0)? ptr: MFAIL; -} - -/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ -static FORCEINLINE void* win32direct_mmap(size_t size) { - void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, - PAGE_READWRITE); - return (ptr != 0)? ptr: MFAIL; -} - -/* This function supports releasing coalesed segments */ -static FORCEINLINE int win32munmap(void* ptr, size_t size) { - MEMORY_BASIC_INFORMATION minfo; - char* cptr = (char*)ptr; - while (size) { - if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0) - return -1; - if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr || - minfo.State != MEM_COMMIT || minfo.RegionSize > size) - return -1; - if (VirtualFree(cptr, 0, MEM_RELEASE) == 0) - return -1; - cptr += minfo.RegionSize; - size -= minfo.RegionSize; - } - return 0; -} - -#define MMAP_DEFAULT(s) win32mmap(s) -#define MUNMAP_DEFAULT(a, s) win32munmap((a), (s)) -#define DIRECT_MMAP_DEFAULT(s) win32direct_mmap(s) -#endif /* WIN32 */ -#endif /* HAVE_MMAP */ - -#if HAVE_MREMAP -#ifndef WIN32 -#define MREMAP_DEFAULT(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv)) -#endif /* WIN32 */ -#endif /* HAVE_MREMAP */ - - -/** - * Define CALL_MORECORE - */ -#if HAVE_MORECORE - #ifdef MORECORE - #define CALL_MORECORE(S) MORECORE(S) - #else /* MORECORE */ - #define CALL_MORECORE(S) MORECORE_DEFAULT(S) - #endif /* MORECORE */ -#else /* HAVE_MORECORE */ - #define CALL_MORECORE(S) MFAIL -#endif /* HAVE_MORECORE */ - -/** - * Define CALL_MMAP/CALL_MUNMAP/CALL_DIRECT_MMAP - */ -#if HAVE_MMAP - #define USE_MMAP_BIT (SIZE_T_ONE) - - #ifdef MMAP - #define CALL_MMAP(s) MMAP(s) - #else /* MMAP */ - #define CALL_MMAP(s) MMAP_DEFAULT(s) - #endif /* MMAP */ - #ifdef MUNMAP - #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) - #else /* MUNMAP */ - #define CALL_MUNMAP(a, s) MUNMAP_DEFAULT((a), (s)) - #endif /* MUNMAP */ - #ifdef DIRECT_MMAP - #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) - #else /* DIRECT_MMAP */ - #define CALL_DIRECT_MMAP(s) DIRECT_MMAP_DEFAULT(s) - #endif /* DIRECT_MMAP */ -#else /* HAVE_MMAP */ - #define USE_MMAP_BIT (SIZE_T_ZERO) - - #define MMAP(s) MFAIL - #define MUNMAP(a, s) (-1) - #define DIRECT_MMAP(s) MFAIL - #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) - #define CALL_MMAP(s) MMAP(s) - #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) -#endif /* HAVE_MMAP */ - -/** - * Define CALL_MREMAP - */ -#if HAVE_MMAP && HAVE_MREMAP - #ifdef MREMAP - #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP((addr), (osz), (nsz), (mv)) - #else /* MREMAP */ - #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP_DEFAULT((addr), (osz), (nsz), (mv)) - #endif /* MREMAP */ -#else /* HAVE_MMAP && HAVE_MREMAP */ - #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL -#endif /* HAVE_MMAP && HAVE_MREMAP */ - -/* mstate bit set if continguous morecore disabled or failed */ -#define USE_NONCONTIGUOUS_BIT (4U) - -/* segment bit set in create_mspace_with_base */ -#define EXTERN_BIT (8U) - - -/* --------------------------- Lock preliminaries ------------------------ */ - -/* - When locks are defined, there is one global lock, plus - one per-mspace lock. - - The global lock_ensures that mparams.magic and other unique - mparams values are initialized only once. It also protects - sequences of calls to MORECORE. In many cases sys_alloc requires - two calls, that should not be interleaved with calls by other - threads. This does not protect against direct calls to MORECORE - by other threads not using this lock, so there is still code to - cope the best we can on interference. - - Per-mspace locks surround calls to malloc, free, etc. To enable use - in layered extensions, per-mspace locks are reentrant. - - Because lock-protected regions generally have bounded times, it is - OK to use the supplied simple spinlocks in the custom versions for - x86. Spinlocks are likely to improve performance for lightly - contended applications, but worsen performance under heavy - contention. - - If USE_LOCKS is > 1, the definitions of lock routines here are - bypassed, in which case you will need to define the type MLOCK_T, - and at least INITIAL_LOCK, ACQUIRE_LOCK, RELEASE_LOCK and possibly - TRY_LOCK (which is not used in this malloc, but commonly needed in - extensions.) You must also declare a - static MLOCK_T malloc_global_mutex = { initialization values };. - -*/ - -#if USE_LOCKS == 1 - -#if USE_SPIN_LOCKS && SPIN_LOCKS_AVAILABLE -#ifndef WIN32 - -/* Custom pthread-style spin locks on x86 and x64 for gcc */ -struct pthread_mlock_t { - volatile unsigned int l; - char cachelinepadding[64]; - unsigned int c; - pthread_t threadid; -}; -#define MLOCK_T struct pthread_mlock_t -#define CURRENT_THREAD pthread_self() -#define INITIAL_LOCK(sl) ((sl)->threadid = 0, (sl)->l = (sl)->c = 0, 0) -#define ACQUIRE_LOCK(sl) pthread_acquire_lock(sl) -#define RELEASE_LOCK(sl) pthread_release_lock(sl) -#define TRY_LOCK(sl) pthread_try_lock(sl) -#define SPINS_PER_YIELD 63 - -static MLOCK_T malloc_global_mutex = { 0, "", 0, 0}; - -static FORCEINLINE int pthread_acquire_lock (MLOCK_T *sl) { - int spins = 0; - volatile unsigned int* lp = &sl->l; - for (;;) { - if (*lp != 0) { - if (sl->threadid == CURRENT_THREAD) { - ++sl->c; - return 0; - } - } - else { - /* place args to cmpxchgl in locals to evade oddities in some gccs */ - int cmp = 0; - int val = 1; - int ret; - __asm__ __volatile__ ("lock; cmpxchgl %1, %2" - : "=a" (ret) - : "r" (val), "m" (*(lp)), "0"(cmp) - : "memory", "cc"); - if (!ret) { - assert(!sl->threadid); - sl->threadid = CURRENT_THREAD; - sl->c = 1; - return 0; - } - } - if ((++spins & SPINS_PER_YIELD) == 0) { -#if defined (__SVR4) && defined (__sun) /* solaris */ - thr_yield(); -#else -#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) - sched_yield(); -#else /* no-op yield on unknown systems */ - ; -#endif /* __linux__ || __FreeBSD__ || __APPLE__ */ -#endif /* solaris */ - } - } -} - -static FORCEINLINE void pthread_release_lock (MLOCK_T *sl) { - volatile unsigned int* lp = &sl->l; - assert(*lp != 0); - assert(sl->threadid == CURRENT_THREAD); - if (--sl->c == 0) { - sl->threadid = 0; - int prev = 0; - int ret; - __asm__ __volatile__ ("lock; xchgl %0, %1" - : "=r" (ret) - : "m" (*(lp)), "0"(prev) - : "memory"); - } -} - -static FORCEINLINE int pthread_try_lock (MLOCK_T *sl) { - volatile unsigned int* lp = &sl->l; - if (*lp != 0) { - if (sl->threadid == CURRENT_THREAD) { - ++sl->c; - return 1; - } - } - else { - int cmp = 0; - int val = 1; - int ret; - __asm__ __volatile__ ("lock; cmpxchgl %1, %2" - : "=a" (ret) - : "r" (val), "m" (*(lp)), "0"(cmp) - : "memory", "cc"); - if (!ret) { - assert(!sl->threadid); - sl->threadid = CURRENT_THREAD; - sl->c = 1; - return 1; - } - } - return 0; -} - - -#else /* WIN32 */ -/* Custom win32-style spin locks on x86 and x64 for MSC */ -struct win32_mlock_t { - volatile long l; - char cachelinepadding[64]; - unsigned int c; - long threadid; -}; - -#define MLOCK_T struct win32_mlock_t -#define CURRENT_THREAD ((long)GetCurrentThreadId()) -#define INITIAL_LOCK(sl) ((sl)->threadid = 0, (sl)->l = (sl)->c = 0, 0) -#define ACQUIRE_LOCK(sl) win32_acquire_lock(sl) -#define RELEASE_LOCK(sl) win32_release_lock(sl) -#define TRY_LOCK(sl) win32_try_lock(sl) -#define SPINS_PER_YIELD 63 - -static MLOCK_T malloc_global_mutex = { 0, 0, 0}; - -static FORCEINLINE int win32_acquire_lock (MLOCK_T *sl) { - int spins = 0; - for (;;) { - if (sl->l != 0) { - if (sl->threadid == CURRENT_THREAD) { - ++sl->c; - return 0; - } - } - else { - if (!interlockedexchange(&sl->l, 1)) { - assert(!sl->threadid); - sl->threadid = CURRENT_THREAD; - sl->c = 1; - return 0; - } - } - if ((++spins & SPINS_PER_YIELD) == 0) - SleepEx(0, FALSE); - } -} - -static FORCEINLINE void win32_release_lock (MLOCK_T *sl) { - assert(sl->threadid == CURRENT_THREAD); - assert(sl->l != 0); - if (--sl->c == 0) { - sl->threadid = 0; - interlockedexchange (&sl->l, 0); - } -} - -static FORCEINLINE int win32_try_lock (MLOCK_T *sl) { - if (sl->l != 0) { - if (sl->threadid == CURRENT_THREAD) { - ++sl->c; - return 1; - } - } - else { - if (!interlockedexchange(&sl->l, 1)){ - assert(!sl->threadid); - sl->threadid = CURRENT_THREAD; - sl->c = 1; - return 1; - } - } - return 0; -} - -#endif /* WIN32 */ -#else /* USE_SPIN_LOCKS */ - -#ifndef WIN32 -/* pthreads-based locks */ - -#define MLOCK_T pthread_mutex_t -#define CURRENT_THREAD pthread_self() -#define INITIAL_LOCK(sl) pthread_init_lock(sl) -#define ACQUIRE_LOCK(sl) pthread_mutex_lock(sl) -#define RELEASE_LOCK(sl) pthread_mutex_unlock(sl) -#define TRY_LOCK(sl) (!pthread_mutex_trylock(sl)) - -static MLOCK_T malloc_global_mutex = PTHREAD_MUTEX_INITIALIZER; - -/* Cope with old-style linux recursive lock initialization by adding */ -/* skipped internal declaration from pthread.h */ -#ifdef linux -#ifndef PTHREAD_MUTEX_RECURSIVE -extern int pthread_mutexattr_setkind_np __P ((pthread_mutexattr_t *__attr, - int __kind)); -#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP -#define pthread_mutexattr_settype(x,y) pthread_mutexattr_setkind_np(x,y) -#endif -#endif - -static int pthread_init_lock (MLOCK_T *sl) { - pthread_mutexattr_t attr; - if (pthread_mutexattr_init(&attr)) return 1; - if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) return 1; - if (pthread_mutex_init(sl, &attr)) return 1; - if (pthread_mutexattr_destroy(&attr)) return 1; - return 0; -} - -#else /* WIN32 */ -/* Win32 critical sections */ -#define MLOCK_T CRITICAL_SECTION -#define CURRENT_THREAD GetCurrentThreadId() -#define INITIAL_LOCK(s) (!InitializeCriticalSectionAndSpinCount((s), 0x80000000|4000)) -#define ACQUIRE_LOCK(s) (EnterCriticalSection(sl), 0) -#define RELEASE_LOCK(s) LeaveCriticalSection(sl) -#define TRY_LOCK(s) TryEnterCriticalSection(sl) -#define NEED_GLOBAL_LOCK_INIT - -static MLOCK_T malloc_global_mutex; -static volatile long malloc_global_mutex_status; - -/* Use spin loop to initialize global lock */ -static void init_malloc_global_mutex() { - for (;;) { - long stat = malloc_global_mutex_status; - if (stat > 0) - return; - /* transition to < 0 while initializing, then to > 0) */ - if (stat == 0 && - interlockedcompareexchange(&malloc_global_mutex_status, -1, 0) == 0) { - InitializeCriticalSection(&malloc_global_mutex); - interlockedexchange(&malloc_global_mutex_status,1); - return; - } - SleepEx(0, FALSE); - } -} - -#endif /* WIN32 */ -#endif /* USE_SPIN_LOCKS */ -#endif /* USE_LOCKS == 1 */ - -/* ----------------------- User-defined locks ------------------------ */ - -#if USE_LOCKS > 1 -/* Define your own lock implementation here */ -/* #define INITIAL_LOCK(sl) ... */ -/* #define ACQUIRE_LOCK(sl) ... */ -/* #define RELEASE_LOCK(sl) ... */ -/* #define TRY_LOCK(sl) ... */ -/* static MLOCK_T malloc_global_mutex = ... */ -#endif /* USE_LOCKS > 1 */ - -/* ----------------------- Lock-based state ------------------------ */ - -#if USE_LOCKS -#define USE_LOCK_BIT (2U) -#else /* USE_LOCKS */ -#define USE_LOCK_BIT (0U) -#define INITIAL_LOCK(l) -#endif /* USE_LOCKS */ - -#if USE_LOCKS -#ifndef ACQUIRE_MALLOC_GLOBAL_LOCK -#define ACQUIRE_MALLOC_GLOBAL_LOCK() ACQUIRE_LOCK(&malloc_global_mutex); -#endif -#ifndef RELEASE_MALLOC_GLOBAL_LOCK -#define RELEASE_MALLOC_GLOBAL_LOCK() RELEASE_LOCK(&malloc_global_mutex); -#endif -#else /* USE_LOCKS */ -#define ACQUIRE_MALLOC_GLOBAL_LOCK() -#define RELEASE_MALLOC_GLOBAL_LOCK() -#endif /* USE_LOCKS */ - - -/* ----------------------- Chunk representations ------------------------ */ - -/* - (The following includes lightly edited explanations by Colin Plumb.) - - The malloc_chunk declaration below is misleading (but accurate and - necessary). It declares a "view" into memory allowing access to - necessary fields at known offsets from a given base. - - Chunks of memory are maintained using a `boundary tag' method as - originally described by Knuth. (See the paper by Paul Wilson - ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such - techniques.) Sizes of free chunks are stored both in the front of - each chunk and at the end. This makes consolidating fragmented - chunks into bigger chunks fast. The head fields also hold bits - representing whether chunks are free or in use. - - Here are some pictures to make it clearer. They are "exploded" to - show that the state of a chunk can be thought of as extending from - the high 31 bits of the head field of its header through the - prev_foot and PINUSE_BIT bit of the following chunk header. - - A chunk that's in use looks like: - - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk (if P = 0) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| - | Size of this chunk 1| +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - +- -+ - | | - +- -+ - | : - +- size - sizeof(size_t) available payload bytes -+ - : | - chunk-> +- -+ - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1| - | Size of next chunk (may or may not be in use) | +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - And if it's free, it looks like this: - - chunk-> +- -+ - | User payload (must be in use, or we would have merged!) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| - | Size of this chunk 0| +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Next pointer | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Prev pointer | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | : - +- size - sizeof(struct chunk) unused bytes -+ - : | - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of this chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0| - | Size of next chunk (must be in use, or we would have merged)| +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | : - +- User payload -+ - : | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |0| - +-+ - Note that since we always merge adjacent free chunks, the chunks - adjacent to a free chunk must be in use. - - Given a pointer to a chunk (which can be derived trivially from the - payload pointer) we can, in O(1) time, find out whether the adjacent - chunks are free, and if so, unlink them from the lists that they - are on and merge them with the current chunk. - - Chunks always begin on even word boundaries, so the mem portion - (which is returned to the user) is also on an even word boundary, and - thus at least double-word aligned. - - The P (PINUSE_BIT) bit, stored in the unused low-order bit of the - chunk size (which is always a multiple of two words), is an in-use - bit for the *previous* chunk. If that bit is *clear*, then the - word before the current chunk size contains the previous chunk - size, and can be used to find the front of the previous chunk. - The very first chunk allocated always has this bit set, preventing - access to non-existent (or non-owned) memory. If pinuse is set for - any given chunk, then you CANNOT determine the size of the - previous chunk, and might even get a memory addressing fault when - trying to do so. - - The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of - the chunk size redundantly records whether the current chunk is - inuse (unless the chunk is mmapped). This redundancy enables usage - checks within free and realloc, and reduces indirection when freeing - and consolidating chunks. - - Each freshly allocated chunk must have both cinuse and pinuse set. - That is, each allocated chunk borders either a previously allocated - and still in-use chunk, or the base of its memory arena. This is - ensured by making all allocations from the the `lowest' part of any - found chunk. Further, no free chunk physically borders another one, - so each free chunk is known to be preceded and followed by either - inuse chunks or the ends of memory. - - Note that the `foot' of the current chunk is actually represented - as the prev_foot of the NEXT chunk. This makes it easier to - deal with alignments etc but can be very confusing when trying - to extend or adapt this code. - - The exceptions to all this are - - 1. The special chunk `top' is the top-most available chunk (i.e., - the one bordering the end of available memory). It is treated - specially. Top is never included in any bin, is used only if - no other chunk is available, and is released back to the - system if it is very large (see M_TRIM_THRESHOLD). In effect, - the top chunk is treated as larger (and thus less well - fitting) than any other available chunk. The top chunk - doesn't update its trailing size field since there is no next - contiguous chunk that would have to index off it. However, - space is still allocated for it (TOP_FOOT_SIZE) to enable - separation or merging when space is extended. - - 3. Chunks allocated via mmap, have both cinuse and pinuse bits - cleared in their head fields. Because they are allocated - one-by-one, each must carry its own prev_foot field, which is - also used to hold the offset this chunk has within its mmapped - region, which is needed to preserve alignment. Each mmapped - chunk is trailed by the first two fields of a fake next-chunk - for sake of usage checks. - -*/ - -struct malloc_chunk { - size_t prev_foot; /* Size of previous chunk (if free). */ - size_t head; /* Size and inuse bits. */ - struct malloc_chunk* fd; /* double links -- used only if free. */ - struct malloc_chunk* bk; -}; - -typedef struct malloc_chunk mchunk; -typedef struct malloc_chunk* mchunkptr; -typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */ -typedef unsigned int bindex_t; /* Described below */ -typedef unsigned int binmap_t; /* Described below */ - -/* ------------------- Chunks sizes and alignments ----------------------- */ - -#define MCHUNK_SIZE (sizeof(mchunk)) - -#if FOOTERS -#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) -#else /* FOOTERS */ -#define CHUNK_OVERHEAD (SIZE_T_SIZE) -#endif /* FOOTERS */ - -/* MMapped chunks need a second word of overhead ... */ -#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) -/* ... and additional padding for fake next-chunk at foot */ -#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES) - -/* The smallest size we can malloc is an aligned minimal chunk */ -#define MIN_CHUNK_SIZE\ - ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) - -/* conversion from malloc headers to user pointers, and back */ -#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES)) -#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES)) -/* chunk associated with aligned address A */ -#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) - -/* Bounds on request (not chunk) sizes. */ -#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2) -#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE) - -/* pad request bytes into a usable size */ -#define pad_request(req) \ - (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) - -/* pad request, checking for minimum (but not maximum) */ -#define request2size(req) \ - (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req)) - - -/* ------------------ Operations on head and foot fields ----------------- */ - -/* - The head field of a chunk is or'ed with PINUSE_BIT when previous - adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in - use, unless mmapped, in which case both bits are cleared. - - FLAG4_BIT is not used by this malloc, but might be useful in extensions. -*/ - -#define PINUSE_BIT (SIZE_T_ONE) -#define CINUSE_BIT (SIZE_T_TWO) -#define FLAG4_BIT (SIZE_T_FOUR) -#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT) -#define FLAG_BITS (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT) - -/* Head value for fenceposts */ -#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE) - -/* extraction of fields from head words */ -#define cinuse(p) ((p)->head & CINUSE_BIT) -#define pinuse(p) ((p)->head & PINUSE_BIT) -#define is_inuse(p) (((p)->head & INUSE_BITS) != PINUSE_BIT) -#define is_mmapped(p) (((p)->head & INUSE_BITS) == 0) - -#define chunksize(p) ((p)->head & ~(FLAG_BITS)) - -#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT) - -/* Treat space at ptr +/- offset as a chunk */ -#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) -#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s))) - -/* Ptr to next or previous physical malloc_chunk. */ -#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS))) -#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) )) - -/* extract next chunk's pinuse bit */ -#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT) - -/* Get/set size at footer */ -#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot) -#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s)) - -/* Set size, pinuse bit, and foot */ -#define set_size_and_pinuse_of_free_chunk(p, s)\ - ((p)->head = (s|PINUSE_BIT), set_foot(p, s)) - -/* Set size, pinuse bit, foot, and clear next pinuse */ -#define set_free_with_pinuse(p, s, n)\ - (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s)) - -/* Get the internal overhead associated with chunk p */ -#define overhead_for(p)\ - (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD) - -/* Return true if malloced space is not necessarily cleared */ -#if MMAP_CLEARS -#define calloc_must_clear(p) (!is_mmapped(p)) -#else /* MMAP_CLEARS */ -#define calloc_must_clear(p) (1) -#endif /* MMAP_CLEARS */ - -/* ---------------------- Overlaid data structures ----------------------- */ - -/* - When chunks are not in use, they are treated as nodes of either - lists or trees. - - "Small" chunks are stored in circular doubly-linked lists, and look - like this: - - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `head:' | Size of chunk, in bytes |P| - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Forward pointer to next chunk in list | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Back pointer to previous chunk in list | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Unused space (may be 0 bytes long) . - . . - . | -nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `foot:' | Size of chunk, in bytes | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Larger chunks are kept in a form of bitwise digital trees (aka - tries) keyed on chunksizes. Because malloc_tree_chunks are only for - free chunks greater than 256 bytes, their size doesn't impose any - constraints on user chunk sizes. Each node looks like: - - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `head:' | Size of chunk, in bytes |P| - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Forward pointer to next chunk of same size | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Back pointer to previous chunk of same size | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Pointer to left child (child[0]) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Pointer to right child (child[1]) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Pointer to parent | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | bin index of this chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Unused space . - . | -nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `foot:' | Size of chunk, in bytes | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Each tree holding treenodes is a tree of unique chunk sizes. Chunks - of the same size are arranged in a circularly-linked list, with only - the oldest chunk (the next to be used, in our FIFO ordering) - actually in the tree. (Tree members are distinguished by a non-null - parent pointer.) If a chunk with the same size an an existing node - is inserted, it is linked off the existing node using pointers that - work in the same way as fd/bk pointers of small chunks. - - Each tree contains a power of 2 sized range of chunk sizes (the - smallest is 0x100 <= x < 0x180), which is is divided in half at each - tree level, with the chunks in the smaller half of the range (0x100 - <= x < 0x140 for the top nose) in the left subtree and the larger - half (0x140 <= x < 0x180) in the right subtree. This is, of course, - done by inspecting individual bits. - - Using these rules, each node's left subtree contains all smaller - sizes than its right subtree. However, the node at the root of each - subtree has no particular ordering relationship to either. (The - dividing line between the subtree sizes is based on trie relation.) - If we remove the last chunk of a given size from the interior of the - tree, we need to replace it with a leaf node. The tree ordering - rules permit a node to be replaced by any leaf below it. - - The smallest chunk in a tree (a common operation in a best-fit - allocator) can be found by walking a path to the leftmost leaf in - the tree. Unlike a usual binary tree, where we follow left child - pointers until we reach a null, here we follow the right child - pointer any time the left one is null, until we reach a leaf with - both child pointers null. The smallest chunk in the tree will be - somewhere along that path. - - The worst case number of steps to add, find, or remove a node is - bounded by the number of bits differentiating chunks within - bins. Under current bin calculations, this ranges from 6 up to 21 - (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case - is of course much better. -*/ - -struct malloc_tree_chunk { - /* The first four fields must be compatible with malloc_chunk */ - size_t prev_foot; - size_t head; - struct malloc_tree_chunk* fd; - struct malloc_tree_chunk* bk; - - struct malloc_tree_chunk* child[2]; - struct malloc_tree_chunk* parent; - bindex_t index; -}; - -typedef struct malloc_tree_chunk tchunk; -typedef struct malloc_tree_chunk* tchunkptr; -typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */ - -/* A little helper macro for trees */ -#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1]) - -/* ----------------------------- Segments -------------------------------- */ - -/* - Each malloc space may include non-contiguous segments, held in a - list headed by an embedded malloc_segment record representing the - top-most space. Segments also include flags holding properties of - the space. Large chunks that are directly allocated by mmap are not - included in this list. They are instead independently created and - destroyed without otherwise keeping track of them. - - Segment management mainly comes into play for spaces allocated by - MMAP. Any call to MMAP might or might not return memory that is - adjacent to an existing segment. MORECORE normally contiguously - extends the current space, so this space is almost always adjacent, - which is simpler and faster to deal with. (This is why MORECORE is - used preferentially to MMAP when both are available -- see - sys_alloc.) When allocating using MMAP, we don't use any of the - hinting mechanisms (inconsistently) supported in various - implementations of unix mmap, or distinguish reserving from - committing memory. Instead, we just ask for space, and exploit - contiguity when we get it. It is probably possible to do - better than this on some systems, but no general scheme seems - to be significantly better. - - Management entails a simpler variant of the consolidation scheme - used for chunks to reduce fragmentation -- new adjacent memory is - normally prepended or appended to an existing segment. However, - there are limitations compared to chunk consolidation that mostly - reflect the fact that segment processing is relatively infrequent - (occurring only when getting memory from system) and that we - don't expect to have huge numbers of segments: - - * Segments are not indexed, so traversal requires linear scans. (It - would be possible to index these, but is not worth the extra - overhead and complexity for most programs on most platforms.) - * New segments are only appended to old ones when holding top-most - memory; if they cannot be prepended to others, they are held in - different segments. - - Except for the top-most segment of an mstate, each segment record - is kept at the tail of its segment. Segments are added by pushing - segment records onto the list headed by &mstate.seg for the - containing mstate. - - Segment flags control allocation/merge/deallocation policies: - * If EXTERN_BIT set, then we did not allocate this segment, - and so should not try to deallocate or merge with others. - (This currently holds only for the initial segment passed - into create_mspace_with_base.) - * If USE_MMAP_BIT set, the segment may be merged with - other surrounding mmapped segments and trimmed/de-allocated - using munmap. - * If neither bit is set, then the segment was obtained using - MORECORE so can be merged with surrounding MORECORE'd segments - and deallocated/trimmed using MORECORE with negative arguments. -*/ - -struct malloc_segment { - char* base; /* base address */ - size_t size; /* allocated size */ - struct malloc_segment* next; /* ptr to next segment */ - flag_t sflags; /* mmap and extern flag */ -}; - -#define is_mmapped_segment(S) ((S)->sflags & USE_MMAP_BIT) -#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT) - -typedef struct malloc_segment msegment; -typedef struct malloc_segment* msegmentptr; - -/* ---------------------------- malloc_state ----------------------------- */ - -/* - A malloc_state holds all of the bookkeeping for a space. - The main fields are: - - Top - The topmost chunk of the currently active segment. Its size is - cached in topsize. The actual size of topmost space is - topsize+TOP_FOOT_SIZE, which includes space reserved for adding - fenceposts and segment records if necessary when getting more - space from the system. The size at which to autotrim top is - cached from mparams in trim_check, except that it is disabled if - an autotrim fails. - - Designated victim (dv) - This is the preferred chunk for servicing small requests that - don't have exact fits. It is normally the chunk split off most - recently to service another small request. Its size is cached in - dvsize. The link fields of this chunk are not maintained since it - is not kept in a bin. - - SmallBins - An array of bin headers for free chunks. These bins hold chunks - with sizes less than MIN_LARGE_SIZE bytes. Each bin contains - chunks of all the same size, spaced 8 bytes apart. To simplify - use in double-linked lists, each bin header acts as a malloc_chunk - pointing to the real first node, if it exists (else pointing to - itself). This avoids special-casing for headers. But to avoid - waste, we allocate only the fd/bk pointers of bins, and then use - repositioning tricks to treat these as the fields of a chunk. - - TreeBins - Treebins are pointers to the roots of trees holding a range of - sizes. There are 2 equally spaced treebins for each power of two - from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything - larger. - - Bin maps - There is one bit map for small bins ("smallmap") and one for - treebins ("treemap). Each bin sets its bit when non-empty, and - clears the bit when empty. Bit operations are then used to avoid - bin-by-bin searching -- nearly all "search" is done without ever - looking at bins that won't be selected. The bit maps - conservatively use 32 bits per map word, even if on 64bit system. - For a good description of some of the bit-based techniques used - here, see Henry S. Warren Jr's book "Hacker's Delight" (and - supplement at http://hackersdelight.org/). Many of these are - intended to reduce the branchiness of paths through malloc etc, as - well as to reduce the number of memory locations read or written. - - Segments - A list of segments headed by an embedded malloc_segment record - representing the initial space. - - Address check support - The least_addr field is the least address ever obtained from - MORECORE or MMAP. Attempted frees and reallocs of any address less - than this are trapped (unless INSECURE is defined). - - Magic tag - A cross-check field that should always hold same value as mparams.magic. - - Flags - Bits recording whether to use MMAP, locks, or contiguous MORECORE - - Statistics - Each space keeps track of current and maximum system memory - obtained via MORECORE or MMAP. - - Trim support - Fields holding the amount of unused topmost memory that should trigger - timming, and a counter to force periodic scanning to release unused - non-topmost segments. - - Locking - If USE_LOCKS is defined, the "mutex" lock is acquired and released - around every public call using this mspace. - - Extension support - A void* pointer and a size_t field that can be used to help implement - extensions to this malloc. -*/ - -/* Bin types, widths and sizes */ -#define NSMALLBINS (32U) -#define NTREEBINS (32U) -#define SMALLBIN_SHIFT (3U) -#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT) -#define TREEBIN_SHIFT (8U) -#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT) -#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE) -#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD) - -struct malloc_state { - binmap_t smallmap; - binmap_t treemap; - size_t dvsize; - size_t topsize; - char* least_addr; - mchunkptr dv; - mchunkptr top; - size_t trim_check; - size_t release_checks; - size_t magic; - mchunkptr smallbins[(NSMALLBINS+1)*2]; - tbinptr treebins[NTREEBINS]; - size_t footprint; - size_t max_footprint; - flag_t mflags; - msegment seg; -#if USE_LOCKS - MLOCK_T mutex; /* locate lock among fields that rarely change */ -#endif /* USE_LOCKS */ - void* extp; /* Unused but available for extensions */ - size_t exts; -}; - -typedef struct malloc_state* mstate; - -/* ------------- Global malloc_state and malloc_params ------------------- */ - -#if !ONLY_MSPACES - -/* The global malloc_state used for all non-"mspace" calls */ -static struct malloc_state _gm_; -#define gm (&_gm_) -#define is_global(M) ((M) == &_gm_) - -#endif /* !ONLY_MSPACES */ - -#define is_initialized(M) ((M)->top != 0) - -/* -------------------------- system alloc setup ------------------------- */ - -/* Operations on mflags */ - -#define use_lock(M) ((M)->mflags & USE_LOCK_BIT) -#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT) -#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT) - -#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT) -#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT) -#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT) - -#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT) -#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT) - -#define set_lock(M,L)\ - ((M)->mflags = (L)?\ - ((M)->mflags | USE_LOCK_BIT) :\ - ((M)->mflags & ~USE_LOCK_BIT)) - -/* page-align a size */ -#define page_align(S)\ - (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE)) - -/* granularity-align a size */ -#define granularity_align(S)\ - (((S) + (mparams.granularity - SIZE_T_ONE))\ - & ~(mparams.granularity - SIZE_T_ONE)) - - -/* For mmap, use granularity alignment on windows, else page-align */ -#ifdef WIN32 -#define mmap_align(S) granularity_align(S) -#else -#define mmap_align(S) page_align(S) -#endif - -/* For sys_alloc, enough padding to ensure can malloc request on success */ -#define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT) - -#define is_page_aligned(S)\ - (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0) -#define is_granularity_aligned(S)\ - (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0) - -/* True if segment S holds address A */ -#define segment_holds(S, A)\ - ((char*)(A) >= S->base && (char*)(A) < S->base + S->size) - -/* Return segment holding given address */ -static msegmentptr segment_holding(mstate m, char* addr) { - msegmentptr sp = &m->seg; - for (;;) { - if (addr >= sp->base && addr < sp->base + sp->size) - return sp; - if ((sp = sp->next) == 0) - return 0; - } -} - -/* Return true if segment contains a segment link */ -static int has_segment_link(mstate m, msegmentptr ss) { - msegmentptr sp = &m->seg; - for (;;) { - if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size) - return 1; - if ((sp = sp->next) == 0) - return 0; - } -} - -#ifndef MORECORE_CANNOT_TRIM -#define should_trim(M,s) ((s) > (M)->trim_check) -#else /* MORECORE_CANNOT_TRIM */ -#define should_trim(M,s) (0) -#endif /* MORECORE_CANNOT_TRIM */ - -/* - TOP_FOOT_SIZE is padding at the end of a segment, including space - that may be needed to place segment records and fenceposts when new - noncontiguous segments are added. -*/ -#define TOP_FOOT_SIZE\ - (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE) - - -/* ------------------------------- Hooks -------------------------------- */ - -/* - PREACTION should be defined to return 0 on success, and nonzero on - failure. If you are not using locking, you can redefine these to do - anything you like. -*/ - -#if USE_LOCKS - -#define PREACTION(M) ((use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0) -#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); } -#else /* USE_LOCKS */ - -#ifndef PREACTION -#define PREACTION(M) (0) -#endif /* PREACTION */ - -#ifndef POSTACTION -#define POSTACTION(M) -#endif /* POSTACTION */ - -#endif /* USE_LOCKS */ - -/* - CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses. - USAGE_ERROR_ACTION is triggered on detected bad frees and - reallocs. The argument p is an address that might have triggered the - fault. It is ignored by the two predefined actions, but might be - useful in custom actions that try to help diagnose errors. -*/ - -#if PROCEED_ON_ERROR - -/* A count of the number of corruption errors causing resets */ -int malloc_corruption_error_count; - -/* default corruption action */ -static void reset_on_error(mstate m); - -#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m) -#define USAGE_ERROR_ACTION(m, p) - -#else /* PROCEED_ON_ERROR */ - -#ifndef CORRUPTION_ERROR_ACTION -#define CORRUPTION_ERROR_ACTION(m) ABORT -#endif /* CORRUPTION_ERROR_ACTION */ - -#ifndef USAGE_ERROR_ACTION -#define USAGE_ERROR_ACTION(m,p) ABORT -#endif /* USAGE_ERROR_ACTION */ - -#endif /* PROCEED_ON_ERROR */ - -/* -------------------------- Debugging setup ---------------------------- */ - -#if ! DEBUG - -#define check_free_chunk(M,P) -#define check_inuse_chunk(M,P) -#define check_malloced_chunk(M,P,N) -#define check_mmapped_chunk(M,P) -#define check_malloc_state(M) -#define check_top_chunk(M,P) - -#else /* DEBUG */ -#define check_free_chunk(M,P) do_check_free_chunk(M,P) -#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P) -#define check_top_chunk(M,P) do_check_top_chunk(M,P) -#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N) -#define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P) -#define check_malloc_state(M) do_check_malloc_state(M) - -static void do_check_any_chunk(mstate m, mchunkptr p); -static void do_check_top_chunk(mstate m, mchunkptr p); -static void do_check_mmapped_chunk(mstate m, mchunkptr p); -static void do_check_inuse_chunk(mstate m, mchunkptr p); -static void do_check_free_chunk(mstate m, mchunkptr p); -static void do_check_malloced_chunk(mstate m, void* mem, size_t s); -static void do_check_tree(mstate m, tchunkptr t); -static void do_check_treebin(mstate m, bindex_t i); -static void do_check_smallbin(mstate m, bindex_t i); -static void do_check_malloc_state(mstate m); -static int bin_find(mstate m, mchunkptr x); -static size_t traverse_and_check(mstate m); -#endif /* DEBUG */ - -/* ---------------------------- Indexing Bins ---------------------------- */ - -#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS) -#define small_index(s) (bindex_t)((s) >> SMALLBIN_SHIFT) -#define small_index2size(i) ((i) << SMALLBIN_SHIFT) -#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE)) - -/* addressing by index. See above about smallbin repositioning */ -#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1]))) -#define treebin_at(M,i) (&((M)->treebins[i])) - -/* assign tree index for size S to variable I. Use x86 asm if possible */ -#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) -#define compute_tree_index(S, I)\ -{\ - unsigned int X = S >> TREEBIN_SHIFT;\ - if (X == 0)\ - I = 0;\ - else if (X > 0xFFFF)\ - I = NTREEBINS-1;\ - else {\ - unsigned int K;\ - __asm__("bsrl\t%1, %0\n\t" : "=r" (K) : "g" (X));\ - I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ - }\ -} - -#elif defined (__INTEL_COMPILER) -#define compute_tree_index(S, I)\ -{\ - size_t X = S >> TREEBIN_SHIFT;\ - if (X == 0)\ - I = 0;\ - else if (X > 0xFFFF)\ - I = NTREEBINS-1;\ - else {\ - unsigned int K = _bit_scan_reverse (X); \ - I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ - }\ -} - -#elif defined(_MSC_VER) && _MSC_VER>=1300 -#define compute_tree_index(S, I)\ -{\ - size_t X = S >> TREEBIN_SHIFT;\ - if (X == 0)\ - I = 0;\ - else if (X > 0xFFFF)\ - I = NTREEBINS-1;\ - else {\ - unsigned int K;\ - _BitScanReverse((DWORD *) &K, (DWORD) X);\ - I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ - }\ -} - -#else /* GNUC */ -#define compute_tree_index(S, I)\ -{\ - size_t X = S >> TREEBIN_SHIFT;\ - if (X == 0)\ - I = 0;\ - else if (X > 0xFFFF)\ - I = NTREEBINS-1;\ - else {\ - unsigned int Y = (unsigned int)X;\ - unsigned int N = ((Y - 0x100) >> 16) & 8;\ - unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\ - N += K;\ - N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\ - K = 14 - N + ((Y <<= K) >> 15);\ - I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\ - }\ -} -#endif /* GNUC */ - -/* Bit representing maximum resolved size in a treebin at i */ -#define bit_for_tree_index(i) \ - (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2) - -/* Shift placing maximum resolved bit in a treebin at i as sign bit */ -#define leftshift_for_tree_index(i) \ - ((i == NTREEBINS-1)? 0 : \ - ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2))) - -/* The size of the smallest chunk held in bin with index i */ -#define minsize_for_tree_index(i) \ - ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \ - (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) - - -/* ------------------------ Operations on bin maps ----------------------- */ - -/* bit corresponding to given index */ -#define idx2bit(i) ((binmap_t)(1) << (i)) - -/* Mark/Clear bits with given index */ -#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i)) -#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i)) -#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i)) - -#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i)) -#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i)) -#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i)) - -/* isolate the least set bit of a bitmap */ -#define least_bit(x) ((x) & -(x)) - -/* mask with all bits to left of least bit of x on */ -#define left_bits(x) ((x<<1) | -(x<<1)) - -/* mask with all bits to left of or equal to least bit of x on */ -#define same_or_left_bits(x) ((x) | -(x)) - -/* index corresponding to given bit. Use x86 asm if possible */ - -#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) -#define compute_bit2idx(X, I)\ -{\ - unsigned int J;\ - __asm__("bsfl\t%1, %0\n\t" : "=r" (J) : "g" (X));\ - I = (bindex_t)J;\ -} - -#elif defined (__INTEL_COMPILER) -#define compute_bit2idx(X, I)\ -{\ - unsigned int J;\ - J = _bit_scan_forward (X); \ - I = (bindex_t)J;\ -} - -#elif defined(_MSC_VER) && _MSC_VER>=1300 -#define compute_bit2idx(X, I)\ -{\ - unsigned int J;\ - _BitScanForward((DWORD *) &J, X);\ - I = (bindex_t)J;\ -} - -#elif USE_BUILTIN_FFS -#define compute_bit2idx(X, I) I = ffs(X)-1 - -#else -#define compute_bit2idx(X, I)\ -{\ - unsigned int Y = X - 1;\ - unsigned int K = Y >> (16-4) & 16;\ - unsigned int N = K; Y >>= K;\ - N += K = Y >> (8-3) & 8; Y >>= K;\ - N += K = Y >> (4-2) & 4; Y >>= K;\ - N += K = Y >> (2-1) & 2; Y >>= K;\ - N += K = Y >> (1-0) & 1; Y >>= K;\ - I = (bindex_t)(N + Y);\ -} -#endif /* GNUC */ - - -/* ----------------------- Runtime Check Support ------------------------- */ - -/* - For security, the main invariant is that malloc/free/etc never - writes to a static address other than malloc_state, unless static - malloc_state itself has been corrupted, which cannot occur via - malloc (because of these checks). In essence this means that we - believe all pointers, sizes, maps etc held in malloc_state, but - check all of those linked or offsetted from other embedded data - structures. These checks are interspersed with main code in a way - that tends to minimize their run-time cost. - - When FOOTERS is defined, in addition to range checking, we also - verify footer fields of inuse chunks, which can be used guarantee - that the mstate controlling malloc/free is intact. This is a - streamlined version of the approach described by William Robertson - et al in "Run-time Detection of Heap-based Overflows" LISA'03 - http://www.usenix.org/events/lisa03/tech/robertson.html The footer - of an inuse chunk holds the xor of its mstate and a random seed, - that is checked upon calls to free() and realloc(). This is - (probablistically) unguessable from outside the program, but can be - computed by any code successfully malloc'ing any chunk, so does not - itself provide protection against code that has already broken - security through some other means. Unlike Robertson et al, we - always dynamically check addresses of all offset chunks (previous, - next, etc). This turns out to be cheaper than relying on hashes. -*/ - -#if !INSECURE -/* Check if address a is at least as high as any from MORECORE or MMAP */ -#define ok_address(M, a) ((char*)(a) >= (M)->least_addr) -/* Check if address of next chunk n is higher than base chunk p */ -#define ok_next(p, n) ((char*)(p) < (char*)(n)) -/* Check if p has inuse status */ -#define ok_inuse(p) is_inuse(p) -/* Check if p has its pinuse bit on */ -#define ok_pinuse(p) pinuse(p) - -#else /* !INSECURE */ -#define ok_address(M, a) (1) -#define ok_next(b, n) (1) -#define ok_inuse(p) (1) -#define ok_pinuse(p) (1) -#endif /* !INSECURE */ - -#if (FOOTERS && !INSECURE) -/* Check if (alleged) mstate m has expected magic field */ -#define ok_magic(M) ((M)->magic == mparams.magic) -#else /* (FOOTERS && !INSECURE) */ -#define ok_magic(M) (1) -#endif /* (FOOTERS && !INSECURE) */ - - -/* In gcc, use __builtin_expect to minimize impact of checks */ -#if !INSECURE -#if defined(__GNUC__) && __GNUC__ >= 3 -#define RTCHECK(e) __builtin_expect(e, 1) -#else /* GNUC */ -#define RTCHECK(e) (e) -#endif /* GNUC */ -#else /* !INSECURE */ -#define RTCHECK(e) (1) -#endif /* !INSECURE */ - -/* macros to set up inuse chunks with or without footers */ - -#if !FOOTERS - -#define mark_inuse_foot(M,p,s) - -/* Macros for setting head/foot of non-mmapped chunks */ - -/* Set cinuse bit and pinuse bit of next chunk */ -#define set_inuse(M,p,s)\ - ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ - ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) - -/* Set cinuse and pinuse of this chunk and pinuse of next chunk */ -#define set_inuse_and_pinuse(M,p,s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ - ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) - -/* Set size, cinuse and pinuse bit of this chunk */ -#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT)) - -#else /* FOOTERS */ - -/* Set foot of inuse chunk to be xor of mstate and seed */ -#define mark_inuse_foot(M,p,s)\ - (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic)) - -#define get_mstate_for(p)\ - ((mstate)(((mchunkptr)((char*)(p) +\ - (chunksize(p))))->prev_foot ^ mparams.magic)) - -#define set_inuse(M,p,s)\ - ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ - (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \ - mark_inuse_foot(M,p,s)) - -#define set_inuse_and_pinuse(M,p,s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ - (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\ - mark_inuse_foot(M,p,s)) - -#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ - mark_inuse_foot(M, p, s)) - -#endif /* !FOOTERS */ - -/* ---------------------------- setting mparams -------------------------- */ - -#ifdef ENABLE_LARGE_PAGES -typedef size_t (WINAPI *GetLargePageMinimum_t)(void); -#endif - -/* Initialize mparams */ -static int init_mparams(void) { -#ifdef NEED_GLOBAL_LOCK_INIT - if (malloc_global_mutex_status <= 0) - init_malloc_global_mutex(); -#endif - - ACQUIRE_MALLOC_GLOBAL_LOCK(); - if (mparams.magic == 0) { - size_t magic; - size_t psize; - size_t gsize; - -#ifndef WIN32 - psize = malloc_getpagesize; - gsize = ((DEFAULT_GRANULARITY != 0)? DEFAULT_GRANULARITY : psize); -#else /* WIN32 */ - { - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - psize = system_info.dwPageSize; - gsize = ((DEFAULT_GRANULARITY != 0)? - DEFAULT_GRANULARITY : system_info.dwAllocationGranularity); -#ifdef ENABLE_LARGE_PAGES - { - GetLargePageMinimum_t GetLargePageMinimum_ = (GetLargePageMinimum_t) GetProcAddress(GetModuleHandle(__T("kernel32.dll")), "GetLargePageMinimum"); - if(GetLargePageMinimum_) { - size_t largepagesize = GetLargePageMinimum_(); - if(largepagesize) { - psize = largepagesize; - gsize = ((DEFAULT_GRANULARITY != 0)? - DEFAULT_GRANULARITY : largepagesize); - if(gsize < largepagesize) gsize = largepagesize; - } - } - } -#endif - } -#endif /* WIN32 */ - - /* Sanity-check configuration: - size_t must be unsigned and as wide as pointer type. - ints must be at least 4 bytes. - alignment must be at least 8. - Alignment, min chunk size, and page size must all be powers of 2. - */ - if ((sizeof(size_t) != sizeof(char*)) || - (MAX_SIZE_T < MIN_CHUNK_SIZE) || - (sizeof(int) < 4) || - (MALLOC_ALIGNMENT < (size_t)8U) || - ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) || - ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) || - ((gsize & (gsize-SIZE_T_ONE)) != 0) || - ((psize & (psize-SIZE_T_ONE)) != 0)) - ABORT; - - mparams.granularity = gsize; - mparams.page_size = psize; - mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD; - mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD; -#if MORECORE_CONTIGUOUS - mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT; -#else /* MORECORE_CONTIGUOUS */ - mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT; -#endif /* MORECORE_CONTIGUOUS */ - -#if !ONLY_MSPACES - /* Set up lock for main malloc area */ - gm->mflags = mparams.default_mflags; - INITIAL_LOCK(&gm->mutex); -#endif - - { -#if USE_DEV_RANDOM - int fd; - unsigned char buf[sizeof(size_t)]; - /* Try to use /dev/urandom, else fall back on using time */ - if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 && - read(fd, buf, sizeof(buf)) == sizeof(buf)) { - magic = *((size_t *) buf); - close(fd); - } - else -#endif /* USE_DEV_RANDOM */ -#ifdef WIN32 - magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U); -#else - magic = (size_t)(time(0) ^ (size_t)0x55555555U); -#endif - magic |= (size_t)8U; /* ensure nonzero */ - magic &= ~(size_t)7U; /* improve chances of fault for bad values */ - mparams.magic = magic; - } - } - - RELEASE_MALLOC_GLOBAL_LOCK(); - return 1; -} - -/* support for mallopt */ -static int change_mparam(int param_number, int value) { - size_t val; - ensure_initialization(); - val = (value == -1)? MAX_SIZE_T : (size_t)value; - switch(param_number) { - case M_TRIM_THRESHOLD: - mparams.trim_threshold = val; - return 1; - case M_GRANULARITY: - if (val >= mparams.page_size && ((val & (val-1)) == 0)) { - mparams.granularity = val; - return 1; - } - else - return 0; - case M_MMAP_THRESHOLD: - mparams.mmap_threshold = val; - return 1; - default: - return 0; - } -} - -#if DEBUG -/* ------------------------- Debugging Support --------------------------- */ - -/* Check properties of any chunk, whether free, inuse, mmapped etc */ -static void do_check_any_chunk(mstate m, mchunkptr p) { - assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); - assert(ok_address(m, p)); -} - -/* Check properties of top chunk */ -static void do_check_top_chunk(mstate m, mchunkptr p) { - msegmentptr sp = segment_holding(m, (char*)p); - size_t sz = p->head & ~INUSE_BITS; /* third-lowest bit can be set! */ - assert(sp != 0); - assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); - assert(ok_address(m, p)); - assert(sz == m->topsize); - assert(sz > 0); - assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE); - assert(pinuse(p)); - assert(!pinuse(chunk_plus_offset(p, sz))); -} - -/* Check properties of (inuse) mmapped chunks */ -static void do_check_mmapped_chunk(mstate m, mchunkptr p) { - size_t sz = chunksize(p); - size_t len = (sz + (p->prev_foot) + MMAP_FOOT_PAD); - assert(is_mmapped(p)); - assert(use_mmap(m)); - assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); - assert(ok_address(m, p)); - assert(!is_small(sz)); - assert((len & (mparams.page_size-SIZE_T_ONE)) == 0); - assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD); - assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0); -} - -/* Check properties of inuse chunks */ -static void do_check_inuse_chunk(mstate m, mchunkptr p) { - do_check_any_chunk(m, p); - assert(is_inuse(p)); - assert(next_pinuse(p)); - /* If not pinuse and not mmapped, previous chunk has OK offset */ - assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p); - if (is_mmapped(p)) - do_check_mmapped_chunk(m, p); -} - -/* Check properties of free chunks */ -static void do_check_free_chunk(mstate m, mchunkptr p) { - size_t sz = chunksize(p); - mchunkptr next = chunk_plus_offset(p, sz); - do_check_any_chunk(m, p); - assert(!is_inuse(p)); - assert(!next_pinuse(p)); - assert (!is_mmapped(p)); - if (p != m->dv && p != m->top) { - if (sz >= MIN_CHUNK_SIZE) { - assert((sz & CHUNK_ALIGN_MASK) == 0); - assert(is_aligned(chunk2mem(p))); - assert(next->prev_foot == sz); - assert(pinuse(p)); - assert (next == m->top || is_inuse(next)); - assert(p->fd->bk == p); - assert(p->bk->fd == p); - } - else /* markers are always of size SIZE_T_SIZE */ - assert(sz == SIZE_T_SIZE); - } -} - -/* Check properties of malloced chunks at the point they are malloced */ -static void do_check_malloced_chunk(mstate m, void* mem, size_t s) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); - size_t sz = p->head & ~INUSE_BITS; - do_check_inuse_chunk(m, p); - assert((sz & CHUNK_ALIGN_MASK) == 0); - assert(sz >= MIN_CHUNK_SIZE); - assert(sz >= s); - /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */ - assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE)); - } -} - -/* Check a tree and its subtrees. */ -static void do_check_tree(mstate m, tchunkptr t) { - tchunkptr head = 0; - tchunkptr u = t; - bindex_t tindex = t->index; - size_t tsize = chunksize(t); - bindex_t idx; - compute_tree_index(tsize, idx); - assert(tindex == idx); - assert(tsize >= MIN_LARGE_SIZE); - assert(tsize >= minsize_for_tree_index(idx)); - assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1)))); - - do { /* traverse through chain of same-sized nodes */ - do_check_any_chunk(m, ((mchunkptr)u)); - assert(u->index == tindex); - assert(chunksize(u) == tsize); - assert(!is_inuse(u)); - assert(!next_pinuse(u)); - assert(u->fd->bk == u); - assert(u->bk->fd == u); - if (u->parent == 0) { - assert(u->child[0] == 0); - assert(u->child[1] == 0); - } - else { - assert(head == 0); /* only one node on chain has parent */ - head = u; - assert(u->parent != u); - assert (u->parent->child[0] == u || - u->parent->child[1] == u || - *((tbinptr*)(u->parent)) == u); - if (u->child[0] != 0) { - assert(u->child[0]->parent == u); - assert(u->child[0] != u); - do_check_tree(m, u->child[0]); - } - if (u->child[1] != 0) { - assert(u->child[1]->parent == u); - assert(u->child[1] != u); - do_check_tree(m, u->child[1]); - } - if (u->child[0] != 0 && u->child[1] != 0) { - assert(chunksize(u->child[0]) < chunksize(u->child[1])); - } - } - u = u->fd; - } while (u != t); - assert(head != 0); -} - -/* Check all the chunks in a treebin. */ -static void do_check_treebin(mstate m, bindex_t i) { - tbinptr* tb = treebin_at(m, i); - tchunkptr t = *tb; - int empty = (m->treemap & (1U << i)) == 0; - if (t == 0) - assert(empty); - if (!empty) - do_check_tree(m, t); -} - -/* Check all the chunks in a smallbin. */ -static void do_check_smallbin(mstate m, bindex_t i) { - sbinptr b = smallbin_at(m, i); - mchunkptr p = b->bk; - unsigned int empty = (m->smallmap & (1U << i)) == 0; - if (p == b) - assert(empty); - if (!empty) { - for (; p != b; p = p->bk) { - size_t size = chunksize(p); - mchunkptr q; - /* each chunk claims to be free */ - do_check_free_chunk(m, p); - /* chunk belongs in bin */ - assert(small_index(size) == i); - assert(p->bk == b || chunksize(p->bk) == chunksize(p)); - /* chunk is followed by an inuse chunk */ - q = next_chunk(p); - if (q->head != FENCEPOST_HEAD) - do_check_inuse_chunk(m, q); - } - } -} - -/* Find x in a bin. Used in other check functions. */ -static int bin_find(mstate m, mchunkptr x) { - size_t size = chunksize(x); - if (is_small(size)) { - bindex_t sidx = small_index(size); - sbinptr b = smallbin_at(m, sidx); - if (smallmap_is_marked(m, sidx)) { - mchunkptr p = b; - do { - if (p == x) - return 1; - } while ((p = p->fd) != b); - } - } - else { - bindex_t tidx; - compute_tree_index(size, tidx); - if (treemap_is_marked(m, tidx)) { - tchunkptr t = *treebin_at(m, tidx); - size_t sizebits = size << leftshift_for_tree_index(tidx); - while (t != 0 && chunksize(t) != size) { - t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; - sizebits <<= 1; - } - if (t != 0) { - tchunkptr u = t; - do { - if (u == (tchunkptr)x) - return 1; - } while ((u = u->fd) != t); - } - } - } - return 0; -} - -/* Traverse each chunk and check it; return total */ -static size_t traverse_and_check(mstate m) { - size_t sum = 0; - if (is_initialized(m)) { - msegmentptr s = &m->seg; - sum += m->topsize + TOP_FOOT_SIZE; - while (s != 0) { - mchunkptr q = align_as_chunk(s->base); - mchunkptr lastq = 0; - assert(pinuse(q)); - while (segment_holds(s, q) && - q != m->top && q->head != FENCEPOST_HEAD) { - sum += chunksize(q); - if (is_inuse(q)) { - assert(!bin_find(m, q)); - do_check_inuse_chunk(m, q); - } - else { - assert(q == m->dv || bin_find(m, q)); - assert(lastq == 0 || is_inuse(lastq)); /* Not 2 consecutive free */ - do_check_free_chunk(m, q); - } - lastq = q; - q = next_chunk(q); - } - s = s->next; - } - } - return sum; -} - -/* Check all properties of malloc_state. */ -static void do_check_malloc_state(mstate m) { - bindex_t i; - size_t total; - /* check bins */ - for (i = 0; i < NSMALLBINS; ++i) - do_check_smallbin(m, i); - for (i = 0; i < NTREEBINS; ++i) - do_check_treebin(m, i); - - if (m->dvsize != 0) { /* check dv chunk */ - do_check_any_chunk(m, m->dv); - assert(m->dvsize == chunksize(m->dv)); - assert(m->dvsize >= MIN_CHUNK_SIZE); - assert(bin_find(m, m->dv) == 0); - } - - if (m->top != 0) { /* check top chunk */ - do_check_top_chunk(m, m->top); - /*assert(m->topsize == chunksize(m->top)); redundant */ - assert(m->topsize > 0); - assert(bin_find(m, m->top) == 0); - } - - total = traverse_and_check(m); - assert(total <= m->footprint); - assert(m->footprint <= m->max_footprint); -} -#endif /* DEBUG */ - -/* ----------------------------- statistics ------------------------------ */ - -#if !NO_MALLINFO -static struct mallinfo internal_mallinfo(mstate m) { - struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - ensure_initialization(); - if (!PREACTION(m)) { - check_malloc_state(m); - if (is_initialized(m)) { - size_t nfree = SIZE_T_ONE; /* top always free */ - size_t mfree = m->topsize + TOP_FOOT_SIZE; - size_t sum = mfree; - msegmentptr s = &m->seg; - while (s != 0) { - mchunkptr q = align_as_chunk(s->base); - while (segment_holds(s, q) && - q != m->top && q->head != FENCEPOST_HEAD) { - size_t sz = chunksize(q); - sum += sz; - if (!is_inuse(q)) { - mfree += sz; - ++nfree; - } - q = next_chunk(q); - } - s = s->next; - } - - nm.arena = sum; - nm.ordblks = nfree; - nm.hblkhd = m->footprint - sum; - nm.usmblks = m->max_footprint; - nm.uordblks = m->footprint - mfree; - nm.fordblks = mfree; - nm.keepcost = m->topsize; - } - - POSTACTION(m); - } - return nm; -} -#endif /* !NO_MALLINFO */ - -static void internal_malloc_stats(mstate m) { - ensure_initialization(); - if (!PREACTION(m)) { - size_t maxfp = 0; - size_t fp = 0; - size_t used = 0; - check_malloc_state(m); - if (is_initialized(m)) { - msegmentptr s = &m->seg; - maxfp = m->max_footprint; - fp = m->footprint; - used = fp - (m->topsize + TOP_FOOT_SIZE); - - while (s != 0) { - mchunkptr q = align_as_chunk(s->base); - while (segment_holds(s, q) && - q != m->top && q->head != FENCEPOST_HEAD) { - if (!is_inuse(q)) - used -= chunksize(q); - q = next_chunk(q); - } - s = s->next; - } - } - - fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp)); - fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp)); - fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used)); - - POSTACTION(m); - } -} - -/* ----------------------- Operations on smallbins ----------------------- */ - -/* - Various forms of linking and unlinking are defined as macros. Even - the ones for trees, which are very long but have very short typical - paths. This is ugly but reduces reliance on inlining support of - compilers. -*/ - -/* Link a free chunk into a smallbin */ -#define insert_small_chunk(M, P, S) {\ - bindex_t I = small_index(S);\ - mchunkptr B = smallbin_at(M, I);\ - mchunkptr F = B;\ - assert(S >= MIN_CHUNK_SIZE);\ - if (!smallmap_is_marked(M, I))\ - mark_smallmap(M, I);\ - else if (RTCHECK(ok_address(M, B->fd)))\ - F = B->fd;\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - B->fd = P;\ - F->bk = P;\ - P->fd = F;\ - P->bk = B;\ -} - -/* Unlink a chunk from a smallbin */ -#define unlink_small_chunk(M, P, S) {\ - mchunkptr F = P->fd;\ - mchunkptr B = P->bk;\ - bindex_t I = small_index(S);\ - assert(P != B);\ - assert(P != F);\ - assert(chunksize(P) == small_index2size(I));\ - if (F == B)\ - clear_smallmap(M, I);\ - else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\ - (B == smallbin_at(M,I) || ok_address(M, B)))) {\ - F->bk = B;\ - B->fd = F;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ -} - -/* Unlink the first chunk from a smallbin */ -#define unlink_first_small_chunk(M, B, P, I) {\ - mchunkptr F = P->fd;\ - assert(P != B);\ - assert(P != F);\ - assert(chunksize(P) == small_index2size(I));\ - if (B == F)\ - clear_smallmap(M, I);\ - else if (RTCHECK(ok_address(M, F))) {\ - B->fd = F;\ - F->bk = B;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ -} - - - -/* Replace dv node, binning the old one */ -/* Used only when dvsize known to be small */ -#define replace_dv(M, P, S) {\ - size_t DVS = M->dvsize;\ - if (DVS != 0) {\ - mchunkptr DV = M->dv;\ - assert(is_small(DVS));\ - insert_small_chunk(M, DV, DVS);\ - }\ - M->dvsize = S;\ - M->dv = P;\ -} - -/* ------------------------- Operations on trees ------------------------- */ - -/* Insert chunk into tree */ -#define insert_large_chunk(M, X, S) {\ - tbinptr* H;\ - bindex_t I;\ - compute_tree_index(S, I);\ - H = treebin_at(M, I);\ - X->index = I;\ - X->child[0] = X->child[1] = 0;\ - if (!treemap_is_marked(M, I)) {\ - mark_treemap(M, I);\ - *H = X;\ - X->parent = (tchunkptr)H;\ - X->fd = X->bk = X;\ - }\ - else {\ - tchunkptr T = *H;\ - size_t K = S << leftshift_for_tree_index(I);\ - for (;;) {\ - if (chunksize(T) != S) {\ - tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\ - K <<= 1;\ - if (*C != 0)\ - T = *C;\ - else if (RTCHECK(ok_address(M, C))) {\ - *C = X;\ - X->parent = T;\ - X->fd = X->bk = X;\ - break;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - break;\ - }\ - }\ - else {\ - tchunkptr F = T->fd;\ - if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\ - T->fd = F->bk = X;\ - X->fd = F;\ - X->bk = T;\ - X->parent = 0;\ - break;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - break;\ - }\ - }\ - }\ - }\ -} - -/* - Unlink steps: - - 1. If x is a chained node, unlink it from its same-sized fd/bk links - and choose its bk node as its replacement. - 2. If x was the last node of its size, but not a leaf node, it must - be replaced with a leaf node (not merely one with an open left or - right), to make sure that lefts and rights of descendents - correspond properly to bit masks. We use the rightmost descendent - of x. We could use any other leaf, but this is easy to locate and - tends to counteract removal of leftmosts elsewhere, and so keeps - paths shorter than minimally guaranteed. This doesn't loop much - because on average a node in a tree is near the bottom. - 3. If x is the base of a chain (i.e., has parent links) relink - x's parent and children to x's replacement (or null if none). -*/ - -#define unlink_large_chunk(M, X) {\ - tchunkptr XP = X->parent;\ - tchunkptr R;\ - if (X->bk != X) {\ - tchunkptr F = X->fd;\ - R = X->bk;\ - if (RTCHECK(ok_address(M, F))) {\ - F->bk = R;\ - R->fd = F;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - else {\ - tchunkptr* RP;\ - if (((R = *(RP = &(X->child[1]))) != 0) ||\ - ((R = *(RP = &(X->child[0]))) != 0)) {\ - tchunkptr* CP;\ - while ((*(CP = &(R->child[1])) != 0) ||\ - (*(CP = &(R->child[0])) != 0)) {\ - R = *(RP = CP);\ - }\ - if (RTCHECK(ok_address(M, RP)))\ - *RP = 0;\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - }\ - if (XP != 0) {\ - tbinptr* H = treebin_at(M, X->index);\ - if (X == *H) {\ - if ((*H = R) == 0) \ - clear_treemap(M, X->index);\ - }\ - else if (RTCHECK(ok_address(M, XP))) {\ - if (XP->child[0] == X) \ - XP->child[0] = R;\ - else \ - XP->child[1] = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - if (R != 0) {\ - if (RTCHECK(ok_address(M, R))) {\ - tchunkptr C0, C1;\ - R->parent = XP;\ - if ((C0 = X->child[0]) != 0) {\ - if (RTCHECK(ok_address(M, C0))) {\ - R->child[0] = C0;\ - C0->parent = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - if ((C1 = X->child[1]) != 0) {\ - if (RTCHECK(ok_address(M, C1))) {\ - R->child[1] = C1;\ - C1->parent = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ -} - -/* Relays to large vs small bin operations */ - -#define insert_chunk(M, P, S)\ - if (is_small(S)) insert_small_chunk(M, P, S)\ - else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); } - -#define unlink_chunk(M, P, S)\ - if (is_small(S)) unlink_small_chunk(M, P, S)\ - else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); } - - -/* Relays to internal calls to malloc/free from realloc, memalign etc */ - -#if ONLY_MSPACES -#define internal_malloc(m, b) mspace_malloc(m, b) -#define internal_free(m, mem) mspace_free(m,mem); -#else /* ONLY_MSPACES */ -#if MSPACES -#define internal_malloc(m, b)\ - (m == gm)? dlmalloc(b) : mspace_malloc(m, b) -#define internal_free(m, mem)\ - if (m == gm) dlfree(mem); else mspace_free(m,mem); -#else /* MSPACES */ -#define internal_malloc(m, b) dlmalloc(b) -#define internal_free(m, mem) dlfree(mem) -#endif /* MSPACES */ -#endif /* ONLY_MSPACES */ - -/* ----------------------- Direct-mmapping chunks ----------------------- */ - -/* - Directly mmapped chunks are set up with an offset to the start of - the mmapped region stored in the prev_foot field of the chunk. This - allows reconstruction of the required argument to MUNMAP when freed, - and also allows adjustment of the returned chunk to meet alignment - requirements (especially in memalign). -*/ - -/* Malloc using mmap */ -static void* mmap_alloc(mstate m, size_t nb) { - size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - if (mmsize > nb) { /* Check for wrap around 0 */ - char* mm = (char*)(CALL_DIRECT_MMAP(mmsize)); - if (mm != CMFAIL) { - size_t offset = align_offset(chunk2mem(mm)); - size_t psize = mmsize - offset - MMAP_FOOT_PAD; - mchunkptr p = (mchunkptr)(mm + offset); - p->prev_foot = offset; - p->head = psize; - mark_inuse_foot(m, p, psize); - chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD; - chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0; - - if (m->least_addr == 0 || mm < m->least_addr) - m->least_addr = mm; - if ((m->footprint += mmsize) > m->max_footprint) - m->max_footprint = m->footprint; - assert(is_aligned(chunk2mem(p))); - check_mmapped_chunk(m, p); - return chunk2mem(p); - } - } - return 0; -} - -/* Realloc using mmap */ -static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) { - size_t oldsize = chunksize(oldp); - if (is_small(nb)) /* Can't shrink mmap regions below small size */ - return 0; - /* Keep old chunk if big enough but not too big */ - if (oldsize >= nb + SIZE_T_SIZE && - (oldsize - nb) <= (mparams.granularity << 1)) - return oldp; - else { - size_t offset = oldp->prev_foot; - size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD; - size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - char* cp = (char*)CALL_MREMAP((char*)oldp - offset, - oldmmsize, newmmsize, 1); - if (cp != CMFAIL) { - mchunkptr newp = (mchunkptr)(cp + offset); - size_t psize = newmmsize - offset - MMAP_FOOT_PAD; - newp->head = psize; - mark_inuse_foot(m, newp, psize); - chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD; - chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0; - - if (cp < m->least_addr) - m->least_addr = cp; - if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint) - m->max_footprint = m->footprint; - check_mmapped_chunk(m, newp); - return newp; - } - } - return 0; -} - -/* -------------------------- mspace management -------------------------- */ - -/* Initialize top chunk and its size */ -static void init_top(mstate m, mchunkptr p, size_t psize) { - /* Ensure alignment */ - size_t offset = align_offset(chunk2mem(p)); - p = (mchunkptr)((char*)p + offset); - psize -= offset; - - m->top = p; - m->topsize = psize; - p->head = psize | PINUSE_BIT; - /* set size of fake trailing chunk holding overhead space only once */ - chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE; - m->trim_check = mparams.trim_threshold; /* reset on each update */ -} - -/* Initialize bins for a new mstate that is otherwise zeroed out */ -static void init_bins(mstate m) { - /* Establish circular links for smallbins */ - bindex_t i; - for (i = 0; i < NSMALLBINS; ++i) { - sbinptr bin = smallbin_at(m,i); - bin->fd = bin->bk = bin; - } -} - -#if PROCEED_ON_ERROR - -/* default corruption action */ -static void reset_on_error(mstate m) { - int i; - ++malloc_corruption_error_count; - /* Reinitialize fields to forget about all memory */ - m->smallbins = m->treebins = 0; - m->dvsize = m->topsize = 0; - m->seg.base = 0; - m->seg.size = 0; - m->seg.next = 0; - m->top = m->dv = 0; - for (i = 0; i < NTREEBINS; ++i) - *treebin_at(m, i) = 0; - init_bins(m); -} -#endif /* PROCEED_ON_ERROR */ - -/* Allocate chunk and prepend remainder with chunk in successor base. */ -static void* prepend_alloc(mstate m, char* newbase, char* oldbase, - size_t nb) { - mchunkptr p = align_as_chunk(newbase); - mchunkptr oldfirst = align_as_chunk(oldbase); - size_t psize = (char*)oldfirst - (char*)p; - mchunkptr q = chunk_plus_offset(p, nb); - size_t qsize = psize - nb; - set_size_and_pinuse_of_inuse_chunk(m, p, nb); - - assert((char*)oldfirst > (char*)q); - assert(pinuse(oldfirst)); - assert(qsize >= MIN_CHUNK_SIZE); - - /* consolidate remainder with first chunk of old base */ - if (oldfirst == m->top) { - size_t tsize = m->topsize += qsize; - m->top = q; - q->head = tsize | PINUSE_BIT; - check_top_chunk(m, q); - } - else if (oldfirst == m->dv) { - size_t dsize = m->dvsize += qsize; - m->dv = q; - set_size_and_pinuse_of_free_chunk(q, dsize); - } - else { - if (!is_inuse(oldfirst)) { - size_t nsize = chunksize(oldfirst); - unlink_chunk(m, oldfirst, nsize); - oldfirst = chunk_plus_offset(oldfirst, nsize); - qsize += nsize; - } - set_free_with_pinuse(q, qsize, oldfirst); - insert_chunk(m, q, qsize); - check_free_chunk(m, q); - } - - check_malloced_chunk(m, chunk2mem(p), nb); - return chunk2mem(p); -} - -/* Add a segment to hold a new noncontiguous region */ -static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) { - /* Determine locations and sizes of segment, fenceposts, old top */ - char* old_top = (char*)m->top; - msegmentptr oldsp = segment_holding(m, old_top); - char* old_end = oldsp->base + oldsp->size; - size_t ssize = pad_request(sizeof(struct malloc_segment)); - char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - size_t offset = align_offset(chunk2mem(rawsp)); - char* asp = rawsp + offset; - char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp; - mchunkptr sp = (mchunkptr)csp; - msegmentptr ss = (msegmentptr)(chunk2mem(sp)); - mchunkptr tnext = chunk_plus_offset(sp, ssize); - mchunkptr p = tnext; - int nfences = 0; - - /* reset top to new space */ - init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); - - /* Set up segment record */ - assert(is_aligned(ss)); - set_size_and_pinuse_of_inuse_chunk(m, sp, ssize); - *ss = m->seg; /* Push current record */ - m->seg.base = tbase; - m->seg.size = tsize; - m->seg.sflags = mmapped; - m->seg.next = ss; - - /* Insert trailing fenceposts */ - for (;;) { - mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE); - p->head = FENCEPOST_HEAD; - ++nfences; - if ((char*)(&(nextp->head)) < old_end) - p = nextp; - else - break; - } - assert(nfences >= 2); - - /* Insert the rest of old top into a bin as an ordinary free chunk */ - if (csp != old_top) { - mchunkptr q = (mchunkptr)old_top; - size_t psize = csp - old_top; - mchunkptr tn = chunk_plus_offset(q, psize); - set_free_with_pinuse(q, psize, tn); - insert_chunk(m, q, psize); - } - - check_top_chunk(m, m->top); -} - -/* -------------------------- System allocation -------------------------- */ - -/* Get memory from system using MORECORE or MMAP */ -static void* sys_alloc(mstate m, size_t nb) { - char* tbase = CMFAIL; - size_t tsize = 0; - flag_t mmap_flag = 0; - - ensure_initialization(); - - /* Directly map large chunks, but only if already initialized */ - if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0) { - void* mem = mmap_alloc(m, nb); - if (mem != 0) - return mem; - } - - /* - Try getting memory in any of three ways (in most-preferred to - least-preferred order): - 1. A call to MORECORE that can normally contiguously extend memory. - (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or - or main space is mmapped or a previous contiguous call failed) - 2. A call to MMAP new space (disabled if not HAVE_MMAP). - Note that under the default settings, if MORECORE is unable to - fulfill a request, and HAVE_MMAP is true, then mmap is - used as a noncontiguous system allocator. This is a useful backup - strategy for systems with holes in address spaces -- in this case - sbrk cannot contiguously expand the heap, but mmap may be able to - find space. - 3. A call to MORECORE that cannot usually contiguously extend memory. - (disabled if not HAVE_MORECORE) - - In all cases, we need to request enough bytes from system to ensure - we can malloc nb bytes upon success, so pad with enough space for - top_foot, plus alignment-pad to make sure we don't lose bytes if - not on boundary, and round this up to a granularity unit. - */ - - if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) { - char* br = CMFAIL; - msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top); - size_t asize = 0; - ACQUIRE_MALLOC_GLOBAL_LOCK(); - - if (ss == 0) { /* First time through or recovery */ - char* base = (char*)CALL_MORECORE(0); - if (base != CMFAIL) { - asize = granularity_align(nb + SYS_ALLOC_PADDING); - /* Adjust to end on a page boundary */ - if (!is_page_aligned(base)) - asize += (page_align((size_t)base) - (size_t)base); - /* Can't call MORECORE if size is negative when treated as signed */ - if (asize < HALF_MAX_SIZE_T && - (br = (char*)(CALL_MORECORE(asize))) == base) { - tbase = base; - tsize = asize; - } - } - } - else { - /* Subtract out existing available top space from MORECORE request. */ - asize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING); - /* Use mem here only if it did continuously extend old space */ - if (asize < HALF_MAX_SIZE_T && - (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) { - tbase = br; - tsize = asize; - } - } - - if (tbase == CMFAIL) { /* Cope with partial failure */ - if (br != CMFAIL) { /* Try to use/extend the space we did get */ - if (asize < HALF_MAX_SIZE_T && - asize < nb + SYS_ALLOC_PADDING) { - size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - asize); - if (esize < HALF_MAX_SIZE_T) { - char* end = (char*)CALL_MORECORE(esize); - if (end != CMFAIL) - asize += esize; - else { /* Can't use; try to release */ - (void) CALL_MORECORE(-asize); - br = CMFAIL; - } - } - } - } - if (br != CMFAIL) { /* Use the space we did get */ - tbase = br; - tsize = asize; - } - else - disable_contiguous(m); /* Don't try contiguous path in the future */ - } - - RELEASE_MALLOC_GLOBAL_LOCK(); - } - - if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */ - size_t rsize = granularity_align(nb + SYS_ALLOC_PADDING); - if (rsize > nb) { /* Fail if wraps around zero */ - char* mp = (char*)(CALL_MMAP(rsize)); - if (mp != CMFAIL) { - tbase = mp; - tsize = rsize; - mmap_flag = USE_MMAP_BIT; - } - } - } - - if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */ - size_t asize = granularity_align(nb + SYS_ALLOC_PADDING); - if (asize < HALF_MAX_SIZE_T) { - char* br = CMFAIL; - char* end = CMFAIL; - ACQUIRE_MALLOC_GLOBAL_LOCK(); - br = (char*)(CALL_MORECORE(asize)); - end = (char*)(CALL_MORECORE(0)); - RELEASE_MALLOC_GLOBAL_LOCK(); - if (br != CMFAIL && end != CMFAIL && br < end) { - size_t ssize = end - br; - if (ssize > nb + TOP_FOOT_SIZE) { - tbase = br; - tsize = ssize; - } - } - } - } - - if (tbase != CMFAIL) { - - if ((m->footprint += tsize) > m->max_footprint) - m->max_footprint = m->footprint; - - if (!is_initialized(m)) { /* first-time initialization */ - if (m->least_addr == 0 || tbase < m->least_addr) - m->least_addr = tbase; - m->seg.base = tbase; - m->seg.size = tsize; - m->seg.sflags = mmap_flag; - m->magic = mparams.magic; - m->release_checks = MAX_RELEASE_CHECK_RATE; - init_bins(m); -#if !ONLY_MSPACES - if (is_global(m)) - init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); - else -#endif - { - /* Offset top by embedded malloc_state */ - mchunkptr mn = next_chunk(mem2chunk(m)); - init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE); - } - } - - else { - /* Try to merge with an existing segment */ - msegmentptr sp = &m->seg; - /* Only consider most recent segment if traversal suppressed */ - while (sp != 0 && tbase != sp->base + sp->size) - sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; - if (sp != 0 && - !is_extern_segment(sp) && - (sp->sflags & USE_MMAP_BIT) == mmap_flag && - segment_holds(sp, m->top)) { /* append */ - sp->size += tsize; - init_top(m, m->top, m->topsize + tsize); - } - else { - if (tbase < m->least_addr) - m->least_addr = tbase; - sp = &m->seg; - while (sp != 0 && sp->base != tbase + tsize) - sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; - if (sp != 0 && - !is_extern_segment(sp) && - (sp->sflags & USE_MMAP_BIT) == mmap_flag) { - char* oldbase = sp->base; - sp->base = tbase; - sp->size += tsize; - return prepend_alloc(m, tbase, oldbase, nb); - } - else - add_segment(m, tbase, tsize, mmap_flag); - } - } - - if (nb < m->topsize) { /* Allocate from new or extended top space */ - size_t rsize = m->topsize -= nb; - mchunkptr p = m->top; - mchunkptr r = m->top = chunk_plus_offset(p, nb); - r->head = rsize | PINUSE_BIT; - set_size_and_pinuse_of_inuse_chunk(m, p, nb); - check_top_chunk(m, m->top); - check_malloced_chunk(m, chunk2mem(p), nb); - return chunk2mem(p); - } - } - - MALLOC_FAILURE_ACTION; - return 0; -} - -/* ----------------------- system deallocation -------------------------- */ - -/* Unmap and unlink any mmapped segments that don't contain used chunks */ -static size_t release_unused_segments(mstate m) { - size_t released = 0; - int nsegs = 0; - msegmentptr pred = &m->seg; - msegmentptr sp = pred->next; - while (sp != 0) { - char* base = sp->base; - size_t size = sp->size; - msegmentptr next = sp->next; - ++nsegs; - if (is_mmapped_segment(sp) && !is_extern_segment(sp)) { - mchunkptr p = align_as_chunk(base); - size_t psize = chunksize(p); - /* Can unmap if first chunk holds entire segment and not pinned */ - if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) { - tchunkptr tp = (tchunkptr)p; - assert(segment_holds(sp, (char*)sp)); - if (p == m->dv) { - m->dv = 0; - m->dvsize = 0; - } - else { - unlink_large_chunk(m, tp); - } - if (CALL_MUNMAP(base, size) == 0) { - released += size; - m->footprint -= size; - /* unlink obsoleted record */ - sp = pred; - sp->next = next; - } - else { /* back out if cannot unmap */ - insert_large_chunk(m, tp, psize); - } - } - } - if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */ - break; - pred = sp; - sp = next; - } - /* Reset check counter */ - m->release_checks = ((nsegs > MAX_RELEASE_CHECK_RATE)? - nsegs : MAX_RELEASE_CHECK_RATE); - return released; -} - -static int sys_trim(mstate m, size_t pad) { - size_t released = 0; - ensure_initialization(); - if (pad < MAX_REQUEST && is_initialized(m)) { - pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */ - - if (m->topsize > pad) { - /* Shrink top space in granularity-size units, keeping at least one */ - size_t unit = mparams.granularity; - size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit - - SIZE_T_ONE) * unit; - msegmentptr sp = segment_holding(m, (char*)m->top); - - if (!is_extern_segment(sp)) { - if (is_mmapped_segment(sp)) { - if (HAVE_MMAP && - sp->size >= extra && - !has_segment_link(m, sp)) { /* can't shrink if pinned */ - size_t newsize = sp->size - extra; - /* Prefer mremap, fall back to munmap */ - if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) || - (CALL_MUNMAP(sp->base + newsize, extra) == 0)) { - released = extra; - } - } - } - else if (HAVE_MORECORE) { - if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */ - extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit; - ACQUIRE_MALLOC_GLOBAL_LOCK(); - { - /* Make sure end of memory is where we last set it. */ - char* old_br = (char*)(CALL_MORECORE(0)); - if (old_br == sp->base + sp->size) { - char* rel_br = (char*)(CALL_MORECORE(-extra)); - char* new_br = (char*)(CALL_MORECORE(0)); - if (rel_br != CMFAIL && new_br < old_br) - released = old_br - new_br; - } - } - RELEASE_MALLOC_GLOBAL_LOCK(); - } - } - - if (released != 0) { - sp->size -= released; - m->footprint -= released; - init_top(m, m->top, m->topsize - released); - check_top_chunk(m, m->top); - } - } - - /* Unmap any unused mmapped segments */ - if (HAVE_MMAP) - released += release_unused_segments(m); - - /* On failure, disable autotrim to avoid repeated failed future calls */ - if (released == 0 && m->topsize > m->trim_check) - m->trim_check = MAX_SIZE_T; - } - - return (released != 0)? 1 : 0; -} - - -/* ---------------------------- malloc support --------------------------- */ - -/* allocate a large request from the best fitting chunk in a treebin */ -static void* tmalloc_large(mstate m, size_t nb) { - tchunkptr v = 0; - size_t rsize = -nb; /* Unsigned negation */ - tchunkptr t; - bindex_t idx; - compute_tree_index(nb, idx); - if ((t = *treebin_at(m, idx)) != 0) { - /* Traverse tree for this bin looking for node with size == nb */ - size_t sizebits = nb << leftshift_for_tree_index(idx); - tchunkptr rst = 0; /* The deepest untaken right subtree */ - for (;;) { - tchunkptr rt; - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - v = t; - if ((rsize = trem) == 0) - break; - } - rt = t->child[1]; - t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; - if (rt != 0 && rt != t) - rst = rt; - if (t == 0) { - t = rst; /* set t to least subtree holding sizes > nb */ - break; - } - sizebits <<= 1; - } - } - if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */ - binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap; - if (leftbits != 0) { - bindex_t i; - binmap_t leastbit = least_bit(leftbits); - compute_bit2idx(leastbit, i); - t = *treebin_at(m, i); - } - } - - while (t != 0) { /* find smallest of tree or subtree */ - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - rsize = trem; - v = t; - } - t = leftmost_child(t); - } - - /* If dv is a better fit, return 0 so malloc will use it */ - if (v != 0 && rsize < (size_t)(m->dvsize - nb)) { - if (RTCHECK(ok_address(m, v))) { /* split */ - mchunkptr r = chunk_plus_offset(v, nb); - assert(chunksize(v) == rsize + nb); - if (RTCHECK(ok_next(v, r))) { - unlink_large_chunk(m, v); - if (rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(m, v, (rsize + nb)); - else { - set_size_and_pinuse_of_inuse_chunk(m, v, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - insert_chunk(m, r, rsize); - } - return chunk2mem(v); - } - } - CORRUPTION_ERROR_ACTION(m); - } - return 0; -} - -/* allocate a small request from the best fitting chunk in a treebin */ -static void* tmalloc_small(mstate m, size_t nb) { - tchunkptr t, v; - size_t rsize; - bindex_t i; - binmap_t leastbit = least_bit(m->treemap); - compute_bit2idx(leastbit, i); - v = t = *treebin_at(m, i); - rsize = chunksize(t) - nb; - - while ((t = leftmost_child(t)) != 0) { - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - rsize = trem; - v = t; - } - } - - if (RTCHECK(ok_address(m, v))) { - mchunkptr r = chunk_plus_offset(v, nb); - assert(chunksize(v) == rsize + nb); - if (RTCHECK(ok_next(v, r))) { - unlink_large_chunk(m, v); - if (rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(m, v, (rsize + nb)); - else { - set_size_and_pinuse_of_inuse_chunk(m, v, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - replace_dv(m, r, rsize); - } - return chunk2mem(v); - } - } - - CORRUPTION_ERROR_ACTION(m); - return 0; -} - -/* --------------------------- realloc support --------------------------- */ - -static void* internal_realloc(mstate m, void* oldmem, size_t bytes) { - if (bytes >= MAX_REQUEST) { - MALLOC_FAILURE_ACTION; - return 0; - } - if (!PREACTION(m)) { - mchunkptr oldp = mem2chunk(oldmem); - size_t oldsize = chunksize(oldp); - mchunkptr next = chunk_plus_offset(oldp, oldsize); - mchunkptr newp = 0; - void* extra = 0; - - /* Try to either shrink or extend into top. Else malloc-copy-free */ - - if (RTCHECK(ok_address(m, oldp) && ok_inuse(oldp) && - ok_next(oldp, next) && ok_pinuse(next))) { - size_t nb = request2size(bytes); - if (is_mmapped(oldp)) - newp = mmap_resize(m, oldp, nb); - else if (oldsize >= nb) { /* already big enough */ - size_t rsize = oldsize - nb; - newp = oldp; - if (rsize >= MIN_CHUNK_SIZE) { - mchunkptr remainder = chunk_plus_offset(newp, nb); - set_inuse(m, newp, nb); - set_inuse_and_pinuse(m, remainder, rsize); - extra = chunk2mem(remainder); - } - } - else if (next == m->top && oldsize + m->topsize > nb) { - /* Expand into top */ - size_t newsize = oldsize + m->topsize; - size_t newtopsize = newsize - nb; - mchunkptr newtop = chunk_plus_offset(oldp, nb); - set_inuse(m, oldp, nb); - newtop->head = newtopsize |PINUSE_BIT; - m->top = newtop; - m->topsize = newtopsize; - newp = oldp; - } - } - else { - USAGE_ERROR_ACTION(m, oldmem); - POSTACTION(m); - return 0; - } -#if DEBUG - if (newp != 0) { - check_inuse_chunk(m, newp); /* Check requires lock */ - } -#endif - - POSTACTION(m); - - if (newp != 0) { - if (extra != 0) { - internal_free(m, extra); - } - return chunk2mem(newp); - } - else { - void* newmem = internal_malloc(m, bytes); - if (newmem != 0) { - size_t oc = oldsize - overhead_for(oldp); - memcpy(newmem, oldmem, (oc < bytes)? oc : bytes); - internal_free(m, oldmem); - } - return newmem; - } - } - return 0; -} - -/* --------------------------- memalign support -------------------------- */ - -static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { - if (alignment <= MALLOC_ALIGNMENT) /* Can just use malloc */ - return internal_malloc(m, bytes); - if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ - alignment = MIN_CHUNK_SIZE; - if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ - size_t a = MALLOC_ALIGNMENT << 1; - while (a < alignment) a <<= 1; - alignment = a; - } - - if (bytes >= MAX_REQUEST - alignment) { - if (m != 0) { /* Test isn't needed but avoids compiler warning */ - MALLOC_FAILURE_ACTION; - } - } - else { - size_t nb = request2size(bytes); - size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; - char* mem = (char*)internal_malloc(m, req); - if (mem != 0) { - void* leader = 0; - void* trailer = 0; - mchunkptr p = mem2chunk(mem); - - if (PREACTION(m)) return 0; - if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */ - /* - Find an aligned spot inside chunk. Since we need to give - back leading space in a chunk of at least MIN_CHUNK_SIZE, if - the first calculation places us at a spot with less than - MIN_CHUNK_SIZE leader, we can move to the next aligned spot. - We've allocated enough total room so that this is always - possible. - */ - char* br = (char*)mem2chunk((size_t)(((size_t)(mem + - alignment - - SIZE_T_ONE)) & - -alignment)); - char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? - br : br+alignment; - mchunkptr newp = (mchunkptr)pos; - size_t leadsize = pos - (char*)(p); - size_t newsize = chunksize(p) - leadsize; - - if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ - newp->prev_foot = p->prev_foot + leadsize; - newp->head = newsize; - } - else { /* Otherwise, give back leader, use the rest */ - set_inuse(m, newp, newsize); - set_inuse(m, p, leadsize); - leader = chunk2mem(p); - } - p = newp; - } - - /* Give back spare room at the end */ - if (!is_mmapped(p)) { - size_t size = chunksize(p); - if (size > nb + MIN_CHUNK_SIZE) { - size_t remainder_size = size - nb; - mchunkptr remainder = chunk_plus_offset(p, nb); - set_inuse(m, p, nb); - set_inuse(m, remainder, remainder_size); - trailer = chunk2mem(remainder); - } - } - - assert (chunksize(p) >= nb); - assert((((size_t)(chunk2mem(p))) % alignment) == 0); - check_inuse_chunk(m, p); - POSTACTION(m); - if (leader != 0) { - internal_free(m, leader); - } - if (trailer != 0) { - internal_free(m, trailer); - } - return chunk2mem(p); - } - } - return 0; -} - -/* ------------------------ comalloc/coalloc support --------------------- */ - -static void** ialloc(mstate m, - size_t n_elements, - size_t* sizes, - int opts, - void* chunks[]) { - /* - This provides common support for independent_X routines, handling - all of the combinations that can result. - - The opts arg has: - bit 0 set if all elements are same size (using sizes[0]) - bit 1 set if elements should be zeroed - */ - - size_t element_size; /* chunksize of each element, if all same */ - size_t contents_size; /* total size of elements */ - size_t array_size; /* request size of pointer array */ - void* mem; /* malloced aggregate space */ - mchunkptr p; /* corresponding chunk */ - size_t remainder_size; /* remaining bytes while splitting */ - void** marray; /* either "chunks" or malloced ptr array */ - mchunkptr array_chunk; /* chunk for malloced ptr array */ - flag_t was_enabled; /* to disable mmap */ - size_t size; - size_t i; - - ensure_initialization(); - /* compute array length, if needed */ - if (chunks != 0) { - if (n_elements == 0) - return chunks; /* nothing to do */ - marray = chunks; - array_size = 0; - } - else { - /* if empty req, must still return chunk representing empty array */ - if (n_elements == 0) - return (void**)internal_malloc(m, 0); - marray = 0; - array_size = request2size(n_elements * (sizeof(void*))); - } - - /* compute total element size */ - if (opts & 0x1) { /* all-same-size */ - element_size = request2size(*sizes); - contents_size = n_elements * element_size; - } - else { /* add up all the sizes */ - element_size = 0; - contents_size = 0; - for (i = 0; i != n_elements; ++i) - contents_size += request2size(sizes[i]); - } - - size = contents_size + array_size; - - /* - Allocate the aggregate chunk. First disable direct-mmapping so - malloc won't use it, since we would not be able to later - free/realloc space internal to a segregated mmap region. - */ - was_enabled = use_mmap(m); - disable_mmap(m); - mem = internal_malloc(m, size - CHUNK_OVERHEAD); - if (was_enabled) - enable_mmap(m); - if (mem == 0) - return 0; - - if (PREACTION(m)) return 0; - p = mem2chunk(mem); - remainder_size = chunksize(p); - - assert(!is_mmapped(p)); - - if (opts & 0x2) { /* optionally clear the elements */ - memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size); - } - - /* If not provided, allocate the pointer array as final part of chunk */ - if (marray == 0) { - size_t array_chunk_size; - array_chunk = chunk_plus_offset(p, contents_size); - array_chunk_size = remainder_size - contents_size; - marray = (void**) (chunk2mem(array_chunk)); - set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size); - remainder_size = contents_size; - } - - /* split out elements */ - for (i = 0; ; ++i) { - marray[i] = chunk2mem(p); - if (i != n_elements-1) { - if (element_size != 0) - size = element_size; - else - size = request2size(sizes[i]); - remainder_size -= size; - set_size_and_pinuse_of_inuse_chunk(m, p, size); - p = chunk_plus_offset(p, size); - } - else { /* the final element absorbs any overallocation slop */ - set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size); - break; - } - } - -#if DEBUG - if (marray != chunks) { - /* final element must have exactly exhausted chunk */ - if (element_size != 0) { - assert(remainder_size == element_size); - } - else { - assert(remainder_size == request2size(sizes[i])); - } - check_inuse_chunk(m, mem2chunk(marray)); - } - for (i = 0; i != n_elements; ++i) - check_inuse_chunk(m, mem2chunk(marray[i])); - -#endif /* DEBUG */ - - POSTACTION(m); - return marray; -} - - -/* -------------------------- public routines ---------------------------- */ - -#if !ONLY_MSPACES - -void* dlmalloc(size_t bytes) { - /* - Basic algorithm: - If a small request (< 256 bytes minus per-chunk overhead): - 1. If one exists, use a remainderless chunk in associated smallbin. - (Remainderless means that there are too few excess bytes to - represent as a chunk.) - 2. If it is big enough, use the dv chunk, which is normally the - chunk adjacent to the one used for the most recent small request. - 3. If one exists, split the smallest available chunk in a bin, - saving remainder in dv. - 4. If it is big enough, use the top chunk. - 5. If available, get memory from system and use it - Otherwise, for a large request: - 1. Find the smallest available binned chunk that fits, and use it - if it is better fitting than dv chunk, splitting if necessary. - 2. If better fitting than any binned chunk, use the dv chunk. - 3. If it is big enough, use the top chunk. - 4. If request size >= mmap threshold, try to directly mmap this chunk. - 5. If available, get memory from system and use it - - The ugly goto's here ensure that postaction occurs along all paths. - */ - -#if USE_LOCKS - ensure_initialization(); /* initialize in sys_alloc if not using locks */ -#endif - - if (!PREACTION(gm)) { - void* mem; - size_t nb; - if (bytes <= MAX_SMALL_REQUEST) { - bindex_t idx; - binmap_t smallbits; - nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); - idx = small_index(nb); - smallbits = gm->smallmap >> idx; - - if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ - mchunkptr b, p; - idx += ~smallbits & 1; /* Uses next bin if idx empty */ - b = smallbin_at(gm, idx); - p = b->fd; - assert(chunksize(p) == small_index2size(idx)); - unlink_first_small_chunk(gm, b, p, idx); - set_inuse_and_pinuse(gm, p, small_index2size(idx)); - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - else if (nb > gm->dvsize) { - if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ - mchunkptr b, p, r; - size_t rsize; - bindex_t i; - binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); - binmap_t leastbit = least_bit(leftbits); - compute_bit2idx(leastbit, i); - b = smallbin_at(gm, i); - p = b->fd; - assert(chunksize(p) == small_index2size(i)); - unlink_first_small_chunk(gm, b, p, i); - rsize = small_index2size(i) - nb; - /* Fit here cannot be remainderless if 4byte sizes */ - if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(gm, p, small_index2size(i)); - else { - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - r = chunk_plus_offset(p, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - replace_dv(gm, r, rsize); - } - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) { - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - } - } - else if (bytes >= MAX_REQUEST) - nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ - else { - nb = pad_request(bytes); - if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) { - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - } - - if (nb <= gm->dvsize) { - size_t rsize = gm->dvsize - nb; - mchunkptr p = gm->dv; - if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ - mchunkptr r = gm->dv = chunk_plus_offset(p, nb); - gm->dvsize = rsize; - set_size_and_pinuse_of_free_chunk(r, rsize); - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - } - else { /* exhaust dv */ - size_t dvs = gm->dvsize; - gm->dvsize = 0; - gm->dv = 0; - set_inuse_and_pinuse(gm, p, dvs); - } - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - else if (nb < gm->topsize) { /* Split top */ - size_t rsize = gm->topsize -= nb; - mchunkptr p = gm->top; - mchunkptr r = gm->top = chunk_plus_offset(p, nb); - r->head = rsize | PINUSE_BIT; - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - mem = chunk2mem(p); - check_top_chunk(gm, gm->top); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - mem = sys_alloc(gm, nb); - - postaction: - POSTACTION(gm); - return mem; - } - - return 0; -} - -void dlfree(void* mem) { - /* - Consolidate freed chunks with preceeding or succeeding bordering - free chunks, if they exist, and then place in a bin. Intermixed - with special cases for top, dv, mmapped chunks, and usage errors. - */ - - if (mem != 0) { - mchunkptr p = mem2chunk(mem); -#if FOOTERS - mstate fm = get_mstate_for(p); - if (!ok_magic(fm)) { - USAGE_ERROR_ACTION(fm, p); - return; - } -#else /* FOOTERS */ -#define fm gm -#endif /* FOOTERS */ - if (!PREACTION(fm)) { - check_inuse_chunk(fm, p); - if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) { - size_t psize = chunksize(p); - mchunkptr next = chunk_plus_offset(p, psize); - if (!pinuse(p)) { - size_t prevsize = p->prev_foot; - if (is_mmapped(p)) { - psize += prevsize + MMAP_FOOT_PAD; - if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) - fm->footprint -= psize; - goto postaction; - } - else { - mchunkptr prev = chunk_minus_offset(p, prevsize); - psize += prevsize; - p = prev; - if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ - if (p != fm->dv) { - unlink_chunk(fm, p, prevsize); - } - else if ((next->head & INUSE_BITS) == INUSE_BITS) { - fm->dvsize = psize; - set_free_with_pinuse(p, psize, next); - goto postaction; - } - } - else - goto erroraction; - } - } - - if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { - if (!cinuse(next)) { /* consolidate forward */ - if (next == fm->top) { - size_t tsize = fm->topsize += psize; - fm->top = p; - p->head = tsize | PINUSE_BIT; - if (p == fm->dv) { - fm->dv = 0; - fm->dvsize = 0; - } - if (should_trim(fm, tsize)) - sys_trim(fm, 0); - goto postaction; - } - else if (next == fm->dv) { - size_t dsize = fm->dvsize += psize; - fm->dv = p; - set_size_and_pinuse_of_free_chunk(p, dsize); - goto postaction; - } - else { - size_t nsize = chunksize(next); - psize += nsize; - unlink_chunk(fm, next, nsize); - set_size_and_pinuse_of_free_chunk(p, psize); - if (p == fm->dv) { - fm->dvsize = psize; - goto postaction; - } - } - } - else - set_free_with_pinuse(p, psize, next); - - if (is_small(psize)) { - insert_small_chunk(fm, p, psize); - check_free_chunk(fm, p); - } - else { - tchunkptr tp = (tchunkptr)p; - insert_large_chunk(fm, tp, psize); - check_free_chunk(fm, p); - if (--fm->release_checks == 0) - release_unused_segments(fm); - } - goto postaction; - } - } - erroraction: - USAGE_ERROR_ACTION(fm, p); - postaction: - POSTACTION(fm); - } - } -#if !FOOTERS -#undef fm -#endif /* FOOTERS */ -} - -void* dlcalloc(size_t n_elements, size_t elem_size) { - void* mem; - size_t req = 0; - if (n_elements != 0) { - req = n_elements * elem_size; - if (((n_elements | elem_size) & ~(size_t)0xffff) && - (req / n_elements != elem_size)) - req = MAX_SIZE_T; /* force downstream failure on overflow */ - } - mem = dlmalloc(req); - if (mem != 0 && calloc_must_clear(mem2chunk(mem))) - memset(mem, 0, req); - return mem; -} - -void* dlrealloc(void* oldmem, size_t bytes) { - if (oldmem == 0) - return dlmalloc(bytes); -#ifdef REALLOC_ZERO_BYTES_FREES - if (bytes == 0) { - dlfree(oldmem); - return 0; - } -#endif /* REALLOC_ZERO_BYTES_FREES */ - else { -#if ! FOOTERS - mstate m = gm; -#else /* FOOTERS */ - mstate m = get_mstate_for(mem2chunk(oldmem)); - if (!ok_magic(m)) { - USAGE_ERROR_ACTION(m, oldmem); - return 0; - } -#endif /* FOOTERS */ - return internal_realloc(m, oldmem, bytes); - } -} - -void* dlmemalign(size_t alignment, size_t bytes) { - return internal_memalign(gm, alignment, bytes); -} - -void** dlindependent_calloc(size_t n_elements, size_t elem_size, - void* chunks[]) { - size_t sz = elem_size; /* serves as 1-element array */ - return ialloc(gm, n_elements, &sz, 3, chunks); -} - -void** dlindependent_comalloc(size_t n_elements, size_t sizes[], - void* chunks[]) { - return ialloc(gm, n_elements, sizes, 0, chunks); -} - -void* dlvalloc(size_t bytes) { - size_t pagesz; - ensure_initialization(); - pagesz = mparams.page_size; - return dlmemalign(pagesz, bytes); -} - -void* dlpvalloc(size_t bytes) { - size_t pagesz; - ensure_initialization(); - pagesz = mparams.page_size; - return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE)); -} - -int dlmalloc_trim(size_t pad) { - int result = 0; - ensure_initialization(); - if (!PREACTION(gm)) { - result = sys_trim(gm, pad); - POSTACTION(gm); - } - return result; -} - -size_t dlmalloc_footprint(void) { - return gm->footprint; -} - -size_t dlmalloc_max_footprint(void) { - return gm->max_footprint; -} - -#if !NO_MALLINFO -struct mallinfo dlmallinfo(void) { - return internal_mallinfo(gm); -} -#endif /* NO_MALLINFO */ - -void dlmalloc_stats() { - internal_malloc_stats(gm); -} - -int dlmallopt(int param_number, int value) { - return change_mparam(param_number, value); -} - -#endif /* !ONLY_MSPACES */ - -size_t dlmalloc_usable_size(void* mem) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); - if (is_inuse(p)) - return chunksize(p) - overhead_for(p); - } - return 0; -} - -/* ----------------------------- user mspaces ---------------------------- */ - -#if MSPACES - -static mstate init_user_mstate(char* tbase, size_t tsize) { - size_t msize = pad_request(sizeof(struct malloc_state)); - mchunkptr mn; - mchunkptr msp = align_as_chunk(tbase); - mstate m = (mstate)(chunk2mem(msp)); - memset(m, 0, msize); - INITIAL_LOCK(&m->mutex); - msp->head = (msize|INUSE_BITS); - m->seg.base = m->least_addr = tbase; - m->seg.size = m->footprint = m->max_footprint = tsize; - m->magic = mparams.magic; - m->release_checks = MAX_RELEASE_CHECK_RATE; - m->mflags = mparams.default_mflags; - m->extp = 0; - m->exts = 0; - disable_contiguous(m); - init_bins(m); - mn = next_chunk(mem2chunk(m)); - init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE); - check_top_chunk(m, m->top); - return m; -} - -mspace create_mspace(size_t capacity, int locked) { - mstate m = 0; - size_t msize; - ensure_initialization(); - msize = pad_request(sizeof(struct malloc_state)); - if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { - size_t rs = ((capacity == 0)? mparams.granularity : - (capacity + TOP_FOOT_SIZE + msize)); - size_t tsize = granularity_align(rs); - char* tbase = (char*)(CALL_MMAP(tsize)); - if (tbase != CMFAIL) { - m = init_user_mstate(tbase, tsize); - m->seg.sflags = USE_MMAP_BIT; - set_lock(m, locked); - } - } - return (mspace)m; -} - -mspace create_mspace_with_base(void* base, size_t capacity, int locked) { - mstate m = 0; - size_t msize; - ensure_initialization(); - msize = pad_request(sizeof(struct malloc_state)); - if (capacity > msize + TOP_FOOT_SIZE && - capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { - m = init_user_mstate((char*)base, capacity); - m->seg.sflags = EXTERN_BIT; - set_lock(m, locked); - } - return (mspace)m; -} - -int mspace_track_large_chunks(mspace msp, int enable) { - int ret = 0; - mstate ms = (mstate)msp; - if (!PREACTION(ms)) { - if (!use_mmap(ms)) - ret = 1; - if (!enable) - enable_mmap(ms); - else - disable_mmap(ms); - POSTACTION(ms); - } - return ret; -} - -size_t destroy_mspace(mspace msp) { - size_t freed = 0; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - msegmentptr sp = &ms->seg; - while (sp != 0) { - char* base = sp->base; - size_t size = sp->size; - flag_t flag = sp->sflags; - sp = sp->next; - if ((flag & USE_MMAP_BIT) && !(flag & EXTERN_BIT) && - CALL_MUNMAP(base, size) == 0) - freed += size; - } - } - else { - USAGE_ERROR_ACTION(ms,ms); - } - return freed; -} - -/* - mspace versions of routines are near-clones of the global - versions. This is not so nice but better than the alternatives. -*/ - - -void* mspace_malloc(mspace msp, size_t bytes) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - if (!PREACTION(ms)) { - void* mem; - size_t nb; - if (bytes <= MAX_SMALL_REQUEST) { - bindex_t idx; - binmap_t smallbits; - nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); - idx = small_index(nb); - smallbits = ms->smallmap >> idx; - - if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ - mchunkptr b, p; - idx += ~smallbits & 1; /* Uses next bin if idx empty */ - b = smallbin_at(ms, idx); - p = b->fd; - assert(chunksize(p) == small_index2size(idx)); - unlink_first_small_chunk(ms, b, p, idx); - set_inuse_and_pinuse(ms, p, small_index2size(idx)); - mem = chunk2mem(p); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - else if (nb > ms->dvsize) { - if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ - mchunkptr b, p, r; - size_t rsize; - bindex_t i; - binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); - binmap_t leastbit = least_bit(leftbits); - compute_bit2idx(leastbit, i); - b = smallbin_at(ms, i); - p = b->fd; - assert(chunksize(p) == small_index2size(i)); - unlink_first_small_chunk(ms, b, p, i); - rsize = small_index2size(i) - nb; - /* Fit here cannot be remainderless if 4byte sizes */ - if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(ms, p, small_index2size(i)); - else { - set_size_and_pinuse_of_inuse_chunk(ms, p, nb); - r = chunk_plus_offset(p, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - replace_dv(ms, r, rsize); - } - mem = chunk2mem(p); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) { - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - } - } - else if (bytes >= MAX_REQUEST) - nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ - else { - nb = pad_request(bytes); - if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) { - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - } - - if (nb <= ms->dvsize) { - size_t rsize = ms->dvsize - nb; - mchunkptr p = ms->dv; - if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ - mchunkptr r = ms->dv = chunk_plus_offset(p, nb); - ms->dvsize = rsize; - set_size_and_pinuse_of_free_chunk(r, rsize); - set_size_and_pinuse_of_inuse_chunk(ms, p, nb); - } - else { /* exhaust dv */ - size_t dvs = ms->dvsize; - ms->dvsize = 0; - ms->dv = 0; - set_inuse_and_pinuse(ms, p, dvs); - } - mem = chunk2mem(p); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - else if (nb < ms->topsize) { /* Split top */ - size_t rsize = ms->topsize -= nb; - mchunkptr p = ms->top; - mchunkptr r = ms->top = chunk_plus_offset(p, nb); - r->head = rsize | PINUSE_BIT; - set_size_and_pinuse_of_inuse_chunk(ms, p, nb); - mem = chunk2mem(p); - check_top_chunk(ms, ms->top); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - mem = sys_alloc(ms, nb); - - postaction: - POSTACTION(ms); - return mem; - } - - return 0; -} - -void mspace_free(mspace msp, void* mem) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); -#if FOOTERS - mstate fm = get_mstate_for(p); - msp = msp; /* placate people compiling -Wunused */ -#else /* FOOTERS */ - mstate fm = (mstate)msp; -#endif /* FOOTERS */ - if (!ok_magic(fm)) { - USAGE_ERROR_ACTION(fm, p); - return; - } - if (!PREACTION(fm)) { - check_inuse_chunk(fm, p); - if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) { - size_t psize = chunksize(p); - mchunkptr next = chunk_plus_offset(p, psize); - if (!pinuse(p)) { - size_t prevsize = p->prev_foot; - if (is_mmapped(p)) { - psize += prevsize + MMAP_FOOT_PAD; - if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) - fm->footprint -= psize; - goto postaction; - } - else { - mchunkptr prev = chunk_minus_offset(p, prevsize); - psize += prevsize; - p = prev; - if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ - if (p != fm->dv) { - unlink_chunk(fm, p, prevsize); - } - else if ((next->head & INUSE_BITS) == INUSE_BITS) { - fm->dvsize = psize; - set_free_with_pinuse(p, psize, next); - goto postaction; - } - } - else - goto erroraction; - } - } - - if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { - if (!cinuse(next)) { /* consolidate forward */ - if (next == fm->top) { - size_t tsize = fm->topsize += psize; - fm->top = p; - p->head = tsize | PINUSE_BIT; - if (p == fm->dv) { - fm->dv = 0; - fm->dvsize = 0; - } - if (should_trim(fm, tsize)) - sys_trim(fm, 0); - goto postaction; - } - else if (next == fm->dv) { - size_t dsize = fm->dvsize += psize; - fm->dv = p; - set_size_and_pinuse_of_free_chunk(p, dsize); - goto postaction; - } - else { - size_t nsize = chunksize(next); - psize += nsize; - unlink_chunk(fm, next, nsize); - set_size_and_pinuse_of_free_chunk(p, psize); - if (p == fm->dv) { - fm->dvsize = psize; - goto postaction; - } - } - } - else - set_free_with_pinuse(p, psize, next); - - if (is_small(psize)) { - insert_small_chunk(fm, p, psize); - check_free_chunk(fm, p); - } - else { - tchunkptr tp = (tchunkptr)p; - insert_large_chunk(fm, tp, psize); - check_free_chunk(fm, p); - if (--fm->release_checks == 0) - release_unused_segments(fm); - } - goto postaction; - } - } - erroraction: - USAGE_ERROR_ACTION(fm, p); - postaction: - POSTACTION(fm); - } - } -} - -void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) { - void* mem; - size_t req = 0; - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - if (n_elements != 0) { - req = n_elements * elem_size; - if (((n_elements | elem_size) & ~(size_t)0xffff) && - (req / n_elements != elem_size)) - req = MAX_SIZE_T; /* force downstream failure on overflow */ - } - mem = internal_malloc(ms, req); - if (mem != 0 && calloc_must_clear(mem2chunk(mem))) - memset(mem, 0, req); - return mem; -} - -void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) { - if (oldmem == 0) - return mspace_malloc(msp, bytes); -#ifdef REALLOC_ZERO_BYTES_FREES - if (bytes == 0) { - mspace_free(msp, oldmem); - return 0; - } -#endif /* REALLOC_ZERO_BYTES_FREES */ - else { -#if FOOTERS - mchunkptr p = mem2chunk(oldmem); - mstate ms = get_mstate_for(p); -#else /* FOOTERS */ - mstate ms = (mstate)msp; -#endif /* FOOTERS */ - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - return internal_realloc(ms, oldmem, bytes); - } -} - -void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - return internal_memalign(ms, alignment, bytes); -} - -void** mspace_independent_calloc(mspace msp, size_t n_elements, - size_t elem_size, void* chunks[]) { - size_t sz = elem_size; /* serves as 1-element array */ - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - return ialloc(ms, n_elements, &sz, 3, chunks); -} - -void** mspace_independent_comalloc(mspace msp, size_t n_elements, - size_t sizes[], void* chunks[]) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - return ialloc(ms, n_elements, sizes, 0, chunks); -} - -int mspace_trim(mspace msp, size_t pad) { - int result = 0; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - if (!PREACTION(ms)) { - result = sys_trim(ms, pad); - POSTACTION(ms); - } - } - else { - USAGE_ERROR_ACTION(ms,ms); - } - return result; -} - -void mspace_malloc_stats(mspace msp) { - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - internal_malloc_stats(ms); - } - else { - USAGE_ERROR_ACTION(ms,ms); - } -} - -size_t mspace_footprint(mspace msp) { - size_t result = 0; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - result = ms->footprint; - } - else { - USAGE_ERROR_ACTION(ms,ms); - } - return result; -} - - -size_t mspace_max_footprint(mspace msp) { - size_t result = 0; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - result = ms->max_footprint; - } - else { - USAGE_ERROR_ACTION(ms,ms); - } - return result; -} - - -#if !NO_MALLINFO -struct mallinfo mspace_mallinfo(mspace msp) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - } - return internal_mallinfo(ms); -} -#endif /* NO_MALLINFO */ - -size_t mspace_usable_size(void* mem) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); - if (is_inuse(p)) - return chunksize(p) - overhead_for(p); - } - return 0; -} - -int mspace_mallopt(int param_number, int value) { - return change_mparam(param_number, value); -} - -#endif /* MSPACES */ - - -/* -------------------- Alternative MORECORE functions ------------------- */ - -/* - Guidelines for creating a custom version of MORECORE: - - * For best performance, MORECORE should allocate in multiples of pagesize. - * MORECORE may allocate more memory than requested. (Or even less, - but this will usually result in a malloc failure.) - * MORECORE must not allocate memory when given argument zero, but - instead return one past the end address of memory from previous - nonzero call. - * For best performance, consecutive calls to MORECORE with positive - arguments should return increasing addresses, indicating that - space has been contiguously extended. - * Even though consecutive calls to MORECORE need not return contiguous - addresses, it must be OK for malloc'ed chunks to span multiple - regions in those cases where they do happen to be contiguous. - * MORECORE need not handle negative arguments -- it may instead - just return MFAIL when given negative arguments. - Negative arguments are always multiples of pagesize. MORECORE - must not misinterpret negative args as large positive unsigned - args. You can suppress all such calls from even occurring by defining - MORECORE_CANNOT_TRIM, - - As an example alternative MORECORE, here is a custom allocator - kindly contributed for pre-OSX macOS. It uses virtually but not - necessarily physically contiguous non-paged memory (locked in, - present and won't get swapped out). You can use it by uncommenting - this section, adding some #includes, and setting up the appropriate - defines above: - - #define MORECORE osMoreCore - - There is also a shutdown routine that should somehow be called for - cleanup upon program exit. - - #define MAX_POOL_ENTRIES 100 - #define MINIMUM_MORECORE_SIZE (64 * 1024U) - static int next_os_pool; - void *our_os_pools[MAX_POOL_ENTRIES]; - - void *osMoreCore(int size) - { - void *ptr = 0; - static void *sbrk_top = 0; - - if (size > 0) - { - if (size < MINIMUM_MORECORE_SIZE) - size = MINIMUM_MORECORE_SIZE; - if (CurrentExecutionLevel() == kTaskLevel) - ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0); - if (ptr == 0) - { - return (void *) MFAIL; - } - // save ptrs so they can be freed during cleanup - our_os_pools[next_os_pool] = ptr; - next_os_pool++; - ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK); - sbrk_top = (char *) ptr + size; - return ptr; - } - else if (size < 0) - { - // we don't currently support shrink behavior - return (void *) MFAIL; - } - else - { - return sbrk_top; - } - } - - // cleanup any allocated memory pools - // called as last thing before shutting down driver - - void osCleanupMem(void) - { - void **ptr; - - for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++) - if (*ptr) - { - PoolDeallocate(*ptr); - *ptr = 0; - } - } - -*/ - - -/* ----------------------------------------------------------------------- -History: - V2.8.4 Wed May 27 09:56:23 2009 Doug Lea (dl at gee) - * Use zeros instead of prev foot for is_mmapped - * Add mspace_track_large_chunks; thanks to Jean Brouwers - * Fix set_inuse in internal_realloc; thanks to Jean Brouwers - * Fix insufficient sys_alloc padding when using 16byte alignment - * Fix bad error check in mspace_footprint - * Adaptations for ptmalloc; thanks to Wolfram Gloger. - * Reentrant spin locks; thanks to Earl Chew and others - * Win32 improvements; thanks to Niall Douglas and Earl Chew - * Add NO_SEGMENT_TRAVERSAL and MAX_RELEASE_CHECK_RATE options - * Extension hook in malloc_state - * Various small adjustments to reduce warnings on some compilers - * Various configuration extensions/changes for more platforms. Thanks - to all who contributed these. - - V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee) - * Add max_footprint functions - * Ensure all appropriate literals are size_t - * Fix conditional compilation problem for some #define settings - * Avoid concatenating segments with the one provided - in create_mspace_with_base - * Rename some variables to avoid compiler shadowing warnings - * Use explicit lock initialization. - * Better handling of sbrk interference. - * Simplify and fix segment insertion, trimming and mspace_destroy - * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x - * Thanks especially to Dennis Flanagan for help on these. - - V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee) - * Fix memalign brace error. - - V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee) - * Fix improper #endif nesting in C++ - * Add explicit casts needed for C++ - - V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee) - * Use trees for large bins - * Support mspaces - * Use segments to unify sbrk-based and mmap-based system allocation, - removing need for emulation on most platforms without sbrk. - * Default safety checks - * Optional footer checks. Thanks to William Robertson for the idea. - * Internal code refactoring - * Incorporate suggestions and platform-specific changes. - Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas, - Aaron Bachmann, Emery Berger, and others. - * Speed up non-fastbin processing enough to remove fastbins. - * Remove useless cfree() to avoid conflicts with other apps. - * Remove internal memcpy, memset. Compilers handle builtins better. - * Remove some options that no one ever used and rename others. - - V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) - * Fix malloc_state bitmap array misdeclaration - - V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee) - * Allow tuning of FIRST_SORTED_BIN_SIZE - * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte. - * Better detection and support for non-contiguousness of MORECORE. - Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger - * Bypass most of malloc if no frees. Thanks To Emery Berger. - * Fix freeing of old top non-contiguous chunk im sysmalloc. - * Raised default trim and map thresholds to 256K. - * Fix mmap-related #defines. Thanks to Lubos Lunak. - * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield. - * Branch-free bin calculation - * Default trim and mmap thresholds now 256K. - - V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee) - * Introduce independent_comalloc and independent_calloc. - Thanks to Michael Pachos for motivation and help. - * Make optional .h file available - * Allow > 2GB requests on 32bit systems. - * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>. - Thanks also to Andreas Mueller <a.mueller at paradatec.de>, - and Anonymous. - * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for - helping test this.) - * memalign: check alignment arg - * realloc: don't try to shift chunks backwards, since this - leads to more fragmentation in some programs and doesn't - seem to help in any others. - * Collect all cases in malloc requiring system memory into sysmalloc - * Use mmap as backup to sbrk - * Place all internal state in malloc_state - * Introduce fastbins (although similar to 2.5.1) - * Many minor tunings and cosmetic improvements - * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK - * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS - Thanks to Tony E. Bennett <tbennett@nvidia.com> and others. - * Include errno.h to support default failure action. - - V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee) - * return null for negative arguments - * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com> - * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h' - (e.g. WIN32 platforms) - * Cleanup header file inclusion for WIN32 platforms - * Cleanup code to avoid Microsoft Visual C++ compiler complaints - * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing - memory allocation routines - * Set 'malloc_getpagesize' for WIN32 platforms (needs more work) - * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to - usage of 'assert' in non-WIN32 code - * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to - avoid infinite loop - * Always call 'fREe()' rather than 'free()' - - V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee) - * Fixed ordering problem with boundary-stamping - - V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee) - * Added pvalloc, as recommended by H.J. Liu - * Added 64bit pointer support mainly from Wolfram Gloger - * Added anonymously donated WIN32 sbrk emulation - * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen - * malloc_extend_top: fix mask error that caused wastage after - foreign sbrks - * Add linux mremap support code from HJ Liu - - V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee) - * Integrated most documentation with the code. - * Add support for mmap, with help from - Wolfram Gloger (Gloger@lrz.uni-muenchen.de). - * Use last_remainder in more cases. - * Pack bins using idea from colin@nyx10.cs.du.edu - * Use ordered bins instead of best-fit threshhold - * Eliminate block-local decls to simplify tracing and debugging. - * Support another case of realloc via move into top - * Fix error occuring when initial sbrk_base not word-aligned. - * Rely on page size for units instead of SBRK_UNIT to - avoid surprises about sbrk alignment conventions. - * Add mallinfo, mallopt. Thanks to Raymond Nijssen - (raymond@es.ele.tue.nl) for the suggestion. - * Add `pad' argument to malloc_trim and top_pad mallopt parameter. - * More precautions for cases where other routines call sbrk, - courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de). - * Added macros etc., allowing use in linux libc from - H.J. Lu (hjl@gnu.ai.mit.edu) - * Inverted this history list - - V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee) - * Re-tuned and fixed to behave more nicely with V2.6.0 changes. - * Removed all preallocation code since under current scheme - the work required to undo bad preallocations exceeds - the work saved in good cases for most test programs. - * No longer use return list or unconsolidated bins since - no scheme using them consistently outperforms those that don't - given above changes. - * Use best fit for very large chunks to prevent some worst-cases. - * Added some support for debugging - - V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee) - * Removed footers when chunks are in use. Thanks to - Paul Wilson (wilson@cs.texas.edu) for the suggestion. - - V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee) - * Added malloc_trim, with help from Wolfram Gloger - (wmglo@Dent.MED.Uni-Muenchen.DE). - - V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g) - - V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g) - * realloc: try to expand in both directions - * malloc: swap order of clean-bin strategy; - * realloc: only conditionally expand backwards - * Try not to scavenge used bins - * Use bin counts as a guide to preallocation - * Occasionally bin return list chunks in first scan - * Add a few optimizations from colin@nyx10.cs.du.edu - - V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g) - * faster bin computation & slightly different binning - * merged all consolidations to one part of malloc proper - (eliminating old malloc_find_space & malloc_clean_bin) - * Scan 2 returns chunks (not just 1) - * Propagate failure in realloc if malloc returns 0 - * Add stuff to allow compilation on non-ANSI compilers - from kpv@research.att.com - - V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu) - * removed potential for odd address access in prev_chunk - * removed dependency on getpagesize.h - * misc cosmetics and a bit more internal documentation - * anticosmetics: mangled names in macros to evade debugger strangeness - * tested on sparc, hp-700, dec-mips, rs6000 - with gcc & native cc (hp, dec only) allowing - Detlefs & Zorn comparison study (in SIGPLAN Notices.) - - Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu) - * Based loosely on libg++-1.2X malloc. (It retains some of the overall - structure of old version, but most details differ.) - -*/ - -#endif diff --git a/drivers/nedmalloc/memory_pool_static_nedmalloc.cpp b/drivers/nedmalloc/memory_pool_static_nedmalloc.cpp deleted file mode 100644 index 21da056f07..0000000000 --- a/drivers/nedmalloc/memory_pool_static_nedmalloc.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/*************************************************************************/ -/* memory_pool_static_nedmalloc.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifdef NEDMALLOC_ENABLED - -// -// C++ Implementation: memory_static_malloc -// -// Description: -// -// -// Author: Juan Linietsky <red@lunatea>, (C) 2006 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "memory_pool_static_nedmalloc.h" -#include "error_macros.h" -#include "os/memory.h" -#include <stdlib.h> -#include <stdio.h> -#include "os/copymem.h" -#include "os/os.h" - -#include "nedmalloc.h" - -/** - * NOTE NOTE NOTE NOTE - * in debug mode, this appends the memory size before the allocated, returned pointer - * so BE CAREFUL! - */ - -void* MemoryPoolStaticNedMalloc::alloc(size_t p_bytes,const char *p_description) { - - ERR_FAIL_COND_V(p_bytes==0,0); - - MutexLock lock(mutex); - - void *mem=nedalloc::nedmalloc(p_bytes); - - ERR_FAIL_COND_V(!mem,0); //out of memory, or unreasonable request - return mem; -} - - -void* MemoryPoolStaticNedMalloc::realloc(void *p_memory,size_t p_bytes) { - - if (p_memory==NULL) { - - return alloc( p_bytes ); - } - - if (p_bytes<=0) { - - this->free(p_memory); - ERR_FAIL_COND_V( p_bytes < 0 , NULL ); - return NULL; - } - - MutexLock lock(mutex); - - return nedalloc::nedrealloc( p_memory, p_bytes ); -} - -void MemoryPoolStaticNedMalloc::free(void *p_ptr) { - - MutexLock lock(mutex); - - ERR_FAIL_COND(p_ptr==0); - - nedalloc::nedfree(p_ptr); -} - - -size_t MemoryPoolStaticNedMalloc::get_available_mem() const { - - return 0xffffffff; -} - -size_t MemoryPoolStaticNedMalloc::get_total_usage() { - - return nedalloc::nedmalloc_footprint(); -} - -/* Most likely available only if memory debugger was compiled in */ -int MemoryPoolStaticNedMalloc::get_alloc_count() { - - return 0; -} -void * MemoryPoolStaticNedMalloc::get_alloc_ptr(int p_alloc_idx) { - - return 0; -} -const char* MemoryPoolStaticNedMalloc::get_alloc_description(int p_alloc_idx) { - - - return ""; -} -size_t MemoryPoolStaticNedMalloc::get_alloc_size(int p_alloc_idx) { - - return 0; -} - - -void MemoryPoolStaticNedMalloc::debug_print_all_memory() { - - nedalloc::nedmalloc_stats(); -} - -MemoryPoolStaticNedMalloc::MemoryPoolStaticNedMalloc() { - - mutex=NULL; -#ifndef NO_THREADS - - mutex=Mutex::create(); // at this point, this should work -#endif - -} - - -MemoryPoolStaticNedMalloc::~MemoryPoolStaticNedMalloc() { - - Mutex *old_mutex=mutex; - mutex=NULL; - if (old_mutex) - memdelete(old_mutex); - -#ifdef DEBUG_ENABLED - - if (OS::get_singleton()->is_stdout_verbose()) - nedalloc::nedmalloc_stats(); - -#endif -} - - -#endif - diff --git a/drivers/nedmalloc/memory_pool_static_nedmalloc.h b/drivers/nedmalloc/memory_pool_static_nedmalloc.h deleted file mode 100644 index 0033353a67..0000000000 --- a/drivers/nedmalloc/memory_pool_static_nedmalloc.h +++ /dev/null @@ -1,77 +0,0 @@ -/*************************************************************************/ -/* memory_pool_static_nedmalloc.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifdef NEDMALLOC_ENABLED - -// -// C++ Interface: memory_static_malloc -// -// Description: -// -// -// Author: Juan Linietsky <red@lunatea>, (C) 2006 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef MEMORY_POOL_STATIC_NEDMALLOC_H -#define MEMORY_POOL_STATIC_NEDMALLOC_H - -#include "os/memory_pool_static.h" -#include "os/mutex.h" -/** - @author Juan Linietsky <red@lunatea> -*/ -class MemoryPoolStaticNedMalloc : public MemoryPoolStatic { - - Mutex *mutex; - -public: - - void* alloc(size_t p_bytes,const char *p_description=""); ///< Pointer in p_description shold be to a const char const like "hello" - void* realloc(void *p_memory,size_t p_bytes); ///< Pointer in - void free(void *p_ptr); ///< Pointer in p_description shold be to a const char const - virtual size_t get_available_mem() const; - virtual size_t get_total_usage(); - - /* Most likely available only if memory debugger was compiled in */ - virtual int get_alloc_count(); - virtual void * get_alloc_ptr(int p_alloc_idx); - virtual const char* get_alloc_description(int p_alloc_idx); - virtual size_t get_alloc_size(int p_alloc_idx); - - virtual void debug_print_all_memory(); - - MemoryPoolStaticNedMalloc(); - ~MemoryPoolStaticNedMalloc(); - -}; - -#endif - -#endif diff --git a/drivers/nedmalloc/nedmalloc.cpp b/drivers/nedmalloc/nedmalloc.cpp deleted file mode 100644 index 9aac277a2a..0000000000 --- a/drivers/nedmalloc/nedmalloc.cpp +++ /dev/null @@ -1,1467 +0,0 @@ -#ifdef NEDMALLOC_ENABLED -/* Alternative malloc implementation for multiple threads without -lock contention based on dlmalloc. (C) 2005-2009 Niall Douglas - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - -#ifdef _MSC_VER -/* Enable full aliasing on MSVC */ -/*#pragma optimize("a", on)*/ -#pragma warning(push) -#pragma warning(disable:4100) /* unreferenced formal parameter */ -#pragma warning(disable:4127) /* conditional expression is constant */ -#pragma warning(disable:4706) /* assignment within conditional expression */ -#endif - -/*#define ENABLE_TOLERANT_NEDMALLOC 1*/ -/*#define ENABLE_FAST_HEAP_DETECTION 1*/ -/*#define NEDMALLOC_DEBUG 1*/ - -/*#define FULLSANITYCHECKS*/ -/* If link time code generation is on, don't force or prevent inlining */ -#if defined(_MSC_VER) && defined(NEDMALLOC_DLL_EXPORTS) -#define FORCEINLINE -#define NOINLINE -#endif - - -#include "nedmalloc.h" -#ifdef WIN32 - #include <malloc.h> - #include <stddef.h> -#endif -#if USE_ALLOCATOR==1 - #define MSPACES 1 - #define ONLY_MSPACES 1 -#endif -#define USE_DL_PREFIX 1 -#ifndef USE_LOCKS - #define USE_LOCKS 1 -#endif -#define FOOTERS 1 /* Need to enable footers so frees lock the right mspace */ -#ifndef NEDMALLOC_DEBUG - #if defined(DEBUG) || defined(_DEBUG) - #define NEDMALLOC_DEBUG 1 - #else - #define NEDMALLOC_DEBUG 0 - #endif -#endif -/* We need to consistently define DEBUG=0|1, _DEBUG and NDEBUG for dlmalloc */ -#undef DEBUG -#undef _DEBUG -#if NEDMALLOC_DEBUG - #define _DEBUG - #define DEBUG 1 -#else - #define DEBUG 0 -#endif -#ifdef NDEBUG /* Disable assert checking on release builds */ - #undef DEBUG - #undef _DEBUG -#endif -/* The default of 64Kb means we spend too much time kernel-side */ -#ifndef DEFAULT_GRANULARITY -#define DEFAULT_GRANULARITY (1*1024*1024) -#if DEBUG -#define DEFAULT_GRANULARITY_ALIGNED -#endif -#endif -/*#define USE_SPIN_LOCKS 0*/ - - -#include "malloc.c.h" -#ifdef NDEBUG /* Disable assert checking on release builds */ - #undef DEBUG -#elif !NEDMALLOC_DEBUG - #ifdef __GNUC__ - #warning DEBUG is defined so allocator will run with assert checking! Define NDEBUG to run at full speed. - #elif defined(_MSC_VER) - #pragma message(__FILE__ ": WARNING: DEBUG is defined so allocator will run with assert checking! Define NDEBUG to run at full speed.") - #endif -#endif - -/* The maximum concurrent threads in a pool possible */ -#ifndef MAXTHREADSINPOOL -#define MAXTHREADSINPOOL 16 -#endif -/* The maximum number of threadcaches which can be allocated */ -#ifndef THREADCACHEMAXCACHES -#define THREADCACHEMAXCACHES 256 -#endif -/* The maximum size to be allocated from the thread cache */ -#ifndef THREADCACHEMAX -#define THREADCACHEMAX 8192 -#endif -#if 0 -/* The number of cache entries for finer grained bins. This is (topbitpos(THREADCACHEMAX)-4)*2 */ -#define THREADCACHEMAXBINS ((13-4)*2) -#else -/* The number of cache entries. This is (topbitpos(THREADCACHEMAX)-4) */ -#define THREADCACHEMAXBINS (13-4) -#endif -/* Point at which the free space in a thread cache is garbage collected */ -#ifndef THREADCACHEMAXFREESPACE -#define THREADCACHEMAXFREESPACE (512*1024) -#endif - - -#ifdef WIN32 - #define TLSVAR DWORD - #define TLSALLOC(k) (*(k)=TlsAlloc(), TLS_OUT_OF_INDEXES==*(k)) - #define TLSFREE(k) (!TlsFree(k)) - #define TLSGET(k) TlsGetValue(k) - #define TLSSET(k, a) (!TlsSetValue(k, a)) - #ifdef DEBUG -static LPVOID ChkedTlsGetValue(DWORD idx) -{ - LPVOID ret=TlsGetValue(idx); - assert(S_OK==GetLastError()); - return ret; -} - #undef TLSGET - #define TLSGET(k) ChkedTlsGetValue(k) - #endif -#else - #define TLSVAR pthread_key_t - #define TLSALLOC(k) pthread_key_create(k, 0) - #define TLSFREE(k) pthread_key_delete(k) - #define TLSGET(k) pthread_getspecific(k) - #define TLSSET(k, a) pthread_setspecific(k, a) -#endif - -#if defined(__cplusplus) -#if !defined(NO_NED_NAMESPACE) -namespace nedalloc { -#else -extern "C" { -#endif -#endif - -#if USE_ALLOCATOR==0 -static void *unsupported_operation(const char *opname) THROWSPEC -{ - fprintf(stderr, "nedmalloc: The operation %s is not supported under this build configuration\n", opname); - abort(); - return 0; -} -static size_t mspacecounter=(size_t) 0xdeadbeef; -#endif -#ifndef ENABLE_FAST_HEAP_DETECTION -static void *RESTRICT leastusedaddress; -static size_t largestusedblock; -#endif - -static FORCEINLINE void *CallMalloc(void *RESTRICT mspace, size_t size, size_t alignment) THROWSPEC -{ - void *RESTRICT ret=0; - size_t _alignment=alignment; -#if USE_MAGIC_HEADERS - size_t *_ret=0; - size+=alignment+3*sizeof(size_t); - _alignment=0; -#endif -#if USE_ALLOCATOR==0 - ret=_alignment ? -#ifdef _MSC_VER - /* This is the MSVCRT equivalent */ - _aligned_malloc(size, _alignment) -#elif defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) - /* This is the glibc/ptmalloc2/dlmalloc/BSD libc equivalent. */ - memalign(_alignment, size) -#else -#error Cannot aligned allocate with the memory allocator of an unknown system! -#endif - : malloc(size); -#elif USE_ALLOCATOR==1 - ret=_alignment ? mspace_memalign((mstate) mspace, _alignment, size) : mspace_malloc((mstate) mspace, size); -#ifndef ENABLE_FAST_HEAP_DETECTION - if(ret) - { - size_t truesize=chunksize(mem2chunk(ret)); - if(!leastusedaddress || (void *)((mstate) mspace)->least_addr<leastusedaddress) leastusedaddress=(void *)((mstate) mspace)->least_addr; - if(!largestusedblock || truesize>largestusedblock) largestusedblock=(truesize+mparams.page_size) & ~(mparams.page_size-1); - } -#endif -#endif - if(!ret) return 0; -#if USE_MAGIC_HEADERS - _ret=(size_t *) ret; - ret=(void *)(_ret+3); - if(alignment) ret=(void *)(((size_t) ret+alignment-1)&~(alignment-1)); - for(; _ret<(size_t *)ret-2; _ret++) *_ret=*(size_t *)"NEDMALOC"; - _ret[0]=(size_t) mspace; - _ret[1]=size-3*sizeof(size_t); -#endif - return ret; -} - -static FORCEINLINE void *CallCalloc(void *RESTRICT mspace, size_t size, size_t alignment) THROWSPEC -{ - void *RESTRICT ret=0; -#if USE_MAGIC_HEADERS - size_t *_ret=0; - size+=alignment+3*sizeof(size_t); -#endif -#if USE_ALLOCATOR==0 - ret=calloc(1, size); -#elif USE_ALLOCATOR==1 - ret=mspace_calloc((mstate) mspace, 1, size); -#ifndef ENABLE_FAST_HEAP_DETECTION - if(ret) - { - size_t truesize=chunksize(mem2chunk(ret)); - if(!leastusedaddress || (void *)((mstate) mspace)->least_addr<leastusedaddress) leastusedaddress=(void *)((mstate) mspace)->least_addr; - if(!largestusedblock || truesize>largestusedblock) largestusedblock=(truesize+mparams.page_size) & ~(mparams.page_size-1); - } -#endif -#endif - if(!ret) return 0; -#if USE_MAGIC_HEADERS - _ret=(size_t *) ret; - ret=(void *)(_ret+3); - if(alignment) ret=(void *)(((size_t) ret+alignment-1)&~(alignment-1)); - for(; _ret<(size_t *)ret-2; _ret++) *_ret=*(size_t *) "NEDMALOC"; - _ret[0]=(size_t) mspace; - _ret[1]=size-3*sizeof(size_t); -#endif - return ret; -} - -static FORCEINLINE void *CallRealloc(void *RESTRICT mspace, void *RESTRICT mem, int isforeign, size_t oldsize, size_t newsize) THROWSPEC -{ - void *RESTRICT ret=0; -#if USE_MAGIC_HEADERS - mstate oldmspace=0; - size_t *_ret=0, *_mem=(size_t *) mem-3; -#endif - if(isforeign) - { /* Transfer */ -#if USE_MAGIC_HEADERS - assert(_mem[0]!=*(size_t *) "NEDMALOC"); -#endif - if((ret=CallMalloc(mspace, newsize, 0))) - { -#if defined(DEBUG) - printf("*** nedmalloc frees system allocated block %p\n", mem); -#endif - memcpy(ret, mem, oldsize<newsize ? oldsize : newsize); - free(mem); - } - return ret; - } -#if USE_MAGIC_HEADERS - assert(_mem[0]==*(size_t *) "NEDMALOC"); - newsize+=3*sizeof(size_t); - oldmspace=(mstate) _mem[1]; - assert(oldsize>=_mem[2]); - for(; *_mem==*(size_t *) "NEDMALOC"; *_mem--=*(size_t *) "nedmaloc"); - mem=(void *)(++_mem); -#endif -#if USE_ALLOCATOR==0 - ret=realloc(mem, newsize); -#elif USE_ALLOCATOR==1 - ret=mspace_realloc((mstate) mspace, mem, newsize); -#ifndef ENABLE_FAST_HEAP_DETECTION - if(ret) - { - size_t truesize=chunksize(mem2chunk(ret)); - if(!largestusedblock || truesize>largestusedblock) largestusedblock=(truesize+mparams.page_size) & ~(mparams.page_size-1); - } -#endif -#endif - if(!ret) - { /* Put it back the way it was */ -#if USE_MAGIC_HEADERS - for(; *_mem==0; *_mem++=*(size_t *) "NEDMALOC"); -#endif - return 0; - } -#if USE_MAGIC_HEADERS - _ret=(size_t *) ret; - ret=(void *)(_ret+3); - for(; _ret<(size_t *)ret-2; _ret++) *_ret=*(size_t *) "NEDMALOC"; - _ret[0]=(size_t) mspace; - _ret[1]=newsize-3*sizeof(size_t); -#endif - return ret; -} - -static FORCEINLINE void CallFree(void *RESTRICT mspace, void *RESTRICT mem, int isforeign) THROWSPEC -{ -#if USE_MAGIC_HEADERS - mstate oldmspace=0; - size_t *_mem=(size_t *) mem-3, oldsize=0; -#endif - if(isforeign) - { -#if USE_MAGIC_HEADERS - assert(_mem[0]!=*(size_t *) "NEDMALOC"); -#endif -#if defined(DEBUG) - printf("*** nedmalloc frees system allocated block %p\n", mem); -#endif - free(mem); - return; - } -#if USE_MAGIC_HEADERS - assert(_mem[0]==*(size_t *) "NEDMALOC"); - oldmspace=(mstate) _mem[1]; - oldsize=_mem[2]; - for(; *_mem==*(size_t *) "NEDMALOC"; *_mem--=*(size_t *) "nedmaloc"); - mem=(void *)(++_mem); -#endif -#if USE_ALLOCATOR==0 - free(mem); -#elif USE_ALLOCATOR==1 - mspace_free((mstate) mspace, mem); -#endif -} - -static NEDMALLOCNOALIASATTR mstate nedblkmstate(void *RESTRICT mem) THROWSPEC -{ - if(mem) - { -#if USE_MAGIC_HEADERS - size_t *_mem=(size_t *) mem-3; - if(_mem[0]==*(size_t *) "NEDMALOC") - { - return (mstate) _mem[1]; - } - else return 0; -#else -#if USE_ALLOCATOR==0 - /* Fail everything */ - return 0; -#elif USE_ALLOCATOR==1 -#ifdef ENABLE_FAST_HEAP_DETECTION -#ifdef WIN32 - /* On Windows for RELEASE both x86 and x64 the NT heap precedes each block with an eight byte header - which looks like: - normal: 4 bytes of size, 4 bytes of [char < 64, char < 64, char < 64 bit 0 always set, char random ] - mmaped: 4 bytes of size 4 bytes of [zero, zero, 0xb, zero ] - - On Windows for DEBUG both x86 and x64 the preceding four bytes is always 0xfdfdfdfd (no man's land). - */ -#pragma pack(push, 1) - struct _HEAP_ENTRY - { - USHORT Size; - USHORT PreviousSize; - UCHAR Cookie; /* SegmentIndex */ - UCHAR Flags; /* always bit 0 (HEAP_ENTRY_BUSY). bit 1=(HEAP_ENTRY_EXTRA_PRESENT), bit 2=normal block (HEAP_ENTRY_FILL_PATTERN), bit 3=mmap block (HEAP_ENTRY_VIRTUAL_ALLOC). Bit 4 (HEAP_ENTRY_LAST_ENTRY) could be set */ - UCHAR UnusedBytes; - UCHAR SmallTagIndex; /* fastbin index. Always one of 0x02, 0x03, 0x04 < 0x80 */ - } *RESTRICT he=((struct _HEAP_ENTRY *) mem)-1; -#pragma pack(pop) - unsigned int header=((unsigned int *)mem)[-1], mask1=0x8080E100, result1, mask2=0xFFFFFF06, result2; - result1=header & mask1; /* Positive testing for NT heap */ - result2=header & mask2; /* Positive testing for dlmalloc */ - if(result1==0x00000100 && result2!=0x00000102) - { /* This is likely a NT heap block */ - return 0; - } -#endif -#ifdef __linux__ - /* On Linux glibc uses ptmalloc2 (really dlmalloc) just as we do, but prev_foot contains rubbish - when the preceding block is allocated because ptmalloc2 finds the local mstate by rounding the ptr - down to the nearest megabyte. It's like dlmalloc with FOOTERS disabled. */ - mchunkptr p=mem2chunk(mem); - mstate fm=get_mstate_for(p); - /* If it's a ptmalloc2 block, fm is likely to be some crazy value */ - if(!is_aligned(fm)) return 0; - if((size_t)mem-(size_t)fm>=(size_t)1<<(SIZE_T_BITSIZE-1)) return 0; - if(ok_magic(fm)) - return fm; - else - return 0; - if(1) { } -#endif - else - { - mchunkptr p=mem2chunk(mem); - mstate fm=get_mstate_for(p); - assert(ok_magic(fm)); /* If this fails, someone tried to free a block twice */ - if(ok_magic(fm)) - return fm; - } -#else -//#ifdef WIN32 -// __try -//#endif - { - /* We try to return zero here if it isn't one of our own blocks, however - the current block annotation scheme used by dlmalloc makes it impossible - to be absolutely sure of avoiding a segfault. - - mchunkptr->prev_foot = mem-(2*size_t) = mstate ^ mparams.magic for PRECEDING block; - mchunkptr->head = mem-(1*size_t) = 8 multiple size of this block with bottom three bits = FLAG_BITS - FLAG_BITS = bit 0 is CINUSE (currently in use unless is mmap), bit 1 is PINUSE (previous block currently - in use unless mmap), bit 2 is UNUSED and currently is always zero. - */ - register void *RESTRICT leastusedaddress_=leastusedaddress; /* Cache these to avoid register reloading */ - register size_t largestusedblock_=largestusedblock; - if(!is_aligned(mem)) return 0; /* Would fail very rarely as all allocators return aligned blocks */ - if(mem<leastusedaddress_) return 0; /* Simple but effective */ - { - mchunkptr p=mem2chunk(mem); - mstate fm=0; - int ismmapped=is_mmapped(p); - if((!ismmapped && !is_inuse(p)) || (p->head & FLAG4_BIT)) return 0; - /* Reduced uncertainty by 0.5^2 = 25.0% */ - /* size should never exceed largestusedblock */ - if(chunksize(p)>largestusedblock_) return 0; - /* Reduced uncertainty by a minimum of 0.5^3 = 12.5%, maximum 0.5^16 = 0.0015% */ - /* Having sanity checked prev_foot and head, check next block */ - if(!ismmapped && (!next_pinuse(p) || (next_chunk(p)->head & FLAG4_BIT))) return 0; - /* Reduced uncertainty by 0.5^5 = 3.13% or 0.5^18 = 0.00038% */ - #if 0 - /* If previous block is free, check that its next block pointer equals us */ - if(!ismmapped && !pinuse(p)) - if(next_chunk(prev_chunk(p))!=p) return 0; - /* We could start comparing prev_foot's for similarity but it starts getting slow. */ - #endif - fm = get_mstate_for(p); - if(!is_aligned(fm) || (void *)fm<leastusedaddress_) return 0; - if((size_t)mem-(size_t)fm>=(size_t)1<<(SIZE_T_BITSIZE-1)) return 0; - assert(ok_magic(fm)); /* If this fails, someone tried to free a block twice */ - if(ok_magic(fm)) - return fm; - } - } -//#ifdef WIN32 -// __except(1) { } -//#endif -#endif -#endif -#endif - } - return 0; -} -NEDMALLOCNOALIASATTR size_t nedblksize(int *RESTRICT isforeign, void *RESTRICT mem) THROWSPEC -{ - if(mem) - { - if(isforeign) *isforeign=1; -#if USE_MAGIC_HEADERS - { - size_t *_mem=(size_t *) mem-3; - if(_mem[0]==*(size_t *) "NEDMALOC") - { - mstate mspace=(mstate) _mem[1]; - size_t size=_mem[2]; - if(isforeign) *isforeign=0; - return size; - } - } -#elif USE_ALLOCATOR==1 - if(nedblkmstate(mem)) - { - mchunkptr p=mem2chunk(mem); - if(isforeign) *isforeign=0; - return chunksize(p)-overhead_for(p); - } -#ifdef DEBUG - else - { - int a=1; /* Set breakpoints here if needed */ - } -#endif -#endif -#if defined(ENABLE_TOLERANT_NEDMALLOC) || USE_ALLOCATOR==0 -#ifdef _MSC_VER - /* This is the MSVCRT equivalent */ - return _msize(mem); -#elif defined(__linux__) - /* This is the glibc/ptmalloc2/dlmalloc equivalent. */ - return malloc_usable_size(mem); -#elif defined(__FreeBSD__) || defined(__APPLE__) - /* This is the BSD libc equivalent. */ - return malloc_size(mem); -#else -#error Cannot tolerate the memory allocator of an unknown system! -#endif -#endif - } - return 0; -} - -NEDMALLOCNOALIASATTR void nedsetvalue(void *v) THROWSPEC { nedpsetvalue((nedpool *) 0, v); } -NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedmalloc(size_t size) THROWSPEC { return nedpmalloc((nedpool *) 0, size); } -NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedcalloc(size_t no, size_t size) THROWSPEC { return nedpcalloc((nedpool *) 0, no, size); } -NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedrealloc(void *mem, size_t size) THROWSPEC { return nedprealloc((nedpool *) 0, mem, size); } -NEDMALLOCNOALIASATTR void nedfree(void *mem) THROWSPEC { nedpfree((nedpool *) 0, mem); } -NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedmemalign(size_t alignment, size_t bytes) THROWSPEC { return nedpmemalign((nedpool *) 0, alignment, bytes); } -NEDMALLOCNOALIASATTR struct nedmallinfo nedmallinfo(void) THROWSPEC { return nedpmallinfo((nedpool *) 0); } -NEDMALLOCNOALIASATTR int nedmallopt(int parno, int value) THROWSPEC { return nedpmallopt((nedpool *) 0, parno, value); } -NEDMALLOCNOALIASATTR int nedmalloc_trim(size_t pad) THROWSPEC { return nedpmalloc_trim((nedpool *) 0, pad); } -void nedmalloc_stats() THROWSPEC { nedpmalloc_stats((nedpool *) 0); } -NEDMALLOCNOALIASATTR size_t nedmalloc_footprint() THROWSPEC { return nedpmalloc_footprint((nedpool *) 0); } -NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void **nedindependent_calloc(size_t elemsno, size_t elemsize, void **chunks) THROWSPEC { return nedpindependent_calloc((nedpool *) 0, elemsno, elemsize, chunks); } -NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void **nedindependent_comalloc(size_t elems, size_t *sizes, void **chunks) THROWSPEC { return nedpindependent_comalloc((nedpool *) 0, elems, sizes, chunks); } - -struct threadcacheblk_t; -typedef struct threadcacheblk_t threadcacheblk; -struct threadcacheblk_t -{ /* Keep less than 16 bytes on 32 bit systems and 32 bytes on 64 bit systems */ -#ifdef FULLSANITYCHECKS - unsigned int magic; -#endif - unsigned int lastUsed, size; - threadcacheblk *next, *prev; -}; -typedef struct threadcache_t -{ -#ifdef FULLSANITYCHECKS - unsigned int magic1; -#endif - int mymspace; /* Last mspace entry this thread used */ - long threadid; - unsigned int mallocs, frees, successes; - size_t freeInCache; /* How much free space is stored in this cache */ - threadcacheblk *bins[(THREADCACHEMAXBINS+1)*2]; -#ifdef FULLSANITYCHECKS - unsigned int magic2; -#endif -} threadcache; -struct nedpool_t -{ - MLOCK_T mutex; - void *uservalue; - int threads; /* Max entries in m to use */ - threadcache *caches[THREADCACHEMAXCACHES]; - TLSVAR mycache; /* Thread cache for this thread. 0 for unset, negative for use mspace-1 directly, otherwise is cache-1 */ - mstate m[MAXTHREADSINPOOL+1]; /* mspace entries for this pool */ -}; -static nedpool syspool; - -static FORCEINLINE NEDMALLOCNOALIASATTR unsigned int size2binidx(size_t _size) THROWSPEC -{ /* 8=1000 16=10000 20=10100 24=11000 32=100000 48=110000 4096=1000000000000 */ - unsigned int topbit, size=(unsigned int)(_size>>4); - /* 16=1 20=1 24=1 32=10 48=11 64=100 96=110 128=1000 4096=100000000 */ - -#if defined(__GNUC__) - topbit = sizeof(size)*__CHAR_BIT__ - 1 - __builtin_clz(size); -#elif defined(_MSC_VER) && _MSC_VER>=1300 - { - unsigned long bsrTopBit; - - _BitScanReverse(&bsrTopBit, size); - - topbit = bsrTopBit; - } -#else -#if 0 - union { - unsigned asInt[2]; - double asDouble; - }; - int n; - - asDouble = (double)size + 0.5; - topbit = (asInt[!FOX_BIGENDIAN] >> 20) - 1023; -#else - { - unsigned int x=size; - x = x | (x >> 1); - x = x | (x >> 2); - x = x | (x >> 4); - x = x | (x >> 8); - x = x | (x >>16); - x = ~x; - x = x - ((x >> 1) & 0x55555555); - x = (x & 0x33333333) + ((x >> 2) & 0x33333333); - x = (x + (x >> 4)) & 0x0F0F0F0F; - x = x + (x << 8); - x = x + (x << 16); - topbit=31 - (x >> 24); - } -#endif -#endif - return topbit; -} - - -#ifdef FULLSANITYCHECKS -static void tcsanitycheck(threadcacheblk **ptr) THROWSPEC -{ - assert((ptr[0] && ptr[1]) || (!ptr[0] && !ptr[1])); - if(ptr[0] && ptr[1]) - { - assert(nedblksize(ptr[0])>=sizeof(threadcacheblk)); - assert(nedblksize(ptr[1])>=sizeof(threadcacheblk)); - assert(*(unsigned int *) "NEDN"==ptr[0]->magic); - assert(*(unsigned int *) "NEDN"==ptr[1]->magic); - assert(!ptr[0]->prev); - assert(!ptr[1]->next); - if(ptr[0]==ptr[1]) - { - assert(!ptr[0]->next); - assert(!ptr[1]->prev); - } - } -} -static void tcfullsanitycheck(threadcache *tc) THROWSPEC -{ - threadcacheblk **tcbptr=tc->bins; - int n; - for(n=0; n<=THREADCACHEMAXBINS; n++, tcbptr+=2) - { - threadcacheblk *b, *ob=0; - tcsanitycheck(tcbptr); - for(b=tcbptr[0]; b; ob=b, b=b->next) - { - assert(*(unsigned int *) "NEDN"==b->magic); - assert(!ob || ob->next==b); - assert(!ob || b->prev==ob); - } - } -} -#endif - -static NOINLINE void RemoveCacheEntries(nedpool *RESTRICT p, threadcache *RESTRICT tc, unsigned int age) THROWSPEC -{ -#ifdef FULLSANITYCHECKS - tcfullsanitycheck(tc); -#endif - if(tc->freeInCache) - { - threadcacheblk **tcbptr=tc->bins; - int n; - for(n=0; n<=THREADCACHEMAXBINS; n++, tcbptr+=2) - { - threadcacheblk **tcb=tcbptr+1; /* come from oldest end of list */ - /*tcsanitycheck(tcbptr);*/ - for(; *tcb && tc->frees-(*tcb)->lastUsed>=age; ) - { - threadcacheblk *f=*tcb; - size_t blksize=f->size; /*nedblksize(f);*/ - assert(blksize<=nedblksize(0, f)); - assert(blksize); -#ifdef FULLSANITYCHECKS - assert(*(unsigned int *) "NEDN"==(*tcb)->magic); -#endif - *tcb=(*tcb)->prev; - if(*tcb) - (*tcb)->next=0; - else - *tcbptr=0; - tc->freeInCache-=blksize; - assert((long) tc->freeInCache>=0); - CallFree(0, f, 0); - /*tcsanitycheck(tcbptr);*/ - } - } - } -#ifdef FULLSANITYCHECKS - tcfullsanitycheck(tc); -#endif -} -static void DestroyCaches(nedpool *RESTRICT p) THROWSPEC -{ - if(p->caches) - { - threadcache *tc; - int n; - for(n=0; n<THREADCACHEMAXCACHES; n++) - { - if((tc=p->caches[n])) - { - tc->frees++; - RemoveCacheEntries(p, tc, 0); - assert(!tc->freeInCache); - tc->mymspace=-1; - tc->threadid=0; - CallFree(0, tc, 0); - p->caches[n]=0; - } - } - } -} - -static NOINLINE threadcache *AllocCache(nedpool *RESTRICT p) THROWSPEC -{ - threadcache *tc=0; - int n, end; - ACQUIRE_LOCK(&p->mutex); - for(n=0; n<THREADCACHEMAXCACHES && p->caches[n]; n++); - if(THREADCACHEMAXCACHES==n) - { /* List exhausted, so disable for this thread */ - RELEASE_LOCK(&p->mutex); - return 0; - } - tc=p->caches[n]=(threadcache *) CallCalloc(p->m[0], sizeof(threadcache), 0); - if(!tc) - { - RELEASE_LOCK(&p->mutex); - return 0; - } -#ifdef FULLSANITYCHECKS - tc->magic1=*(unsigned int *)"NEDMALC1"; - tc->magic2=*(unsigned int *)"NEDMALC2"; -#endif - tc->threadid=(long)(size_t)CURRENT_THREAD; - for(end=0; p->m[end]; end++); - tc->mymspace=abs(tc->threadid) % end; - RELEASE_LOCK(&p->mutex); - if(TLSSET(p->mycache, (void *)(size_t)(n+1))) abort(); - return tc; -} - -static void *threadcache_malloc(nedpool *RESTRICT p, threadcache *RESTRICT tc, size_t *RESTRICT _size) THROWSPEC -{ - void *RESTRICT ret=0; - size_t size=*_size, blksize=0; - unsigned int bestsize; - unsigned int idx=size2binidx(size); - threadcacheblk *RESTRICT blk, **RESTRICT binsptr; -#ifdef FULLSANITYCHECKS - tcfullsanitycheck(tc); -#endif - /* Calculate best fit bin size */ - bestsize=1<<(idx+4); -#if 0 - /* Finer grained bin fit */ - idx<<=1; - if(size>bestsize) - { - idx++; - bestsize+=bestsize>>1; - } - if(size>bestsize) - { - idx++; - bestsize=1<<(4+(idx>>1)); - } -#else - if(size>bestsize) - { - idx++; - bestsize<<=1; - } -#endif - assert(bestsize>=size); - if(size<bestsize) size=bestsize; - assert(size<=THREADCACHEMAX); - assert(idx<=THREADCACHEMAXBINS); - binsptr=&tc->bins[idx*2]; - /* Try to match close, but move up a bin if necessary */ - blk=*binsptr; - if(!blk || blk->size<size) - { /* Bump it up a bin */ - if(idx<THREADCACHEMAXBINS) - { - idx++; - binsptr+=2; - blk=*binsptr; - } - } - if(blk) - { - blksize=blk->size; /*nedblksize(blk);*/ - assert(nedblksize(0, blk)>=blksize); - assert(blksize>=size); - if(blk->next) - blk->next->prev=0; - *binsptr=blk->next; - if(!*binsptr) - binsptr[1]=0; -#ifdef FULLSANITYCHECKS - blk->magic=0; -#endif - assert(binsptr[0]!=blk && binsptr[1]!=blk); - assert(nedblksize(0, blk)>=sizeof(threadcacheblk) && nedblksize(0, blk)<=THREADCACHEMAX+CHUNK_OVERHEAD); - /*printf("malloc: %p, %p, %p, %lu\n", p, tc, blk, (long) _size);*/ - ret=(void *) blk; - } - ++tc->mallocs; - if(ret) - { - assert(blksize>=size); - ++tc->successes; - tc->freeInCache-=blksize; - assert((long) tc->freeInCache>=0); - } -#if defined(DEBUG) && 0 - if(!(tc->mallocs & 0xfff)) - { - printf("*** threadcache=%u, mallocs=%u (%f), free=%u (%f), freeInCache=%u\n", (unsigned int) tc->threadid, tc->mallocs, - (float) tc->successes/tc->mallocs, tc->frees, (float) tc->successes/tc->frees, (unsigned int) tc->freeInCache); - } -#endif -#ifdef FULLSANITYCHECKS - tcfullsanitycheck(tc); -#endif - *_size=size; - return ret; -} -static NOINLINE void ReleaseFreeInCache(nedpool *RESTRICT p, threadcache *RESTRICT tc, int mymspace) THROWSPEC -{ - unsigned int age=THREADCACHEMAXFREESPACE/8192; - /*ACQUIRE_LOCK(&p->m[mymspace]->mutex);*/ - while(age && tc->freeInCache>=THREADCACHEMAXFREESPACE) - { - RemoveCacheEntries(p, tc, age); - /*printf("*** Removing cache entries older than %u (%u)\n", age, (unsigned int) tc->freeInCache);*/ - age>>=1; - } - /*RELEASE_LOCK(&p->m[mymspace]->mutex);*/ -} -static void threadcache_free(nedpool *RESTRICT p, threadcache *RESTRICT tc, int mymspace, void *RESTRICT mem, size_t size) THROWSPEC -{ - unsigned int bestsize; - unsigned int idx=size2binidx(size); - threadcacheblk **RESTRICT binsptr, *RESTRICT tck=(threadcacheblk *) mem; - assert(size>=sizeof(threadcacheblk) && size<=THREADCACHEMAX+CHUNK_OVERHEAD); -#ifdef DEBUG - /* Make sure this is a valid memory block */ - assert(nedblksize(0, mem)); -#endif -#ifdef FULLSANITYCHECKS - tcfullsanitycheck(tc); -#endif - /* Calculate best fit bin size */ - bestsize=1<<(idx+4); -#if 0 - /* Finer grained bin fit */ - idx<<=1; - if(size>bestsize) - { - unsigned int biggerbestsize=bestsize+bestsize<<1; - if(size>=biggerbestsize) - { - idx++; - bestsize=biggerbestsize; - } - } -#endif - if(bestsize!=size) /* dlmalloc can round up, so we round down to preserve indexing */ - size=bestsize; - binsptr=&tc->bins[idx*2]; - assert(idx<=THREADCACHEMAXBINS); - if(tck==*binsptr) - { - fprintf(stderr, "nedmalloc: Attempt to free already freed memory block %p - aborting!\n", tck); - abort(); - } -#ifdef FULLSANITYCHECKS - tck->magic=*(unsigned int *) "NEDN"; -#endif - tck->lastUsed=++tc->frees; - tck->size=(unsigned int) size; - tck->next=*binsptr; - tck->prev=0; - if(tck->next) - tck->next->prev=tck; - else - binsptr[1]=tck; - assert(!*binsptr || (*binsptr)->size==tck->size); - *binsptr=tck; - assert(tck==tc->bins[idx*2]); - assert(tc->bins[idx*2+1]==tck || binsptr[0]->next->prev==tck); - /*printf("free: %p, %p, %p, %lu\n", p, tc, mem, (long) size);*/ - tc->freeInCache+=size; -#ifdef FULLSANITYCHECKS - tcfullsanitycheck(tc); -#endif -#if 1 - if(tc->freeInCache>=THREADCACHEMAXFREESPACE) - ReleaseFreeInCache(p, tc, mymspace); -#endif -} - - - - -static NOINLINE int InitPool(nedpool *RESTRICT p, size_t capacity, int threads) THROWSPEC -{ /* threads is -1 for system pool */ - ensure_initialization(); - ACQUIRE_MALLOC_GLOBAL_LOCK(); - if(p->threads) goto done; - if(INITIAL_LOCK(&p->mutex)) goto err; - if(TLSALLOC(&p->mycache)) goto err; -#if USE_ALLOCATOR==0 - p->m[0]=(mstate) mspacecounter++; -#elif USE_ALLOCATOR==1 - if(!(p->m[0]=(mstate) create_mspace(capacity, 1))) goto err; - p->m[0]->extp=p; -#endif - p->threads=(threads<1 || threads>MAXTHREADSINPOOL) ? MAXTHREADSINPOOL : threads; -done: - RELEASE_MALLOC_GLOBAL_LOCK(); - return 1; -err: - if(threads<0) - abort(); /* If you can't allocate for system pool, we're screwed */ - DestroyCaches(p); - if(p->m[0]) - { -#if USE_ALLOCATOR==1 - destroy_mspace(p->m[0]); -#endif - p->m[0]=0; - } - if(p->mycache) - { - if(TLSFREE(p->mycache)) abort(); - p->mycache=0; - } - RELEASE_MALLOC_GLOBAL_LOCK(); - return 0; -} -static NOINLINE mstate FindMSpace(nedpool *RESTRICT p, threadcache *RESTRICT tc, int *RESTRICT lastUsed, size_t size) THROWSPEC -{ /* Gets called when thread's last used mspace is in use. The strategy - is to run through the list of all available mspaces looking for an - unlocked one and if we fail, we create a new one so long as we don't - exceed p->threads */ - int n, end; - for(n=end=*lastUsed+1; p->m[n]; end=++n) - { - if(TRY_LOCK(&p->m[n]->mutex)) goto found; - } - for(n=0; n<*lastUsed && p->m[n]; n++) - { - if(TRY_LOCK(&p->m[n]->mutex)) goto found; - } - if(end<p->threads) - { - mstate temp; -#if USE_ALLOCATOR==0 - temp=(mstate) mspacecounter++; -#elif USE_ALLOCATOR==1 - if(!(temp=(mstate) create_mspace(size, 1))) - goto badexit; -#endif - /* Now we're ready to modify the lists, we lock */ - ACQUIRE_LOCK(&p->mutex); - while(p->m[end] && end<p->threads) - end++; - if(end>=p->threads) - { /* Drat, must destroy it now */ - RELEASE_LOCK(&p->mutex); -#if USE_ALLOCATOR==1 - destroy_mspace((mstate) temp); -#endif - goto badexit; - } - /* We really want to make sure this goes into memory now but we - have to be careful of breaking aliasing rules, so write it twice */ - *((volatile struct malloc_state **) &p->m[end])=p->m[end]=temp; - ACQUIRE_LOCK(&p->m[end]->mutex); - /*printf("Created mspace idx %d\n", end);*/ - RELEASE_LOCK(&p->mutex); - n=end; - goto found; - } - /* Let it lock on the last one it used */ -badexit: - ACQUIRE_LOCK(&p->m[*lastUsed]->mutex); - return p->m[*lastUsed]; -found: - *lastUsed=n; - if(tc) - tc->mymspace=n; - else - { - if(TLSSET(p->mycache, (void *)(size_t)(-(n+1)))) abort(); - } - return p->m[n]; -} - -typedef struct PoolList_t -{ - size_t size; /* Size of list */ - size_t length; /* Actual entries in list */ -#ifdef DEBUG - nedpool *list[1]; /* Force testing of list expansion */ -#else - nedpool *list[16]; -#endif -} PoolList; -static MLOCK_T poollistlock; -static PoolList *poollist; -NEDMALLOCPTRATTR nedpool *nedcreatepool(size_t capacity, int threads) THROWSPEC -{ - nedpool *ret=0; - if(!poollist) - { - PoolList *newpoollist=0; - if(!(newpoollist=(PoolList *) nedpcalloc(0, 1, sizeof(PoolList)+sizeof(nedpool *)))) return 0; - INITIAL_LOCK(&poollistlock); - ACQUIRE_LOCK(&poollistlock); - poollist=newpoollist; - poollist->size=sizeof(poollist->list)/sizeof(nedpool *); - } - else - ACQUIRE_LOCK(&poollistlock); - if(poollist->length==poollist->size) - { - PoolList *newpoollist=0; - size_t newsize=0; - newsize=sizeof(PoolList)+(poollist->size+1)*sizeof(nedpool *); - if(!(newpoollist=(PoolList *) nedprealloc(0, poollist, newsize))) goto badexit; - poollist=newpoollist; - memset(&poollist->list[poollist->size], 0, newsize-((size_t)&poollist->list[poollist->size]-(size_t)&poollist->list[0])); - poollist->size=((newsize-((char *)&poollist->list[0]-(char *)poollist))/sizeof(nedpool *))-1; - assert(poollist->size>poollist->length); - } - if(!(ret=(nedpool *) nedpcalloc(0, 1, sizeof(nedpool)))) goto badexit; - if(!InitPool(ret, capacity, threads)) - { - nedpfree(0, ret); - goto badexit; - } - poollist->list[poollist->length++]=ret; -badexit: - RELEASE_LOCK(&poollistlock); - return ret; -} -void neddestroypool(nedpool *p) THROWSPEC -{ - unsigned int n; - ACQUIRE_LOCK(&p->mutex); - DestroyCaches(p); - for(n=0; p->m[n]; n++) - { -#if USE_ALLOCATOR==1 - destroy_mspace(p->m[n]); -#endif - p->m[n]=0; - } - RELEASE_LOCK(&p->mutex); - if(TLSFREE(p->mycache)) abort(); - nedpfree(0, p); - ACQUIRE_LOCK(&poollistlock); - assert(poollist); - for(n=0; n<poollist->length && poollist->list[n]!=p; n++); - assert(n!=poollist->length); - memmove(&poollist->list[n], &poollist->list[n+1], (size_t)&poollist->list[poollist->length]-(size_t)&poollist->list[n]); - if(!--poollist->length) - { - assert(!poollist->list[0]); - nedpfree(0, poollist); - poollist=0; - } - RELEASE_LOCK(&poollistlock); -} -void neddestroysyspool() THROWSPEC -{ - nedpool *p=&syspool; - int n; - ACQUIRE_LOCK(&p->mutex); - DestroyCaches(p); - for(n=0; p->m[n]; n++) - { -#if USE_ALLOCATOR==1 - destroy_mspace(p->m[n]); -#endif - p->m[n]=0; - } - /* Render syspool unusable */ - for(n=0; n<THREADCACHEMAXCACHES; n++) - p->caches[n]=(threadcache *)(size_t)(sizeof(size_t)>4 ? 0xdeadbeefdeadbeefULL : 0xdeadbeefUL); - for(n=0; n<MAXTHREADSINPOOL+1; n++) - p->m[n]=(mstate)(size_t)(sizeof(size_t)>4 ? 0xdeadbeefdeadbeefULL : 0xdeadbeefUL); - if(TLSFREE(p->mycache)) abort(); - RELEASE_LOCK(&p->mutex); -} -nedpool **nedpoollist() THROWSPEC -{ - nedpool **ret=0; - if(poollist) - { - ACQUIRE_LOCK(&poollistlock); - if(!(ret=(nedpool **) nedmalloc((poollist->length+1)*sizeof(nedpool *)))) goto badexit; - memcpy(ret, poollist->list, (poollist->length+1)*sizeof(nedpool *)); -badexit: - RELEASE_LOCK(&poollistlock); - } - return ret; -} - -void nedpsetvalue(nedpool *p, void *v) THROWSPEC -{ - if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); } - p->uservalue=v; -} -void *nedgetvalue(nedpool **p, void *mem) THROWSPEC -{ - nedpool *np=0; - mstate fm=nedblkmstate(mem); - if(!fm || !fm->extp) return 0; - np=(nedpool *) fm->extp; - if(p) *p=np; - return np->uservalue; -} - -void nedtrimthreadcache(nedpool *p, int disable) THROWSPEC -{ - int mycache; - if(!p) - { - p=&syspool; - if(!syspool.threads) InitPool(&syspool, 0, -1); - } - mycache=(int)(size_t) TLSGET(p->mycache); - if(!mycache) - { /* Set to mspace 0 */ - if(disable && TLSSET(p->mycache, (void *)(size_t)-1)) abort(); - } - else if(mycache>0) - { /* Set to last used mspace */ - threadcache *tc=p->caches[mycache-1]; -#if defined(DEBUG) - printf("Threadcache utilisation: %lf%% in cache with %lf%% lost to other threads\n", - 100.0*tc->successes/tc->mallocs, 100.0*((double) tc->mallocs-tc->frees)/tc->mallocs); -#endif - if(disable && TLSSET(p->mycache, (void *)(size_t)(-tc->mymspace))) abort(); - tc->frees++; - RemoveCacheEntries(p, tc, 0); - assert(!tc->freeInCache); - if(disable) - { - tc->mymspace=-1; - tc->threadid=0; - CallFree(0, p->caches[mycache-1], 0); - p->caches[mycache-1]=0; - } - } -} -void neddisablethreadcache(nedpool *p) THROWSPEC -{ - nedtrimthreadcache(p, 1); -} - -#define GETMSPACE(m,p,tc,ms,s,action) \ - do \ - { \ - mstate m = GetMSpace((p),(tc),(ms),(s)); \ - action; \ - if(USE_ALLOCATOR==1) { RELEASE_LOCK(&m->mutex); } \ - } while (0) - -static FORCEINLINE mstate GetMSpace(nedpool *RESTRICT p, threadcache *RESTRICT tc, int mymspace, size_t size) THROWSPEC -{ /* Returns a locked and ready for use mspace */ - mstate m=p->m[mymspace]; - assert(m); -#if USE_ALLOCATOR==1 - if(!TRY_LOCK(&p->m[mymspace]->mutex)) m=FindMSpace(p, tc, &mymspace, size); - /*assert(IS_LOCKED(&p->m[mymspace]->mutex));*/ -#endif - return m; -} -static NOINLINE void GetThreadCache_cold1(nedpool *RESTRICT *RESTRICT p) THROWSPEC -{ - *p=&syspool; - if(!syspool.threads) InitPool(&syspool, 0, -1); -} -static NOINLINE void GetThreadCache_cold2(nedpool *RESTRICT *RESTRICT p, threadcache *RESTRICT *RESTRICT tc, int *RESTRICT mymspace, int mycache) THROWSPEC -{ - if(!mycache) - { /* Need to allocate a new cache */ - *tc=AllocCache(*p); - if(!*tc) - { /* Disable */ - if(TLSSET((*p)->mycache, (void *)(size_t)-1)) abort(); - *mymspace=0; - } - else - *mymspace=(*tc)->mymspace; - } - else - { /* Cache disabled, but we do have an assigned thread pool */ - *tc=0; - *mymspace=-mycache-1; - } -} -static FORCEINLINE void GetThreadCache(nedpool *RESTRICT *RESTRICT p, threadcache *RESTRICT *RESTRICT tc, int *RESTRICT mymspace, size_t *RESTRICT size) THROWSPEC -{ - int mycache; - if(size && *size<sizeof(threadcacheblk)) *size=sizeof(threadcacheblk); - if(!*p) - GetThreadCache_cold1(p); - mycache=(int)(size_t) TLSGET((*p)->mycache); - if(mycache>0) - { /* Already have a cache */ - *tc=(*p)->caches[mycache-1]; - *mymspace=(*tc)->mymspace; - } - else GetThreadCache_cold2(p, tc, mymspace, mycache); - assert(*mymspace>=0); - assert(!(*tc) || (long)(size_t)CURRENT_THREAD==(*tc)->threadid); -#ifdef FULLSANITYCHECKS - if(*tc) - { - if(*(unsigned int *)"NEDMALC1"!=(*tc)->magic1 || *(unsigned int *)"NEDMALC2"!=(*tc)->magic2) - { - abort(); - } - } -#endif -} - -NEDMALLOCPTRATTR void * nedpmalloc(nedpool *p, size_t size) THROWSPEC -{ - void *ret=0; - threadcache *tc; - int mymspace; - GetThreadCache(&p, &tc, &mymspace, &size); -#if THREADCACHEMAX - if(tc && size<=THREADCACHEMAX) - { /* Use the thread cache */ - ret=threadcache_malloc(p, tc, &size); - } -#endif - if(!ret) - { /* Use this thread's mspace */ - GETMSPACE(m, p, tc, mymspace, size, - ret=CallMalloc(m, size, 0)); - } - return ret; -} -NEDMALLOCPTRATTR void * nedpcalloc(nedpool *p, size_t no, size_t size) THROWSPEC -{ - size_t rsize=size*no; - void *ret=0; - threadcache *tc; - int mymspace; - GetThreadCache(&p, &tc, &mymspace, &rsize); -#if THREADCACHEMAX - if(tc && rsize<=THREADCACHEMAX) - { /* Use the thread cache */ - if((ret=threadcache_malloc(p, tc, &rsize))) - memset(ret, 0, rsize); - } -#endif - if(!ret) - { /* Use this thread's mspace */ - GETMSPACE(m, p, tc, mymspace, rsize, - ret=CallCalloc(m, rsize, 0)); - } - return ret; -} -NEDMALLOCPTRATTR void * nedprealloc(nedpool *p, void *mem, size_t size) THROWSPEC -{ - void *ret=0; - threadcache *tc; - int mymspace, isforeign=1; - size_t memsize; - if(!mem) return nedpmalloc(p, size); - memsize=nedblksize(&isforeign, mem); - assert(memsize); - if(!memsize) - { - fprintf(stderr, "nedmalloc: nedprealloc() called with a block not created by nedmalloc!\n"); - abort(); - } - else if(size<=memsize && memsize-size< -#ifdef DEBUG - 32 -#else - 1024 -#endif - ) /* If realloc size is within 1Kb smaller than existing, noop it */ - return mem; - GetThreadCache(&p, &tc, &mymspace, &size); -#if THREADCACHEMAX - if(tc && size && size<=THREADCACHEMAX) - { /* Use the thread cache */ - if((ret=threadcache_malloc(p, tc, &size))) - { - memcpy(ret, mem, memsize<size ? memsize : size); - if(memsize>=sizeof(threadcacheblk) && memsize<=(THREADCACHEMAX+CHUNK_OVERHEAD)) - threadcache_free(p, tc, mymspace, mem, memsize); - else - CallFree(0, mem, isforeign); - } - } -#endif - if(!ret) - { /* Reallocs always happen in the mspace they happened in, so skip - locking the preferred mspace for this thread */ - ret=CallRealloc(p->m[mymspace], mem, isforeign, memsize, size); - } - return ret; -} -void nedpfree(nedpool *p, void *mem) THROWSPEC -{ /* Frees always happen in the mspace they happened in, so skip - locking the preferred mspace for this thread */ - threadcache *tc; - int mymspace, isforeign=1; - size_t memsize; - if(!mem) - { /* If you tried this on FreeBSD you'd be sorry! */ -#ifdef DEBUG - fprintf(stderr, "nedmalloc: WARNING nedpfree() called with zero. This is not portable behaviour!\n"); -#endif - return; - } - memsize=nedblksize(&isforeign, mem); - assert(memsize); - if(!memsize) - { - fprintf(stderr, "nedmalloc: nedpfree() called with a block not created by nedmalloc!\n"); - abort(); - } - GetThreadCache(&p, &tc, &mymspace, 0); -#if THREADCACHEMAX - if(mem && tc && memsize>=sizeof(threadcacheblk) && memsize<=(THREADCACHEMAX+CHUNK_OVERHEAD)) - threadcache_free(p, tc, mymspace, mem, memsize); - else -#endif - CallFree(0, mem, isforeign); -} -NEDMALLOCPTRATTR void * nedpmemalign(nedpool *p, size_t alignment, size_t bytes) THROWSPEC -{ - void *ret; - threadcache *tc; - int mymspace; - GetThreadCache(&p, &tc, &mymspace, &bytes); - { /* Use this thread's mspace */ - GETMSPACE(m, p, tc, mymspace, bytes, - ret=CallMalloc(m, bytes, alignment)); - } - return ret; -} -struct nedmallinfo nedpmallinfo(nedpool *p) THROWSPEC -{ - int n; - struct nedmallinfo ret={0}; - if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); } - for(n=0; p->m[n]; n++) - { -#if USE_ALLOCATOR==1 && !NO_MALLINFO - struct mallinfo t=mspace_mallinfo(p->m[n]); - ret.arena+=t.arena; - ret.ordblks+=t.ordblks; - ret.hblkhd+=t.hblkhd; - ret.usmblks+=t.usmblks; - ret.uordblks+=t.uordblks; - ret.fordblks+=t.fordblks; - ret.keepcost+=t.keepcost; -#endif - } - return ret; -} -int nedpmallopt(nedpool *p, int parno, int value) THROWSPEC -{ -#if USE_ALLOCATOR==1 - return mspace_mallopt(parno, value); -#else - return 0; -#endif -} -NEDMALLOCNOALIASATTR void* nedmalloc_internals(size_t *granularity, size_t *magic) THROWSPEC -{ -#if USE_ALLOCATOR==1 - if(granularity) *granularity=mparams.granularity; - if(magic) *magic=mparams.magic; - return (void *) &syspool; -#else - if(granularity) *granularity=0; - if(magic) *magic=0; - return 0; -#endif -} -int nedpmalloc_trim(nedpool *p, size_t pad) THROWSPEC -{ - int n, ret=0; - if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); } - for(n=0; p->m[n]; n++) - { -#if USE_ALLOCATOR==1 - ret+=mspace_trim(p->m[n], pad); -#endif - } - return ret; -} -void nedpmalloc_stats(nedpool *p) THROWSPEC -{ - int n; - if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); } - for(n=0; p->m[n]; n++) - { -#if USE_ALLOCATOR==1 - mspace_malloc_stats(p->m[n]); -#endif - } -} -size_t nedpmalloc_footprint(nedpool *p) THROWSPEC -{ - size_t ret=0; - int n; - if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); } - for(n=0; p->m[n]; n++) - { -#if USE_ALLOCATOR==1 - ret+=mspace_footprint(p->m[n]); -#endif - } - return ret; -} -NEDMALLOCPTRATTR void **nedpindependent_calloc(nedpool *p, size_t elemsno, size_t elemsize, void **chunks) THROWSPEC -{ - void **ret; - threadcache *tc; - int mymspace; - GetThreadCache(&p, &tc, &mymspace, &elemsize); -#if USE_ALLOCATOR==0 - GETMSPACE(m, p, tc, mymspace, elemsno*elemsize, - ret=unsupported_operation("independent_calloc")); -#elif USE_ALLOCATOR==1 - GETMSPACE(m, p, tc, mymspace, elemsno*elemsize, - ret=mspace_independent_calloc(m, elemsno, elemsize, chunks)); -#endif - return ret; -} -NEDMALLOCPTRATTR void **nedpindependent_comalloc(nedpool *p, size_t elems, size_t *sizes, void **chunks) THROWSPEC -{ - void **ret; - threadcache *tc; - int mymspace; - size_t i, *adjustedsizes=(size_t *) alloca(elems*sizeof(size_t)); - if(!adjustedsizes) return 0; - for(i=0; i<elems; i++) - adjustedsizes[i]=sizes[i]<sizeof(threadcacheblk) ? sizeof(threadcacheblk) : sizes[i]; - GetThreadCache(&p, &tc, &mymspace, 0); -#if USE_ALLOCATOR==0 - GETMSPACE(m, p, tc, mymspace, 0, - ret=unsupported_operation("independent_comalloc")); -#elif USE_ALLOCATOR==1 - GETMSPACE(m, p, tc, mymspace, 0, - ret=mspace_independent_comalloc(m, elems, adjustedsizes, chunks)); -#endif - return ret; -} - -#if defined(__cplusplus) -} -#endif - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#endif diff --git a/drivers/nedmalloc/nedmalloc.h b/drivers/nedmalloc/nedmalloc.h deleted file mode 100644 index 7ec65849fc..0000000000 --- a/drivers/nedmalloc/nedmalloc.h +++ /dev/null @@ -1,302 +0,0 @@ -#ifdef NEDMALLOC_ENABLED - -/* nedalloc, an alternative malloc implementation for multiple threads without -lock contention based on dlmalloc v2.8.3. (C) 2005-2009 Niall Douglas - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - -#ifndef NEDMALLOC_H -#define NEDMALLOC_H - -#include "typedefs.h" -#define MALLOC_ALIGNMENT DEFAULT_ALIGNMENT - -#ifdef PSP_ENABLED -#define USE_LOCKS 0 -#define HAVE_MMAP 0 -#endif - -/* See malloc.c.h for what each function does. - -REPLACE_SYSTEM_ALLOCATOR on POSIX causes nedalloc's functions to be called -malloc, free etc. instead of nedmalloc, nedfree etc. You may or may not want -this. On Windows it causes nedmalloc to patch all loaded DLLs and binaries -to replace usage of the system allocator. - -NO_NED_NAMESPACE prevents the functions from being defined in the nedalloc -namespace when in C++ (uses the global namespace instead). - -NEDMALLOCEXTSPEC can be defined to be __declspec(dllexport) or -__attribute__ ((visibility("default"))) or whatever you like. It defaults -to extern unless NEDMALLOC_DLL_EXPORTS is set as it would be when building -nedmalloc.dll. - -USE_LOCKS can be 2 if you want to define your own MLOCK_T, INITIAL_LOCK, -ACQUIRE_LOCK, RELEASE_LOCK, TRY_LOCK, IS_LOCKED and NULL_LOCK_INITIALIZER. - -NEDMALLOC_DEBUG can be defined to cause DEBUG to be set differently for nedmalloc -than for the rest of the build. Remember to set NDEBUG to disable all assertion -checking too. - -USE_MAGIC_HEADERS causes nedalloc to allocate an extra three sizeof(size_t) -to each block. nedpfree() and nedprealloc() can then automagically know when -to free a system allocated block. Enabling this typically adds 20-50% to -application memory usage. - -ENABLE_TOLERANT_NEDMALLOC is automatically turned on if REPLACE_SYSTEM_ALLOCATOR -is set or the Windows DLL is being built. This causes nedmalloc to detect when a -system allocator block is passed to it and to handle it appropriately. Note that -without USE_MAGIC_HEADERS there is a very tiny chance that nedmalloc will segfault -on non-Windows builds (it uses Win32 SEH to trap segfaults on Windows and there -is no comparable system on POSIX). - -USE_ALLOCATOR can be one of these settings (it defaults to 1): - 0: System allocator (nedmalloc now simply acts as a threadcache). - WARNING: Intended for DEBUG USE ONLY - not all functions work correctly. - 1: dlmalloc - -ENABLE_LARGE_PAGES enables support for requesting memory from the system in large -(typically >=2Mb) pages if the host OS supports this. These occupy just a single -TLB entry and can significantly improve performance in large working set applications. - -ENABLE_FAST_HEAP_DETECTION enables special logic to detect blocks allocated -by the system heap. This avoids 1.5%-2% overhead when checking for non-nedmalloc -blocks, but it assumes that the NT and glibc heaps function in a very specific -fashion which may not hold true across OS upgrades. -*/ - -#include <stddef.h> /* for size_t */ - -#ifndef NEDMALLOCEXTSPEC - #ifdef NEDMALLOC_DLL_EXPORTS - #ifdef WIN32 - #define NEDMALLOCEXTSPEC extern __declspec(dllexport) - #elif defined(__GNUC__) - #define NEDMALLOCEXTSPEC extern __attribute__ ((visibility("default"))) - #endif - #ifndef ENABLE_TOLERANT_NEDMALLOC - #define ENABLE_TOLERANT_NEDMALLOC 1 - #endif - #else - #define NEDMALLOCEXTSPEC extern - #endif -#endif - -#if __STDC_VERSION__ >= 199901L /* C99 or better */ - #define RESTRICT restrict -#else - #if defined(_MSC_VER) && _MSC_VER>=1400 - #define RESTRICT __restrict - #endif - #ifdef __GNUC__ - #define RESTRICT __restrict - #endif -#endif -#ifndef RESTRICT - #define RESTRICT -#endif - -#if defined(_MSC_VER) && _MSC_VER>=1400 - #define NEDMALLOCPTRATTR __declspec(restrict) - #define NEDMALLOCNOALIASATTR __declspec(noalias) -#endif -#ifdef __GNUC__ - #define NEDMALLOCPTRATTR __attribute__ ((malloc)) -#endif -#ifndef NEDMALLOCPTRATTR - #define NEDMALLOCPTRATTR -#endif -#ifndef NEDMALLOCNOALIASATTR - #define NEDMALLOCNOALIASATTR -#endif - -#ifndef USE_MAGIC_HEADERS - #define USE_MAGIC_HEADERS 0 -#endif - -#ifndef USE_ALLOCATOR - #define USE_ALLOCATOR 1 /* dlmalloc */ -#endif - -#if !USE_ALLOCATOR && !USE_MAGIC_HEADERS -#error If you are using the system allocator then you MUST use magic headers -#endif - -#ifdef REPLACE_SYSTEM_ALLOCATOR - #if USE_ALLOCATOR==0 - #error Cannot combine using the system allocator with replacing the system allocator - #endif - #ifndef ENABLE_TOLERANT_NEDMALLOC - #define ENABLE_TOLERANT_NEDMALLOC 1 - #endif - #ifndef WIN32 /* We have a dedicated patcher for Windows */ - #define nedmalloc malloc - #define nedcalloc calloc - #define nedrealloc realloc - #define nedfree free - #define nedmemalign memalign - #define nedmallinfo mallinfo - #define nedmallopt mallopt - #define nedmalloc_trim malloc_trim - #define nedmalloc_stats malloc_stats - #define nedmalloc_footprint malloc_footprint - #define nedindependent_calloc independent_calloc - #define nedindependent_comalloc independent_comalloc - #ifdef _MSC_VER - #define nedblksize _msize - #endif - #endif -#endif - -#if defined(__cplusplus) -extern "C" { -#endif -struct nedmallinfo { - size_t arena; /* non-mmapped space allocated from system */ - size_t ordblks; /* number of free chunks */ - size_t smblks; /* always 0 */ - size_t hblks; /* always 0 */ - size_t hblkhd; /* space in mmapped regions */ - size_t usmblks; /* maximum total allocated space */ - size_t fsmblks; /* always 0 */ - size_t uordblks; /* total allocated space */ - size_t fordblks; /* total free space */ - size_t keepcost; /* releasable (via malloc_trim) space */ -}; -#if defined(__cplusplus) -} -#endif - -#if defined(__cplusplus) - #if !defined(NO_NED_NAMESPACE) -namespace nedalloc { - #else -extern "C" { - #endif - #define THROWSPEC throw() -#else - #define THROWSPEC -#endif - -/* These are the global functions */ - -/* Gets the usable size of an allocated block. Note this will always be bigger than what was -asked for due to rounding etc. Optionally returns 1 in isforeign if the block came from the -system allocator - note that there is a small (>0.01%) but real chance of segfault on non-Windows -systems when passing non-nedmalloc blocks if you don't use USE_MAGIC_HEADERS. -*/ -NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR size_t nedblksize(int *RESTRICT isforeign, void *RESTRICT mem) THROWSPEC; - -NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedsetvalue(void *v) THROWSPEC; - -NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedmalloc(size_t size) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedcalloc(size_t no, size_t size) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedrealloc(void *mem, size_t size) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedfree(void *mem) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedmemalign(size_t alignment, size_t bytes) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR struct nedmallinfo nedmallinfo(void) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR int nedmallopt(int parno, int value) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void* nedmalloc_internals(size_t *granularity, size_t *magic) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR int nedmalloc_trim(size_t pad) THROWSPEC; -NEDMALLOCEXTSPEC void nedmalloc_stats(void) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR size_t nedmalloc_footprint(void) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void **nedindependent_calloc(size_t elemsno, size_t elemsize, void **chunks) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void **nedindependent_comalloc(size_t elems, size_t *sizes, void **chunks) THROWSPEC; - -/* Destroys the system memory pool used by the functions above. -Useful for when you have nedmalloc in a DLL you're about to unload. -If you call ANY nedmalloc functions after calling this you will -get a fatal exception! -*/ -NEDMALLOCEXTSPEC void neddestroysyspool() THROWSPEC; - -/* These are the pool functions */ -struct nedpool_t; -typedef struct nedpool_t nedpool; - -/* Creates a memory pool for use with the nedp* functions below. -Capacity is how much to allocate immediately (if you know you'll be allocating a lot -of memory very soon) which you can leave at zero. Threads specifies how many threads -will *normally* be accessing the pool concurrently. Setting this to zero means it -extends on demand, but be careful of this as it can rapidly consume system resources -where bursts of concurrent threads use a pool at once. -*/ -NEDMALLOCEXTSPEC NEDMALLOCPTRATTR nedpool *nedcreatepool(size_t capacity, int threads) THROWSPEC; - -/* Destroys a memory pool previously created by nedcreatepool(). -*/ -NEDMALLOCEXTSPEC void neddestroypool(nedpool *p) THROWSPEC; - -/* Returns a zero terminated snapshot of threadpools existing at the time of call. Call -nedfree() on the returned list when you are done. Returns zero if there is only the -system pool in existence. -*/ -NEDMALLOCEXTSPEC nedpool **nedpoollist() THROWSPEC; - -/* Sets a value to be associated with a pool. You can retrieve this value by passing -any memory block allocated from that pool. -*/ -NEDMALLOCEXTSPEC void nedpsetvalue(nedpool *p, void *v) THROWSPEC; - -/* Gets a previously set value using nedpsetvalue() or zero if memory is unknown. -Optionally can also retrieve pool. You can detect an unknown block by the return -being zero and *p being unmodifed. -*/ -NEDMALLOCEXTSPEC void *nedgetvalue(nedpool **p, void *mem) THROWSPEC; - -/* Trims the thread cache for the calling thread, returning any existing cache -data to the central pool. Remember to ALWAYS call with zero if you used the -system pool. Setting disable to non-zero replicates neddisablethreadcache(). -*/ -NEDMALLOCEXTSPEC void nedtrimthreadcache(nedpool *p, int disable) THROWSPEC; - -/* Disables the thread cache for the calling thread, returning any existing cache -data to the central pool. Remember to ALWAYS call with zero if you used the -system pool. -*/ -NEDMALLOCEXTSPEC void neddisablethreadcache(nedpool *p) THROWSPEC; - - -NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedpmalloc(nedpool *p, size_t size) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedpcalloc(nedpool *p, size_t no, size_t size) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedprealloc(nedpool *p, void *mem, size_t size) THROWSPEC; -NEDMALLOCEXTSPEC void nedpfree(nedpool *p, void *mem) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedpmemalign(nedpool *p, size_t alignment, size_t bytes) THROWSPEC; -NEDMALLOCEXTSPEC struct nedmallinfo nedpmallinfo(nedpool *p) THROWSPEC; -NEDMALLOCEXTSPEC int nedpmallopt(nedpool *p, int parno, int value) THROWSPEC; -NEDMALLOCEXTSPEC int nedpmalloc_trim(nedpool *p, size_t pad) THROWSPEC; -NEDMALLOCEXTSPEC void nedpmalloc_stats(nedpool *p) THROWSPEC; -NEDMALLOCEXTSPEC size_t nedpmalloc_footprint(nedpool *p) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void **nedpindependent_calloc(nedpool *p, size_t elemsno, size_t elemsize, void **chunks) THROWSPEC; -NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void **nedpindependent_comalloc(nedpool *p, size_t elems, size_t *sizes, void **chunks) THROWSPEC; - -#if defined(__cplusplus) -} -#endif - -#endif - -#endif diff --git a/drivers/nrex/SCsub b/drivers/nrex/SCsub index a00c7b86f4..ee39fd2631 100644 --- a/drivers/nrex/SCsub +++ b/drivers/nrex/SCsub @@ -1,7 +1,7 @@ +#!/usr/bin/env python + Import('env') -sources = [ - 'nrex.cpp', - 'regex.cpp', -] -env.add_source_files(env.drivers_sources, sources) +env.add_source_files(env.drivers_sources, "*.cpp") + +Export('env') diff --git a/drivers/ogg/SCsub b/drivers/ogg/SCsub deleted file mode 100644 index 3ee1bb6408..0000000000 --- a/drivers/ogg/SCsub +++ /dev/null @@ -1,9 +0,0 @@ -Import('env') - -ogg_sources = [ - - "ogg/bitwise.c", - "ogg/framing.c", -] - -env.drivers_sources+=ogg_sources diff --git a/drivers/openssl/SCsub b/drivers/openssl/SCsub deleted file mode 100644 index 40e3d0c0f0..0000000000 --- a/drivers/openssl/SCsub +++ /dev/null @@ -1,6 +0,0 @@ -Import('env_drivers') -Import('env') - -env_drivers.add_source_files(env.drivers_sources,"*.cpp") -env_drivers.add_source_files(env.drivers_sources,"*.c") - diff --git a/drivers/openssl/curl_hostcheck.c b/drivers/openssl/curl_hostcheck.c deleted file mode 100644 index f5d44bfaf1..0000000000 --- a/drivers/openssl/curl_hostcheck.c +++ /dev/null @@ -1,221 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* This file is an amalgamation of hostcheck.c and most of rawstr.c - from cURL. The contents of the COPYING file mentioned above are: - -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1996 - 2013, Daniel Stenberg, <daniel@haxx.se>. - -All rights reserved. - -Permission to use, copy, modify, and distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright -notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN -NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of a copyright holder shall not -be used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization of the copyright holder. -*/ - -#ifdef OPENSSL_ENABLED - -#include "curl_hostcheck.h" -#include <string.h> - -/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because - its behavior is altered by the current locale. */ -static char Curl_raw_toupper(char in) -{ - switch (in) { - case 'a': - return 'A'; - case 'b': - return 'B'; - case 'c': - return 'C'; - case 'd': - return 'D'; - case 'e': - return 'E'; - case 'f': - return 'F'; - case 'g': - return 'G'; - case 'h': - return 'H'; - case 'i': - return 'I'; - case 'j': - return 'J'; - case 'k': - return 'K'; - case 'l': - return 'L'; - case 'm': - return 'M'; - case 'n': - return 'N'; - case 'o': - return 'O'; - case 'p': - return 'P'; - case 'q': - return 'Q'; - case 'r': - return 'R'; - case 's': - return 'S'; - case 't': - return 'T'; - case 'u': - return 'U'; - case 'v': - return 'V'; - case 'w': - return 'W'; - case 'x': - return 'X'; - case 'y': - return 'Y'; - case 'z': - return 'Z'; - } - return in; -} - -/* - * Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant - * to be locale independent and only compare strings we know are safe for - * this. See http://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for - * some further explanation to why this function is necessary. - * - * The function is capable of comparing a-z case insensitively even for - * non-ascii. - */ - -static int Curl_raw_equal(const char *first, const char *second) -{ - while(*first && *second) { - if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) - /* get out of the loop as soon as they don't match */ - break; - first++; - second++; - } - /* we do the comparison here (possibly again), just to make sure that if the - loop above is skipped because one of the strings reached zero, we must not - return this as a successful match */ - return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second)); -} - -static int Curl_raw_nequal(const char *first, const char *second, size_t max) -{ - while(*first && *second && max) { - if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) { - break; - } - max--; - first++; - second++; - } - if(0 == max) - return 1; /* they are equal this far */ - - return Curl_raw_toupper(*first) == Curl_raw_toupper(*second); -} - -/* - * Match a hostname against a wildcard pattern. - * E.g. - * "foo.host.com" matches "*.host.com". - * - * We use the matching rule described in RFC6125, section 6.4.3. - * http://tools.ietf.org/html/rfc6125#section-6.4.3 - */ - -static int hostmatch(const char *hostname, const char *pattern) -{ - const char *pattern_label_end, *pattern_wildcard, *hostname_label_end; - int wildcard_enabled; - size_t prefixlen, suffixlen; - pattern_wildcard = strchr(pattern, '*'); - if(pattern_wildcard == NULL) - return Curl_raw_equal(pattern, hostname) ? - CURL_HOST_MATCH : CURL_HOST_NOMATCH; - - /* We require at least 2 dots in pattern to avoid too wide wildcard - match. */ - wildcard_enabled = 1; - pattern_label_end = strchr(pattern, '.'); - if(pattern_label_end == NULL || strchr(pattern_label_end+1, '.') == NULL || - pattern_wildcard > pattern_label_end || - Curl_raw_nequal(pattern, "xn--", 4)) { - wildcard_enabled = 0; - } - if(!wildcard_enabled) - return Curl_raw_equal(pattern, hostname) ? - CURL_HOST_MATCH : CURL_HOST_NOMATCH; - - hostname_label_end = strchr(hostname, '.'); - if(hostname_label_end == NULL || - !Curl_raw_equal(pattern_label_end, hostname_label_end)) - return CURL_HOST_NOMATCH; - - /* The wildcard must match at least one character, so the left-most - label of the hostname is at least as large as the left-most label - of the pattern. */ - if(hostname_label_end - hostname < pattern_label_end - pattern) - return CURL_HOST_NOMATCH; - - prefixlen = pattern_wildcard - pattern; - suffixlen = pattern_label_end - (pattern_wildcard+1); - return Curl_raw_nequal(pattern, hostname, prefixlen) && - Curl_raw_nequal(pattern_wildcard+1, hostname_label_end - suffixlen, - suffixlen) ? - CURL_HOST_MATCH : CURL_HOST_NOMATCH; -} - -int Tool_Curl_cert_hostcheck(const char *match_pattern, const char *hostname) -{ - if(!match_pattern || !*match_pattern || - !hostname || !*hostname) /* sanity check */ - return 0; - - if(Curl_raw_equal(hostname, match_pattern)) /* trivial case */ - return 1; - - if(hostmatch(hostname,match_pattern) == CURL_HOST_MATCH) - return 1; - return 0; -} - -#endif diff --git a/drivers/openssl/curl_hostcheck.h b/drivers/openssl/curl_hostcheck.h deleted file mode 100644 index 7611c6e443..0000000000 --- a/drivers/openssl/curl_hostcheck.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef HEADER_TOOL_CURL_HOSTCHECK_H -#define HEADER_TOOL_CURL_HOSTCHECK_H - -#ifdef OPENSSL_ENABLED - -#ifdef __cplusplus -extern "C" { -#endif - -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#define CURL_HOST_NOMATCH 0 -#define CURL_HOST_MATCH 1 -int Tool_Curl_cert_hostcheck(const char *match_pattern, const char *hostname); - -#ifdef __cplusplus -} -#endif - -#endif - -#endif /* HEADER_CURL_HOSTCHECK_H */ - diff --git a/drivers/openssl/register_openssl.cpp b/drivers/openssl/register_openssl.cpp deleted file mode 100644 index 0d2f9fd537..0000000000 --- a/drivers/openssl/register_openssl.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************/ -/* register_openssl.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "register_openssl.h" - -#include "stream_peer_openssl.h" -#ifdef OPENSSL_ENABLED - -void register_openssl() { - - ObjectTypeDB::register_type<StreamPeerOpenSSL>(); - StreamPeerOpenSSL::initialize_ssl(); - -} - -void unregister_openssl() { - - StreamPeerOpenSSL::finalize_ssl(); - -} -#endif - diff --git a/drivers/openssl/register_openssl.h b/drivers/openssl/register_openssl.h deleted file mode 100644 index a66ca1e9c0..0000000000 --- a/drivers/openssl/register_openssl.h +++ /dev/null @@ -1,39 +0,0 @@ -/*************************************************************************/ -/* register_openssl.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef REGISTER_OPENSSL_H -#define REGISTER_OPENSSL_H - -#ifdef OPENSSL_ENABLED - -void register_openssl(); -void unregister_openssl(); - -#endif - -#endif // REGISTER_OPENSSL_H diff --git a/drivers/openssl/stream_peer_openssl.cpp b/drivers/openssl/stream_peer_openssl.cpp deleted file mode 100644 index aa3d8a8f7f..0000000000 --- a/drivers/openssl/stream_peer_openssl.cpp +++ /dev/null @@ -1,649 +0,0 @@ -/*************************************************************************/ -/* stream_peer_openssl.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifdef OPENSSL_ENABLED -#include "stream_peer_openssl.h" -//hostname matching code from curl - - -//#include <openssl/applink.c> // To prevent crashing (see the OpenSSL FAQ) - -bool StreamPeerOpenSSL::_match_host_name(const char *name, const char *hostname) { - - return Tool_Curl_cert_hostcheck(name,hostname)==CURL_HOST_MATCH; -// print_line("MATCH: "+String(name)+" vs "+String(hostname)); -// return true; -} - -Error StreamPeerOpenSSL::_match_common_name(const char *hostname, const X509 *server_cert) { - - int common_name_loc = -1; - X509_NAME_ENTRY *common_name_entry = NULL; - ASN1_STRING *common_name_asn1 = NULL; - char *common_name_str = NULL; - - // Find the position of the CN field in the Subject field of the certificate - common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name((X509 *) server_cert), NID_commonName, -1); - - ERR_FAIL_COND_V(common_name_loc < 0, ERR_INVALID_PARAMETER ); - - // Extract the CN field - common_name_entry = X509_NAME_get_entry(X509_get_subject_name((X509 *) server_cert), common_name_loc); - - ERR_FAIL_COND_V(common_name_entry == NULL, ERR_INVALID_PARAMETER ); - - // Convert the CN field to a C string - common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry); - - ERR_FAIL_COND_V(common_name_asn1 == NULL, ERR_INVALID_PARAMETER ); - - common_name_str = (char *) ASN1_STRING_data(common_name_asn1); - - // Make sure there isn't an embedded NUL character in the CN - bool malformed_certificate = (size_t)ASN1_STRING_length(common_name_asn1) != strlen(common_name_str); - - ERR_FAIL_COND_V(malformed_certificate, ERR_INVALID_PARAMETER ); - - - // Compare expected hostname with the CN - - - return _match_host_name(common_name_str,hostname)?OK:FAILED; - -} - - -/** -* Tries to find a match for hostname in the certificate's Subject Alternative Name extension. -* -*/ - -Error StreamPeerOpenSSL::_match_subject_alternative_name(const char *hostname, const X509 *server_cert) { - - Error result = FAILED; - int i; - int san_names_nb = -1; - STACK_OF(GENERAL_NAME) *san_names = NULL; - - // Try to extract the names within the SAN extension from the certificate - san_names = (STACK_OF(GENERAL_NAME) *)X509_get_ext_d2i((X509 *) server_cert, NID_subject_alt_name, NULL, NULL); - if (san_names == NULL) { - return ERR_FILE_NOT_FOUND; - } - san_names_nb = sk_GENERAL_NAME_num(san_names); - - // Check each name within the extension - for (i=0; i<san_names_nb; i++) { - const GENERAL_NAME *current_name = sk_GENERAL_NAME_value(san_names, i); - - if (current_name->type == GEN_DNS) { - // Current name is a DNS name, let's check it - char *dns_name = (char *) ASN1_STRING_data(current_name->d.dNSName); - - // Make sure there isn't an embedded NUL character in the DNS name - if ((size_t)ASN1_STRING_length(current_name->d.dNSName) != strlen(dns_name)) { - result = ERR_INVALID_PARAMETER; - break; - } - else { // Compare expected hostname with the DNS name - if (_match_host_name(dns_name, hostname)) { - result = OK; - break; - } - } - } - } - sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free); - - return result; -} - -/* See http://archives.seul.org/libevent/users/Jan-2013/msg00039.html */ -int StreamPeerOpenSSL::_cert_verify_callback(X509_STORE_CTX *x509_ctx, void *arg) { - - /* This is the function that OpenSSL would call if we hadn't called - * SSL_CTX_set_cert_verify_callback(). Therefore, we are "wrapping" - * the default functionality, rather than replacing it. */ - - bool base_cert_valid = X509_verify_cert(x509_ctx); - if (!base_cert_valid) { - print_line("Cause: "+String(X509_verify_cert_error_string(X509_STORE_CTX_get_error(x509_ctx)))); - ERR_print_errors_fp(stdout); - } - X509 *server_cert = X509_STORE_CTX_get_current_cert(x509_ctx); - - ERR_FAIL_COND_V(!server_cert,0); - - char cert_str[256]; - X509_NAME_oneline(X509_get_subject_name (server_cert), - cert_str, sizeof (cert_str)); - - print_line("CERT STR: "+String(cert_str)); - print_line("VALID: "+itos(base_cert_valid)); - - if (!base_cert_valid) - return 0; - - StreamPeerOpenSSL *ssl = (StreamPeerOpenSSL *)arg; - - if (ssl->validate_hostname) { - - Error err = _match_subject_alternative_name(ssl->hostname.utf8().get_data(),server_cert); - - if (err==ERR_FILE_NOT_FOUND) { - - err = _match_common_name(ssl->hostname.utf8().get_data(),server_cert); - } - - if (err!=OK) { - - ssl->status=STATUS_ERROR_HOSTNAME_MISMATCH; - return 0; - } - } - - return 1; - -} - - - -int StreamPeerOpenSSL::_bio_create( BIO *b ) { - b->init = 1; - b->num = 0; - b->ptr = NULL; - b->flags = 0; - return 1; -} - -int StreamPeerOpenSSL::_bio_destroy( BIO *b ) -{ - if ( b == NULL ) - return 0; - - b->ptr = NULL; /* sb_tls_remove() will free it */ - b->init = 0; - b->flags = 0; - return 1; -} - -int StreamPeerOpenSSL::_bio_read( BIO *b, char *buf, int len ) { - - - if ( buf == NULL || len <= 0 ) return 0; - - StreamPeerOpenSSL *sp = (StreamPeerOpenSSL *)b->ptr; - - ERR_FAIL_COND_V( sp == NULL, 0); - - BIO_clear_retry_flags( b ); - if (sp->use_blocking) { - - Error err = sp->base->get_data((uint8_t*)buf,len); - if (err!=OK) { - return -1; - } - - return len; - } else { - - int got; - Error err = sp->base->get_partial_data((uint8_t*)buf,len,got); - if (err!=OK) { - return -1; - } - if (got==0) { - BIO_set_retry_read( b ); - } - return got; - } - - //unreachable - return 0; -} - -int StreamPeerOpenSSL::_bio_write( BIO *b, const char *buf, int len ) { - - if ( buf == NULL || len <= 0 ) return 0; - - StreamPeerOpenSSL *sp = (StreamPeerOpenSSL *)b->ptr; - - ERR_FAIL_COND_V( sp == NULL, 0); - - BIO_clear_retry_flags( b ); - if (sp->use_blocking) { - - Error err = sp->base->put_data((const uint8_t*)buf,len); - if (err!=OK) { - return -1; - } - - return len; - } else { - - int sent; - Error err = sp->base->put_partial_data((const uint8_t*)buf,len,sent); - if (err!=OK) { - return -1; - } - if (sent==0) { - BIO_set_retry_write( b ); - } - return sent; - - } - - //unreachable - return 0; -} - -long StreamPeerOpenSSL::_bio_ctrl( BIO *b, int cmd, long num, void *ptr ) -{ - if ( cmd == BIO_CTRL_FLUSH ) { - /* The OpenSSL library needs this */ - return 1; - } - return 0; -} - -int StreamPeerOpenSSL::_bio_gets( BIO *b, char *buf, int len ) -{ - return -1; -} - -int StreamPeerOpenSSL::_bio_puts( BIO *b, const char *str ) -{ - return _bio_write( b, str, strlen( str ) ); -} - -BIO_METHOD StreamPeerOpenSSL::_bio_method = { - /* it's a source/sink BIO */ - ( 100 | 0x400 ), - "streampeer glue", - _bio_write, - _bio_read, - _bio_puts, - _bio_gets, - _bio_ctrl, - _bio_create, - _bio_destroy -}; - -Error StreamPeerOpenSSL::connect(Ref<StreamPeer> p_base, bool p_validate_certs, const String& p_for_hostname) { - - if (connected) - disconnect(); - - - hostname=p_for_hostname; - status=STATUS_DISCONNECTED; - - // Set up a SSL_CTX object, which will tell our BIO object how to do its work - ctx = SSL_CTX_new(SSLv23_client_method()); - base=p_base; - validate_certs=p_validate_certs; - validate_hostname=p_for_hostname!=""; - - - - - if (p_validate_certs) { - - - if (certs.size()) { - //yay for undocumented OpenSSL functions - - X509_STORE *store = SSL_CTX_get_cert_store(ctx); - for(int i=0;i<certs.size();i++) { - - X509_STORE_add_cert(store,certs[i]); - - } -#if 0 - const unsigned char *in=(const unsigned char *)certs.ptr(); - X509 *Cert = d2i_X509(NULL, &in, certs.size()-1); - if (!Cert) { - print_line(String(ERR_error_string(ERR_get_error(),NULL))); - } - ERR_FAIL_COND_V(!Cert,ERR_PARSE_ERROR); - - X509_STORE *store = SSL_CTX_get_cert_store(ctx); - X509_STORE_add_cert(store,Cert); - - //char *str = X509_NAME_oneline(X509_get_subject_name(Cert),0,0); - //printf ("subject: %s\n", str); /* [1] */ -#endif - } - - //used for testing - //int res = SSL_CTX_load_verify_locations(ctx,"/etc/ssl/certs/ca-certificates.crt",NULL); - //print_line("verify locations res: "+itos(res)); - - - /* Ask OpenSSL to verify the server certificate. Note that this - * does NOT include verifying that the hostname is correct. - * So, by itself, this means anyone with any legitimate - * CA-issued certificate for any website, can impersonate any - * other website in the world. This is not good. See "The - * Most Dangerous Code in the World" article at - * https://crypto.stanford.edu/~dabo/pubs/abstracts/ssl-client-bugs.html - */ - SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); - /* This is how we solve the problem mentioned in the previous - * comment. We "wrap" OpenSSL's validation routine in our - * own routine, which also validates the hostname by calling - * the code provided by iSECPartners. Note that even though - * the "Everything You've Always Wanted to Know About - * Certificate Validation With OpenSSL (But Were Afraid to - * Ask)" paper from iSECPartners says very explicitly not to - * call SSL_CTX_set_cert_verify_callback (at the bottom of - * page 2), what we're doing here is safe because our - * cert_verify_callback() calls X509_verify_cert(), which is - * OpenSSL's built-in routine which would have been called if - * we hadn't set the callback. Therefore, we're just - * "wrapping" OpenSSL's routine, not replacing it. */ - SSL_CTX_set_cert_verify_callback (ctx, _cert_verify_callback,this); - - //Let the verify_callback catch the verify_depth error so that we get an appropriate error in the logfile. (??) - SSL_CTX_set_verify_depth(ctx,max_cert_chain_depth + 1); - - } - - - - - - ssl = SSL_new( ctx ); - bio = BIO_new( &_bio_method ); - bio->ptr = this; - SSL_set_bio( ssl, bio, bio ); - - if (p_for_hostname!=String()) { - SSL_set_tlsext_host_name(ssl,p_for_hostname.utf8().get_data()); - } - - use_blocking=true; // let handshake use blocking - // Set the SSL to automatically retry on failure. - SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); - - // Same as before, try to connect. - int result = SSL_connect( ssl ); - - print_line("CONNECTION RESULT: "+itos(result)); - if (result<1) { - ERR_print_errors_fp(stdout); - _print_error(result); - } - - X509 * peer = SSL_get_peer_certificate(ssl); - - if (peer) { - bool cert_ok = SSL_get_verify_result(ssl) == X509_V_OK; - print_line("cert_ok: "+itos(cert_ok)); - - } else if (validate_certs){ - status=STATUS_ERROR_NO_CERTIFICATE; - } - - connected=true; - status=STATUS_CONNECTED; - - return OK; -} - -Error StreamPeerOpenSSL::accept(Ref<StreamPeer> p_base) { - - - return ERR_UNAVAILABLE; -} - -void StreamPeerOpenSSL::_print_error(int err) { - - err = SSL_get_error(ssl,err); - switch(err) { - case SSL_ERROR_NONE: ERR_PRINT("NO ERROR: The TLS/SSL I/O operation completed"); break; - case SSL_ERROR_ZERO_RETURN: ERR_PRINT("The TLS/SSL connection has been closed."); - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - ERR_PRINT("The operation did not complete."); break; - case SSL_ERROR_WANT_CONNECT: - case SSL_ERROR_WANT_ACCEPT: - ERR_PRINT("The connect/accept operation did not complete"); break; - case SSL_ERROR_WANT_X509_LOOKUP: - ERR_PRINT("The operation did not complete because an application callback set by SSL_CTX_set_client_cert_cb() has asked to be called again."); break; - case SSL_ERROR_SYSCALL: - ERR_PRINT("Some I/O error occurred. The OpenSSL error queue may contain more information on the error."); break; - case SSL_ERROR_SSL: - ERR_PRINT("A failure in the SSL library occurred, usually a protocol error."); break; - - } -} - -Error StreamPeerOpenSSL::put_data(const uint8_t* p_data,int p_bytes) { - - ERR_FAIL_COND_V(!connected,ERR_UNCONFIGURED); - - while(p_bytes>0) { - int ret = SSL_write(ssl,p_data,p_bytes); - if (ret<=0) { - _print_error(ret); - disconnect(); - return ERR_CONNECTION_ERROR; - } - p_data+=ret; - p_bytes-=ret; - } - - return OK; - -} - -Error StreamPeerOpenSSL::put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent){ - - ERR_FAIL_COND_V(!connected,ERR_UNCONFIGURED); - if (p_bytes==0) - return OK; - - Error err = put_data(p_data,p_bytes); - if (err!=OK) - return err; - - r_sent=p_bytes; - return OK; - -} - -Error StreamPeerOpenSSL::get_data(uint8_t* p_buffer, int p_bytes){ - - ERR_FAIL_COND_V(!connected,ERR_UNCONFIGURED); - - while(p_bytes>0) { - - int ret = SSL_read(ssl,p_buffer,p_bytes); - if (ret<=0) { - _print_error(ret); - disconnect(); - return ERR_CONNECTION_ERROR; - } - p_buffer+=ret; - p_bytes-=ret; - } - - return OK; -} - -Error StreamPeerOpenSSL::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received){ - - ERR_FAIL_COND_V(!connected,ERR_UNCONFIGURED); - if (p_bytes==0) { - r_received=0; - return OK; - } - - Error err = get_data(p_buffer,p_bytes); - if (err!=OK) - return err; - r_received=p_bytes; - return OK; -} - -int StreamPeerOpenSSL::get_available_bytes() const { - - ERR_FAIL_COND_V(!connected,0); - - return SSL_pending(ssl); - -} -StreamPeerOpenSSL::StreamPeerOpenSSL() { - - ctx=NULL; - ssl=NULL; - bio=NULL; - connected=false; - use_blocking=true; //might be improved int the future, but for now it always blocks - max_cert_chain_depth=9; - flags=0; -} - -void StreamPeerOpenSSL::disconnect() { - - if (!connected) - return; - SSL_shutdown( ssl ); - SSL_free( ssl ); - SSL_CTX_free(ctx); - base=Ref<StreamPeer>(); - connected=false; - validate_certs=false; - validate_hostname=false; - status=STATUS_DISCONNECTED; - - -} - -StreamPeerOpenSSL::Status StreamPeerOpenSSL::get_status() const { - - return status; -} - - -StreamPeerOpenSSL::~StreamPeerOpenSSL() { - disconnect(); -} - -StreamPeerSSL* StreamPeerOpenSSL::_create_func() { - - return memnew( StreamPeerOpenSSL ); -} - - -Vector<X509*> StreamPeerOpenSSL::certs; - - -void StreamPeerOpenSSL::_load_certs(const ByteArray& p_array) { - - ByteArray::Read r = p_array.read(); - BIO* mem = BIO_new(BIO_s_mem()); - BIO_puts(mem,(const char*)r.ptr()); - while(true) { - X509*cert = PEM_read_bio_X509(mem, NULL, 0, NULL); - if (!cert) - break; - certs.push_back(cert); - } - BIO_free(mem); -} - -void StreamPeerOpenSSL::initialize_ssl() { - - available=true; - - load_certs_func=_load_certs; - - _create=_create_func; - CRYPTO_malloc_init(); // Initialize malloc, free, etc for OpenSSL's use - SSL_library_init(); // Initialize OpenSSL's SSL libraries - SSL_load_error_strings(); // Load SSL error strings - ERR_load_BIO_strings(); // Load BIO error strings - OpenSSL_add_all_algorithms(); // Load all available encryption algorithms - String certs_path =GLOBAL_DEF("ssl/certificates",""); - Globals::get_singleton()->set_custom_property_info("ssl/certificates",PropertyInfo(Variant::STRING,"ssl/certificates",PROPERTY_HINT_FILE,"*.crt")); - if (certs_path!="") { - - - - FileAccess *f=FileAccess::open(certs_path,FileAccess::READ); - if (f) { - ByteArray arr; - int flen = f->get_len(); - arr.resize(flen+1); - { - ByteArray::Write w = arr.write(); - f->get_buffer(w.ptr(),flen); - w[flen]=0; //end f string - } - - memdelete(f); - - _load_certs(arr); - print_line("Loaded certs from '"+certs_path+"': "+itos(certs.size())); - } - } - String config_path =GLOBAL_DEF("ssl/config",""); - Globals::get_singleton()->set_custom_property_info("ssl/config",PropertyInfo(Variant::STRING,"ssl/config",PROPERTY_HINT_FILE,"*.cnf")); - if (config_path!="") { - - Vector<uint8_t> data = FileAccess::get_file_as_array(config_path); - if (data.size()) { - data.push_back(0); - BIO* mem = BIO_new(BIO_s_mem()); - BIO_puts(mem,(const char*) data.ptr()); - - while(true) { - X509*cert = PEM_read_bio_X509(mem, NULL, 0, NULL); - if (!cert) - break; - certs.push_back(cert); - } - BIO_free(mem); - } - print_line("Loaded certs from '"+certs_path+"': "+itos(certs.size())); - - } - -} - -void StreamPeerOpenSSL::finalize_ssl(){ - - for(int i=0;i<certs.size();i++) { - X509_free(certs[i]); - } - certs.clear(); -} - -#endif diff --git a/drivers/openssl/stream_peer_openssl.h b/drivers/openssl/stream_peer_openssl.h deleted file mode 100644 index f1f25f4fc5..0000000000 --- a/drivers/openssl/stream_peer_openssl.h +++ /dev/null @@ -1,113 +0,0 @@ -/*************************************************************************/ -/* stream_peer_openssl.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef STREAM_PEER_OPEN_SSL_H -#define STREAM_PEER_OPEN_SSL_H - -#ifdef OPENSSL_ENABLED - - -#include <stdio.h> // If you don't know what this is for stop reading now. -#include "io/stream_peer_ssl.h" -#include "globals.h" -#include "os/file_access.h" -#include "curl_hostcheck.h" - -#include <openssl/bio.h> // BIO objects for I/O -#include <openssl/ssl.h> // SSL and SSL_CTX for SSL connections -#include <openssl/err.h> // Error reporting -#include <openssl/x509v3.h> - -class StreamPeerOpenSSL : public StreamPeerSSL { -private: - static int _bio_create( BIO *b ); - static int _bio_destroy( BIO *b ); - static int _bio_read( BIO *b, char *buf, int len ); - static int _bio_write( BIO *b, const char *buf, int len ); - static long _bio_ctrl( BIO *b, int cmd, long num, void *ptr ); - static int _bio_gets( BIO *b, char *buf, int len ); - static int _bio_puts( BIO *b, const char *str ); - - static BIO_METHOD _bio_method; - - static bool _match_host_name(const char *name, const char *hostname); - static Error _match_common_name(const char *hostname, const X509 *server_cert); - static Error _match_subject_alternative_name(const char *hostname, const X509 *server_cert); - - - static int _cert_verify_callback(X509_STORE_CTX *x509_ctx, void *arg); - - - Status status; - String hostname; - int max_cert_chain_depth; - SSL_CTX* ctx; - SSL* ssl; - BIO* bio; - bool connected; - int flags; - bool use_blocking; - bool validate_certs; - bool validate_hostname; - - Ref<StreamPeer> base; - - static StreamPeerSSL* _create_func(); - void _print_error(int err); - - static Vector<X509*> certs; - - static void _load_certs(const ByteArray& p_array); -protected: - static void _bind_methods(); -public: - - - virtual Error accept(Ref<StreamPeer> p_base); - virtual Error connect(Ref<StreamPeer> p_base,bool p_validate_certs=false,const String& p_for_hostname=String()); - virtual Status get_status() const; - - virtual void disconnect(); - - virtual Error put_data(const uint8_t* p_data,int p_bytes); - virtual Error put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent); - - virtual Error get_data(uint8_t* p_buffer, int p_bytes); - virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received); - - virtual int get_available_bytes() const; - - static void initialize_ssl(); - static void finalize_ssl(); - - StreamPeerOpenSSL(); - ~StreamPeerOpenSSL(); -}; - -#endif -#endif // STREAM_PEER_SSL_H diff --git a/drivers/opus/SCsub b/drivers/opus/SCsub deleted file mode 100644 index bed8b496fc..0000000000 --- a/drivers/opus/SCsub +++ /dev/null @@ -1,196 +0,0 @@ -Import('env') - -opus_sources = [ - "opus/audio_stream_opus.cpp", -] - -opus_sources_silk=[] - -opus_sources_lib = [ - "opus/silk/tables_other.c", - "opus/silk/sum_sqr_shift.c", - "opus/silk/PLC.c", - "opus/silk/dec_API.c", - "opus/silk/decode_pulses.c", - "opus/silk/inner_prod_aligned.c", - "opus/silk/init_encoder.c", - "opus/silk/interpolate.c", - "opus/silk/stereo_encode_pred.c", - "opus/silk/decode_frame.c", - "opus/silk/NLSF_del_dec_quant.c", - "opus/silk/VAD.c", - "opus/silk/resampler_private_AR2.c", - "opus/silk/NLSF_unpack.c", - "opus/silk/resampler_down2.c", - "opus/silk/sort.c", - "opus/silk/resampler_private_IIR_FIR.c", - "opus/silk/resampler_down2_3.c", - "opus/silk/resampler_private_up2_HQ.c", - "opus/silk/tables_gain.c", - "opus/silk/stereo_find_predictor.c", - "opus/silk/stereo_quant_pred.c", - "opus/silk/NLSF_stabilize.c", - "opus/silk/ana_filt_bank_1.c", - "opus/silk/check_control_input.c", - "opus/silk/bwexpander.c", - "opus/silk/A2NLSF.c", - "opus/silk/LPC_inv_pred_gain.c", - "opus/silk/log2lin.c", - "opus/silk/process_NLSFs.c", - "opus/silk/sigm_Q15.c", - "opus/silk/VQ_WMat_EC.c", - "opus/silk/quant_LTP_gains.c", - "opus/silk/resampler_private_down_FIR.c", - "opus/silk/NLSF_decode.c", - "opus/silk/control_codec.c", - "opus/silk/NLSF_VQ_weights_laroia.c", - "opus/silk/decode_pitch.c", - "opus/silk/stereo_decode_pred.c", - "opus/silk/tables_pulses_per_block.c", - "opus/silk/init_decoder.c", - "opus/silk/table_LSF_cos.c", - "opus/silk/decode_core.c", - "opus/silk/code_signs.c", - "opus/silk/enc_API.c", - "opus/silk/tables_LTP.c", - "opus/silk/pitch_est_tables.c", - "opus/silk/biquad_alt.c", - "opus/silk/encode_indices.c", - "opus/silk/tables_NLSF_CB_WB.c", - "opus/silk/debug.c", - "opus/silk/decode_parameters.c", - "opus/silk/tables_pitch_lag.c", - "opus/silk/NLSF2A.c", - "opus/silk/resampler.c", - "opus/silk/decode_indices.c", - "opus/silk/NLSF_VQ.c", - "opus/silk/bwexpander_32.c", - "opus/silk/tables_NLSF_CB_NB_MB.c", - "opus/silk/encode_pulses.c", - "opus/silk/NSQ_del_dec.c", - "opus/silk/control_SNR.c", - "opus/silk/shell_coder.c", - "opus/silk/NLSF_encode.c", - "opus/silk/stereo_MS_to_LR.c", - "opus/silk/stereo_LR_to_MS.c", - "opus/silk/HP_variable_cutoff.c", - "opus/silk/LPC_analysis_filter.c", - "opus/silk/CNG.c", - "opus/silk/decoder_set_fs.c", - "opus/silk/resampler_rom.c", - "opus/silk/control_audio_bandwidth.c", - "opus/silk/lin2log.c", - "opus/silk/LP_variable_cutoff.c", - "opus/silk/NSQ.c", - "opus/silk/gain_quant.c", - "opus/celt/laplace.c", - "opus/celt/vq.c", - "opus/celt/quant_bands.c", - "opus/celt/kiss_fft.c", - "opus/celt/entcode.c", - "opus/celt/entenc.c", - "opus/celt/celt_lpc.c", - "opus/celt/pitch.c", - "opus/celt/rate.c", - "opus/celt/mathops.c", - #"opus/celt/arm/armcpu.c", - #"opus/celt/arm/celt_neon_intr.c", - #"opus/celt/arm/celt_ne10_mdct.c", - #"opus/celt/arm/celt_ne10_fft.c", - #"opus/celt/arm/arm_celt_map.c", - "opus/celt/celt_encoder.c", - "opus/celt/celt.c", - "opus/celt/bands.c", - "opus/celt/cwrs.c", - "opus/celt/entdec.c", - "opus/celt/celt_decoder.c", - "opus/celt/mdct.c", - "opus/celt/modes.c", - "opus/repacketizer.c", - "opus/mlp_data.c", - "opus/opus_multistream.c", - "opus/opusfile.c", - "opus/opus_encoder.c", - "opus/analysis.c", - "opus/mlp.c", - "opus/info.c", - "opus/stream.c", - "opus/opus_decoder.c", - "opus/internal.c", - "opus/wincerts.c", - "opus/opus.c", - "opus/opus_multistream_encoder.c", - "opus/http.c", - "opus/opus_multistream_decoder.c" -] - -if("opus_fixed_point" in env and env.opus_fixed_point=="yes"): - env.Append(CFLAGS=["-DOPUS_FIXED_POINT"]) - opus_sources_silk = [ - "opus/silk/fixed/schur64_FIX.c", - "opus/silk/fixed/residual_energy16_FIX.c", - "opus/silk/fixed/encode_frame_FIX.c", - "opus/silk/fixed/regularize_correlations_FIX.c", - "opus/silk/fixed/apply_sine_window_FIX.c", - "opus/silk/fixed/solve_LS_FIX.c", - "opus/silk/fixed/schur_FIX.c", - "opus/silk/fixed/pitch_analysis_core_FIX.c", - "opus/silk/fixed/noise_shape_analysis_FIX.c", - "opus/silk/fixed/find_LTP_FIX.c", - "opus/silk/fixed/vector_ops_FIX.c", - "opus/silk/fixed/autocorr_FIX.c", - "opus/silk/fixed/warped_autocorrelation_FIX.c", - "opus/silk/fixed/find_pitch_lags_FIX.c", - "opus/silk/fixed/k2a_Q16_FIX.c", - "opus/silk/fixed/LTP_scale_ctrl_FIX.c", - "opus/silk/fixed/corrMatrix_FIX.c", - "opus/silk/fixed/prefilter_FIX.c", - "opus/silk/fixed/find_LPC_FIX.c", - "opus/silk/fixed/residual_energy_FIX.c", - "opus/silk/fixed/process_gains_FIX.c", - "opus/silk/fixed/LTP_analysis_filter_FIX.c", - "opus/silk/fixed/k2a_FIX.c", - "opus/silk/fixed/burg_modified_FIX.c", - "opus/silk/fixed/find_pred_coefs_FIX.c" - ] -else: - opus_sources_silk = [ - "opus/silk/float/LTP_scale_ctrl_FLP.c", - "opus/silk/float/regularize_correlations_FLP.c", - "opus/silk/float/corrMatrix_FLP.c", - "opus/silk/float/LPC_analysis_filter_FLP.c", - "opus/silk/float/levinsondurbin_FLP.c", - "opus/silk/float/schur_FLP.c", - "opus/silk/float/scale_vector_FLP.c", - "opus/silk/float/apply_sine_window_FLP.c", - "opus/silk/float/pitch_analysis_core_FLP.c", - "opus/silk/float/wrappers_FLP.c", - "opus/silk/float/bwexpander_FLP.c", - "opus/silk/float/warped_autocorrelation_FLP.c", - "opus/silk/float/solve_LS_FLP.c", - "opus/silk/float/find_LPC_FLP.c", - "opus/silk/float/autocorrelation_FLP.c", - "opus/silk/float/find_pred_coefs_FLP.c", - "opus/silk/float/find_pitch_lags_FLP.c", - "opus/silk/float/burg_modified_FLP.c", - "opus/silk/float/find_LTP_FLP.c", - "opus/silk/float/energy_FLP.c", - "opus/silk/float/sort_FLP.c", - "opus/silk/float/LPC_inv_pred_gain_FLP.c", - "opus/silk/float/k2a_FLP.c", - "opus/silk/float/noise_shape_analysis_FLP.c", - "opus/silk/float/inner_product_FLP.c", - "opus/silk/float/process_gains_FLP.c", - "opus/silk/float/encode_frame_FLP.c", - "opus/silk/float/scale_copy_vector_FLP.c", - "opus/silk/float/residual_energy_FLP.c", - "opus/silk/float/LTP_analysis_filter_FLP.c", - "opus/silk/float/prefilter_FLP.c" - ] - - -env.drivers_sources+=opus_sources_silk -env.drivers_sources+=opus_sources_lib -env.drivers_sources+=opus_sources - -Export('env') diff --git a/drivers/opus/analysis.c b/drivers/opus/analysis.c deleted file mode 100644 index 6a0cd30113..0000000000 --- a/drivers/opus/analysis.c +++ /dev/null @@ -1,672 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/celt/kiss_fft.h" -#include "opus/celt/celt.h" -#include "opus/celt/modes.h" -#include "opus/celt/arch.h" -#include "opus/celt/quant_bands.h" -#include <stdio.h> -#include "opus/analysis.h" -#include "opus/mlp.h" -#include "opus/celt/stack_alloc.h" - -#ifndef M_PI -#define M_PI 3.141592653 -#endif - -static const float dct_table[128] = { - 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, - 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, - 0.351851f, 0.338330f, 0.311806f, 0.273300f, 0.224292f, 0.166664f, 0.102631f, 0.034654f, - -0.034654f,-0.102631f,-0.166664f,-0.224292f,-0.273300f,-0.311806f,-0.338330f,-0.351851f, - 0.346760f, 0.293969f, 0.196424f, 0.068975f,-0.068975f,-0.196424f,-0.293969f,-0.346760f, - -0.346760f,-0.293969f,-0.196424f,-0.068975f, 0.068975f, 0.196424f, 0.293969f, 0.346760f, - 0.338330f, 0.224292f, 0.034654f,-0.166664f,-0.311806f,-0.351851f,-0.273300f,-0.102631f, - 0.102631f, 0.273300f, 0.351851f, 0.311806f, 0.166664f,-0.034654f,-0.224292f,-0.338330f, - 0.326641f, 0.135299f,-0.135299f,-0.326641f,-0.326641f,-0.135299f, 0.135299f, 0.326641f, - 0.326641f, 0.135299f,-0.135299f,-0.326641f,-0.326641f,-0.135299f, 0.135299f, 0.326641f, - 0.311806f, 0.034654f,-0.273300f,-0.338330f,-0.102631f, 0.224292f, 0.351851f, 0.166664f, - -0.166664f,-0.351851f,-0.224292f, 0.102631f, 0.338330f, 0.273300f,-0.034654f,-0.311806f, - 0.293969f,-0.068975f,-0.346760f,-0.196424f, 0.196424f, 0.346760f, 0.068975f,-0.293969f, - -0.293969f, 0.068975f, 0.346760f, 0.196424f,-0.196424f,-0.346760f,-0.068975f, 0.293969f, - 0.273300f,-0.166664f,-0.338330f, 0.034654f, 0.351851f, 0.102631f,-0.311806f,-0.224292f, - 0.224292f, 0.311806f,-0.102631f,-0.351851f,-0.034654f, 0.338330f, 0.166664f,-0.273300f, -}; - -static const float analysis_window[240] = { - 0.000043f, 0.000171f, 0.000385f, 0.000685f, 0.001071f, 0.001541f, 0.002098f, 0.002739f, - 0.003466f, 0.004278f, 0.005174f, 0.006156f, 0.007222f, 0.008373f, 0.009607f, 0.010926f, - 0.012329f, 0.013815f, 0.015385f, 0.017037f, 0.018772f, 0.020590f, 0.022490f, 0.024472f, - 0.026535f, 0.028679f, 0.030904f, 0.033210f, 0.035595f, 0.038060f, 0.040604f, 0.043227f, - 0.045928f, 0.048707f, 0.051564f, 0.054497f, 0.057506f, 0.060591f, 0.063752f, 0.066987f, - 0.070297f, 0.073680f, 0.077136f, 0.080665f, 0.084265f, 0.087937f, 0.091679f, 0.095492f, - 0.099373f, 0.103323f, 0.107342f, 0.111427f, 0.115579f, 0.119797f, 0.124080f, 0.128428f, - 0.132839f, 0.137313f, 0.141849f, 0.146447f, 0.151105f, 0.155823f, 0.160600f, 0.165435f, - 0.170327f, 0.175276f, 0.180280f, 0.185340f, 0.190453f, 0.195619f, 0.200838f, 0.206107f, - 0.211427f, 0.216797f, 0.222215f, 0.227680f, 0.233193f, 0.238751f, 0.244353f, 0.250000f, - 0.255689f, 0.261421f, 0.267193f, 0.273005f, 0.278856f, 0.284744f, 0.290670f, 0.296632f, - 0.302628f, 0.308658f, 0.314721f, 0.320816f, 0.326941f, 0.333097f, 0.339280f, 0.345492f, - 0.351729f, 0.357992f, 0.364280f, 0.370590f, 0.376923f, 0.383277f, 0.389651f, 0.396044f, - 0.402455f, 0.408882f, 0.415325f, 0.421783f, 0.428254f, 0.434737f, 0.441231f, 0.447736f, - 0.454249f, 0.460770f, 0.467298f, 0.473832f, 0.480370f, 0.486912f, 0.493455f, 0.500000f, - 0.506545f, 0.513088f, 0.519630f, 0.526168f, 0.532702f, 0.539230f, 0.545751f, 0.552264f, - 0.558769f, 0.565263f, 0.571746f, 0.578217f, 0.584675f, 0.591118f, 0.597545f, 0.603956f, - 0.610349f, 0.616723f, 0.623077f, 0.629410f, 0.635720f, 0.642008f, 0.648271f, 0.654508f, - 0.660720f, 0.666903f, 0.673059f, 0.679184f, 0.685279f, 0.691342f, 0.697372f, 0.703368f, - 0.709330f, 0.715256f, 0.721144f, 0.726995f, 0.732807f, 0.738579f, 0.744311f, 0.750000f, - 0.755647f, 0.761249f, 0.766807f, 0.772320f, 0.777785f, 0.783203f, 0.788573f, 0.793893f, - 0.799162f, 0.804381f, 0.809547f, 0.814660f, 0.819720f, 0.824724f, 0.829673f, 0.834565f, - 0.839400f, 0.844177f, 0.848895f, 0.853553f, 0.858151f, 0.862687f, 0.867161f, 0.871572f, - 0.875920f, 0.880203f, 0.884421f, 0.888573f, 0.892658f, 0.896677f, 0.900627f, 0.904508f, - 0.908321f, 0.912063f, 0.915735f, 0.919335f, 0.922864f, 0.926320f, 0.929703f, 0.933013f, - 0.936248f, 0.939409f, 0.942494f, 0.945503f, 0.948436f, 0.951293f, 0.954072f, 0.956773f, - 0.959396f, 0.961940f, 0.964405f, 0.966790f, 0.969096f, 0.971321f, 0.973465f, 0.975528f, - 0.977510f, 0.979410f, 0.981228f, 0.982963f, 0.984615f, 0.986185f, 0.987671f, 0.989074f, - 0.990393f, 0.991627f, 0.992778f, 0.993844f, 0.994826f, 0.995722f, 0.996534f, 0.997261f, - 0.997902f, 0.998459f, 0.998929f, 0.999315f, 0.999615f, 0.999829f, 0.999957f, 1.000000f, -}; - -static const int tbands[NB_TBANDS+1] = { - 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120 -}; - -static const int extra_bands[NB_TOT_BANDS+1] = { - 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120, 160, 200 -}; - -/*static const float tweight[NB_TBANDS+1] = { - .3, .4, .5, .6, .7, .8, .9, 1., 1., 1., 1., 1., 1., 1., .8, .7, .6, .5 -};*/ - -#define NB_TONAL_SKIP_BANDS 9 - -#define cA 0.43157974f -#define cB 0.67848403f -#define cC 0.08595542f -#define cE ((float)M_PI/2) -static OPUS_INLINE float fast_atan2f(float y, float x) { - float x2, y2; - /* Should avoid underflow on the values we'll get */ - if (ABS16(x)+ABS16(y)<1e-9f) - { - x*=1e12f; - y*=1e12f; - } - x2 = x*x; - y2 = y*y; - if(x2<y2){ - float den = (y2 + cB*x2) * (y2 + cC*x2); - if (den!=0) - return -x*y*(y2 + cA*x2) / den + (y<0 ? -cE : cE); - else - return (y<0 ? -cE : cE); - }else{ - float den = (x2 + cB*y2) * (x2 + cC*y2); - if (den!=0) - return x*y*(x2 + cA*y2) / den + (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE); - else - return (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE); - } -} - -void tonality_analysis_init(TonalityAnalysisState *tonal) -{ - /* Initialize reusable fields. */ - tonal->arch = opus_select_arch(); - /* Clear remaining fields. */ - tonality_analysis_reset(tonal); -} - -void tonality_analysis_reset(TonalityAnalysisState *tonal) -{ - /* Clear non-reusable fields. */ - char *start = (char*)&tonal->TONALITY_ANALYSIS_RESET_START; - OPUS_CLEAR(start, sizeof(TonalityAnalysisState) - (start - (char*)tonal)); -} - -void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len) -{ - int pos; - int curr_lookahead; - float psum; - int i; - - pos = tonal->read_pos; - curr_lookahead = tonal->write_pos-tonal->read_pos; - if (curr_lookahead<0) - curr_lookahead += DETECT_SIZE; - - if (len > 480 && pos != tonal->write_pos) - { - pos++; - if (pos==DETECT_SIZE) - pos=0; - } - if (pos == tonal->write_pos) - pos--; - if (pos<0) - pos = DETECT_SIZE-1; - OPUS_COPY(info_out, &tonal->info[pos], 1); - tonal->read_subframe += len/120; - while (tonal->read_subframe>=4) - { - tonal->read_subframe -= 4; - tonal->read_pos++; - } - if (tonal->read_pos>=DETECT_SIZE) - tonal->read_pos-=DETECT_SIZE; - - /* Compensate for the delay in the features themselves. - FIXME: Need a better estimate the 10 I just made up */ - curr_lookahead = IMAX(curr_lookahead-10, 0); - - psum=0; - /* Summing the probability of transition patterns that involve music at - time (DETECT_SIZE-curr_lookahead-1) */ - for (i=0;i<DETECT_SIZE-curr_lookahead;i++) - psum += tonal->pmusic[i]; - for (;i<DETECT_SIZE;i++) - psum += tonal->pspeech[i]; - psum = psum*tonal->music_confidence + (1-psum)*tonal->speech_confidence; - /*printf("%f %f %f\n", psum, info_out->music_prob, info_out->tonality);*/ - - info_out->music_prob = psum; -} - -static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt_mode, const void *x, int len, int offset, int c1, int c2, int C, int lsb_depth, downmix_func downmix) -{ - int i, b; - const kiss_fft_state *kfft; - VARDECL(kiss_fft_cpx, in); - VARDECL(kiss_fft_cpx, out); - int N = 480, N2=240; - float * OPUS_RESTRICT A = tonal->angle; - float * OPUS_RESTRICT dA = tonal->d_angle; - float * OPUS_RESTRICT d2A = tonal->d2_angle; - VARDECL(float, tonality); - VARDECL(float, noisiness); - float band_tonality[NB_TBANDS]; - float logE[NB_TBANDS]; - float BFCC[8]; - float features[25]; - float frame_tonality; - float max_frame_tonality; - /*float tw_sum=0;*/ - float frame_noisiness; - const float pi4 = (float)(M_PI*M_PI*M_PI*M_PI); - float slope=0; - float frame_stationarity; - float relativeE; - float frame_probs[2]; - float alpha, alphaE, alphaE2; - float frame_loudness; - float bandwidth_mask; - int bandwidth=0; - float maxE = 0; - float noise_floor; - int remaining; - AnalysisInfo *info; - SAVE_STACK; - - tonal->last_transition++; - alpha = 1.f/IMIN(20, 1+tonal->count); - alphaE = 1.f/IMIN(50, 1+tonal->count); - alphaE2 = 1.f/IMIN(1000, 1+tonal->count); - - if (tonal->count<4) - tonal->music_prob = .5; - kfft = celt_mode->mdct.kfft[0]; - if (tonal->count==0) - tonal->mem_fill = 240; - downmix(x, &tonal->inmem[tonal->mem_fill], IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, c1, c2, C); - if (tonal->mem_fill+len < ANALYSIS_BUF_SIZE) - { - tonal->mem_fill += len; - /* Don't have enough to update the analysis */ - RESTORE_STACK; - return; - } - info = &tonal->info[tonal->write_pos++]; - if (tonal->write_pos>=DETECT_SIZE) - tonal->write_pos-=DETECT_SIZE; - - ALLOC(in, 480, kiss_fft_cpx); - ALLOC(out, 480, kiss_fft_cpx); - ALLOC(tonality, 240, float); - ALLOC(noisiness, 240, float); - for (i=0;i<N2;i++) - { - float w = analysis_window[i]; - in[i].r = (kiss_fft_scalar)(w*tonal->inmem[i]); - in[i].i = (kiss_fft_scalar)(w*tonal->inmem[N2+i]); - in[N-i-1].r = (kiss_fft_scalar)(w*tonal->inmem[N-i-1]); - in[N-i-1].i = (kiss_fft_scalar)(w*tonal->inmem[N+N2-i-1]); - } - OPUS_MOVE(tonal->inmem, tonal->inmem+ANALYSIS_BUF_SIZE-240, 240); - remaining = len - (ANALYSIS_BUF_SIZE-tonal->mem_fill); - downmix(x, &tonal->inmem[240], remaining, offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C); - tonal->mem_fill = 240 + remaining; - opus_fft(kfft, in, out, tonal->arch); -#ifndef OPUS_FIXED_POINT - /* If there's any NaN on the input, the entire output will be NaN, so we only need to check one value. */ - if (celt_isnan(out[0].r)) - { - info->valid = 0; - RESTORE_STACK; - return; - } -#endif - - for (i=1;i<N2;i++) - { - float X1r, X2r, X1i, X2i; - float angle, d_angle, d2_angle; - float angle2, d_angle2, d2_angle2; - float mod1, mod2, avg_mod; - X1r = (float)out[i].r+out[N-i].r; - X1i = (float)out[i].i-out[N-i].i; - X2r = (float)out[i].i+out[N-i].i; - X2i = (float)out[N-i].r-out[i].r; - - angle = (float)(.5f/M_PI)*fast_atan2f(X1i, X1r); - d_angle = angle - A[i]; - d2_angle = d_angle - dA[i]; - - angle2 = (float)(.5f/M_PI)*fast_atan2f(X2i, X2r); - d_angle2 = angle2 - angle; - d2_angle2 = d_angle2 - d_angle; - - mod1 = d2_angle - (float)floor(.5+d2_angle); - noisiness[i] = ABS16(mod1); - mod1 *= mod1; - mod1 *= mod1; - - mod2 = d2_angle2 - (float)floor(.5+d2_angle2); - noisiness[i] += ABS16(mod2); - mod2 *= mod2; - mod2 *= mod2; - - avg_mod = .25f*(d2A[i]+2.f*mod1+mod2); - tonality[i] = 1.f/(1.f+40.f*16.f*pi4*avg_mod)-.015f; - - A[i] = angle2; - dA[i] = d_angle2; - d2A[i] = mod2; - } - - frame_tonality = 0; - max_frame_tonality = 0; - /*tw_sum = 0;*/ - info->activity = 0; - frame_noisiness = 0; - frame_stationarity = 0; - if (!tonal->count) - { - for (b=0;b<NB_TBANDS;b++) - { - tonal->lowE[b] = 1e10; - tonal->highE[b] = -1e10; - } - } - relativeE = 0; - frame_loudness = 0; - for (b=0;b<NB_TBANDS;b++) - { - float E=0, tE=0, nE=0; - float L1, L2; - float stationarity; - for (i=tbands[b];i<tbands[b+1];i++) - { - float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r - + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i; -#ifdef OPUS_FIXED_POINT - /* FIXME: It's probably best to change the BFCC filter initial state instead */ - binE *= 5.55e-17f; -#endif - E += binE; - tE += binE*tonality[i]; - nE += binE*2.f*(.5f-noisiness[i]); - } -#ifndef OPUS_FIXED_POINT - /* Check for extreme band energies that could cause NaNs later. */ - if (!(E<1e9f) || celt_isnan(E)) - { - info->valid = 0; - RESTORE_STACK; - return; - } -#endif - - tonal->E[tonal->E_count][b] = E; - frame_noisiness += nE/(1e-15f+E); - - frame_loudness += (float)sqrt(E+1e-10f); - logE[b] = (float)log(E+1e-10f); - tonal->lowE[b] = MIN32(logE[b], tonal->lowE[b]+.01f); - tonal->highE[b] = MAX32(logE[b], tonal->highE[b]-.1f); - if (tonal->highE[b] < tonal->lowE[b]+1.f) - { - tonal->highE[b]+=.5f; - tonal->lowE[b]-=.5f; - } - relativeE += (logE[b]-tonal->lowE[b])/(1e-15f+tonal->highE[b]-tonal->lowE[b]); - - L1=L2=0; - for (i=0;i<NB_FRAMES;i++) - { - L1 += (float)sqrt(tonal->E[i][b]); - L2 += tonal->E[i][b]; - } - - stationarity = MIN16(0.99f,L1/(float)sqrt(1e-15+NB_FRAMES*L2)); - stationarity *= stationarity; - stationarity *= stationarity; - frame_stationarity += stationarity; - /*band_tonality[b] = tE/(1e-15+E)*/; - band_tonality[b] = MAX16(tE/(1e-15f+E), stationarity*tonal->prev_band_tonality[b]); -#if 0 - if (b>=NB_TONAL_SKIP_BANDS) - { - frame_tonality += tweight[b]*band_tonality[b]; - tw_sum += tweight[b]; - } -#else - frame_tonality += band_tonality[b]; - if (b>=NB_TBANDS-NB_TONAL_SKIP_BANDS) - frame_tonality -= band_tonality[b-NB_TBANDS+NB_TONAL_SKIP_BANDS]; -#endif - max_frame_tonality = MAX16(max_frame_tonality, (1.f+.03f*(b-NB_TBANDS))*frame_tonality); - slope += band_tonality[b]*(b-8); - /*printf("%f %f ", band_tonality[b], stationarity);*/ - tonal->prev_band_tonality[b] = band_tonality[b]; - } - - bandwidth_mask = 0; - bandwidth = 0; - maxE = 0; - noise_floor = 5.7e-4f/(1<<(IMAX(0,lsb_depth-8))); -#ifdef OPUS_FIXED_POINT - noise_floor *= 1<<(15+SIG_SHIFT); -#endif - noise_floor *= noise_floor; - for (b=0;b<NB_TOT_BANDS;b++) - { - float E=0; - int band_start, band_end; - /* Keep a margin of 300 Hz for aliasing */ - band_start = extra_bands[b]; - band_end = extra_bands[b+1]; - for (i=band_start;i<band_end;i++) - { - float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r - + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i; - E += binE; - } - maxE = MAX32(maxE, E); - tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E); - E = MAX32(E, tonal->meanE[b]); - /* Use a simple follower with 13 dB/Bark slope for spreading function */ - bandwidth_mask = MAX32(.05f*bandwidth_mask, E); - /* Consider the band "active" only if all these conditions are met: - 1) less than 10 dB below the simple follower - 2) less than 90 dB below the peak band (maximal masking possible considering - both the ATH and the loudness-dependent slope of the spreading function) - 3) above the PCM quantization noise floor - */ - if (E>.1*bandwidth_mask && E*1e9f > maxE && E > noise_floor*(band_end-band_start)) - bandwidth = b; - } - if (tonal->count<=2) - bandwidth = 20; - frame_loudness = 20*(float)log10(frame_loudness); - tonal->Etracker = MAX32(tonal->Etracker-.03f, frame_loudness); - tonal->lowECount *= (1-alphaE); - if (frame_loudness < tonal->Etracker-30) - tonal->lowECount += alphaE; - - for (i=0;i<8;i++) - { - float sum=0; - for (b=0;b<16;b++) - sum += dct_table[i*16+b]*logE[b]; - BFCC[i] = sum; - } - - frame_stationarity /= NB_TBANDS; - relativeE /= NB_TBANDS; - if (tonal->count<10) - relativeE = .5; - frame_noisiness /= NB_TBANDS; -#if 1 - info->activity = frame_noisiness + (1-frame_noisiness)*relativeE; -#else - info->activity = .5*(1+frame_noisiness-frame_stationarity); -#endif - frame_tonality = (max_frame_tonality/(NB_TBANDS-NB_TONAL_SKIP_BANDS)); - frame_tonality = MAX16(frame_tonality, tonal->prev_tonality*.8f); - tonal->prev_tonality = frame_tonality; - - slope /= 8*8; - info->tonality_slope = slope; - - tonal->E_count = (tonal->E_count+1)%NB_FRAMES; - tonal->count++; - info->tonality = frame_tonality; - - for (i=0;i<4;i++) - features[i] = -0.12299f*(BFCC[i]+tonal->mem[i+24]) + 0.49195f*(tonal->mem[i]+tonal->mem[i+16]) + 0.69693f*tonal->mem[i+8] - 1.4349f*tonal->cmean[i]; - - for (i=0;i<4;i++) - tonal->cmean[i] = (1-alpha)*tonal->cmean[i] + alpha*BFCC[i]; - - for (i=0;i<4;i++) - features[4+i] = 0.63246f*(BFCC[i]-tonal->mem[i+24]) + 0.31623f*(tonal->mem[i]-tonal->mem[i+16]); - for (i=0;i<3;i++) - features[8+i] = 0.53452f*(BFCC[i]+tonal->mem[i+24]) - 0.26726f*(tonal->mem[i]+tonal->mem[i+16]) -0.53452f*tonal->mem[i+8]; - - if (tonal->count > 5) - { - for (i=0;i<9;i++) - tonal->std[i] = (1-alpha)*tonal->std[i] + alpha*features[i]*features[i]; - } - - for (i=0;i<8;i++) - { - tonal->mem[i+24] = tonal->mem[i+16]; - tonal->mem[i+16] = tonal->mem[i+8]; - tonal->mem[i+8] = tonal->mem[i]; - tonal->mem[i] = BFCC[i]; - } - for (i=0;i<9;i++) - features[11+i] = (float)sqrt(tonal->std[i]); - features[20] = info->tonality; - features[21] = info->activity; - features[22] = frame_stationarity; - features[23] = info->tonality_slope; - features[24] = tonal->lowECount; - -#ifndef DISABLE_FLOAT_API - mlp_process(&net, features, frame_probs); - frame_probs[0] = .5f*(frame_probs[0]+1); - /* Curve fitting between the MLP probability and the actual probability */ - frame_probs[0] = .01f + 1.21f*frame_probs[0]*frame_probs[0] - .23f*(float)pow(frame_probs[0], 10); - /* Probability of active audio (as opposed to silence) */ - frame_probs[1] = .5f*frame_probs[1]+.5f; - /* Consider that silence has a 50-50 probability. */ - frame_probs[0] = frame_probs[1]*frame_probs[0] + (1-frame_probs[1])*.5f; - - /*printf("%f %f ", frame_probs[0], frame_probs[1]);*/ - { - /* Probability of state transition */ - float tau; - /* Represents independence of the MLP probabilities, where - beta=1 means fully independent. */ - float beta; - /* Denormalized probability of speech (p0) and music (p1) after update */ - float p0, p1; - /* Probabilities for "all speech" and "all music" */ - float s0, m0; - /* Probability sum for renormalisation */ - float psum; - /* Instantaneous probability of speech and music, with beta pre-applied. */ - float speech0; - float music0; - - /* One transition every 3 minutes of active audio */ - tau = .00005f*frame_probs[1]; - beta = .05f; - if (1) { - /* Adapt beta based on how "unexpected" the new prob is */ - float p, q; - p = MAX16(.05f,MIN16(.95f,frame_probs[0])); - q = MAX16(.05f,MIN16(.95f,tonal->music_prob)); - beta = .01f+.05f*ABS16(p-q)/(p*(1-q)+q*(1-p)); - } - /* p0 and p1 are the probabilities of speech and music at this frame - using only information from previous frame and applying the - state transition model */ - p0 = (1-tonal->music_prob)*(1-tau) + tonal->music_prob *tau; - p1 = tonal->music_prob *(1-tau) + (1-tonal->music_prob)*tau; - /* We apply the current probability with exponent beta to work around - the fact that the probability estimates aren't independent. */ - p0 *= (float)pow(1-frame_probs[0], beta); - p1 *= (float)pow(frame_probs[0], beta); - /* Normalise the probabilities to get the Marokv probability of music. */ - tonal->music_prob = p1/(p0+p1); - info->music_prob = tonal->music_prob; - - /* This chunk of code deals with delayed decision. */ - psum=1e-20f; - /* Instantaneous probability of speech and music, with beta pre-applied. */ - speech0 = (float)pow(1-frame_probs[0], beta); - music0 = (float)pow(frame_probs[0], beta); - if (tonal->count==1) - { - tonal->pspeech[0]=.5; - tonal->pmusic [0]=.5; - } - /* Updated probability of having only speech (s0) or only music (m0), - before considering the new observation. */ - s0 = tonal->pspeech[0] + tonal->pspeech[1]; - m0 = tonal->pmusic [0] + tonal->pmusic [1]; - /* Updates s0 and m0 with instantaneous probability. */ - tonal->pspeech[0] = s0*(1-tau)*speech0; - tonal->pmusic [0] = m0*(1-tau)*music0; - /* Propagate the transition probabilities */ - for (i=1;i<DETECT_SIZE-1;i++) - { - tonal->pspeech[i] = tonal->pspeech[i+1]*speech0; - tonal->pmusic [i] = tonal->pmusic [i+1]*music0; - } - /* Probability that the latest frame is speech, when all the previous ones were music. */ - tonal->pspeech[DETECT_SIZE-1] = m0*tau*speech0; - /* Probability that the latest frame is music, when all the previous ones were speech. */ - tonal->pmusic [DETECT_SIZE-1] = s0*tau*music0; - - /* Renormalise probabilities to 1 */ - for (i=0;i<DETECT_SIZE;i++) - psum += tonal->pspeech[i] + tonal->pmusic[i]; - psum = 1.f/psum; - for (i=0;i<DETECT_SIZE;i++) - { - tonal->pspeech[i] *= psum; - tonal->pmusic [i] *= psum; - } - psum = tonal->pmusic[0]; - for (i=1;i<DETECT_SIZE;i++) - psum += tonal->pspeech[i]; - - /* Estimate our confidence in the speech/music decisions */ - if (frame_probs[1]>.75) - { - if (tonal->music_prob>.9) - { - float adapt; - adapt = 1.f/(++tonal->music_confidence_count); - tonal->music_confidence_count = IMIN(tonal->music_confidence_count, 500); - tonal->music_confidence += adapt*MAX16(-.2f,frame_probs[0]-tonal->music_confidence); - } - if (tonal->music_prob<.1) - { - float adapt; - adapt = 1.f/(++tonal->speech_confidence_count); - tonal->speech_confidence_count = IMIN(tonal->speech_confidence_count, 500); - tonal->speech_confidence += adapt*MIN16(.2f,frame_probs[0]-tonal->speech_confidence); - } - } else { - if (tonal->music_confidence_count==0) - tonal->music_confidence = .9f; - if (tonal->speech_confidence_count==0) - tonal->speech_confidence = .1f; - } - } - if (tonal->last_music != (tonal->music_prob>.5f)) - tonal->last_transition=0; - tonal->last_music = tonal->music_prob>.5f; -#else - info->music_prob = 0; -#endif - /*for (i=0;i<25;i++) - printf("%f ", features[i]); - printf("\n");*/ - - info->bandwidth = bandwidth; - /*printf("%d %d\n", info->bandwidth, info->opus_bandwidth);*/ - info->noisiness = frame_noisiness; - info->valid = 1; - RESTORE_STACK; -} - -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) -{ - int offset; - int pcm_len; - - if (analysis_pcm != NULL) - { - /* Avoid overflow/wrap-around of the analysis buffer */ - analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/100, analysis_frame_size); - - pcm_len = analysis_frame_size - analysis->analysis_offset; - offset = analysis->analysis_offset; - do { - tonality_analysis(analysis, celt_mode, analysis_pcm, IMIN(480, pcm_len), offset, c1, c2, C, lsb_depth, downmix); - offset += 480; - pcm_len -= 480; - } while (pcm_len>0); - analysis->analysis_offset = analysis_frame_size; - - analysis->analysis_offset -= frame_size; - } - - analysis_info->valid = 0; - tonality_get_info(analysis, analysis_info, frame_size); -} diff --git a/drivers/opus/analysis.h b/drivers/opus/analysis.h deleted file mode 100644 index 9d81164e25..0000000000 --- a/drivers/opus/analysis.h +++ /dev/null @@ -1,103 +0,0 @@ -/* 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 "opus/celt/celt.h" -#include "opus/opus_private.h" - -#define NB_FRAMES 8 -#define NB_TBANDS 18 -#define NB_TOT_BANDS 21 -#define ANALYSIS_BUF_SIZE 720 /* 15 ms at 48 kHz */ - -#define DETECT_SIZE 200 - -typedef struct { - int arch; -#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; - float E[NB_FRAMES][NB_TBANDS]; - float lowE[NB_TBANDS]; - float highE[NB_TBANDS]; - float meanE[NB_TOT_BANDS]; - float mem[32]; - float cmean[8]; - float std[9]; - float music_prob; - float Etracker; - float lowECount; - int E_count; - int last_music; - int last_transition; - int count; - float subframe_mem[3]; - int analysis_offset; - /** Probability of having speech for time i to DETECT_SIZE-1 (and music before). - pspeech[0] is the probability that all frames in the window are speech. */ - float pspeech[DETECT_SIZE]; - /** Probability of having music for time i to DETECT_SIZE-1 (and speech before). - pmusic[0] is the probability that all frames in the window are music. */ - float pmusic[DETECT_SIZE]; - float speech_confidence; - float music_confidence; - int speech_confidence_count; - int music_confidence_count; - int write_pos; - int read_pos; - int read_subframe; - 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); - -/** Reset a TonalityAnalysisState stuct. - * - * 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/drivers/opus/audio_stream_opus.h b/drivers/opus/audio_stream_opus.h deleted file mode 100644 index fc5531470d..0000000000 --- a/drivers/opus/audio_stream_opus.h +++ /dev/null @@ -1,141 +0,0 @@ -/*************************************************************************/ -/* audio_stream_opus.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Author: George Marques <george@gmarqu.es> */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef AUDIO_STREAM_OPUS_H -#define AUDIO_STREAM_OPUS_H - -#include "scene/resources/audio_stream.h" -#include "opus/opusfile.h" -#include "opus/internal.h" -#include "os/file_access.h" -#include "io/resource_loader.h" - -class AudioStreamPlaybackOpus : public AudioStreamPlayback { - - OBJ_TYPE(AudioStreamPlaybackOpus,AudioStreamPlayback) - - enum { - MIN_MIX=1024 - }; - - FileAccess *f; - - OpusFileCallbacks _op_callbacks; - float length; - static int _op_read_func(void *_stream, unsigned char *_ptr, int _nbytes); - static int _op_seek_func(void *_stream, opus_int64 _offset, int _whence); - static int _op_close_func(void *_stream); - static opus_int64 _op_tell_func(void *_stream); - static const float osrate; - - String file; - int64_t frames_mixed; - - bool stream_loaded; - volatile bool playing; - OggOpusFile *opus_file; - int stream_channels; - int current_section; - int pre_skip; - - bool paused; - bool loops; - int repeats; - - Error _load_stream(); - void _clear_stream(); - void _close_file(); - - bool stream_valid; - float loop_restart_time; - -public: - Error set_file(const String& p_file); - - virtual void play(float p_from=0); - virtual void stop(); - virtual bool is_playing() const { return playing; } - - virtual void set_loop_restart_time(float p_time) { loop_restart_time=p_time; } - - virtual void set_paused(bool p_paused) { paused=p_paused; } - virtual bool is_paused() const { return paused; } - - virtual void set_loop(bool p_enable) { loops=p_enable; } - virtual bool has_loop() const {return loops; } - - virtual float get_length() const; - - virtual String get_stream_name() const { return ""; } - - virtual int get_loop_count() const { return repeats; } - - virtual float get_pos() const; - virtual void seek_pos(float p_time); - - virtual int get_channels() const { return stream_channels; } - virtual int get_mix_rate() const { return osrate; } - - virtual int get_minimum_buffer_size() const; - - virtual int mix(int16_t* p_bufer,int p_frames); - - AudioStreamPlaybackOpus(); - ~AudioStreamPlaybackOpus(); -}; - - -class AudioStreamOpus: public AudioStream { - - OBJ_TYPE(AudioStreamOpus,AudioStream) - - String file; -public: - - Ref<AudioStreamPlayback> instance_playback() { - Ref<AudioStreamPlaybackOpus> pb = memnew( AudioStreamPlaybackOpus ); - pb->set_file(file); - return pb; - } - - void set_file(const String& p_file) { file=p_file; } - -}; - -class ResourceFormatLoaderAudioStreamOpus: public ResourceFormatLoader { -public: - virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); - virtual void get_recognized_extensions(List<String> *p_extensions) const; - virtual bool handles_type(const String& p_type) const; - virtual String get_resource_type(const String &p_path) const; -}; - -#endif // AUDIO_STREAM_OPUS_H diff --git a/drivers/opus/celt/_kiss_fft_guts.h b/drivers/opus/celt/_kiss_fft_guts.h deleted file mode 100644 index a41f9a1a05..0000000000 --- a/drivers/opus/celt/_kiss_fft_guts.h +++ /dev/null @@ -1,182 +0,0 @@ -/*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 "opus/celt/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 OPUS_FIXED_POINT -#include "opus/celt/arch.h" - - -#define SAMP_MAX 2147483647 -#define TWID_MAX 32767 -#define TRIG_UPSCALE 1 - -#define SAMP_MIN -SAMP_MAX - - -# define S_MUL(a,b) MULT16_32_Q15(b, a) - -# define C_MUL(m,a,b) \ - do{ (m).r = SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ - (m).i = ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0) - -# define C_MULC(m,a,b) \ - do{ (m).r = ADD32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ - (m).i = SUB32(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((a).r,(b).r); (res).i=ADD32((a).i,(b).i); \ - }while(0) -#define C_SUB( res, a,b)\ - do {(res).r=SUB32((a).r,(b).r); (res).i=SUB32((a).i,(b).i); \ - }while(0) -#define C_ADDTO( res , a)\ - do {(res).r = ADD32((res).r, (a).r); (res).i = ADD32((res).i,(a).i);\ - }while(0) - -#define C_SUBFROM( res , a)\ - do {(res).r = ADD32((res).r,(a).r); (res).i = SUB32((res).i,(a).i); \ - }while(0) - -#if defined(OPUS_ARM_INLINE_ASM) -#include "opus/celt/arm/kiss_fft_armv4.h" -#endif - -#if defined(OPUS_ARM_INLINE_EDSP) -#include "opus/celt/arm/kiss_fft_armv5e.h" -#endif -#if defined(MIPSr1_ASM) -#include "opus/celt/mips/kiss_fft_mipsr1.h" -#endif - -#else /* not FIXED_POINT*/ - -# define S_MUL(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 OPUS_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/drivers/opus/celt/arch.h b/drivers/opus/celt/arch.h deleted file mode 100644 index 7fb036e9fe..0000000000 --- a/drivers/opus/celt/arch.h +++ /dev/null @@ -1,241 +0,0 @@ -/* 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/opus_types.h" -#include "opus/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 - -#define CELT_SIG_SCALE 32768.f - -#define celt_fatal(str) _celt_fatal(str, __FILE__, __LINE__); -#ifdef ENABLE_ASSERTIONS -#include <stdio.h> -#include <stdlib.h> -#ifdef __GNUC__ -__attribute__((noreturn)) -#endif -static OPUS_INLINE 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); - abort(); -} -#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);}} -#else -#define celt_assert(cond) -#define celt_assert2(cond, message) -#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 UADD32(a,b) ((a)+(b)) -#define USUB32(a,b) ((a)-(b)) - -#define PRINT_MIPS(file) - -#ifdef OPUS_FIXED_POINT - -typedef opus_int16 opus_val16; -typedef opus_int32 opus_val32; - -typedef opus_val32 celt_sig; -typedef opus_val16 celt_norm; -typedef opus_val32 celt_ener; - -#define Q15ONE 32767 - -#define SIG_SHIFT 12 - -#define NORM_SCALING 16384 - -#define DB_SHIFT 10 - -#define EPSILON 1 -#define VERY_SMALL 0 -#define VERY_LARGE16 ((opus_val16)32767) -#define Q15_ONE ((opus_val16)32767) - -#define SCALEIN(a) (a) -#define SCALEOUT(a) (a) - -#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 "opus/celt/fixed_debug.h" -#else - -#include "opus/celt/fixed_generic.h" - -#ifdef OPUS_ARM_INLINE_EDSP -#include "opus/celt/arm/fixed_armv5e.h" -#elif defined (OPUS_ARM_INLINE_ASM) -#include "opus/celt/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 celt_sig; -typedef float celt_norm; -typedef float celt_ener; - -#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 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 NEG16(x) (-(x)) -#define NEG32(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 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 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 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_Q31(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 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 DIV32_16(a,b) (((opus_val32)(a))/(opus_val16)(b)) -#define DIV32(a,b) (((opus_val32)(a))/(opus_val32)(b)) - -#define SCALEIN(a) ((a)*CELT_SIG_SCALE) -#define SCALEOUT(a) ((a)*(1/CELT_SIG_SCALE)) - -#define SIG2WORD16(x) (x) - -#endif /* !FIXED_POINT */ - -#ifndef GLOBAL_STACK_SIZE -#ifdef OPUS_FIXED_POINT -#define GLOBAL_STACK_SIZE 100000 -#else -#define GLOBAL_STACK_SIZE 100000 -#endif -#endif - -#endif /* ARCH_H */ diff --git a/drivers/opus/celt/arm/arm_celt_map.c b/drivers/opus/celt/arm/arm_celt_map.c deleted file mode 100644 index 92c83c1763..0000000000 --- a/drivers/opus/celt/arm/arm_celt_map.c +++ /dev/null @@ -1,118 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/celt/pitch.h" -#include "opus/celt/kiss_fft.h" -#include "opus/celt/mdct.h" - -#if defined(OPUS_HAVE_RTCD) - -# if defined(FIXED_POINT) -opus_val32 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *, - const opus_val16 *, opus_val32 *, int , int) = { - celt_pitch_xcorr_c, /* ARMv4 */ - MAY_HAVE_EDSP(celt_pitch_xcorr), /* EDSP */ - MAY_HAVE_MEDIA(celt_pitch_xcorr), /* Media */ - MAY_HAVE_NEON(celt_pitch_xcorr) /* NEON */ -}; -# else /* !FIXED_POINT */ -# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) -void (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *, - const opus_val16 *, opus_val32 *, int, int) = { - celt_pitch_xcorr_c, /* ARMv4 */ - celt_pitch_xcorr_c, /* EDSP */ - celt_pitch_xcorr_c, /* Media */ - celt_pitch_xcorr_float_neon /* Neon */ -}; -# endif -# endif /* FIXED_POINT */ - -# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) -# if defined(HAVE_ARM_NE10) -# if defined(CUSTOM_MODES) -int (*const OPUS_FFT_ALLOC_ARCH_IMPL[OPUS_ARCHMASK+1])(kiss_fft_state *st) = { - opus_fft_alloc_arch_c, /* ARMv4 */ - opus_fft_alloc_arch_c, /* EDSP */ - opus_fft_alloc_arch_c, /* Media */ - opus_fft_alloc_arm_neon /* Neon with NE10 library support */ -}; - -void (*const OPUS_FFT_FREE_ARCH_IMPL[OPUS_ARCHMASK+1])(kiss_fft_state *st) = { - opus_fft_free_arch_c, /* ARMv4 */ - opus_fft_free_arch_c, /* EDSP */ - opus_fft_free_arch_c, /* Media */ - opus_fft_free_arm_neon /* Neon with NE10 */ -}; -# endif /* CUSTOM_MODES */ - -void (*const OPUS_FFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg, - const kiss_fft_cpx *fin, - kiss_fft_cpx *fout) = { - opus_fft_c, /* ARMv4 */ - opus_fft_c, /* EDSP */ - opus_fft_c, /* Media */ - opus_fft_neon /* Neon with NE10 */ -}; - -void (*const OPUS_IFFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg, - const kiss_fft_cpx *fin, - kiss_fft_cpx *fout) = { - opus_ifft_c, /* ARMv4 */ - opus_ifft_c, /* EDSP */ - opus_ifft_c, /* Media */ - opus_ifft_neon /* Neon with NE10 */ -}; - -void (*const CLT_MDCT_FORWARD_IMPL[OPUS_ARCHMASK+1])(const mdct_lookup *l, - kiss_fft_scalar *in, - kiss_fft_scalar * OPUS_RESTRICT out, - const opus_val16 *window, - int overlap, int shift, - int stride, int arch) = { - clt_mdct_forward_c, /* ARMv4 */ - clt_mdct_forward_c, /* EDSP */ - clt_mdct_forward_c, /* Media */ - clt_mdct_forward_neon /* Neon with NE10 */ -}; - -void (*const CLT_MDCT_BACKWARD_IMPL[OPUS_ARCHMASK+1])(const mdct_lookup *l, - kiss_fft_scalar *in, - kiss_fft_scalar * OPUS_RESTRICT out, - const opus_val16 *window, - int overlap, int shift, - int stride, int arch) = { - clt_mdct_backward_c, /* ARMv4 */ - clt_mdct_backward_c, /* EDSP */ - clt_mdct_backward_c, /* Media */ - clt_mdct_backward_neon /* Neon with NE10 */ -}; - -# endif /* HAVE_ARM_NE10 */ -# endif /* OPUS_ARM_MAY_HAVE_NEON_INTR */ - -#endif /* OPUS_HAVE_RTCD */ diff --git a/drivers/opus/celt/arm/armcpu.c b/drivers/opus/celt/arm/armcpu.c deleted file mode 100644 index ac8ad2ec14..0000000000 --- a/drivers/opus/celt/arm/armcpu.c +++ /dev/null @@ -1,171 +0,0 @@ -/* 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. -*/ - -/* Original code from libtheora modified to suit to Opus */ -#include "opus/opus_config.h" - -#ifdef OPUS_HAVE_RTCD - -#include "opus/celt/arm/armcpu.h" -#include "opus/celt/cpu_support.h" -#include "opus/celt/os_support.h" -#include "opus/opus_types.h" - -#define OPUS_CPU_ARM_V4 (1) -#define OPUS_CPU_ARM_EDSP (1<<1) -#define OPUS_CPU_ARM_MEDIA (1<<2) -#define OPUS_CPU_ARM_NEON (1<<3) - -#if defined(_MSC_VER) -/*For GetExceptionCode() and EXCEPTION_ILLEGAL_INSTRUCTION.*/ -# define WIN32_LEAN_AND_MEAN -# define WIN32_EXTRA_LEAN -# include <windows.h> - -static OPUS_INLINE opus_uint32 opus_cpu_capabilities(void){ - opus_uint32 flags; - flags=0; - /* MSVC has no OPUS_INLINE __asm support for ARM, but it does let you __emit - * instructions via their assembled hex code. - * All of these instructions should be essentially nops. */ -# if defined(OPUS_ARM_MAY_HAVE_EDSP) - __try{ - /*PLD [r13]*/ - __emit(0xF5DDF000); - flags|=OPUS_CPU_ARM_EDSP; - } - __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){ - /*Ignore exception.*/ - } -# if defined(OPUS_ARM_MAY_HAVE_MEDIA) - __try{ - /*SHADD8 r3,r3,r3*/ - __emit(0xE6333F93); - flags|=OPUS_CPU_ARM_MEDIA; - } - __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){ - /*Ignore exception.*/ - } -# if defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR) - __try{ - /*VORR q0,q0,q0*/ - __emit(0xF2200150); - flags|=OPUS_CPU_ARM_NEON; - } - __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){ - /*Ignore exception.*/ - } -# endif -# endif -# endif - return flags; -} - -#elif defined(__linux__) -/* Linux based */ -opus_uint32 opus_cpu_capabilities(void) -{ - opus_uint32 flags = 0; - FILE *cpuinfo; - - /* Reading /proc/self/auxv would be easier, but that doesn't work reliably on - * Android */ - cpuinfo = fopen("/proc/cpuinfo", "r"); - - if(cpuinfo != NULL) - { - /* 512 should be enough for anybody (it's even enough for all the flags that - * x86 has accumulated... so far). */ - char buf[512]; - - while(fgets(buf, 512, cpuinfo) != NULL) - { -# if defined(OPUS_ARM_MAY_HAVE_EDSP) || defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR) - /* Search for edsp and neon flag */ - if(memcmp(buf, "Features", 8) == 0) - { - char *p; -# if defined(OPUS_ARM_MAY_HAVE_EDSP) - p = strstr(buf, " edsp"); - if(p != NULL && (p[5] == ' ' || p[5] == '\n')) - flags |= OPUS_CPU_ARM_EDSP; -# endif - -# if defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR) - p = strstr(buf, " neon"); - if(p != NULL && (p[5] == ' ' || p[5] == '\n')) - flags |= OPUS_CPU_ARM_NEON; -# endif - } -# endif - -# if defined(OPUS_ARM_MAY_HAVE_MEDIA) - /* Search for media capabilities (>= ARMv6) */ - if(memcmp(buf, "CPU architecture:", 17) == 0) - { - int version; - version = atoi(buf+17); - - if(version >= 6) - flags |= OPUS_CPU_ARM_MEDIA; - } -# endif - } - - fclose(cpuinfo); - } - return flags; -} -#else -/* The feature registers which can tell us what the processor supports are - * accessible in priveleged modes only, so we can't have a general user-space - * detection method like on x86.*/ -# error "Configured to use ARM asm but no CPU detection method available for " \ - "your platform. Reconfigure with --disable-rtcd (or send patches)." -#endif - -int opus_select_arch(void) -{ - opus_uint32 flags = opus_cpu_capabilities(); - int arch = 0; - - if(!(flags & OPUS_CPU_ARM_EDSP)) - return arch; - arch++; - - if(!(flags & OPUS_CPU_ARM_MEDIA)) - return arch; - arch++; - - if(!(flags & OPUS_CPU_ARM_NEON)) - return arch; - arch++; - - return arch; -} - -#endif diff --git a/drivers/opus/celt/arm/celt_ne10_fft.c b/drivers/opus/celt/arm/celt_ne10_fft.c deleted file mode 100644 index e57d23ee1d..0000000000 --- a/drivers/opus/celt/arm/celt_ne10_fft.c +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright (c) 2015 Xiph.Org Foundation - Written by Viswanath Puttagunta */ -/** - @file celt_ne10_fft.c - @brief ARM Neon optimizations for fft using NE10 library - */ - -/* - 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 SKIP_CONFIG_H -#include "opus/opus_config.h" -#endif - -#include <NE10_init.h> -#include <NE10_dsp.h> -#include "opus/celt/os_support.h" -#include "opus/celt/kiss_fft.h" -#include "opus/celt/stack_alloc.h" - -#if !defined(FIXED_POINT) -# define NE10_FFT_ALLOC_C2C_TYPE_NEON ne10_fft_alloc_c2c_float32_neon -# define NE10_FFT_CFG_TYPE_T ne10_fft_cfg_float32_t -# define NE10_FFT_STATE_TYPE_T ne10_fft_state_float32_t -# define NE10_FFT_DESTROY_C2C_TYPE ne10_fft_destroy_c2c_float32 -# define NE10_FFT_CPX_TYPE_T ne10_fft_cpx_float32_t -# define NE10_FFT_C2C_1D_TYPE_NEON ne10_fft_c2c_1d_float32_neon -#else -# define NE10_FFT_ALLOC_C2C_TYPE_NEON(nfft) ne10_fft_alloc_c2c_int32_neon(nfft) -# define NE10_FFT_CFG_TYPE_T ne10_fft_cfg_int32_t -# define NE10_FFT_STATE_TYPE_T ne10_fft_state_int32_t -# define NE10_FFT_DESTROY_C2C_TYPE ne10_fft_destroy_c2c_int32 -# define NE10_FFT_DESTROY_C2C_TYPE ne10_fft_destroy_c2c_int32 -# define NE10_FFT_CPX_TYPE_T ne10_fft_cpx_int32_t -# define NE10_FFT_C2C_1D_TYPE_NEON ne10_fft_c2c_1d_int32_neon -#endif - -#if defined(CUSTOM_MODES) - -/* nfft lengths in NE10 that support scaled fft */ -# define NE10_FFTSCALED_SUPPORT_MAX 4 -static const int ne10_fft_scaled_support[NE10_FFTSCALED_SUPPORT_MAX] = { - 480, 240, 120, 60 -}; - -int opus_fft_alloc_arm_neon(kiss_fft_state *st) -{ - int i; - size_t memneeded = sizeof(struct arch_fft_state); - - st->arch_fft = (arch_fft_state *)opus_alloc(memneeded); - if (!st->arch_fft) - return -1; - - for (i = 0; i < NE10_FFTSCALED_SUPPORT_MAX; i++) { - if(st->nfft == ne10_fft_scaled_support[i]) - break; - } - if (i == NE10_FFTSCALED_SUPPORT_MAX) { - /* This nfft length (scaled fft) is not supported in NE10 */ - st->arch_fft->is_supported = 0; - st->arch_fft->priv = NULL; - } - else { - st->arch_fft->is_supported = 1; - st->arch_fft->priv = (void *)NE10_FFT_ALLOC_C2C_TYPE_NEON(st->nfft); - if (st->arch_fft->priv == NULL) { - return -1; - } - } - return 0; -} - -void opus_fft_free_arm_neon(kiss_fft_state *st) -{ - NE10_FFT_CFG_TYPE_T cfg; - - if (!st->arch_fft) - return; - - cfg = (NE10_FFT_CFG_TYPE_T)st->arch_fft->priv; - if (cfg) - NE10_FFT_DESTROY_C2C_TYPE(cfg); - opus_free(st->arch_fft); -} -#endif - -void opus_fft_neon(const kiss_fft_state *st, - const kiss_fft_cpx *fin, - kiss_fft_cpx *fout) -{ - NE10_FFT_STATE_TYPE_T state; - NE10_FFT_CFG_TYPE_T cfg = &state; - VARDECL(NE10_FFT_CPX_TYPE_T, buffer); - SAVE_STACK; - ALLOC(buffer, st->nfft, NE10_FFT_CPX_TYPE_T); - - if (!st->arch_fft->is_supported) { - /* This nfft length (scaled fft) not supported in NE10 */ - opus_fft_c(st, fin, fout); - } - else { - memcpy((void *)cfg, st->arch_fft->priv, sizeof(NE10_FFT_STATE_TYPE_T)); - state.buffer = (NE10_FFT_CPX_TYPE_T *)&buffer[0]; -#if !defined(FIXED_POINT) - state.is_forward_scaled = 1; - - NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout, - (NE10_FFT_CPX_TYPE_T *)fin, - cfg, 0); -#else - NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout, - (NE10_FFT_CPX_TYPE_T *)fin, - cfg, 0, 1); -#endif - } - RESTORE_STACK; -} - -void opus_ifft_neon(const kiss_fft_state *st, - const kiss_fft_cpx *fin, - kiss_fft_cpx *fout) -{ - NE10_FFT_STATE_TYPE_T state; - NE10_FFT_CFG_TYPE_T cfg = &state; - VARDECL(NE10_FFT_CPX_TYPE_T, buffer); - SAVE_STACK; - ALLOC(buffer, st->nfft, NE10_FFT_CPX_TYPE_T); - - if (!st->arch_fft->is_supported) { - /* This nfft length (scaled fft) not supported in NE10 */ - opus_ifft_c(st, fin, fout); - } - else { - memcpy((void *)cfg, st->arch_fft->priv, sizeof(NE10_FFT_STATE_TYPE_T)); - state.buffer = (NE10_FFT_CPX_TYPE_T *)&buffer[0]; -#if !defined(FIXED_POINT) - state.is_backward_scaled = 0; - - NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout, - (NE10_FFT_CPX_TYPE_T *)fin, - cfg, 1); -#else - NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout, - (NE10_FFT_CPX_TYPE_T *)fin, - cfg, 1, 0); -#endif - } - RESTORE_STACK; -} diff --git a/drivers/opus/celt/arm/celt_ne10_mdct.c b/drivers/opus/celt/arm/celt_ne10_mdct.c deleted file mode 100644 index eb407b674f..0000000000 --- a/drivers/opus/celt/arm/celt_ne10_mdct.c +++ /dev/null @@ -1,256 +0,0 @@ -/* Copyright (c) 2015 Xiph.Org Foundation - Written by Viswanath Puttagunta */ -/** - @file celt_ne10_mdct.c - @brief ARM Neon optimizations for mdct using NE10 library - */ - -/* - 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 SKIP_CONFIG_H -#include "opus/opus_config.h" -#endif - -#include "opus/celt/kiss_fft.h" -#include "opus/celt/_kiss_fft_guts.h" -#include "opus/celt/mdct.h" -#include "opus/celt/stack_alloc.h" - -void clt_mdct_forward_neon(const mdct_lookup *l, - kiss_fft_scalar *in, - kiss_fft_scalar * OPUS_RESTRICT out, - const opus_val16 *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; - - SAVE_STACK; - - 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 opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1); - const opus_val16 * 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++ = MULT16_32_Q15(*wp2, xp1[N2]) + MULT16_32_Q15(*wp1,*xp2); - *yp++ = MULT16_32_Q15(*wp1, *xp1) - MULT16_32_Q15(*wp2, xp2[-N2]); - 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++ = -MULT16_32_Q15(*wp1, xp1[-N2]) + MULT16_32_Q15(*wp2, *xp2); - *yp++ = MULT16_32_Q15(*wp2, *xp1) + MULT16_32_Q15(*wp1, xp2[N2]); - xp1+=2; - xp2-=2; - wp1+=2; - wp2-=2; - } - } - /* Pre-rotation */ - { - kiss_fft_scalar * OPUS_RESTRICT yp = f; - const kiss_twiddle_scalar *t = &trig[0]; - 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); - yc.r = yr; - yc.i = yi; - f2[i] = yc; - } - } - - opus_fft(st, f2, (kiss_fft_cpx *)f, arch); - - /* Post-rotate */ - { - /* Temp pointers to make it really clear to the compiler what we're doing */ - const kiss_fft_cpx * OPUS_RESTRICT fp = (kiss_fft_cpx *)f; - 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; - yr = S_MUL(fp->i,t[N4+i]) - S_MUL(fp->r,t[i]); - yi = S_MUL(fp->r,t[N4+i]) + S_MUL(fp->i,t[i]); - *yp1 = yr; - *yp2 = yi; - fp++; - yp1 += 2*stride; - yp2 -= 2*stride; - } - } - RESTORE_STACK; -} - -void clt_mdct_backward_neon(const mdct_lookup *l, - kiss_fft_scalar *in, - kiss_fft_scalar * OPUS_RESTRICT out, - const opus_val16 * OPUS_RESTRICT window, - int overlap, int shift, int stride, int arch) -{ - int i; - int N, N2, N4; - VARDECL(kiss_fft_scalar, f); - const kiss_twiddle_scalar *trig; - const kiss_fft_state *st = l->kfft[shift]; - - 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); - - /* 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 = f; - const kiss_twiddle_scalar * OPUS_RESTRICT t = &trig[0]; - for(i=0;i<N4;i++) - { - kiss_fft_scalar yr, yi; - yr = S_MUL(*xp2, t[i]) + S_MUL(*xp1, t[N4+i]); - yi = S_MUL(*xp1, t[i]) - S_MUL(*xp2, t[N4+i]); - yp[2*i] = yr; - yp[2*i+1] = yi; - xp1+=2*stride; - xp2-=2*stride; - } - } - - opus_ifft(st, (kiss_fft_cpx *)f, (kiss_fft_cpx*)(out+(overlap>>1)), arch); - - /* 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; - re = yp0[0]; - im = yp0[1]; - t0 = t[i]; - t1 = t[N4+i]; - /* We'd scale up by 2 here, but instead it's done when mixing the windows */ - yr = S_MUL(re,t0) + S_MUL(im,t1); - yi = S_MUL(re,t1) - S_MUL(im,t0); - re = yp1[0]; - im = yp1[1]; - 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 = S_MUL(re,t0) + S_MUL(im,t1); - yi = S_MUL(re,t1) - S_MUL(im,t0); - 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 opus_val16 * OPUS_RESTRICT wp1 = window; - const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1; - - for(i = 0; i < overlap/2; i++) - { - kiss_fft_scalar x1, x2; - x1 = *xp1; - x2 = *yp1; - *yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1); - *xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1); - wp1++; - wp2--; - } - } - RESTORE_STACK; -} diff --git a/drivers/opus/celt/arm/celt_neon_intr.c b/drivers/opus/celt/arm/celt_neon_intr.c deleted file mode 100644 index 82b6958644..0000000000 --- a/drivers/opus/celt/arm/celt_neon_intr.c +++ /dev/null @@ -1,249 +0,0 @@ -/* Copyright (c) 2014-2015 Xiph.Org Foundation - Written by Viswanath Puttagunta */ -/** - @file celt_neon_intr.c - @brief ARM Neon Intrinsic optimizations 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. -*/ -#include "opus/opus_config.h" - -#include <arm_neon.h> -#include "opus/celt/pitch.h" - -#if !defined(FIXED_POINT) -/* - * Function: xcorr_kernel_neon_float - * --------------------------------- - * Computes 4 correlation values and stores them in sum[4] - */ -static void xcorr_kernel_neon_float(const float32_t *x, const float32_t *y, - float32_t sum[4], int len) { - float32x4_t YY[3]; - float32x4_t YEXT[3]; - float32x4_t XX[2]; - float32x2_t XX_2; - float32x4_t SUMM; - const float32_t *xi = x; - const float32_t *yi = y; - - celt_assert(len>0); - - YY[0] = vld1q_f32(yi); - SUMM = vdupq_n_f32(0); - - /* Consume 8 elements in x vector and 12 elements in y - * vector. However, the 12'th element never really gets - * touched in this loop. So, if len == 8, then we only - * must access y[0] to y[10]. y[11] must not be accessed - * hence make sure len > 8 and not len >= 8 - */ - while (len > 8) { - yi += 4; - YY[1] = vld1q_f32(yi); - yi += 4; - YY[2] = vld1q_f32(yi); - - XX[0] = vld1q_f32(xi); - xi += 4; - XX[1] = vld1q_f32(xi); - xi += 4; - - SUMM = vmlaq_lane_f32(SUMM, YY[0], vget_low_f32(XX[0]), 0); - YEXT[0] = vextq_f32(YY[0], YY[1], 1); - SUMM = vmlaq_lane_f32(SUMM, YEXT[0], vget_low_f32(XX[0]), 1); - YEXT[1] = vextq_f32(YY[0], YY[1], 2); - SUMM = vmlaq_lane_f32(SUMM, YEXT[1], vget_high_f32(XX[0]), 0); - YEXT[2] = vextq_f32(YY[0], YY[1], 3); - SUMM = vmlaq_lane_f32(SUMM, YEXT[2], vget_high_f32(XX[0]), 1); - - SUMM = vmlaq_lane_f32(SUMM, YY[1], vget_low_f32(XX[1]), 0); - YEXT[0] = vextq_f32(YY[1], YY[2], 1); - SUMM = vmlaq_lane_f32(SUMM, YEXT[0], vget_low_f32(XX[1]), 1); - YEXT[1] = vextq_f32(YY[1], YY[2], 2); - SUMM = vmlaq_lane_f32(SUMM, YEXT[1], vget_high_f32(XX[1]), 0); - YEXT[2] = vextq_f32(YY[1], YY[2], 3); - SUMM = vmlaq_lane_f32(SUMM, YEXT[2], vget_high_f32(XX[1]), 1); - - YY[0] = YY[2]; - len -= 8; - } - - /* Consume 4 elements in x vector and 8 elements in y - * vector. However, the 8'th element in y never really gets - * touched in this loop. So, if len == 4, then we only - * must access y[0] to y[6]. y[7] must not be accessed - * hence make sure len>4 and not len>=4 - */ - if (len > 4) { - yi += 4; - YY[1] = vld1q_f32(yi); - - XX[0] = vld1q_f32(xi); - xi += 4; - - SUMM = vmlaq_lane_f32(SUMM, YY[0], vget_low_f32(XX[0]), 0); - YEXT[0] = vextq_f32(YY[0], YY[1], 1); - SUMM = vmlaq_lane_f32(SUMM, YEXT[0], vget_low_f32(XX[0]), 1); - YEXT[1] = vextq_f32(YY[0], YY[1], 2); - SUMM = vmlaq_lane_f32(SUMM, YEXT[1], vget_high_f32(XX[0]), 0); - YEXT[2] = vextq_f32(YY[0], YY[1], 3); - SUMM = vmlaq_lane_f32(SUMM, YEXT[2], vget_high_f32(XX[0]), 1); - - YY[0] = YY[1]; - len -= 4; - } - - while (--len > 0) { - XX_2 = vld1_dup_f32(xi++); - SUMM = vmlaq_lane_f32(SUMM, YY[0], XX_2, 0); - YY[0]= vld1q_f32(++yi); - } - - XX_2 = vld1_dup_f32(xi); - SUMM = vmlaq_lane_f32(SUMM, YY[0], XX_2, 0); - - vst1q_f32(sum, SUMM); -} - -/* - * Function: xcorr_kernel_neon_float_process1 - * --------------------------------- - * Computes single correlation values and stores in *sum - */ -static void xcorr_kernel_neon_float_process1(const float32_t *x, - const float32_t *y, float32_t *sum, int len) { - float32x4_t XX[4]; - float32x4_t YY[4]; - float32x2_t XX_2; - float32x2_t YY_2; - float32x4_t SUMM; - float32x2_t SUMM_2[2]; - const float32_t *xi = x; - const float32_t *yi = y; - - SUMM = vdupq_n_f32(0); - - /* Work on 16 values per iteration */ - while (len >= 16) { - XX[0] = vld1q_f32(xi); - xi += 4; - XX[1] = vld1q_f32(xi); - xi += 4; - XX[2] = vld1q_f32(xi); - xi += 4; - XX[3] = vld1q_f32(xi); - xi += 4; - - YY[0] = vld1q_f32(yi); - yi += 4; - YY[1] = vld1q_f32(yi); - yi += 4; - YY[2] = vld1q_f32(yi); - yi += 4; - YY[3] = vld1q_f32(yi); - yi += 4; - - SUMM = vmlaq_f32(SUMM, YY[0], XX[0]); - SUMM = vmlaq_f32(SUMM, YY[1], XX[1]); - SUMM = vmlaq_f32(SUMM, YY[2], XX[2]); - SUMM = vmlaq_f32(SUMM, YY[3], XX[3]); - len -= 16; - } - - /* Work on 8 values */ - if (len >= 8) { - XX[0] = vld1q_f32(xi); - xi += 4; - XX[1] = vld1q_f32(xi); - xi += 4; - - YY[0] = vld1q_f32(yi); - yi += 4; - YY[1] = vld1q_f32(yi); - yi += 4; - - SUMM = vmlaq_f32(SUMM, YY[0], XX[0]); - SUMM = vmlaq_f32(SUMM, YY[1], XX[1]); - len -= 8; - } - - /* Work on 4 values */ - if (len >= 4) { - XX[0] = vld1q_f32(xi); - xi += 4; - YY[0] = vld1q_f32(yi); - yi += 4; - SUMM = vmlaq_f32(SUMM, YY[0], XX[0]); - len -= 4; - } - - /* Start accumulating results */ - SUMM_2[0] = vget_low_f32(SUMM); - if (len >= 2) { - /* While at it, consume 2 more values if available */ - XX_2 = vld1_f32(xi); - xi += 2; - YY_2 = vld1_f32(yi); - yi += 2; - SUMM_2[0] = vmla_f32(SUMM_2[0], YY_2, XX_2); - len -= 2; - } - SUMM_2[1] = vget_high_f32(SUMM); - SUMM_2[0] = vadd_f32(SUMM_2[0], SUMM_2[1]); - SUMM_2[0] = vpadd_f32(SUMM_2[0], SUMM_2[0]); - /* Ok, now we have result accumulated in SUMM_2[0].0 */ - - if (len > 0) { - /* Case when you have one value left */ - XX_2 = vld1_dup_f32(xi); - YY_2 = vld1_dup_f32(yi); - SUMM_2[0] = vmla_f32(SUMM_2[0], XX_2, YY_2); - } - - vst1_lane_f32(sum, SUMM_2[0], 0); -} - -void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y, - opus_val32 *xcorr, int len, int max_pitch) { - int i; - celt_assert(max_pitch > 0); - celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0); - - for (i = 0; i < (max_pitch-3); i += 4) { - xcorr_kernel_neon_float((const float32_t *)_x, (const float32_t *)_y+i, - (float32_t *)xcorr+i, len); - } - - /* In case max_pitch isn't multiple of 4 - * compute single correlation value per iteration - */ - for (; i < max_pitch; i++) { - xcorr_kernel_neon_float_process1((const float32_t *)_x, - (const float32_t *)_y+i, (float32_t *)xcorr+i, len); - } -} -#endif diff --git a/drivers/opus/celt/arm/fft_arm.h b/drivers/opus/celt/arm/fft_arm.h deleted file mode 100644 index c99458b4af..0000000000 --- a/drivers/opus/celt/arm/fft_arm.h +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (c) 2015 Xiph.Org Foundation - Written by Viswanath Puttagunta */ -/** - @file fft_arm.h - @brief ARM Neon Intrinsic optimizations for fft using NE10 library - */ - -/* - 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(FFT_ARM_H) -#define FFT_ARM_H - -#include "opus/opus_config.h" -#include "opus/celt/kiss_fft.h" - -#if defined(HAVE_ARM_NE10) - -int opus_fft_alloc_arm_neon(kiss_fft_state *st); -void opus_fft_free_arm_neon(kiss_fft_state *st); - -void opus_fft_neon(const kiss_fft_state *st, - const kiss_fft_cpx *fin, - kiss_fft_cpx *fout); - -void opus_ifft_neon(const kiss_fft_state *st, - const kiss_fft_cpx *fin, - kiss_fft_cpx *fout); - -#if !defined(OPUS_HAVE_RTCD) -#define OVERRIDE_OPUS_FFT (1) - -#define opus_fft_alloc_arch(_st, arch) \ - ((void)(arch), opus_fft_alloc_arm_neon(_st)) - -#define opus_fft_free_arch(_st, arch) \ - ((void)(arch), opus_fft_free_arm_neon(_st)) - -#define opus_fft(_st, _fin, _fout, arch) \ - ((void)(arch), opus_fft_neon(_st, _fin, _fout)) - -#define opus_ifft(_st, _fin, _fout, arch) \ - ((void)(arch), opus_ifft_neon(_st, _fin, _fout)) - -#endif /* OPUS_HAVE_RTCD */ - -#endif /* HAVE_ARM_NE10 */ - -#endif diff --git a/drivers/opus/celt/arm/fixed_armv5e.h b/drivers/opus/celt/arm/fixed_armv5e.h deleted file mode 100644 index 2db23262e8..0000000000 --- a/drivers/opus/celt/arm/fixed_armv5e.h +++ /dev/null @@ -1,151 +0,0 @@ -/* Copyright (C) 2007-2009 Xiph.Org Foundation - Copyright (C) 2003-2008 Jean-Marc Valin - Copyright (C) 2007-2008 CSIRO - 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 FIXED_ARMv5E_H -#define FIXED_ARMv5E_H - -#include "opus/celt/arm/fixed_armv4.h" - -/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */ -#undef MULT16_32_Q16 -static OPUS_INLINE opus_val32 MULT16_32_Q16_armv5e(opus_val16 a, opus_val32 b) -{ - int res; - __asm__( - "#MULT16_32_Q16\n\t" - "smulwb %0, %1, %2\n\t" - : "=r"(res) - : "r"(b),"r"(a) - ); - return res; -} -#define MULT16_32_Q16(a, b) (MULT16_32_Q16_armv5e(a, b)) - - -/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */ -#undef MULT16_32_Q15 -static OPUS_INLINE opus_val32 MULT16_32_Q15_armv5e(opus_val16 a, opus_val32 b) -{ - int res; - __asm__( - "#MULT16_32_Q15\n\t" - "smulwb %0, %1, %2\n\t" - : "=r"(res) - : "r"(b), "r"(a) - ); - return res<<1; -} -#define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv5e(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. */ -#undef MAC16_32_Q15 -static OPUS_INLINE opus_val32 MAC16_32_Q15_armv5e(opus_val32 c, opus_val16 a, - opus_val32 b) -{ - int res; - __asm__( - "#MAC16_32_Q15\n\t" - "smlawb %0, %1, %2, %3;\n" - : "=r"(res) - : "r"(b<<1), "r"(a), "r"(c) - ); - return res; -} -#define MAC16_32_Q15(c, a, b) (MAC16_32_Q15_armv5e(c, a, b)) - -/** 16x32 multiply, followed by a 16-bit shift right and 32-bit add. - Result fits in 32 bits. */ -#undef MAC16_32_Q16 -static OPUS_INLINE opus_val32 MAC16_32_Q16_armv5e(opus_val32 c, opus_val16 a, - opus_val32 b) -{ - int res; - __asm__( - "#MAC16_32_Q16\n\t" - "smlawb %0, %1, %2, %3;\n" - : "=r"(res) - : "r"(b), "r"(a), "r"(c) - ); - return res; -} -#define MAC16_32_Q16(c, a, b) (MAC16_32_Q16_armv5e(c, a, b)) - -/** 16x16 multiply-add where the result fits in 32 bits */ -#undef MAC16_16 -static OPUS_INLINE opus_val32 MAC16_16_armv5e(opus_val32 c, opus_val16 a, - opus_val16 b) -{ - int res; - __asm__( - "#MAC16_16\n\t" - "smlabb %0, %1, %2, %3;\n" - : "=r"(res) - : "r"(a), "r"(b), "r"(c) - ); - return res; -} -#define MAC16_16(c, a, b) (MAC16_16_armv5e(c, a, b)) - -/** 16x16 multiplication where the result fits in 32 bits */ -#undef MULT16_16 -static OPUS_INLINE opus_val32 MULT16_16_armv5e(opus_val16 a, opus_val16 b) -{ - int res; - __asm__( - "#MULT16_16\n\t" - "smulbb %0, %1, %2;\n" - : "=r"(res) - : "r"(a), "r"(b) - ); - return res; -} -#define MULT16_16(a, b) (MULT16_16_armv5e(a, b)) - -#ifdef OPUS_ARM_INLINE_MEDIA - -#undef SIG2WORD16 -static OPUS_INLINE opus_val16 SIG2WORD16_armv6(opus_val32 x) -{ - celt_sig res; - __asm__( - "#SIG2WORD16\n\t" - "ssat %0, #16, %1, ASR #12\n\t" - : "=r"(res) - : "r"(x+2048) - ); - return EXTRACT16(res); -} -#define SIG2WORD16(x) (SIG2WORD16_armv6(x)) - -#endif /* OPUS_ARM_INLINE_MEDIA */ - -#endif diff --git a/drivers/opus/celt/arm/kiss_fft_armv4.h b/drivers/opus/celt/arm/kiss_fft_armv4.h deleted file mode 100644 index 0f5617324d..0000000000 --- a/drivers/opus/celt/arm/kiss_fft_armv4.h +++ /dev/null @@ -1,121 +0,0 @@ -/*Copyright (c) 2013, Xiph.Org Foundation and contributors. - - 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_ARMv4_H -#define KISS_FFT_ARMv4_H - -#if !defined(KISS_FFT_GUTS_H) -#error "This file should only be included from _kiss_fft_guts.h" -#endif - -#ifdef OPUS_FIXED_POINT - -#undef C_MUL -#define C_MUL(m,a,b) \ - do{ \ - int br__; \ - int bi__; \ - int tt__; \ - __asm__ __volatile__( \ - "#C_MUL\n\t" \ - "ldrsh %[br], [%[bp], #0]\n\t" \ - "ldm %[ap], {r0,r1}\n\t" \ - "ldrsh %[bi], [%[bp], #2]\n\t" \ - "smull %[tt], %[mi], r1, %[br]\n\t" \ - "smlal %[tt], %[mi], r0, %[bi]\n\t" \ - "rsb %[bi], %[bi], #0\n\t" \ - "smull %[br], %[mr], r0, %[br]\n\t" \ - "mov %[tt], %[tt], lsr #15\n\t" \ - "smlal %[br], %[mr], r1, %[bi]\n\t" \ - "orr %[mi], %[tt], %[mi], lsl #17\n\t" \ - "mov %[br], %[br], lsr #15\n\t" \ - "orr %[mr], %[br], %[mr], lsl #17\n\t" \ - : [mr]"=r"((m).r), [mi]"=r"((m).i), \ - [br]"=&r"(br__), [bi]"=r"(bi__), [tt]"=r"(tt__) \ - : [ap]"r"(&(a)), [bp]"r"(&(b)) \ - : "r0", "r1" \ - ); \ - } \ - while(0) - -#undef C_MUL4 -#define C_MUL4(m,a,b) \ - do{ \ - int br__; \ - int bi__; \ - int tt__; \ - __asm__ __volatile__( \ - "#C_MUL4\n\t" \ - "ldrsh %[br], [%[bp], #0]\n\t" \ - "ldm %[ap], {r0,r1}\n\t" \ - "ldrsh %[bi], [%[bp], #2]\n\t" \ - "smull %[tt], %[mi], r1, %[br]\n\t" \ - "smlal %[tt], %[mi], r0, %[bi]\n\t" \ - "rsb %[bi], %[bi], #0\n\t" \ - "smull %[br], %[mr], r0, %[br]\n\t" \ - "mov %[tt], %[tt], lsr #17\n\t" \ - "smlal %[br], %[mr], r1, %[bi]\n\t" \ - "orr %[mi], %[tt], %[mi], lsl #15\n\t" \ - "mov %[br], %[br], lsr #17\n\t" \ - "orr %[mr], %[br], %[mr], lsl #15\n\t" \ - : [mr]"=r"((m).r), [mi]"=r"((m).i), \ - [br]"=&r"(br__), [bi]"=r"(bi__), [tt]"=r"(tt__) \ - : [ap]"r"(&(a)), [bp]"r"(&(b)) \ - : "r0", "r1" \ - ); \ - } \ - while(0) - -#undef C_MULC -#define C_MULC(m,a,b) \ - do{ \ - int br__; \ - int bi__; \ - int tt__; \ - __asm__ __volatile__( \ - "#C_MULC\n\t" \ - "ldrsh %[br], [%[bp], #0]\n\t" \ - "ldm %[ap], {r0,r1}\n\t" \ - "ldrsh %[bi], [%[bp], #2]\n\t" \ - "smull %[tt], %[mr], r0, %[br]\n\t" \ - "smlal %[tt], %[mr], r1, %[bi]\n\t" \ - "rsb %[bi], %[bi], #0\n\t" \ - "smull %[br], %[mi], r1, %[br]\n\t" \ - "mov %[tt], %[tt], lsr #15\n\t" \ - "smlal %[br], %[mi], r0, %[bi]\n\t" \ - "orr %[mr], %[tt], %[mr], lsl #17\n\t" \ - "mov %[br], %[br], lsr #15\n\t" \ - "orr %[mi], %[br], %[mi], lsl #17\n\t" \ - : [mr]"=r"((m).r), [mi]"=r"((m).i), \ - [br]"=&r"(br__), [bi]"=r"(bi__), [tt]"=r"(tt__) \ - : [ap]"r"(&(a)), [bp]"r"(&(b)) \ - : "r0", "r1" \ - ); \ - } \ - while(0) - -#endif /* FIXED_POINT */ - -#endif /* KISS_FFT_ARMv4_H */ diff --git a/drivers/opus/celt/arm/kiss_fft_armv5e.h b/drivers/opus/celt/arm/kiss_fft_armv5e.h deleted file mode 100644 index 0ab75fbc58..0000000000 --- a/drivers/opus/celt/arm/kiss_fft_armv5e.h +++ /dev/null @@ -1,118 +0,0 @@ -/*Copyright (c) 2013, Xiph.Org Foundation and contributors. - - 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_ARMv5E_H -#define KISS_FFT_ARMv5E_H - -#if !defined(KISS_FFT_GUTS_H) -#error "This file should only be included from _kiss_fft_guts.h" -#endif - -#ifdef OPUS_FIXED_POINT - -#if defined(__thumb__)||defined(__thumb2__) -#define LDRD_CONS "Q" -#else -#define LDRD_CONS "Uq" -#endif - -#undef C_MUL -#define C_MUL(m,a,b) \ - do{ \ - int mr1__; \ - int mr2__; \ - int mi__; \ - long long aval__; \ - int bval__; \ - __asm__( \ - "#C_MUL\n\t" \ - "ldrd %[aval], %H[aval], %[ap]\n\t" \ - "ldr %[bval], %[bp]\n\t" \ - "smulwb %[mi], %H[aval], %[bval]\n\t" \ - "smulwb %[mr1], %[aval], %[bval]\n\t" \ - "smulwt %[mr2], %H[aval], %[bval]\n\t" \ - "smlawt %[mi], %[aval], %[bval], %[mi]\n\t" \ - : [mr1]"=r"(mr1__), [mr2]"=r"(mr2__), [mi]"=r"(mi__), \ - [aval]"=&r"(aval__), [bval]"=r"(bval__) \ - : [ap]LDRD_CONS(a), [bp]"m"(b) \ - ); \ - (m).r = SHL32(SUB32(mr1__, mr2__), 1); \ - (m).i = SHL32(mi__, 1); \ - } \ - while(0) - -#undef C_MUL4 -#define C_MUL4(m,a,b) \ - do{ \ - int mr1__; \ - int mr2__; \ - int mi__; \ - long long aval__; \ - int bval__; \ - __asm__( \ - "#C_MUL4\n\t" \ - "ldrd %[aval], %H[aval], %[ap]\n\t" \ - "ldr %[bval], %[bp]\n\t" \ - "smulwb %[mi], %H[aval], %[bval]\n\t" \ - "smulwb %[mr1], %[aval], %[bval]\n\t" \ - "smulwt %[mr2], %H[aval], %[bval]\n\t" \ - "smlawt %[mi], %[aval], %[bval], %[mi]\n\t" \ - : [mr1]"=r"(mr1__), [mr2]"=r"(mr2__), [mi]"=r"(mi__), \ - [aval]"=&r"(aval__), [bval]"=r"(bval__) \ - : [ap]LDRD_CONS(a), [bp]"m"(b) \ - ); \ - (m).r = SHR32(SUB32(mr1__, mr2__), 1); \ - (m).i = SHR32(mi__, 1); \ - } \ - while(0) - -#undef C_MULC -#define C_MULC(m,a,b) \ - do{ \ - int mr__; \ - int mi1__; \ - int mi2__; \ - long long aval__; \ - int bval__; \ - __asm__( \ - "#C_MULC\n\t" \ - "ldrd %[aval], %H[aval], %[ap]\n\t" \ - "ldr %[bval], %[bp]\n\t" \ - "smulwb %[mr], %[aval], %[bval]\n\t" \ - "smulwb %[mi1], %H[aval], %[bval]\n\t" \ - "smulwt %[mi2], %[aval], %[bval]\n\t" \ - "smlawt %[mr], %H[aval], %[bval], %[mr]\n\t" \ - : [mr]"=r"(mr__), [mi1]"=r"(mi1__), [mi2]"=r"(mi2__), \ - [aval]"=&r"(aval__), [bval]"=r"(bval__) \ - : [ap]LDRD_CONS(a), [bp]"m"(b) \ - ); \ - (m).r = SHL32(mr__, 1); \ - (m).i = SHL32(SUB32(mi1__, mi2__), 1); \ - } \ - while(0) - -#endif /* FIXED_POINT */ - -#endif /* KISS_FFT_GUTS_H */ diff --git a/drivers/opus/celt/arm/mdct_arm.h b/drivers/opus/celt/arm/mdct_arm.h deleted file mode 100644 index faf3c8acab..0000000000 --- a/drivers/opus/celt/arm/mdct_arm.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (c) 2015 Xiph.Org Foundation - Written by Viswanath Puttagunta */ -/** - @file arm_mdct.h - @brief ARM Neon Intrinsic optimizations for mdct using NE10 library - */ - -/* - 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(MDCT_ARM_H) -#define MDCT_ARM_H - -#include "opus/opus_config.h" -#include "opus/celt/mdct.h" - -#if defined(HAVE_ARM_NE10) -/** Compute a forward MDCT and scale by 4/N, trashes the input array */ -void clt_mdct_forward_neon(const mdct_lookup *l, kiss_fft_scalar *in, - kiss_fft_scalar * OPUS_RESTRICT out, - const opus_val16 *window, int overlap, - int shift, int stride, int arch); - -void clt_mdct_backward_neon(const mdct_lookup *l, kiss_fft_scalar *in, - kiss_fft_scalar * OPUS_RESTRICT out, - const opus_val16 *window, int overlap, - int shift, int stride, int arch); - -#if !defined(OPUS_HAVE_RTCD) -#define OVERRIDE_OPUS_MDCT (1) -#define clt_mdct_forward(_l, _in, _out, _window, _int, _shift, _stride, _arch) \ - clt_mdct_forward_neon(_l, _in, _out, _window, _int, _shift, _stride, _arch) -#define clt_mdct_backward(_l, _in, _out, _window, _int, _shift, _stride, _arch) \ - clt_mdct_backward_neon(_l, _in, _out, _window, _int, _shift, _stride, _arch) -#endif /* OPUS_HAVE_RTCD */ -#endif /* HAVE_ARM_NE10 */ - -#endif diff --git a/drivers/opus/celt/arm/pitch_arm.h b/drivers/opus/celt/arm/pitch_arm.h deleted file mode 100644 index 996fbc7fd9..0000000000 --- a/drivers/opus/celt/arm/pitch_arm.h +++ /dev/null @@ -1,68 +0,0 @@ -/* 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. -*/ - -#if !defined(PITCH_ARM_H) -# define PITCH_ARM_H - -# include "opus/celt/arm/armcpu.h" - -# if defined(FIXED_POINT) - -# if defined(OPUS_ARM_MAY_HAVE_NEON) -opus_val32 celt_pitch_xcorr_neon(const opus_val16 *_x, const opus_val16 *_y, - opus_val32 *xcorr, int len, int max_pitch); -# endif - -# if defined(OPUS_ARM_MAY_HAVE_MEDIA) -# define celt_pitch_xcorr_media MAY_HAVE_EDSP(celt_pitch_xcorr) -# endif - -# if defined(OPUS_ARM_MAY_HAVE_EDSP) -opus_val32 celt_pitch_xcorr_edsp(const opus_val16 *_x, const opus_val16 *_y, - opus_val32 *xcorr, int len, int max_pitch); -# endif - -# if !defined(OPUS_HAVE_RTCD) -# define OVERRIDE_PITCH_XCORR (1) -# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \ - ((void)(arch),PRESUME_NEON(celt_pitch_xcorr)(_x, _y, xcorr, len, max_pitch)) -# endif - -#else /* Start !FIXED_POINT */ -/* Float case */ -#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) -void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y, - opus_val32 *xcorr, int len, int max_pitch); -#if !defined(OPUS_HAVE_RTCD) || defined(OPUS_ARM_PRESUME_NEON_INTR) -#define OVERRIDE_PITCH_XCORR (1) -# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \ - ((void)(arch),celt_pitch_xcorr_float_neon(_x, _y, xcorr, len, max_pitch)) -#endif -#endif - -#endif /* end !FIXED_POINT */ -#endif diff --git a/drivers/opus/celt/bands.c b/drivers/opus/celt/bands.c deleted file mode 100644 index bdd87dd327..0000000000 --- a/drivers/opus/celt/bands.c +++ /dev/null @@ -1,1526 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include <math.h> -#include "opus/celt/bands.h" -#include "opus/celt/modes.h" -#include "opus/celt/vq.h" -#include "opus/celt/cwrs.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/os_support.h" -#include "opus/celt/mathops.h" -#include "opus/celt/rate.h" -#include "opus/celt/quant_bands.h" -#include "opus/celt/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 */ -static opus_int16 bitexact_cos(opus_int16 x) -{ - opus_int32 tmp; - opus_int16 x2; - tmp = (4096+((opus_int32)(x)*(x)))>>13; - celt_assert(tmp<=32767); - x2 = tmp; - x2 = (32767-x2) + FRAC_MUL16(x2, (-7651 + FRAC_MUL16(x2, (8277 + FRAC_MUL16(-626, x2))))); - celt_assert(x2<=32766); - return 1+x2; -} - -static 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 OPUS_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 i, c, N; - const opus_int16 *eBands = m->eBands; - 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 = celt_ilog2(maxval) - 14 + (((m->logN[i]>>BITRES)+LM+1)>>1); - j=eBands[i]<<LM; - if (shift>0) - { - do { - sum = MAC16_16(sum, EXTRACT16(SHR32(X[j+c*N],shift)), - EXTRACT16(SHR32(X[j+c*N],shift))); - } while (++j<eBands[i+1]<<LM); - } else { - do { - sum = MAC16_16(sum, EXTRACT16(SHL32(X[j+c*N],-shift)), - EXTRACT16(SHL32(X[j+c*N],-shift))); - } while (++j<eBands[i+1]<<LM); - } - /* We're adding one here to ensure the normalized band isn't larger than unity norm */ - bandE[i+c*m->nbEBands] = EPSILON+VSHR32(EXTEND32(celt_sqrt(sum)),-shift); - } else { - bandE[i+c*m->nbEBands] = EPSILON; - } - /*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 { - i=0; do { - opus_val16 g; - int j,shift; - opus_val16 E; - shift = celt_zlog2(bandE[i+c*m->nbEBands])-13; - E = VSHR32(bandE[i+c*m->nbEBands], shift); - g = EXTRACT16(celt_rcp(SHL32(E,3))); - j=M*eBands[i]; do { - X[j+c*N] = MULT16_16_Q15(VSHR32(freq[j+c*N],shift-1),g); - } 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 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_c(&X[c*N+(eBands[i]<<LM)], &X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM); - 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 opus_val16 *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]; - for (i=0;i<M*eBands[start];i++) - *f++ = 0; - for (i=start;i<end;i++) - { - int j, band_end; - opus_val16 g; - opus_val16 lg; -#ifdef OPUS_FIXED_POINT - int shift; -#endif - j=M*eBands[i]; - band_end = M*eBands[i+1]; - lg = ADD16(bandLogE[i], SHL16((opus_val16)eMeans[i],6)); -#ifndef OPUS_FIXED_POINT - g = celt_exp2(lg); -#else - /* Handle the integer part of the log energy */ - shift = 16-(lg>>DB_SHIFT); - if (shift>31) - { - shift=0; - g=0; - } else { - /* Handle the fractional part. */ - g = celt_exp2_frac(lg&((1<<DB_SHIFT)-1)); - } - /* Handle extreme gains with negative shift. */ - if (shift<0) - { - /* For shift < -2 we'd be likely to overflow, so we're capping - the gain here. This shouldn't happen unless the bitstream is - already corrupted. */ - if (shift < -2) - { - g = 32767; - shift = -2; - } - do { - *f++ = SHL32(MULT16_16(*x++, g), -shift); - } while (++j<band_end); - } else -#endif - /* Be careful of the fixed-point "else" just above when changing this code */ - do { - *f++ = SHR32(MULT16_16(*x++, g), shift); - } 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 opus_val16 *logE, const opus_val16 *prev1logE, - const opus_val16 *prev2logE, const int *pulses, opus_uint32 seed, int arch) -{ - int c, i, j, k; - for (i=start;i<end;i++) - { - int N0; - opus_val16 thresh, sqrt_1; - int depth; -#ifdef OPUS_FIXED_POINT - int shift; - opus_val32 thresh32; -#endif - - N0 = m->eBands[i+1]-m->eBands[i]; - /* depth in 1/8 bits */ - celt_assert(pulses[i]>=0); - depth = celt_udiv(1+pulses[i], (m->eBands[i+1]-m->eBands[i]))>>LM; - -#ifdef OPUS_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; - opus_val16 prev1; - opus_val16 prev2; - opus_val32 Ediff; - opus_val16 r; - int renormalize=0; - prev1 = prev1logE[c*m->nbEBands+i]; - prev2 = prev2logE[c*m->nbEBands+i]; - if (C==1) - { - prev1 = MAX16(prev1,prev1logE[m->nbEBands+i]); - prev2 = MAX16(prev2,prev2logE[m->nbEBands+i]); - } - Ediff = EXTEND32(logE[c*m->nbEBands+i])-EXTEND32(MIN16(prev1,prev2)); - Ediff = MAX32(0, Ediff); - -#ifdef OPUS_FIXED_POINT - if (Ediff < 16384) - { - opus_val32 r32 = SHR32(celt_exp2(-EXTRACT16(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 = SHR32(MULT16_16_Q15(sqrt_1, r),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(-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, Q15ONE, arch); - } while (++c<C); - } -} - -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 OPUS_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)); - a1 = DIV32_16(SHL32(EXTEND32(left),14),norm); - a2 = DIV32_16(SHL32(EXTEND32(right),14),norm); - for (j=0;j<N;j++) - { - celt_norm r, l; - l = X[j]; - r = Y[j]; - X[j] = EXTRACT16(SHR32(MAC16_16(MULT16_16(a1, l), a2, r), 14)); - /* 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 = MULT16_16(QCONST16(.70710678f, 15), X[j]); - r = MULT16_16(QCONST16(.70710678f, 15), Y[j]); - X[j] = EXTRACT16(SHR32(ADD32(l, r), 15)); - Y[j] = EXTRACT16(SHR32(SUB32(r, l), 15)); - } -} - -static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT Y, opus_val16 mid, int N, int arch) -{ - int j; - opus_val32 xp=0, side=0; - opus_val32 El, Er; - opus_val16 mid2; -#ifdef OPUS_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) */ - dual_inner_prod(Y, X, Y, N, &xp, &side, arch); - /* Compensating for the mid normalization */ - xp = MULT16_32_Q15(mid, xp); - /* mid and side are in Q15, not Q14 like X and Y */ - mid2 = SHR32(mid, 1); - El = MULT16_16(mid2, mid2) + side - 2*xp; - Er = MULT16_16(mid2, mid2) + side + 2*xp; - if (Er < QCONST32(6e-4f, 28) || El < QCONST32(6e-4f, 28)) - { - OPUS_COPY(Y, X, N); - return; - } - -#ifdef OPUS_FIXED_POINT - kl = celt_ilog2(El)>>1; - kr = celt_ilog2(Er)>>1; -#endif - t = VSHR32(El, (kl-7)<<1); - lgain = celt_rsqrt_norm(t); - t = VSHR32(Er, (kr-7)<<1); - rgain = celt_rsqrt_norm(t); - -#ifdef OPUS_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 = MULT16_16_P15(mid, X[j]); - r = Y[j]; - X[j] = EXTRACT16(PSHR32(MULT16_16(lgain, SUB16(l,r)), kl+1)); - Y[j] = EXTRACT16(PSHR32(MULT16_16(rgain, ADD16(l,r)), kr+1)); - } -} - -/* 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) -{ - 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(x[j], x[j]), 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*256; - nbBands++; - } - } 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(sum, 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 = MULT16_16(QCONST16(.70710678f,15), X[stride*2*j+i]); - tmp2 = MULT16_16(QCONST16(.70710678f,15), X[stride*(2*j+1)+i]); - X[stride*2*j+i] = EXTRACT16(PSHR32(ADD32(tmp1, tmp2), 15)); - X[stride*(2*j+1)+i] = EXTRACT16(PSHR32(SUB32(tmp1, tmp2), 15)); - } -} - -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; - 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; -}; - -struct split_ctx { - int inv; - int imid; - int iside; - int delta; - int itheta; - 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) -{ - int qn; - int itheta=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 = stereo_itheta(X, Y, stereo, N, ctx->arch); - } - tell = ec_tell_frac(ec); - if (qn!=1) - { - if (encode) - itheta = (itheta*qn+8192)>>14; - - /* 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); - 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; - 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; - itheta = 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; - sctx->qalloc = qalloc; -} -static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y, int b, - celt_norm *lowband_out) -{ -#ifdef RESYNTH - int resynth = 1; -#else - int resynth = !ctx->encode; -#endif - 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; - b-=1<<BITRES; - } - if (resynth) - x[0] = sign ? -NORM_SCALING : NORM_SCALING; - x = Y; - } while (++c<1+stereo); - if (lowband_out) - lowband_out[0] = SHR16(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_val16 gain, int fill) -{ - const unsigned char *cache; - int q; - int curr_bits; - int imid=0, iside=0; - int B0=B; - opus_val16 mid=0, side=0; - unsigned cm=0; -#ifdef RESYNTH - int resynth = 1; -#else - int resynth = !ctx->encode; -#endif - 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); - imid = sctx.imid; - iside = sctx.iside; - delta = sctx.delta; - itheta = sctx.itheta; - qalloc = sctx.qalloc; -#ifdef OPUS_FIXED_POINT - mid = imid; - side = iside; -#else - mid = (1.f/32768)*imid; - side = (1.f/32768)*iside; -#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, - MULT16_16_P15(gain,mid), fill); - 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, - MULT16_16_P15(gain,side), fill>>B)<<(B0>>1); - } else { - cm = quant_partition(ctx, Y, N, sbits, B, - next_lowband2, LM, - MULT16_16_P15(gain,side), fill>>B)<<(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, - MULT16_16_P15(gain,mid), fill); - } - } else { - /* 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 -#ifdef RESYNTH - , gain -#endif - ); - } else { - cm = alg_unquant(X, N, K, spread, B, ec, gain); - } - } else { - /* If there's no pulse, fill the band anyway */ - int j; - if (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] = (celt_norm)((opus_int32)ctx->seed>>20); - } - 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, 10); - tmp = (ctx->seed)&0x8000 ? tmp : -tmp; - X[j] = lowband[j]+tmp; - } - cm = fill; - } - renormalise_vector(X, N, gain, ctx->arch); - } - } - } - } - - return cm; -} - - -/* 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_val16 gain, celt_norm *lowband_scratch, int fill) -{ - 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; -#ifdef RESYNTH - int resynth = 1; -#else - int resynth = !ctx->encode; -#endif - 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, b, 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); - } - - cm = quant_partition(ctx, X, N, b, B, lowband, - LM, gain, fill); - - /* This code is used by the decoder and by the resynthesis-enabled encoder */ - if (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_16_Q15(n,X[j]); - } - cm &= (1<<B)-1; - } - return cm; -} - - -/* 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) -{ - int imid=0, iside=0; - int inv = 0; - opus_val16 mid=0, side=0; - unsigned cm=0; -#ifdef RESYNTH - int resynth = 1; -#else - int resynth = !ctx->encode; -#endif - 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, b, lowband_out); - } - - orig_fill = fill; - - compute_theta(ctx, &sctx, X, Y, N, &b, B, B, - LM, 1, &fill); - inv = sctx.inv; - imid = sctx.imid; - iside = sctx.iside; - delta = sctx.delta; - itheta = sctx.itheta; - qalloc = sctx.qalloc; -#ifdef OPUS_FIXED_POINT - mid = imid; - side = iside; -#else - mid = (1.f/32768)*imid; - side = (1.f/32768)*iside; -#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. */ - sign = x2[0]*y2[1] - 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, Q15ONE, lowband_scratch, orig_fill); - /* 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 (resynth) - { - celt_norm tmp; - X[0] = MULT16_16_Q15(mid, X[0]); - X[1] = MULT16_16_Q15(mid, X[1]); - Y[0] = MULT16_16_Q15(side, Y[0]); - Y[1] = MULT16_16_Q15(side, Y[1]); - tmp = X[0]; - X[0] = SUB16(tmp,Y[0]); - Y[0] = ADD16(tmp,Y[0]); - tmp = X[1]; - X[1] = SUB16(tmp,Y[1]); - Y[1] = ADD16(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) - { - /* 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, - Q15ONE, lowband_scratch, fill); - rebalance = mbits - (rebalance-ctx->remaining_bits); - if (rebalance > 3<<BITRES && itheta!=0) - sbits += rebalance - (3<<BITRES); - - /* 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); - } else { - /* 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); - rebalance = sbits - (rebalance-ctx->remaining_bits); - if (rebalance > 3<<BITRES && itheta!=16384) - mbits += rebalance - (3<<BITRES); - /* 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, - Q15ONE, lowband_scratch, fill); - } - } - - - /* This code is used by the decoder and by the resynthesis-enabled encoder */ - if (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; -} - - -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 arch) -{ - 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); - celt_norm *lowband_scratch; - int B; - int M; - int lowband_offset; - int update_lowband = 1; - int C = Y_ != NULL ? 2 : 1; - int norm_offset; -#ifdef RESYNTH - int resynth = 1; -#else - int resynth = !encode; -#endif - struct band_ctx ctx; - 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; - /* We can use the last band as scratch space because we don't need that - scratch space for the last band. */ - lowband_scratch = X_+M*eBands[m->nbEBands-1]; - - 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; - 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]; - 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; - 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; - } - - if (resynth && M*eBands[i]-N >= M*eBands[start] && (update_lowband || lowband_offset==0)) - lowband_offset = i; - - 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 (i==end-1) - 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; - while(M*eBands[++fold_end] < effective_lowband+norm_offset+N); - 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, Q15ONE, lowband_scratch, x_cm); - 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, Q15ONE, lowband_scratch, y_cm); - } else { - if (Y!=NULL) - { - 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); - } 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, Q15ONE, lowband_scratch, x_cm|y_cm); - } - 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); - } - *seed = ctx.seed; - - RESTORE_STACK; -} - diff --git a/drivers/opus/celt/bands.h b/drivers/opus/celt/bands.h deleted file mode 100644 index eb7ea4cc24..0000000000 --- a/drivers/opus/celt/bands.h +++ /dev/null @@ -1,120 +0,0 @@ -/* 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 "opus/celt/arch.h" -#include "opus/celt/modes.h" -#include "opus/celt/entenc.h" -#include "opus/celt/entdec.h" -#include "opus/celt/rate.h" - -/** 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); - -/*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 opus_val16 *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); - -#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 arch); - -void anti_collapse(const CELTMode *m, celt_norm *X_, - unsigned char *collapse_masks, int LM, int C, int size, int start, - int end, const opus_val16 *logE, const opus_val16 *prev1logE, - const opus_val16 *prev2logE, const int *pulses, opus_uint32 seed, - 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/drivers/opus/celt/celt.c b/drivers/opus/celt/celt.c deleted file mode 100644 index 4a16651441..0000000000 --- a/drivers/opus/celt/celt.c +++ /dev/null @@ -1,296 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#define CELT_C - -#include "opus/celt/os_support.h" -#include "opus/celt/mdct.h" -#include <math.h> -#include "opus/celt/celt.h" -#include "opus/celt/pitch.h" -#include "opus/celt/bands.h" -#include "opus/celt/modes.h" -#include "opus/celt/entcode.h" -#include "opus/celt/quant_bands.h" -#include "opus/celt/rate.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/mathops.h" -#include "opus/celt/float_cast.h" -#include <stdarg.h> -#include "opus/celt/celt_lpc.h" -#include "opus/celt/vq.h" - -#ifndef PACKAGE_VERSION -#define PACKAGE_VERSION "unknown" -#endif - -#if defined(MIPSr1_ASM) -#include "opus/celt/mips/celt_mipsr1.h" -#endif - - -int resampling_factor(opus_int32 rate) -{ - int ret; - switch (rate) - { - 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, - opus_val16 g10, opus_val16 g11, opus_val16 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 = MAC16_32_Q16(x[i], g10, x2); - t = MAC16_32_Q16(t, g11, ADD32(x1,x3)); - t = MAC16_32_Q16(t, g12, ADD32(x0,x4)); - y[i] = t; - x4=SHL32(x[i-T+3],1); - t = MAC16_32_Q16(x[i+1], g10, x1); - t = MAC16_32_Q16(t, g11, ADD32(x0,x2)); - t = MAC16_32_Q16(t, g12, ADD32(x4,x3)); - y[i+1] = t; - x3=SHL32(x[i-T+4],1); - t = MAC16_32_Q16(x[i+2], g10, x0); - t = MAC16_32_Q16(t, g11, ADD32(x4,x1)); - t = MAC16_32_Q16(t, g12, ADD32(x3,x2)); - y[i+2] = t; - x2=SHL32(x[i-T+5],1); - t = MAC16_32_Q16(x[i+3], g10, x4); - t = MAC16_32_Q16(t, g11, ADD32(x3,x0)); - t = MAC16_32_Q16(t, g12, ADD32(x2,x1)); - y[i+3] = t; - x1=SHL32(x[i-T+6],1); - t = MAC16_32_Q16(x[i+4], g10, x3); - t = MAC16_32_Q16(t, g11, ADD32(x2,x4)); - t = MAC16_32_Q16(t, g12, ADD32(x1,x0)); - y[i+4] = t; - } -#ifdef CUSTOM_MODES - for (;i<N;i++) - { - opus_val32 t; - x0=SHL32(x[i-T+2],1); - t = MAC16_32_Q16(x[i], g10, x2); - t = MAC16_32_Q16(t, g11, ADD32(x1,x3)); - t = MAC16_32_Q16(t, g12, ADD32(x0,x4)); - 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, - opus_val16 g10, opus_val16 g11, opus_val16 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] - + MULT16_32_Q15(g10,x2) - + MULT16_32_Q15(g11,ADD32(x1,x3)) - + MULT16_32_Q15(g12,ADD32(x0,x4)); - x4=x3; - x3=x2; - x2=x1; - x1=x0; - } - -} -#endif -#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 opus_val16 *window, int overlap, int arch) -{ - int i; - /* printf ("%d %d %f %f\n", T0, T1, g0, g1); */ - opus_val16 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)}}; - - 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; - } - g00 = MULT16_16_P15(g0, gains[tapset0][0]); - g01 = MULT16_16_P15(g0, gains[tapset0][1]); - g02 = MULT16_16_P15(g0, gains[tapset0][2]); - g10 = MULT16_16_P15(g1, gains[tapset1][0]); - g11 = MULT16_16_P15(g1, gains[tapset1][1]); - g12 = MULT16_16_P15(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++) - { - opus_val16 f; - x0=x[i-T1+2]; - f = MULT16_16_Q15(window[i],window[i]); - y[i] = x[i] - + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g00),x[i-T0]) - + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g01),ADD32(x[i-T0+1],x[i-T0-1])) - + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g02),ADD32(x[i-T0+2],x[i-T0-2])) - + MULT16_32_Q15(MULT16_16_Q15(f,g10),x2) - + MULT16_32_Q15(MULT16_16_Q15(f,g11),ADD32(x1,x3)) - + MULT16_32_Q15(MULT16_16_Q15(f,g12),ADD32(x0,x4)); - 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 */ - -const signed char tf_select_table[4][8] = { - {0, -1, 0, -1, 0,-1, 0,-1}, - {0, -1, 0, -2, 1, 0, 1,-1}, - {0, -2, 0, -3, 2, 0, 1,-1}, - {0, -2, 0, -3, 3, 0, 1,-1}, -}; - - -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 OPUS_FIXED_POINT - "-fixed" -#endif -#ifdef FUZZING - "-fuzzing" -#endif - ; -} diff --git a/drivers/opus/celt/celt.h b/drivers/opus/celt/celt.h deleted file mode 100644 index 72814dc0de..0000000000 --- a/drivers/opus/celt/celt.h +++ /dev/null @@ -1,229 +0,0 @@ -/* 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/opus_types.h" -#include "opus/opus_defines.h" -#include "opus/opus_custom.h" -#include "opus/celt/entenc.h" -#include "opus/celt/entdec.h" -#include "opus/celt/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define CELTEncoder OpusCustomEncoder -#define CELTDecoder OpusCustomDecoder -#define CELTMode OpusCustomMode - -typedef struct { - int valid; - float tonality; - float tonality_slope; - float noisiness; - float activity; - float music_prob; - int bandwidth; -}AnalysisInfo; - -#define __celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr))) - -#define __celt_check_analysis_ptr(ptr) ((ptr) + ((ptr) - (const AnalysisInfo*)(ptr))) - -/* Encoder/decoder Requests */ - -/* Expose this option again when variable framesize actually works */ -#define OPUS_FRAMESIZE_VARIABLE 5010 /**< Optimize the frame size dynamically */ - - -#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, __opus_check_val16_ptr(x) - -/* Encoder stuff */ - -int celt_encoder_get_size(int channels); - -int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_val16 * 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(OpusCustomDecoder * OPUS_RESTRICT st, const unsigned char *data, - int len, opus_val16 * 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 - - -#ifdef CUSTOM_MODES -#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}; - -#ifdef CUSTOM_MODES -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]; - -int resampling_factor(opus_int32 rate); - -void celt_preemphasis(const opus_val16 * 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 opus_val16 *window, int overlap, int arch); - -#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 - -void init_caps(const CELTMode *m,int *cap,int LM,int C); - -#ifdef RESYNTH -void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef, celt_sig *mem); -void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[], - opus_val16 *oldBandE, int start, int effEnd, int C, int CC, int isTransient, - int LM, int downsample, int silence); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* CELT_H */ diff --git a/drivers/opus/celt/celt_decoder.c b/drivers/opus/celt/celt_decoder.c deleted file mode 100644 index 88072ed110..0000000000 --- a/drivers/opus/celt/celt_decoder.c +++ /dev/null @@ -1,1241 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#define CELT_DECODER_C - -#include "opus/celt/cpu_support.h" -#include "opus/celt/os_support.h" -#include "opus/celt/mdct.h" -#include <math.h> -#include "opus/celt/celt.h" -#include "opus/celt/pitch.h" -#include "opus/celt/bands.h" -#include "opus/celt/modes.h" -#include "opus/celt/entcode.h" -#include "opus/celt/quant_bands.h" -#include "opus/celt/rate.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/mathops.h" -#include "opus/celt/float_cast.h" -#include <stdarg.h> -#include "opus/celt/celt_lpc.h" -#include "opus/celt/vq.h" - -#if defined(SMALL_FOOTPRINT) && defined(FIXED_POINT) -#define NORM_ALIASING_HACK -#endif -/**********************************************************************/ -/* */ -/* DECODER */ -/* */ -/**********************************************************************/ -#define DECODE_BUFFER_SIZE 2048 - -/** 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 arch; - - /* 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_count; - int postfilter_period; - int postfilter_period_old; - opus_val16 postfilter_gain; - opus_val16 postfilter_gain_old; - int postfilter_tapset; - int postfilter_tapset_old; - - celt_sig preemph_memD[2]; - - celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */ - /* opus_val16 lpc[], Size = channels*LPC_ORDER */ - /* opus_val16 oldEBands[], Size = 2*mode->nbEBands */ - /* opus_val16 oldLogE[], Size = 2*mode->nbEBands */ - /* opus_val16 oldLogE2[], Size = 2*mode->nbEBands */ - /* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */ -}; - -int celt_decoder_get_size(int channels) -{ - const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL); - return opus_custom_decoder_get_size(mode, channels); -} - -OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_get_size(const CELTMode *mode, int channels) -{ - int size = sizeof(struct CELTDecoder) - + (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig) - + channels*LPC_ORDER*sizeof(opus_val16) - + 4*2*mode->nbEBands*sizeof(opus_val16); - return size; -} - -#ifdef CUSTOM_MODES -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; - 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; - st->arch = opus_select_arch(); - - st->loss_count = 0; - - opus_custom_decoder_ctl(st, OPUS_RESET_STATE); - - return OPUS_OK; -} - -#ifdef CUSTOM_MODES -void opus_custom_decoder_destroy(CELTDecoder *st) -{ - opus_free(st); -} -#endif /* CUSTOM_MODES */ - - -#ifndef RESYNTH -static -#endif -void deemphasis(celt_sig *in[], opus_val16 *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; -#ifndef OPUS_FIXED_POINT - (void)accum; - celt_assert(accum==0); -#endif - ALLOC(scratch, N, celt_sig); - coef0 = coef[0]; - Nd = N/downsample; - c=0; do { - int j; - celt_sig * OPUS_RESTRICT x; - opus_val16 * OPUS_RESTRICT y; - celt_sig m = mem[c]; - x =in[c]; - y = pcm+c; -#ifdef CUSTOM_MODES - if (coef[1] != 0) - { - opus_val16 coef1 = coef[1]; - opus_val16 coef3 = coef[3]; - for (j=0;j<N;j++) - { - celt_sig tmp = x[j] + m + VERY_SMALL; - 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 = x[j] + m + VERY_SMALL; - m = MULT16_32_Q15(coef0, tmp); - scratch[j] = tmp; - } - apply_downsampling=1; - } else { - /* Shortcut for the standard (non-custom modes) case */ -#ifdef OPUS_FIXED_POINT - if (accum) - { - for (j=0;j<N;j++) - { - celt_sig tmp = x[j] + m + VERY_SMALL; - m = MULT16_32_Q15(coef0, tmp); - y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(tmp)))); - } - } else -#endif - { - for (j=0;j<N;j++) - { - celt_sig tmp = x[j] + m + VERY_SMALL; - m = MULT16_32_Q15(coef0, tmp); - y[j*C] = SCALEOUT(SIG2WORD16(tmp)); - } - } - } - mem[c] = m; - - if (apply_downsampling) - { - /* Perform down-sampling */ -#ifdef OPUS_FIXED_POINT - if (accum) - { - for (j=0;j<Nd;j++) - y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(scratch[j*downsample])))); - } else -#endif - { - for (j=0;j<Nd;j++) - y[j*C] = SCALEOUT(SIG2WORD16(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[], - opus_val16 *oldBandE, int start, int effEnd, int C, int CC, - int isTransient, int LM, int downsample, - int silence, int arch) -{ - 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; - - 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); - /* 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); - for (i=0;i<N;i++) - freq[i] = HALF32(ADD32(freq[i],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); - 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); - } - 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]]; - } -} - -/* 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) - -static int celt_plc_pitch_search(celt_sig *decode_mem[2], int C, int arch) -{ - int pitch_index; - VARDECL( opus_val16, lp_pitch_buf ); - SAVE_STACK; - ALLOC( lp_pitch_buf, DECODE_BUFFER_SIZE>>1, opus_val16 ); - pitch_downsample(decode_mem, lp_pitch_buf, - DECODE_BUFFER_SIZE, C, 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 pitch_index; -} - -static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM) -{ - int c; - int i; - const int C = st->channels; - celt_sig *decode_mem[2]; - celt_sig *out_syn[2]; - opus_val16 *lpc; - opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE; - const OpusCustomMode *mode; - int nbEBands; - int overlap; - int start; - int loss_count; - int noise_based; - const opus_int16 *eBands; - SAVE_STACK; - - 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); - lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*C); - oldBandE = lpc+C*LPC_ORDER; - oldLogE = oldBandE + 2*nbEBands; - oldLogE2 = oldLogE + 2*nbEBands; - backgroundLogE = oldLogE2 + 2*nbEBands; - - loss_count = st->loss_count; - start = st->start; - noise_based = loss_count >= 5 || start != 0; - if (noise_based) - { - /* Noise-based PLC/CNG */ -#ifdef NORM_ALIASING_HACK - celt_norm *X; -#else - VARDECL(celt_norm, X); -#endif - opus_uint32 seed; - int end; - int effEnd; - opus_val16 decay; - end = st->end; - effEnd = IMAX(start, IMIN(end, mode->effEBands)); - -#ifdef NORM_ALIASING_HACK - /* This is an ugly hack that breaks aliasing rules and would be easily broken, - but it saves almost 4kB of stack. */ - X = (celt_norm*)(out_syn[C-1]+overlap/2); -#else - ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ -#endif - - /* Energy decay */ - decay = loss_count==0 ? QCONST16(1.5f, DB_SHIFT) : QCONST16(.5f, DB_SHIFT); - c=0; do - { - for (i=start;i<end;i++) - oldBandE[c*nbEBands+i] = MAX16(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] = (celt_norm)((opus_int32)seed>>20); - } - renormalise_vector(X+boffs, blen, Q15ONE, st->arch); - } - } - st->rng = seed; - - c=0; do { - OPUS_MOVE(decode_mem[c], decode_mem[c]+N, - DECODE_BUFFER_SIZE-N+(overlap>>1)); - } while (++c<C); - - celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, C, C, 0, LM, st->downsample, 0, st->arch); - } else { - /* Pitch-based PLC */ - const opus_val16 *window; - opus_val16 fade = Q15ONE; - int pitch_index; - VARDECL(opus_val32, etmp); - VARDECL(opus_val16, exc); - - if (loss_count == 0) - { - st->last_pitch_index = pitch_index = celt_plc_pitch_search(decode_mem, C, st->arch); - } else { - pitch_index = st->last_pitch_index; - fade = QCONST16(.8f,15); - } - - ALLOC(etmp, overlap, opus_val32); - ALLOC(exc, MAX_PERIOD, opus_val16); - 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 exc_length; - int j; - - buf = decode_mem[c]; - for (i=0;i<MAX_PERIOD;i++) { - exc[i] = ROUND16(buf[DECODE_BUFFER_SIZE-MAX_PERIOD+i], SIG_SHIFT); - } - - if (loss_count == 0) - { - opus_val32 ac[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, - LPC_ORDER, MAX_PERIOD, st->arch); - /* Add a noise floor of -40 dB. */ -#ifdef OPUS_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<=LPC_ORDER;i++) - { - /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/ -#ifdef OPUS_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*LPC_ORDER, ac, LPC_ORDER); - } - /* 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); - /* Initialize the LPC history with the samples just before the start - of the region for which we're computing the excitation. */ - { - opus_val16 lpc_mem[LPC_ORDER]; - for (i=0;i<LPC_ORDER;i++) - { - lpc_mem[i] = - ROUND16(buf[DECODE_BUFFER_SIZE-exc_length-1-i], SIG_SHIFT); - } - /* Compute the excitation for exc_length samples before the loss. */ - celt_fir(exc+MAX_PERIOD-exc_length, lpc+c*LPC_ORDER, - exc+MAX_PERIOD-exc_length, exc_length, LPC_ORDER, lpc_mem, st->arch); - } - - /* 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 OPUS_FIXED_POINT - int shift = IMAX(0,2*celt_zlog2(celt_maxabs16(&exc[MAX_PERIOD-exc_length], exc_length))-20); -#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 = ROUND16( - buf[DECODE_BUFFER_SIZE-MAX_PERIOD-N+extrapolation_offset+j], - SIG_SHIFT); - S1 += SHR32(MULT16_16(tmp, tmp), 8); - } - - { - opus_val16 lpc_mem[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<LPC_ORDER;i++) - lpc_mem[i] = ROUND16(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*LPC_ORDER, - buf+DECODE_BUFFER_SIZE-N, extrapolation_len, LPC_ORDER, - lpc_mem, st->arch); - } - - /* 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 = ROUND16(buf[DECODE_BUFFER_SIZE-N+i], SIG_SHIFT); - S2 += SHR32(MULT16_16(tmp, tmp), 8); - } - /* This checks for an "explosion" in the synthesis. */ -#ifdef OPUS_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(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]); - } - } - } - - /* 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, buf+DECODE_BUFFER_SIZE, - st->postfilter_period, st->postfilter_period, overlap, - -st->postfilter_gain, -st->postfilter_gain, - st->postfilter_tapset, 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++) - { - buf[DECODE_BUFFER_SIZE+i] = - MULT16_32_Q15(window[i], etmp[overlap-1-i]) - + MULT16_32_Q15(window[overlap-i-1], etmp[i]); - } - } while (++c<C); - } - - st->loss_count = loss_count+1; - - RESTORE_STACK; -} - -int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, - int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum) -{ - int c, i, N; - int spread_decision; - opus_int32 bits; - ec_dec _dec; -#ifdef NORM_ALIASING_HACK - celt_norm *X; -#else - VARDECL(celt_norm, X); -#endif - 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]; - opus_val16 *lpc; - opus_val16 *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; - ALLOC_STACK; - - mode = st->mode; - nbEBands = mode->nbEBands; - overlap = mode->overlap; - eBands = mode->eBands; - start = st->start; - end = st->end; - frame_size *= st->downsample; - - lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*CC); - oldBandE = lpc+CC*LPC_ORDER; - oldLogE = oldBandE + 2*nbEBands; - oldLogE2 = oldLogE + 2*nbEBands; - backgroundLogE = oldLogE2 + 2*nbEBands; - -#ifdef CUSTOM_MODES - if (st->signalling && data!=NULL) - { - int data0=data[0]; - /* Convert "standard mode" to Opus header */ - if (mode->Fs==48000 && mode->shortMdctSize==120) - { - 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); - 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); - deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum); - RESTORE_STACK; - return frame_size/st->downsample; - } - - if (dec == NULL) - { - ec_dec_init(&_dec,(unsigned char*)data,len); - dec = &_dec; - } - - if (C==1) - { - for (i=0;i<nbEBands;i++) - oldBandE[i]=MAX16(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; - /* 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) - 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 = 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, fine_quant, dec, C); - - c=0; do { - OPUS_MOVE(decode_mem[c], decode_mem[c]+N, DECODE_BUFFER_SIZE-N+overlap/2); - } while (++c<CC); - - /* Decode fixed codebook */ - ALLOC(collapse_masks, C*nbEBands, unsigned char); - -#ifdef NORM_ALIASING_HACK - /* This is an ugly hack that breaks aliasing rules and would be easily broken, - but it saves almost 4kB of stack. */ - X = (celt_norm*)(out_syn[CC-1]+overlap/2); -#else - ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ -#endif - - 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, st->arch); - - if (anti_collapse_rsv > 0) - { - anti_collapse_on = ec_dec_bits(dec, 1); - } - - unquant_energy_finalise(mode, start, end, 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, st->arch); - - if (silence) - { - for (i=0;i<C*nbEBands;i++) - oldBandE[i] = -QCONST16(28.f,DB_SHIFT); - } - - celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, - C, CC, isTransient, LM, st->downsample, silence, st->arch); - - 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); - - /* In case start or end were to change */ - if (!isTransient) - { - opus_val16 max_background_increase; - OPUS_COPY(oldLogE2, oldLogE, 2*nbEBands); - OPUS_COPY(oldLogE, oldBandE, 2*nbEBands); - /* 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 allow up to 6 dB - increase for each update.*/ - if (st->loss_count < 10) - max_background_increase = M*QCONST16(0.001f,DB_SHIFT); - else - max_background_increase = QCONST16(1.f,DB_SHIFT); - for (i=0;i<2*nbEBands;i++) - backgroundLogE[i] = MIN16(backgroundLogE[i] + max_background_increase, oldBandE[i]); - } else { - for (i=0;i<2*nbEBands;i++) - oldLogE[i] = MIN16(oldLogE[i], oldBandE[i]); - } - c=0; do - { - for (i=0;i<start;i++) - { - oldBandE[c*nbEBands+i]=0; - oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT); - } - for (i=end;i<nbEBands;i++) - { - oldBandE[c*nbEBands+i]=0; - oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT); - } - } while (++c<2); - st->rng = dec->rng; - - deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum); - st->loss_count = 0; - RESTORE_STACK; - if (ec_tell(dec) > 8*len) - return OPUS_INTERNAL_ERROR; - if(ec_get_error(dec)) - st->error = 1; - return frame_size/st->downsample; -} - - -#ifdef CUSTOM_MODES - -#ifdef OPUS_FIXED_POINT -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); -} - -#ifndef DISABLE_FLOAT_API -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_int16, out); - ALLOC_STACK; - - if (pcm==NULL) - return OPUS_BAD_ARG; - - C = st->channels; - N = frame_size; - - ALLOC(out, C*N, opus_int16); - 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]=out[j]*(1.f/32768.f); - - RESTORE_STACK; - return ret; -} -#endif /* DISABLE_FLOAT_API */ - -#else - -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); -} - -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(celt_sig, out); - ALLOC_STACK; - - if (pcm==NULL) - return OPUS_BAD_ARG; - - C = st->channels; - N = frame_size; - ALLOC(out, C*N, celt_sig); - - 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] = FLOAT2INT16 (out[j]); - - RESTORE_STACK; - return ret; -} - -#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 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; - opus_val16 *lpc, *oldBandE, *oldLogE, *oldLogE2; - lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*st->channels); - oldBandE = lpc+st->channels*LPC_ORDER; - 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]=-QCONST16(28.f,DB_SHIFT); - } - 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; - 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/drivers/opus/celt/celt_encoder.c b/drivers/opus/celt/celt_encoder.c deleted file mode 100644 index 9099bcd278..0000000000 --- a/drivers/opus/celt/celt_encoder.c +++ /dev/null @@ -1,2404 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#define CELT_ENCODER_C - -#include "opus/celt/cpu_support.h" -#include "opus/celt/os_support.h" -#include "opus/celt/mdct.h" -#include <math.h> -#include "opus/celt/celt.h" -#include "opus/celt/pitch.h" -#include "opus/celt/bands.h" -#include "opus/celt/modes.h" -#include "opus/celt/entcode.h" -#include "opus/celt/quant_bands.h" -#include "opus/celt/rate.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/mathops.h" -#include "opus/celt/float_cast.h" -#include <stdarg.h> -#include "opus/celt/celt_lpc.h" -#include "opus/celt/vq.h" - - -/** Encoder state - @brief Encoder state - */ -struct OpusCustomEncoder { - const OpusCustomMode *mode; /**< Mode used by the encoder */ - int channels; - int stream_channels; - - int force_intra; - int clip; - int disable_pf; - int complexity; - int upsample; - int start, end; - - opus_int32 bitrate; - int vbr; - int signalling; - int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */ - int loss_rate; - int lsb_depth; - int variable_duration; - int lfe; - int arch; - - /* Everything beyond this point gets cleared on a reset */ -#define ENCODER_RESET_START rng - - opus_uint32 rng; - int spread_decision; - opus_val32 delayedIntra; - int tonal_average; - int lastCodedBands; - int hf_average; - int tapset_decision; - - int prefilter_period; - opus_val16 prefilter_gain; - int prefilter_tapset; -#ifdef RESYNTH - int prefilter_period_old; - opus_val16 prefilter_gain_old; - int prefilter_tapset_old; -#endif - int consec_transient; - AnalysisInfo analysis; - - opus_val32 preemph_memE[2]; - opus_val32 preemph_memD[2]; - - /* VBR-related parameters */ - opus_int32 vbr_reservoir; - opus_int32 vbr_drift; - opus_int32 vbr_offset; - opus_int32 vbr_count; - opus_val32 overlap_max; - opus_val16 stereo_saving; - int intensity; - opus_val16 *energy_mask; - opus_val16 spec_avg; - -#ifdef RESYNTH - /* +MAX_PERIOD/2 to make space for overlap */ - celt_sig syn_mem[2][2*MAX_PERIOD+MAX_PERIOD/2]; -#endif - - celt_sig in_mem[1]; /* Size = channels*mode->overlap */ - /* celt_sig prefilter_mem[], Size = channels*COMBFILTER_MAXPERIOD */ - /* opus_val16 oldBandE[], Size = channels*mode->nbEBands */ - /* opus_val16 oldLogE[], Size = channels*mode->nbEBands */ - /* opus_val16 oldLogE2[], Size = channels*mode->nbEBands */ -}; - -int celt_encoder_get_size(int channels) -{ - CELTMode *mode = opus_custom_mode_create(48000, 960, NULL); - return opus_custom_encoder_get_size(mode, channels); -} - -OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_get_size(const CELTMode *mode, int channels) -{ - int size = sizeof(struct CELTEncoder) - + (channels*mode->overlap-1)*sizeof(celt_sig) /* celt_sig in_mem[channels*mode->overlap]; */ - + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig) /* celt_sig prefilter_mem[channels*COMBFILTER_MAXPERIOD]; */ - + 3*channels*mode->nbEBands*sizeof(opus_val16); /* opus_val16 oldBandE[channels*mode->nbEBands]; */ - /* opus_val16 oldLogE[channels*mode->nbEBands]; */ - /* opus_val16 oldLogE2[channels*mode->nbEBands]; */ - return size; -} - -#ifdef CUSTOM_MODES -CELTEncoder *opus_custom_encoder_create(const CELTMode *mode, int channels, int *error) -{ - int ret; - CELTEncoder *st = (CELTEncoder *)opus_alloc(opus_custom_encoder_get_size(mode, channels)); - /* init will handle the NULL case */ - ret = opus_custom_encoder_init(st, mode, channels); - if (ret != OPUS_OK) - { - opus_custom_encoder_destroy(st); - st = NULL; - } - if (error) - *error = ret; - return st; -} -#endif /* CUSTOM_MODES */ - -static int opus_custom_encoder_init_arch(CELTEncoder *st, const CELTMode *mode, - int channels, int arch) -{ - if (channels < 0 || channels > 2) - return OPUS_BAD_ARG; - - if (st==NULL || mode==NULL) - return OPUS_ALLOC_FAIL; - - OPUS_CLEAR((char*)st, opus_custom_encoder_get_size(mode, channels)); - - st->mode = mode; - st->stream_channels = st->channels = channels; - - st->upsample = 1; - st->start = 0; - st->end = st->mode->effEBands; - st->signalling = 1; - - st->arch = arch; - - st->constrained_vbr = 1; - st->clip = 1; - - st->bitrate = OPUS_BITRATE_MAX; - st->vbr = 0; - st->force_intra = 0; - st->complexity = 5; - st->lsb_depth=24; - - opus_custom_encoder_ctl(st, OPUS_RESET_STATE); - - return OPUS_OK; -} - -#ifdef CUSTOM_MODES -int opus_custom_encoder_init(CELTEncoder *st, const CELTMode *mode, int channels) -{ - return opus_custom_encoder_init_arch(st, mode, channels, opus_select_arch()); -} -#endif - -int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels, - int arch) -{ - int ret; - ret = opus_custom_encoder_init_arch(st, - opus_custom_mode_create(48000, 960, NULL), channels, arch); - if (ret != OPUS_OK) - return ret; - st->upsample = resampling_factor(sampling_rate); - return OPUS_OK; -} - -#ifdef CUSTOM_MODES -void opus_custom_encoder_destroy(CELTEncoder *st) -{ - opus_free(st); -} -#endif /* CUSTOM_MODES */ - - -static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int C, - opus_val16 *tf_estimate, int *tf_chan) -{ - int i; - VARDECL(opus_val16, tmp); - opus_val32 mem0,mem1; - int is_transient = 0; - opus_int32 mask_metric = 0; - int c; - opus_val16 tf_max; - int len2; - /* Table of 6*64/x, trained on real data to minimize the average error */ - static const unsigned char inv_table[128] = { - 255,255,156,110, 86, 70, 59, 51, 45, 40, 37, 33, 31, 28, 26, 25, - 23, 22, 21, 20, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12, - 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, - 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, - }; - SAVE_STACK; - ALLOC(tmp, len, opus_val16); - - len2=len/2; - for (c=0;c<C;c++) - { - opus_val32 mean; - opus_int32 unmask=0; - opus_val32 norm; - opus_val16 maxE; - mem0=0; - mem1=0; - /* High-pass filter: (1 - 2*z^-1 + z^-2) / (1 - z^-1 + .5*z^-2) */ - for (i=0;i<len;i++) - { - opus_val32 x,y; - x = SHR32(in[i+c*len],SIG_SHIFT); - y = ADD32(mem0, x); -#ifdef OPUS_FIXED_POINT - mem0 = mem1 + y - SHL32(x,1); - mem1 = x - SHR32(y,1); -#else - mem0 = mem1 + y - 2*x; - mem1 = x - .5f*y; -#endif - tmp[i] = EXTRACT16(SHR32(y,2)); - /*printf("%f ", tmp[i]);*/ - } - /*printf("\n");*/ - /* First few samples are bad because we don't propagate the memory */ - OPUS_CLEAR(tmp, 12); - -#ifdef OPUS_FIXED_POINT - /* Normalize tmp to max range */ - { - int shift=0; - shift = 14-celt_ilog2(1+celt_maxabs16(tmp, len)); - if (shift!=0) - { - for (i=0;i<len;i++) - tmp[i] = SHL16(tmp[i], shift); - } - } -#endif - - mean=0; - mem0=0; - /* Grouping by two to reduce complexity */ - /* Forward pass to compute the post-echo threshold*/ - for (i=0;i<len2;i++) - { - opus_val16 x2 = PSHR32(MULT16_16(tmp[2*i],tmp[2*i]) + MULT16_16(tmp[2*i+1],tmp[2*i+1]),16); - mean += x2; -#ifdef OPUS_FIXED_POINT - /* FIXME: Use PSHR16() instead */ - tmp[i] = mem0 + PSHR32(x2-mem0,4); -#else - tmp[i] = mem0 + MULT16_16_P15(QCONST16(.0625f,15),x2-mem0); -#endif - mem0 = tmp[i]; - } - - mem0=0; - maxE=0; - /* Backward pass to compute the pre-echo threshold */ - for (i=len2-1;i>=0;i--) - { -#ifdef OPUS_FIXED_POINT - /* FIXME: Use PSHR16() instead */ - tmp[i] = mem0 + PSHR32(tmp[i]-mem0,3); -#else - tmp[i] = mem0 + MULT16_16_P15(QCONST16(0.125f,15),tmp[i]-mem0); -#endif - mem0 = tmp[i]; - maxE = MAX16(maxE, mem0); - } - /*for (i=0;i<len2;i++)printf("%f ", tmp[i]/mean);printf("\n");*/ - - /* Compute the ratio of the "frame energy" over the harmonic mean of the energy. - This essentially corresponds to a bitrate-normalized temporal noise-to-mask - ratio */ - - /* As a compromise with the old transient detector, frame energy is the - geometric mean of the energy and half the max */ -#ifdef OPUS_FIXED_POINT - /* Costs two sqrt() to avoid overflows */ - mean = MULT16_16(celt_sqrt(mean), celt_sqrt(MULT16_16(maxE,len2>>1))); -#else - mean = celt_sqrt(mean * maxE*.5*len2); -#endif - /* Inverse of the mean energy in Q15+6 */ - norm = SHL32(EXTEND32(len2),6+14)/ADD32(EPSILON,SHR32(mean,1)); - /* Compute harmonic mean discarding the unreliable boundaries - The data is smooth, so we only take 1/4th of the samples */ - unmask=0; - for (i=12;i<len2-5;i+=4) - { - int id; -#ifdef OPUS_FIXED_POINT - id = MAX32(0,MIN32(127,MULT16_32_Q15(tmp[i]+EPSILON,norm))); /* Do not round to nearest */ -#else - id = (int)MAX32(0,MIN32(127,floor(64*norm*(tmp[i]+EPSILON)))); /* Do not round to nearest */ -#endif - unmask += inv_table[id]; - } - /*printf("%d\n", unmask);*/ - /* Normalize, compensate for the 1/4th of the sample and the factor of 6 in the inverse table */ - unmask = 64*unmask*4/(6*(len2-17)); - if (unmask>mask_metric) - { - *tf_chan = c; - mask_metric = unmask; - } - } - is_transient = mask_metric>200; - - /* Arbitrary metric for VBR boost */ - tf_max = MAX16(0,celt_sqrt(27*mask_metric)-42); - /* *tf_estimate = 1 + MIN16(1, sqrt(MAX16(0, tf_max-30))/20); */ - *tf_estimate = celt_sqrt(MAX32(0, SHL32(MULT16_16(QCONST16(0.0069,14),MIN16(163,tf_max)),14)-QCONST32(0.139,28))); - /*printf("%d %f\n", tf_max, mask_metric);*/ - RESTORE_STACK; -#ifdef FUZZING - is_transient = rand()&0x1; -#endif - /*printf("%d %f %d\n", is_transient, (float)*tf_estimate, tf_max);*/ - return is_transient; -} - -/* Looks for sudden increases of energy to decide whether we need to patch - the transient decision */ -static int patch_transient_decision(opus_val16 *newE, opus_val16 *oldE, int nbEBands, - int start, int end, int C) -{ - int i, c; - opus_val32 mean_diff=0; - opus_val16 spread_old[26]; - /* Apply an aggressive (-6 dB/Bark) spreading function to the old frame to - avoid false detection caused by irrelevant bands */ - if (C==1) - { - spread_old[start] = oldE[start]; - for (i=start+1;i<end;i++) - spread_old[i] = MAX16(spread_old[i-1]-QCONST16(1.0f, DB_SHIFT), oldE[i]); - } else { - spread_old[start] = MAX16(oldE[start],oldE[start+nbEBands]); - for (i=start+1;i<end;i++) - spread_old[i] = MAX16(spread_old[i-1]-QCONST16(1.0f, DB_SHIFT), - MAX16(oldE[i],oldE[i+nbEBands])); - } - for (i=end-2;i>=start;i--) - spread_old[i] = MAX16(spread_old[i], spread_old[i+1]-QCONST16(1.0f, DB_SHIFT)); - /* Compute mean increase */ - c=0; do { - for (i=IMAX(2,start);i<end-1;i++) - { - opus_val16 x1, x2; - x1 = MAX16(0, newE[i + c*nbEBands]); - x2 = MAX16(0, spread_old[i]); - mean_diff = ADD32(mean_diff, EXTEND32(MAX16(0, SUB16(x1, x2)))); - } - } while (++c<C); - mean_diff = DIV32(mean_diff, C*(end-1-IMAX(2,start))); - /*printf("%f %f %d\n", mean_diff, max_diff, count);*/ - return mean_diff > QCONST16(1.f, DB_SHIFT); -} - -/** Apply window and compute the MDCT for all sub-frames and - all channels in a frame */ -static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig * OPUS_RESTRICT in, - celt_sig * OPUS_RESTRICT out, int C, int CC, int LM, int upsample, - int arch) -{ - const int overlap = mode->overlap; - int N; - int B; - int shift; - int i, b, c; - if (shortBlocks) - { - B = shortBlocks; - N = mode->shortMdctSize; - shift = mode->maxLM; - } else { - B = 1; - N = mode->shortMdctSize<<LM; - shift = mode->maxLM-LM; - } - c=0; do { - for (b=0;b<B;b++) - { - /* Interleaving the sub-frames while doing the MDCTs */ - clt_mdct_forward(&mode->mdct, in+c*(B*N+overlap)+b*N, - &out[b+c*N*B], mode->window, overlap, shift, B, - arch); - } - } while (++c<CC); - if (CC==2&&C==1) - { - for (i=0;i<B*N;i++) - out[i] = ADD32(HALF32(out[i]), HALF32(out[B*N+i])); - } - if (upsample != 1) - { - c=0; do - { - int bound = B*N/upsample; - for (i=0;i<bound;i++) - out[c*B*N+i] *= upsample; - OPUS_CLEAR(&out[c*B*N+bound], B*N-bound); - } while (++c<C); - } -} - - -void celt_preemphasis(const opus_val16 * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp, - int N, int CC, int upsample, const opus_val16 *coef, celt_sig *mem, int clip) -{ - int i; - opus_val16 coef0; - celt_sig m; - int Nu; - - coef0 = coef[0]; - m = *mem; - - /* Fast path for the normal 48kHz case and no clipping */ - if (coef[1] == 0 && upsample == 1 && !clip) - { - for (i=0;i<N;i++) - { - opus_val16 x; - x = SCALEIN(pcmp[CC*i]); - /* Apply pre-emphasis */ - inp[i] = SHL32(x, SIG_SHIFT) - m; - m = SHR32(MULT16_16(coef0, x), 15-SIG_SHIFT); - } - *mem = m; - return; - } - - Nu = N/upsample; - if (upsample!=1) - { - OPUS_CLEAR(inp, N); - } - for (i=0;i<Nu;i++) - inp[i*upsample] = SCALEIN(pcmp[CC*i]); - -#ifndef OPUS_FIXED_POINT - if (clip) - { - /* Clip input to avoid encoding non-portable files */ - for (i=0;i<Nu;i++) - inp[i*upsample] = MAX32(-65536.f, MIN32(65536.f,inp[i*upsample])); - } -#else - (void)clip; /* Avoids a warning about clip being unused. */ -#endif -#ifdef CUSTOM_MODES - if (coef[1] != 0) - { - opus_val16 coef1 = coef[1]; - opus_val16 coef2 = coef[2]; - for (i=0;i<N;i++) - { - celt_sig x, tmp; - x = inp[i]; - /* Apply pre-emphasis */ - tmp = MULT16_16(coef2, x); - inp[i] = tmp + m; - m = MULT16_32_Q15(coef1, inp[i]) - MULT16_32_Q15(coef0, tmp); - } - } else -#endif - { - for (i=0;i<N;i++) - { - opus_val16 x; - x = inp[i]; - /* Apply pre-emphasis */ - inp[i] = SHL32(x, SIG_SHIFT) - m; - m = SHR32(MULT16_16(coef0, x), 15-SIG_SHIFT); - } - } - *mem = m; -} - - - -static opus_val32 l1_metric(const celt_norm *tmp, int N, int LM, opus_val16 bias) -{ - int i; - opus_val32 L1; - L1 = 0; - for (i=0;i<N;i++) - L1 += EXTEND32(ABS16(tmp[i])); - /* When in doubt, prefer good freq resolution */ - L1 = MAC16_32_Q15(L1, LM*bias, L1); - return L1; - -} - -static int tf_analysis(const CELTMode *m, int len, int isTransient, - int *tf_res, int lambda, celt_norm *X, int N0, int LM, - int *tf_sum, opus_val16 tf_estimate, int tf_chan) -{ - int i; - VARDECL(int, metric); - int cost0; - int cost1; - VARDECL(int, path0); - VARDECL(int, path1); - VARDECL(celt_norm, tmp); - VARDECL(celt_norm, tmp_1); - int sel; - int selcost[2]; - int tf_select=0; - opus_val16 bias; - - SAVE_STACK; - bias = MULT16_16_Q14(QCONST16(.04f,15), MAX16(-QCONST16(.25f,14), QCONST16(.5f,14)-tf_estimate)); - /*printf("%f ", bias);*/ - - ALLOC(metric, len, int); - ALLOC(tmp, (m->eBands[len]-m->eBands[len-1])<<LM, celt_norm); - ALLOC(tmp_1, (m->eBands[len]-m->eBands[len-1])<<LM, celt_norm); - ALLOC(path0, len, int); - ALLOC(path1, len, int); - - *tf_sum = 0; - for (i=0;i<len;i++) - { - int k, N; - int narrow; - opus_val32 L1, best_L1; - int best_level=0; - N = (m->eBands[i+1]-m->eBands[i])<<LM; - /* band is too narrow to be split down to LM=-1 */ - narrow = (m->eBands[i+1]-m->eBands[i])==1; - OPUS_COPY(tmp, &X[tf_chan*N0 + (m->eBands[i]<<LM)], N); - /* Just add the right channel if we're in stereo */ - /*if (C==2) - for (j=0;j<N;j++) - tmp[j] = ADD16(SHR16(tmp[j], 1),SHR16(X[N0+j+(m->eBands[i]<<LM)], 1));*/ - L1 = l1_metric(tmp, N, isTransient ? LM : 0, bias); - best_L1 = L1; - /* Check the -1 case for transients */ - if (isTransient && !narrow) - { - OPUS_COPY(tmp_1, tmp, N); - haar1(tmp_1, N>>LM, 1<<LM); - L1 = l1_metric(tmp_1, N, LM+1, bias); - if (L1<best_L1) - { - best_L1 = L1; - best_level = -1; - } - } - /*printf ("%f ", L1);*/ - for (k=0;k<LM+!(isTransient||narrow);k++) - { - int B; - - if (isTransient) - B = (LM-k-1); - else - B = k+1; - - haar1(tmp, N>>k, 1<<k); - - L1 = l1_metric(tmp, N, B, bias); - - if (L1 < best_L1) - { - best_L1 = L1; - best_level = k+1; - } - } - /*printf ("%d ", isTransient ? LM-best_level : best_level);*/ - /* metric is in Q1 to be able to select the mid-point (-0.5) for narrower bands */ - if (isTransient) - metric[i] = 2*best_level; - else - metric[i] = -2*best_level; - *tf_sum += (isTransient ? LM : 0) - metric[i]/2; - /* For bands that can't be split to -1, set the metric to the half-way point to avoid - biasing the decision */ - if (narrow && (metric[i]==0 || metric[i]==-2*LM)) - metric[i]-=1; - /*printf("%d ", metric[i]);*/ - } - /*printf("\n");*/ - /* Search for the optimal tf resolution, including tf_select */ - tf_select = 0; - for (sel=0;sel<2;sel++) - { - cost0 = 0; - cost1 = isTransient ? 0 : lambda; - for (i=1;i<len;i++) - { - int curr0, curr1; - curr0 = IMIN(cost0, cost1 + lambda); - curr1 = IMIN(cost0 + lambda, cost1); - cost0 = curr0 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*sel+0]); - cost1 = curr1 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*sel+1]); - } - cost0 = IMIN(cost0, cost1); - selcost[sel]=cost0; - } - /* For now, we're conservative and only allow tf_select=1 for transients. - * If tests confirm it's useful for non-transients, we could allow it. */ - if (selcost[1]<selcost[0] && isTransient) - tf_select=1; - cost0 = 0; - cost1 = isTransient ? 0 : lambda; - /* Viterbi forward pass */ - for (i=1;i<len;i++) - { - int curr0, curr1; - int from0, from1; - - from0 = cost0; - from1 = cost1 + lambda; - if (from0 < from1) - { - curr0 = from0; - path0[i]= 0; - } else { - curr0 = from1; - path0[i]= 1; - } - - from0 = cost0 + lambda; - from1 = cost1; - if (from0 < from1) - { - curr1 = from0; - path1[i]= 0; - } else { - curr1 = from1; - path1[i]= 1; - } - cost0 = curr0 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*tf_select+0]); - cost1 = curr1 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*tf_select+1]); - } - tf_res[len-1] = cost0 < cost1 ? 0 : 1; - /* Viterbi backward pass to check the decisions */ - for (i=len-2;i>=0;i--) - { - if (tf_res[i+1] == 1) - tf_res[i] = path1[i+1]; - else - tf_res[i] = path0[i+1]; - } - /*printf("%d %f\n", *tf_sum, tf_estimate);*/ - RESTORE_STACK; -#ifdef FUZZING - tf_select = rand()&0x1; - tf_res[0] = rand()&0x1; - for (i=1;i<len;i++) - tf_res[i] = tf_res[i-1] ^ ((rand()&0xF) == 0); -#endif - return tf_select; -} - -static void tf_encode(int start, int end, int isTransient, int *tf_res, int LM, int tf_select, ec_enc *enc) -{ - int curr, i; - int tf_select_rsv; - int tf_changed; - int logp; - opus_uint32 budget; - opus_uint32 tell; - budget = enc->storage*8; - tell = ec_tell(enc); - logp = isTransient ? 2 : 4; - /* Reserve space to code the tf_select decision. */ - tf_select_rsv = LM>0 && tell+logp+1 <= budget; - budget -= tf_select_rsv; - curr = tf_changed = 0; - for (i=start;i<end;i++) - { - if (tell+logp<=budget) - { - ec_enc_bit_logp(enc, tf_res[i] ^ curr, logp); - tell = ec_tell(enc); - curr = tf_res[i]; - tf_changed |= curr; - } - else - tf_res[i] = curr; - logp = isTransient ? 4 : 5; - } - /* Only code tf_select if it would actually make a difference. */ - if (tf_select_rsv && - tf_select_table[LM][4*isTransient+0+tf_changed]!= - tf_select_table[LM][4*isTransient+2+tf_changed]) - ec_enc_bit_logp(enc, tf_select, 1); - else - tf_select = 0; - for (i=start;i<end;i++) - tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]]; - /*for(i=0;i<end;i++)printf("%d ", isTransient ? tf_res[i] : LM+tf_res[i]);printf("\n");*/ -} - - -static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X, - const opus_val16 *bandLogE, int end, int LM, int C, int N0, - AnalysisInfo *analysis, opus_val16 *stereo_saving, opus_val16 tf_estimate, - int intensity, opus_val16 surround_trim, int arch) -{ - int i; - opus_val32 diff=0; - int c; - int trim_index; - opus_val16 trim = QCONST16(5.f, 8); - opus_val16 logXC, logXC2; - if (C==2) - { - opus_val16 sum = 0; /* Q10 */ - opus_val16 minXC; /* Q10 */ - /* Compute inter-channel correlation for low frequencies */ - for (i=0;i<8;i++) - { - opus_val32 partial; - partial = celt_inner_prod(&X[m->eBands[i]<<LM], &X[N0+(m->eBands[i]<<LM)], - (m->eBands[i+1]-m->eBands[i])<<LM, arch); - sum = ADD16(sum, EXTRACT16(SHR32(partial, 18))); - } - sum = MULT16_16_Q15(QCONST16(1.f/8, 15), sum); - sum = MIN16(QCONST16(1.f, 10), ABS16(sum)); - minXC = sum; - for (i=8;i<intensity;i++) - { - opus_val32 partial; - partial = celt_inner_prod(&X[m->eBands[i]<<LM], &X[N0+(m->eBands[i]<<LM)], - (m->eBands[i+1]-m->eBands[i])<<LM, arch); - minXC = MIN16(minXC, ABS16(EXTRACT16(SHR32(partial, 18)))); - } - minXC = MIN16(QCONST16(1.f, 10), ABS16(minXC)); - /*printf ("%f\n", sum);*/ - /* mid-side savings estimations based on the LF average*/ - logXC = celt_log2(QCONST32(1.001f, 20)-MULT16_16(sum, sum)); - /* mid-side savings estimations based on min correlation */ - logXC2 = MAX16(HALF16(logXC), celt_log2(QCONST32(1.001f, 20)-MULT16_16(minXC, minXC))); -#ifdef OPUS_FIXED_POINT - /* Compensate for Q20 vs Q14 input and convert output to Q8 */ - logXC = PSHR32(logXC-QCONST16(6.f, DB_SHIFT),DB_SHIFT-8); - logXC2 = PSHR32(logXC2-QCONST16(6.f, DB_SHIFT),DB_SHIFT-8); -#endif - - trim += MAX16(-QCONST16(4.f, 8), MULT16_16_Q15(QCONST16(.75f,15),logXC)); - *stereo_saving = MIN16(*stereo_saving + QCONST16(0.25f, 8), -HALF16(logXC2)); - } - - /* Estimate spectral tilt */ - c=0; do { - for (i=0;i<end-1;i++) - { - diff += bandLogE[i+c*m->nbEBands]*(opus_int32)(2+2*i-end); - } - } while (++c<C); - diff /= C*(end-1); - /*printf("%f\n", diff);*/ - trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), SHR16(diff+QCONST16(1.f, DB_SHIFT),DB_SHIFT-8)/6 )); - trim -= SHR16(surround_trim, DB_SHIFT-8); - trim -= 2*SHR16(tf_estimate, 14-8); -#ifndef DISABLE_FLOAT_API - if (analysis->valid) - { - trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), - (opus_val16)(QCONST16(2.f, 8)*(analysis->tonality_slope+.05f)))); - } -#else - (void)analysis; -#endif - -#ifdef OPUS_FIXED_POINT - trim_index = PSHR32(trim, 8); -#else - trim_index = (int)floor(.5f+trim); -#endif - trim_index = IMAX(0, IMIN(10, trim_index)); - /*printf("%d\n", trim_index);*/ -#ifdef FUZZING - trim_index = rand()%11; -#endif - return trim_index; -} - -static int stereo_analysis(const CELTMode *m, const celt_norm *X, - int LM, int N0) -{ - int i; - int thetas; - opus_val32 sumLR = EPSILON, sumMS = EPSILON; - - /* Use the L1 norm to model the entropy of the L/R signal vs the M/S signal */ - for (i=0;i<13;i++) - { - int j; - for (j=m->eBands[i]<<LM;j<m->eBands[i+1]<<LM;j++) - { - opus_val32 L, R, M, S; - /* We cast to 32-bit first because of the -32768 case */ - L = EXTEND32(X[j]); - R = EXTEND32(X[N0+j]); - M = ADD32(L, R); - S = SUB32(L, R); - sumLR = ADD32(sumLR, ADD32(ABS32(L), ABS32(R))); - sumMS = ADD32(sumMS, ADD32(ABS32(M), ABS32(S))); - } - } - sumMS = MULT16_32_Q15(QCONST16(0.707107f, 15), sumMS); - thetas = 13; - /* We don't need thetas for lower bands with LM<=1 */ - if (LM<=1) - thetas -= 8; - return MULT16_32_Q15((m->eBands[13]<<(LM+1))+thetas, sumMS) - > MULT16_32_Q15(m->eBands[13]<<(LM+1), sumLR); -} - -#define MSWAP(a,b) do {opus_val16 tmp = a;a=b;b=tmp;} while(0) -static opus_val16 median_of_5(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) - { - MSWAP(t0, t3); - MSWAP(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); - } -} - -static opus_val16 median_of_3(const opus_val16 *x) -{ - opus_val16 t0, t1, t2; - if (x[0] > x[1]) - { - t0 = x[1]; - t1 = x[0]; - } else { - t0 = x[0]; - t1 = x[1]; - } - t2 = x[2]; - if (t1 < t2) - return t1; - else if (t0 < t2) - return t2; - else - return t0; -} - -static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16 *bandLogE2, - int nbEBands, int start, int end, int C, int *offsets, int lsb_depth, const opus_int16 *logN, - int isTransient, int vbr, int constrained_vbr, const opus_int16 *eBands, int LM, - int effectiveBytes, opus_int32 *tot_boost_, int lfe, opus_val16 *surround_dynalloc) -{ - int i, c; - opus_int32 tot_boost=0; - opus_val16 maxDepth; - VARDECL(opus_val16, follower); - VARDECL(opus_val16, noise_floor); - SAVE_STACK; - ALLOC(follower, C*nbEBands, opus_val16); - ALLOC(noise_floor, C*nbEBands, opus_val16); - OPUS_CLEAR(offsets, nbEBands); - /* Dynamic allocation code */ - maxDepth=-QCONST16(31.9f, DB_SHIFT); - for (i=0;i<end;i++) - { - /* Noise floor must take into account eMeans, the depth, the width of the bands - and the preemphasis filter (approx. square of bark band ID) */ - noise_floor[i] = MULT16_16(QCONST16(0.0625f, DB_SHIFT),logN[i]) - +QCONST16(.5f,DB_SHIFT)+SHL16(9-lsb_depth,DB_SHIFT)-SHL16(eMeans[i],6) - +MULT16_16(QCONST16(.0062,DB_SHIFT),(i+5)*(i+5)); - } - c=0;do - { - for (i=0;i<end;i++) - maxDepth = MAX16(maxDepth, bandLogE[c*nbEBands+i]-noise_floor[i]); - } while (++c<C); - /* Make sure that dynamic allocation can't make us bust the budget */ - if (effectiveBytes > 50 && LM>=1 && !lfe) - { - int last=0; - c=0;do - { - opus_val16 offset; - opus_val16 tmp; - opus_val16 *f; - f = &follower[c*nbEBands]; - f[0] = bandLogE2[c*nbEBands]; - for (i=1;i<end;i++) - { - /* The last band to be at least 3 dB higher than the previous one - is the last we'll consider. Otherwise, we run into problems on - bandlimited signals. */ - if (bandLogE2[c*nbEBands+i] > bandLogE2[c*nbEBands+i-1]+QCONST16(.5f,DB_SHIFT)) - last=i; - f[i] = MIN16(f[i-1]+QCONST16(1.5f,DB_SHIFT), bandLogE2[c*nbEBands+i]); - } - for (i=last-1;i>=0;i--) - f[i] = MIN16(f[i], MIN16(f[i+1]+QCONST16(2.f,DB_SHIFT), bandLogE2[c*nbEBands+i])); - - /* Combine with a median filter to avoid dynalloc triggering unnecessarily. - The "offset" value controls how conservative we are -- a higher offset - reduces the impact of the median filter and makes dynalloc use more bits. */ - offset = QCONST16(1.f, DB_SHIFT); - for (i=2;i<end-2;i++) - f[i] = MAX16(f[i], median_of_5(&bandLogE2[c*nbEBands+i-2])-offset); - tmp = median_of_3(&bandLogE2[c*nbEBands])-offset; - f[0] = MAX16(f[0], tmp); - f[1] = MAX16(f[1], tmp); - tmp = median_of_3(&bandLogE2[c*nbEBands+end-3])-offset; - f[end-2] = MAX16(f[end-2], tmp); - f[end-1] = MAX16(f[end-1], tmp); - - for (i=0;i<end;i++) - f[i] = MAX16(f[i], noise_floor[i]); - } while (++c<C); - if (C==2) - { - for (i=start;i<end;i++) - { - /* Consider 24 dB "cross-talk" */ - follower[nbEBands+i] = MAX16(follower[nbEBands+i], follower[ i]-QCONST16(4.f,DB_SHIFT)); - follower[ i] = MAX16(follower[ i], follower[nbEBands+i]-QCONST16(4.f,DB_SHIFT)); - follower[i] = HALF16(MAX16(0, bandLogE[i]-follower[i]) + MAX16(0, bandLogE[nbEBands+i]-follower[nbEBands+i])); - } - } else { - for (i=start;i<end;i++) - { - follower[i] = MAX16(0, bandLogE[i]-follower[i]); - } - } - for (i=start;i<end;i++) - follower[i] = MAX16(follower[i], surround_dynalloc[i]); - /* For non-transient CBR/CVBR frames, halve the dynalloc contribution */ - if ((!vbr || constrained_vbr)&&!isTransient) - { - for (i=start;i<end;i++) - follower[i] = HALF16(follower[i]); - } - for (i=start;i<end;i++) - { - int width; - int boost; - int boost_bits; - - if (i<8) - follower[i] *= 2; - if (i>=12) - follower[i] = HALF16(follower[i]); - follower[i] = MIN16(follower[i], QCONST16(4, DB_SHIFT)); - - width = C*(eBands[i+1]-eBands[i])<<LM; - if (width<6) - { - boost = (int)SHR32(EXTEND32(follower[i]),DB_SHIFT); - boost_bits = boost*width<<BITRES; - } else if (width > 48) { - boost = (int)SHR32(EXTEND32(follower[i])*8,DB_SHIFT); - boost_bits = (boost*width<<BITRES)/8; - } else { - boost = (int)SHR32(EXTEND32(follower[i])*width/6,DB_SHIFT); - boost_bits = boost*6<<BITRES; - } - /* For CBR and non-transient CVBR frames, limit dynalloc to 1/4 of the bits */ - if ((!vbr || (constrained_vbr&&!isTransient)) - && (tot_boost+boost_bits)>>BITRES>>3 > effectiveBytes/4) - { - opus_int32 cap = ((effectiveBytes/4)<<BITRES<<3); - offsets[i] = cap-tot_boost; - tot_boost = cap; - break; - } else { - offsets[i] = boost; - tot_boost += boost_bits; - } - } - } - *tot_boost_ = tot_boost; - RESTORE_STACK; - return maxDepth; -} - - -static int run_prefilter(CELTEncoder *st, celt_sig *in, celt_sig *prefilter_mem, int CC, int N, - int prefilter_tapset, int *pitch, opus_val16 *gain, int *qgain, int enabled, int nbAvailableBytes) -{ - int c; - VARDECL(celt_sig, _pre); - celt_sig *pre[2]; - const CELTMode *mode; - int pitch_index; - opus_val16 gain1; - opus_val16 pf_threshold; - int pf_on; - int qg; - int overlap; - SAVE_STACK; - - mode = st->mode; - overlap = mode->overlap; - ALLOC(_pre, CC*(N+COMBFILTER_MAXPERIOD), celt_sig); - - pre[0] = _pre; - pre[1] = _pre + (N+COMBFILTER_MAXPERIOD); - - - c=0; do { - OPUS_COPY(pre[c], prefilter_mem+c*COMBFILTER_MAXPERIOD, COMBFILTER_MAXPERIOD); - OPUS_COPY(pre[c]+COMBFILTER_MAXPERIOD, in+c*(N+overlap)+overlap, N); - } while (++c<CC); - - if (enabled) - { - VARDECL(opus_val16, pitch_buf); - ALLOC(pitch_buf, (COMBFILTER_MAXPERIOD+N)>>1, opus_val16); - - pitch_downsample(pre, pitch_buf, COMBFILTER_MAXPERIOD+N, CC, st->arch); - /* Don't search for the fir last 1.5 octave of the range because - there's too many false-positives due to short-term correlation */ - pitch_search(pitch_buf+(COMBFILTER_MAXPERIOD>>1), pitch_buf, N, - COMBFILTER_MAXPERIOD-3*COMBFILTER_MINPERIOD, &pitch_index, - st->arch); - pitch_index = COMBFILTER_MAXPERIOD-pitch_index; - - gain1 = remove_doubling(pitch_buf, COMBFILTER_MAXPERIOD, COMBFILTER_MINPERIOD, - N, &pitch_index, st->prefilter_period, st->prefilter_gain, st->arch); - if (pitch_index > COMBFILTER_MAXPERIOD-2) - pitch_index = COMBFILTER_MAXPERIOD-2; - gain1 = MULT16_16_Q15(QCONST16(.7f,15),gain1); - /*printf("%d %d %f %f\n", pitch_change, pitch_index, gain1, st->analysis.tonality);*/ - if (st->loss_rate>2) - gain1 = HALF32(gain1); - if (st->loss_rate>4) - gain1 = HALF32(gain1); - if (st->loss_rate>8) - gain1 = 0; - } else { - gain1 = 0; - pitch_index = COMBFILTER_MINPERIOD; - } - - /* Gain threshold for enabling the prefilter/postfilter */ - pf_threshold = QCONST16(.2f,15); - - /* Adjusting the threshold based on rate and continuity */ - if (abs(pitch_index-st->prefilter_period)*10>pitch_index) - pf_threshold += QCONST16(.2f,15); - if (nbAvailableBytes<25) - pf_threshold += QCONST16(.1f,15); - if (nbAvailableBytes<35) - pf_threshold += QCONST16(.1f,15); - if (st->prefilter_gain > QCONST16(.4f,15)) - pf_threshold -= QCONST16(.1f,15); - if (st->prefilter_gain > QCONST16(.55f,15)) - pf_threshold -= QCONST16(.1f,15); - - /* Hard threshold at 0.2 */ - pf_threshold = MAX16(pf_threshold, QCONST16(.2f,15)); - if (gain1<pf_threshold) - { - gain1 = 0; - pf_on = 0; - qg = 0; - } else { - /*This block is not gated by a total bits check only because - of the nbAvailableBytes check above.*/ - if (ABS16(gain1-st->prefilter_gain)<QCONST16(.1f,15)) - gain1=st->prefilter_gain; - -#ifdef OPUS_FIXED_POINT - qg = ((gain1+1536)>>10)/3-1; -#else - qg = (int)floor(.5f+gain1*32/3)-1; -#endif - qg = IMAX(0, IMIN(7, qg)); - gain1 = QCONST16(0.09375f,15)*(qg+1); - pf_on = 1; - } - /*printf("%d %f\n", pitch_index, gain1);*/ - - c=0; do { - int offset = mode->shortMdctSize-overlap; - st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD); - OPUS_COPY(in+c*(N+overlap), st->in_mem+c*(overlap), overlap); - if (offset) - comb_filter(in+c*(N+overlap)+overlap, pre[c]+COMBFILTER_MAXPERIOD, - st->prefilter_period, st->prefilter_period, offset, -st->prefilter_gain, -st->prefilter_gain, - st->prefilter_tapset, st->prefilter_tapset, NULL, 0, st->arch); - - comb_filter(in+c*(N+overlap)+overlap+offset, pre[c]+COMBFILTER_MAXPERIOD+offset, - st->prefilter_period, pitch_index, N-offset, -st->prefilter_gain, -gain1, - st->prefilter_tapset, prefilter_tapset, mode->window, overlap, st->arch); - OPUS_COPY(st->in_mem+c*(overlap), in+c*(N+overlap)+N, overlap); - - if (N>COMBFILTER_MAXPERIOD) - { - OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, pre[c]+N, COMBFILTER_MAXPERIOD); - } else { - OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, prefilter_mem+c*COMBFILTER_MAXPERIOD+N, COMBFILTER_MAXPERIOD-N); - OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD+COMBFILTER_MAXPERIOD-N, pre[c]+COMBFILTER_MAXPERIOD, N); - } - } while (++c<CC); - - RESTORE_STACK; - *gain = gain1; - *pitch = pitch_index; - *qgain = qg; - return pf_on; -} - -static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32 base_target, - int LM, opus_int32 bitrate, int lastCodedBands, int C, int intensity, - int constrained_vbr, opus_val16 stereo_saving, int tot_boost, - opus_val16 tf_estimate, int pitch_change, opus_val16 maxDepth, - int variable_duration, int lfe, int has_surround_mask, opus_val16 surround_masking, - opus_val16 temporal_vbr) -{ - /* The target rate in 8th bits per frame */ - opus_int32 target; - int coded_bins; - int coded_bands; - opus_val16 tf_calibration; - int nbEBands; - const opus_int16 *eBands; - - nbEBands = mode->nbEBands; - eBands = mode->eBands; - - coded_bands = lastCodedBands ? lastCodedBands : nbEBands; - coded_bins = eBands[coded_bands]<<LM; - if (C==2) - coded_bins += eBands[IMIN(intensity, coded_bands)]<<LM; - - target = base_target; - - /*printf("%f %f %f %f %d %d ", st->analysis.activity, st->analysis.tonality, tf_estimate, st->stereo_saving, tot_boost, coded_bands);*/ -#ifndef DISABLE_FLOAT_API - if (analysis->valid && analysis->activity<.4) - target -= (opus_int32)((coded_bins<<BITRES)*(.4f-analysis->activity)); -#endif - /* Stereo savings */ - if (C==2) - { - int coded_stereo_bands; - int coded_stereo_dof; - opus_val16 max_frac; - coded_stereo_bands = IMIN(intensity, coded_bands); - coded_stereo_dof = (eBands[coded_stereo_bands]<<LM)-coded_stereo_bands; - /* Maximum fraction of the bits we can save if the signal is mono. */ - max_frac = DIV32_16(MULT16_16(QCONST16(0.8f, 15), coded_stereo_dof), coded_bins); - stereo_saving = MIN16(stereo_saving, QCONST16(1.f, 8)); - /*printf("%d %d %d ", coded_stereo_dof, coded_bins, tot_boost);*/ - target -= (opus_int32)MIN32(MULT16_32_Q15(max_frac,target), - SHR32(MULT16_16(stereo_saving-QCONST16(0.1f,8),(coded_stereo_dof<<BITRES)),8)); - } - /* Boost the rate according to dynalloc (minus the dynalloc average for calibration). */ - target += tot_boost-(16<<LM); - /* Apply transient boost, compensating for average boost. */ - tf_calibration = variable_duration==OPUS_FRAMESIZE_VARIABLE ? - QCONST16(0.02f,14) : QCONST16(0.04f,14); - target += (opus_int32)SHL32(MULT16_32_Q15(tf_estimate-tf_calibration, target),1); - -#ifndef DISABLE_FLOAT_API - /* Apply tonality boost */ - if (analysis->valid && !lfe) - { - opus_int32 tonal_target; - float tonal; - - /* Tonality boost (compensating for the average). */ - tonal = MAX16(0.f,analysis->tonality-.15f)-0.09f; - tonal_target = target + (opus_int32)((coded_bins<<BITRES)*1.2f*tonal); - if (pitch_change) - tonal_target += (opus_int32)((coded_bins<<BITRES)*.8f); - /*printf("%f %f ", analysis->tonality, tonal);*/ - target = tonal_target; - } -#else - (void)analysis; - (void)pitch_change; -#endif - - if (has_surround_mask&&!lfe) - { - opus_int32 surround_target = target + (opus_int32)SHR32(MULT16_16(surround_masking,coded_bins<<BITRES), DB_SHIFT); - /*printf("%f %d %d %d %d %d %d ", surround_masking, coded_bins, st->end, st->intensity, surround_target, target, st->bitrate);*/ - target = IMAX(target/4, surround_target); - } - - { - opus_int32 floor_depth; - int bins; - bins = eBands[nbEBands-2]<<LM; - /*floor_depth = SHR32(MULT16_16((C*bins<<BITRES),celt_log2(SHL32(MAX16(1,sample_max),13))), DB_SHIFT);*/ - floor_depth = (opus_int32)SHR32(MULT16_16((C*bins<<BITRES),maxDepth), DB_SHIFT); - floor_depth = IMAX(floor_depth, target>>2); - target = IMIN(target, floor_depth); - /*printf("%f %d\n", maxDepth, floor_depth);*/ - } - - if ((!has_surround_mask||lfe) && (constrained_vbr || bitrate<64000)) - { - opus_val16 rate_factor; -#ifdef OPUS_FIXED_POINT - rate_factor = MAX16(0,(bitrate-32000)); -#else - rate_factor = MAX16(0,(1.f/32768)*(bitrate-32000)); -#endif - if (constrained_vbr) - rate_factor = MIN16(rate_factor, QCONST16(0.67f, 15)); - target = base_target + (opus_int32)MULT16_32_Q15(rate_factor, target-base_target); - - } - - if (!has_surround_mask && tf_estimate < QCONST16(.2f, 14)) - { - opus_val16 amount; - opus_val16 tvbr_factor; - amount = MULT16_16_Q15(QCONST16(.0000031f, 30), IMAX(0, IMIN(32000, 96000-bitrate))); - tvbr_factor = SHR32(MULT16_16(temporal_vbr, amount), DB_SHIFT); - target += (opus_int32)MULT16_32_Q15(tvbr_factor, target); - } - - /* Don't allow more than doubling the rate */ - target = IMIN(2*base_target, target); - - return target; -} - -int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc) -{ - int i, c, N; - opus_int32 bits; - ec_enc _enc; - VARDECL(celt_sig, in); - VARDECL(celt_sig, freq); - VARDECL(celt_norm, X); - VARDECL(celt_ener, bandE); - VARDECL(opus_val16, bandLogE); - VARDECL(opus_val16, bandLogE2); - VARDECL(int, fine_quant); - VARDECL(opus_val16, error); - VARDECL(int, pulses); - VARDECL(int, cap); - VARDECL(int, offsets); - VARDECL(int, fine_priority); - VARDECL(int, tf_res); - VARDECL(unsigned char, collapse_masks); - celt_sig *prefilter_mem; - opus_val16 *oldBandE, *oldLogE, *oldLogE2; - int shortBlocks=0; - int isTransient=0; - const int CC = st->channels; - const int C = st->stream_channels; - int LM, M; - int tf_select; - int nbFilledBytes, nbAvailableBytes; - int start; - int end; - int effEnd; - int codedBands; - int tf_sum; - int alloc_trim; - int pitch_index=COMBFILTER_MINPERIOD; - opus_val16 gain1 = 0; - int dual_stereo=0; - int effectiveBytes; - int dynalloc_logp; - opus_int32 vbr_rate; - opus_int32 total_bits; - opus_int32 total_boost; - opus_int32 balance; - opus_int32 tell; - int prefilter_tapset=0; - int pf_on; - int anti_collapse_rsv; - int anti_collapse_on=0; - int silence=0; - int tf_chan = 0; - opus_val16 tf_estimate; - int pitch_change=0; - opus_int32 tot_boost; - opus_val32 sample_max; - opus_val16 maxDepth; - const OpusCustomMode *mode; - int nbEBands; - int overlap; - const opus_int16 *eBands; - int secondMdct; - int signalBandwidth; - int transient_got_disabled=0; - opus_val16 surround_masking=0; - opus_val16 temporal_vbr=0; - opus_val16 surround_trim = 0; - opus_int32 equiv_rate = 510000; - VARDECL(opus_val16, surround_dynalloc); - ALLOC_STACK; - - mode = st->mode; - nbEBands = mode->nbEBands; - overlap = mode->overlap; - eBands = mode->eBands; - start = st->start; - end = st->end; - tf_estimate = 0; - if (nbCompressedBytes<2 || pcm==NULL) - { - RESTORE_STACK; - return OPUS_BAD_ARG; - } - - frame_size *= st->upsample; - for (LM=0;LM<=mode->maxLM;LM++) - if (mode->shortMdctSize<<LM==frame_size) - break; - if (LM>mode->maxLM) - { - RESTORE_STACK; - return OPUS_BAD_ARG; - } - M=1<<LM; - N = M*mode->shortMdctSize; - - prefilter_mem = st->in_mem+CC*(overlap); - oldBandE = (opus_val16*)(st->in_mem+CC*(overlap+COMBFILTER_MAXPERIOD)); - oldLogE = oldBandE + CC*nbEBands; - oldLogE2 = oldLogE + CC*nbEBands; - - if (enc==NULL) - { - tell=1; - nbFilledBytes=0; - } else { - tell=ec_tell(enc); - nbFilledBytes=(tell+4)>>3; - } - -#ifdef CUSTOM_MODES - if (st->signalling && enc==NULL) - { - int tmp = (mode->effEBands-end)>>1; - end = st->end = IMAX(1, mode->effEBands-tmp); - compressed[0] = tmp<<5; - compressed[0] |= LM<<3; - compressed[0] |= (C==2)<<2; - /* Convert "standard mode" to Opus header */ - if (mode->Fs==48000 && mode->shortMdctSize==120) - { - int c0 = toOpus(compressed[0]); - if (c0<0) - { - RESTORE_STACK; - return OPUS_BAD_ARG; - } - compressed[0] = c0; - } - compressed++; - nbCompressedBytes--; - } -#else - celt_assert(st->signalling==0); -#endif - - /* Can't produce more than 1275 output bytes */ - nbCompressedBytes = IMIN(nbCompressedBytes,1275); - nbAvailableBytes = nbCompressedBytes - nbFilledBytes; - - if (st->vbr && st->bitrate!=OPUS_BITRATE_MAX) - { - opus_int32 den=mode->Fs>>BITRES; - vbr_rate=(st->bitrate*frame_size+(den>>1))/den; -#ifdef CUSTOM_MODES - if (st->signalling) - vbr_rate -= 8<<BITRES; -#endif - effectiveBytes = vbr_rate>>(3+BITRES); - } else { - opus_int32 tmp; - vbr_rate = 0; - tmp = st->bitrate*frame_size; - if (tell>1) - tmp += tell; - if (st->bitrate!=OPUS_BITRATE_MAX) - nbCompressedBytes = IMAX(2, IMIN(nbCompressedBytes, - (tmp+4*mode->Fs)/(8*mode->Fs)-!!st->signalling)); - effectiveBytes = nbCompressedBytes; - } - if (st->bitrate != OPUS_BITRATE_MAX) - equiv_rate = st->bitrate - (40*C+20)*((400>>LM) - 50); - - if (enc==NULL) - { - ec_enc_init(&_enc, compressed, nbCompressedBytes); - enc = &_enc; - } - - if (vbr_rate>0) - { - /* Computes the max bit-rate allowed in VBR mode to avoid violating the - target rate and buffering. - We must do this up front so that bust-prevention logic triggers - correctly if we don't have enough bits. */ - if (st->constrained_vbr) - { - opus_int32 vbr_bound; - opus_int32 max_allowed; - /* We could use any multiple of vbr_rate as bound (depending on the - delay). - This is clamped to ensure we use at least two bytes if the encoder - was entirely empty, but to allow 0 in hybrid mode. */ - vbr_bound = vbr_rate; - max_allowed = IMIN(IMAX(tell==1?2:0, - (vbr_rate+vbr_bound-st->vbr_reservoir)>>(BITRES+3)), - nbAvailableBytes); - if(max_allowed < nbAvailableBytes) - { - nbCompressedBytes = nbFilledBytes+max_allowed; - nbAvailableBytes = max_allowed; - ec_enc_shrink(enc, nbCompressedBytes); - } - } - } - total_bits = nbCompressedBytes*8; - - effEnd = end; - if (effEnd > mode->effEBands) - effEnd = mode->effEBands; - - ALLOC(in, CC*(N+overlap), celt_sig); - - sample_max=MAX32(st->overlap_max, celt_maxabs16(pcm, C*(N-overlap)/st->upsample)); - st->overlap_max=celt_maxabs16(pcm+C*(N-overlap)/st->upsample, C*overlap/st->upsample); - sample_max=MAX32(sample_max, st->overlap_max); -#ifdef OPUS_FIXED_POINT - silence = (sample_max==0); -#else - silence = (sample_max <= (opus_val16)1/(1<<st->lsb_depth)); -#endif -#ifdef FUZZING - if ((rand()&0x3F)==0) - silence = 1; -#endif - if (tell==1) - ec_enc_bit_logp(enc, silence, 15); - else - silence=0; - if (silence) - { - /*In VBR mode there is no need to send more than the minimum. */ - if (vbr_rate>0) - { - effectiveBytes=nbCompressedBytes=IMIN(nbCompressedBytes, nbFilledBytes+2); - total_bits=nbCompressedBytes*8; - nbAvailableBytes=2; - ec_enc_shrink(enc, nbCompressedBytes); - } - /* Pretend we've filled all the remaining bits with zeros - (that's what the initialiser did anyway) */ - tell = nbCompressedBytes*8; - enc->nbits_total+=tell-ec_tell(enc); - } - c=0; do { - int need_clip=0; -#ifndef OPUS_FIXED_POINT - need_clip = st->clip && sample_max>65536.f; -#endif - celt_preemphasis(pcm+c, in+c*(N+overlap)+overlap, N, CC, st->upsample, - mode->preemph, st->preemph_memE+c, need_clip); - } while (++c<CC); - - - - /* Find pitch period and gain */ - { - int enabled; - int qg; - enabled = ((st->lfe&&nbAvailableBytes>3) || nbAvailableBytes>12*C) && start==0 && !silence && !st->disable_pf - && st->complexity >= 5 && !(st->consec_transient && LM!=3 && st->variable_duration==OPUS_FRAMESIZE_VARIABLE); - - prefilter_tapset = st->tapset_decision; - pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, nbAvailableBytes); - if ((gain1 > QCONST16(.4f,15) || st->prefilter_gain > QCONST16(.4f,15)) && (!st->analysis.valid || st->analysis.tonality > .3) - && (pitch_index > 1.26*st->prefilter_period || pitch_index < .79*st->prefilter_period)) - pitch_change = 1; - if (pf_on==0) - { - if(start==0 && tell+16<=total_bits) - ec_enc_bit_logp(enc, 0, 1); - } else { - /*This block is not gated by a total bits check only because - of the nbAvailableBytes check above.*/ - int octave; - ec_enc_bit_logp(enc, 1, 1); - pitch_index += 1; - octave = EC_ILOG(pitch_index)-5; - ec_enc_uint(enc, octave, 6); - ec_enc_bits(enc, pitch_index-(16<<octave), 4+octave); - pitch_index -= 1; - ec_enc_bits(enc, qg, 3); - ec_enc_icdf(enc, prefilter_tapset, tapset_icdf, 2); - } - } - - isTransient = 0; - shortBlocks = 0; - if (st->complexity >= 1 && !st->lfe) - { - isTransient = transient_analysis(in, N+overlap, CC, - &tf_estimate, &tf_chan); - } - if (LM>0 && ec_tell(enc)+3<=total_bits) - { - if (isTransient) - shortBlocks = M; - } else { - isTransient = 0; - transient_got_disabled=1; - } - - ALLOC(freq, CC*N, celt_sig); /**< Interleaved signal MDCTs */ - ALLOC(bandE,nbEBands*CC, celt_ener); - ALLOC(bandLogE,nbEBands*CC, opus_val16); - - secondMdct = shortBlocks && st->complexity>=8; - ALLOC(bandLogE2, C*nbEBands, opus_val16); - if (secondMdct) - { - compute_mdcts(mode, 0, in, freq, C, CC, LM, st->upsample, st->arch); - compute_band_energies(mode, freq, bandE, effEnd, C, LM); - amp2Log2(mode, effEnd, end, bandE, bandLogE2, C); - for (i=0;i<C*nbEBands;i++) - bandLogE2[i] += HALF16(SHL16(LM, DB_SHIFT)); - } - - compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample, st->arch); - if (CC==2&&C==1) - tf_chan = 0; - compute_band_energies(mode, freq, bandE, effEnd, C, LM); - - if (st->lfe) - { - for (i=2;i<end;i++) - { - bandE[i] = IMIN(bandE[i], MULT16_32_Q15(QCONST16(1e-4f,15),bandE[0])); - bandE[i] = MAX32(bandE[i], EPSILON); - } - } - amp2Log2(mode, effEnd, end, bandE, bandLogE, C); - - ALLOC(surround_dynalloc, C*nbEBands, opus_val16); - OPUS_CLEAR(surround_dynalloc, end); - /* This computes how much masking takes place between surround channels */ - if (start==0&&st->energy_mask&&!st->lfe) - { - int mask_end; - int midband; - int count_dynalloc; - opus_val32 mask_avg=0; - opus_val32 diff=0; - int count=0; - mask_end = IMAX(2,st->lastCodedBands); - for (c=0;c<C;c++) - { - for(i=0;i<mask_end;i++) - { - opus_val16 mask; - mask = MAX16(MIN16(st->energy_mask[nbEBands*c+i], - QCONST16(.25f, DB_SHIFT)), -QCONST16(2.0f, DB_SHIFT)); - if (mask > 0) - mask = HALF16(mask); - mask_avg += MULT16_16(mask, eBands[i+1]-eBands[i]); - count += eBands[i+1]-eBands[i]; - diff += MULT16_16(mask, 1+2*i-mask_end); - } - } - celt_assert(count>0); - mask_avg = DIV32_16(mask_avg,count); - mask_avg += QCONST16(.2f, DB_SHIFT); - diff = diff*6/(C*(mask_end-1)*(mask_end+1)*mask_end); - /* Again, being conservative */ - diff = HALF32(diff); - diff = MAX32(MIN32(diff, QCONST32(.031f, DB_SHIFT)), -QCONST32(.031f, DB_SHIFT)); - /* Find the band that's in the middle of the coded spectrum */ - for (midband=0;eBands[midband+1] < eBands[mask_end]/2;midband++); - count_dynalloc=0; - for(i=0;i<mask_end;i++) - { - opus_val32 lin; - opus_val16 unmask; - lin = mask_avg + diff*(i-midband); - if (C==2) - unmask = MAX16(st->energy_mask[i], st->energy_mask[nbEBands+i]); - else - unmask = st->energy_mask[i]; - unmask = MIN16(unmask, QCONST16(.0f, DB_SHIFT)); - unmask -= lin; - if (unmask > QCONST16(.25f, DB_SHIFT)) - { - surround_dynalloc[i] = unmask - QCONST16(.25f, DB_SHIFT); - count_dynalloc++; - } - } - if (count_dynalloc>=3) - { - /* If we need dynalloc in many bands, it's probably because our - initial masking rate was too low. */ - mask_avg += QCONST16(.25f, DB_SHIFT); - if (mask_avg>0) - { - /* Something went really wrong in the original calculations, - disabling masking. */ - mask_avg = 0; - diff = 0; - OPUS_CLEAR(surround_dynalloc, mask_end); - } else { - for(i=0;i<mask_end;i++) - surround_dynalloc[i] = MAX16(0, surround_dynalloc[i]-QCONST16(.25f, DB_SHIFT)); - } - } - mask_avg += QCONST16(.2f, DB_SHIFT); - /* Convert to 1/64th units used for the trim */ - surround_trim = 64*diff; - /*printf("%d %d ", mask_avg, surround_trim);*/ - surround_masking = mask_avg; - } - /* Temporal VBR (but not for LFE) */ - if (!st->lfe) - { - opus_val16 follow=-QCONST16(10.0f,DB_SHIFT); - opus_val32 frame_avg=0; - opus_val16 offset = shortBlocks?HALF16(SHL16(LM, DB_SHIFT)):0; - for(i=start;i<end;i++) - { - follow = MAX16(follow-QCONST16(1.f, DB_SHIFT), bandLogE[i]-offset); - if (C==2) - follow = MAX16(follow, bandLogE[i+nbEBands]-offset); - frame_avg += follow; - } - frame_avg /= (end-start); - temporal_vbr = SUB16(frame_avg,st->spec_avg); - temporal_vbr = MIN16(QCONST16(3.f, DB_SHIFT), MAX16(-QCONST16(1.5f, DB_SHIFT), temporal_vbr)); - st->spec_avg += MULT16_16_Q15(QCONST16(.02f, 15), temporal_vbr); - } - /*for (i=0;i<21;i++) - printf("%f ", bandLogE[i]); - printf("\n");*/ - - if (!secondMdct) - { - OPUS_COPY(bandLogE2, bandLogE, C*nbEBands); - } - - /* Last chance to catch any transient we might have missed in the - time-domain analysis */ - if (LM>0 && ec_tell(enc)+3<=total_bits && !isTransient && st->complexity>=5 && !st->lfe) - { - if (patch_transient_decision(bandLogE, oldBandE, nbEBands, start, end, C)) - { - isTransient = 1; - shortBlocks = M; - compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample, st->arch); - compute_band_energies(mode, freq, bandE, effEnd, C, LM); - amp2Log2(mode, effEnd, end, bandE, bandLogE, C); - /* Compensate for the scaling of short vs long mdcts */ - for (i=0;i<C*nbEBands;i++) - bandLogE2[i] += HALF16(SHL16(LM, DB_SHIFT)); - tf_estimate = QCONST16(.2f,14); - } - } - - if (LM>0 && ec_tell(enc)+3<=total_bits) - ec_enc_bit_logp(enc, isTransient, 3); - - ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ - - /* Band normalisation */ - normalise_bands(mode, freq, X, bandE, effEnd, C, M); - - ALLOC(tf_res, nbEBands, int); - /* Disable variable tf resolution for hybrid and at very low bitrate */ - if (effectiveBytes>=15*C && start==0 && st->complexity>=2 && !st->lfe) - { - int lambda; - if (effectiveBytes<40) - lambda = 12; - else if (effectiveBytes<60) - lambda = 6; - else if (effectiveBytes<100) - lambda = 4; - else - lambda = 3; - lambda*=2; - tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, &tf_sum, tf_estimate, tf_chan); - for (i=effEnd;i<end;i++) - tf_res[i] = tf_res[effEnd-1]; - } else { - tf_sum = 0; - for (i=0;i<end;i++) - tf_res[i] = isTransient; - tf_select=0; - } - - ALLOC(error, C*nbEBands, opus_val16); - quant_coarse_energy(mode, start, end, effEnd, bandLogE, - oldBandE, total_bits, error, enc, - C, LM, nbAvailableBytes, st->force_intra, - &st->delayedIntra, st->complexity >= 4, st->loss_rate, st->lfe); - - tf_encode(start, end, isTransient, tf_res, LM, tf_select, enc); - - if (ec_tell(enc)+4<=total_bits) - { - if (st->lfe) - { - st->tapset_decision = 0; - st->spread_decision = SPREAD_NORMAL; - } else if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C || start != 0) - { - if (st->complexity == 0) - st->spread_decision = SPREAD_NONE; - else - st->spread_decision = SPREAD_NORMAL; - } else { - /* Disable new spreading+tapset estimator until we can show it works - better than the old one. So far it seems like spreading_decision() - works best. */ -#if 0 - if (st->analysis.valid) - { - static const opus_val16 spread_thresholds[3] = {-QCONST16(.6f, 15), -QCONST16(.2f, 15), -QCONST16(.07f, 15)}; - static const opus_val16 spread_histeresis[3] = {QCONST16(.15f, 15), QCONST16(.07f, 15), QCONST16(.02f, 15)}; - static const opus_val16 tapset_thresholds[2] = {QCONST16(.0f, 15), QCONST16(.15f, 15)}; - static const opus_val16 tapset_histeresis[2] = {QCONST16(.1f, 15), QCONST16(.05f, 15)}; - st->spread_decision = hysteresis_decision(-st->analysis.tonality, spread_thresholds, spread_histeresis, 3, st->spread_decision); - st->tapset_decision = hysteresis_decision(st->analysis.tonality_slope, tapset_thresholds, tapset_histeresis, 2, st->tapset_decision); - } else -#endif - { - st->spread_decision = spreading_decision(mode, X, - &st->tonal_average, st->spread_decision, &st->hf_average, - &st->tapset_decision, pf_on&&!shortBlocks, effEnd, C, M); - } - /*printf("%d %d\n", st->tapset_decision, st->spread_decision);*/ - /*printf("%f %d %f %d\n\n", st->analysis.tonality, st->spread_decision, st->analysis.tonality_slope, st->tapset_decision);*/ - } - ec_enc_icdf(enc, st->spread_decision, spread_icdf, 5); - } - - ALLOC(offsets, nbEBands, int); - - maxDepth = dynalloc_analysis(bandLogE, bandLogE2, nbEBands, start, end, C, offsets, - st->lsb_depth, mode->logN, isTransient, st->vbr, st->constrained_vbr, - eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc); - /* For LFE, everything interesting is in the first band */ - if (st->lfe) - offsets[0] = IMIN(8, effectiveBytes/3); - ALLOC(cap, nbEBands, int); - init_caps(mode,cap,LM,C); - - dynalloc_logp = 6; - total_bits<<=BITRES; - total_boost = 0; - tell = ec_tell_frac(enc); - for (i=start;i<end;i++) - { - int width, quanta; - int dynalloc_loop_logp; - int boost; - int j; - 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; - for (j = 0; tell+(dynalloc_loop_logp<<BITRES) < total_bits-total_boost - && boost < cap[i]; j++) - { - int flag; - flag = j<offsets[i]; - ec_enc_bit_logp(enc, flag, dynalloc_loop_logp); - tell = ec_tell_frac(enc); - if (!flag) - break; - boost += quanta; - total_boost += quanta; - dynalloc_loop_logp = 1; - } - /* Making dynalloc more likely */ - if (j) - dynalloc_logp = IMAX(2, dynalloc_logp-1); - offsets[i] = boost; - } - - if (C==2) - { - static const opus_val16 intensity_thresholds[21]= - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 off*/ - { 1, 2, 3, 4, 5, 6, 7, 8,16,24,36,44,50,56,62,67,72,79,88,106,134}; - static const opus_val16 intensity_histeresis[21]= - { 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 5, 6, 8, 8}; - - /* Always use MS for 2.5 ms frames until we can do a better analysis */ - if (LM!=0) - dual_stereo = stereo_analysis(mode, X, LM, N); - - st->intensity = hysteresis_decision((opus_val16)(equiv_rate/1000), - intensity_thresholds, intensity_histeresis, 21, st->intensity); - st->intensity = IMIN(end,IMAX(start, st->intensity)); - } - - alloc_trim = 5; - if (tell+(6<<BITRES) <= total_bits - total_boost) - { - if (st->lfe) - alloc_trim = 5; - else - alloc_trim = alloc_trim_analysis(mode, X, bandLogE, - end, LM, C, N, &st->analysis, &st->stereo_saving, tf_estimate, - st->intensity, surround_trim, st->arch); - ec_enc_icdf(enc, alloc_trim, trim_icdf, 7); - tell = ec_tell_frac(enc); - } - - /* Variable bitrate */ - if (vbr_rate>0) - { - opus_val16 alpha; - opus_int32 delta; - /* The target rate in 8th bits per frame */ - opus_int32 target, base_target; - opus_int32 min_allowed; - int lm_diff = mode->maxLM - LM; - - /* Don't attempt to use more than 510 kb/s, even for frames smaller than 20 ms. - The CELT allocator will just not be able to use more than that anyway. */ - nbCompressedBytes = IMIN(nbCompressedBytes,1275>>(3-LM)); - base_target = vbr_rate - ((40*C+20)<<BITRES); - - if (st->constrained_vbr) - base_target += (st->vbr_offset>>lm_diff); - - target = compute_vbr(mode, &st->analysis, base_target, LM, equiv_rate, - st->lastCodedBands, C, st->intensity, st->constrained_vbr, - st->stereo_saving, tot_boost, tf_estimate, pitch_change, maxDepth, - st->variable_duration, st->lfe, st->energy_mask!=NULL, surround_masking, - temporal_vbr); - - /* The current offset is removed from the target and the space used - so far is added*/ - target=target+tell; - /* In VBR mode the frame size must not be reduced so much that it would - result in the encoder running out of bits. - The margin of 2 bytes ensures that none of the bust-prevention logic - in the decoder will have triggered so far. */ - min_allowed = ((tell+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3)) + 2 - nbFilledBytes; - - nbAvailableBytes = (target+(1<<(BITRES+2)))>>(BITRES+3); - nbAvailableBytes = IMAX(min_allowed,nbAvailableBytes); - nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes) - nbFilledBytes; - - /* By how much did we "miss" the target on that frame */ - delta = target - vbr_rate; - - target=nbAvailableBytes<<(BITRES+3); - - /*If the frame is silent we don't adjust our drift, otherwise - the encoder will shoot to very high rates after hitting a - span of silence, but we do allow the bitres to refill. - This means that we'll undershoot our target in CVBR/VBR modes - on files with lots of silence. */ - if(silence) - { - nbAvailableBytes = 2; - target = 2*8<<BITRES; - delta = 0; - } - - if (st->vbr_count < 970) - { - st->vbr_count++; - alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+20),16)); - } else - alpha = QCONST16(.001f,15); - /* How many bits have we used in excess of what we're allowed */ - if (st->constrained_vbr) - st->vbr_reservoir += target - vbr_rate; - /*printf ("%d\n", st->vbr_reservoir);*/ - - /* Compute the offset we need to apply in order to reach the target */ - if (st->constrained_vbr) - { - st->vbr_drift += (opus_int32)MULT16_32_Q15(alpha,(delta*(1<<lm_diff))-st->vbr_offset-st->vbr_drift); - st->vbr_offset = -st->vbr_drift; - } - /*printf ("%d\n", st->vbr_drift);*/ - - if (st->constrained_vbr && st->vbr_reservoir < 0) - { - /* We're under the min value -- increase rate */ - int adjust = (-st->vbr_reservoir)/(8<<BITRES); - /* Unless we're just coding silence */ - nbAvailableBytes += silence?0:adjust; - st->vbr_reservoir = 0; - /*printf ("+%d\n", adjust);*/ - } - nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes); - /*printf("%d\n", nbCompressedBytes*50*8);*/ - /* This moves the raw bits to take into account the new compressed size */ - ec_enc_shrink(enc, nbCompressedBytes); - } - - /* Bit allocation */ - ALLOC(fine_quant, nbEBands, int); - ALLOC(pulses, nbEBands, int); - ALLOC(fine_priority, nbEBands, int); - - /* bits = packet size - where we are - safety*/ - bits = (((opus_int32)nbCompressedBytes*8)<<BITRES) - ec_tell_frac(enc) - 1; - anti_collapse_rsv = isTransient&&LM>=2&&bits>=((LM+2)<<BITRES) ? (1<<BITRES) : 0; - bits -= anti_collapse_rsv; - signalBandwidth = end-1; -#ifndef DISABLE_FLOAT_API - if (st->analysis.valid) - { - int min_bandwidth; - if (equiv_rate < (opus_int32)32000*C) - min_bandwidth = 13; - else if (equiv_rate < (opus_int32)48000*C) - min_bandwidth = 16; - else if (equiv_rate < (opus_int32)60000*C) - min_bandwidth = 18; - else if (equiv_rate < (opus_int32)80000*C) - min_bandwidth = 19; - else - min_bandwidth = 20; - signalBandwidth = IMAX(st->analysis.bandwidth, min_bandwidth); - } -#endif - if (st->lfe) - signalBandwidth = 1; - codedBands = compute_allocation(mode, start, end, offsets, cap, - alloc_trim, &st->intensity, &dual_stereo, bits, &balance, pulses, - fine_quant, fine_priority, C, LM, enc, 1, st->lastCodedBands, signalBandwidth); - if (st->lastCodedBands) - st->lastCodedBands = IMIN(st->lastCodedBands+1,IMAX(st->lastCodedBands-1,codedBands)); - else - st->lastCodedBands = codedBands; - - quant_fine_energy(mode, start, end, oldBandE, error, fine_quant, enc, C); - - /* Residual quantisation */ - ALLOC(collapse_masks, C*nbEBands, unsigned char); - quant_all_bands(1, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks, - bandE, pulses, shortBlocks, st->spread_decision, - dual_stereo, st->intensity, tf_res, nbCompressedBytes*(8<<BITRES)-anti_collapse_rsv, - balance, enc, LM, codedBands, &st->rng, st->arch); - - if (anti_collapse_rsv > 0) - { - anti_collapse_on = st->consec_transient<2; -#ifdef FUZZING - anti_collapse_on = rand()&0x1; -#endif - ec_enc_bits(enc, anti_collapse_on, 1); - } - quant_energy_finalise(mode, start, end, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_tell(enc), enc, C); - - if (silence) - { - for (i=0;i<C*nbEBands;i++) - oldBandE[i] = -QCONST16(28.f,DB_SHIFT); - } - -#ifdef RESYNTH - /* Re-synthesis of the coded audio if required */ - { - celt_sig *out_mem[2]; - - if (anti_collapse_on) - { - anti_collapse(mode, X, collapse_masks, LM, C, N, - start, end, oldBandE, oldLogE, oldLogE2, pulses, st->rng); - } - - c=0; do { - OPUS_MOVE(st->syn_mem[c], st->syn_mem[c]+N, 2*MAX_PERIOD-N+overlap/2); - } while (++c<CC); - - c=0; do { - out_mem[c] = st->syn_mem[c]+2*MAX_PERIOD-N; - } while (++c<CC); - - celt_synthesis(mode, X, out_mem, oldBandE, start, effEnd, - C, CC, isTransient, LM, st->upsample, silence, st->arch); - - c=0; do { - st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD); - st->prefilter_period_old=IMAX(st->prefilter_period_old, COMBFILTER_MINPERIOD); - comb_filter(out_mem[c], out_mem[c], st->prefilter_period_old, st->prefilter_period, mode->shortMdctSize, - st->prefilter_gain_old, st->prefilter_gain, st->prefilter_tapset_old, st->prefilter_tapset, - mode->window, overlap); - if (LM!=0) - comb_filter(out_mem[c]+mode->shortMdctSize, out_mem[c]+mode->shortMdctSize, st->prefilter_period, pitch_index, N-mode->shortMdctSize, - st->prefilter_gain, gain1, st->prefilter_tapset, prefilter_tapset, - mode->window, overlap); - } while (++c<CC); - - /* We reuse freq[] as scratch space for the de-emphasis */ - deemphasis(out_mem, (opus_val16*)pcm, N, CC, st->upsample, mode->preemph, st->preemph_memD); - st->prefilter_period_old = st->prefilter_period; - st->prefilter_gain_old = st->prefilter_gain; - st->prefilter_tapset_old = st->prefilter_tapset; - } -#endif - - st->prefilter_period = pitch_index; - st->prefilter_gain = gain1; - st->prefilter_tapset = prefilter_tapset; -#ifdef RESYNTH - if (LM!=0) - { - st->prefilter_period_old = st->prefilter_period; - st->prefilter_gain_old = st->prefilter_gain; - st->prefilter_tapset_old = st->prefilter_tapset; - } -#endif - - if (CC==2&&C==1) { - OPUS_COPY(&oldBandE[nbEBands], oldBandE, nbEBands); - } - - if (!isTransient) - { - OPUS_COPY(oldLogE2, oldLogE, CC*nbEBands); - OPUS_COPY(oldLogE, oldBandE, CC*nbEBands); - } else { - for (i=0;i<CC*nbEBands;i++) - oldLogE[i] = MIN16(oldLogE[i], 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]=-QCONST16(28.f,DB_SHIFT); - } - for (i=end;i<nbEBands;i++) - { - oldBandE[c*nbEBands+i]=0; - oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT); - } - } while (++c<CC); - - if (isTransient || transient_got_disabled) - st->consec_transient++; - else - st->consec_transient=0; - st->rng = enc->rng; - - /* If there's any room left (can only happen for very high rates), - it's already filled with zeros */ - ec_enc_done(enc); - -#ifdef CUSTOM_MODES - if (st->signalling) - nbCompressedBytes++; -#endif - - RESTORE_STACK; - if (ec_get_error(enc)) - return OPUS_INTERNAL_ERROR; - else - return nbCompressedBytes; -} - - -#ifdef CUSTOM_MODES - -#ifdef OPUS_FIXED_POINT -int opus_custom_encode(CELTEncoder * OPUS_RESTRICT st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) -{ - return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL); -} - -#ifndef DISABLE_FLOAT_API -int opus_custom_encode_float(CELTEncoder * OPUS_RESTRICT st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) -{ - int j, ret, C, N; - VARDECL(opus_int16, in); - ALLOC_STACK; - - if (pcm==NULL) - return OPUS_BAD_ARG; - - C = st->channels; - N = frame_size; - ALLOC(in, C*N, opus_int16); - - for (j=0;j<C*N;j++) - in[j] = FLOAT2INT16(pcm[j]); - - ret=celt_encode_with_ec(st,in,frame_size,compressed,nbCompressedBytes, NULL); -#ifdef RESYNTH - for (j=0;j<C*N;j++) - ((float*)pcm)[j]=in[j]*(1.f/32768.f); -#endif - RESTORE_STACK; - return ret; -} -#endif /* DISABLE_FLOAT_API */ -#else - -int opus_custom_encode(CELTEncoder * OPUS_RESTRICT st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) -{ - int j, ret, C, N; - VARDECL(celt_sig, in); - ALLOC_STACK; - - if (pcm==NULL) - return OPUS_BAD_ARG; - - C=st->channels; - N=frame_size; - ALLOC(in, C*N, celt_sig); - for (j=0;j<C*N;j++) { - in[j] = SCALEOUT(pcm[j]); - } - - ret = celt_encode_with_ec(st,in,frame_size,compressed,nbCompressedBytes, NULL); -#ifdef RESYNTH - for (j=0;j<C*N;j++) - ((opus_int16*)pcm)[j] = FLOAT2INT16(in[j]); -#endif - RESTORE_STACK; - return ret; -} - -int opus_custom_encode_float(CELTEncoder * OPUS_RESTRICT st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) -{ - return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL); -} - -#endif - -#endif /* CUSTOM_MODES */ - -int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...) -{ - va_list ap; - - va_start(ap, request); - switch (request) - { - case OPUS_SET_COMPLEXITY_REQUEST: - { - int value = va_arg(ap, opus_int32); - if (value<0 || value>10) - goto bad_arg; - st->complexity = value; - } - 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_PREDICTION_REQUEST: - { - int value = va_arg(ap, opus_int32); - if (value<0 || value>2) - goto bad_arg; - st->disable_pf = value<=1; - st->force_intra = value==0; - } - break; - case OPUS_SET_PACKET_LOSS_PERC_REQUEST: - { - int value = va_arg(ap, opus_int32); - if (value<0 || value>100) - goto bad_arg; - st->loss_rate = value; - } - break; - case OPUS_SET_VBR_CONSTRAINT_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - st->constrained_vbr = value; - } - break; - case OPUS_SET_VBR_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - st->vbr = value; - } - break; - case OPUS_SET_BITRATE_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if (value<=500 && value!=OPUS_BITRATE_MAX) - goto bad_arg; - value = IMIN(value, 260000*st->channels); - st->bitrate = 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 OPUS_SET_LSB_DEPTH_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if (value<8 || value>24) - goto bad_arg; - st->lsb_depth=value; - } - break; - case OPUS_GET_LSB_DEPTH_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - *value=st->lsb_depth; - } - break; - case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - st->variable_duration = value; - } - break; - case OPUS_RESET_STATE: - { - int i; - opus_val16 *oldBandE, *oldLogE, *oldLogE2; - oldBandE = (opus_val16*)(st->in_mem+st->channels*(st->mode->overlap+COMBFILTER_MAXPERIOD)); - oldLogE = oldBandE + st->channels*st->mode->nbEBands; - oldLogE2 = oldLogE + st->channels*st->mode->nbEBands; - OPUS_CLEAR((char*)&st->ENCODER_RESET_START, - opus_custom_encoder_get_size(st->mode, st->channels)- - ((char*)&st->ENCODER_RESET_START - (char*)st)); - for (i=0;i<st->channels*st->mode->nbEBands;i++) - oldLogE[i]=oldLogE2[i]=-QCONST16(28.f,DB_SHIFT); - st->vbr_offset = 0; - st->delayedIntra = 1; - st->spread_decision = SPREAD_NORMAL; - st->tonal_average = 256; - st->hf_average = 0; - st->tapset_decision = 0; - } - break; -#ifdef CUSTOM_MODES - case CELT_SET_INPUT_CLIPPING_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - st->clip = value; - } - break; -#endif - case CELT_SET_SIGNALLING_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - st->signalling = value; - } - break; - case CELT_SET_ANALYSIS_REQUEST: - { - AnalysisInfo *info = va_arg(ap, AnalysisInfo *); - if (info) - OPUS_COPY(&st->analysis, info, 1); - } - 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 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_LFE_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - st->lfe = value; - } - break; - case OPUS_SET_ENERGY_MASK_REQUEST: - { - opus_val16 *value = va_arg(ap, opus_val16*); - st->energy_mask = value; - } - 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/drivers/opus/celt/celt_lpc.c b/drivers/opus/celt/celt_lpc.c deleted file mode 100644 index 5b8c01021f..0000000000 --- a/drivers/opus/celt/celt_lpc.c +++ /dev/null @@ -1,312 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/celt/celt_lpc.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/mathops.h" -#include "opus/celt/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 OPUS_FIXED_POINT - opus_val32 lpc[LPC_ORDER]; -#else - float *lpc = _lpc; -#endif - - for (i = 0; i < p; i++) - lpc[i] = 0; - if (ac[0] != 0) - { - for (i = 0; i < p; i++) { - /* Sum up this iteration's reflection coefficient */ - opus_val32 rr = 0; - for (j = 0; j < i; j++) - rr += MULT32_32_Q31(lpc[j],ac[i - j]); - rr += SHR32(ac[i + 1],3); - r = -frac_div32(SHL32(rr,3), error); - /* Update LPC coefficients and total error */ - lpc[i] = SHR32(r,3); - 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 OPUS_FIXED_POINT - if (error<SHR32(ac[0],10)) - break; -#else - if (error<.001f*ac[0]) - break; -#endif - } - } -#ifdef OPUS_FIXED_POINT - for (i=0;i<p;i++) - _lpc[i] = ROUND16(lpc[i],16); -#endif -} - - -void celt_fir_c( - const opus_val16 *_x, - const opus_val16 *num, - opus_val16 *_y, - int N, - int ord, - opus_val16 *mem, - int arch) -{ - int i,j; - VARDECL(opus_val16, rnum); - VARDECL(opus_val16, x); - SAVE_STACK; - - ALLOC(rnum, ord, opus_val16); - ALLOC(x, N+ord, opus_val16); - for(i=0;i<ord;i++) - rnum[i] = num[ord-i-1]; - for(i=0;i<ord;i++) - x[i] = mem[ord-i-1]; - for (i=0;i<N;i++) - x[i+ord]=_x[i]; - for(i=0;i<ord;i++) - mem[i] = _x[N-i-1]; -#ifdef SMALL_FOOTPRINT - (void)arch; - for (i=0;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]); - } - _y[i] = SATURATE16(PSHR32(sum, SIG_SHIFT)); - } -#else - for (i=0;i<N-3;i+=4) - { - opus_val32 sum[4]={0,0,0,0}; - xcorr_kernel(rnum, x+i, sum, ord, arch); - _y[i ] = SATURATE16(ADD32(EXTEND32(_x[i ]), PSHR32(sum[0], SIG_SHIFT))); - _y[i+1] = SATURATE16(ADD32(EXTEND32(_x[i+1]), PSHR32(sum[1], SIG_SHIFT))); - _y[i+2] = SATURATE16(ADD32(EXTEND32(_x[i+2]), PSHR32(sum[2], SIG_SHIFT))); - _y[i+3] = SATURATE16(ADD32(EXTEND32(_x[i+3]), PSHR32(sum[3], SIG_SHIFT))); - } - for (;i<N;i++) - { - opus_val32 sum = 0; - for (j=0;j<ord;j++) - sum = MAC16_16(sum,rnum[j],x[i+j]); - _y[i] = SATURATE16(ADD32(EXTEND32(_x[i]), PSHR32(sum, SIG_SHIFT))); - } -#endif - 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] = ROUND16(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]; - xcorr_kernel(rden, y+i, sum, ord, arch); - - /* Patch up the result to compensate for the fact that this is an IIR */ - y[i+ord ] = -ROUND16(sum[0],SIG_SHIFT); - _y[i ] = sum[0]; - sum[1] = MAC16_16(sum[1], y[i+ord ], den[0]); - y[i+ord+1] = -ROUND16(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] = -ROUND16(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] = -ROUND16(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] = ROUND16(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 opus_val16 *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++) - { - xx[i] = MULT16_16_Q15(x[i],window[i]); - xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]); - } - xptr = xx; - } - shift=0; -#ifdef OPUS_FIXED_POINT - { - opus_val32 ac0; - ac0 = 1+(n<<7); - if (n&1) ac0 += SHR32(MULT16_16(xptr[0],xptr[0]),9); - for(i=(n&1);i<n;i+=2) - { - ac0 += SHR32(MULT16_16(xptr[i],xptr[i]),9); - ac0 += SHR32(MULT16_16(xptr[i+1],xptr[i+1]),9); - } - - shift = celt_ilog2(ac0)-30+10; - 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 OPUS_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/drivers/opus/celt/celt_lpc.h b/drivers/opus/celt/celt_lpc.h deleted file mode 100644 index dc0352d468..0000000000 --- a/drivers/opus/celt/celt_lpc.h +++ /dev/null @@ -1,67 +0,0 @@ -/* 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 PLC_H -#define PLC_H - -#include "opus/celt/arch.h" -#include "opus/celt/cpu_support.h" - -#if defined(OPUS_X86_MAY_HAVE_SSE4_1) -#include "opus/celt/x86/celt_lpc_sse.h" -#endif - -#define 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, - opus_val16 *mem, - int arch); - -#if !defined(OVERRIDE_CELT_FIR) -#define celt_fir(x, num, y, N, ord, mem, arch) \ - (celt_fir_c(x, num, y, N, ord, mem, 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 opus_val16 *window, int overlap, int lag, int n, int arch); - -#endif /* PLC_H */ diff --git a/drivers/opus/celt/cpu_support.h b/drivers/opus/celt/cpu_support.h deleted file mode 100644 index 2507e1861e..0000000000 --- a/drivers/opus/celt/cpu_support.h +++ /dev/null @@ -1,70 +0,0 @@ -/* 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/opus_types.h" -#include "opus/opus_defines.h" - -#if defined(OPUS_HAVE_RTCD) && \ - (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)) -#include "opus/celt/arm/armcpu.h" - -/* We currently support 4 ARM variants: - * arch[0] -> ARMv4 - * arch[1] -> ARMv5E - * arch[2] -> ARMv6 - * arch[3] -> NEON - */ -#define OPUS_ARCHMASK 3 - -#elif (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_AVX) && !defined(OPUS_X86_PRESUME_AVX)) - -#include "opus/celt/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/drivers/opus/celt/cwrs.c b/drivers/opus/celt/cwrs.c deleted file mode 100644 index 983d4580a9..0000000000 --- a/drivers/opus/celt/cwrs.c +++ /dev/null @@ -1,712 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/celt/os_support.h" -#include "opus/celt/cwrs.h" -#include "opus/celt/mathops.h" -#include "opus/celt/arch.h" - -#ifdef 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 - http://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(CUSTOM_MODES) -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(CUSTOM_MODES) - /*...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(CUSTOM_MODES) - /*...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(CUSTOM_MODES) - /*...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(CUSTOM_MODES) - /*...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(CUSTOM_MODES) - /*...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(CUSTOM_MODES) - /*...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(CUSTOM_MODES) - /*...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(CUSTOM_MODES) - /*...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(CUSTOM_MODES) - /*...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(CUSTOM_MODES) - /*...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(CUSTOM_MODES) - /*...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(CUSTOM_MODES) -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_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; -} - -#ifdef 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/drivers/opus/celt/cwrs.h b/drivers/opus/celt/cwrs.h deleted file mode 100644 index f0ea844e5e..0000000000 --- a/drivers/opus/celt/cwrs.h +++ /dev/null @@ -1,48 +0,0 @@ -/* 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 "opus/celt/arch.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/entenc.h" -#include "opus/celt/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/drivers/opus/celt/ecintrin.h b/drivers/opus/celt/ecintrin.h deleted file mode 100644 index 6ed8fb280e..0000000000 --- a/drivers/opus/celt/ecintrin.h +++ /dev/null @@ -1,87 +0,0 @@ -/* 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/opus_types.h" -#include <math.h> -#include <limits.h> -#include "opus/celt/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) -# include <intrin.h> -/*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/drivers/opus/celt/entcode.c b/drivers/opus/celt/entcode.c deleted file mode 100644 index d1c6b25c7f..0000000000 --- a/drivers/opus/celt/entcode.c +++ /dev/null @@ -1,150 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/celt/entcode.h" -#include "opus/celt/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/drivers/opus/celt/entcode.h b/drivers/opus/celt/entcode.h deleted file mode 100644 index 4d736d4dca..0000000000 --- a/drivers/opus/celt/entcode.h +++ /dev/null @@ -1,152 +0,0 @@ -/* 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/opus_types.h" -#include "opus/opus_defines.h" - -#if !defined(_entcode_H) -# define _entcode_H (1) -# include <limits.h> -# include <stddef.h> -# include "opus/celt/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 oustanding 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_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_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/drivers/opus/celt/entdec.c b/drivers/opus/celt/entdec.c deleted file mode 100644 index fdc49c92c1..0000000000 --- a/drivers/opus/celt/entdec.c +++ /dev/null @@ -1,242 +0,0 @@ -/* 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/opus_config.h" - -#include <stddef.h> -#include "opus/celt/os_support.h" -#include "opus/celt/arch.h" -#include "opus/celt/entdec.h" -#include "opus/celt/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; -} - -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/drivers/opus/celt/entdec.h b/drivers/opus/celt/entdec.h deleted file mode 100644 index fda60ab326..0000000000 --- a/drivers/opus/celt/entdec.h +++ /dev/null @@ -1,100 +0,0 @@ -/* 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 "opus/celt/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); - -/*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 one, 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/drivers/opus/celt/entenc.c b/drivers/opus/celt/entenc.c deleted file mode 100644 index da7f2c8e62..0000000000 --- a/drivers/opus/celt/entenc.c +++ /dev/null @@ -1,291 +0,0 @@ -/* 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/opus_config.h" -#include "opus/celt/os_support.h" -#include "opus/celt/arch.h" -#include "opus/celt/entenc.h" -#include "opus/celt/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_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){ - 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/drivers/opus/celt/entenc.h b/drivers/opus/celt/entenc.h deleted file mode 100644 index 3f4a3acc93..0000000000 --- a/drivers/opus/celt/entenc.h +++ /dev/null @@ -1,110 +0,0 @@ -/* 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 "opus/celt/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 discernable 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 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 one, 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 reamining 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/drivers/opus/celt/fixed_debug.h b/drivers/opus/celt/fixed_debug.h deleted file mode 100644 index 3b8d5ef7a9..0000000000 --- a/drivers/opus/celt/fixed_debug.h +++ /dev/null @@ -1,784 +0,0 @@ -/* 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/opus_defines.h" - -#ifdef CELT_C -OPUS_EXPORT opus_int64 celt_mips=0; -#else -extern opus_int64 celt_mips; -#endif - -#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)) - -/** 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_val32)1)<<(bits)))) - -#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) - -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) -{ - int 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 = 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", a, shift, file, line); -#ifdef FIXED_DEBUG_ASSERT - celt_assert(0); -#endif - } - res = a<<shift; - if (!VERIFY_INT(res)) - { - fprintf (stderr, "SHL32: output is not int: %lld<<%d = %lld in %s: line %d\n", a, shift, 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 ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a)))) -#define HALF16(x) (SHR16(x,1)) -#define HALF32(x) (SHR32(x,1)) - -//#define SHR(a,shift) ((a) >> (shift)) -//#define SHL(a,shift) ((a) << (shift)) - -#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", a, 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", 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", a, 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", a, 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", a, b, 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; -} - -#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_val32)(1)<<(15+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)<<(15+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", celt_mips);} while (0); - -#endif diff --git a/drivers/opus/celt/fixed_generic.h b/drivers/opus/celt/fixed_generic.h deleted file mode 100644 index 71ab048e4a..0000000000 --- a/drivers/opus/celt/fixed_generic.h +++ /dev/null @@ -1,151 +0,0 @@ -/* 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 */ -#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR((b),16)), SHR(MULT16_16SU((a),((b)&0x0000ffff)),16)) - -/** 16x32 multiplication, followed by a 16-bit shift right (round-to-nearest). Results fits in 32 bits */ -#define MULT16_32_P16(a,b) ADD32(MULT16_16((a),SHR((b),16)), PSHR(MULT16_16SU((a),((b)&0x0000ffff)),16)) - -/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */ -#define MULT16_32_Q15(a,b) ADD32(SHL(MULT16_16((a),SHR((b),16)),1), SHR(MULT16_16SU((a),((b)&0x0000ffff)),15)) - -/** 32x32 multiplication, followed by a 31-bit shift right. Results fits in 32 bits */ -#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)) - -/** 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_val32)1)<<(bits)))) - -/** 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))) - -/** "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-neareast 32-bit value. Result is a 16-bit value */ -#define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a)))) -/** 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)) - -/** 16x16 multiplication where the result fits in 16 bits */ -#define MULT16_16_16(a,b) ((((opus_val16)(a))*((opus_val16)(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(MIPSr1_ASM) -#include "opus/celt/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/drivers/opus/celt/float_cast.h b/drivers/opus/celt/float_cast.h deleted file mode 100644 index 36a1bfe671..0000000000 --- a/drivers/opus/celt/float_cast.h +++ /dev/null @@ -1,140 +0,0 @@ -/* 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 "opus/celt/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. -*/ - -#if (HAVE_LRINTF) - -/* 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)) - -#define _ISOC9X_SOURCE 1 -#define _ISOC99_SOURCE 1 - -#define __USE_ISOC9X 1 -#define __USE_ISOC99 1 - -#include <math.h> -#define float2int(x) lrint(x) - -#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && defined (_M_X64) - #include <xmmintrin.h> - - __inline long int float2int(float value) - { - 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. - */ - - __inline long int - float2int (float flt) - { int intgr; - - _asm - { fld flt - fistp intgr - } ; - - return intgr ; - } - -#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); -} -#endif /* DISABLE_FLOAT_API */ - -#endif /* FLOAT_CAST_H */ diff --git a/drivers/opus/celt/kiss_fft.c b/drivers/opus/celt/kiss_fft.c deleted file mode 100644 index cf8d049fa1..0000000000 --- a/drivers/opus/celt/kiss_fft.c +++ /dev/null @@ -1,602 +0,0 @@ -/*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 -#include "opus/opus_config.h" -#endif - -#include "opus/celt/_kiss_fft_guts.h" -#include "opus/celt/arch.h" -#include "opus/celt/os_support.h" -#include "opus/celt/mathops.h" -#include "opus/celt/stack_alloc.h" - -/* The guts header contains all the multiplication and addition macros that are defined for - complex numbers. It also delares 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 - { - opus_val16 tw; - tw = QCONST16(0.7071067812f, 15); - /* 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(Fout2[1].r+Fout2[1].i, tw); - t.i = S_MUL(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 = -Fout2[2].r; - C_SUB( Fout2[2] , Fout[2] , t ); - C_ADDTO( Fout[2] , t ); - - t.r = S_MUL(Fout2[3].i-Fout2[3].r, tw); - t.i = S_MUL(-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 = scratch0.r + scratch1.i; - Fout[1].i = scratch0.i - scratch1.r; - Fout[3].r = scratch0.r - scratch1.i; - Fout[3].i = 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 = scratch[5].r + scratch[4].i; - Fout[m].i = scratch[5].i - scratch[4].r; - Fout[m3].r = scratch[5].r - scratch[4].i; - Fout[m3].i = 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 OPUS_FIXED_POINT - epi3.r = -16384; - epi3.i = -28378; -#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 = Fout->r - HALF_OF(scratch[3].r); - Fout[m].i = Fout->i - HALF_OF(scratch[3].i); - - C_MULBYSCALAR( scratch[0] , epi3.i ); - - C_ADDTO(*Fout,scratch[3]); - - Fout[m2].r = Fout[m].r + scratch[0].i; - Fout[m2].i = Fout[m].i - scratch[0].r; - - Fout[m].r -= scratch[0].i; - 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 OPUS_FIXED_POINT - ya.r = 10126; - ya.i = -31164; - yb.r = -26510; - yb.i = -19261; -#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 += scratch[7].r + scratch[8].r; - Fout0->i += scratch[7].i + scratch[8].i; - - scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r); - scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r); - - scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i); - scratch[6].i = -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 = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r); - scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r); - scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i); - scratch[12].i = 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 OPUS_FIXED_POINT - for (i=0;i<nfft;++i) { - opus_val32 phase = -i; - kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft)); - } -#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 OPUS_FIXED_POINT - st->scale_shift = celt_ilog2(st->nfft); - if (st->nfft == 1<<st->scale_shift) - st->scale = Q15ONE; - else - st->scale = (1073741824+st->nfft/2)/st->nfft>>(15-st->scale_shift); -#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 */ - -void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout) -{ - 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: - kf_bfly2(fout, m, fstride[i]); - break; - case 4: - kf_bfly4(fout,fstride[i]<<shift,st,m, fstride[i], m2); - break; - #ifndef RADIX_TWO_ONLY - case 3: - kf_bfly3(fout,fstride[i]<<shift,st,m, fstride[i], m2); - break; - case 5: - kf_bfly5(fout,fstride[i]<<shift,st,m, fstride[i], m2); - break; - #endif - } - m = m2; - } -} - -void opus_fft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) -{ - int i; - opus_val16 scale; -#ifdef OPUS_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 = SHR32(MULT16_32_Q16(scale, x.r), scale_shift); - fout[st->bitrev[i]].i = SHR32(MULT16_32_Q16(scale, x.i), scale_shift); - } - opus_fft_impl(st, fout); -} - - -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); - for (i=0;i<st->nfft;i++) - fout[i].i = -fout[i].i; -} diff --git a/drivers/opus/celt/kiss_fft.h b/drivers/opus/celt/kiss_fft.h deleted file mode 100644 index 6229044c43..0000000000 --- a/drivers/opus/celt/kiss_fft.h +++ /dev/null @@ -1,200 +0,0 @@ -/*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 "opus/celt/arch.h" -#include "opus/celt/cpu_support.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#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 OPUS_FIXED_POINT -#include "opus/celt/arch.h" - -# define kiss_fft_scalar opus_int32 -# define kiss_twiddle_scalar opus_int16 - - -#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 - -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; - -#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; - opus_val16 scale; -#ifdef OPUS_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 "opus/celt/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); -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) */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/opus/celt/laplace.c b/drivers/opus/celt/laplace.c deleted file mode 100644 index 5bc956af45..0000000000 --- a/drivers/opus/celt/laplace.c +++ /dev/null @@ -1,131 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/celt/laplace.h" -#include "opus/celt/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; -} diff --git a/drivers/opus/celt/laplace.h b/drivers/opus/celt/laplace.h deleted file mode 100644 index 9efcc73aa2..0000000000 --- a/drivers/opus/celt/laplace.h +++ /dev/null @@ -1,48 +0,0 @@ -/* 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. -*/ - -#include "opus/celt/entenc.h" -#include "opus/celt/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); diff --git a/drivers/opus/celt/mathops.c b/drivers/opus/celt/mathops.c deleted file mode 100644 index 3f7c1a8bdd..0000000000 --- a/drivers/opus/celt/mathops.c +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (c) 2002-2008 Jean-Marc Valin - Copyright (c) 2007-2008 CSIRO - Copyright (c) 2007-2009 Xiph.Org Foundation - 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. -*/ -#include "opus/opus_config.h" - -#include "opus/celt/mathops.h" - -/*Compute floor(sqrt(_val)) with exact arithmetic. - This has been tested on all possible 32-bit inputs.*/ -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 OPUS_FIXED_POINT - -opus_val32 frac_div32(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)); - 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)))); -} - -/** Sqrt approximation (QX input, QX/2 output) */ -opus_val32 celt_sqrt(opus_val32 x) -{ - int k; - opus_val16 n; - opus_val32 rt; - static const opus_val16 C[5] = {23175, 11561, -3011, 1699, -664}; - 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 = 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]))))))))); - rt = VSHR32(rt,7-k); - return rt; -} - -#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 NEG32(_celt_cos_pi_2(EXTRACT16(65536-x))); - } - } else { - if (x&0x0000ffff) - return 0; - else if (x&0x0001ffff) - return -32767; - else - return 32767; - } -} - -/** Reciprocal approximation (Q15 input, Q16 output) */ -opus_val32 celt_rcp(opus_val32 x) -{ - int i; - opus_val16 n; - opus_val16 r; - celt_assert2(x>0, "celt_rcp() only defined for positive values"); - i = celt_ilog2(x); - /* n is Q15 with range [0,1). */ - n = VSHR32(x,i-15)-32768; - /* 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, n)); - /* Perform two Newton iterations: - r -= r*((r*n)-1.Q15) - = r*((r*n)+(r-1.Q15)). */ - r = SUB16(r, MULT16_16_Q15(r, - ADD16(MULT16_16_Q15(r, n), 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. */ - r = SUB16(r, ADD16(1, MULT16_16_Q15(r, - ADD16(MULT16_16_Q15(r, n), ADD16(r, -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 diff --git a/drivers/opus/celt/mathops.h b/drivers/opus/celt/mathops.h deleted file mode 100644 index a008d71e18..0000000000 --- a/drivers/opus/celt/mathops.h +++ /dev/null @@ -1,258 +0,0 @@ -/* Copyright (c) 2002-2008 Jean-Marc Valin - Copyright (c) 2007-2008 CSIRO - Copyright (c) 2007-2009 Xiph.Org Foundation - 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. -*/ - -#ifndef MATHOPS_H -#define MATHOPS_H - -#include "opus/celt/arch.h" -#include "opus/celt/entcode.h" -#include "opus/celt/os_support.h" - -/* 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); - -#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 - -#ifndef OVERRIDE_CELT_MAXABS32 -#ifdef OPUS_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 OPUS_FIXED_POINT - -#define PI 3.141592653f -#define celt_sqrt(x) ((float)sqrt(x)) -#define celt_rsqrt(x) (1.f/celt_sqrt(x)) -#define celt_rsqrt_norm(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)) - -#ifdef FLOAT_APPROX - -/* Note: This assumes radix-2 floating point with the exponent at bits 23..30 and an offset of 127 - denorm, +/- inf and NaN are *not* handled */ - -/** Base-2 log approximation (log2(x)). */ -static OPUS_INLINE float celt_log2(float x) -{ - int integer; - float frac; - union { - float f; - opus_uint32 i; - } in; - in.f = x; - integer = (in.i>>23)-127; - in.i -= integer<<23; - frac = in.f - 1.5f; - frac = -0.41445418f + frac*(0.95909232f - + frac*(-0.33951290f + frac*0.16541097f)); - return 1+integer+frac; -} - -/** Base-2 exponential approximation (2^x). */ -static OPUS_INLINE float celt_exp2(float x) -{ - int integer; - float frac; - union { - float f; - opus_uint32 i; - } res; - integer = floor(x); - if (integer < -50) - return 0; - frac = x-integer; - /* K0 = 1, K1 = log(2), K2 = 3-4*log(2), K3 = 3*log(2) - 2 */ - res.f = 0.99992522f + frac * (0.69583354f - + frac * (0.22606716f + 0.078024523f*frac)); - res.i = (res.i + (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 - -#endif - -#ifdef OPUS_FIXED_POINT - -#include "opus/celt/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_assert2(x>0, "celt_ilog2() only defined for strictly positive numbers"); - 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_sqrt(opus_val32 x); - -opus_val16 celt_cos_norm(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-DB_SHIFT)), 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 SHL16(i-13,DB_SHIFT)+SHR16(frac,14-DB_SHIFT); -} - -/* - 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)))))); -} -/** 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); -} - -opus_val32 celt_rcp(opus_val32 x); - -#define celt_div(a,b) MULT32_32_Q31((opus_val32)(a),celt_rcp(b)) - -opus_val32 frac_div32(opus_val32 a, opus_val32 b); - -#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 (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 */ -#endif /* MATHOPS_H */ diff --git a/drivers/opus/celt/mdct.c b/drivers/opus/celt/mdct.c deleted file mode 100644 index 641a20e49a..0000000000 --- a/drivers/opus/celt/mdct.c +++ /dev/null @@ -1,341 +0,0 @@ -/* 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 -#include "opus/opus_config.h" -#endif - -#include "opus/celt/mdct.h" -#include "opus/celt/kiss_fft.h" -#include "opus/celt/_kiss_fft_guts.h" -#include <math.h> -#include "opus/celt/os_support.h" -#include "opus/celt/mathops.h" -#include "opus/celt/stack_alloc.h" - -#if defined(MIPSr1_ASM) -#include "opus/celt/mips/mdct_mipsr1.h" -#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) -#if 1 - 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(-32767,MIN32(32767,floor(.5+32768*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 opus_val16 *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; - opus_val16 scale; -#ifdef OPUS_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 - 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 opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1); - const opus_val16 * 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++ = MULT16_32_Q15(*wp2, xp1[N2]) + MULT16_32_Q15(*wp1,*xp2); - *yp++ = MULT16_32_Q15(*wp1, *xp1) - MULT16_32_Q15(*wp2, xp2[-N2]); - 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++ = -MULT16_32_Q15(*wp1, xp1[-N2]) + MULT16_32_Q15(*wp2, *xp2); - *yp++ = MULT16_32_Q15(*wp2, *xp1) + MULT16_32_Q15(*wp1, xp2[N2]); - xp1+=2; - xp2-=2; - wp1+=2; - wp2-=2; - } - } - /* Pre-rotation */ - { - kiss_fft_scalar * OPUS_RESTRICT yp = f; - const kiss_twiddle_scalar *t = &trig[0]; - 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); - yc.r = yr; - yc.i = yi; - yc.r = PSHR32(MULT16_32_Q16(scale, yc.r), scale_shift); - yc.i = PSHR32(MULT16_32_Q16(scale, yc.i), scale_shift); - f2[st->bitrev[i]] = yc; - } - } - - /* N/4 complex FFT, does not downscale anymore */ - opus_fft_impl(st, f2); - - /* 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; - yr = S_MUL(fp->i,t[N4+i]) - S_MUL(fp->r,t[i]); - yi = S_MUL(fp->r,t[N4+i]) + S_MUL(fp->i,t[i]); - *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 opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride, int arch) -{ - int i; - int N, N2, N4; - const kiss_twiddle_scalar *trig; - (void) arch; - - N = l->n; - trig = l->trig; - for (i=0;i<shift;i++) - { - N >>= 1; - trig += N; - } - N2 = N>>1; - N4 = N>>2; - - /* 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; - rev = *bitrev++; - yr = S_MUL(*xp2, t[i]) + S_MUL(*xp1, t[N4+i]); - yi = S_MUL(*xp1, t[i]) - S_MUL(*xp2, 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))); - - /* 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 = S_MUL(re,t0) + S_MUL(im,t1); - yi = S_MUL(re,t1) - S_MUL(im,t0); - /* 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 = S_MUL(re,t0) + S_MUL(im,t1); - yi = S_MUL(re,t1) - S_MUL(im,t0); - 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 opus_val16 * OPUS_RESTRICT wp1 = window; - const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1; - - for(i = 0; i < overlap/2; i++) - { - kiss_fft_scalar x1, x2; - x1 = *xp1; - x2 = *yp1; - *yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1); - *xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1); - wp1++; - wp2--; - } - } -} -#endif /* OVERRIDE_clt_mdct_backward */ diff --git a/drivers/opus/celt/mdct.h b/drivers/opus/celt/mdct.h deleted file mode 100644 index 2ec98a92e5..0000000000 --- a/drivers/opus/celt/mdct.h +++ /dev/null @@ -1,112 +0,0 @@ -/* 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/opus_defines.h" -#include "opus/celt/kiss_fft.h" -#include "opus/celt/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 "opus/celt/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 opus_val16 *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 opus_val16 * 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 opus_val16 *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 opus_val16 *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/drivers/opus/celt/mfrngcod.h b/drivers/opus/celt/mfrngcod.h deleted file mode 100644 index c24d98cde2..0000000000 --- a/drivers/opus/celt/mfrngcod.h +++ /dev/null @@ -1,48 +0,0 @@ -/* 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 "opus/celt/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/drivers/opus/celt/mips/celt_mipsr1.h b/drivers/opus/celt/mips/celt_mipsr1.h deleted file mode 100644 index 906848f1ec..0000000000 --- a/drivers/opus/celt/mips/celt_mipsr1.h +++ /dev/null @@ -1,148 +0,0 @@ -/* 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. -*/ - -#ifndef __CELT_MIPSR1_H__ -#define __CELT_MIPSR1_H__ -#include "opus/opus_config.h" - -#define CELT_C - -#include "opus/celt/os_support.h" -#include "opus/celt/mdct.h" -#include <math.h> -#include "opus/celt/celt.h" -#include "opus/celt/pitch.h" -#include "opus/celt/bands.h" -#include "opus/celt/modes.h" -#include "opus/celt/entcode.h" -#include "opus/celt/quant_bands.h" -#include "opus/celt/rate.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/mathops.h" -#include "opus/celt/float_cast.h" -#include <stdarg.h> -#include "opus/celt/celt_lpc.h" -#include "opus/celt/vq.h" - -#define 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 opus_val16 *window, int overlap, int arch) -{ - int i; - opus_val32 x0, x1, x2, x3, x4; - - (void)arch; - - /* printf ("%d %d %f %f\n", T0, T1, g0, g1); */ - opus_val16 g00, g01, g02, g10, g11, g12; - 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)}}; - - 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; - } - - g00 = MULT16_16_P15(g0, gains[tapset0][0]); - g01 = MULT16_16_P15(g0, gains[tapset0][1]); - g02 = MULT16_16_P15(g0, gains[tapset0][2]); - g10 = MULT16_16_P15(g1, gains[tapset1][0]); - g11 = MULT16_16_P15(g1, gains[tapset1][1]); - g12 = MULT16_16_P15(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++) - { - opus_val16 f; - opus_val32 res; - f = MULT16_16_Q15(window[i],window[i]); - x0= x[i-T1+2]; - - asm volatile("MULT $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15((Q15ONE-f),g00)), "r" ((int)x[i-T0])); - - asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15((Q15ONE-f),g01)), "r" ((int)ADD32(x[i-T0-1],x[i-T0+1]))); - asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15((Q15ONE-f),g02)), "r" ((int)ADD32(x[i-T0-2],x[i-T0+2]))); - asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15(f,g10)), "r" ((int)x2)); - asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15(f,g11)), "r" ((int)ADD32(x3,x1))); - asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15(f,g12)), "r" ((int)ADD32(x4,x0))); - - asm volatile("EXTR.W %0,$ac1, %1" : "=r" (res): "i" (15)); - - y[i] = x[i] + res; - - x4=x3; - x3=x2; - x2=x1; - x1=x0; - } - - x4 = x[i-T1-2]; - x3 = x[i-T1-1]; - x2 = x[i-T1]; - x1 = x[i-T1+1]; - - 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; - } - - for (i=overlap;i<N;i++) - { - opus_val32 res; - x0=x[i-T1+2]; - - asm volatile("MULT $ac1, %0, %1" : : "r" ((int)g10), "r" ((int)x2)); - - asm volatile("MADD $ac1, %0, %1" : : "r" ((int)g11), "r" ((int)ADD32(x3,x1))); - asm volatile("MADD $ac1, %0, %1" : : "r" ((int)g12), "r" ((int)ADD32(x4,x0))); - asm volatile("EXTR.W %0,$ac1, %1" : "=r" (res): "i" (15)); - y[i] = x[i] + res; - x4=x3; - x3=x2; - x2=x1; - x1=x0; - } -} - -#endif /* __CELT_MIPSR1_H__ */ diff --git a/drivers/opus/celt/mips/kiss_fft_mipsr1.h b/drivers/opus/celt/mips/kiss_fft_mipsr1.h deleted file mode 100644 index 09dc9af464..0000000000 --- a/drivers/opus/celt/mips/kiss_fft_mipsr1.h +++ /dev/null @@ -1,167 +0,0 @@ -/*Copyright (c) 2013, Xiph.Org Foundation and contributors. - - 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_MIPSR1_H -#define KISS_FFT_MIPSR1_H - -#if !defined(KISS_FFT_GUTS_H) -#error "This file should only be included from _kiss_fft_guts.h" -#endif - -#ifdef OPUS_FIXED_POINT - -#define S_MUL_ADD(a, b, c, d) (S_MUL(a,b)+S_MUL(c,d)) -#define S_MUL_SUB(a, b, c, d) (S_MUL(a,b)-S_MUL(c,d)) - -#undef S_MUL_ADD -static inline int S_MUL_ADD(int a, int b, int c, int d) { - int m; - asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a), "r" ((int)b)); - asm volatile("madd $ac1, %0, %1" : : "r" ((int)c), "r" ((int)d)); - asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m): "i" (15)); - return m; -} - -#undef S_MUL_SUB -static inline int S_MUL_SUB(int a, int b, int c, int d) { - int m; - asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a), "r" ((int)b)); - asm volatile("msub $ac1, %0, %1" : : "r" ((int)c), "r" ((int)d)); - asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m): "i" (15)); - return m; -} - -#undef C_MUL -# define C_MUL(m,a,b) (m=C_MUL_fun(a,b)) -static inline kiss_fft_cpx C_MUL_fun(kiss_fft_cpx a, kiss_twiddle_cpx b) { - kiss_fft_cpx m; - - asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a.r), "r" ((int)b.r)); - asm volatile("msub $ac1, %0, %1" : : "r" ((int)a.i), "r" ((int)b.i)); - asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m.r): "i" (15)); - asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a.r), "r" ((int)b.i)); - asm volatile("madd $ac1, %0, %1" : : "r" ((int)a.i), "r" ((int)b.r)); - asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m.i): "i" (15)); - - return m; -} -#undef C_MULC -# define C_MULC(m,a,b) (m=C_MULC_fun(a,b)) -static inline kiss_fft_cpx C_MULC_fun(kiss_fft_cpx a, kiss_twiddle_cpx b) { - kiss_fft_cpx m; - - asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a.r), "r" ((int)b.r)); - asm volatile("madd $ac1, %0, %1" : : "r" ((int)a.i), "r" ((int)b.i)); - asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m.r): "i" (15)); - asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a.i), "r" ((int)b.r)); - asm volatile("msub $ac1, %0, %1" : : "r" ((int)a.r), "r" ((int)b.i)); - asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m.i): "i" (15)); - - return m; -} - -#endif /* FIXED_POINT */ - -#define 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 OPUS_FIXED_POINT - ya.r = 10126; - ya.i = -31164; - yb.r = -26510; - yb.i = -19261; -#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 += scratch[7].r + scratch[8].r; - Fout0->i += scratch[7].i + scratch[8].i; - scratch[5].r = scratch[0].r + S_MUL_ADD(scratch[7].r,ya.r,scratch[8].r,yb.r); - scratch[5].i = scratch[0].i + S_MUL_ADD(scratch[7].i,ya.r,scratch[8].i,yb.r); - - scratch[6].r = S_MUL_ADD(scratch[10].i,ya.i,scratch[9].i,yb.i); - scratch[6].i = -S_MUL_ADD(scratch[10].r,ya.i,scratch[9].r,yb.i); - - C_SUB(*Fout1,scratch[5],scratch[6]); - C_ADD(*Fout4,scratch[5],scratch[6]); - - scratch[11].r = scratch[0].r + S_MUL_ADD(scratch[7].r,yb.r,scratch[8].r,ya.r); - scratch[11].i = scratch[0].i + S_MUL_ADD(scratch[7].i,yb.r,scratch[8].i,ya.r); - - scratch[12].r = S_MUL_SUB(scratch[9].i,ya.i,scratch[10].i,yb.i); - scratch[12].i = S_MUL_SUB(scratch[10].r,yb.i,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 /* KISS_FFT_MIPSR1_H */ diff --git a/drivers/opus/celt/mips/mdct_mipsr1.h b/drivers/opus/celt/mips/mdct_mipsr1.h deleted file mode 100644 index 0bb8b5a056..0000000000 --- a/drivers/opus/celt/mips/mdct_mipsr1.h +++ /dev/null @@ -1,286 +0,0 @@ -/* 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_MIPSR1_H__ -#define __MDCT_MIPSR1_H__ - -#ifndef SKIP_CONFIG_H -#include "opus/opus_config.h" -#endif - -#include "opus/celt/mdct.h" -#include "opus/celt/kiss_fft.h" -#include "opus/celt/_kiss_fft_guts.h" -#include <math.h> -#include "opus/celt/os_support.h" -#include "opus/celt/mathops.h" -#include "opus/celt/stack_alloc.h" - -/* Forward MDCT trashes the input array */ -#define OVERRIDE_clt_mdct_forward -void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out, - const opus_val16 *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; - opus_val16 scale; -#ifdef OPUS_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 - - (void)arch; - - SAVE_STACK; - 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 opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1); - const opus_val16 * 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_ADD(*wp2, xp1[N2],*wp1,*xp2); - *yp++ = S_MUL_SUB(*wp1, *xp1,*wp2, xp2[-N2]); - 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_SUB(*wp2, *xp2, *wp1, xp1[-N2]); - *yp++ = S_MUL_ADD(*wp2, *xp1, *wp1, xp2[N2]); - xp1+=2; - xp2-=2; - wp1+=2; - wp2-=2; - } - } - /* Pre-rotation */ - { - kiss_fft_scalar * OPUS_RESTRICT yp = f; - const kiss_twiddle_scalar *t = &trig[0]; - 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_SUB(re,t0,im,t1); - yi = S_MUL_ADD(im,t0,re,t1); - - yc.r = yr; - yc.i = yi; - yc.r = PSHR32(MULT16_32_Q16(scale, yc.r), scale_shift); - yc.i = PSHR32(MULT16_32_Q16(scale, yc.i), scale_shift); - f2[st->bitrev[i]] = yc; - } - } - - /* N/4 complex FFT, does not downscale anymore */ - opus_fft_impl(st, f2); - - /* 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; - yr = S_MUL_SUB(fp->i,t[N4+i] , fp->r,t[i]); - yi = S_MUL_ADD(fp->r,t[N4+i] ,fp->i,t[i]); - *yp1 = yr; - *yp2 = yi; - fp++; - yp1 += 2*stride; - yp2 -= 2*stride; - } - } - RESTORE_STACK; -} - -#define OVERRIDE_clt_mdct_backward -void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out, - const opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride, int arch) -{ - int i; - int N, N2, N4; - const kiss_twiddle_scalar *trig; - - (void)arch; - - N = l->n; - trig = l->trig; - for (i=0;i<shift;i++) - { - N >>= 1; - trig += N; - } - N2 = N>>1; - N4 = N>>2; - - /* 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; - rev = *bitrev++; - yr = S_MUL_ADD(*xp2, t[i] , *xp1, t[N4+i]); - yi = S_MUL_SUB(*xp1, t[i] , *xp2, 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))); - - /* Post-rotate and de-shuffle from both ends of the buffer at once to make - it in-place. */ - { - kiss_fft_scalar * OPUS_RESTRICT yp0 = out+(overlap>>1); - kiss_fft_scalar * OPUS_RESTRICT 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 = S_MUL_ADD(re,t0 , im,t1); - yi = S_MUL_SUB(re,t1 , im,t0); - /* 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 = S_MUL_ADD(re,t0,im,t1); - yi = S_MUL_SUB(re,t1,im,t0); - 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 opus_val16 * OPUS_RESTRICT wp1 = window; - const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1; - - for(i = 0; i < overlap/2; i++) - { - kiss_fft_scalar x1, x2; - x1 = *xp1; - x2 = *yp1; - *yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1); - *xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1); - wp1++; - wp2--; - } - } -} -#endif /* __MDCT_MIPSR1_H__ */ diff --git a/drivers/opus/celt/mips/vq_mipsr1.h b/drivers/opus/celt/mips/vq_mipsr1.h deleted file mode 100644 index c68159972f..0000000000 --- a/drivers/opus/celt/mips/vq_mipsr1.h +++ /dev/null @@ -1,122 +0,0 @@ -/* 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 __VQ_MIPSR1_H__ -#define __VQ_MIPSR1_H__ -#include "opus/opus_config.h" - -#include "opus/celt/mathops.h" -#include "opus/celt/arch.h" - -static unsigned extract_collapse_mask(int *iy, int N, int B); -static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X, int N, opus_val32 Ryy, opus_val16 gain); -static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread); -static void renormalise_vector_mips(celt_norm *X, int N, opus_val16 gain, int arch); - -#define 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); - 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)); - } -} - -#define OVERRIDE_renormalise_vector - -#define renormalise_vector(X, N, gain, arch) \ - (renormalise_vector_mips(X, N, gain, arch)) - -void renormalise_vector_mips(celt_norm *X, int N, opus_val16 gain, int arch) -{ - int i; -#ifdef OPUS_FIXED_POINT - int k; -#endif - opus_val32 E = EPSILON; - opus_val16 g; - opus_val32 t; - celt_norm *xptr = X; - int X0, X1; - - (void)arch; - - asm volatile("mult $ac1, $0, $0"); - asm volatile("MTLO %0, $ac1" : :"r" (E)); - /*if(N %4) - printf("error");*/ - for (i=0;i<N-2;i+=2) - { - X0 = (int)*xptr++; - asm volatile("MADD $ac1, %0, %1" : : "r" (X0), "r" (X0)); - - X1 = (int)*xptr++; - asm volatile("MADD $ac1, %0, %1" : : "r" (X1), "r" (X1)); - } - - for (;i<N;i++) - { - X0 = (int)*xptr++; - asm volatile("MADD $ac1, %0, %1" : : "r" (X0), "r" (X0)); - } - - asm volatile("MFLO %0, $ac1" : "=r" (E)); -#ifdef OPUS_FIXED_POINT - k = celt_ilog2(E)>>1; -#endif - t = VSHR32(E, 2*(k-7)); - g = MULT16_16_P15(celt_rsqrt_norm(t),gain); - - xptr = X; - for (i=0;i<N;i++) - { - *xptr = EXTRACT16(PSHR32(MULT16_16(g, *xptr), k+1)); - xptr++; - } - /*return celt_sqrt(E);*/ -} - -#endif /* __VQ_MIPSR1_H__ */ diff --git a/drivers/opus/celt/modes.c b/drivers/opus/celt/modes.c deleted file mode 100644 index d628f1468b..0000000000 --- a/drivers/opus/celt/modes.c +++ /dev/null @@ -1,439 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/celt/celt.h" -#include "opus/celt/modes.h" -#include "opus/celt/rate.h" -#include "opus/celt/os_support.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/quant_bands.h" -#include "opus/celt/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 OPUS_FIXED_POINT - #include "opus/celt/static_modes_fixed.h" - #else - #include "opus/celt/static_modes_float.h" - #endif -#endif /* CUSTOM_MODES_ONLY */ - -#ifndef M_PI -#define M_PI 3.141592653 -#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) - 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; - opus_val16 *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; - } - if (frame_size < 40 || frame_size > 1024 || frame_size%2!=0) - { - 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. */ - 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 = (opus_val16*)opus_alloc(mode->overlap*sizeof(opus_val16)); - if (window==NULL) - goto failure; - -#ifndef OPUS_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 - 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 - 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); - - 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 */ -} - -#ifdef CUSTOM_MODES -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 */ - opus_free((opus_int16*)mode->eBands); - opus_free((opus_int16*)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); -} -#endif diff --git a/drivers/opus/celt/modes.h b/drivers/opus/celt/modes.h deleted file mode 100644 index a5f1c30ac9..0000000000 --- a/drivers/opus/celt/modes.h +++ /dev/null @@ -1,75 +0,0 @@ -/* 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/opus_types.h" -#include "opus/celt/celt.h" -#include "opus/celt/arch.h" -#include "opus/celt/mdct.h" -#include "opus/celt/entenc.h" -#include "opus/celt/entdec.h" - -#define MAX_PERIOD 1024 - -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 opus_val16 *window; - mdct_lookup mdct; - PulseCache cache; -}; - - -#endif diff --git a/drivers/opus/celt/opus_custom_demo.c b/drivers/opus/celt/opus_custom_demo.c deleted file mode 100644 index 956bec4e45..0000000000 --- a/drivers/opus/celt/opus_custom_demo.c +++ /dev/null @@ -1,207 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/opus_custom.h" -#include "opus/celt/arch.h" -#include <stdio.h> -#include <stdlib.h> -#include <math.h> -#include <string.h> - -#define MAX_PACKET 1275 - -int main(int argc, char *argv[]) -{ - int err; - char *inFile, *outFile; - FILE *fin, *fout; - OpusCustomMode *mode=NULL; - OpusCustomEncoder *enc; - OpusCustomDecoder *dec; - int len; - opus_int32 frame_size, channels, rate; - int bytes_per_packet; - unsigned char data[MAX_PACKET]; - int complexity; -#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH) - int i; - double rmsd = 0; -#endif - int count = 0; - opus_int32 skip; - opus_int16 *in, *out; - if (argc != 9 && argc != 8 && argc != 7) - { - fprintf (stderr, "Usage: test_opus_custom <rate> <channels> <frame size> " - " <bytes per packet> [<complexity> [packet loss rate]] " - "<input> <output>\n"); - return 1; - } - - rate = (opus_int32)atol(argv[1]); - channels = atoi(argv[2]); - frame_size = atoi(argv[3]); - mode = opus_custom_mode_create(rate, frame_size, NULL); - if (mode == NULL) - { - fprintf(stderr, "failed to create a mode\n"); - return 1; - } - - bytes_per_packet = atoi(argv[4]); - if (bytes_per_packet < 0 || bytes_per_packet > MAX_PACKET) - { - fprintf (stderr, "bytes per packet must be between 0 and %d\n", - MAX_PACKET); - return 1; - } - - inFile = argv[argc-2]; - fin = fopen(inFile, "rb"); - if (!fin) - { - fprintf (stderr, "Could not open input file %s\n", argv[argc-2]); - return 1; - } - outFile = argv[argc-1]; - fout = fopen(outFile, "wb+"); - if (!fout) - { - fprintf (stderr, "Could not open output file %s\n", argv[argc-1]); - fclose(fin); - return 1; - } - - enc = opus_custom_encoder_create(mode, channels, &err); - if (err != 0) - { - fprintf(stderr, "Failed to create the encoder: %s\n", opus_strerror(err)); - fclose(fin); - fclose(fout); - return 1; - } - dec = opus_custom_decoder_create(mode, channels, &err); - if (err != 0) - { - fprintf(stderr, "Failed to create the decoder: %s\n", opus_strerror(err)); - fclose(fin); - fclose(fout); - return 1; - } - opus_custom_decoder_ctl(dec, OPUS_GET_LOOKAHEAD(&skip)); - - if (argc>7) - { - complexity=atoi(argv[5]); - opus_custom_encoder_ctl(enc,OPUS_SET_COMPLEXITY(complexity)); - } - - in = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16)); - out = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16)); - - while (!feof(fin)) - { - int ret; - err = fread(in, sizeof(short), frame_size*channels, fin); - if (feof(fin)) - break; - len = opus_custom_encode(enc, in, frame_size, data, bytes_per_packet); - if (len <= 0) - fprintf (stderr, "opus_custom_encode() failed: %s\n", opus_strerror(len)); - - /* This is for simulating bit errors */ -#if 0 - int errors = 0; - int eid = 0; - /* This simulates random bit error */ - for (i=0;i<len*8;i++) - { - if (rand()%atoi(argv[8])==0) - { - if (i<64) - { - errors++; - eid = i; - } - data[i/8] ^= 1<<(7-(i%8)); - } - } - if (errors == 1) - data[eid/8] ^= 1<<(7-(eid%8)); - else if (errors%2 == 1) - data[rand()%8] ^= 1<<rand()%8; -#endif - -#if 1 /* Set to zero to use the encoder's output instead */ - /* This is to simulate packet loss */ - if (argc==9 && rand()%1000<atoi(argv[argc-3])) - /*if (errors && (errors%2==0))*/ - ret = opus_custom_decode(dec, NULL, len, out, frame_size); - else - ret = opus_custom_decode(dec, data, len, out, frame_size); - if (ret < 0) - fprintf(stderr, "opus_custom_decode() failed: %s\n", opus_strerror(ret)); -#else - for (i=0;i<ret*channels;i++) - out[i] = in[i]; -#endif -#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH) - for (i=0;i<ret*channels;i++) - { - rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]); - /*out[i] -= in[i];*/ - } -#endif - count++; - fwrite(out+skip*channels, sizeof(short), (ret-skip)*channels, fout); - skip = 0; - } - PRINT_MIPS(stderr); - - opus_custom_encoder_destroy(enc); - opus_custom_decoder_destroy(dec); - fclose(fin); - fclose(fout); - opus_custom_mode_destroy(mode); - free(in); - free(out); -#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH) - if (rmsd > 0) - { - rmsd = sqrt(rmsd/(1.0*frame_size*channels*count)); - fprintf (stderr, "Error: encoder doesn't match decoder\n"); - fprintf (stderr, "RMS mismatch is %f\n", rmsd); - return 1; - } else { - fprintf (stderr, "Encoder matches decoder!!\n"); - } -#endif - return 0; -} - diff --git a/drivers/opus/celt/os_support.h b/drivers/opus/celt/os_support.h deleted file mode 100644 index 5e36b3ae56..0000000000 --- a/drivers/opus/celt/os_support.h +++ /dev/null @@ -1,92 +0,0 @@ -/* 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/opus_types.h" -#include "opus/opus_defines.h" - -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - -/** Opus wrapper for malloc(). To do your own dynamic allocation, all you need to do is replace this function and opus_free */ -#ifndef OVERRIDE_OPUS_ALLOC -static OPUS_INLINE void *opus_alloc (size_t size) -{ - return malloc(size); -} -#endif - -/** Same as celt_alloc(), except that the area is only needed inside a CELT call (might cause problem with wideband though) */ -#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, all you need to do is replace this function and opus_alloc */ -#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/drivers/opus/celt/pitch.c b/drivers/opus/celt/pitch.c deleted file mode 100644 index 1bcbabe943..0000000000 --- a/drivers/opus/celt/pitch.c +++ /dev/null @@ -1,541 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/celt/pitch.h" -#include "opus/celt/os_support.h" -#include "opus/celt/modes.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/mathops.h" -#include "opus/celt/celt_lpc.h" - -static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len, - int max_pitch, int *best_pitch -#ifdef OPUS_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 OPUS_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 OPUS_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(const opus_val16 *x, - const opus_val16 *num, - opus_val16 *y, - int N, - opus_val16 *mem) -{ - 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=mem[0]; - mem1=mem[1]; - mem2=mem[2]; - mem3=mem[3]; - mem4=mem[4]; - 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]; - y[i] = ROUND16(sum, SIG_SHIFT); - } - mem[0]=mem0; - mem[1]=mem1; - mem[2]=mem2; - mem[3]=mem3; - mem[4]=mem4; -} - - -void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp, - int len, int C, int arch) -{ - int i; - opus_val32 ac[5]; - opus_val16 tmp=Q15ONE; - opus_val16 lpc[4], mem[5]={0,0,0,0,0}; - opus_val16 lpc2[5]; - opus_val16 c1 = QCONST16(.8f,15); -#ifdef OPUS_FIXED_POINT - int shift; - opus_val32 maxabs = celt_maxabs32(x[0], len); - if (C==2) - { - opus_val32 maxabs_1 = celt_maxabs32(x[1], len); - maxabs = MAX32(maxabs, maxabs_1); - } - if (maxabs<1) - maxabs=1; - shift = celt_ilog2(maxabs)-10; - if (shift<0) - shift=0; - if (C==2) - shift++; -#endif - for (i=1;i<len>>1;i++) - x_lp[i] = SHR32(HALF32(HALF32(x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]), shift); - x_lp[0] = SHR32(HALF32(HALF32(x[0][1])+x[0][0]), shift); - if (C==2) - { - for (i=1;i<len>>1;i++) - x_lp[i] += SHR32(HALF32(HALF32(x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i]), shift); - x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), shift); - } - - _celt_autocorr(x_lp, ac, NULL, 0, - 4, len>>1, arch); - - /* Noise floor -40 dB */ -#ifdef OPUS_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 OPUS_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, x_lp, len>>1, mem); -} - -/* Pure C implementation. */ -#ifdef OPUS_FIXED_POINT -opus_val32 -#else -void -#endif -#if defined(OVERRIDE_PITCH_XCORR) -celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y, - opus_val32 *xcorr, int len, int max_pitch) -#else -celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y, - opus_val32 *xcorr, int len, int max_pitch, int arch) -#endif -{ - -#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 OPUS_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 OPUS_FIXED_POINT - maxcorr = MAX32(maxcorr, sum); -#endif - } -#ifdef OPUS_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 OPUS_FIXED_POINT - opus_val32 maxcorr=1; -#endif - celt_assert(max_pitch>0); - celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0); - for (i=0;i<max_pitch-3;i+=4) - { - opus_val32 sum[4]={0,0,0,0}; -#if defined(OVERRIDE_PITCH_XCORR) - xcorr_kernel_c(_x, _y+i, sum, len); -#else - xcorr_kernel(_x, _y+i, sum, len, arch); -#endif - xcorr[i]=sum[0]; - xcorr[i+1]=sum[1]; - xcorr[i+2]=sum[2]; - xcorr[i+3]=sum[3]; -#ifdef OPUS_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; -#if defined(OVERRIDE_PITCH_XCORR) - sum = celt_inner_prod_c(_x, _y+i, len); -#else - sum = celt_inner_prod(_x, _y+i, len, arch); -#endif - xcorr[i] = sum; -#ifdef OPUS_FIXED_POINT - maxcorr = MAX32(maxcorr, sum); -#endif - } -#ifdef OPUS_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 OPUS_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 OPUS_FIXED_POINT - xmax = celt_maxabs16(x_lp4, len>>2); - ymax = celt_maxabs16(y_lp4, lag>>2); - shift = celt_ilog2(MAX32(1, MAX32(xmax, ymax)))-11; - 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 OPUS_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 OPUS_FIXED_POINT - , 0, maxcorr -#endif - ); - - /* Finer search with 2x decimation */ -#ifdef OPUS_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 OPUS_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_c(x_lp, y+i, len>>1); -#endif - xcorr[i] = MAX32(-1, sum); -#ifdef OPUS_FIXED_POINT - maxcorr = MAX32(maxcorr, sum); -#endif - } - find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch -#ifdef OPUS_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; -} - -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; -#ifdef OPUS_FIXED_POINT - { - opus_val32 x2y2; - int sh, t; - x2y2 = 1+HALF32(MULT32_32_Q31(xx,yy)); - sh = celt_ilog2(x2y2)>>1; - t = VSHR32(x2y2, 2*(sh-7)); - g = g0 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1); - } -#else - g = g0 = xy/celt_sqrt(1+xx*yy); -#endif - /* 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 += xy2; - yy = yy_lookup[T1] + yy_lookup[T1b]; -#ifdef OPUS_FIXED_POINT - { - opus_val32 x2y2; - int sh, t; - x2y2 = 1+MULT32_32_Q31(xx,yy); - sh = celt_ilog2(x2y2)>>1; - t = VSHR32(x2y2, 2*(sh-7)); - g1 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1); - } -#else - g1 = xy/celt_sqrt(1+2.f*xx*1.f*yy); -#endif - if (abs(T1-prev_period)<=1) - cont = prev_gain; - else if (abs(T1-prev_period)<=2 && 5*k*k < T0) - cont = HALF32(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/drivers/opus/celt/pitch.h b/drivers/opus/celt/pitch.h deleted file mode 100644 index ecae7667b8..0000000000 --- a/drivers/opus/celt/pitch.h +++ /dev/null @@ -1,220 +0,0 @@ -/* 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 "opus/celt/modes.h" -#include "opus/celt/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 "opus/celt/x86/pitch_sse.h" -#endif - -#if defined(MIPSr1_ASM) -#include "opus/celt/mips/pitch_mipsr1.h" -#endif - -#if ((defined(OPUS_ARM_ASM) && defined(FIXED_POINT)) \ - || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)) -# include "opus/celt/arm/pitch_arm.h" -#endif - -void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp, - int len, int C, 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 OPUS_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); - -#if !defined(OVERRIDE_PITCH_XCORR) -/*Is run-time CPU detection enabled on this platform?*/ -# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_ASM) \ - || (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) \ - && !defined(OPUS_ARM_PRESUME_NEON_INTR))) -extern -# if defined(FIXED_POINT) -opus_val32 -# else -void -# endif -(*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *, - const opus_val16 *, opus_val32 *, int, int); - -# define OVERRIDE_PITCH_XCORR -# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \ - ((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \ - xcorr, len, max_pitch)) -# else - -#ifdef OPUS_FIXED_POINT -opus_val32 -#else -void -#endif -celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y, - opus_val32 *xcorr, int len, int max_pitch, int arch); - -# endif -#endif - -#endif diff --git a/drivers/opus/celt/quant_bands.c b/drivers/opus/celt/quant_bands.c deleted file mode 100644 index b38bfa8b8e..0000000000 --- a/drivers/opus/celt/quant_bands.c +++ /dev/null @@ -1,553 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/celt/quant_bands.h" -#include "opus/celt/laplace.h" -#include <math.h> -#include "opus/celt/os_support.h" -#include "opus/celt/arch.h" -#include "opus/celt/mathops.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/rate.h" - -#ifdef OPUS_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 OPUS_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 opus_val16 *eBands, opus_val16 *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++) - { - opus_val16 d = SUB16(SHR16(eBands[i+c*len], 3), SHR16(oldEBands[i+c*len], 3)); - dist = MAC16_16(dist, d,d); - } - } while (++c<C); - return MIN32(200,SHR32(dist,2*DB_SHIFT-6)); -} - -static int quant_coarse_energy_impl(const CELTMode *m, int start, int end, - const opus_val16 *eBands, opus_val16 *oldEBands, - opus_int32 budget, opus_int32 tell, - const unsigned char *prob_model, opus_val16 *error, ec_enc *enc, - int C, int LM, int intra, opus_val16 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; - opus_val16 x; - opus_val32 f, tmp; - opus_val16 oldE; - opus_val16 decay_bound; - x = eBands[i+c*m->nbEBands]; - oldE = MAX16(-QCONST16(9.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]); -#ifdef OPUS_FIXED_POINT - f = SHL32(EXTEND32(x),7) - PSHR32(MULT16_16(coef,oldE), 8) - prev[c]; - /* Rounding to nearest integer here is really important! */ - qi = (f+QCONST32(.5f,DB_SHIFT+7))>>(DB_SHIFT+7); - decay_bound = EXTRACT16(MAX32(-QCONST16(28.f,DB_SHIFT), - 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 = MAX16(-QCONST16(28.f,DB_SHIFT), 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)SHR16(SUB16(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] = PSHR32(f,7) - SHL16(qi,DB_SHIFT); - badness += abs(qi0-qi); - q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT); - - tmp = PSHR32(MULT16_16(coef,oldE),8) + prev[c] + SHL32(q,7); -#ifdef OPUS_FIXED_POINT - tmp = MAX32(-QCONST32(28.f, DB_SHIFT+7), tmp); -#endif - oldEBands[i+c*m->nbEBands] = PSHR32(tmp, 7); - prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8)); - } while (++c < C); - } - return lfe ? 0 : badness; -} - -void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd, - const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget, - opus_val16 *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; - opus_val16 max_decay; - VARDECL(opus_val16, oldEBands_intra); - VARDECL(opus_val16, 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 = QCONST16(16.f,DB_SHIFT); - if (end-start>10) - { -#ifdef OPUS_FIXED_POINT - max_decay = MIN32(max_decay, SHL32(EXTEND32(nbAvailableBytes),DB_SHIFT-3)); -#else - max_decay = MIN32(max_decay, .125f*nbAvailableBytes); -#endif - } - if (lfe) - max_decay = QCONST16(3.f,DB_SHIFT); - enc_start_state = *enc; - - ALLOC(oldEBands_intra, C*m->nbEBands, opus_val16); - ALLOC(error_intra, C*m->nbEBands, opus_val16); - 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, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, ec_enc *enc, int C) -{ - int i, c; - - /* Encode finer resolution */ - for (i=start;i<end;i++) - { - opus_int16 frac = 1<<fine_quant[i]; - if (fine_quant[i] <= 0) - continue; - c=0; - do { - int q2; - opus_val16 offset; -#ifdef OPUS_FIXED_POINT - /* Has to be without rounding */ - q2 = (error[i+c*m->nbEBands]+QCONST16(.5f,DB_SHIFT))>>(DB_SHIFT-fine_quant[i]); -#else - q2 = (int)floor((error[i+c*m->nbEBands]+.5f)*frac); -#endif - if (q2 > frac-1) - q2 = frac-1; - if (q2<0) - q2 = 0; - ec_enc_bits(enc, q2, fine_quant[i]); -#ifdef OPUS_FIXED_POINT - offset = SUB16(SHR32(SHL32(EXTEND32(q2),DB_SHIFT)+QCONST16(.5f,DB_SHIFT),fine_quant[i]),QCONST16(.5f,DB_SHIFT)); -#else - offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f; -#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, opus_val16 *oldEBands, opus_val16 *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; - opus_val16 offset; - q2 = error[i+c*m->nbEBands]<0 ? 0 : 1; - ec_enc_bits(enc, q2, 1); -#ifdef OPUS_FIXED_POINT - offset = SHR16(SHL16(q2,DB_SHIFT)-QCONST16(.5f,DB_SHIFT),fine_quant[i]+1); -#else - offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384); -#endif - oldEBands[i+c*m->nbEBands] += offset; - bits_left--; - } while (++c < C); - } - } -} - -void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM) -{ - const unsigned char *prob_model = e_prob_model[LM][intra]; - int i, c; - opus_val32 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_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] = MAX16(-QCONST16(9.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]); - tmp = PSHR32(MULT16_16(coef,oldEBands[i+c*m->nbEBands]),8) + prev[c] + SHL32(q,7); -#ifdef OPUS_FIXED_POINT - tmp = MAX32(-QCONST32(28.f, DB_SHIFT+7), tmp); -#endif - oldEBands[i+c*m->nbEBands] = PSHR32(tmp, 7); - prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8)); - } while (++c < C); - } -} - -void unquant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, ec_dec *dec, int C) -{ - int i, c; - /* Decode finer resolution */ - for (i=start;i<end;i++) - { - if (fine_quant[i] <= 0) - continue; - c=0; - do { - int q2; - opus_val16 offset; - q2 = ec_dec_bits(dec, fine_quant[i]); -#ifdef OPUS_FIXED_POINT - offset = SUB16(SHR32(SHL32(EXTEND32(q2),DB_SHIFT)+QCONST16(.5f,DB_SHIFT),fine_quant[i]),QCONST16(.5f,DB_SHIFT)); -#else - offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f; -#endif - oldEBands[i+c*m->nbEBands] += offset; - } while (++c < C); - } -} - -void unquant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *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; - opus_val16 offset; - q2 = ec_dec_bits(dec, 1); -#ifdef OPUS_FIXED_POINT - offset = SHR16(SHL16(q2,DB_SHIFT)-QCONST16(.5f,DB_SHIFT),fine_quant[i]+1); -#else - offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384); -#endif - oldEBands[i+c*m->nbEBands] += offset; - bits_left--; - } while (++c < C); - } - } -} - -void amp2Log2(const CELTMode *m, int effEnd, int end, - celt_ener *bandE, opus_val16 *bandLogE, int C) -{ - int c, i; - c=0; - do { - for (i=0;i<effEnd;i++) - bandLogE[i+c*m->nbEBands] = - celt_log2(SHL32(bandE[i+c*m->nbEBands],2)) - - SHL16((opus_val16)eMeans[i],6); - for (i=effEnd;i<end;i++) - bandLogE[c*m->nbEBands+i] = -QCONST16(14.f,DB_SHIFT); - } while (++c < C); -} diff --git a/drivers/opus/celt/quant_bands.h b/drivers/opus/celt/quant_bands.h deleted file mode 100644 index 31d4b94e41..0000000000 --- a/drivers/opus/celt/quant_bands.h +++ /dev/null @@ -1,66 +0,0 @@ -/* 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 "opus/celt/arch.h" -#include "opus/celt/modes.h" -#include "opus/celt/entenc.h" -#include "opus/celt/entdec.h" -#include "opus/celt/mathops.h" - -#ifdef OPUS_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, opus_val16 *bandLogE, int C); - -void log2Amp(const CELTMode *m, int start, int end, - celt_ener *eBands, const opus_val16 *oldEBands, int C); - -void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd, - const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget, - opus_val16 *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, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, ec_enc *enc, int C); - -void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *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, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM); - -void unquant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, ec_dec *dec, int C); - -void unquant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C); - -#endif /* QUANT_BANDS */ diff --git a/drivers/opus/celt/rate.c b/drivers/opus/celt/rate.c deleted file mode 100644 index e69fb3f030..0000000000 --- a/drivers/opus/celt/rate.c +++ /dev/null @@ -1,636 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include <math.h> -#include "opus/celt/modes.h" -#include "opus/celt/cwrs.h" -#include "opus/celt/arch.h" -#include "opus/celt/os_support.h" - -#include "opus/celt/entcode.h" -#include "opus/celt/rate.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 -}; - -#ifdef 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]+((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] + (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 cocentrated 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.*/ - /*Choose a threshold with some hysteresis to keep bands from - fluctuating in and out.*/ -#ifdef FUZZING - if ((rand()&0x1) == 0) -#else - if (codedBands<=start+2 || (band_bits > ((j<prev?7:9)*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 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; -} - diff --git a/drivers/opus/celt/rate.h b/drivers/opus/celt/rate.h deleted file mode 100644 index cf8085fccf..0000000000 --- a/drivers/opus/celt/rate.h +++ /dev/null @@ -1,101 +0,0 @@ -/* 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 "opus/celt/cwrs.h" -#include "opus/celt/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 compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stero, - 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); - -#endif diff --git a/drivers/opus/celt/stack_alloc.h b/drivers/opus/celt/stack_alloc.h deleted file mode 100644 index 7cd6c56ccf..0000000000 --- a/drivers/opus/celt/stack_alloc.h +++ /dev/null @@ -1,184 +0,0 @@ -/* 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/opus_types.h" -#include "opus/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 */ - -#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),sizeof(type)/sizeof(char)),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=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)) -#define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)/sizeof(char)),(stack)+=(size)*(sizeof(type)/sizeof(char)),(type*)((stack)-(size)*(sizeof(type)/sizeof(char)))) -#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=opus_alloc_scratch(GLOBAL_STACK_SIZE)) : global_stack); _saved_stack = global_stack; - -#endif /* ENABLE_VALGRIND */ - -#include "opus/celt/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/drivers/opus/celt/static_modes_fixed.h b/drivers/opus/celt/static_modes_fixed.h deleted file mode 100644 index 352642f507..0000000000 --- a/drivers/opus/celt/static_modes_fixed.h +++ /dev/null @@ -1,892 +0,0 @@ -/* The contents of this file was automatically generated by dump_modes.c - with arguments: 48000 960 - It contains static definitions for some pre-defined modes. */ -#include "opus/celt/modes.h" -#include "opus/celt/rate.h" - -#ifdef HAVE_ARM_NE10 -#define OVERRIDE_FFT 1 -#include "opus/celt/static_modes_fixed_arm_ne10.h" -#endif - -#ifndef DEF_WINDOW120 -#define DEF_WINDOW120 -static const opus_val16 window120[120] = { -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 - -#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 - -#ifndef FFT_TWIDDLES48000_960 -#define FFT_TWIDDLES48000_960 -static const kiss_twiddle_cpx fft_twiddles48000_960[480] = { -{32767, 0}, {32766, -429}, -{32757, -858}, {32743, -1287}, -{32724, -1715}, {32698, -2143}, -{32667, -2570}, {32631, -2998}, -{32588, -3425}, {32541, -3851}, -{32488, -4277}, {32429, -4701}, -{32364, -5125}, {32295, -5548}, -{32219, -5971}, {32138, -6393}, -{32051, -6813}, {31960, -7231}, -{31863, -7650}, {31760, -8067}, -{31652, -8481}, {31539, -8895}, -{31419, -9306}, {31294, -9716}, -{31165, -10126}, {31030, -10532}, -{30889, -10937}, {30743, -11340}, -{30592, -11741}, {30436, -12141}, -{30274, -12540}, {30107, -12935}, -{29936, -13328}, {29758, -13718}, -{29577, -14107}, {29390, -14493}, -{29197, -14875}, {29000, -15257}, -{28797, -15635}, {28590, -16010}, -{28379, -16384}, {28162, -16753}, -{27940, -17119}, {27714, -17484}, -{27482, -17845}, {27246, -18205}, -{27006, -18560}, {26760, -18911}, -{26510, -19260}, {26257, -19606}, -{25997, -19947}, {25734, -20286}, -{25466, -20621}, {25194, -20952}, -{24918, -21281}, {24637, -21605}, -{24353, -21926}, {24063, -22242}, -{23770, -22555}, {23473, -22865}, -{23171, -23171}, {22866, -23472}, -{22557, -23769}, {22244, -24063}, -{21927, -24352}, {21606, -24636}, -{21282, -24917}, {20954, -25194}, -{20622, -25465}, {20288, -25733}, -{19949, -25997}, {19607, -26255}, -{19261, -26509}, {18914, -26760}, -{18561, -27004}, {18205, -27246}, -{17846, -27481}, {17485, -27713}, -{17122, -27940}, {16755, -28162}, -{16385, -28378}, {16012, -28590}, -{15636, -28797}, {15258, -28999}, -{14878, -29197}, {14494, -29389}, -{14108, -29576}, {13720, -29757}, -{13329, -29934}, {12937, -30107}, -{12540, -30274}, {12142, -30435}, -{11744, -30592}, {11342, -30743}, -{10939, -30889}, {10534, -31030}, -{10127, -31164}, {9718, -31294}, -{9307, -31418}, {8895, -31537}, -{8482, -31652}, {8067, -31759}, -{7650, -31862}, {7233, -31960}, -{6815, -32051}, {6393, -32138}, -{5973, -32219}, {5549, -32294}, -{5127, -32364}, {4703, -32429}, -{4278, -32487}, {3852, -32541}, -{3426, -32588}, {2999, -32630}, -{2572, -32667}, {2144, -32698}, -{1716, -32724}, {1287, -32742}, -{860, -32757}, {430, -32766}, -{0, -32767}, {-429, -32766}, -{-858, -32757}, {-1287, -32743}, -{-1715, -32724}, {-2143, -32698}, -{-2570, -32667}, {-2998, -32631}, -{-3425, -32588}, {-3851, -32541}, -{-4277, -32488}, {-4701, -32429}, -{-5125, -32364}, {-5548, -32295}, -{-5971, -32219}, {-6393, -32138}, -{-6813, -32051}, {-7231, -31960}, -{-7650, -31863}, {-8067, -31760}, -{-8481, -31652}, {-8895, -31539}, -{-9306, -31419}, {-9716, -31294}, -{-10126, -31165}, {-10532, -31030}, -{-10937, -30889}, {-11340, -30743}, -{-11741, -30592}, {-12141, -30436}, -{-12540, -30274}, {-12935, -30107}, -{-13328, -29936}, {-13718, -29758}, -{-14107, -29577}, {-14493, -29390}, -{-14875, -29197}, {-15257, -29000}, -{-15635, -28797}, {-16010, -28590}, -{-16384, -28379}, {-16753, -28162}, -{-17119, -27940}, {-17484, -27714}, -{-17845, -27482}, {-18205, -27246}, -{-18560, -27006}, {-18911, -26760}, -{-19260, -26510}, {-19606, -26257}, -{-19947, -25997}, {-20286, -25734}, -{-20621, -25466}, {-20952, -25194}, -{-21281, -24918}, {-21605, -24637}, -{-21926, -24353}, {-22242, -24063}, -{-22555, -23770}, {-22865, -23473}, -{-23171, -23171}, {-23472, -22866}, -{-23769, -22557}, {-24063, -22244}, -{-24352, -21927}, {-24636, -21606}, -{-24917, -21282}, {-25194, -20954}, -{-25465, -20622}, {-25733, -20288}, -{-25997, -19949}, {-26255, -19607}, -{-26509, -19261}, {-26760, -18914}, -{-27004, -18561}, {-27246, -18205}, -{-27481, -17846}, {-27713, -17485}, -{-27940, -17122}, {-28162, -16755}, -{-28378, -16385}, {-28590, -16012}, -{-28797, -15636}, {-28999, -15258}, -{-29197, -14878}, {-29389, -14494}, -{-29576, -14108}, {-29757, -13720}, -{-29934, -13329}, {-30107, -12937}, -{-30274, -12540}, {-30435, -12142}, -{-30592, -11744}, {-30743, -11342}, -{-30889, -10939}, {-31030, -10534}, -{-31164, -10127}, {-31294, -9718}, -{-31418, -9307}, {-31537, -8895}, -{-31652, -8482}, {-31759, -8067}, -{-31862, -7650}, {-31960, -7233}, -{-32051, -6815}, {-32138, -6393}, -{-32219, -5973}, {-32294, -5549}, -{-32364, -5127}, {-32429, -4703}, -{-32487, -4278}, {-32541, -3852}, -{-32588, -3426}, {-32630, -2999}, -{-32667, -2572}, {-32698, -2144}, -{-32724, -1716}, {-32742, -1287}, -{-32757, -860}, {-32766, -430}, -{-32767, 0}, {-32766, 429}, -{-32757, 858}, {-32743, 1287}, -{-32724, 1715}, {-32698, 2143}, -{-32667, 2570}, {-32631, 2998}, -{-32588, 3425}, {-32541, 3851}, -{-32488, 4277}, {-32429, 4701}, -{-32364, 5125}, {-32295, 5548}, -{-32219, 5971}, {-32138, 6393}, -{-32051, 6813}, {-31960, 7231}, -{-31863, 7650}, {-31760, 8067}, -{-31652, 8481}, {-31539, 8895}, -{-31419, 9306}, {-31294, 9716}, -{-31165, 10126}, {-31030, 10532}, -{-30889, 10937}, {-30743, 11340}, -{-30592, 11741}, {-30436, 12141}, -{-30274, 12540}, {-30107, 12935}, -{-29936, 13328}, {-29758, 13718}, -{-29577, 14107}, {-29390, 14493}, -{-29197, 14875}, {-29000, 15257}, -{-28797, 15635}, {-28590, 16010}, -{-28379, 16384}, {-28162, 16753}, -{-27940, 17119}, {-27714, 17484}, -{-27482, 17845}, {-27246, 18205}, -{-27006, 18560}, {-26760, 18911}, -{-26510, 19260}, {-26257, 19606}, -{-25997, 19947}, {-25734, 20286}, -{-25466, 20621}, {-25194, 20952}, -{-24918, 21281}, {-24637, 21605}, -{-24353, 21926}, {-24063, 22242}, -{-23770, 22555}, {-23473, 22865}, -{-23171, 23171}, {-22866, 23472}, -{-22557, 23769}, {-22244, 24063}, -{-21927, 24352}, {-21606, 24636}, -{-21282, 24917}, {-20954, 25194}, -{-20622, 25465}, {-20288, 25733}, -{-19949, 25997}, {-19607, 26255}, -{-19261, 26509}, {-18914, 26760}, -{-18561, 27004}, {-18205, 27246}, -{-17846, 27481}, {-17485, 27713}, -{-17122, 27940}, {-16755, 28162}, -{-16385, 28378}, {-16012, 28590}, -{-15636, 28797}, {-15258, 28999}, -{-14878, 29197}, {-14494, 29389}, -{-14108, 29576}, {-13720, 29757}, -{-13329, 29934}, {-12937, 30107}, -{-12540, 30274}, {-12142, 30435}, -{-11744, 30592}, {-11342, 30743}, -{-10939, 30889}, {-10534, 31030}, -{-10127, 31164}, {-9718, 31294}, -{-9307, 31418}, {-8895, 31537}, -{-8482, 31652}, {-8067, 31759}, -{-7650, 31862}, {-7233, 31960}, -{-6815, 32051}, {-6393, 32138}, -{-5973, 32219}, {-5549, 32294}, -{-5127, 32364}, {-4703, 32429}, -{-4278, 32487}, {-3852, 32541}, -{-3426, 32588}, {-2999, 32630}, -{-2572, 32667}, {-2144, 32698}, -{-1716, 32724}, {-1287, 32742}, -{-860, 32757}, {-430, 32766}, -{0, 32767}, {429, 32766}, -{858, 32757}, {1287, 32743}, -{1715, 32724}, {2143, 32698}, -{2570, 32667}, {2998, 32631}, -{3425, 32588}, {3851, 32541}, -{4277, 32488}, {4701, 32429}, -{5125, 32364}, {5548, 32295}, -{5971, 32219}, {6393, 32138}, -{6813, 32051}, {7231, 31960}, -{7650, 31863}, {8067, 31760}, -{8481, 31652}, {8895, 31539}, -{9306, 31419}, {9716, 31294}, -{10126, 31165}, {10532, 31030}, -{10937, 30889}, {11340, 30743}, -{11741, 30592}, {12141, 30436}, -{12540, 30274}, {12935, 30107}, -{13328, 29936}, {13718, 29758}, -{14107, 29577}, {14493, 29390}, -{14875, 29197}, {15257, 29000}, -{15635, 28797}, {16010, 28590}, -{16384, 28379}, {16753, 28162}, -{17119, 27940}, {17484, 27714}, -{17845, 27482}, {18205, 27246}, -{18560, 27006}, {18911, 26760}, -{19260, 26510}, {19606, 26257}, -{19947, 25997}, {20286, 25734}, -{20621, 25466}, {20952, 25194}, -{21281, 24918}, {21605, 24637}, -{21926, 24353}, {22242, 24063}, -{22555, 23770}, {22865, 23473}, -{23171, 23171}, {23472, 22866}, -{23769, 22557}, {24063, 22244}, -{24352, 21927}, {24636, 21606}, -{24917, 21282}, {25194, 20954}, -{25465, 20622}, {25733, 20288}, -{25997, 19949}, {26255, 19607}, -{26509, 19261}, {26760, 18914}, -{27004, 18561}, {27246, 18205}, -{27481, 17846}, {27713, 17485}, -{27940, 17122}, {28162, 16755}, -{28378, 16385}, {28590, 16012}, -{28797, 15636}, {28999, 15258}, -{29197, 14878}, {29389, 14494}, -{29576, 14108}, {29757, 13720}, -{29934, 13329}, {30107, 12937}, -{30274, 12540}, {30435, 12142}, -{30592, 11744}, {30743, 11342}, -{30889, 10939}, {31030, 10534}, -{31164, 10127}, {31294, 9718}, -{31418, 9307}, {31537, 8895}, -{31652, 8482}, {31759, 8067}, -{31862, 7650}, {31960, 7233}, -{32051, 6815}, {32138, 6393}, -{32219, 5973}, {32294, 5549}, -{32364, 5127}, {32429, 4703}, -{32487, 4278}, {32541, 3852}, -{32588, 3426}, {32630, 2999}, -{32667, 2572}, {32698, 2144}, -{32724, 1716}, {32742, 1287}, -{32757, 860}, {32766, 430}, -}; -#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 */ -17476, /* scale */ -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 */ -17476, /* scale */ -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 */ -17476, /* scale */ -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 */ -17476, /* scale */ -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 opus_val16 mdct_twiddles960[1800] = { -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 - -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 */ -}; - -/* List of all the available modes */ -#define TOTAL_MODES 1 -static const CELTMode * const static_mode_list[TOTAL_MODES] = { -&mode48000_960_120, -}; diff --git a/drivers/opus/celt/static_modes_float.h b/drivers/opus/celt/static_modes_float.h deleted file mode 100644 index f7d501a993..0000000000 --- a/drivers/opus/celt/static_modes_float.h +++ /dev/null @@ -1,888 +0,0 @@ -/* The contents of this file was automatically generated by dump_modes.c - with arguments: 48000 960 - It contains static definitions for some pre-defined modes. */ -#include "opus/celt/modes.h" -#include "opus/celt/rate.h" - -#ifdef HAVE_ARM_NE10 -#define OVERRIDE_FFT 1 -#include "opus/celt/static_modes_float_arm_ne10.h" -#endif - -#ifndef DEF_WINDOW120 -#define DEF_WINDOW120 -static const opus_val16 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.75605424f, 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 - -#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.1230318e-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.2246064e-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.8369095e-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.002083333f, /* 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.004166667f, /* 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.008333333f, /* 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.016666667f, /* 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 opus_val16 mdct_twiddles960[1800] = { -0.99999994f, 0.99999321f, 0.99997580f, 0.99994773f, 0.99990886f, -0.99985933f, 0.99979913f, 0.99972820f, 0.99964654f, 0.99955416f, -0.99945110f, 0.99933738f, 0.99921292f, 0.99907774f, 0.99893188f, -0.99877530f, 0.99860805f, 0.99843007f, 0.99824142f, 0.99804211f, -0.99783206f, 0.99761140f, 0.99737996f, 0.99713790f, 0.99688518f, -0.99662173f, 0.99634761f, 0.99606287f, 0.99576741f, 0.99546129f, -0.99514455f, 0.99481714f, 0.99447906f, 0.99413031f, 0.99377096f, -0.99340093f, 0.99302030f, 0.99262899f, 0.99222708f, 0.99181455f, -0.99139136f, 0.99095762f, 0.99051321f, 0.99005818f, 0.98959261f, -0.98911643f, 0.98862964f, 0.98813224f, 0.98762429f, 0.98710573f, -0.98657662f, 0.98603696f, 0.98548669f, 0.98492593f, 0.98435456f, -0.98377270f, 0.98318028f, 0.98257732f, 0.98196387f, 0.98133987f, -0.98070538f, 0.98006040f, 0.97940493f, 0.97873890f, 0.97806245f, -0.97737551f, 0.97667813f, 0.97597027f, 0.97525197f, 0.97452319f, -0.97378403f, 0.97303438f, 0.97227436f, 0.97150391f, 0.97072303f, -0.96993178f, 0.96913016f, 0.96831810f, 0.96749574f, 0.96666300f, -0.96581990f, 0.96496642f, 0.96410263f, 0.96322852f, 0.96234411f, -0.96144938f, 0.96054435f, 0.95962906f, 0.95870346f, 0.95776761f, -0.95682150f, 0.95586514f, 0.95489854f, 0.95392174f, 0.95293468f, -0.95193744f, 0.95093000f, 0.94991243f, 0.94888461f, 0.94784665f, -0.94679856f, 0.94574034f, 0.94467193f, 0.94359344f, 0.94250488f, -0.94140619f, 0.94029742f, 0.93917859f, 0.93804967f, 0.93691075f, -0.93576175f, 0.93460274f, 0.93343377f, 0.93225473f, 0.93106574f, -0.92986679f, 0.92865789f, 0.92743903f, 0.92621022f, 0.92497152f, -0.92372292f, 0.92246443f, 0.92119598f, 0.91991776f, 0.91862965f, -0.91733170f, 0.91602397f, 0.91470635f, 0.91337901f, 0.91204184f, -0.91069490f, 0.90933824f, 0.90797186f, 0.90659571f, 0.90520984f, -0.90381432f, 0.90240908f, 0.90099424f, 0.89956969f, 0.89813554f, -0.89669174f, 0.89523834f, 0.89377540f, 0.89230281f, 0.89082074f, -0.88932908f, 0.88782793f, 0.88631725f, 0.88479710f, 0.88326746f, -0.88172835f, 0.88017982f, 0.87862182f, 0.87705445f, 0.87547767f, -0.87389153f, 0.87229604f, 0.87069118f, 0.86907703f, 0.86745358f, -0.86582077f, 0.86417878f, 0.86252749f, 0.86086690f, 0.85919720f, -0.85751826f, 0.85583007f, 0.85413277f, 0.85242635f, 0.85071075f, -0.84898609f, 0.84725231f, 0.84550947f, 0.84375757f, 0.84199661f, -0.84022665f, 0.83844769f, 0.83665979f, 0.83486289f, 0.83305705f, -0.83124226f, 0.82941860f, 0.82758605f, 0.82574469f, 0.82389444f, -0.82203537f, 0.82016748f, 0.81829083f, 0.81640542f, 0.81451124f, -0.81260836f, 0.81069672f, 0.80877650f, 0.80684757f, 0.80490994f, -0.80296379f, 0.80100900f, 0.79904562f, 0.79707366f, 0.79509324f, -0.79310423f, 0.79110676f, 0.78910083f, 0.78708643f, 0.78506362f, -0.78303236f, 0.78099275f, 0.77894479f, 0.77688843f, 0.77482378f, -0.77275085f, 0.77066964f, 0.76858020f, 0.76648247f, 0.76437658f, -0.76226246f, 0.76014024f, 0.75800985f, 0.75587130f, 0.75372469f, -0.75157005f, 0.74940729f, 0.74723655f, 0.74505776f, 0.74287105f, -0.74067634f, 0.73847371f, 0.73626316f, 0.73404479f, 0.73181850f, -0.72958434f, 0.72734243f, 0.72509271f, 0.72283524f, 0.72057003f, -0.71829706f, 0.71601641f, 0.71372813f, 0.71143216f, 0.70912862f, -0.70681745f, 0.70449871f, 0.70217246f, 0.69983864f, 0.69749737f, -0.69514859f, 0.69279242f, 0.69042879f, 0.68805778f, 0.68567938f, -0.68329364f, 0.68090063f, 0.67850029f, 0.67609268f, 0.67367786f, -0.67125577f, 0.66882652f, 0.66639012f, 0.66394657f, 0.66149592f, -0.65903819f, 0.65657341f, 0.65410155f, 0.65162271f, 0.64913690f, -0.64664418f, 0.64414448f, 0.64163786f, 0.63912445f, 0.63660413f, -0.63407701f, 0.63154310f, 0.62900239f, 0.62645501f, 0.62390089f, -0.62134010f, 0.61877263f, 0.61619854f, 0.61361790f, 0.61103064f, -0.60843682f, 0.60583651f, 0.60322970f, 0.60061646f, 0.59799677f, -0.59537065f, 0.59273821f, 0.59009939f, 0.58745426f, 0.58480281f, -0.58214509f, 0.57948118f, 0.57681108f, 0.57413477f, 0.57145232f, -0.56876373f, 0.56606907f, 0.56336832f, 0.56066155f, 0.55794877f, -0.55523002f, 0.55250537f, 0.54977477f, 0.54703826f, 0.54429591f, -0.54154772f, 0.53879374f, 0.53603399f, 0.53326851f, 0.53049731f, -0.52772039f, 0.52493787f, 0.52214974f, 0.51935595f, 0.51655668f, -0.51375180f, 0.51094145f, 0.50812566f, 0.50530440f, 0.50247771f, -0.49964568f, 0.49680826f, 0.49396557f, 0.49111754f, 0.48826426f, -0.48540577f, 0.48254207f, 0.47967321f, 0.47679919f, 0.47392011f, -0.47103590f, 0.46814668f, 0.46525243f, 0.46235323f, 0.45944905f, -0.45653993f, 0.45362595f, 0.45070711f, 0.44778344f, 0.44485497f, -0.44192174f, 0.43898380f, 0.43604112f, 0.43309379f, 0.43014181f, -0.42718524f, 0.42422408f, 0.42125839f, 0.41828820f, 0.41531351f, -0.41233435f, 0.40935081f, 0.40636289f, 0.40337059f, 0.40037400f, -0.39737311f, 0.39436796f, 0.39135858f, 0.38834500f, 0.38532731f, -0.38230544f, 0.37927949f, 0.37624949f, 0.37321547f, 0.37017745f, -0.36713544f, 0.36408952f, 0.36103970f, 0.35798600f, 0.35492846f, -0.35186714f, 0.34880206f, 0.34573323f, 0.34266070f, 0.33958447f, -0.33650464f, 0.33342120f, 0.33033419f, 0.32724363f, 0.32414958f, -0.32105204f, 0.31795108f, 0.31484672f, 0.31173897f, 0.30862790f, -0.30551350f, 0.30239585f, 0.29927495f, 0.29615086f, 0.29302359f, -0.28989318f, 0.28675964f, 0.28362307f, 0.28048345f, 0.27734083f, -0.27419522f, 0.27104670f, 0.26789525f, 0.26474094f, 0.26158381f, -0.25842386f, 0.25526115f, 0.25209570f, 0.24892756f, 0.24575676f, -0.24258332f, 0.23940729f, 0.23622867f, 0.23304754f, 0.22986393f, -0.22667783f, 0.22348931f, 0.22029841f, 0.21710514f, 0.21390954f, -0.21071166f, 0.20751151f, 0.20430915f, 0.20110460f, 0.19789790f, -0.19468907f, 0.19147816f, 0.18826519f, 0.18505022f, 0.18183327f, -0.17861435f, 0.17539354f, 0.17217083f, 0.16894630f, 0.16571994f, -0.16249183f, 0.15926196f, 0.15603039f, 0.15279715f, 0.14956227f, -0.14632578f, 0.14308774f, 0.13984816f, 0.13660708f, 0.13336454f, -0.13012058f, 0.12687522f, 0.12362850f, 0.12038045f, 0.11713112f, -0.11388054f, 0.11062872f, 0.10737573f, 0.10412160f, 0.10086634f, -0.097609997f, 0.094352618f, 0.091094226f, 0.087834857f, 0.084574550f, -0.081313334f, 0.078051247f, 0.074788325f, 0.071524605f, 0.068260118f, -0.064994894f, 0.061728980f, 0.058462404f, 0.055195201f, 0.051927410f, -0.048659060f, 0.045390189f, 0.042120833f, 0.038851023f, 0.035580799f, -0.032310195f, 0.029039243f, 0.025767982f, 0.022496443f, 0.019224664f, -0.015952680f, 0.012680525f, 0.0094082337f, 0.0061358409f, 0.0028633832f, --0.00040910527f, -0.0036815894f, -0.0069540343f, -0.010226404f, -0.013498665f, --0.016770782f, -0.020042717f, -0.023314439f, -0.026585912f, -0.029857099f, --0.033127967f, -0.036398482f, -0.039668605f, -0.042938303f, -0.046207540f, --0.049476285f, -0.052744497f, -0.056012146f, -0.059279196f, -0.062545612f, --0.065811358f, -0.069076397f, -0.072340697f, -0.075604223f, -0.078866936f, --0.082128808f, -0.085389800f, -0.088649876f, -0.091909006f, -0.095167145f, --0.098424271f, -0.10168034f, -0.10493532f, -0.10818918f, -0.11144188f, --0.11469338f, -0.11794366f, -0.12119267f, -0.12444039f, -0.12768677f, --0.13093179f, -0.13417540f, -0.13741758f, -0.14065829f, -0.14389749f, --0.14713514f, -0.15037122f, -0.15360570f, -0.15683852f, -0.16006967f, --0.16329910f, -0.16652679f, -0.16975269f, -0.17297678f, -0.17619900f, --0.17941935f, -0.18263777f, -0.18585424f, -0.18906870f, -0.19228116f, --0.19549155f, -0.19869985f, -0.20190603f, -0.20511003f, -0.20831184f, --0.21151142f, -0.21470875f, -0.21790376f, -0.22109644f, -0.22428675f, --0.22747467f, -0.23066014f, -0.23384315f, -0.23702365f, -0.24020162f, --0.24337701f, -0.24654980f, -0.24971995f, -0.25288740f, -0.25605217f, --0.25921419f, -0.26237345f, -0.26552987f, -0.26868346f, -0.27183419f, --0.27498198f, -0.27812684f, -0.28126872f, -0.28440759f, -0.28754342f, --0.29067615f, -0.29380578f, -0.29693225f, -0.30005556f, -0.30317566f, --0.30629250f, -0.30940607f, -0.31251630f, -0.31562322f, -0.31872672f, --0.32182685f, -0.32492352f, -0.32801670f, -0.33110636f, -0.33419248f, --0.33727503f, -0.34035397f, -0.34342924f, -0.34650084f, -0.34956875f, --0.35263291f, -0.35569328f, -0.35874987f, -0.36180258f, -0.36485144f, --0.36789638f, -0.37093741f, -0.37397444f, -0.37700745f, -0.38003644f, --0.38306138f, -0.38608220f, -0.38909888f, -0.39211139f, -0.39511973f, --0.39812380f, -0.40112361f, -0.40411916f, -0.40711036f, -0.41009718f, --0.41307965f, -0.41605768f, -0.41903123f, -0.42200032f, -0.42496487f, --0.42792490f, -0.43088034f, -0.43383113f, -0.43677729f, -0.43971881f, --0.44265559f, -0.44558764f, -0.44851488f, -0.45143735f, -0.45435500f, --0.45726776f, -0.46017563f, -0.46307856f, -0.46597654f, -0.46886954f, --0.47175750f, -0.47464043f, -0.47751826f, -0.48039100f, -0.48325855f, --0.48612097f, -0.48897815f, -0.49183011f, -0.49467680f, -0.49751821f, --0.50035429f, -0.50318497f, -0.50601029f, -0.50883019f, -0.51164466f, --0.51445359f, -0.51725709f, -0.52005500f, -0.52284735f, -0.52563411f, --0.52841520f, -0.53119069f, -0.53396046f, -0.53672451f, -0.53948283f, --0.54223537f, -0.54498214f, -0.54772300f, -0.55045801f, -0.55318713f, --0.55591035f, -0.55862761f, -0.56133890f, -0.56404412f, -0.56674337f, --0.56943649f, -0.57212353f, -0.57480448f, -0.57747924f, -0.58014780f, --0.58281022f, -0.58546633f, -0.58811617f, -0.59075975f, -0.59339696f, --0.59602785f, -0.59865236f, -0.60127044f, -0.60388207f, -0.60648727f, --0.60908598f, -0.61167812f, -0.61426371f, -0.61684275f, -0.61941516f, --0.62198097f, -0.62454009f, -0.62709254f, -0.62963831f, -0.63217729f, --0.63470948f, -0.63723493f, -0.63975352f, -0.64226526f, -0.64477009f, --0.64726806f, -0.64975911f, -0.65224314f, -0.65472025f, -0.65719032f, --0.65965337f, -0.66210932f, -0.66455823f, -0.66700000f, -0.66943461f, --0.67186207f, -0.67428231f, -0.67669535f, -0.67910111f, -0.68149966f, --0.68389088f, -0.68627477f, -0.68865126f, -0.69102043f, -0.69338220f, --0.69573659f, -0.69808346f, -0.70042288f, -0.70275480f, -0.70507920f, --0.70739603f, -0.70970529f, -0.71200693f, -0.71430099f, -0.71658736f, --0.71886611f, -0.72113711f, -0.72340041f, -0.72565591f, -0.72790372f, --0.73014367f, -0.73237586f, -0.73460019f, -0.73681659f, -0.73902518f, --0.74122584f, -0.74341851f, -0.74560326f, -0.74778003f, -0.74994880f, --0.75210953f, -0.75426215f, -0.75640678f, -0.75854325f, -0.76067162f, --0.76279181f, -0.76490390f, -0.76700771f, -0.76910341f, -0.77119076f, --0.77326995f, -0.77534080f, -0.77740335f, -0.77945763f, -0.78150350f, --0.78354102f, -0.78557014f, -0.78759086f, -0.78960317f, -0.79160696f, --0.79360235f, -0.79558921f, -0.79756755f, -0.79953730f, -0.80149853f, --0.80345118f, -0.80539525f, -0.80733067f, -0.80925739f, -0.81117553f, --0.81308490f, -0.81498563f, -0.81687760f, -0.81876087f, -0.82063532f, --0.82250100f, -0.82435787f, -0.82620591f, -0.82804507f, -0.82987541f, --0.83169687f, -0.83350939f, -0.83531296f, -0.83710766f, -0.83889335f, --0.84067005f, -0.84243774f, -0.84419644f, -0.84594607f, -0.84768665f, --0.84941816f, -0.85114056f, -0.85285389f, -0.85455805f, -0.85625303f, --0.85793889f, -0.85961550f, -0.86128294f, -0.86294121f, -0.86459017f, --0.86622989f, -0.86786032f, -0.86948150f, -0.87109333f, -0.87269586f, --0.87428904f, -0.87587279f, -0.87744725f, -0.87901229f, -0.88056785f, --0.88211405f, -0.88365078f, -0.88517809f, -0.88669586f, -0.88820416f, --0.88970292f, -0.89119220f, -0.89267188f, -0.89414203f, -0.89560264f, --0.89705360f, -0.89849502f, -0.89992678f, -0.90134889f, -0.90276134f, --0.90416414f, -0.90555727f, -0.90694070f, -0.90831441f, -0.90967834f, --0.91103262f, -0.91237706f, -0.91371179f, -0.91503674f, -0.91635185f, --0.91765714f, -0.91895264f, -0.92023826f, -0.92151409f, -0.92277998f, --0.92403603f, -0.92528218f, -0.92651838f, -0.92774469f, -0.92896110f, --0.93016750f, -0.93136400f, -0.93255049f, -0.93372697f, -0.93489349f, --0.93604994f, -0.93719643f, -0.93833286f, -0.93945926f, -0.94057560f, --0.94168180f, -0.94277799f, -0.94386405f, -0.94494003f, -0.94600588f, --0.94706154f, -0.94810712f, -0.94914252f, -0.95016778f, -0.95118284f, --0.95218778f, -0.95318246f, -0.95416695f, -0.95514119f, -0.95610523f, --0.95705903f, -0.95800257f, -0.95893586f, -0.95985889f, -0.96077162f, --0.96167403f, -0.96256620f, -0.96344805f, -0.96431959f, -0.96518075f, --0.96603161f, -0.96687216f, -0.96770233f, -0.96852213f, -0.96933156f, --0.97013056f, -0.97091925f, -0.97169751f, -0.97246534f, -0.97322279f, --0.97396982f, -0.97470641f, -0.97543252f, -0.97614825f, -0.97685349f, --0.97754824f, -0.97823256f, -0.97890645f, -0.97956979f, -0.98022264f, --0.98086500f, -0.98149687f, -0.98211825f, -0.98272908f, -0.98332942f, --0.98391914f, -0.98449844f, -0.98506713f, -0.98562527f, -0.98617285f, --0.98670989f, -0.98723638f, -0.98775226f, -0.98825759f, -0.98875231f, --0.98923647f, -0.98971003f, -0.99017298f, -0.99062532f, -0.99106705f, --0.99149817f, -0.99191868f, -0.99232858f, -0.99272782f, -0.99311644f, --0.99349445f, -0.99386179f, -0.99421853f, -0.99456459f, -0.99489999f, --0.99522477f, -0.99553883f, -0.99584228f, -0.99613506f, -0.99641716f, --0.99668860f, -0.99694937f, -0.99719942f, -0.99743885f, -0.99766755f, --0.99788558f, -0.99809295f, -0.99828959f, -0.99847561f, -0.99865085f, --0.99881548f, -0.99896932f, -0.99911255f, -0.99924499f, -0.99936682f, --0.99947786f, -0.99957830f, -0.99966794f, -0.99974692f, -0.99981517f, --0.99987274f, -0.99991959f, -0.99995571f, -0.99998116f, -0.99999589f, -0.99999964f, 0.99997288f, 0.99990326f, 0.99979085f, 0.99963558f, -0.99943751f, 0.99919659f, 0.99891287f, 0.99858636f, 0.99821711f, -0.99780506f, 0.99735034f, 0.99685282f, 0.99631262f, 0.99572974f, -0.99510419f, 0.99443603f, 0.99372530f, 0.99297196f, 0.99217612f, -0.99133772f, 0.99045694f, 0.98953366f, 0.98856801f, 0.98756003f, -0.98650974f, 0.98541719f, 0.98428243f, 0.98310548f, 0.98188645f, -0.98062533f, 0.97932225f, 0.97797716f, 0.97659022f, 0.97516143f, -0.97369087f, 0.97217858f, 0.97062469f, 0.96902919f, 0.96739221f, -0.96571374f, 0.96399397f, 0.96223283f, 0.96043050f, 0.95858705f, -0.95670253f, 0.95477700f, 0.95281059f, 0.95080340f, 0.94875544f, -0.94666684f, 0.94453770f, 0.94236809f, 0.94015813f, 0.93790787f, -0.93561745f, 0.93328691f, 0.93091643f, 0.92850608f, 0.92605597f, -0.92356616f, 0.92103678f, 0.91846794f, 0.91585976f, 0.91321236f, -0.91052586f, 0.90780038f, 0.90503591f, 0.90223277f, 0.89939094f, -0.89651060f, 0.89359182f, 0.89063478f, 0.88763964f, 0.88460642f, -0.88153529f, 0.87842643f, 0.87527996f, 0.87209594f, 0.86887461f, -0.86561602f, 0.86232042f, 0.85898781f, 0.85561842f, 0.85221243f, -0.84876984f, 0.84529096f, 0.84177583f, 0.83822471f, 0.83463764f, -0.83101481f, 0.82735640f, 0.82366252f, 0.81993335f, 0.81616908f, -0.81236988f, 0.80853581f, 0.80466717f, 0.80076402f, 0.79682660f, -0.79285502f, 0.78884947f, 0.78481019f, 0.78073722f, 0.77663082f, -0.77249116f, 0.76831841f, 0.76411277f, 0.75987434f, 0.75560343f, -0.75130010f, 0.74696463f, 0.74259710f, 0.73819780f, 0.73376691f, -0.72930455f, 0.72481096f, 0.72028631f, 0.71573079f, 0.71114463f, -0.70652801f, 0.70188117f, 0.69720417f, 0.69249737f, 0.68776089f, -0.68299496f, 0.67819971f, 0.67337549f, 0.66852236f, 0.66364062f, -0.65873051f, 0.65379208f, 0.64882571f, 0.64383155f, 0.63880974f, -0.63376063f, 0.62868434f, 0.62358117f, 0.61845124f, 0.61329484f, -0.60811216f, 0.60290343f, 0.59766883f, 0.59240872f, 0.58712316f, -0.58181250f, 0.57647687f, 0.57111657f, 0.56573176f, 0.56032276f, -0.55488980f, 0.54943299f, 0.54395270f, 0.53844911f, 0.53292239f, -0.52737290f, 0.52180082f, 0.51620632f, 0.51058978f, 0.50495136f, -0.49929130f, 0.49360985f, 0.48790723f, 0.48218375f, 0.47643960f, -0.47067502f, 0.46489030f, 0.45908567f, 0.45326138f, 0.44741765f, -0.44155475f, 0.43567297f, 0.42977250f, 0.42385364f, 0.41791660f, -0.41196167f, 0.40598908f, 0.39999911f, 0.39399201f, 0.38796803f, -0.38192743f, 0.37587047f, 0.36979741f, 0.36370850f, 0.35760403f, -0.35148421f, 0.34534934f, 0.33919969f, 0.33303553f, 0.32685706f, -0.32066461f, 0.31445843f, 0.30823877f, 0.30200592f, 0.29576012f, -0.28950164f, 0.28323078f, 0.27694780f, 0.27065292f, 0.26434645f, -0.25802869f, 0.25169984f, 0.24536023f, 0.23901010f, 0.23264973f, -0.22627939f, 0.21989937f, 0.21350993f, 0.20711134f, 0.20070387f, -0.19428782f, 0.18786344f, 0.18143101f, 0.17499080f, 0.16854310f, -0.16208819f, 0.15562633f, 0.14915779f, 0.14268288f, 0.13620184f, -0.12971498f, 0.12322257f, 0.11672486f, 0.11022217f, 0.10371475f, -0.097202882f, 0.090686858f, 0.084166944f, 0.077643424f, 0.071116582f, -0.064586692f, 0.058054037f, 0.051518895f, 0.044981543f, 0.038442269f, -0.031901345f, 0.025359053f, 0.018815678f, 0.012271495f, 0.0057267868f, --0.00081816671f, -0.0073630852f, -0.013907688f, -0.020451695f, -0.026994826f, --0.033536803f, -0.040077340f, -0.046616159f, -0.053152986f, -0.059687532f, --0.066219524f, -0.072748676f, -0.079274714f, -0.085797355f, -0.092316322f, --0.098831341f, -0.10534211f, -0.11184838f, -0.11834986f, -0.12484626f, --0.13133731f, -0.13782275f, -0.14430228f, -0.15077563f, -0.15724251f, --0.16370267f, -0.17015581f, -0.17660165f, -0.18303993f, -0.18947038f, --0.19589271f, -0.20230664f, -0.20871192f, -0.21510825f, -0.22149536f, --0.22787298f, -0.23424086f, -0.24059868f, -0.24694622f, -0.25328314f, --0.25960925f, -0.26592422f, -0.27222782f, -0.27851975f, -0.28479972f, --0.29106751f, -0.29732284f, -0.30356544f, -0.30979502f, -0.31601134f, --0.32221413f, -0.32840309f, -0.33457801f, -0.34073856f, -0.34688455f, --0.35301566f, -0.35913166f, -0.36523229f, -0.37131724f, -0.37738630f, --0.38343921f, -0.38947567f, -0.39549544f, -0.40149832f, -0.40748394f, --0.41345215f, -0.41940263f, -0.42533514f, -0.43124944f, -0.43714526f, --0.44302234f, -0.44888046f, -0.45471936f, -0.46053877f, -0.46633846f, --0.47211814f, -0.47787762f, -0.48361665f, -0.48933494f, -0.49503228f, --0.50070840f, -0.50636309f, -0.51199609f, -0.51760709f, -0.52319598f, --0.52876246f, -0.53430629f, -0.53982723f, -0.54532504f, -0.55079949f, --0.55625033f, -0.56167740f, -0.56708032f, -0.57245898f, -0.57781315f, --0.58314258f, -0.58844697f, -0.59372622f, -0.59897995f, -0.60420811f, --0.60941035f, -0.61458647f, -0.61973625f, -0.62485951f, -0.62995601f, --0.63502556f, -0.64006782f, -0.64508271f, -0.65007001f, -0.65502942f, --0.65996075f, -0.66486382f, -0.66973841f, -0.67458433f, -0.67940134f, --0.68418926f, -0.68894786f, -0.69367695f, -0.69837630f, -0.70304573f, --0.70768511f, -0.71229410f, -0.71687263f, -0.72142041f, -0.72593731f, --0.73042315f, -0.73487765f, -0.73930067f, -0.74369204f, -0.74805158f, --0.75237900f, -0.75667429f, -0.76093709f, -0.76516730f, -0.76936477f, --0.77352923f, -0.77766061f, -0.78175867f, -0.78582323f, -0.78985411f, --0.79385114f, -0.79781419f, -0.80174309f, -0.80563760f, -0.80949765f, --0.81332302f, -0.81711352f, -0.82086903f, -0.82458937f, -0.82827437f, --0.83192390f, -0.83553779f, -0.83911592f, -0.84265804f, -0.84616417f, --0.84963393f, -0.85306740f, -0.85646427f, -0.85982448f, -0.86314780f, --0.86643422f, -0.86968350f, -0.87289548f, -0.87607014f, -0.87920725f, --0.88230664f, -0.88536829f, -0.88839203f, -0.89137769f, -0.89432514f, --0.89723432f, -0.90010506f, -0.90293723f, -0.90573072f, -0.90848541f, --0.91120118f, -0.91387796f, -0.91651553f, -0.91911387f, -0.92167282f, --0.92419231f, -0.92667222f, -0.92911243f, -0.93151283f, -0.93387336f, --0.93619382f, -0.93847424f, -0.94071442f, -0.94291431f, -0.94507378f, --0.94719279f, -0.94927126f, -0.95130903f, -0.95330608f, -0.95526224f, --0.95717752f, -0.95905179f, -0.96088499f, -0.96267700f, -0.96442777f, --0.96613729f, -0.96780539f, -0.96943200f, -0.97101706f, -0.97256058f, --0.97406244f, -0.97552258f, -0.97694093f, -0.97831738f, -0.97965199f, --0.98094457f, -0.98219514f, -0.98340368f, -0.98457009f, -0.98569429f, --0.98677629f, -0.98781598f, -0.98881340f, -0.98976845f, -0.99068111f, --0.99155134f, -0.99237907f, -0.99316430f, -0.99390697f, -0.99460709f, --0.99526459f, -0.99587947f, -0.99645168f, -0.99698120f, -0.99746799f, --0.99791211f, -0.99831343f, -0.99867201f, -0.99898779f, -0.99926084f, --0.99949104f, -0.99967843f, -0.99982297f, -0.99992472f, -0.99998361f, -0.99999869f, 0.99989158f, 0.99961317f, 0.99916345f, 0.99854255f, -0.99775058f, 0.99678761f, 0.99565387f, 0.99434954f, 0.99287480f, -0.99122995f, 0.98941529f, 0.98743105f, 0.98527765f, 0.98295540f, -0.98046476f, 0.97780609f, 0.97497988f, 0.97198665f, 0.96882683f, -0.96550101f, 0.96200979f, 0.95835376f, 0.95453346f, 0.95054960f, -0.94640291f, 0.94209403f, 0.93762374f, 0.93299282f, 0.92820197f, -0.92325211f, 0.91814411f, 0.91287869f, 0.90745693f, 0.90187967f, -0.89614785f, 0.89026248f, 0.88422459f, 0.87803519f, 0.87169534f, -0.86520612f, 0.85856867f, 0.85178405f, 0.84485358f, 0.83777827f, -0.83055943f, 0.82319832f, 0.81569612f, 0.80805415f, 0.80027372f, -0.79235619f, 0.78430289f, 0.77611518f, 0.76779449f, 0.75934225f, -0.75075996f, 0.74204898f, 0.73321080f, 0.72424710f, 0.71515924f, -0.70594883f, 0.69661748f, 0.68716675f, 0.67759830f, 0.66791373f, -0.65811473f, 0.64820296f, 0.63818014f, 0.62804794f, 0.61780810f, -0.60746247f, 0.59701276f, 0.58646071f, 0.57580817f, 0.56505698f, -0.55420899f, 0.54326600f, 0.53222996f, 0.52110273f, 0.50988621f, -0.49858227f, 0.48719296f, 0.47572014f, 0.46416581f, 0.45253196f, -0.44082057f, 0.42903364f, 0.41717321f, 0.40524128f, 0.39323992f, -0.38117120f, 0.36903715f, 0.35683987f, 0.34458145f, 0.33226398f, -0.31988961f, 0.30746040f, 0.29497850f, 0.28244606f, 0.26986524f, -0.25723818f, 0.24456702f, 0.23185398f, 0.21910121f, 0.20631088f, -0.19348522f, 0.18062639f, 0.16773662f, 0.15481812f, 0.14187308f, -0.12890373f, 0.11591230f, 0.10290100f, 0.089872077f, 0.076827750f, -0.063770257f, 0.050701842f, 0.037624735f, 0.024541186f, 0.011453429f, --0.0016362892f, -0.014725727f, -0.027812643f, -0.040894791f, -0.053969935f, --0.067035832f, -0.080090240f, -0.093130924f, -0.10615565f, -0.11916219f, --0.13214831f, -0.14511178f, -0.15805040f, -0.17096193f, -0.18384418f, --0.19669491f, -0.20951195f, -0.22229309f, -0.23503613f, -0.24773891f, --0.26039925f, -0.27301496f, -0.28558388f, -0.29810387f, -0.31057280f, --0.32298848f, -0.33534884f, -0.34765175f, -0.35989508f, -0.37207675f, --0.38419467f, -0.39624676f, -0.40823093f, -0.42014518f, -0.43198743f, --0.44375566f, -0.45544785f, -0.46706200f, -0.47859612f, -0.49004826f, --0.50141639f, -0.51269865f, -0.52389306f, -0.53499764f, -0.54601061f, --0.55693001f, -0.56775403f, -0.57848072f, -0.58910829f, -0.59963489f, --0.61005878f, -0.62037814f, -0.63059121f, -0.64069623f, -0.65069145f, --0.66057515f, -0.67034572f, -0.68000144f, -0.68954057f, -0.69896162f, --0.70826286f, -0.71744281f, -0.72649974f, -0.73543227f, -0.74423873f, --0.75291771f, -0.76146764f, -0.76988715f, -0.77817470f, -0.78632891f, --0.79434842f, -0.80223179f, -0.80997771f, -0.81758487f, -0.82505190f, --0.83237761f, -0.83956063f, -0.84659988f, -0.85349399f, -0.86024189f, --0.86684239f, -0.87329435f, -0.87959671f, -0.88574833f, -0.89174819f, --0.89759529f, -0.90328854f, -0.90882701f, -0.91420978f, -0.91943592f, --0.92450452f, -0.92941469f, -0.93416560f, -0.93875647f, -0.94318646f, --0.94745487f, -0.95156091f, -0.95550388f, -0.95928317f, -0.96289814f, --0.96634805f, -0.96963239f, -0.97275060f, -0.97570217f, -0.97848648f, --0.98110318f, -0.98355180f, -0.98583186f, -0.98794299f, -0.98988485f, --0.99165714f, -0.99325943f, -0.99469161f, -0.99595332f, -0.99704438f, --0.99796462f, -0.99871385f, -0.99929196f, -0.99969882f, -0.99993443f, -0.99999464f, 0.99956632f, 0.99845290f, 0.99665523f, 0.99417448f, -0.99101239f, 0.98717111f, 0.98265326f, 0.97746199f, 0.97160077f, -0.96507365f, 0.95788515f, 0.95004016f, 0.94154406f, 0.93240267f, -0.92262226f, 0.91220951f, 0.90117162f, 0.88951606f, 0.87725091f, -0.86438453f, 0.85092574f, 0.83688372f, 0.82226819f, 0.80708915f, -0.79135692f, 0.77508235f, 0.75827658f, 0.74095112f, 0.72311783f, -0.70478898f, 0.68597710f, 0.66669506f, 0.64695615f, 0.62677377f, -0.60616189f, 0.58513457f, 0.56370622f, 0.54189157f, 0.51970547f, -0.49716324f, 0.47428027f, 0.45107225f, 0.42755505f, 0.40374488f, -0.37965798f, 0.35531086f, 0.33072025f, 0.30590299f, 0.28087607f, -0.25565663f, 0.23026201f, 0.20470956f, 0.17901683f, 0.15320139f, -0.12728097f, 0.10127331f, 0.075196236f, 0.049067631f, 0.022905400f, --0.0032725304f, -0.029448219f, -0.055603724f, -0.081721120f, -0.10778251f, --0.13377003f, -0.15966587f, -0.18545228f, -0.21111161f, -0.23662624f, --0.26197869f, -0.28715160f, -0.31212771f, -0.33688989f, -0.36142120f, --0.38570482f, -0.40972409f, -0.43346253f, -0.45690393f, -0.48003218f, --0.50283146f, -0.52528608f, -0.54738069f, -0.56910020f, -0.59042966f, --0.61135447f, -0.63186026f, -0.65193301f, -0.67155898f, -0.69072473f, --0.70941705f, -0.72762316f, -0.74533063f, -0.76252723f, -0.77920127f, --0.79534131f, -0.81093621f, -0.82597536f, -0.84044844f, -0.85434550f, --0.86765707f, -0.88037395f, -0.89248747f, -0.90398932f, -0.91487163f, --0.92512697f, -0.93474823f, -0.94372886f, -0.95206273f, -0.95974404f, --0.96676767f, -0.97312868f, -0.97882277f, -0.98384601f, -0.98819500f, --0.99186671f, -0.99485862f, -0.99716878f, -0.99879545f, -0.99973762f, -}; -#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 */ -}; - -/* List of all the available modes */ -#define TOTAL_MODES 1 -static const CELTMode * const static_mode_list[TOTAL_MODES] = { -&mode48000_960_120, -}; diff --git a/drivers/opus/celt/vq.c b/drivers/opus/celt/vq.c deleted file mode 100644 index 3061e3006f..0000000000 --- a/drivers/opus/celt/vq.c +++ /dev/null @@ -1,405 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/celt/mathops.h" -#include "opus/celt/cwrs.h" -#include "opus/celt/vq.h" -#include "opus/celt/arch.h" -#include "opus/celt/os_support.h" -#include "opus/celt/bands.h" -#include "opus/celt/rate.h" -#include "opus/celt/pitch.h" - -#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); - 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)); - } -} -#endif /* OVERRIDE_vq_exp_rotation1 */ - -static 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); - } - } -} - -/** Takes the pitch vector and the decoded residual vector, computes the gain - that will give ||p+g*y||=1 and mixes the residual with the pitch. */ -static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X, - int N, opus_val32 Ryy, opus_val16 gain) -{ - int i; -#ifdef OPUS_FIXED_POINT - int k; -#endif - opus_val32 t; - opus_val16 g; - -#ifdef OPUS_FIXED_POINT - k = celt_ilog2(Ryy)>>1; -#endif - t = VSHR32(Ryy, 2*(k-7)); - g = MULT16_16_P15(celt_rsqrt_norm(t),gain); - - i=0; - do - X[i] = EXTRACT16(PSHR32(MULT16_16(g, iy[i]), k+1)); - 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; -} - -unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc -#ifdef RESYNTH - , opus_val16 gain -#endif - ) -{ - VARDECL(celt_norm, y); - VARDECL(int, iy); - VARDECL(opus_val16, signx); - int i, j; - opus_val16 s; - int pulsesLeft; - opus_val32 sum; - opus_val32 xy; - opus_val16 yy; - unsigned collapse_mask; - SAVE_STACK; - - celt_assert2(K>0, "alg_quant() needs at least one pulse"); - celt_assert2(N>1, "alg_quant() needs at least two dimensions"); - - ALLOC(y, N, celt_norm); - ALLOC(iy, N, int); - ALLOC(signx, N, opus_val16); - - exp_rotation(X, N, 1, B, K, spread); - - /* Get rid of the sign */ - sum = 0; - j=0; do { - if (X[j]>0) - signx[j]=1; - else { - signx[j]=-1; - X[j]=-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 OPUS_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); - } - rcp = EXTRACT16(MULT16_32_Q16(K-1, celt_rcp(sum))); - j=0; do { -#ifdef OPUS_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_assert2(pulsesLeft>=1, "Allocated too many pulses in the quick pass"); - - /* This should never happen, but just in case it does (e.g. on silence) - we fill the first bin with pulses. */ -#ifdef OPUS_FIXED_POINT_DEBUG - celt_assert2(pulsesLeft<=N+3, "Not enough pulses in the quick pass"); -#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; - } - - s = 1; - for (i=0;i<pulsesLeft;i++) - { - int best_id; - opus_val32 best_num = -VERY_LARGE16; - opus_val16 best_den = 0; -#ifdef OPUS_FIXED_POINT - int rshift; -#endif -#ifdef OPUS_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 = ADD32(yy, 1); - j=0; - do { - opus_val16 Rxy, Ryy; - /* 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: Make sure to use conditional moves here */ - if (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*s; - iy[best_id]++; - } - - /* Put the original sign back */ - j=0; - do { - X[j] = MULT16_16(signx[j],X[j]); - if (signx[j] < 0) - iy[j] = -iy[j]; - } while (++j<N); - encode_pulses(iy, N, K, enc); - -#ifdef RESYNTH - normalise_residual(iy, X, N, yy, gain); - exp_rotation(X, N, -1, B, K, spread); -#endif - - collapse_mask = extract_collapse_mask(iy, N, B); - 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_val16 gain) -{ - opus_val32 Ryy; - unsigned collapse_mask; - VARDECL(int, iy); - 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); - normalise_residual(iy, X, N, Ryy, gain); - 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_val16 gain, int arch) -{ - int i; -#ifdef OPUS_FIXED_POINT - int k; -#endif - opus_val32 E; - opus_val16 g; - opus_val32 t; - celt_norm *xptr; - E = EPSILON + celt_inner_prod(X, X, N, arch); -#ifdef OPUS_FIXED_POINT - k = celt_ilog2(E)>>1; -#endif - t = VSHR32(E, 2*(k-7)); - g = MULT16_16_P15(celt_rsqrt_norm(t),gain); - - xptr = X; - for (i=0;i<N;i++) - { - *xptr = EXTRACT16(PSHR32(MULT16_16(g, *xptr), k+1)); - xptr++; - } - /*return celt_sqrt(E);*/ -} -#endif /* OVERRIDE_renormalise_vector */ - -int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch) -{ - int i; - int itheta; - opus_val16 mid, side; - opus_val32 Emid, Eside; - - Emid = Eside = EPSILON; - if (stereo) - { - for (i=0;i<N;i++) - { - celt_norm m, s; - m = ADD16(SHR16(X[i],1),SHR16(Y[i],1)); - s = SUB16(SHR16(X[i],1),SHR16(Y[i],1)); - Emid = MAC16_16(Emid, m, m); - Eside = MAC16_16(Eside, s, s); - } - } else { - Emid += celt_inner_prod(X, X, N, arch); - Eside += celt_inner_prod(Y, Y, N, arch); - } - mid = celt_sqrt(Emid); - side = celt_sqrt(Eside); -#ifdef OPUS_FIXED_POINT - /* 0.63662 = 2/pi */ - itheta = MULT16_16_Q15(QCONST16(0.63662f,15),celt_atan2p(side, mid)); -#else - itheta = (int)floor(.5f+16384*0.63662f*atan2(side,mid)); -#endif - - return itheta; -} diff --git a/drivers/opus/celt/vq.h b/drivers/opus/celt/vq.h deleted file mode 100644 index 10b5e55306..0000000000 --- a/drivers/opus/celt/vq.h +++ /dev/null @@ -1,75 +0,0 @@ -/* 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 "opus/celt/entenc.h" -#include "opus/celt/entdec.h" -#include "opus/celt/modes.h" - -#if defined(MIPSr1_ASM) -#include "opus/celt/mips/vq_mipsr1.h" -#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 -#ifdef RESYNTH - , opus_val16 gain -#endif - ); - -/** 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_val16 gain); - -void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch); - -int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch); - -#endif /* VQ_H */ diff --git a/drivers/opus/celt/x86/celt_lpc_sse.c b/drivers/opus/celt/x86/celt_lpc_sse.c deleted file mode 100644 index cfc86dc66c..0000000000 --- a/drivers/opus/celt/x86/celt_lpc_sse.c +++ /dev/null @@ -1,129 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include <xmmintrin.h> -#include <emmintrin.h> -#include <smmintrin.h> -#include "opus/celt/celt_lpc.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/mathops.h" -#include "opus/celt/pitch.h" -#include "opus/celt/x86/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, - opus_val16 *mem, - int arch) -{ - int i,j; - VARDECL(opus_val16, rnum); - VARDECL(opus_val16, x); - - __m128i vecNoA; - opus_int32 noA ; - SAVE_STACK; - - ALLOC(rnum, ord, opus_val16); - ALLOC(x, N+ord, opus_val16); - for(i=0;i<ord;i++) - rnum[i] = num[ord-i-1]; - for(i=0;i<ord;i++) - x[i] = mem[ord-i-1]; - - for (i=0;i<N-7;i+=8) - { - x[i+ord ]=_x[i ]; - x[i+ord+1]=_x[i+1]; - x[i+ord+2]=_x[i+2]; - x[i+ord+3]=_x[i+3]; - x[i+ord+4]=_x[i+4]; - x[i+ord+5]=_x[i+5]; - x[i+ord+6]=_x[i+6]; - x[i+ord+7]=_x[i+7]; - } - - for (;i<N-3;i+=4) - { - x[i+ord ]=_x[i ]; - x[i+ord+1]=_x[i+1]; - x[i+ord+2]=_x[i+2]; - x[i+ord+3]=_x[i+3]; - } - - for (;i<N;i++) - x[i+ord]=_x[i]; - - for(i=0;i<ord;i++) - mem[i] = _x[N-i-1]; -#ifdef SMALL_FOOTPRINT - for (i=0;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]); - } - _y[i] = SATURATE16(PSHR32(sum, SIG_SHIFT)); - } -#else - 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; - - xcorr_kernel(rnum, x+i, sums, ord, arch); - - vecSum = _mm_loadu_si128((__m128i *)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 *)(_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]); - _y[i] = SATURATE16(ADD32(EXTEND32(_x[i]), PSHR32(sum, SIG_SHIFT))); - } - -#endif - RESTORE_STACK; -} - -#endif diff --git a/drivers/opus/celt/x86/celt_lpc_sse.h b/drivers/opus/celt/x86/celt_lpc_sse.h deleted file mode 100644 index 3787afd3ff..0000000000 --- a/drivers/opus/celt/x86/celt_lpc_sse.h +++ /dev/null @@ -1,65 +0,0 @@ -/* 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 -#include "opus/opus_config.h" - -#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT) -#define OVERRIDE_CELT_FIR - -void celt_fir_sse4_1( - const opus_val16 *x, - const opus_val16 *num, - opus_val16 *y, - int N, - int ord, - opus_val16 *mem, - int arch); - -#if defined(OPUS_X86_PRESUME_SSE4_1) -#define celt_fir(x, num, y, N, ord, mem, arch) \ - ((void)arch, celt_fir_sse4_1(x, num, y, N, ord, mem, arch)) - -#else - -extern void (*const CELT_FIR_IMPL[OPUS_ARCHMASK + 1])( - const opus_val16 *x, - const opus_val16 *num, - opus_val16 *y, - int N, - int ord, - opus_val16 *mem, - int arch); - -# define celt_fir(x, num, y, N, ord, mem, arch) \ - ((*CELT_FIR_IMPL[(arch) & OPUS_ARCHMASK])(x, num, y, N, ord, mem, arch)) - -#endif -#endif - -#endif diff --git a/drivers/opus/celt/x86/pitch_sse.c b/drivers/opus/celt/x86/pitch_sse.c deleted file mode 100644 index 9f22ffd9ab..0000000000 --- a/drivers/opus/celt/x86/pitch_sse.c +++ /dev/null @@ -1,182 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/silk/macros.h" -#include "opus/celt/celt_lpc.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/mathops.h" -#include "opus/celt/pitch.h" - -#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT) - -#include <xmmintrin.h> -#include "opus/celt/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/drivers/opus/celt/x86/pitch_sse.h b/drivers/opus/celt/x86/pitch_sse.h deleted file mode 100644 index 2b4b54f61f..0000000000 --- a/drivers/opus/celt/x86/pitch_sse.h +++ /dev/null @@ -1,189 +0,0 @@ -/* 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 -#include "opus/opus_config.h" - -#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_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_SSE2) && !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_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) - -#define OVERRIDE_DUAL_INNER_PROD -#define OVERRIDE_COMB_FILTER_CONST - -#undef dual_inner_prod -#undef comb_filter_const - -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 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)) -#else - -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 -#endif - -#endif diff --git a/drivers/opus/celt/x86/pitch_sse2.c b/drivers/opus/celt/x86/pitch_sse2.c deleted file mode 100644 index b5a78b4acd..0000000000 --- a/drivers/opus/celt/x86/pitch_sse2.c +++ /dev/null @@ -1,92 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include <xmmintrin.h> -#include <emmintrin.h> - -#include "opus/silk/macros.h" -#include "opus/celt/celt_lpc.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/mathops.h" -#include "opus/celt/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 *)(&x[i + 0])); - inVec2_76543210 = _mm_loadu_si128((__m128i *)(&y[i + 0])); - - inVec1_FEDCBA98 = _mm_loadu_si128((__m128i *)(&x[i + 8])); - inVec2_FEDCBA98 = _mm_loadu_si128((__m128i *)(&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 *)(&x[i + 0])); - inVec2_76543210 = _mm_loadu_si128((__m128i *)(&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/drivers/opus/celt/x86/pitch_sse4_1.c b/drivers/opus/celt/x86/pitch_sse4_1.c deleted file mode 100644 index 57fb332210..0000000000 --- a/drivers/opus/celt/x86/pitch_sse4_1.c +++ /dev/null @@ -1,192 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include <xmmintrin.h> -#include <emmintrin.h> - -#include "opus/silk/macros.h" -#include "opus/celt/celt_lpc.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/mathops.h" -#include "opus/celt/pitch.h" - -#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT) -#include <smmintrin.h> -#include "opus/celt/x86/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 *)(&x[i + 0])); - inVec2_76543210 = _mm_loadu_si128((__m128i *)(&y[i + 0])); - - inVec1_FEDCBA98 = _mm_loadu_si128((__m128i *)(&x[i + 8])); - inVec2_FEDCBA98 = _mm_loadu_si128((__m128i *)(&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 *)(&x[i + 0])); - inVec2_76543210 = _mm_loadu_si128((__m128i *)(&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; - - 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 *)(&x[j + 0])); - vecY0 = _mm_loadu_si128((__m128i *)(&y[j + 0])); - vecY1 = _mm_loadu_si128((__m128i *)(&y[j + 1])); - vecY2 = _mm_loadu_si128((__m128i *)(&y[j + 2])); - vecY3 = _mm_loadu_si128((__m128i *)(&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); - } - - for (;j<len;j++) - { - vecX = OP_CVTEPI16_EPI32_M64(&x[j + 0]); - vecX0 = _mm_shuffle_epi32(vecX, 0x00); - - 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 *)(&sum[0])); - initSum = _mm_add_epi32(initSum, vecSum); - _mm_storeu_si128((__m128i *)sum, initSum); -} -#endif diff --git a/drivers/opus/celt/x86/x86_celt_map.c b/drivers/opus/celt/x86/x86_celt_map.c deleted file mode 100644 index 5146ea2b38..0000000000 --- a/drivers/opus/celt/x86/x86_celt_map.c +++ /dev/null @@ -1,152 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/celt/x86/x86cpu.h" -#include "opus/celt/celt_lpc.h" -#include "opus/celt/pitch.h" -#include "opus/celt/x86/pitch_sse.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, - opus_val16 *mem, - 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_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 - -#endif -#endif diff --git a/drivers/opus/celt/x86/x86cpu.c b/drivers/opus/celt/x86/x86cpu.c deleted file mode 100644 index 91b9b185c2..0000000000 --- a/drivers/opus/celt/x86/x86cpu.c +++ /dev/null @@ -1,154 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/celt/cpu_support.h" -#include "opus/silk/macros.h" -#include "opus/silk/main.h" -#include "opus/celt/pitch.h" -#include "opus/celt/x86/x86cpu.h" - -#if (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_AVX) && !defined(OPUS_X86_PRESUME_AVX)) - - -#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]) : - "0" (InfoType) - ); -#else - __asm__ __volatile__ ( - "cpuid": - "=a" (CPUInfo[0]), - "=b" (CPUInfo[1]), - "=c" (CPUInfo[2]), - "=d" (CPUInfo[3]) : - "0" (InfoType) - ); -#endif -#elif defined(CPU_INFO_BY_C) - __get_cpuid(InfoType, &(CPUInfo[0]), &(CPUInfo[1]), &(CPUInfo[2]), &(CPUInfo[3])); -#endif -} - -#endif - -typedef struct CPU_Feature{ - /* SIMD: 128-bit */ - int HW_SSE; - int HW_SSE2; - int HW_SSE41; - /* SIMD: 256-bit */ - int HW_AVX; -} CPU_Feature; - -static void opus_cpu_feature_check(CPU_Feature *cpu_feature) -{ - unsigned int info[4] = {0}; - 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_AVX = (info[2] & (1 << 28)) != 0; - } - else { - cpu_feature->HW_SSE = 0; - cpu_feature->HW_SSE2 = 0; - cpu_feature->HW_SSE41 = 0; - cpu_feature->HW_AVX = 0; - } -} - -int opus_select_arch(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_AVX) - { - return arch; - } - arch++; - - return arch; -} - -#endif diff --git a/drivers/opus/http.c b/drivers/opus/http.c deleted file mode 100644 index 602d514f6e..0000000000 --- a/drivers/opus/http.c +++ /dev/null @@ -1,3427 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/internal.h" -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <string.h> - -/*RFCs referenced in this file: - RFC 761: DOD Standard Transmission Control Protocol - RFC 1535: A Security Problem and Proposed Correction With Widely Deployed DNS - Software - RFC 1738: Uniform Resource Locators (URL) - RFC 1945: Hypertext Transfer Protocol -- HTTP/1.0 - RFC 2068: Hypertext Transfer Protocol -- HTTP/1.1 - RFC 2145: Use and Interpretation of HTTP Version Numbers - RFC 2246: The TLS Protocol Version 1.0 - RFC 2459: Internet X.509 Public Key Infrastructure Certificate and - Certificate Revocation List (CRL) Profile - RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1 - RFC 2617: HTTP Authentication: Basic and Digest Access Authentication - RFC 2817: Upgrading to TLS Within HTTP/1.1 - RFC 2818: HTTP Over TLS - RFC 3492: Punycode: A Bootstring encoding of Unicode for Internationalized - Domain Names in Applications (IDNA) - RFC 3986: Uniform Resource Identifier (URI): Generic Syntax - RFC 3987: Internationalized Resource Identifiers (IRIs) - RFC 4343: Domain Name System (DNS) Case Insensitivity Clarification - RFC 5894: Internationalized Domain Names for Applications (IDNA): - Background, Explanation, and Rationale - RFC 6066: Transport Layer Security (TLS) Extensions: Extension Definitions - RFC 6125: Representation and Verification of Domain-Based Application Service - Identity within Internet Public Key Infrastructure Using X.509 (PKIX) - Certificates in the Context of Transport Layer Security (TLS) - RFC 6555: Happy Eyeballs: Success with Dual-Stack Hosts*/ - -typedef struct OpusParsedURL OpusParsedURL; -typedef struct OpusStringBuf OpusStringBuf; -typedef struct OpusHTTPConn OpusHTTPConn; -typedef struct OpusHTTPStream OpusHTTPStream; - -static char *op_string_range_dup(const char *_start,const char *_end){ - size_t len; - char *ret; - OP_ASSERT(_start<=_end); - len=_end-_start; - /*This is to help avoid overflow elsewhere, later.*/ - if(OP_UNLIKELY(len>=INT_MAX))return NULL; - ret=(char *)_ogg_malloc(sizeof(*ret)*(len+1)); - if(OP_LIKELY(ret!=NULL)){ - ret=(char *)memcpy(ret,_start,sizeof(*ret)*(len)); - ret[len]='\0'; - } - return ret; -} - -static char *op_string_dup(const char *_s){ - return op_string_range_dup(_s,_s+strlen(_s)); -} - -static char *op_string_tolower(char *_s){ - int i; - for(i=0;_s[i]!='\0';i++){ - int c; - c=_s[i]; - if(c>='A'&&c<='Z')c+='a'-'A'; - _s[i]=(char)c; - } - return _s; -} - -/*URI character classes (from RFC 3986).*/ -#define OP_URL_ALPHA \ - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" -#define OP_URL_DIGIT "0123456789" -#define OP_URL_HEXDIGIT "0123456789ABCDEFabcdef" -/*Not a character class, but the characters allowed in <scheme>.*/ -#define OP_URL_SCHEME OP_URL_ALPHA OP_URL_DIGIT "+-." -#define OP_URL_GEN_DELIMS "#/:?@[]" -#define OP_URL_SUB_DELIMS "!$&'()*+,;=" -#define OP_URL_RESERVED OP_URL_GEN_DELIMS OP_URL_SUB_DELIMS -#define OP_URL_UNRESERVED OP_URL_ALPHA OP_URL_DIGIT "-._~" -/*Not a character class, but the characters allowed in <pct-encoded>.*/ -#define OP_URL_PCT_ENCODED "%" -/*Not a character class or production rule, but for convenience.*/ -#define OP_URL_PCHAR_BASE \ - OP_URL_UNRESERVED OP_URL_PCT_ENCODED OP_URL_SUB_DELIMS -#define OP_URL_PCHAR OP_URL_PCHAR_BASE ":@" -/*Not a character class, but the characters allowed in <userinfo> and - <IP-literal>.*/ -#define OP_URL_PCHAR_NA OP_URL_PCHAR_BASE ":" -/*Not a character class, but the characters allowed in <segment-nz-nc>.*/ -#define OP_URL_PCHAR_NC OP_URL_PCHAR_BASE "@" -/*Not a character clsss, but the characters allowed in <path>.*/ -#define OP_URL_PATH OP_URL_PCHAR "/" -/*Not a character class, but the characters allowed in <query> / <fragment>.*/ -#define OP_URL_QUERY_FRAG OP_URL_PCHAR "/?" - -/*Check the <% HEXDIG HEXDIG> escapes of a URL for validity. - Return: 0 if valid, or a negative value on failure.*/ -static int op_validate_url_escapes(const char *_s){ - int i; - for(i=0;_s[i];i++){ - if(_s[i]=='%'){ - if(OP_UNLIKELY(!isxdigit(_s[i+1])) - ||OP_UNLIKELY(!isxdigit(_s[i+2])) - /*RFC 3986 says %00 "should be rejected if the application is not - expecting to receive raw data within a component."*/ - ||OP_UNLIKELY(_s[i+1]=='0'&&_s[i+2]=='0')){ - return OP_FALSE; - } - i+=2; - } - } - return 0; -} - -/*Convert a hex digit to its actual value. - _c: The hex digit to convert. - Presumed to be valid ('0'...'9', 'A'...'F', or 'a'...'f'). - Return: The value of the digit, in the range [0,15].*/ -static int op_hex_value(int _c){ - return _c>='a'?_c-'a'+10:_c>='A'?_c-'A'+10:_c-'0'; -} - -/*Unescape all the <% HEXDIG HEXDIG> sequences in a string in-place. - This does no validity checking.*/ -static char *op_unescape_url_component(char *_s){ - int i; - int j; - for(i=j=0;_s[i];i++,j++){ - if(_s[i]=='%'){ - _s[i]=(char)(op_hex_value(_s[i+1])<<4|op_hex_value(_s[i+2])); - i+=2; - } - } - return _s; -} - -/*Parse a file: URL. - This code is not meant to be fast: strspn() with large sets is likely to be - slow, but it is very convenient. - It is meant to be RFC 1738-compliant (as updated by RFC 3986).*/ -static const char *op_parse_file_url(const char *_src){ - const char *scheme_end; - const char *path; - const char *path_end; - scheme_end=_src+strspn(_src,OP_URL_SCHEME); - if(OP_UNLIKELY(*scheme_end!=':') - ||scheme_end-_src!=4||op_strncasecmp(_src,"file",4)!=0){ - /*Unsupported protocol.*/ - return NULL; - } - /*Make sure all escape sequences are valid to simplify unescaping later.*/ - if(OP_UNLIKELY(op_validate_url_escapes(scheme_end+1)<0))return NULL; - if(scheme_end[1]=='/'&&scheme_end[2]=='/'){ - const char *host; - /*file: URLs can have a host! - Yeah, I was surprised, too, but that's what RFC 1738 says. - It also says, "The file URL scheme is unusual in that it does not specify - an Internet protocol or access method for such files; as such, its - utility in network protocols between hosts is limited," which is a mild - understatement.*/ - host=scheme_end+3; - /*The empty host is what we expect.*/ - if(OP_LIKELY(*host=='/'))path=host; - else{ - const char *host_end; - char host_buf[28]; - /*RFC 1738 says localhost "is interpreted as `the machine from which the - URL is being interpreted,'" so let's check for it.*/ - host_end=host+strspn(host,OP_URL_PCHAR_BASE); - /*No <port> allowed. - This also rejects IP-Literals.*/ - if(*host_end!='/')return NULL; - /*An escaped "localhost" can take at most 27 characters.*/ - if(OP_UNLIKELY(host_end-host>27))return NULL; - memcpy(host_buf,host,sizeof(*host_buf)*(host_end-host)); - host_buf[host_end-host]='\0'; - op_unescape_url_component(host_buf); - op_string_tolower(host_buf); - /*Some other host: give up.*/ - if(OP_UNLIKELY(strcmp(host_buf,"localhost")!=0))return NULL; - path=host_end; - } - } - else path=scheme_end+1; - path_end=path+strspn(path,OP_URL_PATH); - /*This will reject a <query> or <fragment> component, too. - I don't know what to do with queries, but a temporal fragment would at - least make sense. - RFC 1738 pretty clearly defines a <searchpart> that's equivalent to the - RFC 3986 <query> component for other schemes, but not the file: scheme, - so I'm going to just reject it.*/ - if(*path_end!='\0')return NULL; - return path; -} - -#if defined(OP_ENABLE_HTTP) -# if defined(_WIN32) -# include <winsock2.h> -# include <ws2tcpip.h> -# include <openssl/ssl.h> -# include "opus/winerrno.h" - -typedef SOCKET op_sock; - -# define OP_INVALID_SOCKET (INVALID_SOCKET) - -/*Vista and later support WSAPoll(), but we don't want to rely on that. - Instead we re-implement it badly using select(). - Unfortunately, they define a conflicting struct pollfd, so we only define our - own if it looks like that one has not already been defined.*/ -# if !defined(POLLIN) -/*Equivalent to POLLIN.*/ -# define POLLRDNORM (0x0100) -/*Priority band data can be read.*/ -# define POLLRDBAND (0x0200) -/*There is data to read.*/ -# define POLLIN (POLLRDNORM|POLLRDBAND) -/* There is urgent data to read.*/ -# define POLLPRI (0x0400) -/*Equivalent to POLLOUT.*/ -# define POLLWRNORM (0x0010) -/*Writing now will not block.*/ -# define POLLOUT (POLLWRNORM) -/*Priority data may be written.*/ -# define POLLWRBAND (0x0020) -/*Error condition (output only).*/ -# define POLLERR (0x0001) -/*Hang up (output only).*/ -# define POLLHUP (0x0002) -/*Invalid request: fd not open (output only).*/ -# define POLLNVAL (0x0004) - -struct pollfd{ - /*File descriptor.*/ - op_sock fd; - /*Requested events.*/ - short events; - /*Returned events.*/ - short revents; -}; -# endif - -/*But Winsock never defines nfds_t (it's simply hard-coded to ULONG).*/ -typedef unsigned long nfds_t; - -/*The usage of FD_SET() below is O(N^2). - This is okay because select() is limited to 64 sockets in Winsock, anyway. - In practice, we only ever call it with one or two sockets.*/ -static int op_poll_win32(struct pollfd *_fds,nfds_t _nfds,int _timeout){ - struct timeval tv; - fd_set ifds; - fd_set ofds; - fd_set efds; - nfds_t i; - int ret; - FD_ZERO(&ifds); - FD_ZERO(&ofds); - FD_ZERO(&efds); - for(i=0;i<_nfds;i++){ - _fds[i].revents=0; - if(_fds[i].events&POLLIN)FD_SET(_fds[i].fd,&ifds); - if(_fds[i].events&POLLOUT)FD_SET(_fds[i].fd,&ofds); - FD_SET(_fds[i].fd,&efds); - } - if(_timeout>=0){ - tv.tv_sec=_timeout/1000; - tv.tv_usec=(_timeout%1000)*1000; - } - ret=select(-1,&ifds,&ofds,&efds,_timeout<0?NULL:&tv); - if(ret>0){ - for(i=0;i<_nfds;i++){ - if(FD_ISSET(_fds[i].fd,&ifds))_fds[i].revents|=POLLIN; - if(FD_ISSET(_fds[i].fd,&ofds))_fds[i].revents|=POLLOUT; - /*This isn't correct: there are several different things that might have - happened to a fd in efds, but I don't know a good way to distinguish - them without more context from the caller. - It's okay, because we don't actually check any of these bits, we just - need _some_ bit set.*/ - if(FD_ISSET(_fds[i].fd,&efds))_fds[i].revents|=POLLHUP; - } - } - return ret; -} - -/*We define op_errno() to make it clear that it's not an l-value like normal - errno is.*/ -# define op_errno() (WSAGetLastError()?WSAGetLastError()-WSABASEERR:0) -# define op_reset_errno() (WSASetLastError(0)) - -/*The remaining functions don't get an op_ prefix even though they only - operate on sockets, because we don't use non-socket I/O here, and this - minimizes the changes needed to deal with Winsock.*/ -# define close(_fd) closesocket(_fd) -/*This relies on sizeof(u_long)==sizeof(int), which is always true on both - Win32 and Win64.*/ -# define ioctl(_fd,_req,_arg) ioctlsocket(_fd,_req,(u_long *)(_arg)) -# define getsockopt(_fd,_level,_name,_val,_len) \ - getsockopt(_fd,_level,_name,(char *)(_val),_len) -# define setsockopt(_fd,_level,_name,_val,_len) \ - setsockopt(_fd,_level,_name,(const char *)(_val),_len) -# define poll(_fds,_nfds,_timeout) op_poll_win32(_fds,_nfds,_timeout) - -# if defined(_MSC_VER) -typedef ptrdiff_t ssize_t; -# endif - -/*Load certificates from the built-in certificate store.*/ -int SSL_CTX_set_default_verify_paths_win32(SSL_CTX *_ssl_ctx); -# define SSL_CTX_set_default_verify_paths \ - SSL_CTX_set_default_verify_paths_win32 - -# else -/*Normal Berkeley sockets.*/ -# include <sys/ioctl.h> -# include <sys/types.h> -# include <sys/socket.h> -# include <arpa/inet.h> -# include <netinet/in.h> -# include <netinet/tcp.h> -# include <fcntl.h> -# include <netdb.h> -# include <poll.h> -# include <unistd.h> -# include <openssl/ssl.h> - -typedef int op_sock; - -# define OP_INVALID_SOCKET (-1) - -# define op_errno() (errno) -# define op_reset_errno() (errno=0) - -# endif -# include <sys/timeb.h> -# include <openssl/x509v3.h> - -/*The maximum number of simultaneous connections. - RFC 2616 says this SHOULD NOT be more than 2, but everyone on the modern web - ignores that (e.g., IE 8 bumped theirs up from 2 to 6, Firefox uses 15). - If it makes you feel better, we'll only ever actively read from one of these - at a time. - The others are kept around mainly to avoid slow-starting a new connection - when seeking, and time out rapidly.*/ -# define OP_NCONNS_MAX (4) - -/*The amount of time before we attempt to re-resolve the host. - This is 10 minutes, as recommended in RFC 6555 for expiring cached connection - results for dual-stack hosts.*/ -# define OP_RESOLVE_CACHE_TIMEOUT_MS (10*60*(opus_int32)1000) - -/*The number of redirections at which we give up. - The value here is the current default in Firefox. - RFC 2068 mandated a maximum of 5, but RFC 2616 relaxed that to "a client - SHOULD detect infinite redirection loops." - Fortunately, 20 is less than infinity.*/ -# define OP_REDIRECT_LIMIT (20) - -/*The initial size of the buffer used to read a response message (before the - body).*/ -# define OP_RESPONSE_SIZE_MIN (510) -/*The maximum size of a response message (before the body). - Responses larger than this will be discarded. - I've seen a real server return 20 kB of data for a 302 Found response. - Increasing this beyond 32kB will cause problems on platforms with a 16-bit - int.*/ -# define OP_RESPONSE_SIZE_MAX (32766) - -/*The number of milliseconds we will allow a connection to sit idle before we - refuse to resurrect it. - Apache as of 2.2 has reduced its default timeout to 5 seconds (from 15), so - that's what we'll use here.*/ -# define OP_CONNECTION_IDLE_TIMEOUT_MS (5*1000) - -/*The number of milliseconds we will wait to send or receive data before giving - up.*/ -# define OP_POLL_TIMEOUT_MS (30*1000) - -/*We will always attempt to read ahead at least this much in preference to - opening a new connection.*/ -# define OP_READAHEAD_THRESH_MIN (32*(opus_int32)1024) - -/*The amount of data to request after a seek. - This is a trade-off between read throughput after a seek vs. the the ability - to quickly perform another seek with the same connection.*/ -# define OP_PIPELINE_CHUNK_SIZE (32*(opus_int32)1024) -/*Subsequent chunks are requested with larger and larger sizes until they pass - this threshold, after which we just ask for the rest of the resource.*/ -# define OP_PIPELINE_CHUNK_SIZE_MAX (1024*(opus_int32)1024) -/*This is the maximum number of requests we'll make with a single connection. - Many servers will simply disconnect after we attempt some number of requests, - possibly without sending a Connection: close header, meaning we won't - discover it until we try to read beyond the end of the current chunk. - We can reconnect when that happens, but this is slow. - Instead, we impose a limit ourselves (set to the default for Apache - installations and thus likely the most common value in use).*/ -# define OP_PIPELINE_MAX_REQUESTS (100) -/*This should be the number of requests, starting from a chunk size of - OP_PIPELINE_CHUNK_SIZE and doubling each time, until we exceed - OP_PIPELINE_CHUNK_SIZE_MAX and just request the rest of the file. - We won't reuse a connection when seeking unless it has at least this many - requests left, to reduce the chances we'll have to open a new connection - while reading forward afterwards.*/ -# define OP_PIPELINE_MIN_REQUESTS (7) - -/*Is this an https URL? - For now we can simply check the last letter of the scheme.*/ -# define OP_URL_IS_SSL(_url) ((_url)->scheme[4]=='s') - -/*Does this URL use the default port for its scheme?*/ -# define OP_URL_IS_DEFAULT_PORT(_url) \ - (!OP_URL_IS_SSL(_url)&&(_url)->port==80 \ - ||OP_URL_IS_SSL(_url)&&(_url)->port==443) - -struct OpusParsedURL{ - /*Either "http" or "https".*/ - char *scheme; - /*The user name from the <userinfo> component, or NULL.*/ - char *user; - /*The password from the <userinfo> component, or NULL.*/ - char *pass; - /*The <host> component. - This may not be NULL.*/ - char *host; - /*The <path> and <query> components. - This may not be NULL.*/ - char *path; - /*The <port> component. - This is set to the default port if the URL did not contain one.*/ - unsigned port; -}; - -/*Parse a URL. - This code is not meant to be fast: strspn() with large sets is likely to be - slow, but it is very convenient. - It is meant to be RFC 3986-compliant. - We currently do not support IRIs (Internationalized Resource Identifiers, - RFC 3987). - Callers should translate them to URIs first.*/ -static int op_parse_url_impl(OpusParsedURL *_dst,const char *_src){ - const char *scheme_end; - const char *authority; - const char *userinfo_end; - const char *user; - const char *user_end; - const char *pass; - const char *hostport; - const char *hostport_end; - const char *host_end; - const char *port; - opus_int32 port_num; - const char *port_end; - const char *path; - const char *path_end; - const char *uri_end; - scheme_end=_src+strspn(_src,OP_URL_SCHEME); - if(OP_UNLIKELY(*scheme_end!=':') - ||OP_UNLIKELY(scheme_end-_src<4)||OP_UNLIKELY(scheme_end-_src>5) - ||OP_UNLIKELY(op_strncasecmp(_src,"https",scheme_end-_src)!=0)){ - /*Unsupported protocol.*/ - return OP_EIMPL; - } - if(OP_UNLIKELY(scheme_end[1]!='/')||OP_UNLIKELY(scheme_end[2]!='/')){ - /*We require an <authority> component.*/ - return OP_EINVAL; - } - authority=scheme_end+3; - /*Make sure all escape sequences are valid to simplify unescaping later.*/ - if(OP_UNLIKELY(op_validate_url_escapes(authority)<0))return OP_EINVAL; - /*Look for a <userinfo> component.*/ - userinfo_end=authority+strspn(authority,OP_URL_PCHAR_NA); - if(*userinfo_end=='@'){ - /*Found one.*/ - user=authority; - /*Look for a password (yes, clear-text passwords are deprecated, I know, - but what else are people supposed to use? use SSL if you care).*/ - user_end=authority+strspn(authority,OP_URL_PCHAR_BASE); - if(*user_end==':')pass=user_end+1; - else pass=NULL; - hostport=userinfo_end+1; - } - else{ - /*We shouldn't have to initialize user_end, but gcc is too dumb to figure - out that user!=NULL below means we didn't take this else branch.*/ - user=user_end=NULL; - pass=NULL; - hostport=authority; - } - /*Try to figure out where the <host> component ends.*/ - if(hostport[0]=='['){ - hostport++; - /*We have an <IP-literal>, which can contain colons.*/ - hostport_end=host_end=hostport+strspn(hostport,OP_URL_PCHAR_NA); - if(OP_UNLIKELY(*hostport_end++!=']'))return OP_EINVAL; - } - /*Currently we don't support IDNA (RFC 5894), because I don't want to deal - with the policy about which domains should not be internationalized to - avoid confusing similarities. - Give this API Punycode (RFC 3492) domain names instead.*/ - else hostport_end=host_end=hostport+strspn(hostport,OP_URL_PCHAR_BASE); - /*TODO: Validate host.*/ - /*Is there a port number?*/ - port_num=-1; - if(*hostport_end==':'){ - int i; - port=hostport_end+1; - port_end=port+strspn(port,OP_URL_DIGIT); - path=port_end; - /*Not part of RFC 3986, but require port numbers in the range 0...65535.*/ - if(OP_LIKELY(port_end-port>0)){ - while(*port=='0')port++; - if(OP_UNLIKELY(port_end-port>5))return OP_EINVAL; - port_num=0; - for(i=0;i<port_end-port;i++)port_num=port_num*10+port[i]-'0'; - if(OP_UNLIKELY(port_num>65535))return OP_EINVAL; - } - } - else path=hostport_end; - path_end=path+strspn(path,OP_URL_PATH); - /*If the path is not empty, it must begin with a '/'.*/ - if(OP_LIKELY(path_end>path)&&OP_UNLIKELY(path[0]!='/'))return OP_EINVAL; - /*Consume the <query> component, if any (right now we don't split this out - from the <path> component).*/ - if(*path_end=='?')path_end=path_end+strspn(path_end,OP_URL_QUERY_FRAG); - /*Discard the <fragment> component, if any. - This doesn't get sent to the server. - Some day we should add support for Media Fragment URIs - <http://www.w3.org/TR/media-frags/>.*/ - if(*path_end=='#')uri_end=path_end+1+strspn(path_end+1,OP_URL_QUERY_FRAG); - else uri_end=path_end; - /*If there's anything left, this was not a valid URL.*/ - if(OP_UNLIKELY(*uri_end!='\0'))return OP_EINVAL; - _dst->scheme=op_string_range_dup(_src,scheme_end); - if(OP_UNLIKELY(_dst->scheme==NULL))return OP_EFAULT; - op_string_tolower(_dst->scheme); - if(user!=NULL){ - _dst->user=op_string_range_dup(user,user_end); - if(OP_UNLIKELY(_dst->user==NULL))return OP_EFAULT; - op_unescape_url_component(_dst->user); - /*Unescaping might have created a ':' in the username. - That's not allowed by RFC 2617's Basic Authentication Scheme.*/ - if(OP_UNLIKELY(strchr(_dst->user,':')!=NULL))return OP_EINVAL; - } - else _dst->user=NULL; - if(pass!=NULL){ - _dst->pass=op_string_range_dup(pass,userinfo_end); - if(OP_UNLIKELY(_dst->pass==NULL))return OP_EFAULT; - op_unescape_url_component(_dst->pass); - } - else _dst->pass=NULL; - _dst->host=op_string_range_dup(hostport,host_end); - if(OP_UNLIKELY(_dst->host==NULL))return OP_EFAULT; - if(port_num<0){ - if(_src[4]=='s')port_num=443; - else port_num=80; - } - _dst->port=(unsigned)port_num; - /*RFC 2616 says an empty <abs-path> component is equivalent to "/", and we - MUST use the latter in the Request-URI. - Reserve space for the slash here.*/ - if(path==path_end||path[0]=='?')path--; - _dst->path=op_string_range_dup(path,path_end); - if(OP_UNLIKELY(_dst->path==NULL))return OP_EFAULT; - /*And force-set it here.*/ - _dst->path[0]='/'; - return 0; -} - -static void op_parsed_url_init(OpusParsedURL *_url){ - memset(_url,0,sizeof(*_url)); -} - -static void op_parsed_url_clear(OpusParsedURL *_url){ - _ogg_free(_url->scheme); - _ogg_free(_url->user); - _ogg_free(_url->pass); - _ogg_free(_url->host); - _ogg_free(_url->path); -} - -static int op_parse_url(OpusParsedURL *_dst,const char *_src){ - OpusParsedURL url; - int ret; - op_parsed_url_init(&url); - ret=op_parse_url_impl(&url,_src); - if(OP_UNLIKELY(ret<0))op_parsed_url_clear(&url); - else *_dst=*&url; - return ret; -} - -/*A buffer to hold growing strings. - The main purpose of this is to consolidate allocation checks and simplify - cleanup on a failed allocation.*/ -struct OpusStringBuf{ - char *buf; - int nbuf; - int cbuf; -}; - -static void op_sb_init(OpusStringBuf *_sb){ - _sb->buf=NULL; - _sb->nbuf=0; - _sb->cbuf=0; -} - -static void op_sb_clear(OpusStringBuf *_sb){ - _ogg_free(_sb->buf); -} - -/*Make sure we have room for at least _capacity characters (plus 1 more for the - terminating NUL).*/ -static int op_sb_ensure_capacity(OpusStringBuf *_sb,int _capacity){ - char *buf; - int cbuf; - buf=_sb->buf; - cbuf=_sb->cbuf; - if(_capacity>=cbuf-1){ - if(OP_UNLIKELY(cbuf>INT_MAX-1>>1))return OP_EFAULT; - if(OP_UNLIKELY(_capacity>=INT_MAX-1))return OP_EFAULT; - cbuf=OP_MAX(2*cbuf+1,_capacity+1); - buf=_ogg_realloc(buf,sizeof(*buf)*cbuf); - if(OP_UNLIKELY(buf==NULL))return OP_EFAULT; - _sb->buf=buf; - _sb->cbuf=cbuf; - } - return 0; -} - -/*Increase the capacity of the buffer, but not to more than _max_size - characters (plus 1 more for the terminating NUL).*/ -static int op_sb_grow(OpusStringBuf *_sb,int _max_size){ - char *buf; - int cbuf; - buf=_sb->buf; - cbuf=_sb->cbuf; - OP_ASSERT(_max_size<=INT_MAX-1); - cbuf=cbuf<=_max_size-1>>1?2*cbuf+1:_max_size+1; - buf=_ogg_realloc(buf,sizeof(*buf)*cbuf); - if(OP_UNLIKELY(buf==NULL))return OP_EFAULT; - _sb->buf=buf; - _sb->cbuf=cbuf; - return 0; -} - -static int op_sb_append(OpusStringBuf *_sb,const char *_s,int _len){ - char *buf; - int nbuf; - int ret; - nbuf=_sb->nbuf; - if(OP_UNLIKELY(nbuf>INT_MAX-_len))return OP_EFAULT; - ret=op_sb_ensure_capacity(_sb,nbuf+_len); - if(OP_UNLIKELY(ret<0))return ret; - buf=_sb->buf; - memcpy(buf+nbuf,_s,sizeof(*buf)*_len); - nbuf+=_len; - buf[nbuf]='\0'; - _sb->nbuf=nbuf; - return 0; -} - -static int op_sb_append_string(OpusStringBuf *_sb,const char *_s){ - return op_sb_append(_sb,_s,strlen(_s)); -} - -static int op_sb_append_port(OpusStringBuf *_sb,unsigned _port){ - char port_buf[7]; - OP_ASSERT(_port<=65535U); - sprintf(port_buf,":%u",_port); - return op_sb_append_string(_sb,port_buf); -} - -static int op_sb_append_nonnegative_int64(OpusStringBuf *_sb,opus_int64 _i){ - char digit; - int nbuf_start; - int ret; - OP_ASSERT(_i>=0); - nbuf_start=_sb->nbuf; - ret=0; - do{ - digit='0'+_i%10; - ret|=op_sb_append(_sb,&digit,1); - _i/=10; - } - while(_i>0); - if(OP_LIKELY(ret>=0)){ - char *buf; - int nbuf_end; - buf=_sb->buf; - nbuf_end=_sb->nbuf-1; - /*We've added the digits backwards. - Reverse them.*/ - while(nbuf_start<nbuf_end){ - digit=buf[nbuf_start]; - buf[nbuf_start]=buf[nbuf_end]; - buf[nbuf_end]=digit; - nbuf_start++; - nbuf_end--; - } - } - return ret; -} - -static struct addrinfo *op_resolve(const char *_host,unsigned _port){ - struct addrinfo *addrs; - struct addrinfo hints; - char service[6]; - memset(&hints,0,sizeof(hints)); - hints.ai_socktype=SOCK_STREAM; -#if defined(AI_NUMERICSERV) - hints.ai_flags=AI_NUMERICSERV; -#endif - OP_ASSERT(_port<=65535U); - sprintf(service,"%u",_port); - if(OP_LIKELY(!getaddrinfo(_host,service,&hints,&addrs)))return addrs; - return NULL; -} - -static int op_sock_set_nonblocking(op_sock _fd,int _nonblocking){ -#if !defined(_WIN32) - int flags; - flags=fcntl(_fd,F_GETFL); - if(OP_UNLIKELY(flags<0))return flags; - if(_nonblocking)flags|=O_NONBLOCK; - else flags&=~O_NONBLOCK; - return fcntl(_fd,F_SETFL,flags); -#else - return ioctl(_fd,FIONBIO,&_nonblocking); -#endif -} - -/*Disable/enable write coalescing if we can. - We always send whole requests at once and always parse the response headers - before sending another one, so normally write coalescing just causes added - delay.*/ -static void op_sock_set_tcp_nodelay(op_sock _fd,int _nodelay){ -# if defined(TCP_NODELAY)&&(defined(IPPROTO_TCP)||defined(SOL_TCP)) -# if defined(IPPROTO_TCP) -# define OP_SO_LEVEL IPPROTO_TCP -# else -# define OP_SO_LEVEL SOL_TCP -# endif - /*It doesn't really matter if this call fails, but it would be interesting - to hit a case where it does.*/ - OP_ALWAYS_TRUE(!setsockopt(_fd,OP_SO_LEVEL,TCP_NODELAY, - &_nodelay,sizeof(_nodelay))); -# endif -} - -#if defined(_WIN32) -static void op_init_winsock(){ - static LONG count; - static WSADATA wsadata; - if(InterlockedIncrement(&count)==1)WSAStartup(0x0202,&wsadata); -} -#endif - -/*A single physical connection to an HTTP server. - We may have several of these open at once.*/ -struct OpusHTTPConn{ - /*The current position indicator for this connection.*/ - opus_int64 pos; - /*The position where the current request will end, or -1 if we're reading - until EOF (an unseekable stream or the initial HTTP/1.0 request).*/ - opus_int64 end_pos; - /*The position where next request we've sent will start, or -1 if we haven't - sent the next request yet.*/ - opus_int64 next_pos; - /*The end of the next request or -1 if we requested the rest of the resource. - This is only set to a meaningful value if next_pos is not -1.*/ - opus_int64 next_end; - /*The SSL connection, if this is https.*/ - SSL *ssl_conn; - /*The next connection in either the LRU or free list.*/ - OpusHTTPConn *next; - /*The last time we blocked for reading from this connection.*/ - struct timeb read_time; - /*The number of bytes we've read since the last time we blocked.*/ - opus_int64 read_bytes; - /*The estimated throughput of this connection, in bytes/s.*/ - opus_int64 read_rate; - /*The socket we're reading from.*/ - op_sock fd; - /*The number of remaining requests we are allowed on this connection.*/ - int nrequests_left; - /*The chunk size to use for pipelining requests.*/ - opus_int32 chunk_size; -}; - -static void op_http_conn_init(OpusHTTPConn *_conn){ - _conn->next_pos=-1; - _conn->ssl_conn=NULL; - _conn->next=NULL; - _conn->fd=OP_INVALID_SOCKET; -} - -static void op_http_conn_clear(OpusHTTPConn *_conn){ - if(_conn->ssl_conn!=NULL)SSL_free(_conn->ssl_conn); - /*SSL frees the BIO for us.*/ - if(_conn->fd!=OP_INVALID_SOCKET)close(_conn->fd); -} - -/*The global stream state.*/ -struct OpusHTTPStream{ - /*The list of connections.*/ - OpusHTTPConn conns[OP_NCONNS_MAX]; - /*The context object used as a framework for TLS/SSL functions.*/ - SSL_CTX *ssl_ctx; - /*The cached session to reuse for future connections.*/ - SSL_SESSION *ssl_session; - /*The LRU list (ordered from MRU to LRU) of currently connected - connections.*/ - OpusHTTPConn *lru_head; - /*The free list.*/ - OpusHTTPConn *free_head; - /*The URL to connect to.*/ - OpusParsedURL url; - /*Information about the address we connected to.*/ - struct addrinfo addr_info; - /*The address we connected to.*/ - union{ - struct sockaddr s; - struct sockaddr_in v4; - struct sockaddr_in6 v6; - } addr; - /*The last time we re-resolved the host.*/ - struct timeb resolve_time; - /*A buffer used to build HTTP requests.*/ - OpusStringBuf request; - /*A buffer used to build proxy CONNECT requests.*/ - OpusStringBuf proxy_connect; - /*A buffer used to receive the response headers.*/ - OpusStringBuf response; - /*The Content-Length, if specified, or -1 otherwise. - This will always be specified for seekable streams.*/ - opus_int64 content_length; - /*The position indicator used when no connection is active.*/ - opus_int64 pos; - /*The host we actually connected to.*/ - char *connect_host; - /*The port we actually connected to.*/ - unsigned connect_port; - /*The connection we're currently reading from. - This can be -1 if no connection is active.*/ - int cur_conni; - /*Whether or not the server supports range requests.*/ - int seekable; - /*Whether or not the server supports HTTP/1.1 with persistent connections.*/ - int pipeline; - /*Whether or not we should skip certificate checks.*/ - int skip_certificate_check; - /*The offset of the tail of the request. - Only the offset in the Range: header appears after this, allowing us to - quickly edit the request to ask for a new range.*/ - int request_tail; - /*The estimated time required to open a new connection, in milliseconds.*/ - opus_int32 connect_rate; -}; - -static void op_http_stream_init(OpusHTTPStream *_stream){ - OpusHTTPConn **pnext; - int ci; - pnext=&_stream->free_head; - for(ci=0;ci<OP_NCONNS_MAX;ci++){ - op_http_conn_init(_stream->conns+ci); - *pnext=_stream->conns+ci; - pnext=&_stream->conns[ci].next; - } - _stream->ssl_ctx=NULL; - _stream->ssl_session=NULL; - _stream->lru_head=NULL; - op_parsed_url_init(&_stream->url); - op_sb_init(&_stream->request); - op_sb_init(&_stream->proxy_connect); - op_sb_init(&_stream->response); - _stream->connect_host=NULL; - _stream->seekable=0; -} - -/*Close the connection and move it to the free list. - _stream: The stream containing the free list. - _conn: The connection to close. - _penxt: The linked-list pointer currently pointing to this connection. - _gracefully: Whether or not to shut down cleanly.*/ -static void op_http_conn_close(OpusHTTPStream *_stream,OpusHTTPConn *_conn, - OpusHTTPConn **_pnext,int _gracefully){ - /*If we don't shut down gracefully, the server MUST NOT re-use our session - according to RFC 2246, because it can't tell the difference between an - abrupt close and a truncation attack. - So we shut down gracefully if we can. - However, we will not wait if this would block (it's not worth the savings - from session resumption to do so). - Clients (that's us) MAY resume a TLS session that ended with an incomplete - close, according to RFC 2818, so there's no reason to make sure the server - shut things down gracefully.*/ - if(_gracefully&&_conn->ssl_conn!=NULL)SSL_shutdown(_conn->ssl_conn); - op_http_conn_clear(_conn); - _conn->next_pos=-1; - _conn->ssl_conn=NULL; - _conn->fd=OP_INVALID_SOCKET; - OP_ASSERT(*_pnext==_conn); - *_pnext=_conn->next; - _conn->next=_stream->free_head; - _stream->free_head=_conn; -} - -static void op_http_stream_clear(OpusHTTPStream *_stream){ - while(_stream->lru_head!=NULL){ - op_http_conn_close(_stream,_stream->lru_head,&_stream->lru_head,0); - } - if(_stream->ssl_session!=NULL)SSL_SESSION_free(_stream->ssl_session); - if(_stream->ssl_ctx!=NULL)SSL_CTX_free(_stream->ssl_ctx); - op_sb_clear(&_stream->response); - op_sb_clear(&_stream->proxy_connect); - op_sb_clear(&_stream->request); - if(_stream->connect_host!=_stream->url.host)_ogg_free(_stream->connect_host); - op_parsed_url_clear(&_stream->url); -} - -static int op_http_conn_write_fully(OpusHTTPConn *_conn, - const char *_buf,int _buf_size){ - struct pollfd fd; - SSL *ssl_conn; - fd.fd=_conn->fd; - ssl_conn=_conn->ssl_conn; - while(_buf_size>0){ - int err; - if(ssl_conn!=NULL){ - int ret; - ret=SSL_write(ssl_conn,_buf,_buf_size); - if(ret>0){ - /*Wrote some data.*/ - _buf+=ret; - _buf_size-=ret; - continue; - } - /*Connection closed.*/ - else if(ret==0)return OP_FALSE; - err=SSL_get_error(ssl_conn,ret); - /*Yes, renegotiations can cause SSL_write() to block for reading.*/ - if(err==SSL_ERROR_WANT_READ)fd.events=POLLIN; - else if(err==SSL_ERROR_WANT_WRITE)fd.events=POLLOUT; - else return OP_FALSE; - } - else{ - ssize_t ret; - op_reset_errno(); - ret=send(fd.fd,_buf,_buf_size,0); - if(ret>0){ - _buf+=ret; - _buf_size-=ret; - continue; - } - err=op_errno(); - if(err!=EAGAIN&&err!=EWOULDBLOCK)return OP_FALSE; - fd.events=POLLOUT; - } - if(poll(&fd,1,OP_POLL_TIMEOUT_MS)<=0)return OP_FALSE; - } - return 0; -} - -static int op_http_conn_estimate_available(OpusHTTPConn *_conn){ - int available; - int ret; - ret=ioctl(_conn->fd,FIONREAD,&available); - if(ret<0)available=0; - /*This requires the SSL read_ahead flag to be unset to work. - We ignore partial records as well as the protocol overhead for any pending - bytes. - This means we might return somewhat less than can truly be read without - blocking (if there's a partial record). - This is okay, because we're using this value to estimate network transfer - time, and we _have_ already received those bytes. - We also might return slightly more (due to protocol overhead), but that's - small enough that it probably doesn't matter.*/ - if(_conn->ssl_conn!=NULL)available+=SSL_pending(_conn->ssl_conn); - return available; -} - -static opus_int32 op_time_diff_ms(const struct timeb *_end, - const struct timeb *_start){ - opus_int64 dtime; - dtime=_end->time-(opus_int64)_start->time; - OP_ASSERT(_end->millitm<1000); - OP_ASSERT(_start->millitm<1000); - if(OP_UNLIKELY(dtime>(OP_INT32_MAX-1000)/1000))return OP_INT32_MAX; - if(OP_UNLIKELY(dtime<(OP_INT32_MIN+1000)/1000))return OP_INT32_MIN; - return (opus_int32)dtime*1000+_end->millitm-_start->millitm; -} - -/*Update the read rate estimate for this connection.*/ -static void op_http_conn_read_rate_update(OpusHTTPConn *_conn){ - struct timeb read_time; - opus_int32 read_delta_ms; - opus_int64 read_delta_bytes; - opus_int64 read_rate; - read_delta_bytes=_conn->read_bytes; - if(read_delta_bytes<=0)return; - ftime(&read_time); - read_delta_ms=op_time_diff_ms(&read_time,&_conn->read_time); - read_rate=_conn->read_rate; - read_delta_ms=OP_MAX(read_delta_ms,1); - read_rate+=read_delta_bytes*1000/read_delta_ms-read_rate+4>>3; - *&_conn->read_time=*&read_time; - _conn->read_bytes=0; - _conn->read_rate=read_rate; -} - -/*Tries to read from the given connection. - [out] _buf: Returns the data read. - _buf_size: The size of the buffer. - _blocking: Whether or not to block until some data is retrieved. - Return: A positive number of bytes read on success. - 0: The read would block, or the connection was closed. - OP_EREAD: There was a fatal read error.*/ -static int op_http_conn_read(OpusHTTPConn *_conn, - char *_buf,int _buf_size,int _blocking){ - struct pollfd fd; - SSL *ssl_conn; - int nread; - int nread_unblocked; - fd.fd=_conn->fd; - ssl_conn=_conn->ssl_conn; - nread=nread_unblocked=0; - /*RFC 2818 says "client implementations MUST treat any premature closes as - errors and the data received as potentially truncated," so we make very - sure to report read errors upwards.*/ - do{ - int err; - if(ssl_conn!=NULL){ - int ret; - ret=SSL_read(ssl_conn,_buf+nread,_buf_size-nread); - OP_ASSERT(ret<=_buf_size-nread); - if(ret>0){ - /*Read some data. - Keep going to see if there's more.*/ - nread+=ret; - nread_unblocked+=ret; - continue; - } - /*If we already read some data, return it right now.*/ - if(nread>0)break; - err=SSL_get_error(ssl_conn,ret); - if(ret==0){ - /*Connection close. - Check for a clean shutdown to prevent truncation attacks. - This check always succeeds for SSLv2, as it has no "close notify" - message and thus can't verify an orderly shutdown.*/ - return err==SSL_ERROR_ZERO_RETURN?0:OP_EREAD; - } - if(err==SSL_ERROR_WANT_READ)fd.events=POLLIN; - /*Yes, renegotiations can cause SSL_read() to block for writing.*/ - else if(err==SSL_ERROR_WANT_WRITE)fd.events=POLLOUT; - /*Some other error.*/ - else return OP_EREAD; - } - else{ - ssize_t ret; - op_reset_errno(); - ret=recv(fd.fd,_buf+nread,_buf_size-nread,0); - OP_ASSERT(ret<=_buf_size-nread); - if(ret>0){ - /*Read some data. - Keep going to see if there's more.*/ - nread+=ret; - nread_unblocked+=ret; - continue; - } - /*If we already read some data or the connection was closed, return - right now.*/ - if(ret==0||nread>0)break; - err=op_errno(); - if(err!=EAGAIN&&err!=EWOULDBLOCK)return OP_EREAD; - fd.events=POLLIN; - } - _conn->read_bytes+=nread_unblocked; - op_http_conn_read_rate_update(_conn); - nread_unblocked=0; - if(!_blocking)break; - /*Need to wait to get any data at all.*/ - if(poll(&fd,1,OP_POLL_TIMEOUT_MS)<=0)return OP_EREAD; - } - while(nread<_buf_size); - _conn->read_bytes+=nread_unblocked; - return nread; -} - -/*Tries to look at the pending data for a connection without consuming it. - [out] _buf: Returns the data at which we're peeking. - _buf_size: The size of the buffer.*/ -static int op_http_conn_peek(OpusHTTPConn *_conn,char *_buf,int _buf_size){ - struct pollfd fd; - SSL *ssl_conn; - int ret; - fd.fd=_conn->fd; - ssl_conn=_conn->ssl_conn; - for(;;){ - int err; - if(ssl_conn!=NULL){ - ret=SSL_peek(ssl_conn,_buf,_buf_size); - /*Either saw some data or the connection was closed.*/ - if(ret>=0)return ret; - err=SSL_get_error(ssl_conn,ret); - if(err==SSL_ERROR_WANT_READ)fd.events=POLLIN; - /*Yes, renegotiations can cause SSL_peek() to block for writing.*/ - else if(err==SSL_ERROR_WANT_WRITE)fd.events=POLLOUT; - else return 0; - } - else{ - op_reset_errno(); - ret=(int)recv(fd.fd,_buf,_buf_size,MSG_PEEK); - /*Either saw some data or the connection was closed.*/ - if(ret>=0)return ret; - err=op_errno(); - if(err!=EAGAIN&&err!=EWOULDBLOCK)return 0; - fd.events=POLLIN; - } - /*Need to wait to get any data at all.*/ - if(poll(&fd,1,OP_POLL_TIMEOUT_MS)<=0)return 0; - } -} - -/*When parsing response headers, RFC 2616 mandates that all lines end in CR LF. - However, even in the year 2012, I have seen broken servers use just a LF. - This is the evil that Postel's advice from RFC 761 breeds.*/ - -/*Reads the entirety of a response to an HTTP request into the response buffer. - Actual parsing and validation is done later. - Return: The number of bytes in the response on success, OP_EREAD if the - connection was closed before reading any data, or another negative - value on any other error.*/ -static int op_http_conn_read_response(OpusHTTPConn *_conn, - OpusStringBuf *_response){ - int ret; - _response->nbuf=0; - ret=op_sb_ensure_capacity(_response,OP_RESPONSE_SIZE_MIN); - if(OP_UNLIKELY(ret<0))return ret; - for(;;){ - char *buf; - int size; - int capacity; - int read_limit; - int terminated; - size=_response->nbuf; - capacity=_response->cbuf-1; - if(OP_UNLIKELY(size>=capacity)){ - ret=op_sb_grow(_response,OP_RESPONSE_SIZE_MAX); - if(OP_UNLIKELY(ret<0))return ret; - capacity=_response->cbuf-1; - /*The response was too large. - This prevents a bad server from running us out of memory.*/ - if(OP_UNLIKELY(size>=capacity))return OP_EIMPL; - } - buf=_response->buf; - ret=op_http_conn_peek(_conn,buf+size,capacity-size); - if(OP_UNLIKELY(ret<=0))return size<=0?OP_EREAD:OP_FALSE; - /*We read some data.*/ - /*Make sure the starting characters are "HTTP". - Otherwise we could wind up waiting forever for a response from - something that is not an HTTP server.*/ - if(size<4&&op_strncasecmp(buf,"HTTP",OP_MIN(size+ret,4))!=0){ - return OP_FALSE; - } - /*How far can we read without passing the "\r\n\r\n" terminator?*/ - buf[size+ret]='\0'; - terminated=0; - for(read_limit=OP_MAX(size-3,0);read_limit<size+ret;read_limit++){ - /*We don't look for the leading '\r' thanks to broken servers.*/ - if(buf[read_limit]=='\n'){ - if(buf[read_limit+1]=='\r'&&OP_LIKELY(buf[read_limit+2]=='\n')){ - terminated=3; - break; - } - /*This case is for broken servers.*/ - else if(OP_UNLIKELY(buf[read_limit+1]=='\n')){ - terminated=2; - break; - } - } - } - read_limit+=terminated; - OP_ASSERT(size<=read_limit); - OP_ASSERT(read_limit<=size+ret); - /*Actually consume that data.*/ - ret=op_http_conn_read(_conn,buf+size,read_limit-size,1); - if(OP_UNLIKELY(ret<=0))return OP_FALSE; - size+=ret; - buf[size]='\0'; - _response->nbuf=size; - /*We found the terminator and read all the data up to and including it.*/ - if(terminated&&OP_LIKELY(size>=read_limit))return size; - } - return OP_EIMPL; -} - -# define OP_HTTP_DIGIT "0123456789" - -/*The Reason-Phrase is not allowed to contain control characters, except - horizontal tab (HT: \011).*/ -# define OP_HTTP_CREASON_PHRASE \ - "\001\002\003\004\005\006\007\010\012\013\014\015\016\017\020\021" \ - "\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177" - -# define OP_HTTP_CTLS \ - "\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020" \ - "\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177" - -/*This also includes '\t', but we get that from OP_HTTP_CTLS.*/ -# define OP_HTTP_SEPARATORS " \"(),/:;<=>?@[\\]{}" - -/*TEXT can also include LWS, but that has structure, so we parse it - separately.*/ -# define OP_HTTP_CTOKEN OP_HTTP_CTLS OP_HTTP_SEPARATORS - -/*Return: The amount of linear white space (LWS) at the start of _s.*/ -static int op_http_lwsspn(const char *_s){ - int i; - for(i=0;;){ - if(_s[0]=='\r'&&_s[1]=='\n'&&(_s[2]=='\t'||_s[2]==' '))i+=3; - /*This case is for broken servers.*/ - else if(_s[0]=='\n'&&(_s[1]=='\t'||_s[1]==' '))i+=2; - else if(_s[i]=='\t'||_s[i]==' ')i++; - else return i; - } -} - -static char *op_http_parse_status_line(int *_v1_1_compat, - char **_status_code,char *_response){ - char *next; - char *status_code; - int v1_1_compat; - size_t d; - /*RFC 2616 Section 6.1 does not say that the tokens in the Status-Line cannot - be separated by optional LWS, but since it specifically calls out where - spaces are to be placed and that CR and LF are not allowed except at the - end, I am assuming this to be true.*/ - /*We already validated that this starts with "HTTP"*/ - OP_ASSERT(op_strncasecmp(_response,"HTTP",4)==0); - next=_response+4; - if(OP_UNLIKELY(*next++!='/'))return NULL; - d=strspn(next,OP_HTTP_DIGIT); - /*"Leading zeros MUST be ignored by recipients."*/ - while(*next=='0'){ - next++; - OP_ASSERT(d>0); - d--; - } - /*We only support version 1.x*/ - if(OP_UNLIKELY(d!=1)||OP_UNLIKELY(*next++!='1'))return NULL; - if(OP_UNLIKELY(*next++!='.'))return NULL; - d=strspn(next,OP_HTTP_DIGIT); - if(OP_UNLIKELY(d<=0))return NULL; - /*"Leading zeros MUST be ignored by recipients."*/ - while(*next=='0'){ - next++; - OP_ASSERT(d>0); - d--; - } - /*We don't need to parse the version number. - Any non-zero digit means it's greater than 1.*/ - v1_1_compat=d>0; - next+=d; - if(OP_UNLIKELY(*next++!=' '))return NULL; - status_code=next; - d=strspn(next,OP_HTTP_DIGIT); - if(OP_UNLIKELY(d!=3))return NULL; - next+=d; - /*The Reason-Phrase can be empty, but the space must be here.*/ - if(OP_UNLIKELY(*next++!=' '))return NULL; - next+=strcspn(next,OP_HTTP_CREASON_PHRASE); - /*We are not mandating this be present thanks to broken servers.*/ - if(OP_LIKELY(*next=='\r'))next++; - if(OP_UNLIKELY(*next++!='\n'))return NULL; - if(_v1_1_compat!=NULL)*_v1_1_compat=v1_1_compat; - *_status_code=status_code; - return next; -} - -/*Get the next response header. - [out] _header: The header token, NUL-terminated, with leading and trailing - whitespace stripped, and converted to lower case (to simplify - case-insensitive comparisons), or NULL if there are no more - response headers. - [out] _cdr: The remaining contents of the header, excluding the initial - colon (':') and the terminating CRLF ("\r\n"), - NUL-terminated, and with leading and trailing whitespace - stripped, or NULL if there are no more response headers. - [inout] _s: On input, this points to the start of the current line of the - response headers. - On output, it points to the start of the first line following - this header, or NULL if there are no more response headers. - Return: 0 on success, or a negative value on failure.*/ -static int op_http_get_next_header(char **_header,char **_cdr,char **_s){ - char *header; - char *header_end; - char *cdr; - char *cdr_end; - char *next; - size_t d; - next=*_s; - /*The second case is for broken servers.*/ - if(next[0]=='\r'&&next[1]=='\n'||OP_UNLIKELY(next[0]=='\n')){ - /*No more headers.*/ - *_header=NULL; - *_cdr=NULL; - *_s=NULL; - return 0; - } - header=next+op_http_lwsspn(next); - d=strcspn(header,OP_HTTP_CTOKEN); - if(OP_UNLIKELY(d<=0))return OP_FALSE; - header_end=header+d; - next=header_end+op_http_lwsspn(header_end); - if(OP_UNLIKELY(*next++!=':'))return OP_FALSE; - next+=op_http_lwsspn(next); - cdr=next; - do{ - cdr_end=next+strcspn(next,OP_HTTP_CTLS); - next=cdr_end+op_http_lwsspn(cdr_end); - } - while(next>cdr_end); - /*We are not mandating this be present thanks to broken servers.*/ - if(OP_LIKELY(*next=='\r'))next++; - if(OP_UNLIKELY(*next++!='\n'))return OP_FALSE; - *header_end='\0'; - *cdr_end='\0'; - /*Field names are case-insensitive.*/ - op_string_tolower(header); - *_header=header; - *_cdr=cdr; - *_s=next; - return 0; -} - -static opus_int64 op_http_parse_nonnegative_int64(const char **_next, - const char *_cdr){ - const char *next; - opus_int64 ret; - int i; - next=_cdr+strspn(_cdr,OP_HTTP_DIGIT); - *_next=next; - if(OP_UNLIKELY(next<=_cdr))return OP_FALSE; - while(*_cdr=='0')_cdr++; - if(OP_UNLIKELY(next-_cdr>19))return OP_EIMPL; - ret=0; - for(i=0;i<next-_cdr;i++){ - int digit; - digit=_cdr[i]-'0'; - /*Check for overflow.*/ - if(OP_UNLIKELY(ret>(OP_INT64_MAX-9)/10+(digit<=7)))return OP_EIMPL; - ret=ret*10+digit; - } - return ret; -} - -static opus_int64 op_http_parse_content_length(const char *_cdr){ - const char *next; - opus_int64 content_length; - content_length=op_http_parse_nonnegative_int64(&next,_cdr); - if(OP_UNLIKELY(*next!='\0'))return OP_FALSE; - return content_length; -} - -static int op_http_parse_content_range(opus_int64 *_first,opus_int64 *_last, - opus_int64 *_length,const char *_cdr){ - opus_int64 first; - opus_int64 last; - opus_int64 length; - size_t d; - if(OP_UNLIKELY(op_strncasecmp(_cdr,"bytes",5)!=0))return OP_FALSE; - _cdr+=5; - d=op_http_lwsspn(_cdr); - if(OP_UNLIKELY(d<=0))return OP_FALSE; - _cdr+=d; - if(*_cdr!='*'){ - first=op_http_parse_nonnegative_int64(&_cdr,_cdr); - if(OP_UNLIKELY(first<0))return (int)first; - _cdr+=op_http_lwsspn(_cdr); - if(*_cdr++!='-')return OP_FALSE; - _cdr+=op_http_lwsspn(_cdr); - last=op_http_parse_nonnegative_int64(&_cdr,_cdr); - if(OP_UNLIKELY(last<0))return (int)last; - _cdr+=op_http_lwsspn(_cdr); - } - else{ - /*This is for a 416 response (Requested range not satisfiable).*/ - first=last=-1; - _cdr++; - } - if(OP_UNLIKELY(*_cdr++!='/'))return OP_FALSE; - if(*_cdr!='*'){ - length=op_http_parse_nonnegative_int64(&_cdr,_cdr); - if(OP_UNLIKELY(length<0))return (int)length; - } - else{ - /*The total length is unspecified.*/ - _cdr++; - length=-1; - } - if(OP_UNLIKELY(*_cdr!='\0'))return OP_FALSE; - if(OP_UNLIKELY(last<first))return OP_FALSE; - if(length>=0&&OP_UNLIKELY(last>=length))return OP_FALSE; - *_first=first; - *_last=last; - *_length=length; - return 0; -} - -/*Parse the Connection response header and look for a "close" token. - Return: 1 if a "close" token is found, 0 if it's not found, and a negative - value on error.*/ -static int op_http_parse_connection(char *_cdr){ - size_t d; - int ret; - ret=0; - for(;;){ - d=strcspn(_cdr,OP_HTTP_CTOKEN); - if(OP_UNLIKELY(d<=0))return OP_FALSE; - if(op_strncasecmp(_cdr,"close",(int)d)==0)ret=1; - /*We're supposed to strip and ignore any headers mentioned in the - Connection header if this response is from an HTTP/1.0 server (to - work around forwarding of hop-by-hop headers by old proxies), but the - only hop-by-hop header we look at is Connection itself. - Everything else is a well-defined end-to-end header, and going back and - undoing the things we did based on already-examined headers would be - hard (since we only scan them once, in a destructive manner). - Therefore we just ignore all the other tokens.*/ - _cdr+=d; - d=op_http_lwsspn(_cdr); - if(d<=0)break; - _cdr+=d; - } - return OP_UNLIKELY(*_cdr!='\0')?OP_FALSE:ret; -} - -typedef int (*op_ssl_step_func)(SSL *_ssl_conn); - -/*Try to run an SSL function to completion (blocking if necessary).*/ -static int op_do_ssl_step(SSL *_ssl_conn,op_sock _fd,op_ssl_step_func _step){ - struct pollfd fd; - fd.fd=_fd; - for(;;){ - int ret; - int err; - ret=(*_step)(_ssl_conn); - if(ret>=0)return ret; - err=SSL_get_error(_ssl_conn,ret); - if(err==SSL_ERROR_WANT_READ)fd.events=POLLIN; - else if(err==SSL_ERROR_WANT_WRITE)fd.events=POLLOUT; - else return OP_FALSE; - if(poll(&fd,1,OP_POLL_TIMEOUT_MS)<=0)return OP_FALSE; - } -} - -/*Implement a BIO type that just indicates every operation should be retried. - We use this when initializing an SSL connection via a proxy to allow the - initial handshake to proceed all the way up to the first read attempt, and - then return. - This allows the TLS client hello message to be pipelined with the HTTP - CONNECT request.*/ - -static int op_bio_retry_write(BIO *_b,const char *_buf,int _num){ - (void)_buf; - (void)_num; - BIO_clear_retry_flags(_b); - BIO_set_retry_write(_b); - return -1; -} - -static int op_bio_retry_read(BIO *_b,char *_buf,int _num){ - (void)_buf; - (void)_num; - BIO_clear_retry_flags(_b); - BIO_set_retry_read(_b); - return -1; -} - -static int op_bio_retry_puts(BIO *_b,const char *_str){ - return op_bio_retry_write(_b,_str,0); -} - -static long op_bio_retry_ctrl(BIO *_b,int _cmd,long _num,void *_ptr){ - long ret; - (void)_b; - (void)_num; - (void)_ptr; - ret=0; - switch(_cmd){ - case BIO_CTRL_RESET: - case BIO_C_RESET_READ_REQUEST:{ - BIO_clear_retry_flags(_b); - /*Fall through.*/ - } - case BIO_CTRL_EOF: - case BIO_CTRL_SET: - case BIO_CTRL_SET_CLOSE: - case BIO_CTRL_FLUSH: - case BIO_CTRL_DUP:{ - ret=1; - }break; - } - return ret; -} - -static int op_bio_retry_new(BIO *_b){ - _b->init=1; - _b->num=0; - _b->ptr=NULL; - return 1; -} - -static int op_bio_retry_free(BIO *_b){ - return _b!=NULL; -} - -/*This is not const because OpenSSL doesn't allow it, even though it won't - write to it.*/ -static BIO_METHOD op_bio_retry_method={ - BIO_TYPE_NULL, - "retry", - op_bio_retry_write, - op_bio_retry_read, - op_bio_retry_puts, - NULL, - op_bio_retry_ctrl, - op_bio_retry_new, - op_bio_retry_free, - NULL -}; - -/*Establish a CONNECT tunnel and pipeline the start of the TLS handshake for - proxying https URL requests.*/ -static int op_http_conn_establish_tunnel(OpusHTTPStream *_stream, - OpusHTTPConn *_conn,op_sock _fd,SSL *_ssl_conn,BIO *_ssl_bio){ - BIO *retry_bio; - char *status_code; - char *next; - int ret; - _conn->ssl_conn=NULL; - _conn->fd=_fd; - OP_ASSERT(_stream->proxy_connect.nbuf>0); - ret=op_http_conn_write_fully(_conn, - _stream->proxy_connect.buf,_stream->proxy_connect.nbuf); - if(OP_UNLIKELY(ret<0))return ret; - retry_bio=BIO_new(&op_bio_retry_method); - if(OP_UNLIKELY(retry_bio==NULL))return OP_EFAULT; - SSL_set_bio(_ssl_conn,retry_bio,_ssl_bio); - SSL_set_connect_state(_ssl_conn); - /*This shouldn't succeed, since we can't read yet.*/ - OP_ALWAYS_TRUE(SSL_connect(_ssl_conn)<0); - SSL_set_bio(_ssl_conn,_ssl_bio,_ssl_bio); - /*Only now do we disable write coalescing, to allow the CONNECT - request and the start of the TLS handshake to be combined.*/ - op_sock_set_tcp_nodelay(_fd,1); - ret=op_http_conn_read_response(_conn,&_stream->response); - if(OP_UNLIKELY(ret<0))return ret; - next=op_http_parse_status_line(NULL,&status_code,_stream->response.buf); - /*According to RFC 2817, "Any successful (2xx) response to a - CONNECT request indicates that the proxy has established a - connection to the requested host and port.*/ - if(OP_UNLIKELY(next==NULL)||OP_UNLIKELY(status_code[0]!='2'))return OP_FALSE; - return 0; -} - -/*Match a host name against a host with a possible wildcard pattern according - to the rules of RFC 6125 Section 6.4.3. - Return: 0 if the pattern doesn't match, and a non-zero value if it does.*/ -static int op_http_hostname_match(const char *_host,size_t _host_len, - ASN1_STRING *_pattern){ - const char *pattern; - size_t host_label_len; - size_t host_suffix_len; - size_t pattern_len; - size_t pattern_label_len; - size_t pattern_prefix_len; - size_t pattern_suffix_len; - pattern=(const char *)ASN1_STRING_data(_pattern); - pattern_len=strlen(pattern); - /*Check the pattern for embedded NULs.*/ - if(OP_UNLIKELY(pattern_len!=(size_t)ASN1_STRING_length(_pattern)))return 0; - pattern_label_len=strcspn(pattern,"."); - OP_ASSERT(pattern_label_len<=pattern_len); - pattern_prefix_len=strcspn(pattern,"*"); - if(pattern_prefix_len>=pattern_label_len){ - /*"The client SHOULD NOT attempt to match a presented identifier in which - the wildcard character comprises a label other than the left-most label - (e.g., do not match bar.*.example.net)." [RFC 6125 Section 6.4.3]*/ - if(pattern_prefix_len<pattern_len)return 0; - /*If the pattern does not contain a wildcard in the first element, do an - exact match. - Don't use the system strcasecmp here, as that uses the locale and - RFC 4343 makes clear that DNS's case-insensitivity only applies to - the ASCII range.*/ - return _host_len==pattern_len&&op_strncasecmp(_host,pattern,_host_len)==0; - } - /*"However, the client SHOULD NOT attempt to match a presented identifier - where the wildcard character is embedded within an A-label or U-label of - an internationalized domain name." [RFC 6125 Section 6.4.3]*/ - if(op_strncasecmp(pattern,"xn--",4)==0)return 0; - host_label_len=strcspn(_host,"."); - /*Make sure the host has at least two dots, to prevent the wildcard match - from being ridiculously wide. - We should have already checked to ensure it had at least one.*/ - if(OP_UNLIKELY(_host[host_label_len]!='.') - ||strchr(_host+host_label_len+1,'.')==NULL){ - return 0; - } - OP_ASSERT(host_label_len<_host_len); - /*"If the wildcard character is the only character of the left-most label in - the presented identifier, the client SHOULD NOT compare against anything - but the left-most label of the reference identifier (e.g., *.example.com - would match foo.example.com but not bar.foo.example.com)." [RFC 6125 - Section 6.4.3] - This is really confusingly worded, as we check this by actually comparing - the rest of the pattern for an exact match. - We also use the fact that the wildcard must match at least one character, - so the left-most label of the hostname must be at least as large as the - left-most label of the pattern.*/ - if(host_label_len<pattern_label_len)return 0; - OP_ASSERT(pattern[pattern_prefix_len]=='*'); - /*"The client MAY match a presented identifier in which the wildcard - character is not the only character of the label (e.g., baz*.example.net - and *baz.example.net and b*z.example.net would be taken to match - baz1.example.net and foobaz.example.net and buzz.example.net, - respectively)." [RFC 6125 Section 6.4.3]*/ - pattern_suffix_len=pattern_len-pattern_prefix_len-1; - host_suffix_len=_host_len-host_label_len - +pattern_label_len-pattern_prefix_len-1; - return pattern_suffix_len==host_suffix_len - &&op_strncasecmp(_host,pattern,pattern_prefix_len)==0 - &&op_strncasecmp(_host+_host_len-host_suffix_len, - pattern+pattern_prefix_len+1,host_suffix_len)==0; -} - -/*Convert a host to a numeric address, if possible. - Return: A struct addrinfo containing the address, if it was numeric, and NULL - otherise.*/ -static struct addrinfo *op_inet_pton(const char *_host){ - struct addrinfo *addrs; - struct addrinfo hints; - memset(&hints,0,sizeof(hints)); - hints.ai_socktype=SOCK_STREAM; - hints.ai_flags=AI_NUMERICHOST; - if(!getaddrinfo(_host,NULL,&hints,&addrs))return addrs; - return NULL; -} - -/*Verify the server's hostname matches the certificate they presented using - the procedure from Section 6 of RFC 6125. - Return: 0 if the certificate doesn't match, and a non-zero value if it does.*/ -static int op_http_verify_hostname(OpusHTTPStream *_stream,SSL *_ssl_conn){ - X509 *peer_cert; - STACK_OF(GENERAL_NAME) *san_names; - char *host; - size_t host_len; - int ret; - host=_stream->url.host; - host_len=strlen(host); - peer_cert=SSL_get_peer_certificate(_ssl_conn); - /*We set VERIFY_PEER, so we shouldn't get here without a certificate.*/ - if(OP_UNLIKELY(peer_cert==NULL))return 0; - ret=0; - OP_ASSERT(host_len<INT_MAX); - /*RFC 2818 says (after correcting for Eratta 1077): "If a subjectAltName - extension of type dNSName is present, that MUST be used as the identity. - Otherwise, the (most specific) Common Name field in the Subject field of - the certificate MUST be used. - Although the use of the Common Name is existing practice, it is deprecated - and Certification Authorities are encouraged to use the dNSName - instead." - "Matching is performed using the matching rules specified by RFC 2459. - If more than one identity of a given type is present in the certificate - (e.g., more than one dNSName name), a match in any one of the set is - considered acceptable. - Names may contain the wildcard character * which is condered to match any - single domain name component or component fragment. - E.g., *.a.com matches foo.a.com but not bar.foo.a.com. - f*.com matches foo.com but not bar.com." - "In some cases, the URI is specified as an IP address rather than a - hostname. - In this case, the iPAddress subjectAltName must be present in the - certificate and must exactly match the IP in the URI."*/ - san_names=X509_get_ext_d2i(peer_cert,NID_subject_alt_name,NULL,NULL); - if(san_names!=NULL){ - struct addrinfo *addr; - unsigned char *ip; - int ip_len; - int nsan_names; - int sni; - /*Check to see if the host was specified as a simple IP address.*/ - addr=op_inet_pton(host); - ip=NULL; - ip_len=0; - if(addr!=NULL){ - switch(addr->ai_family){ - case AF_INET:{ - struct sockaddr_in *s; - s=(struct sockaddr_in *)addr->ai_addr; - OP_ASSERT(addr->ai_addrlen>=sizeof(*s)); - ip=(unsigned char *)&s->sin_addr; - ip_len=sizeof(s->sin_addr); - }break; - case AF_INET6:{ - struct sockaddr_in6 *s; - s=(struct sockaddr_in6 *)addr->ai_addr; - OP_ASSERT(addr->ai_addrlen>=sizeof(*s)); - ip=(unsigned char *)&s->sin6_addr; - ip_len=sizeof(s->sin6_addr); - }break; - } - } - /*We can only verify fully-qualified domain names. - To quote RFC 6125: "The extracted data MUST include only information that - can be securely parsed out of the inputs (e.g., parsing the fully - qualified DNS domain name out of the "host" component (or its - equivalent) of a URI or deriving the application service type from the - scheme of a URI) ..." - We don't have a way to check (without relying on DNS records, which might - be subverted) if this address is fully-qualified. - This is particularly problematic when using a CONNECT tunnel, as it is - the server that does DNS lookup, not us. - However, we are certain that if the hostname has no '.', it is definitely - not a fully-qualified domain name (with the exception of crazy TLDs that - actually resolve, like "uz", but I am willing to ignore those). - RFC 1535 says "...in any event where a '.' exists in a specified name it - should be assumed to be a fully qualified domain name (FQDN) and SHOULD - be tried as a rooted name first." - That doesn't give us any security guarantees, of course (a subverted DNS - could fail the original query and our resolver might still retry with a - local domain appended). - If we don't have a FQDN, just set the number of names to 0, so we'll fail - and clean up any resources we allocated.*/ - if(ip==NULL&&strchr(host,'.')==NULL)nsan_names=0; - /*RFC 2459 says there MUST be at least one, but we don't depend on it.*/ - else nsan_names=sk_GENERAL_NAME_num(san_names); - for(sni=0;sni<nsan_names;sni++){ - const GENERAL_NAME *name; - name=sk_GENERAL_NAME_value(san_names,sni); - if(ip==NULL){ - if(name->type==GEN_DNS - &&op_http_hostname_match(host,host_len,name->d.dNSName)){ - ret=1; - break; - } - } - else if(name->type==GEN_IPADD){ - unsigned char *cert_ip; - /*If we do have an IP address, compare it directly. - RFC 6125: "When the reference identity is an IP address, the identity - MUST be converted to the 'network byte order' octet string - representation. - For IP Version 4, as specified in RFC 791, the octet string will - contain exactly four octets. - For IP Version 6, as specified in RFC 2460, the octet string will - contain exactly sixteen octets. - This octet string is then compared against subjectAltName values of - type iPAddress. - A match occurs if the reference identity octet string and the value - octet strings are identical."*/ - cert_ip=ASN1_STRING_data(name->d.iPAddress); - if(ip_len==ASN1_STRING_length(name->d.iPAddress) - &&memcmp(ip,cert_ip,ip_len)==0){ - ret=1; - break; - } - } - } - sk_GENERAL_NAME_pop_free(san_names,GENERAL_NAME_free); - if(addr!=NULL)freeaddrinfo(addr); - } - /*Do the same FQDN check we did above. - We don't do this once in advance for both cases, because in the - subjectAltName case we might have an IPv6 address without a dot.*/ - else if(strchr(host,'.')!=NULL){ - int last_cn_loc; - int cn_loc; - /*If there is no subjectAltName, match against commonName. - RFC 6125 says that at least one significant CA is known to issue certs - with multiple CNs, although it SHOULD NOT. - It also says: "The server's identity may also be verified by comparing - the reference identity to the Common Name (CN) value in the last - Relative Distinguished Name (RDN) of the subject field of the server's - certificate (where "last" refers to the DER-encoded order...)." - So find the last one and check it.*/ - cn_loc=-1; - do{ - last_cn_loc=cn_loc; - cn_loc=X509_NAME_get_index_by_NID(X509_get_subject_name(peer_cert), - NID_commonName,last_cn_loc); - } - while(cn_loc>=0); - ret=last_cn_loc>=0 - &&op_http_hostname_match(host,host_len, - X509_NAME_ENTRY_get_data( - X509_NAME_get_entry(X509_get_subject_name(peer_cert),last_cn_loc))); - } - X509_free(peer_cert); - return ret; -} - -/*Perform the TLS handshake on a new connection.*/ -static int op_http_conn_start_tls(OpusHTTPStream *_stream,OpusHTTPConn *_conn, - op_sock _fd,SSL *_ssl_conn){ - SSL_SESSION *ssl_session; - BIO *ssl_bio; - int skip_certificate_check; - int ret; - ssl_bio=BIO_new_socket(_fd,BIO_NOCLOSE); - if(OP_LIKELY(ssl_bio==NULL))return OP_FALSE; -# if !defined(OPENSSL_NO_TLSEXT) - /*Support for RFC 6066 Server Name Indication.*/ - SSL_set_tlsext_host_name(_ssl_conn,_stream->url.host); -# endif - /*Resume a previous session if available.*/ - if(_stream->ssl_session!=NULL){ - SSL_set_session(_ssl_conn,_stream->ssl_session); - } - /*If we're proxying, establish the CONNECT tunnel.*/ - if(_stream->proxy_connect.nbuf>0){ - ret=op_http_conn_establish_tunnel(_stream,_conn, - _fd,_ssl_conn,ssl_bio); - if(OP_UNLIKELY(ret<0))return ret; - } - else{ - /*Otherwise, just use this socket directly.*/ - op_sock_set_tcp_nodelay(_fd,1); - SSL_set_bio(_ssl_conn,ssl_bio,ssl_bio); - SSL_set_connect_state(_ssl_conn); - } - ret=op_do_ssl_step(_ssl_conn,_fd,SSL_connect); - if(OP_UNLIKELY(ret<=0))return OP_FALSE; - ssl_session=_stream->ssl_session; - skip_certificate_check=_stream->skip_certificate_check; - if(ssl_session==NULL||!skip_certificate_check){ - ret=op_do_ssl_step(_ssl_conn,_fd,SSL_do_handshake); - if(OP_UNLIKELY(ret<=0))return OP_FALSE; - /*OpenSSL does not do hostname verification, despite the fact that we just - passed it the hostname above in the call to SSL_set_tlsext_host_name(), - because they are morons. - Do it for them.*/ - if(!skip_certificate_check&&!op_http_verify_hostname(_stream,_ssl_conn)){ - return OP_FALSE; - } - if(ssl_session==NULL){ - /*Save the session for later resumption.*/ - _stream->ssl_session=SSL_get1_session(_ssl_conn); - } - } - _conn->ssl_conn=_ssl_conn; - _conn->fd=_fd; - _conn->nrequests_left=OP_PIPELINE_MAX_REQUESTS; - return 0; -} - -/*Try to start a connection to the next address in the given list of a given - type. - _fd: The socket to connect with. - [inout] _addr: A pointer to the list of addresses. - This will be advanced to the first one that matches the given - address family (possibly the current one). - _ai_family: The address family to connect to. - Return: 1 If the connection was successful. - 0 If the connection is in progress. - OP_FALSE If the connection failed and there were no more addresses - left to try. - *_addr will be set to NULL in this case.*/ -static int op_sock_connect_next(op_sock _fd, - const struct addrinfo **_addr,int _ai_family){ - const struct addrinfo *addr; - int err; - addr=*_addr; - for(;;){ - /*Move to the next address of the requested type.*/ - for(;addr!=NULL&&addr->ai_family!=_ai_family;addr=addr->ai_next); - *_addr=addr; - /*No more: failure.*/ - if(addr==NULL)return OP_FALSE; - if(connect(_fd,addr->ai_addr,addr->ai_addrlen)>=0)return 1; - err=op_errno(); - /*Winsock will set WSAEWOULDBLOCK.*/ - if(OP_LIKELY(err==EINPROGRESS||err==EWOULDBLOCK))return 0; - addr=addr->ai_next; - } -} - -/*The number of address families to try connecting to simultaneously.*/ -# define OP_NPROTOS (2) - -static int op_http_connect_impl(OpusHTTPStream *_stream,OpusHTTPConn *_conn, - const struct addrinfo *_addrs,struct timeb *_start_time){ - const struct addrinfo *addr; - const struct addrinfo *addrs[OP_NPROTOS]; - struct pollfd fds[OP_NPROTOS]; - int ai_family; - int nprotos; - int ret; - int pi; - int pj; - for(pi=0;pi<OP_NPROTOS;pi++)addrs[pi]=NULL; - /*Try connecting via both IPv4 and IPv6 simultaneously, and keep the first - one that succeeds. - Start by finding the first address from each family. - We order the first connection attempts in the same order the address - families were returned in the DNS records in accordance with RFC 6555.*/ - for(addr=_addrs,nprotos=0;addr!=NULL&&nprotos<OP_NPROTOS;addr=addr->ai_next){ - if(addr->ai_family==AF_INET6||addr->ai_family==AF_INET){ - OP_ASSERT(addr->ai_addrlen<=sizeof(struct sockaddr_in6)); - OP_ASSERT(addr->ai_addrlen<=sizeof(struct sockaddr_in)); - /*If we've seen this address family before, skip this address for now.*/ - for(pi=0;pi<nprotos;pi++)if(addrs[pi]->ai_family==addr->ai_family)break; - if(pi<nprotos)continue; - addrs[nprotos++]=addr; - } - } - /*Pop the connection off the free list and put it on the LRU list.*/ - OP_ASSERT(_stream->free_head==_conn); - _stream->free_head=_conn->next; - _conn->next=_stream->lru_head; - _stream->lru_head=_conn; - ftime(_start_time); - *&_conn->read_time=*_start_time; - _conn->read_bytes=0; - _conn->read_rate=0; - /*Try to start a connection to each protocol. - RFC 6555 says it is RECOMMENDED that connection attempts be paced - 150...250 ms apart "to balance human factors against network load", but - that "stateful algorithms" (that's us) "are expected to be more - aggressive". - We are definitely more aggressive: we don't pace at all.*/ - for(pi=0;pi<nprotos;pi++){ - ai_family=addrs[pi]->ai_family; - fds[pi].fd=socket(ai_family,SOCK_STREAM,addrs[pi]->ai_protocol); - fds[pi].events=POLLOUT; - if(OP_LIKELY(fds[pi].fd!=OP_INVALID_SOCKET)){ - if(OP_LIKELY(op_sock_set_nonblocking(fds[pi].fd,1)>=0)){ - ret=op_sock_connect_next(fds[pi].fd,addrs+pi,ai_family); - if(OP_UNLIKELY(ret>0)){ - /*It succeeded right away (technically possible), so stop.*/ - nprotos=pi+1; - break; - } - /*Otherwise go on to the next protocol, and skip the clean-up below.*/ - else if(ret==0)continue; - /*Tried all the addresses for this protocol.*/ - } - /*Clean up the socket.*/ - close(fds[pi].fd); - } - /*Remove this protocol from the list.*/ - memmove(addrs+pi,addrs+pi+1,sizeof(*addrs)*(nprotos-pi-1)); - nprotos--; - pi--; - } - /*Wait for one of the connections to finish.*/ - while(pi>=nprotos&&nprotos>0&&poll(fds,nprotos,OP_POLL_TIMEOUT_MS)>0){ - for(pi=0;pi<nprotos;pi++){ - socklen_t errlen; - int err; - /*Still waiting...*/ - if(!fds[pi].revents)continue; - errlen=sizeof(err); - /*Some platforms will return the pending error in &err and return 0. - Others will put it in errno and return -1.*/ - ret=getsockopt(fds[pi].fd,SOL_SOCKET,SO_ERROR,&err,&errlen); - if(ret<0)err=op_errno(); - /*Success!*/ - if(err==0||err==EISCONN)break; - /*Move on to the next address for this protocol.*/ - ai_family=addrs[pi]->ai_family; - addrs[pi]=addrs[pi]->ai_next; - ret=op_sock_connect_next(fds[pi].fd,addrs+pi,ai_family); - /*It succeeded right away, so stop.*/ - if(ret>0)break; - /*Otherwise go on to the next protocol, and skip the clean-up below.*/ - else if(ret==0)continue; - /*Tried all the addresses for this protocol. - Remove it from the list.*/ - close(fds[pi].fd); - memmove(fds+pi,fds+pi+1,sizeof(*fds)*(nprotos-pi-1)); - memmove(addrs+pi,addrs+pi+1,sizeof(*addrs)*(nprotos-pi-1)); - nprotos--; - pi--; - } - } - /*Close all the other sockets.*/ - for(pj=0;pj<nprotos;pj++)if(pi!=pj)close(fds[pj].fd); - /*If none of them succeeded, we're done.*/ - if(pi>=nprotos)return OP_FALSE; - /*Save this address for future connection attempts.*/ - if(addrs[pi]!=&_stream->addr_info){ - memcpy(&_stream->addr_info,addrs[pi],sizeof(_stream->addr_info)); - _stream->addr_info.ai_addr=&_stream->addr.s; - _stream->addr_info.ai_next=NULL; - memcpy(&_stream->addr,addrs[pi]->ai_addr,addrs[pi]->ai_addrlen); - } - if(OP_URL_IS_SSL(&_stream->url)){ - SSL *ssl_conn; - /*Start the SSL connection.*/ - OP_ASSERT(_stream->ssl_ctx!=NULL); - ssl_conn=SSL_new(_stream->ssl_ctx); - if(OP_LIKELY(ssl_conn!=NULL)){ - ret=op_http_conn_start_tls(_stream,_conn,fds[pi].fd,ssl_conn); - if(OP_LIKELY(ret>=0))return ret; - SSL_free(ssl_conn); - } - close(fds[pi].fd); - _conn->fd=OP_INVALID_SOCKET; - return OP_FALSE; - } - /*Just a normal non-SSL connection.*/ - _conn->ssl_conn=NULL; - _conn->fd=fds[pi].fd; - _conn->nrequests_left=OP_PIPELINE_MAX_REQUESTS; - /*Disable write coalescing. - We always send whole requests at once and always parse the response headers - before sending another one.*/ - op_sock_set_tcp_nodelay(fds[pi].fd,1); - return 0; -} - -static int op_http_connect(OpusHTTPStream *_stream,OpusHTTPConn *_conn, - const struct addrinfo *_addrs,struct timeb *_start_time){ - struct timeb resolve_time; - struct addrinfo *new_addrs; - int ret; - /*Re-resolve the host if we need to (RFC 6555 says we MUST do so - occasionally).*/ - new_addrs=NULL; - ftime(&resolve_time); - if(_addrs!=&_stream->addr_info||op_time_diff_ms(&resolve_time, - &_stream->resolve_time)>=OP_RESOLVE_CACHE_TIMEOUT_MS){ - new_addrs=op_resolve(_stream->connect_host,_stream->connect_port); - if(OP_LIKELY(new_addrs!=NULL)){ - _addrs=new_addrs; - *&_stream->resolve_time=*&resolve_time; - } - else if(OP_LIKELY(_addrs==NULL))return OP_FALSE; - } - ret=op_http_connect_impl(_stream,_conn,_addrs,_start_time); - if(new_addrs!=NULL)freeaddrinfo(new_addrs); - return ret; -} - -# define OP_BASE64_LENGTH(_len) (((_len)+2)/3*4) - -static const char BASE64_TABLE[64]={ - 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', - 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', - 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', - 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' -}; - -static char *op_base64_encode(char *_dst,const char *_src,int _len){ - unsigned s0; - unsigned s1; - unsigned s2; - int ngroups; - int i; - ngroups=_len/3; - for(i=0;i<ngroups;i++){ - s0=_src[3*i+0]; - s1=_src[3*i+1]; - s2=_src[3*i+2]; - _dst[4*i+0]=BASE64_TABLE[s0>>2]; - _dst[4*i+1]=BASE64_TABLE[(s0&3)<<4|s1>>4]; - _dst[4*i+2]=BASE64_TABLE[(s1&15)<<2|s2>>6]; - _dst[4*i+3]=BASE64_TABLE[s2&63]; - } - _len-=3*i; - if(_len==1){ - s0=_src[3*i+0]; - _dst[4*i+0]=BASE64_TABLE[s0>>2]; - _dst[4*i+1]=BASE64_TABLE[(s0&3)<<4]; - _dst[4*i+2]='='; - _dst[4*i+3]='='; - i++; - } - else if(_len==2){ - s0=_src[3*i+0]; - s1=_src[3*i+1]; - _dst[4*i+0]=BASE64_TABLE[s0>>2]; - _dst[4*i+1]=BASE64_TABLE[(s0&3)<<4|s1>>4]; - _dst[4*i+2]=BASE64_TABLE[(s1&15)<<2]; - _dst[4*i+3]='='; - i++; - } - _dst[4*i]='\0'; - return _dst+4*i; -} - -/*Construct an HTTP authorization header using RFC 2617's Basic Authentication - Scheme and append it to the given string buffer.*/ -static int op_sb_append_basic_auth_header(OpusStringBuf *_sb, - const char *_header,const char *_user,const char *_pass){ - int user_len; - int pass_len; - int user_pass_len; - int base64_len; - int nbuf_total; - int ret; - ret=op_sb_append_string(_sb,_header); - ret|=op_sb_append(_sb,": Basic ",8); - user_len=strlen(_user); - pass_len=strlen(_pass); - if(OP_UNLIKELY(pass_len>INT_MAX-user_len))return OP_EFAULT; - if(OP_UNLIKELY(user_len+pass_len>(INT_MAX>>2)*3-3))return OP_EFAULT; - user_pass_len=user_len+1+pass_len; - base64_len=OP_BASE64_LENGTH(user_pass_len); - /*Stick "user:pass" at the end of the buffer so we can Base64 encode it - in-place.*/ - nbuf_total=_sb->nbuf; - if(OP_UNLIKELY(base64_len>INT_MAX-nbuf_total))return OP_EFAULT; - nbuf_total+=base64_len; - ret|=op_sb_ensure_capacity(_sb,nbuf_total); - if(OP_UNLIKELY(ret<0))return ret; - _sb->nbuf=nbuf_total-user_pass_len; - OP_ALWAYS_TRUE(!op_sb_append(_sb,_user,user_len)); - OP_ALWAYS_TRUE(!op_sb_append(_sb,":",1)); - OP_ALWAYS_TRUE(!op_sb_append(_sb,_pass,pass_len)); - op_base64_encode(_sb->buf+nbuf_total-base64_len, - _sb->buf+nbuf_total-user_pass_len,user_pass_len); - return op_sb_append(_sb,"\r\n",2); -} - -static int op_http_allow_pipelining(const char *_server){ - /*Servers known to do bad things with pipelined requests. - This list is taken from Gecko's nsHttpConnection::SupportsPipelining() (in - netwerk/protocol/http/nsHttpConnection.cpp).*/ - static const char *BAD_SERVERS[]={ - "EFAServer/", - "Microsoft-IIS/4.", - "Microsoft-IIS/5.", - "Netscape-Enterprise/3.", - "Netscape-Enterprise/4.", - "Netscape-Enterprise/5.", - "Netscape-Enterprise/6.", - "WebLogic 3.", - "WebLogic 4.", - "WebLogic 5.", - "WebLogic 6.", - "Winstone Servlet Engine v0." - }; -# define NBAD_SERVERS ((int)(sizeof(BAD_SERVERS)/sizeof(*BAD_SERVERS))) - if(*_server>='E'&&*_server<='W'){ - int si; - for(si=0;si<NBAD_SERVERS;si++){ - if(strncmp(_server,BAD_SERVERS[si],strlen(BAD_SERVERS[si]))==0){ - return 0; - } - } - } - return 1; -# undef NBAD_SERVERS -} - -static int op_http_stream_open(OpusHTTPStream *_stream,const char *_url, - int _skip_certificate_check,const char *_proxy_host,unsigned _proxy_port, - const char *_proxy_user,const char *_proxy_pass,OpusServerInfo *_info){ - struct addrinfo *addrs; - int nredirs; - int ret; -#if defined(_WIN32) - op_init_winsock(); -#endif - ret=op_parse_url(&_stream->url,_url); - if(OP_UNLIKELY(ret<0))return ret; - if(_proxy_host!=NULL){ - if(OP_UNLIKELY(_proxy_port>65535U))return OP_EINVAL; - _stream->connect_host=op_string_dup(_proxy_host); - _stream->connect_port=_proxy_port; - } - else{ - _stream->connect_host=_stream->url.host; - _stream->connect_port=_stream->url.port; - } - addrs=NULL; - for(nredirs=0;nredirs<OP_REDIRECT_LIMIT;nredirs++){ - OpusParsedURL next_url; - struct timeb start_time; - struct timeb end_time; - char *next; - char *status_code; - int minor_version_pos; - int v1_1_compat; - /*Initialize the SSL library if necessary.*/ - if(OP_URL_IS_SSL(&_stream->url)&&_stream->ssl_ctx==NULL){ - SSL_CTX *ssl_ctx; -# if !defined(OPENSSL_NO_LOCKING) - /*The documentation says SSL_library_init() is not reentrant. - We don't want to add our own depenencies on a threading library, and it - appears that it's safe to call OpenSSL's locking functions before the - library is initialized, so that's what we'll do (really OpenSSL should - do this for us). - This doesn't guarantee that _other_ threads in the application aren't - calling SSL_library_init() at the same time, but there's not much we - can do about that.*/ - CRYPTO_w_lock(CRYPTO_LOCK_SSL); -# endif - SSL_library_init(); - /*Needed to get SHA2 algorithms with old OpenSSL versions.*/ - OpenSSL_add_ssl_algorithms(); -# if !defined(OPENSSL_NO_LOCKING) - CRYPTO_w_unlock(CRYPTO_LOCK_SSL); -# endif - ssl_ctx=SSL_CTX_new(SSLv23_client_method()); - if(ssl_ctx==NULL)return OP_EFAULT; - if(!_skip_certificate_check){ - /*We don't do anything if this fails, since it just means we won't load - any certificates (and thus all checks will fail). - However, as that is probably the result of a system - mis-configuration, assert here to make it easier to identify.*/ - OP_ALWAYS_TRUE(SSL_CTX_set_default_verify_paths(ssl_ctx)); - SSL_CTX_set_verify(ssl_ctx,SSL_VERIFY_PEER,NULL); - } - _stream->ssl_ctx=ssl_ctx; - _stream->skip_certificate_check=_skip_certificate_check; - if(_proxy_host!=NULL){ - /*We need to establish a CONNECT tunnel to handle https proxying. - Build the request we'll send to do so.*/ - _stream->proxy_connect.nbuf=0; - ret=op_sb_append(&_stream->proxy_connect,"CONNECT ",8); - ret|=op_sb_append_string(&_stream->proxy_connect,_stream->url.host); - ret|=op_sb_append_port(&_stream->proxy_connect,_stream->url.port); - /*CONNECT requires at least HTTP 1.1.*/ - ret|=op_sb_append(&_stream->proxy_connect," HTTP/1.1\r\n",11); - ret|=op_sb_append(&_stream->proxy_connect,"Host: ",6); - ret|=op_sb_append_string(&_stream->proxy_connect,_stream->url.host); - /*The example in RFC 2817 Section 5.2 specifies an explicit port even - when connecting to the default port. - Given that the proxy doesn't know whether we're trying to connect to - an http or an https URL except by the port number, this seems like a - good idea.*/ - ret|=op_sb_append_port(&_stream->proxy_connect,_stream->url.port); - ret|=op_sb_append(&_stream->proxy_connect,"\r\n",2); - ret|=op_sb_append(&_stream->proxy_connect,"User-Agent: .\r\n",15); - if(_proxy_user!=NULL&&_proxy_pass!=NULL){ - ret|=op_sb_append_basic_auth_header(&_stream->proxy_connect, - "Proxy-Authorization",_proxy_user,_proxy_pass); - } - /*For backwards compatibility.*/ - ret|=op_sb_append(&_stream->proxy_connect, - "Proxy-Connection: keep-alive\r\n",30); - ret|=op_sb_append(&_stream->proxy_connect,"\r\n",2); - if(OP_UNLIKELY(ret<0))return ret; - } - } - /*Actually make the connection.*/ - ret=op_http_connect(_stream,_stream->conns+0,addrs,&start_time); - if(OP_UNLIKELY(ret<0))return ret; - /*Build the request to send.*/ - _stream->request.nbuf=0; - ret=op_sb_append(&_stream->request,"GET ",4); - ret|=op_sb_append_string(&_stream->request, - _proxy_host!=NULL?_url:_stream->url.path); - /*Send HTTP/1.0 by default for maximum compatibility (so we don't have to - re-try if HTTP/1.1 fails, though it shouldn't, even for a 1.0 server). - This means we aren't conditionally compliant with RFC 2145, because we - violate the requirement that "An HTTP client SHOULD send a request - version equal to the highest version for which the client is at least - conditionally compliant...". - According to RFC 2145, that means we can't claim any compliance with any - IETF HTTP specification.*/ - ret|=op_sb_append(&_stream->request," HTTP/1.0\r\n",11); - /*Remember where this is so we can upgrade to HTTP/1.1 if the server - supports it.*/ - minor_version_pos=_stream->request.nbuf-3; - ret|=op_sb_append(&_stream->request,"Host: ",6); - ret|=op_sb_append_string(&_stream->request,_stream->url.host); - if(!OP_URL_IS_DEFAULT_PORT(&_stream->url)){ - ret|=op_sb_append_port(&_stream->request,_stream->url.port); - } - ret|=op_sb_append(&_stream->request,"\r\n",2); - /*User-Agents have been a bad idea, so send as little as possible. - RFC 2616 requires at least one token in the User-Agent, which must have - at least one character.*/ - ret|=op_sb_append(&_stream->request,"User-Agent: .\r\n",15); - if(_proxy_host!=NULL&&!OP_URL_IS_SSL(&_stream->url) - &&_proxy_user!=NULL&&_proxy_pass!=NULL){ - ret|=op_sb_append_basic_auth_header(&_stream->request, - "Proxy-Authorization",_proxy_user,_proxy_pass); - } - if(_stream->url.user!=NULL&&_stream->url.pass!=NULL){ - ret|=op_sb_append_basic_auth_header(&_stream->request, - "Authorization",_stream->url.user,_stream->url.pass); - } - /*Always send a Referer [sic] header. - It's common to refuse to serve a resource unless one is present. - We just use the relative "/" URI to suggest we came from the same domain, - as this is the most common check. - This might violate RFC 2616's mandate that the field "MUST NOT be sent if - the Request-URI was obtained from a source that does not have its own - URI, such as input from the user keyboard," but we don't really have any - way to know.*/ - /*TODO: Should we update this on redirects?*/ - ret|=op_sb_append(&_stream->request,"Referer: /\r\n",12); - /*Always send a Range request header to find out if we're seekable. - This requires an HTTP/1.1 server to succeed, but we'll still get what we - want with an HTTP/1.0 server that ignores this request header.*/ - ret|=op_sb_append(&_stream->request,"Range: bytes=0-\r\n",17); - /*Remember where this is so we can append offsets to it later.*/ - _stream->request_tail=_stream->request.nbuf-4; - ret|=op_sb_append(&_stream->request,"\r\n",2); - if(OP_UNLIKELY(ret<0))return ret; - ret=op_http_conn_write_fully(_stream->conns+0, - _stream->request.buf,_stream->request.nbuf); - if(OP_UNLIKELY(ret<0))return ret; - ret=op_http_conn_read_response(_stream->conns+0,&_stream->response); - if(OP_UNLIKELY(ret<0))return ret; - ftime(&end_time); - next=op_http_parse_status_line(&v1_1_compat,&status_code, - _stream->response.buf); - if(OP_UNLIKELY(next==NULL))return OP_FALSE; - if(status_code[0]=='2'){ - opus_int64 content_length; - opus_int64 range_length; - int pipeline_supported; - int pipeline_disabled; - /*We only understand 20x codes.*/ - if(status_code[1]!='0')return OP_FALSE; - content_length=-1; - range_length=-1; - /*Pipelining must be explicitly enabled.*/ - pipeline_supported=0; - pipeline_disabled=0; - for(;;){ - char *header; - char *cdr; - ret=op_http_get_next_header(&header,&cdr,&next); - if(OP_UNLIKELY(ret<0))return ret; - if(header==NULL)break; - if(strcmp(header,"content-length")==0){ - /*Two Content-Length headers?*/ - if(OP_UNLIKELY(content_length>=0))return OP_FALSE; - content_length=op_http_parse_content_length(cdr); - if(OP_UNLIKELY(content_length<0))return (int)content_length; - /*Make sure the Content-Length and Content-Range headers match.*/ - if(range_length>=0&&OP_UNLIKELY(content_length!=range_length)){ - return OP_FALSE; - } - } - else if(strcmp(header,"content-range")==0){ - opus_int64 range_first; - opus_int64 range_last; - /*Two Content-Range headers?*/ - if(OP_UNLIKELY(range_length>=0))return OP_FALSE; - ret=op_http_parse_content_range(&range_first,&range_last, - &range_length,cdr); - if(OP_UNLIKELY(ret<0))return ret; - /*"A response with satus code 206 (Partial Content) MUST NOT - include a Content-Range field with a byte-range-resp-spec of - '*'."*/ - if(status_code[2]=='6' - &&(OP_UNLIKELY(range_first<0)||OP_UNLIKELY(range_last<0))){ - return OP_FALSE; - } - /*We asked for the entire resource.*/ - if(range_length>=0){ - /*Quit if we didn't get it.*/ - if(range_last>=0&&OP_UNLIKELY(range_last!=range_length-1)){ - return OP_FALSE; - } - } - /*If there was no length, use the end of the range.*/ - else if(range_last>=0)range_length=range_last+1; - /*Make sure the Content-Length and Content-Range headers match.*/ - if(content_length>=0&&OP_UNLIKELY(content_length!=range_length)){ - return OP_FALSE; - } - } - else if(strcmp(header,"connection")==0){ - /*According to RFC 2616, if an HTTP/1.1 application does not support - pipelining, it "MUST include the 'close' connection option in - every message." - Therefore, if we receive one in the initial response, disable - pipelining entirely. - The server still might support it (e.g., we might just have hit the - request limit for a temporary child process), but if it doesn't - and we assume it does, every time we cross a chunk boundary we'll - error out and reconnect, adding lots of latency.*/ - ret=op_http_parse_connection(cdr); - if(OP_UNLIKELY(ret<0))return ret; - pipeline_disabled|=ret; - } - else if(strcmp(header,"server")==0){ - /*If we got a Server response header, and it wasn't from a known-bad - server, enable pipelining, as long as it's at least HTTP/1.1. - According to RFC 2145, the server is supposed to respond with the - highest minor version number it supports unless it is known or - suspected that we incorrectly implement the HTTP specification. - So it should send back at least HTTP/1.1, despite our HTTP/1.0 - request.*/ - pipeline_supported=v1_1_compat; - if(v1_1_compat)pipeline_disabled|=!op_http_allow_pipelining(cdr); - if(_info!=NULL&&_info->server==NULL)_info->server=op_string_dup(cdr); - } - /*Collect station information headers if the caller requested it. - If there's more than one copy of a header, the first one wins.*/ - else if(_info!=NULL){ - if(strcmp(header,"content-type")==0){ - if(_info->content_type==NULL){ - _info->content_type=op_string_dup(cdr); - } - } - else if(header[0]=='i'&&header[1]=='c' - &&(header[2]=='e'||header[2]=='y')&&header[3]=='-'){ - if(strcmp(header+4,"name")==0){ - if(_info->name==NULL)_info->name=op_string_dup(cdr); - } - else if(strcmp(header+4,"description")==0){ - if(_info->description==NULL)_info->description=op_string_dup(cdr); - } - else if(strcmp(header+4,"genre")==0){ - if(_info->genre==NULL)_info->genre=op_string_dup(cdr); - } - else if(strcmp(header+4,"url")==0){ - if(_info->url==NULL)_info->url=op_string_dup(cdr); - } - else if(strcmp(header,"icy-br")==0 - ||strcmp(header,"ice-bitrate")==0){ - if(_info->bitrate_kbps<0){ - opus_int64 bitrate_kbps; - /*Just re-using this function to parse a random unsigned - integer field.*/ - bitrate_kbps=op_http_parse_content_length(cdr); - if(bitrate_kbps>=0&&bitrate_kbps<=OP_INT32_MAX){ - _info->bitrate_kbps=(opus_int32)bitrate_kbps; - } - } - } - else if(strcmp(header,"icy-pub")==0 - ||strcmp(header,"ice-public")==0){ - if(_info->is_public<0&&(cdr[0]=='0'||cdr[0]=='1')&&cdr[1]=='\0'){ - _info->is_public=cdr[0]-'0'; - } - } - } - } - } - switch(status_code[2]){ - /*200 OK*/ - case '0':break; - /*203 Non-Authoritative Information*/ - case '3':break; - /*204 No Content*/ - case '4':{ - if(content_length>=0&&OP_UNLIKELY(content_length!=0)){ - return OP_FALSE; - } - }break; - /*206 Partial Content*/ - case '6':{ - /*No Content-Range header.*/ - if(OP_UNLIKELY(range_length<0))return OP_FALSE; - content_length=range_length; - /*The server supports range requests for this resource. - We can seek.*/ - _stream->seekable=1; - }break; - /*201 Created: the response "SHOULD include an entity containing a list - of resource characteristics and location(s)," but not an Opus file. - 202 Accepted: the response "SHOULD include an indication of request's - current status and either a pointer to a status monitor or some - estimate of when the user can expect the request to be fulfilled," - but not an Opus file. - 205 Reset Content: this "MUST NOT include an entity," meaning no Opus - file. - 207...209 are not yet defined, so we don't know how to handle them.*/ - default:return OP_FALSE; - } - _stream->content_length=content_length; - _stream->pipeline=pipeline_supported&&!pipeline_disabled; - /*Pipelining requires HTTP/1.1 persistent connections.*/ - if(_stream->pipeline)_stream->request.buf[minor_version_pos]='1'; - _stream->conns[0].pos=0; - _stream->conns[0].end_pos=_stream->seekable?content_length:-1; - _stream->conns[0].chunk_size=-1; - _stream->cur_conni=0; - _stream->connect_rate=op_time_diff_ms(&end_time,&start_time); - _stream->connect_rate=OP_MAX(_stream->connect_rate,1); - if(_info!=NULL)_info->is_ssl=OP_URL_IS_SSL(&_stream->url); - /*The URL has been successfully opened.*/ - return 0; - } - /*Shouldn't get 1xx; 4xx and 5xx are both failures (and we don't retry). - Everything else is undefined.*/ - else if(status_code[0]!='3')return OP_FALSE; - /*We have some form of redirect request.*/ - /*We only understand 30x codes.*/ - if(status_code[1]!='0')return OP_FALSE; - switch(status_code[2]){ - /*300 Multiple Choices: "If the server has a preferred choice of - representation, it SHOULD include the specific URI for that - representation in the Location field," otherwise we'll fail.*/ - case '0': - /*301 Moved Permanently*/ - case '1': - /*302 Found*/ - case '2': - /*307 Temporary Redirect*/ - case '7': - /*308 Permanent Redirect (defined by draft-reschke-http-status-308-07).*/ - case '8':break; - /*305 Use Proxy: "The Location field gives the URI of the proxy." - TODO: This shouldn't actually be that hard to do.*/ - case '5':return OP_EIMPL; - /*303 See Other: "The new URI is not a substitute reference for the - originally requested resource." - 304 Not Modified: "The 304 response MUST NOT contain a message-body." - 306 (Unused) - 309 is not yet defined, so we don't know how to handle it.*/ - default:return OP_FALSE; - } - _url=NULL; - for(;;){ - char *header; - char *cdr; - ret=op_http_get_next_header(&header,&cdr,&next); - if(OP_UNLIKELY(ret<0))return ret; - if(header==NULL)break; - if(strcmp(header,"location")==0&&OP_LIKELY(_url==NULL))_url=cdr; - } - if(OP_UNLIKELY(_url==NULL))return OP_FALSE; - ret=op_parse_url(&next_url,_url); - if(OP_UNLIKELY(ret<0))return ret; - if(_proxy_host==NULL||_stream->ssl_session!=NULL){ - if(strcmp(_stream->url.host,next_url.host)==0 - &&_stream->url.port==next_url.port){ - /*Try to skip re-resolve when connecting to the same host.*/ - addrs=&_stream->addr_info; - } - else{ - if(_stream->ssl_session!=NULL){ - /*Forget any cached SSL session from the last host.*/ - SSL_SESSION_free(_stream->ssl_session); - _stream->ssl_session=NULL; - } - } - } - if(_proxy_host==NULL){ - OP_ASSERT(_stream->connect_host==_stream->url.host); - _stream->connect_host=next_url.host; - _stream->connect_port=next_url.port; - } - /*Always try to skip re-resolve for proxy connections.*/ - else addrs=&_stream->addr_info; - op_parsed_url_clear(&_stream->url); - *&_stream->url=*&next_url; - /*TODO: On servers/proxies that support pipelining, we might be able to - re-use this connection.*/ - op_http_conn_close(_stream,_stream->conns+0,&_stream->lru_head,1); - } - /*Redirection limit reached.*/ - return OP_FALSE; -} - -static int op_http_conn_send_request(OpusHTTPStream *_stream, - OpusHTTPConn *_conn,opus_int64 _pos,opus_int32 _chunk_size, - int _try_not_to_block){ - opus_int64 next_end; - int ret; - /*We shouldn't have another request outstanding.*/ - OP_ASSERT(_conn->next_pos<0); - /*Build the request to send.*/ - OP_ASSERT(_stream->request.nbuf>=_stream->request_tail); - _stream->request.nbuf=_stream->request_tail; - ret=op_sb_append_nonnegative_int64(&_stream->request,_pos); - ret|=op_sb_append(&_stream->request,"-",1); - if(_chunk_size>0&&OP_ADV_OFFSET(_pos,2*_chunk_size)<_stream->content_length){ - /*We shouldn't be pipelining requests with non-HTTP/1.1 servers.*/ - OP_ASSERT(_stream->pipeline); - next_end=_pos+_chunk_size; - ret|=op_sb_append_nonnegative_int64(&_stream->request,next_end-1); - /*Use a larger chunk size for our next request.*/ - _chunk_size<<=1; - /*But after a while, just request the rest of the resource.*/ - if(_chunk_size>OP_PIPELINE_CHUNK_SIZE_MAX)_chunk_size=-1; - } - else{ - /*Either this was a non-pipelined request or we were close enough to the - end to just ask for the rest.*/ - next_end=-1; - _chunk_size=-1; - } - ret|=op_sb_append(&_stream->request,"\r\n\r\n",4); - if(OP_UNLIKELY(ret<0))return ret; - /*If we don't want to block, check to see if there's enough space in the send - queue. - There's still a chance we might block, even if there is enough space, but - it's a much slimmer one. - Blocking at all is pretty unlikely, as we won't have any requests queued - when _try_not_to_block is set, so if FIONSPACE isn't available (e.g., on - Linux), just skip the test.*/ - if(_try_not_to_block){ -# if defined(FIONSPACE) - int available; - ret=ioctl(_conn->fd,FIONSPACE,&available); - if(ret<0||available<_stream->request.nbuf)return 1; -# endif - } - ret=op_http_conn_write_fully(_conn, - _stream->request.buf,_stream->request.nbuf); - if(OP_UNLIKELY(ret<0))return ret; - _conn->next_pos=_pos; - _conn->next_end=next_end; - /*Save the chunk size to use for the next request.*/ - _conn->chunk_size=_chunk_size; - _conn->nrequests_left--; - return ret; -} - -/*Handles the response to all requests after the first one. - Return: 1 if the connection was closed or timed out, 0 on success, or a - negative value on any other error.*/ -static int op_http_conn_handle_response(OpusHTTPStream *_stream, - OpusHTTPConn *_conn){ - char *next; - char *status_code; - opus_int64 range_length; - opus_int64 next_pos; - opus_int64 next_end; - int ret; - ret=op_http_conn_read_response(_conn,&_stream->response); - /*If the server just closed the connection on us, we may have just hit a - connection re-use limit, so we might want to retry.*/ - if(OP_UNLIKELY(ret<0))return ret==OP_EREAD?1:ret; - next=op_http_parse_status_line(NULL,&status_code,_stream->response.buf); - if(OP_UNLIKELY(next==NULL))return OP_FALSE; - /*We _need_ a 206 Partial Content response. - Nothing else will do.*/ - if(strncmp(status_code,"206",3)!=0){ - /*But on a 408 Request Timeout, we might want to re-try.*/ - return strncmp(status_code,"408",3)==0?1:OP_FALSE; - } - next_pos=_conn->next_pos; - next_end=_conn->next_end; - range_length=-1; - for(;;){ - char *header; - char *cdr; - ret=op_http_get_next_header(&header,&cdr,&next); - if(OP_UNLIKELY(ret<0))return ret; - if(header==NULL)break; - if(strcmp(header,"content-range")==0){ - opus_int64 range_first; - opus_int64 range_last; - /*Two Content-Range headers?*/ - if(OP_UNLIKELY(range_length>=0))return OP_FALSE; - ret=op_http_parse_content_range(&range_first,&range_last, - &range_length,cdr); - if(OP_UNLIKELY(ret<0))return ret; - /*"A response with satus code 206 (Partial Content) MUST NOT - include a Content-Range field with a byte-range-resp-spec of - '*'."*/ - if(OP_UNLIKELY(range_first<0)||OP_UNLIKELY(range_last<0))return OP_FALSE; - /*We also don't want range_last to overflow.*/ - if(OP_UNLIKELY(range_last>=OP_INT64_MAX))return OP_FALSE; - range_last++; - /*Quit if we didn't get the offset we asked for.*/ - if(range_first!=next_pos)return OP_FALSE; - if(next_end<0){ - /*We asked for the rest of the resource.*/ - if(range_length>=0){ - /*Quit if we didn't get it.*/ - if(OP_UNLIKELY(range_last!=range_length))return OP_FALSE; - } - /*If there was no length, use the end of the range.*/ - else range_length=range_last; - next_end=range_last; - } - else{ - if(range_last!=next_end)return OP_FALSE; - /*If there was no length, use the larger of the content length or the - end of this chunk.*/ - if(range_length<0){ - range_length=OP_MAX(range_last,_stream->content_length); - } - } - } - else if(strcmp(header,"content-length")==0){ - opus_int64 content_length; - /*Validate the Content-Length header, if present, against the request we - made.*/ - content_length=op_http_parse_content_length(cdr); - if(OP_UNLIKELY(content_length<0))return (int)content_length; - if(next_end<0){ - /*If we haven't seen the Content-Range header yet and we asked for the - rest of the resource, set next_end, so we can make sure they match - when we do find the Content-Range header.*/ - if(OP_UNLIKELY(next_pos>OP_INT64_MAX-content_length))return OP_FALSE; - next_end=next_pos+content_length; - } - /*Otherwise, make sure they match now.*/ - else if(OP_UNLIKELY(next_end-next_pos!=content_length))return OP_FALSE; - } - else if(strcmp(header,"connection")==0){ - ret=op_http_parse_connection(cdr); - if(OP_UNLIKELY(ret<0))return ret; - /*If the server told us it was going to close the connection, don't make - any more requests.*/ - if(OP_UNLIKELY(ret>0))_conn->nrequests_left=0; - } - } - /*No Content-Range header.*/ - if(OP_UNLIKELY(range_length<0))return OP_FALSE; - /*Update the content_length if necessary.*/ - _stream->content_length=range_length; - _conn->pos=next_pos; - _conn->end_pos=next_end; - _conn->next_pos=-1; - return 0; -} - -/*Open a new connection that will start reading at byte offset _pos. - _pos: The byte offset to start reading from. - _chunk_size: The number of bytes to ask for in the initial request, or -1 to - request the rest of the resource. - This may be more bytes than remain, in which case it will be - converted into a request for the rest.*/ -static int op_http_conn_open_pos(OpusHTTPStream *_stream, - OpusHTTPConn *_conn,opus_int64 _pos,opus_int32 _chunk_size){ - struct timeb start_time; - struct timeb end_time; - opus_int32 connect_rate; - opus_int32 connect_time; - int ret; - ret=op_http_connect(_stream,_conn,&_stream->addr_info,&start_time); - if(OP_UNLIKELY(ret<0))return ret; - ret=op_http_conn_send_request(_stream,_conn,_pos,_chunk_size,0); - if(OP_UNLIKELY(ret<0))return ret; - ret=op_http_conn_handle_response(_stream,_conn); - if(OP_UNLIKELY(ret!=0))return OP_FALSE; - ftime(&end_time); - _stream->cur_conni=_conn-_stream->conns; - OP_ASSERT(_stream->cur_conni>=0&&_stream->cur_conni<OP_NCONNS_MAX); - /*The connection has been successfully opened. - Update the connection time estimate.*/ - connect_time=op_time_diff_ms(&end_time,&start_time); - connect_rate=_stream->connect_rate; - connect_rate+=OP_MAX(connect_time,1)-connect_rate+8>>4; - _stream->connect_rate=connect_rate; - return 0; -} - -/*Read data from the current response body. - If we're pipelining and we get close to the end of this response, queue - another request. - If we've reached the end of this response body, parse the next response and - keep going. - [out] _buf: Returns the data read. - _buf_size: The size of the buffer. - Return: A positive number of bytes read on success. - 0: The connection was closed. - OP_EREAD: There was a fatal read error.*/ -static int op_http_conn_read_body(OpusHTTPStream *_stream, - OpusHTTPConn *_conn,unsigned char *_buf,int _buf_size){ - opus_int64 pos; - opus_int64 end_pos; - opus_int64 next_pos; - opus_int64 content_length; - int nread; - int pipeline; - int ret; - /*Currently this function can only be called on the LRU head. - Otherwise, we'd need a _pnext pointer if we needed to close the connection, - and re-opening it would re-organize the lists.*/ - OP_ASSERT(_stream->lru_head==_conn); - /*We should have filterd out empty reads by this point.*/ - OP_ASSERT(_buf_size>0); - pos=_conn->pos; - end_pos=_conn->end_pos; - next_pos=_conn->next_pos; - pipeline=_stream->pipeline; - content_length=_stream->content_length; - if(end_pos>=0){ - /*Have we reached the end of the current response body?*/ - if(pos>=end_pos){ - OP_ASSERT(content_length>=0); - /*If this was the end of the stream, we're done. - Also return early if a non-blocking read was requested (regardless of - whether we might be able to parse the next response without - blocking).*/ - if(content_length<=end_pos)return 0; - /*Otherwise, start on the next response.*/ - if(next_pos<0){ - /*We haven't issued another request yet.*/ - if(!pipeline||_conn->nrequests_left<=0){ - /*There are two ways to get here: either the server told us it was - going to close the connection after the last request, or we - thought we were reading the whole resource, but it grew while we - were reading it. - The only way the latter could have happened is if content_length - changed while seeking. - Open a new request to read the rest.*/ - OP_ASSERT(_stream->seekable); - /*Try to open a new connection to read another chunk.*/ - op_http_conn_close(_stream,_conn,&_stream->lru_head,1); - /*If we're not pipelining, we should be requesting the rest.*/ - OP_ASSERT(pipeline||_conn->chunk_size==-1); - ret=op_http_conn_open_pos(_stream,_conn,end_pos,_conn->chunk_size); - if(OP_UNLIKELY(ret<0))return OP_EREAD; - } - else{ - /*Issue the request now (better late than never).*/ - ret=op_http_conn_send_request(_stream,_conn,pos,_conn->chunk_size,0); - if(OP_UNLIKELY(ret<0))return OP_EREAD; - next_pos=_conn->next_pos; - OP_ASSERT(next_pos>=0); - } - } - if(next_pos>=0){ - /*We shouldn't be trying to read past the current request body if we're - seeking somewhere else.*/ - OP_ASSERT(next_pos==end_pos); - ret=op_http_conn_handle_response(_stream,_conn); - if(OP_UNLIKELY(ret<0))return OP_EREAD; - if(OP_UNLIKELY(ret>0)&&pipeline){ - opus_int64 next_end; - next_end=_conn->next_end; - /*Our request timed out or the server closed the connection. - Try re-connecting.*/ - op_http_conn_close(_stream,_conn,&_stream->lru_head,1); - /*Unless there's a bug, we should be able to convert - (next_pos,next_end) into valid (_pos,_chunk_size) parameters.*/ - OP_ASSERT(next_end<0 - ||next_end-next_pos>=0&&next_end-next_pos<=OP_INT32_MAX); - ret=op_http_conn_open_pos(_stream,_conn,next_pos, - next_end<0?-1:(opus_int32)(next_end-next_pos)); - if(OP_UNLIKELY(ret<0))return OP_EREAD; - } - else if(OP_UNLIKELY(ret!=0))return OP_EREAD; - } - pos=_conn->pos; - end_pos=_conn->end_pos; - content_length=_stream->content_length; - } - OP_ASSERT(end_pos>pos); - _buf_size=OP_MIN(_buf_size,end_pos-pos); - } - nread=op_http_conn_read(_conn,(char *)_buf,_buf_size,1); - if(OP_UNLIKELY(nread<0))return nread; - pos+=nread; - _conn->pos=pos; - OP_ASSERT(end_pos<0||content_length>=0); - /*TODO: If nrequests_left<=0, we can't make a new request, and there will be - a big pause after we hit the end of the chunk while we open a new - connection. - It would be nice to be able to start that process now, but we have no way - to do it in the background without blocking (even if we could start it, we - have no guarantee the application will return control to us in a - sufficiently timely manner to allow us to complete it, and this is - uncommon enough that it's not worth using threads just for this).*/ - if(end_pos>=0&&end_pos<content_length&&next_pos<0 - &&pipeline&&OP_LIKELY(_conn->nrequests_left>0)){ - opus_int64 request_thresh; - opus_int32 chunk_size; - /*Are we getting close to the end of the current response body? - If so, we should request more data.*/ - request_thresh=_stream->connect_rate*_conn->read_rate>>12; - /*But don't commit ourselves too quickly.*/ - chunk_size=_conn->chunk_size; - if(chunk_size>=0)request_thresh=OP_MIN(chunk_size>>2,request_thresh); - if(end_pos-pos<request_thresh){ - ret=op_http_conn_send_request(_stream,_conn,end_pos,_conn->chunk_size,1); - if(OP_UNLIKELY(ret<0))return OP_EREAD; - } - } - return nread; -} - -static int op_http_stream_read(void *_stream, - unsigned char *_ptr,int _buf_size){ - OpusHTTPStream *stream; - ptrdiff_t nread; - opus_int64 size; - opus_int64 pos; - int ci; - stream=(OpusHTTPStream *)_stream; - /*Check for an empty read.*/ - if(_buf_size<=0)return 0; - ci=stream->cur_conni; - /*No current connection => EOF.*/ - if(ci<0)return 0; - pos=stream->conns[ci].pos; - size=stream->content_length; - /*Check for EOF.*/ - if(size>=0){ - if(pos>=size)return 0; - /*Check for a short read.*/ - if(_buf_size>size-pos)_buf_size=(int)(size-pos); - } - nread=op_http_conn_read_body(stream,stream->conns+ci,_ptr,_buf_size); - if(OP_UNLIKELY(nread<=0)){ - /*We hit an error or EOF. - Either way, we're done with this connection.*/ - op_http_conn_close(stream,stream->conns+ci,&stream->lru_head,1); - stream->cur_conni=-1; - stream->pos=pos; - } - return nread; -} - -/*Discard data until we reach the _target position. - This destroys the contents of _stream->response.buf, as we need somewhere to - read this data, and that is a convenient place. - _just_read_ahead: Whether or not this is a plain fast-forward. - If 0, we need to issue a new request for a chunk at _target - and discard all the data from our current request(s). - Otherwise, we should be able to reach _target without - issuing any new requests. - _target: The stream position to which to read ahead.*/ -static int op_http_conn_read_ahead(OpusHTTPStream *_stream, - OpusHTTPConn *_conn,int _just_read_ahead,opus_int64 _target){ - opus_int64 pos; - opus_int64 end_pos; - opus_int64 next_pos; - opus_int64 next_end; - ptrdiff_t nread; - int ret; - pos=_conn->pos; - end_pos=_conn->end_pos; - next_pos=_conn->next_pos; - next_end=_conn->next_end; - if(!_just_read_ahead){ - /*We need to issue a new pipelined request. - This is the only case where we allow more than one outstanding request - at a time, so we need to reset next_pos (we'll restore it below if we - did have an outstanding request).*/ - OP_ASSERT(_stream->pipeline); - _conn->next_pos=-1; - ret=op_http_conn_send_request(_stream,_conn,_target, - OP_PIPELINE_CHUNK_SIZE,0); - if(OP_UNLIKELY(ret<0))return ret; - } - /*We can reach the target position by reading forward in the current chunk.*/ - if(_just_read_ahead&&(end_pos<0||_target<end_pos))end_pos=_target; - else if(next_pos>=0){ - opus_int64 next_next_pos; - opus_int64 next_next_end; - /*We already have a request outstanding. - Finish off the current chunk.*/ - while(pos<end_pos){ - nread=op_http_conn_read(_conn,_stream->response.buf, - (int)OP_MIN(end_pos-pos,_stream->response.cbuf),1); - /*We failed to read ahead.*/ - if(nread<=0)return OP_FALSE; - pos+=nread; - } - OP_ASSERT(pos==end_pos); - if(_just_read_ahead){ - next_next_pos=next_next_end=-1; - end_pos=_target; - } - else{ - OP_ASSERT(_conn->next_pos==_target); - next_next_pos=_target; - next_next_end=_conn->next_end; - _conn->next_pos=next_pos; - _conn->next_end=next_end; - end_pos=next_end; - } - ret=op_http_conn_handle_response(_stream,_conn); - if(OP_UNLIKELY(ret!=0))return OP_FALSE; - _conn->next_pos=next_next_pos; - _conn->next_end=next_next_end; - } - while(pos<end_pos){ - nread=op_http_conn_read(_conn,_stream->response.buf, - (int)OP_MIN(end_pos-pos,_stream->response.cbuf),1); - /*We failed to read ahead.*/ - if(nread<=0)return OP_FALSE; - pos+=nread; - } - OP_ASSERT(pos==end_pos); - if(!_just_read_ahead){ - ret=op_http_conn_handle_response(_stream,_conn); - if(OP_UNLIKELY(ret!=0))return OP_FALSE; - } - else _conn->pos=end_pos; - OP_ASSERT(_conn->pos==_target); - return 0; -} - -static int op_http_stream_seek(void *_stream,opus_int64 _offset,int _whence){ - struct timeb seek_time; - OpusHTTPStream *stream; - OpusHTTPConn *conn; - OpusHTTPConn **pnext; - OpusHTTPConn *close_conn; - OpusHTTPConn **close_pnext; - opus_int64 content_length; - opus_int64 pos; - int pipeline; - int ci; - int ret; - stream=(OpusHTTPStream *)_stream; - if(!stream->seekable)return -1; - content_length=stream->content_length; - /*If we're seekable, we should have gotten a Content-Length.*/ - OP_ASSERT(content_length>=0); - ci=stream->cur_conni; - pos=ci<0?content_length:stream->conns[ci].pos; - switch(_whence){ - case SEEK_SET:{ - /*Check for overflow:*/ - if(_offset<0)return -1; - pos=_offset; - }break; - case SEEK_CUR:{ - /*Check for overflow:*/ - if(_offset<-pos||_offset>OP_INT64_MAX-pos)return -1; - pos+=_offset; - }break; - case SEEK_END:{ - /*Check for overflow:*/ - if(_offset>content_length||_offset<content_length-OP_INT64_MAX)return -1; - pos=content_length-_offset; - }break; - default:return -1; - } - /*Mark when we deactivated the active connection.*/ - if(ci>=0){ - op_http_conn_read_rate_update(stream->conns+ci); - *&seek_time=*&stream->conns[ci].read_time; - } - else ftime(&seek_time); - /*If we seeked past the end of the stream, just disable the active - connection.*/ - if(pos>=content_length){ - stream->cur_conni=-1; - stream->pos=pos; - return 0; - } - /*First try to find a connection we can use without waiting.*/ - pnext=&stream->lru_head; - conn=stream->lru_head; - while(conn!=NULL){ - opus_int64 conn_pos; - opus_int64 end_pos; - int available; - /*If this connection has been dormant too long or has made too many - requests, close it. - This is to prevent us from hitting server limits/firewall timeouts.*/ - if(op_time_diff_ms(&seek_time,&conn->read_time)> - OP_CONNECTION_IDLE_TIMEOUT_MS - ||conn->nrequests_left<OP_PIPELINE_MIN_REQUESTS){ - op_http_conn_close(stream,conn,pnext,1); - conn=*pnext; - continue; - } - available=op_http_conn_estimate_available(conn); - conn_pos=conn->pos; - end_pos=conn->end_pos; - if(conn->next_pos>=0){ - OP_ASSERT(end_pos>=0); - OP_ASSERT(conn->next_pos==end_pos); - end_pos=conn->next_end; - } - OP_ASSERT(end_pos<0||conn_pos<=end_pos); - /*Can we quickly read ahead without issuing a new request or waiting for - any more data? - If we have an oustanding request, we'll over-estimate the amount of data - it has available (because we'll count the response headers, too), but - that probably doesn't matter.*/ - if(conn_pos<=pos&&pos-conn_pos<=available&&(end_pos<0||pos<end_pos)){ - /*Found a suitable connection to re-use.*/ - ret=op_http_conn_read_ahead(stream,conn,1,pos); - if(OP_UNLIKELY(ret<0)){ - /*The connection might have become stale, so close it and keep going.*/ - op_http_conn_close(stream,conn,pnext,1); - conn=*pnext; - continue; - } - /*Sucessfully resurrected this connection.*/ - *pnext=conn->next; - conn->next=stream->lru_head; - stream->lru_head=conn; - stream->cur_conni=conn-stream->conns; - return 0; - } - pnext=&conn->next; - conn=conn->next; - } - /*Chances are that didn't work, so now try to find one we can use by reading - ahead a reasonable amount and/or by issuing a new request.*/ - close_pnext=NULL; - close_conn=NULL; - pnext=&stream->lru_head; - conn=stream->lru_head; - pipeline=stream->pipeline; - while(conn!=NULL){ - opus_int64 conn_pos; - opus_int64 end_pos; - opus_int64 read_ahead_thresh; - int available; - int just_read_ahead; - /*Dividing by 2048 instead of 1000 scales this by nearly 1/2, biasing away - from connection re-use (and roughly compensating for the lag required to - reopen the TCP window of a connection that's been idle). - There's no overflow checking here, because it's vanishingly unlikely, and - all it would do is cause us to make poor decisions.*/ - read_ahead_thresh=OP_MAX(OP_READAHEAD_THRESH_MIN, - stream->connect_rate*conn->read_rate>>11); - available=op_http_conn_estimate_available(conn); - conn_pos=conn->pos; - end_pos=conn->end_pos; - if(conn->next_pos>=0){ - OP_ASSERT(end_pos>=0); - OP_ASSERT(conn->next_pos==end_pos); - end_pos=conn->next_end; - } - OP_ASSERT(end_pos<0||conn_pos<=end_pos); - /*Can we quickly read ahead without issuing a new request?*/ - just_read_ahead=conn_pos<=pos&&pos-conn_pos-available<=read_ahead_thresh - &&(end_pos<0||pos<end_pos); - if(just_read_ahead||pipeline&&end_pos>=0 - &&end_pos-conn_pos-available<=read_ahead_thresh){ - /*Found a suitable connection to re-use.*/ - ret=op_http_conn_read_ahead(stream,conn,just_read_ahead,pos); - if(OP_UNLIKELY(ret<0)){ - /*The connection might have become stale, so close it and keep going.*/ - op_http_conn_close(stream,conn,pnext,1); - conn=*pnext; - continue; - } - /*Sucessfully resurrected this connection.*/ - *pnext=conn->next; - conn->next=stream->lru_head; - stream->lru_head=conn; - stream->cur_conni=conn-stream->conns; - return 0; - } - close_pnext=pnext; - close_conn=conn; - pnext=&conn->next; - conn=conn->next; - } - /*No suitable connections. - Open a new one.*/ - if(stream->free_head==NULL){ - /*All connections in use. - Expire one of them (we should have already picked which one when scanning - the list).*/ - OP_ASSERT(close_conn!=NULL); - OP_ASSERT(close_pnext!=NULL); - op_http_conn_close(stream,close_conn,close_pnext,1); - } - OP_ASSERT(stream->free_head!=NULL); - conn=stream->free_head; - /*If we can pipeline, only request a chunk of data. - If we're seeking now, there's a good chance we will want to seek again - soon, and this avoids committing this connection to reading the rest of - the stream. - Particularly with SSL or proxies, issuing a new request on the same - connection can be substantially faster than opening a new one. - This also limits the amount of data the server will blast at us on this - connection if we later seek elsewhere and start reading from a different - connection.*/ - ret=op_http_conn_open_pos(stream,conn,pos, - pipeline?OP_PIPELINE_CHUNK_SIZE:-1); - if(OP_UNLIKELY(ret<0)){ - op_http_conn_close(stream,conn,&stream->lru_head,1); - return -1; - } - return 0; -} - -static opus_int64 op_http_stream_tell(void *_stream){ - OpusHTTPStream *stream; - int ci; - stream=(OpusHTTPStream *)_stream; - ci=stream->cur_conni; - return ci<0?stream->pos:stream->conns[ci].pos; -} - -static int op_http_stream_close(void *_stream){ - OpusHTTPStream *stream; - stream=(OpusHTTPStream *)_stream; - if(OP_LIKELY(stream!=NULL)){ - op_http_stream_clear(stream); - _ogg_free(stream); - } - return 0; -} - -static const OpusFileCallbacks OP_HTTP_CALLBACKS={ - op_http_stream_read, - op_http_stream_seek, - op_http_stream_tell, - op_http_stream_close -}; -#endif - -void opus_server_info_init(OpusServerInfo *_info){ - _info->name=NULL; - _info->description=NULL; - _info->genre=NULL; - _info->url=NULL; - _info->server=NULL; - _info->content_type=NULL; - _info->bitrate_kbps=-1; - _info->is_public=-1; - _info->is_ssl=0; -} - -void opus_server_info_clear(OpusServerInfo *_info){ - _ogg_free(_info->content_type); - _ogg_free(_info->server); - _ogg_free(_info->url); - _ogg_free(_info->genre); - _ogg_free(_info->description); - _ogg_free(_info->name); -} - -/*The actual URL stream creation function. - This one isn't extensible like the application-level interface, but because - it isn't public, we're free to change it in the future.*/ -static void *op_url_stream_create_impl(OpusFileCallbacks *_cb,const char *_url, - int _skip_certificate_check,const char *_proxy_host,unsigned _proxy_port, - const char *_proxy_user,const char *_proxy_pass,OpusServerInfo *_info){ - const char *path; - /*Check to see if this is a valid file: URL.*/ - path=op_parse_file_url(_url); - if(path!=NULL){ - char *unescaped_path; - void *ret; - unescaped_path=op_string_dup(path); - if(OP_UNLIKELY(unescaped_path==NULL))return NULL; - ret=op_fopen(_cb,op_unescape_url_component(unescaped_path),"rb"); - _ogg_free(unescaped_path); - return ret; - } -#if defined(OP_ENABLE_HTTP) - /*If not, try http/https.*/ - else{ - OpusHTTPStream *stream; - int ret; - stream=(OpusHTTPStream *)_ogg_malloc(sizeof(*stream)); - if(OP_UNLIKELY(stream==NULL))return NULL; - op_http_stream_init(stream); - ret=op_http_stream_open(stream,_url,_skip_certificate_check, - _proxy_host,_proxy_port,_proxy_user,_proxy_pass,_info); - if(OP_UNLIKELY(ret<0)){ - op_http_stream_clear(stream); - _ogg_free(stream); - return NULL; - } - *_cb=*&OP_HTTP_CALLBACKS; - return stream; - } -#else - (void)_skip_certificate_check; - (void)_proxy_host; - (void)_proxy_port; - (void)_proxy_user; - (void)_proxy_pass; - (void)_info; - return NULL; -#endif -} - -/*The actual implementation of op_url_stream_vcreate(). - We have to do a careful dance here to avoid potential memory leaks if - OpusServerInfo is requested, since this function is also used by - op_vopen_url() and op_vtest_url(). - Even if this function succeeds, those functions might ultimately fail. - If they do, they should return without having touched the OpusServerInfo - passed by the application. - Therefore, if this function succeeds and OpusServerInfo is requested, the - actual info will be stored in *_info and a pointer to the application's - storage will be placed in *_pinfo. - If this function fails or if the application did not request OpusServerInfo, - *_pinfo will be NULL. - Our caller is responsible for copying *_info to **_pinfo if it ultimately - succeeds, or for clearing *_info if it ultimately fails.*/ -void *op_url_stream_vcreate_impl(OpusFileCallbacks *_cb, - const char *_url,OpusServerInfo *_info,OpusServerInfo **_pinfo,va_list _ap){ - int skip_certificate_check; - const char *proxy_host; - opus_int32 proxy_port; - const char *proxy_user; - const char *proxy_pass; - OpusServerInfo *pinfo; - skip_certificate_check=0; - proxy_host=NULL; - proxy_port=8080; - proxy_user=NULL; - proxy_pass=NULL; - pinfo=NULL; - for(;;){ - ptrdiff_t request; - request=va_arg(_ap,char *)-(char *)NULL; - /*If we hit NULL, we're done processing options.*/ - if(!request)break; - switch(request){ - case OP_SSL_SKIP_CERTIFICATE_CHECK_REQUEST:{ - skip_certificate_check=!!va_arg(_ap,opus_int32); - }break; - case OP_HTTP_PROXY_HOST_REQUEST:{ - proxy_host=va_arg(_ap,const char *); - }break; - case OP_HTTP_PROXY_PORT_REQUEST:{ - proxy_port=va_arg(_ap,opus_int32); - if(proxy_port<0||proxy_port>(opus_int32)65535)return NULL; - }break; - case OP_HTTP_PROXY_USER_REQUEST:{ - proxy_user=va_arg(_ap,const char *); - }break; - case OP_HTTP_PROXY_PASS_REQUEST:{ - proxy_pass=va_arg(_ap,const char *); - }break; - case OP_GET_SERVER_INFO_REQUEST:{ - pinfo=va_arg(_ap,OpusServerInfo *); - }break; - /*Some unknown option.*/ - default:return NULL; - } - } - /*If the caller has requested server information, proxy it to a local copy to - simplify error handling.*/ - *_pinfo=NULL; - if(pinfo!=NULL){ - void *ret; - opus_server_info_init(_info); - ret=op_url_stream_create_impl(_cb,_url,skip_certificate_check, - proxy_host,proxy_port,proxy_user,proxy_pass,_info); - if(ret!=NULL)*_pinfo=pinfo; - else opus_server_info_clear(_info); - return ret; - } - return op_url_stream_create_impl(_cb,_url,skip_certificate_check, - proxy_host,proxy_port,proxy_user,proxy_pass,NULL); -} - -void *op_url_stream_vcreate(OpusFileCallbacks *_cb, - const char *_url,va_list _ap){ - OpusServerInfo info; - OpusServerInfo *pinfo; - void *ret; - ret=op_url_stream_vcreate_impl(_cb,_url,&info,&pinfo,_ap); - if(pinfo!=NULL)*pinfo=*&info; - return ret; -} - -void *op_url_stream_create(OpusFileCallbacks *_cb, - const char *_url,...){ - va_list ap; - void *ret; - va_start(ap,_url); - ret=op_url_stream_vcreate(_cb,_url,ap); - va_end(ap); - return ret; -} - -/*Convenience routines to open/test URLs in a single step.*/ - -OggOpusFile *op_vopen_url(const char *_url,int *_error,va_list _ap){ - OpusFileCallbacks cb; - OggOpusFile *of; - OpusServerInfo info; - OpusServerInfo *pinfo; - void *source; - source=op_url_stream_vcreate_impl(&cb,_url,&info,&pinfo,_ap); - if(OP_UNLIKELY(source==NULL)){ - OP_ASSERT(pinfo==NULL); - if(_error!=NULL)*_error=OP_EFAULT; - return NULL; - } - of=op_open_callbacks(source,&cb,NULL,0,_error); - if(OP_UNLIKELY(of==NULL)){ - if(pinfo!=NULL)opus_server_info_clear(&info); - (*cb.close)(source); - } - else if(pinfo!=NULL)*pinfo=*&info; - return of; -} - -OggOpusFile *op_open_url(const char *_url,int *_error,...){ - OggOpusFile *ret; - va_list ap; - va_start(ap,_error); - ret=op_vopen_url(_url,_error,ap); - va_end(ap); - return ret; -} - -OggOpusFile *op_vtest_url(const char *_url,int *_error,va_list _ap){ - OpusFileCallbacks cb; - OggOpusFile *of; - OpusServerInfo info; - OpusServerInfo *pinfo; - void *source; - source=op_url_stream_vcreate_impl(&cb,_url,&info,&pinfo,_ap); - if(OP_UNLIKELY(source==NULL)){ - OP_ASSERT(pinfo==NULL); - if(_error!=NULL)*_error=OP_EFAULT; - return NULL; - } - of=op_test_callbacks(source,&cb,NULL,0,_error); - if(OP_UNLIKELY(of==NULL)){ - if(pinfo!=NULL)opus_server_info_clear(&info); - (*cb.close)(source); - } - else if(pinfo!=NULL)*pinfo=*&info; - return of; -} - -OggOpusFile *op_test_url(const char *_url,int *_error,...){ - OggOpusFile *ret; - va_list ap; - va_start(ap,_error); - ret=op_vtest_url(_url,_error,ap); - va_end(ap); - return ret; -} diff --git a/drivers/opus/info.c b/drivers/opus/info.c deleted file mode 100644 index b94393351e..0000000000 --- a/drivers/opus/info.c +++ /dev/null @@ -1,751 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/internal.h" -#include <limits.h> -#include <string.h> - -static unsigned op_parse_uint16le(const unsigned char *_data){ - return _data[0]|_data[1]<<8; -} - -static int op_parse_int16le(const unsigned char *_data){ - int ret; - ret=_data[0]|_data[1]<<8; - return (ret^0x8000)-0x8000; -} - -static opus_uint32 op_parse_uint32le(const unsigned char *_data){ - return _data[0]|(opus_uint32)_data[1]<<8| - (opus_uint32)_data[2]<<16|(opus_uint32)_data[3]<<24; -} - -static opus_uint32 op_parse_uint32be(const unsigned char *_data){ - return _data[3]|(opus_uint32)_data[2]<<8| - (opus_uint32)_data[1]<<16|(opus_uint32)_data[0]<<24; -} - -int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ - OpusHead head; - if(_len<8)return OP_ENOTFORMAT; - if(memcmp(_data,"OpusHead",8)!=0)return OP_ENOTFORMAT; - if(_len<9)return OP_EBADHEADER; - head.version=_data[8]; - if(head.version>15)return OP_EVERSION; - if(_len<19)return OP_EBADHEADER; - head.channel_count=_data[9]; - head.pre_skip=op_parse_uint16le(_data+10); - head.input_sample_rate=op_parse_uint32le(_data+12); - head.output_gain=op_parse_int16le(_data+16); - head.mapping_family=_data[18]; - if(head.mapping_family==0){ - if(head.channel_count<1||head.channel_count>2)return OP_EBADHEADER; - if(head.version<=1&&_len>19)return OP_EBADHEADER; - head.stream_count=1; - head.coupled_count=head.channel_count-1; - if(_head!=NULL){ - _head->mapping[0]=0; - _head->mapping[1]=1; - } - } - else if(head.mapping_family==1){ - size_t size; - int ci; - if(head.channel_count<1||head.channel_count>8)return OP_EBADHEADER; - size=21+head.channel_count; - if(_len<size||head.version<=1&&_len>size)return OP_EBADHEADER; - head.stream_count=_data[19]; - if(head.stream_count<1)return OP_EBADHEADER; - head.coupled_count=_data[20]; - if(head.coupled_count>head.stream_count)return OP_EBADHEADER; - for(ci=0;ci<head.channel_count;ci++){ - if(_data[21+ci]>=head.stream_count+head.coupled_count - &&_data[21+ci]!=255){ - return OP_EBADHEADER; - } - } - if(_head!=NULL)memcpy(_head->mapping,_data+21,head.channel_count); - } - /*General purpose players should not attempt to play back content with - channel mapping family 255.*/ - else if(head.mapping_family==255)return OP_EIMPL; - /*No other channel mapping families are currently defined.*/ - else return OP_EBADHEADER; - if(_head!=NULL)memcpy(_head,&head,head.mapping-(unsigned char *)&head); - return 0; -} - -void opus_tags_init(OpusTags *_tags){ - memset(_tags,0,sizeof(*_tags)); -} - -void opus_tags_clear(OpusTags *_tags){ - int ncomments; - int ci; - ncomments=_tags->comments; - if(_tags->user_comments!=NULL)ncomments++; - for(ci=ncomments;ci-->0;)_ogg_free(_tags->user_comments[ci]); - _ogg_free(_tags->user_comments); - _ogg_free(_tags->comment_lengths); - _ogg_free(_tags->vendor); -} - -/*Ensure there's room for up to _ncomments comments.*/ -static int op_tags_ensure_capacity(OpusTags *_tags,size_t _ncomments){ - char **user_comments; - int *comment_lengths; - int cur_ncomments; - char *binary_suffix_data; - int binary_suffix_len; - size_t size; - if(OP_UNLIKELY(_ncomments>=(size_t)INT_MAX))return OP_EFAULT; - size=sizeof(*_tags->comment_lengths)*(_ncomments+1); - if(size/sizeof(*_tags->comment_lengths)!=_ncomments+1)return OP_EFAULT; - cur_ncomments=_tags->comments; - comment_lengths=_tags->comment_lengths; - binary_suffix_len=comment_lengths==NULL?0:comment_lengths[cur_ncomments]; - comment_lengths=(int *)_ogg_realloc(_tags->comment_lengths,size); - if(OP_UNLIKELY(comment_lengths==NULL))return OP_EFAULT; - comment_lengths[_ncomments]=binary_suffix_len; - _tags->comment_lengths=comment_lengths; - size=sizeof(*_tags->user_comments)*(_ncomments+1); - if(size/sizeof(*_tags->user_comments)!=_ncomments+1)return OP_EFAULT; - user_comments=_tags->user_comments; - binary_suffix_data=user_comments==NULL?NULL:user_comments[cur_ncomments]; - user_comments=(char **)_ogg_realloc(_tags->user_comments,size); - if(OP_UNLIKELY(user_comments==NULL))return OP_EFAULT; - user_comments[_ncomments]=binary_suffix_data; - _tags->user_comments=user_comments; - return 0; -} - -/*Duplicate a (possibly non-NUL terminated) string with a known length.*/ -static char *op_strdup_with_len(const char *_s,size_t _len){ - size_t size; - char *ret; - size=sizeof(*ret)*(_len+1); - if(OP_UNLIKELY(size<_len))return NULL; - ret=(char *)_ogg_malloc(size); - if(OP_LIKELY(ret!=NULL)){ - ret=(char *)memcpy(ret,_s,sizeof(*ret)*_len); - ret[_len]='\0'; - } - return ret; -} - -/*The actual implementation of opus_tags_parse(). - Unlike the public API, this function requires _tags to already be - initialized, modifies its contents before success is guaranteed, and assumes - the caller will clear it on error.*/ -static int opus_tags_parse_impl(OpusTags *_tags, - const unsigned char *_data,size_t _len){ - opus_uint32 count; - size_t len; - int ncomments; - int ci; - len=_len; - if(len<8)return OP_ENOTFORMAT; - if(memcmp(_data,"OpusTags",8)!=0)return OP_ENOTFORMAT; - if(len<16)return OP_EBADHEADER; - _data+=8; - len-=8; - count=op_parse_uint32le(_data); - _data+=4; - len-=4; - if(count>len)return OP_EBADHEADER; - if(_tags!=NULL){ - _tags->vendor=op_strdup_with_len((char *)_data,count); - if(_tags->vendor==NULL)return OP_EFAULT; - } - _data+=count; - len-=count; - if(len<4)return OP_EBADHEADER; - count=op_parse_uint32le(_data); - _data+=4; - len-=4; - /*Check to make sure there's minimally sufficient data left in the packet.*/ - if(count>len>>2)return OP_EBADHEADER; - /*Check for overflow (the API limits this to an int).*/ - if(count>(opus_uint32)INT_MAX-1)return OP_EFAULT; - if(_tags!=NULL){ - int ret; - ret=op_tags_ensure_capacity(_tags,count); - if(ret<0)return ret; - } - ncomments=(int)count; - for(ci=0;ci<ncomments;ci++){ - /*Check to make sure there's minimally sufficient data left in the packet.*/ - if((size_t)(ncomments-ci)>len>>2)return OP_EBADHEADER; - count=op_parse_uint32le(_data); - _data+=4; - len-=4; - if(count>len)return OP_EBADHEADER; - /*Check for overflow (the API limits this to an int).*/ - if(count>(opus_uint32)INT_MAX)return OP_EFAULT; - if(_tags!=NULL){ - _tags->user_comments[ci]=op_strdup_with_len((char *)_data,count); - if(_tags->user_comments[ci]==NULL)return OP_EFAULT; - _tags->comment_lengths[ci]=(int)count; - _tags->comments=ci+1; - } - _data+=count; - len-=count; - } - if(len>0&&(_data[0]&1)){ - if(len>(opus_uint32)INT_MAX)return OP_EFAULT; - _tags->user_comments[ncomments]=(char *)_ogg_malloc(len); - if(OP_UNLIKELY(_tags->user_comments[ncomments]==NULL))return OP_EFAULT; - memcpy(_tags->user_comments[ncomments],_data,len); - _tags->comment_lengths[ncomments]=(int)len; - } - return 0; -} - -int opus_tags_parse(OpusTags *_tags,const unsigned char *_data,size_t _len){ - if(_tags!=NULL){ - OpusTags tags; - int ret; - opus_tags_init(&tags); - ret=opus_tags_parse_impl(&tags,_data,_len); - if(ret<0)opus_tags_clear(&tags); - else *_tags=*&tags; - return ret; - } - else return opus_tags_parse_impl(NULL,_data,_len); -} - -/*The actual implementation of opus_tags_copy(). - Unlike the public API, this function requires _dst to already be - initialized, modifies its contents before success is guaranteed, and assumes - the caller will clear it on error.*/ -static int opus_tags_copy_impl(OpusTags *_dst,const OpusTags *_src){ - char *vendor; - int ncomments; - int ret; - int ci; - vendor=_src->vendor; - _dst->vendor=op_strdup_with_len(vendor,strlen(vendor)); - if(OP_UNLIKELY(_dst->vendor==NULL))return OP_EFAULT; - ncomments=_src->comments; - ret=op_tags_ensure_capacity(_dst,ncomments); - if(OP_UNLIKELY(ret<0))return ret; - for(ci=0;ci<ncomments;ci++){ - int len; - len=_src->comment_lengths[ci]; - OP_ASSERT(len>=0); - _dst->user_comments[ci]=op_strdup_with_len(_src->user_comments[ci],len); - if(OP_UNLIKELY(_dst->user_comments[ci]==NULL))return OP_EFAULT; - _dst->comment_lengths[ci]=len; - _dst->comments=ci+1; - } - if(_src->comment_lengths!=NULL){ - int len; - len=_src->comment_lengths[ncomments]; - if(len>0){ - _dst->user_comments[ncomments]=(char *)_ogg_malloc(len); - if(OP_UNLIKELY(_dst->user_comments[ncomments]==NULL))return OP_EFAULT; - memcpy(_dst->user_comments[ncomments],_src->user_comments[ncomments],len); - _dst->comment_lengths[ncomments]=len; - } - } - return 0; -} - -int opus_tags_copy(OpusTags *_dst,const OpusTags *_src){ - OpusTags dst; - int ret; - opus_tags_init(&dst); - ret=opus_tags_copy_impl(&dst,_src); - if(OP_UNLIKELY(ret<0))opus_tags_clear(&dst); - else *_dst=*&dst; - return 0; -} - -int opus_tags_add(OpusTags *_tags,const char *_tag,const char *_value){ - char *comment; - int tag_len; - int value_len; - int ncomments; - int ret; - ncomments=_tags->comments; - ret=op_tags_ensure_capacity(_tags,ncomments+1); - if(OP_UNLIKELY(ret<0))return ret; - tag_len=strlen(_tag); - value_len=strlen(_value); - /*+2 for '=' and '\0'.*/ - comment=(char *)_ogg_malloc(sizeof(*comment)*(tag_len+value_len+2)); - if(OP_UNLIKELY(comment==NULL))return OP_EFAULT; - memcpy(comment,_tag,sizeof(*comment)*tag_len); - comment[tag_len]='='; - memcpy(comment+tag_len+1,_value,sizeof(*comment)*(value_len+1)); - _tags->user_comments[ncomments]=comment; - _tags->comment_lengths[ncomments]=tag_len+value_len+1; - _tags->comments=ncomments+1; - return 0; -} - -int opus_tags_add_comment(OpusTags *_tags,const char *_comment){ - char *comment; - int comment_len; - int ncomments; - int ret; - ncomments=_tags->comments; - ret=op_tags_ensure_capacity(_tags,ncomments+1); - if(OP_UNLIKELY(ret<0))return ret; - comment_len=(int)strlen(_comment); - comment=op_strdup_with_len(_comment,comment_len); - if(OP_UNLIKELY(_tags->user_comments[ncomments]==NULL))return OP_EFAULT; - _tags->user_comments[ncomments]=comment; - _tags->comment_lengths[ncomments]=comment_len; - _tags->comments=ncomments+1; - return 0; -} - -int opus_tags_set_binary_suffix(OpusTags *_tags, - const unsigned char *_data,int _len){ - unsigned char *binary_suffix_data; - int ncomments; - int ret; - if(_len<0||_len>0&&(_data==NULL||!(_data[0]&1)))return OP_EINVAL; - ncomments=_tags->comments; - ret=op_tags_ensure_capacity(_tags,ncomments); - if(OP_UNLIKELY(ret<0))return ret; - binary_suffix_data= - (unsigned char *)_ogg_realloc(_tags->user_comments[ncomments],_len); - if(OP_UNLIKELY(binary_suffix_data==NULL))return OP_EFAULT; - memcpy(binary_suffix_data,_data,_len); - _tags->user_comments[ncomments]=(char *)binary_suffix_data; - _tags->comment_lengths[ncomments]=_len; - return 0; -} - -int opus_tagcompare(const char *_tag_name,const char *_comment){ - return opus_tagncompare(_tag_name,strlen(_tag_name),_comment); -} - -int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment){ - int ret; - OP_ASSERT(_tag_len>=0); - ret=op_strncasecmp(_tag_name,_comment,_tag_len); - return ret?ret:'='-_comment[_tag_len]; -} - -const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count){ - char **user_comments; - int tag_len; - int found; - int ncomments; - int ci; - tag_len=strlen(_tag); - ncomments=_tags->comments; - user_comments=_tags->user_comments; - found=0; - for(ci=0;ci<ncomments;ci++){ - if(!opus_tagncompare(_tag,tag_len,user_comments[ci])){ - /*We return a pointer to the data, not a copy.*/ - if(_count==found++)return user_comments[ci]+tag_len+1; - } - } - /*Didn't find anything.*/ - return NULL; -} - -int opus_tags_query_count(const OpusTags *_tags,const char *_tag){ - char **user_comments; - int tag_len; - int found; - int ncomments; - int ci; - tag_len=strlen(_tag); - ncomments=_tags->comments; - user_comments=_tags->user_comments; - found=0; - for(ci=0;ci<ncomments;ci++){ - if(!opus_tagncompare(_tag,tag_len,user_comments[ci]))found++; - } - return found; -} - -const unsigned char *opus_tags_get_binary_suffix(const OpusTags *_tags, - int *_len){ - int ncomments; - int len; - ncomments=_tags->comments; - len=_tags->comment_lengths==NULL?0:_tags->comment_lengths[ncomments]; - *_len=len; - OP_ASSERT(len==0||_tags->user_comments!=NULL); - return len>0?(const unsigned char *)_tags->user_comments[ncomments]:NULL; -} - -static int opus_tags_get_gain(const OpusTags *_tags,int *_gain_q8, - const char *_tag_name,size_t _tag_len){ - char **comments; - int ncomments; - int ci; - comments=_tags->user_comments; - ncomments=_tags->comments; - /*Look for the first valid tag with the name _tag_name and use that.*/ - for(ci=0;ci<ncomments;ci++){ - if(opus_tagncompare(_tag_name,_tag_len,comments[ci])==0){ - char *p; - opus_int32 gain_q8; - int negative; - p=comments[ci]+_tag_len+1; - negative=0; - if(*p=='-'){ - negative=-1; - p++; - } - else if(*p=='+')p++; - gain_q8=0; - while(*p>='0'&&*p<='9'){ - gain_q8=10*gain_q8+*p-'0'; - if(gain_q8>32767-negative)break; - p++; - } - /*This didn't look like a signed 16-bit decimal integer. - Not a valid gain tag.*/ - if(*p!='\0')continue; - *_gain_q8=(int)(gain_q8+negative^negative); - return 0; - } - } - return OP_FALSE; -} - -int opus_tags_get_album_gain(const OpusTags *_tags,int *_gain_q8){ - return opus_tags_get_gain(_tags,_gain_q8,"R128_ALBUM_GAIN",15); -} - -int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8){ - return opus_tags_get_gain(_tags,_gain_q8,"R128_TRACK_GAIN",15); -} - -static int op_is_jpeg(const unsigned char *_buf,size_t _buf_sz){ - return _buf_sz>=11&&memcmp(_buf,"\xFF\xD8\xFF\xE0",4)==0 - &&(_buf[4]<<8|_buf[5])>=16&&memcmp(_buf+6,"JFIF",5)==0; -} - -/*Tries to extract the width, height, bits per pixel, and palette size of a - JPEG. - On failure, simply leaves its outputs unmodified.*/ -static void op_extract_jpeg_params(const unsigned char *_buf,size_t _buf_sz, - opus_uint32 *_width,opus_uint32 *_height, - opus_uint32 *_depth,opus_uint32 *_colors,int *_has_palette){ - if(op_is_jpeg(_buf,_buf_sz)){ - size_t offs; - offs=2; - for(;;){ - size_t segment_len; - int marker; - while(offs<_buf_sz&&_buf[offs]!=0xFF)offs++; - while(offs<_buf_sz&&_buf[offs]==0xFF)offs++; - marker=_buf[offs]; - offs++; - /*If we hit EOI* (end of image), or another SOI* (start of image), - or SOS (start of scan), then stop now.*/ - if(offs>=_buf_sz||(marker>=0xD8&&marker<=0xDA))break; - /*RST* (restart markers): skip (no segment length).*/ - else if(marker>=0xD0&&marker<=0xD7)continue; - /*Read the length of the marker segment.*/ - if(_buf_sz-offs<2)break; - segment_len=_buf[offs]<<8|_buf[offs+1]; - if(segment_len<2||_buf_sz-offs<segment_len)break; - if(marker==0xC0||(marker>0xC0&&marker<0xD0&&(marker&3)!=0)){ - /*Found a SOFn (start of frame) marker segment:*/ - if(segment_len>=8){ - *_height=_buf[offs+3]<<8|_buf[offs+4]; - *_width=_buf[offs+5]<<8|_buf[offs+6]; - *_depth=_buf[offs+2]*_buf[offs+7]; - *_colors=0; - *_has_palette=0; - } - break; - } - /*Other markers: skip the whole marker segment.*/ - offs+=segment_len; - } - } -} - -static int op_is_png(const unsigned char *_buf,size_t _buf_sz){ - return _buf_sz>=8&&memcmp(_buf,"\x89PNG\x0D\x0A\x1A\x0A",8)==0; -} - -/*Tries to extract the width, height, bits per pixel, and palette size of a - PNG. - On failure, simply leaves its outputs unmodified.*/ -static void op_extract_png_params(const unsigned char *_buf,size_t _buf_sz, - opus_uint32 *_width,opus_uint32 *_height, - opus_uint32 *_depth,opus_uint32 *_colors,int *_has_palette){ - if(op_is_png(_buf,_buf_sz)){ - size_t offs; - offs=8; - while(_buf_sz-offs>=12){ - ogg_uint32_t chunk_len; - chunk_len=op_parse_uint32be(_buf+offs); - if(chunk_len>_buf_sz-(offs+12))break; - else if(chunk_len==13&&memcmp(_buf+offs+4,"IHDR",4)==0){ - int color_type; - *_width=op_parse_uint32be(_buf+offs+8); - *_height=op_parse_uint32be(_buf+offs+12); - color_type=_buf[offs+17]; - if(color_type==3){ - *_depth=24; - *_has_palette=1; - } - else{ - int sample_depth; - sample_depth=_buf[offs+16]; - if(color_type==0)*_depth=sample_depth; - else if(color_type==2)*_depth=sample_depth*3; - else if(color_type==4)*_depth=sample_depth*2; - else if(color_type==6)*_depth=sample_depth*4; - *_colors=0; - *_has_palette=0; - break; - } - } - else if(*_has_palette>0&&memcmp(_buf+offs+4,"PLTE",4)==0){ - *_colors=chunk_len/3; - break; - } - offs+=12+chunk_len; - } - } -} - -static int op_is_gif(const unsigned char *_buf,size_t _buf_sz){ - return _buf_sz>=6&&(memcmp(_buf,"GIF87a",6)==0||memcmp(_buf,"GIF89a",6)==0); -} - -/*Tries to extract the width, height, bits per pixel, and palette size of a - GIF. - On failure, simply leaves its outputs unmodified.*/ -static void op_extract_gif_params(const unsigned char *_buf,size_t _buf_sz, - opus_uint32 *_width,opus_uint32 *_height, - opus_uint32 *_depth,opus_uint32 *_colors,int *_has_palette){ - if(op_is_gif(_buf,_buf_sz)&&_buf_sz>=14){ - *_width=_buf[6]|_buf[7]<<8; - *_height=_buf[8]|_buf[9]<<8; - /*libFLAC hard-codes the depth to 24.*/ - *_depth=24; - *_colors=1<<((_buf[10]&7)+1); - *_has_palette=1; - } -} - -/*The actual implementation of opus_picture_tag_parse(). - Unlike the public API, this function requires _pic to already be - initialized, modifies its contents before success is guaranteed, and assumes - the caller will clear it on error.*/ -static int opus_picture_tag_parse_impl(OpusPictureTag *_pic,const char *_tag, - unsigned char *_buf,size_t _buf_sz,size_t _base64_sz){ - opus_int32 picture_type; - opus_uint32 mime_type_length; - char *mime_type; - opus_uint32 description_length; - char *description; - opus_uint32 width; - opus_uint32 height; - opus_uint32 depth; - opus_uint32 colors; - opus_uint32 data_length; - opus_uint32 file_width; - opus_uint32 file_height; - opus_uint32 file_depth; - opus_uint32 file_colors; - int format; - int has_palette; - int colors_set; - size_t i; - /*Decode the BASE64 data.*/ - for(i=0;i<_base64_sz;i++){ - opus_uint32 value; - int j; - value=0; - for(j=0;j<4;j++){ - unsigned c; - unsigned d; - c=(unsigned char)_tag[4*i+j]; - if(c=='+')d=62; - else if(c=='/')d=63; - else if(c>='0'&&c<='9')d=52+c-'0'; - else if(c>='a'&&c<='z')d=26+c-'a'; - else if(c>='A'&&c<='Z')d=c-'A'; - else if(c=='='&&3*i+j>_buf_sz)d=0; - else return OP_ENOTFORMAT; - value=value<<6|d; - } - _buf[3*i]=(unsigned char)(value>>16); - if(3*i+1<_buf_sz){ - _buf[3*i+1]=(unsigned char)(value>>8); - if(3*i+2<_buf_sz)_buf[3*i+2]=(unsigned char)value; - } - } - i=0; - picture_type=op_parse_uint32be(_buf+i); - i+=4; - /*Extract the MIME type.*/ - mime_type_length=op_parse_uint32be(_buf+i); - i+=4; - if(mime_type_length>_buf_sz-32)return OP_ENOTFORMAT; - mime_type=(char *)_ogg_malloc(sizeof(*_pic->mime_type)*(mime_type_length+1)); - if(mime_type==NULL)return OP_EFAULT; - memcpy(mime_type,_buf+i,sizeof(*mime_type)*mime_type_length); - mime_type[mime_type_length]='\0'; - _pic->mime_type=mime_type; - i+=mime_type_length; - /*Extract the description string.*/ - description_length=op_parse_uint32be(_buf+i); - i+=4; - if(description_length>_buf_sz-mime_type_length-32)return OP_ENOTFORMAT; - description= - (char *)_ogg_malloc(sizeof(*_pic->mime_type)*(description_length+1)); - if(description==NULL)return OP_EFAULT; - memcpy(description,_buf+i,sizeof(*description)*description_length); - description[description_length]='\0'; - _pic->description=description; - i+=description_length; - /*Extract the remaining fields.*/ - width=op_parse_uint32be(_buf+i); - i+=4; - height=op_parse_uint32be(_buf+i); - i+=4; - depth=op_parse_uint32be(_buf+i); - i+=4; - colors=op_parse_uint32be(_buf+i); - i+=4; - /*If one of these is set, they all must be, but colors==0 is a valid value.*/ - colors_set=width!=0||height!=0||depth!=0||colors!=0; - if((width==0||height==0||depth==0)&&colors_set)return OP_ENOTFORMAT; - data_length=op_parse_uint32be(_buf+i); - i+=4; - if(data_length>_buf_sz-i)return OP_ENOTFORMAT; - /*Trim extraneous data so we don't copy it below.*/ - _buf_sz=i+data_length; - /*Attempt to determine the image format.*/ - format=OP_PIC_FORMAT_UNKNOWN; - if(mime_type_length==3&&strcmp(mime_type,"-->")==0){ - format=OP_PIC_FORMAT_URL; - /*Picture type 1 must be a 32x32 PNG.*/ - if(picture_type==1&&(width!=0||height!=0)&&(width!=32||height!=32)){ - return OP_ENOTFORMAT; - } - /*Append a terminating NUL for the convenience of our callers.*/ - _buf[_buf_sz++]='\0'; - } - else{ - if(mime_type_length==10 - &&op_strncasecmp(mime_type,"image/jpeg",mime_type_length)==0){ - if(op_is_jpeg(_buf+i,data_length))format=OP_PIC_FORMAT_JPEG; - } - else if(mime_type_length==9 - &&op_strncasecmp(mime_type,"image/png",mime_type_length)==0){ - if(op_is_png(_buf+i,data_length))format=OP_PIC_FORMAT_PNG; - } - else if(mime_type_length==9 - &&op_strncasecmp(mime_type,"image/gif",mime_type_length)==0){ - if(op_is_gif(_buf+i,data_length))format=OP_PIC_FORMAT_GIF; - } - else if(mime_type_length==0||(mime_type_length==6 - &&op_strncasecmp(mime_type,"image/",mime_type_length)==0)){ - if(op_is_jpeg(_buf+i,data_length))format=OP_PIC_FORMAT_JPEG; - else if(op_is_png(_buf+i,data_length))format=OP_PIC_FORMAT_PNG; - else if(op_is_gif(_buf+i,data_length))format=OP_PIC_FORMAT_GIF; - } - file_width=file_height=file_depth=file_colors=0; - has_palette=-1; - switch(format){ - case OP_PIC_FORMAT_JPEG:{ - op_extract_jpeg_params(_buf+i,data_length, - &file_width,&file_height,&file_depth,&file_colors,&has_palette); - }break; - case OP_PIC_FORMAT_PNG:{ - op_extract_png_params(_buf+i,data_length, - &file_width,&file_height,&file_depth,&file_colors,&has_palette); - }break; - case OP_PIC_FORMAT_GIF:{ - op_extract_gif_params(_buf+i,data_length, - &file_width,&file_height,&file_depth,&file_colors,&has_palette); - }break; - } - if(has_palette>=0){ - /*If we successfully extracted these parameters from the image, override - any declared values.*/ - width=file_width; - height=file_height; - depth=file_depth; - colors=file_colors; - } - /*Picture type 1 must be a 32x32 PNG.*/ - if(picture_type==1&&(format!=OP_PIC_FORMAT_PNG||width!=32||height!=32)){ - return OP_ENOTFORMAT; - } - } - /*Adjust _buf_sz instead of using data_length to capture the terminating NUL - for URLs.*/ - _buf_sz-=i; - memmove(_buf,_buf+i,sizeof(*_buf)*_buf_sz); - _buf=(unsigned char *)_ogg_realloc(_buf,_buf_sz); - if(_buf_sz>0&&_buf==NULL)return OP_EFAULT; - _pic->type=picture_type; - _pic->width=width; - _pic->height=height; - _pic->depth=depth; - _pic->colors=colors; - _pic->data_length=data_length; - _pic->data=_buf; - _pic->format=format; - return 0; -} - -int opus_picture_tag_parse(OpusPictureTag *_pic,const char *_tag){ - OpusPictureTag pic; - unsigned char *buf; - size_t base64_sz; - size_t buf_sz; - size_t tag_length; - int ret; - if(opus_tagncompare("METADATA_BLOCK_PICTURE",22,_tag)==0)_tag+=23; - /*Figure out how much BASE64-encoded data we have.*/ - tag_length=strlen(_tag); - if(tag_length&3)return OP_ENOTFORMAT; - base64_sz=tag_length>>2; - buf_sz=3*base64_sz; - if(buf_sz<32)return OP_ENOTFORMAT; - if(_tag[tag_length-1]=='=')buf_sz--; - if(_tag[tag_length-2]=='=')buf_sz--; - if(buf_sz<32)return OP_ENOTFORMAT; - /*Allocate an extra byte to allow appending a terminating NUL to URL data.*/ - buf=(unsigned char *)_ogg_malloc(sizeof(*buf)*(buf_sz+1)); - if(buf==NULL)return OP_EFAULT; - opus_picture_tag_init(&pic); - ret=opus_picture_tag_parse_impl(&pic,_tag,buf,buf_sz,base64_sz); - if(ret<0){ - opus_picture_tag_clear(&pic); - _ogg_free(buf); - } - else *_pic=*&pic; - return ret; -} - -void opus_picture_tag_init(OpusPictureTag *_pic){ - memset(_pic,0,sizeof(*_pic)); -} - -void opus_picture_tag_clear(OpusPictureTag *_pic){ - _ogg_free(_pic->description); - _ogg_free(_pic->mime_type); - _ogg_free(_pic->data); -} diff --git a/drivers/opus/internal.c b/drivers/opus/internal.c deleted file mode 100644 index bd7d2ee4bb..0000000000 --- a/drivers/opus/internal.c +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/internal.h" - -#if defined(OP_ENABLE_ASSERTIONS) -void op_fatal_impl(const char *_str,const char *_file,int _line){ - fprintf(stderr,"Fatal (internal) error in %s, line %i: %s\n", - _file,_line,_str); - abort(); -} -#endif - -/*A version of strncasecmp() that is guaranteed to only ignore the case of - ASCII characters.*/ -int op_strncasecmp(const char *_a,const char *_b,int _n){ - int i; - for(i=0;i<_n;i++){ - int a; - int b; - int d; - a=_a[i]; - b=_b[i]; - if(a>='a'&&a<='z')a-='a'-'A'; - if(b>='a'&&b<='z')b-='a'-'A'; - d=a-b; - if(d)return d; - } - return 0; -} diff --git a/drivers/opus/internal.h b/drivers/opus/internal.h deleted file mode 100644 index f7a5bd8c74..0000000000 --- a/drivers/opus/internal.h +++ /dev/null @@ -1,254 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ********************************************************************/ -#if !defined(_opusfile_internal_h) -# define _opusfile_internal_h (1) - -# if !defined(_REENTRANT) -# define _REENTRANT -# endif -# if !defined(_GNU_SOURCE) -# define _GNU_SOURCE -# endif -# if !defined(_LARGEFILE_SOURCE) -# define _LARGEFILE_SOURCE -# endif -# if !defined(_LARGEFILE64_SOURCE) -# define _LARGEFILE64_SOURCE -# endif -# if !defined(_FILE_OFFSET_BITS) -# define _FILE_OFFSET_BITS 64 -# endif - -# include <stdlib.h> -# include "opus/opusfile.h" - -typedef struct OggOpusLink OggOpusLink; - -# if defined(OP_FIXED_POINT) - -typedef opus_int16 op_sample; - -# else - -typedef float op_sample; - -/*We're using this define to test for libopus 1.1 or later until libopus - provides a better mechanism.*/ -# if defined(OPUS_GET_EXPERT_FRAME_DURATION_REQUEST) -/*Enable soft clipping prevention in 16-bit decodes.*/ -# define OP_SOFT_CLIP (1) -# endif - -# endif - -# if OP_GNUC_PREREQ(4,2) -/*Disable excessive warnings about the order of operations.*/ -# pragma GCC diagnostic ignored "-Wparentheses" -# elif defined(_MSC_VER) -/*Disable excessive warnings about the order of operations.*/ -# pragma warning(disable:4554) -/*Disable warnings about "deprecated" POSIX functions.*/ -# pragma warning(disable:4996) -# endif - -# if OP_GNUC_PREREQ(3,0) -/*Another alternative is - (__builtin_constant_p(_x)?!!(_x):__builtin_expect(!!(_x),1)) - but that evaluates _x multiple times, which may be bad.*/ -# define OP_LIKELY(_x) (__builtin_expect(!!(_x),1)) -# define OP_UNLIKELY(_x) (__builtin_expect(!!(_x),0)) -# else -# define OP_LIKELY(_x) (!!(_x)) -# define OP_UNLIKELY(_x) (!!(_x)) -# endif - -# if defined(OP_ENABLE_ASSERTIONS) -# if OP_GNUC_PREREQ(2,5)||__SUNPRO_C>=0x590 -__attribute__((noreturn)) -# endif -void op_fatal_impl(const char *_str,const char *_file,int _line); - -# define OP_FATAL(_str) (op_fatal_impl(_str,__FILE__,__LINE__)) - -# define OP_ASSERT(_cond) \ - do{ \ - if(OP_UNLIKELY(!(_cond)))OP_FATAL("assertion failed: " #_cond); \ - } \ - while(0) -# define OP_ALWAYS_TRUE(_cond) OP_ASSERT(_cond) - -# else -# define OP_FATAL(_str) abort() -# define OP_ASSERT(_cond) -# define OP_ALWAYS_TRUE(_cond) ((void)(_cond)) -# endif - -# define OP_INT64_MAX (2*(((ogg_int64_t)1<<62)-1)|1) -# define OP_INT64_MIN (-OP_INT64_MAX-1) -# define OP_INT32_MAX (2*(((ogg_int32_t)1<<30)-1)|1) -# define OP_INT32_MIN (-OP_INT32_MAX-1) - -# define OP_MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) -# define OP_MAX(_a,_b) ((_a)>(_b)?(_a):(_b)) -# define OP_CLAMP(_lo,_x,_hi) (OP_MAX(_lo,OP_MIN(_x,_hi))) - -/*Advance a file offset by the given amount, clamping against OP_INT64_MAX. - This is used to advance a known offset by things like OP_CHUNK_SIZE or - OP_PAGE_SIZE_MAX, while making sure to avoid signed overflow. - It assumes that both _offset and _amount are non-negative.*/ -#define OP_ADV_OFFSET(_offset,_amount) \ - (OP_MIN(_offset,OP_INT64_MAX-(_amount))+(_amount)) - -/*The maximum channel count for any mapping we'll actually decode.*/ -# define OP_NCHANNELS_MAX (8) - -/*Initial state.*/ -# define OP_NOTOPEN (0) -/*We've found the first Opus stream in the first link.*/ -# define OP_PARTOPEN (1) -# define OP_OPENED (2) -/*We've found the first Opus stream in the current link.*/ -# define OP_STREAMSET (3) -/*We've initialized the decoder for the chosen Opus stream in the current - link.*/ -# define OP_INITSET (4) - -/*Information cached for a single link in a chained Ogg Opus file. - We choose the first Opus stream encountered in each link to play back (and - require at least one).*/ -struct OggOpusLink{ - /*The byte offset of the first header page in this link.*/ - opus_int64 offset; - /*The byte offset of the first data page from the chosen Opus stream in this - link (after the headers).*/ - opus_int64 data_offset; - /*The byte offset of the last page from the chosen Opus stream in this link. - This is used when seeking to ensure we find a page before the last one, so - that end-trimming calculations work properly. - This is only valid for seekable sources.*/ - opus_int64 end_offset; - /*The granule position of the last sample. - This is only valid for seekable sources.*/ - ogg_int64_t pcm_end; - /*The granule position before the first sample.*/ - ogg_int64_t pcm_start; - /*The serial number.*/ - ogg_uint32_t serialno; - /*The contents of the info header.*/ - OpusHead head; - /*The contents of the comment header.*/ - OpusTags tags; -}; - -struct OggOpusFile{ - /*The callbacks used to access the data source.*/ - OpusFileCallbacks callbacks; - /*A FILE *, memory bufer, etc.*/ - void *source; - /*Whether or not we can seek with this data source.*/ - int seekable; - /*The number of links in this chained Ogg Opus file.*/ - int nlinks; - /*The cached information from each link in a chained Ogg Opus file. - If source isn't seekable (e.g., it's a pipe), only the current link - appears.*/ - OggOpusLink *links; - /*The number of serial numbers from a single link.*/ - int nserialnos; - /*The capacity of the list of serial numbers from a single link.*/ - int cserialnos; - /*Storage for the list of serial numbers from a single link.*/ - ogg_uint32_t *serialnos; - /*This is the current offset of the data processed by the ogg_sync_state. - After a seek, this should be set to the target offset so that we can track - the byte offsets of subsequent pages. - After a call to op_get_next_page(), this will point to the first byte after - that page.*/ - opus_int64 offset; - /*The total size of this data source, or -1 if it's unseekable.*/ - opus_int64 end; - /*Used to locate pages in the data source.*/ - ogg_sync_state oy; - /*One of OP_NOTOPEN, OP_PARTOPEN, OP_OPENED, OP_STREAMSET, OP_INITSET.*/ - int ready_state; - /*The current link being played back.*/ - int cur_link; - /*The number of decoded samples to discard from the start of decoding.*/ - opus_int32 cur_discard_count; - /*The granule position of the previous packet (current packet start time).*/ - ogg_int64_t prev_packet_gp; - /*The stream offset of the most recent page with completed packets, or -1. - This is only needed to recover continued packet data in the seeking logic, - when we use the current position as one of our bounds, only to later - discover it was the correct starting point.*/ - opus_int64 prev_page_offset; - /*The number of bytes read since the last bitrate query, including framing.*/ - opus_int64 bytes_tracked; - /*The number of samples decoded since the last bitrate query.*/ - ogg_int64_t samples_tracked; - /*Takes physical pages and welds them into a logical stream of packets.*/ - ogg_stream_state os; - /*Re-timestamped packets from a single page. - Buffering these relies on the undocumented libogg behavior that ogg_packet - pointers remain valid until the next page is submitted to the - ogg_stream_state they came from.*/ - ogg_packet op[255]; - /*The index of the next packet to return.*/ - int op_pos; - /*The total number of packets available.*/ - int op_count; - /*Central working state for the packet-to-PCM decoder.*/ - OpusMSDecoder *od; - /*The application-provided packet decode callback.*/ - op_decode_cb_func decode_cb; - /*The application-provided packet decode callback context.*/ - void *decode_cb_ctx; - /*The stream count used to initialize the decoder.*/ - int od_stream_count; - /*The coupled stream count used to initialize the decoder.*/ - int od_coupled_count; - /*The channel count used to initialize the decoder.*/ - int od_channel_count; - /*The channel mapping used to initialize the decoder.*/ - unsigned char od_mapping[OP_NCHANNELS_MAX]; - /*The buffered data for one decoded packet.*/ - op_sample *od_buffer; - /*The current position in the decoded buffer.*/ - int od_buffer_pos; - /*The number of valid samples in the decoded buffer.*/ - int od_buffer_size; - /*The type of gain offset to apply. - One of OP_HEADER_GAIN, OP_TRACK_GAIN, or OP_ABSOLUTE_GAIN.*/ - int gain_type; - /*The offset to apply to the gain.*/ - opus_int32 gain_offset_q8; - /*Internal state for soft clipping and dithering float->short output.*/ -#if !defined(OP_FIXED_POINT) -# if defined(OP_SOFT_CLIP) - float clip_state[OP_NCHANNELS_MAX]; -# endif - float dither_a[OP_NCHANNELS_MAX*4]; - float dither_b[OP_NCHANNELS_MAX*4]; - opus_uint32 dither_seed; - int dither_mute; - int dither_disabled; - /*The number of channels represented by the internal state. - This gets set to 0 whenever anything that would prevent state propagation - occurs (switching between the float/short APIs, or between the - stereo/multistream APIs).*/ - int state_channel_count; -#endif -}; - -int op_strncasecmp(const char *_a,const char *_b,int _n); - -#endif diff --git a/drivers/opus/mlp.c b/drivers/opus/mlp.c deleted file mode 100644 index 125106e882..0000000000 --- a/drivers/opus/mlp.c +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (c) 2008-2011 Octasic Inc. - 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. -*/ -#include "opus/opus_config.h" - -#include "opus/opus_types.h" -#include "opus/opus_defines.h" - -#include <math.h> -#include "opus/mlp.h" -#include "opus/celt/arch.h" -#include "opus/tansig_table.h" -#define MAX_NEURONS 100 - -#if 0 -static OPUS_INLINE opus_val16 tansig_approx(opus_val32 _x) /* Q19 */ -{ - int i; - opus_val16 xx; /* Q11 */ - /*double x, y;*/ - opus_val16 dy, yy; /* Q14 */ - /*x = 1.9073e-06*_x;*/ - if (_x>=QCONST32(8,19)) - return QCONST32(1.,14); - if (_x<=-QCONST32(8,19)) - return -QCONST32(1.,14); - xx = EXTRACT16(SHR32(_x, 8)); - /*i = lrint(25*x);*/ - i = SHR32(ADD32(1024,MULT16_16(25, xx)),11); - /*x -= .04*i;*/ - xx -= EXTRACT16(SHR32(MULT16_16(20972,i),8)); - /*x = xx*(1./2048);*/ - /*y = tansig_table[250+i];*/ - yy = tansig_table[250+i]; - /*y = yy*(1./16384);*/ - dy = 16384-MULT16_16_Q14(yy,yy); - yy = yy + MULT16_16_Q14(MULT16_16_Q11(xx,dy),(16384 - MULT16_16_Q11(yy,xx))); - return yy; -} -#else -/*extern const float tansig_table[501];*/ -static OPUS_INLINE float tansig_approx(float x) -{ - int i; - float y, dy; - float sign=1; - /* Tests are reversed to catch NaNs */ - if (!(x<8)) - return 1; - if (!(x>-8)) - return -1; -#ifndef OPUS_FIXED_POINT - /* Another check in case of -ffast-math */ - if (celt_isnan(x)) - return 0; -#endif - if (x<0) - { - x=-x; - sign=-1; - } - i = (int)floor(.5f+25*x); - x -= .04f*i; - y = tansig_table[i]; - dy = 1-y*y; - y = y + x*dy*(1 - y*x); - return sign*y; -} -#endif - -#if 0 -void mlp_process(const MLP *m, const opus_val16 *in, opus_val16 *out) -{ - int j; - opus_val16 hidden[MAX_NEURONS]; - const opus_val16 *W = m->weights; - /* Copy to tmp_in */ - for (j=0;j<m->topo[1];j++) - { - int k; - opus_val32 sum = SHL32(EXTEND32(*W++),8); - for (k=0;k<m->topo[0];k++) - sum = MAC16_16(sum, in[k],*W++); - hidden[j] = tansig_approx(sum); - } - for (j=0;j<m->topo[2];j++) - { - int k; - opus_val32 sum = SHL32(EXTEND32(*W++),14); - for (k=0;k<m->topo[1];k++) - sum = MAC16_16(sum, hidden[k], *W++); - out[j] = tansig_approx(EXTRACT16(PSHR32(sum,17))); - } -} -#else -void mlp_process(const MLP *m, const float *in, float *out) -{ - int j; - float hidden[MAX_NEURONS]; - const float *W = m->weights; - /* Copy to tmp_in */ - for (j=0;j<m->topo[1];j++) - { - int k; - float sum = *W++; - for (k=0;k<m->topo[0];k++) - sum = sum + in[k]**W++; - hidden[j] = tansig_approx(sum); - } - for (j=0;j<m->topo[2];j++) - { - int k; - float sum = *W++; - for (k=0;k<m->topo[1];k++) - sum = sum + hidden[k]**W++; - out[j] = tansig_approx(sum); - } -} -#endif diff --git a/drivers/opus/mlp.h b/drivers/opus/mlp.h deleted file mode 100644 index 2b4962625d..0000000000 --- a/drivers/opus/mlp.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (c) 2008-2011 Octasic Inc. - 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 _MLP_H_ -#define _MLP_H_ - -#include "opus/celt/arch.h" - -typedef struct { - int layers; - const int *topo; - const float *weights; -} MLP; - -extern const MLP net; - -void mlp_process(const MLP *m, const float *in, float *out); - -#endif /* _MLP_H_ */ diff --git a/drivers/opus/mlp_data.c b/drivers/opus/mlp_data.c deleted file mode 100644 index c542a509cf..0000000000 --- a/drivers/opus/mlp_data.c +++ /dev/null @@ -1,106 +0,0 @@ -/* The contents of this file was automatically generated by mlp_train.c - It contains multi-layer perceptron (MLP) weights. */ -#include "opus/opus_config.h" - -#include "opus/mlp.h" - -/* RMS error was 0.138320, seed was 1361535663 */ - -static const float weights[422] = { - -/* hidden layer */ --0.0941125f, -0.302976f, -0.603555f, -0.19393f, -0.185983f, --0.601617f, -0.0465317f, -0.114563f, -0.103599f, -0.618938f, --0.317859f, -0.169949f, -0.0702885f, 0.148065f, 0.409524f, -0.548432f, 0.367649f, -0.494393f, 0.764306f, -1.83957f, -0.170849f, 12.786f, -1.08848f, -1.27284f, -16.2606f, -24.1773f, -5.57454f, -0.17276f, -0.163388f, -0.224421f, --0.0948944f, -0.0728695f, -0.26557f, -0.100283f, -0.0515459f, --0.146142f, -0.120674f, -0.180655f, 0.12857f, 0.442138f, --0.493735f, 0.167767f, 0.206699f, -0.197567f, 0.417999f, -1.50364f, -0.773341f, -10.0401f, 0.401872f, 2.97966f, -15.2165f, -1.88905f, -1.19254f, 0.0285397f, -0.00405139f, -0.0707565f, 0.00825699f, -0.0927269f, -0.010393f, -0.00428882f, --0.00489743f, -0.0709731f, -0.00255992f, 0.0395619f, 0.226424f, -0.0325231f, 0.162175f, -0.100118f, 0.485789f, 0.12697f, -0.285937f, 0.0155637f, 0.10546f, 3.05558f, 1.15059f, --1.00904f, -1.83088f, 3.31766f, -3.42516f, -0.119135f, --0.0405654f, 0.00690068f, 0.0179877f, -0.0382487f, 0.00597941f, --0.0183611f, 0.00190395f, -0.144322f, -0.0435671f, 0.000990594f, -0.221087f, 0.142405f, 0.484066f, 0.404395f, 0.511955f, --0.237255f, 0.241742f, 0.35045f, -0.699428f, 10.3993f, -2.6507f, -2.43459f, -4.18838f, 1.05928f, 1.71067f, -0.00667811f, -0.0721335f, -0.0397346f, 0.0362704f, -0.11496f, --0.0235776f, 0.0082161f, -0.0141741f, -0.0329699f, -0.0354253f, -0.00277404f, -0.290654f, -1.14767f, -0.319157f, -0.686544f, -0.36897f, 0.478899f, 0.182579f, -0.411069f, 0.881104f, --4.60683f, 1.4697f, 0.335845f, -1.81905f, -30.1699f, -5.55225f, 0.0019508f, -0.123576f, -0.0727332f, -0.0641597f, --0.0534458f, -0.108166f, -0.0937368f, -0.0697883f, -0.0275475f, --0.192309f, -0.110074f, 0.285375f, -0.405597f, 0.0926724f, --0.287881f, -0.851193f, -0.099493f, -0.233764f, -1.2852f, -1.13611f, 3.12168f, -0.0699f, -1.86216f, 2.65292f, --7.31036f, 2.44776f, -0.00111802f, -0.0632786f, -0.0376296f, --0.149851f, 0.142963f, 0.184368f, 0.123433f, 0.0756158f, -0.117312f, 0.0933395f, 0.0692163f, 0.0842592f, 0.0704683f, -0.0589963f, 0.0942205f, -0.448862f, 0.0262677f, 0.270352f, --0.262317f, 0.172586f, 2.00227f, -0.159216f, 0.038422f, -10.2073f, 4.15536f, -2.3407f, -0.0550265f, 0.00964792f, --0.141336f, 0.0274501f, 0.0343921f, -0.0487428f, 0.0950172f, --0.00775017f, -0.0372492f, -0.00548121f, -0.0663695f, 0.0960506f, --0.200008f, -0.0412827f, 0.58728f, 0.0515787f, 0.337254f, -0.855024f, 0.668371f, -0.114904f, -3.62962f, -0.467477f, --0.215472f, 2.61537f, 0.406117f, -1.36373f, 0.0425394f, -0.12208f, 0.0934502f, 0.123055f, 0.0340935f, -0.142466f, -0.035037f, -0.0490666f, 0.0733208f, 0.0576672f, 0.123984f, --0.0517194f, -0.253018f, 0.590565f, 0.145849f, 0.315185f, -0.221534f, -0.149081f, 0.216161f, -0.349575f, 24.5664f, --0.994196f, 0.614289f, -18.7905f, -2.83277f, -0.716801f, --0.347201f, 0.479515f, -0.246027f, 0.0758683f, 0.137293f, --0.17781f, 0.118751f, -0.00108329f, -0.237334f, 0.355732f, --0.12991f, -0.0547627f, -0.318576f, -0.325524f, 0.180494f, --0.0625604f, 0.141219f, 0.344064f, 0.37658f, -0.591772f, -5.8427f, -0.38075f, 0.221894f, -1.41934f, -1.87943e+06f, -1.34114f, 0.0283355f, -0.0447856f, -0.0211466f, -0.0256927f, -0.0139618f, 0.0207934f, -0.0107666f, 0.0110969f, 0.0586069f, --0.0253545f, -0.0328433f, 0.11872f, -0.216943f, 0.145748f, -0.119808f, -0.0915211f, -0.120647f, -0.0787719f, -0.143644f, --0.595116f, -1.152f, -1.25335f, -1.17092f, 4.34023f, --975268.f, -1.37033f, -0.0401123f, 0.210602f, -0.136656f, -0.135962f, -0.0523293f, 0.0444604f, 0.0143928f, 0.00412666f, --0.0193003f, 0.218452f, -0.110204f, -2.02563f, 0.918238f, --2.45362f, 1.19542f, -0.061362f, -1.92243f, 0.308111f, -0.49764f, 0.912356f, 0.209272f, -2.34525f, 2.19326f, --6.47121f, 1.69771f, -0.725123f, 0.0118929f, 0.0377944f, -0.0554003f, 0.0226452f, -0.0704421f, -0.0300309f, 0.0122978f, --0.0041782f, -0.0686612f, 0.0313115f, 0.039111f, 0.364111f, --0.0945548f, 0.0229876f, -0.17414f, 0.329795f, 0.114714f, -0.30022f, 0.106997f, 0.132355f, 5.79932f, 0.908058f, --0.905324f, -3.3561f, 0.190647f, 0.184211f, -0.673648f, -0.231807f, -0.0586222f, 0.230752f, -0.438277f, 0.245857f, --0.17215f, 0.0876383f, -0.720512f, 0.162515f, 0.0170571f, -0.101781f, 0.388477f, 1.32931f, 1.08548f, -0.936301f, --2.36958f, -6.71988f, -3.44376f, 2.13818f, 14.2318f, -4.91459f, -3.09052f, -9.69191f, -0.768234f, 1.79604f, -0.0549653f, 0.163399f, 0.0797025f, 0.0343933f, -0.0555876f, --0.00505673f, 0.0187258f, 0.0326628f, 0.0231486f, 0.15573f, -0.0476223f, -0.254824f, 1.60155f, -0.801221f, 2.55496f, -0.737629f, -1.36249f, -0.695463f, -2.44301f, -1.73188f, -3.95279f, 1.89068f, 0.486087f, -11.3343f, 3.9416e+06f, - -/* output layer */ --0.381439f, 0.12115f, -0.906927f, 2.93878f, 1.6388f, -0.882811f, 0.874344f, 1.21726f, -0.874545f, 0.321706f, -0.785055f, 0.946558f, -0.575066f, -3.46553f, 0.884905f, -0.0924047f, -9.90712f, 0.391338f, 0.160103f, -2.04954f, -4.1455f, 0.0684029f, -0.144761f, -0.285282f, 0.379244f, --1.1584f, -0.0277241f, -9.85f, -4.82386f, 3.71333f, -3.87308f, 3.52558f}; - -static const int topo[3] = {25, 15, 2}; - -const MLP net = { - 3, - topo, - weights -}; diff --git a/drivers/opus/opus.c b/drivers/opus/opus.c deleted file mode 100644 index 762a9d7469..0000000000 --- a/drivers/opus/opus.c +++ /dev/null @@ -1,347 +0,0 @@ -/* Copyright (c) 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. -*/ -#include "opus/opus_config.h" - -#include "opus/opus.h" -#include "opus/opus_private.h" - -#ifndef DISABLE_FLOAT_API -OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem) -{ - int c; - int i; - float *x; - - if (C<1 || N<1 || !_x || !declip_mem) return; - - /* First thing: saturate everything to +/- 2 which is the highest level our - non-linearity can handle. At the point where the signal reaches +/-2, - the derivative will be zero anyway, so this doesn't introduce any - discontinuity in the derivative. */ - for (i=0;i<N*C;i++) - _x[i] = MAX16(-2.f, MIN16(2.f, _x[i])); - 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; - 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); - 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; - } -} -#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) -{ - 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; - - if (size==NULL) - return OPUS_BAD_ARG; - - 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*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 (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); -} - diff --git a/drivers/opus/opus.h b/drivers/opus/opus.h deleted file mode 100644 index 4cb171378b..0000000000 --- a/drivers/opus/opus.h +++ /dev/null @@ -1,981 +0,0 @@ -/* 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/opus_types.h" -#include "opus/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 assuptions 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 1 byte, 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. - */ -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 (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@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 (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/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 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 assuptions 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; - -/** 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 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 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 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); - -/** 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(4); - -/** 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); - -/** 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 manipualte 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/drivers/opus/opus_custom.h b/drivers/opus/opus_custom.h deleted file mode 100644 index 32fcb81ac7..0000000000 --- a/drivers/opus/opus_custom.h +++ /dev/null @@ -1,342 +0,0 @@ -/* 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/opus_defines.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef CUSTOM_MODES -# 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. - @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); - -# ifdef CUSTOM_MODES -/** 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 a 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); - -/** 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 an 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); - -/** 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/drivers/opus/opus_decoder.c b/drivers/opus/opus_decoder.c deleted file mode 100644 index b954b98f02..0000000000 --- a/drivers/opus/opus_decoder.c +++ /dev/null @@ -1,978 +0,0 @@ -/* Copyright (c) 2010 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. -*/ -#include "opus/opus_config.h" - -#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 "opus/celt/celt.h" -#include "opus/opus.h" -#include "opus/celt/entdec.h" -#include "opus/celt/modes.h" -#include "opus/silk/API.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/float_cast.h" -#include "opus/opus_private.h" -#include "opus/celt/os_support.h" -#include "opus/silk/structs.h" -#include "opus/silk/define.h" -#include "opus/celt/mathops.h" -#include "opus/celt/cpu_support.h" - -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 arch; - - /* 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 OPUS_FIXED_POINT - opus_val16 softclip_mem[2]; -#endif - - opus_uint32 rangeFinal; -}; - - -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) - || (channels!=1&&channels!=2)) - return OPUS_BAD_ARG; - - OPUS_CLEAR((char*)st, opus_decoder_get_size(channels)); - /* Initialize SILK encoder */ - 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->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; - 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) - || (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; -} - -static void smooth_fade(const opus_val16 *in1, const opus_val16 *in2, - opus_val16 *out, int overlap, int channels, - const opus_val16 *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 = MULT16_16_Q15(window[i*inc], window[i*inc]); - out[i*channels+c] = SHR32(MAC16_16(MULT16_16(w,in2[i*channels+c]), - Q15ONE-w, in1[i*channels+c]), 15); - } - } -} - -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_val16 *pcm, int frame_size, int decode_fec) -{ - void *silk_dec; - CELTDecoder *celt_dec; - int i, silk_ret=0, celt_ret=0; - ec_dec dec; - opus_int32 silk_frame_size; - int pcm_silk_size; - VARDECL(opus_int16, pcm_silk); - int pcm_transition_silk_size; - VARDECL(opus_val16, pcm_transition_silk); - int pcm_transition_celt_size; - VARDECL(opus_val16, pcm_transition_celt); - opus_val16 *pcm_transition=NULL; - int redundant_audio_size; - VARDECL(opus_val16, redundant_audio); - - int audiosize; - int mode; - 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 opus_val16 *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; - ec_dec_init(&dec,(unsigned char*)data,len); - } else { - audiosize = frame_size; - mode = st->prev_mode; - - 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); - 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. */ -#ifdef OPUS_FIXED_POINT - celt_accum = (mode != MODE_CELT_ONLY) && (frame_size >= F10); -#else - celt_accum = 0; -#endif - - 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_val16); - if (transition && mode == MODE_CELT_ONLY) - { - pcm_transition = pcm_transition_celt; - opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0); - } - 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; - } - - /* Don't allocate any memory when in CELT-only mode */ - pcm_silk_size = (mode != MODE_CELT_ONLY && !celt_accum) ? IMAX(F10, frame_size)*st->channels : ALLOC_NONE; - ALLOC(pcm_silk, pcm_silk_size, opus_int16); - - /* SILK processing */ - if (mode != MODE_CELT_ONLY) - { - int lost_flag, decoded_samples; - opus_int16 *pcm_ptr; -#ifdef OPUS_FIXED_POINT - if (celt_accum) - pcm_ptr = pcm; - else -#endif - pcm_ptr = pcm_silk; - - if (st->prev_mode==MODE_CELT_ONLY) - silk_InitDecoder( 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( st->bandwidth == OPUS_BANDWIDTH_NARROWBAND ) { - st->DecControl.internalSampleRate = 8000; - } else if( st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) { - st->DecControl.internalSampleRate = 12000; - } else if( st->bandwidth == OPUS_BANDWIDTH_WIDEBAND ) { - st->DecControl.internalSampleRate = 16000; - } else { - st->DecControl.internalSampleRate = 16000; - silk_assert( 0 ); - } - } else { - /* Hybrid mode */ - st->DecControl.internalSampleRate = 16000; - } - } - - 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, 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 ); - } - - start_band = 0; - if (!decode_fec && mode != MODE_CELT_ONLY && data != NULL - && ec_tell(&dec)+17+20*(st->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; - - { - int endband=21; - - switch(st->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; - } - celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband)); - celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels)); - } - - if (redundancy) - { - transition = 0; - pcm_transition_silk_size=ALLOC_NONE; - } - - ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16); - - if (transition && mode != MODE_CELT_ONLY) - { - pcm_transition = pcm_transition_silk; - opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0); - } - - /* Only allocation memory for redundancy if/when needed */ - redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE; - ALLOC(redundant_audio, redundant_audio_size, opus_val16); - - /* 5 ms redundant frame for CELT->SILK*/ - if (redundancy && celt_to_silk) - { - 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); - celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)); - } - - /* MUST be after PLC */ - celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band)); - - if (mode != MODE_SILK_ONLY) - { - 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) - celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); - /* Decode CELT */ - celt_ret = celt_decode_with_ec(celt_dec, decode_fec ? NULL : data, - len, pcm, celt_frame_size, &dec, celt_accum); - } 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) ) - { - celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); - celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL, celt_accum); - } - } - - if (mode != MODE_CELT_ONLY && !celt_accum) - { -#ifdef OPUS_FIXED_POINT - for (i=0;i<frame_size*st->channels;i++) - pcm[i] = SAT16(ADD32(pcm[i], pcm_silk[i])); -#else - for (i=0;i<frame_size*st->channels;i++) - pcm[i] = pcm[i] + (opus_val16)((1.f/32768.f)*pcm_silk[i]); -#endif - } - - { - const CELTMode *celt_mode; - 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) - { - celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); - 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); - 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); - } - if (redundancy && celt_to_silk) - { - 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; - x = MULT16_32_P16(pcm[i],gain); - pcm[i] = SATURATE(x, 32767); - } - } - - if (len <= 1) - st->rangeFinal = 0; - else - st->rangeFinal = dec.rng ^ 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_val16 *pcm, int frame_size, int decode_fec, - int self_delimited, opus_int32 *packet_offset, int soft_clip) -{ - 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]; - 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; - 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); - 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); - if (count<0) - return 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); - /* 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); - 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); - 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; - ret = opus_decode_frame(st, data, size[i], pcm+nb_samples*st->channels, frame_size-nb_samples, 0); - 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 OPUS_FIXED_POINT - if (soft_clip) - opus_pcm_soft_clip(pcm, nb_samples, st->channels, st->softclip_mem); - else - st->softclip_mem[0]=st->softclip_mem[1]=0; -#endif - return nb_samples; -} - -#ifdef OPUS_FIXED_POINT - -int opus_decode(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); -} - -#ifndef DISABLE_FLOAT_API -int opus_decode_float(OpusDecoder *st, const unsigned char *data, - opus_int32 len, float *pcm, int frame_size, int decode_fec) -{ - VARDECL(opus_int16, 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; - } - ALLOC(out, frame_size*st->channels, opus_int16); - - ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0); - if (ret > 0) - { - for (i=0;i<ret*st->channels;i++) - pcm[i] = (1.f/32768.f)*(out[i]); - } - RESTORE_STACK; - return ret; -} -#endif - - -#else -int opus_decode(OpusDecoder *st, const unsigned char *data, - opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec) -{ - VARDECL(float, 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; - } - ALLOC(out, frame_size*st->channels, float); - - ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1); - if (ret > 0) - { - for (i=0;i<ret*st->channels;i++) - pcm[i] = FLOAT2INT16(out[i]); - } - RESTORE_STACK; - return ret; -} - -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); -} - -#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_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_InitDecoder( silk_dec ); - st->stream_channels = st->channels; - st->frame_size = st->Fs/400; - } - 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) - 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_uint32 *value = va_arg(ap, opus_uint32*); - if (!value) - { - goto bad_arg; - } - *value = st->last_packet_duration; - } - break; - 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_decoder_get_nb_samples(const OpusDecoder *dec, - const unsigned char packet[], opus_int32 len) -{ - return opus_packet_get_nb_samples(packet, len, dec->Fs); -} diff --git a/drivers/opus/opus_defines.h b/drivers/opus/opus_defines.h deleted file mode 100644 index b972ce0eb9..0000000000 --- a/drivers/opus/opus_defines.h +++ /dev/null @@ -1,753 +0,0 @@ -/* 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/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) -# ifdef OPUS_BUILD -# 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 */ - -/* 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)) -#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_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr))) -/** @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 - -#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 */ - -/**@}*/ - - -/** @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>Enable inband FEC.</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.</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_VARIABLE</dt><dd>Optimize the frame size dynamically.</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_VARIABLE</dt><dd>Optimize the frame size dynamically.</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) - -/**@}*/ - -/** @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) - -/**@}*/ - -/** @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) - -/**@}*/ - -/** @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/drivers/opus/opus_encoder.c b/drivers/opus/opus_encoder.c deleted file mode 100644 index 5c6af5a199..0000000000 --- a/drivers/opus/opus_encoder.c +++ /dev/null @@ -1,2524 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include <stdarg.h> -#include "opus/celt/celt.h" -#include "opus/celt/entenc.h" -#include "opus/celt/modes.h" -#include "opus/silk/API.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/float_cast.h" -#include "opus/opus.h" -#include "opus/celt/arch.h" -#include "opus/celt/pitch.h" -#include "opus/opus_private.h" -#include "opus/celt/os_support.h" -#include "opus/celt/cpu_support.h" -#include "opus/analysis.h" -#include "opus/celt/mathops.h" -#include "opus/silk/tuning_parameters.h" -#ifdef OPUS_FIXED_POINT -#include "opus/silk/fixed/structs_FIX.h" -#else -#include "opus/silk/float/structs_FLP.h" -#endif - -#define MAX_ENCODER_BUFFER 480 - -typedef struct { - opus_val32 XX, XY, YY; - opus_val16 smoothed_width; - opus_val16 max_follower; -} StereoWidthState; - -struct OpusEncoder { - int celt_enc_offset; - int silk_enc_offset; - silk_EncControlStruct silk_mode; - int application; - int channels; - int delay_compensation; - int force_channels; - int signal_type; - int user_bandwidth; - int max_bandwidth; - int user_forced_mode; - int voice_ratio; - opus_int32 Fs; - int use_vbr; - int vbr_constraint; - int variable_duration; - opus_int32 bitrate_bps; - opus_int32 user_bitrate_bps; - int lsb_depth; - int encoder_buffer; - int lfe; - int arch; -#ifndef DISABLE_FLOAT_API - TonalityAnalysisState analysis; -#endif - -#define OPUS_ENCODER_RESET_START stream_channels - int stream_channels; - opus_int16 hybrid_stereo_width_Q14; - opus_int32 variable_HP_smth2_Q15; - opus_val16 prev_HB_gain; - opus_val32 hp_mem[4]; - int mode; - int prev_mode; - int prev_channels; - int prev_framesize; - int bandwidth; - int silk_bw_switch; - /* Sampling rate (at the API level) */ - int first; - opus_val16 * energy_masking; - StereoWidthState width_mem; - opus_val16 delay_buffer[MAX_ENCODER_BUFFER*2]; -#ifndef DISABLE_FLOAT_API - int detected_bandwidth; -#endif - opus_uint32 rangeFinal; -}; - -/* Transition tables for the voice and music. First column is the - middle (memoriless) threshold. The second column is the hysteresis - (difference with the middle) */ -static const opus_int32 mono_voice_bandwidth_thresholds[8] = { - 11000, 1000, /* NB<->MB */ - 14000, 1000, /* MB<->WB */ - 17000, 1000, /* WB<->SWB */ - 21000, 2000, /* SWB<->FB */ -}; -static const opus_int32 mono_music_bandwidth_thresholds[8] = { - 12000, 1000, /* NB<->MB */ - 15000, 1000, /* MB<->WB */ - 18000, 2000, /* WB<->SWB */ - 22000, 2000, /* SWB<->FB */ -}; -static const opus_int32 stereo_voice_bandwidth_thresholds[8] = { - 11000, 1000, /* NB<->MB */ - 14000, 1000, /* MB<->WB */ - 21000, 2000, /* WB<->SWB */ - 28000, 2000, /* SWB<->FB */ -}; -static const opus_int32 stereo_music_bandwidth_thresholds[8] = { - 12000, 1000, /* NB<->MB */ - 18000, 2000, /* MB<->WB */ - 21000, 2000, /* WB<->SWB */ - 30000, 2000, /* SWB<->FB */ -}; -/* Threshold bit-rates for switching between mono and stereo */ -static const opus_int32 stereo_voice_threshold = 30000; -static const opus_int32 stereo_music_threshold = 30000; - -/* Threshold bit-rate for switching between SILK/hybrid and CELT-only */ -static const opus_int32 mode_thresholds[2][2] = { - /* voice */ /* music */ - { 64000, 16000}, /* mono */ - { 36000, 16000}, /* stereo */ -}; - -int opus_encoder_get_size(int channels) -{ - int silkEncSizeBytes, celtEncSizeBytes; - int ret; - if (channels<1 || channels > 2) - return 0; - ret = silk_Get_Encoder_Size( &silkEncSizeBytes ); - if (ret) - return 0; - silkEncSizeBytes = align(silkEncSizeBytes); - celtEncSizeBytes = celt_encoder_get_size(channels); - return align(sizeof(OpusEncoder))+silkEncSizeBytes+celtEncSizeBytes; -} - -int opus_encoder_init(OpusEncoder* st, opus_int32 Fs, int channels, int application) -{ - void *silk_enc; - CELTEncoder *celt_enc; - int err; - int ret, silkEncSizeBytes; - - if((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)||(channels!=1&&channels!=2)|| - (application != OPUS_APPLICATION_VOIP && application != OPUS_APPLICATION_AUDIO - && application != OPUS_APPLICATION_RESTRICTED_LOWDELAY)) - return OPUS_BAD_ARG; - - OPUS_CLEAR((char*)st, opus_encoder_get_size(channels)); - /* Create SILK encoder */ - ret = silk_Get_Encoder_Size( &silkEncSizeBytes ); - if (ret) - return OPUS_BAD_ARG; - silkEncSizeBytes = align(silkEncSizeBytes); - st->silk_enc_offset = align(sizeof(OpusEncoder)); - st->celt_enc_offset = st->silk_enc_offset+silkEncSizeBytes; - silk_enc = (char*)st+st->silk_enc_offset; - celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset); - - st->stream_channels = st->channels = channels; - - st->Fs = Fs; - - st->arch = opus_select_arch(); - - ret = silk_InitEncoder( silk_enc, st->arch, &st->silk_mode ); - if(ret)return OPUS_INTERNAL_ERROR; - - /* default SILK parameters */ - st->silk_mode.nChannelsAPI = channels; - st->silk_mode.nChannelsInternal = channels; - st->silk_mode.API_sampleRate = st->Fs; - st->silk_mode.maxInternalSampleRate = 16000; - st->silk_mode.minInternalSampleRate = 8000; - st->silk_mode.desiredInternalSampleRate = 16000; - st->silk_mode.payloadSize_ms = 20; - st->silk_mode.bitRate = 25000; - st->silk_mode.packetLossPercentage = 0; - st->silk_mode.complexity = 9; - st->silk_mode.useInBandFEC = 0; - st->silk_mode.useDTX = 0; - st->silk_mode.useCBR = 0; - st->silk_mode.reducedDependency = 0; - - /* Create CELT encoder */ - /* Initialize CELT encoder */ - err = celt_encoder_init(celt_enc, Fs, channels, st->arch); - if(err!=OPUS_OK)return OPUS_INTERNAL_ERROR; - - celt_encoder_ctl(celt_enc, CELT_SET_SIGNALLING(0)); - celt_encoder_ctl(celt_enc, OPUS_SET_COMPLEXITY(st->silk_mode.complexity)); - - st->use_vbr = 1; - /* Makes constrained VBR the default (safer for real-time use) */ - st->vbr_constraint = 1; - st->user_bitrate_bps = OPUS_AUTO; - st->bitrate_bps = 3000+Fs*channels; - st->application = application; - st->signal_type = OPUS_AUTO; - st->user_bandwidth = OPUS_AUTO; - st->max_bandwidth = OPUS_BANDWIDTH_FULLBAND; - st->force_channels = OPUS_AUTO; - st->user_forced_mode = OPUS_AUTO; - st->voice_ratio = -1; - st->encoder_buffer = st->Fs/100; - st->lsb_depth = 24; - st->variable_duration = OPUS_FRAMESIZE_ARG; - - /* Delay compensation of 4 ms (2.5 ms for SILK's extra look-ahead - + 1.5 ms for SILK resamplers and stereo prediction) */ - st->delay_compensation = st->Fs/250; - - st->hybrid_stereo_width_Q14 = 1 << 14; - st->prev_HB_gain = Q15ONE; - st->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ); - st->first = 1; - st->mode = MODE_HYBRID; - st->bandwidth = OPUS_BANDWIDTH_FULLBAND; - -#ifndef DISABLE_FLOAT_API - tonality_analysis_init(&st->analysis); -#endif - - return OPUS_OK; -} - -static unsigned char gen_toc(int mode, int framerate, int bandwidth, int channels) -{ - int period; - unsigned char toc; - period = 0; - while (framerate < 400) - { - framerate <<= 1; - period++; - } - if (mode == MODE_SILK_ONLY) - { - toc = (bandwidth-OPUS_BANDWIDTH_NARROWBAND)<<5; - toc |= (period-2)<<3; - } else if (mode == MODE_CELT_ONLY) - { - int tmp = bandwidth-OPUS_BANDWIDTH_MEDIUMBAND; - if (tmp < 0) - tmp = 0; - toc = 0x80; - toc |= tmp << 5; - toc |= period<<3; - } else /* Hybrid */ - { - toc = 0x60; - toc |= (bandwidth-OPUS_BANDWIDTH_SUPERWIDEBAND)<<4; - toc |= (period-2)<<3; - } - toc |= (channels==2)<<2; - return toc; -} - -#ifndef OPUS_FIXED_POINT -static void silk_biquad_float( - const opus_val16 *in, /* I: Input signal */ - const opus_int32 *B_Q28, /* I: MA coefficients [3] */ - const opus_int32 *A_Q28, /* I: AR coefficients [2] */ - opus_val32 *S, /* I/O: State vector [2] */ - opus_val16 *out, /* O: Output signal */ - const opus_int32 len, /* I: Signal length (must be even) */ - int stride -) -{ - /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */ - opus_int k; - opus_val32 vout; - opus_val32 inval; - opus_val32 A[2], B[3]; - - A[0] = (opus_val32)(A_Q28[0] * (1.f/((opus_int32)1<<28))); - A[1] = (opus_val32)(A_Q28[1] * (1.f/((opus_int32)1<<28))); - B[0] = (opus_val32)(B_Q28[0] * (1.f/((opus_int32)1<<28))); - B[1] = (opus_val32)(B_Q28[1] * (1.f/((opus_int32)1<<28))); - B[2] = (opus_val32)(B_Q28[2] * (1.f/((opus_int32)1<<28))); - - /* Negate A_Q28 values and split in two parts */ - - for( k = 0; k < len; k++ ) { - /* S[ 0 ], S[ 1 ]: Q12 */ - inval = in[ k*stride ]; - vout = S[ 0 ] + B[0]*inval; - - S[ 0 ] = S[1] - vout*A[0] + B[1]*inval; - - S[ 1 ] = - vout*A[1] + B[2]*inval + VERY_SMALL; - - /* Scale back to Q0 and saturate */ - out[ k*stride ] = vout; - } -} -#endif - -static void hp_cutoff(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs) -{ - opus_int32 B_Q28[ 3 ], A_Q28[ 2 ]; - opus_int32 Fc_Q19, r_Q28, r_Q22; - - silk_assert( cutoff_Hz <= silk_int32_MAX / SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ) ); - Fc_Q19 = silk_DIV32_16( silk_SMULBB( SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ), cutoff_Hz ), Fs/1000 ); - silk_assert( Fc_Q19 > 0 && Fc_Q19 < 32768 ); - - r_Q28 = SILK_FIX_CONST( 1.0, 28 ) - silk_MUL( SILK_FIX_CONST( 0.92, 9 ), Fc_Q19 ); - - /* b = r * [ 1; -2; 1 ]; */ - /* a = [ 1; -2 * r * ( 1 - 0.5 * Fc^2 ); r^2 ]; */ - B_Q28[ 0 ] = r_Q28; - B_Q28[ 1 ] = silk_LSHIFT( -r_Q28, 1 ); - B_Q28[ 2 ] = r_Q28; - - /* -r * ( 2 - Fc * Fc ); */ - r_Q22 = silk_RSHIFT( r_Q28, 6 ); - A_Q28[ 0 ] = silk_SMULWW( r_Q22, silk_SMULWW( Fc_Q19, Fc_Q19 ) - SILK_FIX_CONST( 2.0, 22 ) ); - A_Q28[ 1 ] = silk_SMULWW( r_Q22, r_Q22 ); - -#ifdef OPUS_FIXED_POINT - silk_biquad_alt( in, B_Q28, A_Q28, hp_mem, out, len, channels ); - if( channels == 2 ) { - silk_biquad_alt( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels ); - } -#else - silk_biquad_float( in, B_Q28, A_Q28, hp_mem, out, len, channels ); - if( channels == 2 ) { - silk_biquad_float( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels ); - } -#endif -} - -#ifdef OPUS_FIXED_POINT -static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs) -{ - int c, i; - int shift; - - /* Approximates -round(log2(4.*cutoff_Hz/Fs)) */ - shift=celt_ilog2(Fs/(cutoff_Hz*3)); - for (c=0;c<channels;c++) - { - for (i=0;i<len;i++) - { - opus_val32 x, tmp, y; - x = SHL32(EXTEND32(in[channels*i+c]), 15); - /* First stage */ - tmp = x-hp_mem[2*c]; - hp_mem[2*c] = hp_mem[2*c] + PSHR32(x - hp_mem[2*c], shift); - /* Second stage */ - y = tmp - hp_mem[2*c+1]; - hp_mem[2*c+1] = hp_mem[2*c+1] + PSHR32(tmp - hp_mem[2*c+1], shift); - out[channels*i+c] = EXTRACT16(SATURATE(PSHR32(y, 15), 32767)); - } - } -} - -#else -static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs) -{ - int c, i; - float coef; - - coef = 4.0f*cutoff_Hz/Fs; - for (c=0;c<channels;c++) - { - for (i=0;i<len;i++) - { - opus_val32 x, tmp, y; - x = in[channels*i+c]; - /* First stage */ - tmp = x-hp_mem[2*c]; - hp_mem[2*c] = hp_mem[2*c] + coef*(x - hp_mem[2*c]) + VERY_SMALL; - /* Second stage */ - y = tmp - hp_mem[2*c+1]; - hp_mem[2*c+1] = hp_mem[2*c+1] + coef*(tmp - hp_mem[2*c+1]) + VERY_SMALL; - out[channels*i+c] = y; - } - } -} -#endif - -static void stereo_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus_val16 g2, - int overlap48, int frame_size, int channels, const opus_val16 *window, opus_int32 Fs) -{ - int i; - int overlap; - int inc; - inc = 48000/Fs; - overlap=overlap48/inc; - g1 = Q15ONE-g1; - g2 = Q15ONE-g2; - for (i=0;i<overlap;i++) - { - opus_val32 diff; - opus_val16 g, w; - w = MULT16_16_Q15(window[i*inc], window[i*inc]); - g = SHR32(MAC16_16(MULT16_16(w,g2), - Q15ONE-w, g1), 15); - diff = EXTRACT16(HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1])); - diff = MULT16_16_Q15(g, diff); - out[i*channels] = out[i*channels] - diff; - out[i*channels+1] = out[i*channels+1] + diff; - } - for (;i<frame_size;i++) - { - opus_val32 diff; - diff = EXTRACT16(HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1])); - diff = MULT16_16_Q15(g2, diff); - out[i*channels] = out[i*channels] - diff; - out[i*channels+1] = out[i*channels+1] + diff; - } -} - -static void gain_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus_val16 g2, - int overlap48, int frame_size, int channels, const opus_val16 *window, opus_int32 Fs) -{ - int i; - int inc; - int overlap; - int c; - inc = 48000/Fs; - overlap=overlap48/inc; - if (channels==1) - { - for (i=0;i<overlap;i++) - { - opus_val16 g, w; - w = MULT16_16_Q15(window[i*inc], window[i*inc]); - g = SHR32(MAC16_16(MULT16_16(w,g2), - Q15ONE-w, g1), 15); - out[i] = MULT16_16_Q15(g, in[i]); - } - } else { - for (i=0;i<overlap;i++) - { - opus_val16 g, w; - w = MULT16_16_Q15(window[i*inc], window[i*inc]); - g = SHR32(MAC16_16(MULT16_16(w,g2), - Q15ONE-w, g1), 15); - out[i*2] = MULT16_16_Q15(g, in[i*2]); - out[i*2+1] = MULT16_16_Q15(g, in[i*2+1]); - } - } - c=0;do { - for (i=overlap;i<frame_size;i++) - { - out[i*channels+c] = MULT16_16_Q15(g2, in[i*channels+c]); - } - } - while (++c<channels); -} - -OpusEncoder *opus_encoder_create(opus_int32 Fs, int channels, int application, int *error) -{ - int ret; - OpusEncoder *st; - if((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)||(channels!=1&&channels!=2)|| - (application != OPUS_APPLICATION_VOIP && application != OPUS_APPLICATION_AUDIO - && application != OPUS_APPLICATION_RESTRICTED_LOWDELAY)) - { - if (error) - *error = OPUS_BAD_ARG; - return NULL; - } - st = (OpusEncoder *)opus_alloc(opus_encoder_get_size(channels)); - if (st == NULL) - { - if (error) - *error = OPUS_ALLOC_FAIL; - return NULL; - } - ret = opus_encoder_init(st, Fs, channels, application); - if (error) - *error = ret; - if (ret != OPUS_OK) - { - opus_free(st); - st = NULL; - } - return st; -} - -static opus_int32 user_bitrate_to_bitrate(OpusEncoder *st, int frame_size, int max_data_bytes) -{ - if(!frame_size)frame_size=st->Fs/400; - if (st->user_bitrate_bps==OPUS_AUTO) - return 60*st->Fs/frame_size + st->Fs*st->channels; - else if (st->user_bitrate_bps==OPUS_BITRATE_MAX) - return max_data_bytes*8*st->Fs/frame_size; - else - return st->user_bitrate_bps; -} - -#ifndef DISABLE_FLOAT_API -/* Don't use more than 60 ms for the frame size analysis */ -#define MAX_DYNAMIC_FRAMESIZE 24 -/* Estimates how much the bitrate will be boosted based on the sub-frame energy */ -static float transient_boost(const float *E, const float *E_1, int LM, int maxM) -{ - int i; - int M; - float sumE=0, sumE_1=0; - float metric; - - M = IMIN(maxM, (1<<LM)+1); - for (i=0;i<M;i++) - { - sumE += E[i]; - sumE_1 += E_1[i]; - } - metric = sumE*sumE_1/(M*M); - /*if (LM==3) - printf("%f\n", metric);*/ - /*return metric>10 ? 1 : 0;*/ - /*return MAX16(0,1-exp(-.25*(metric-2.)));*/ - return MIN16(1,(float)sqrt(MAX16(0,.05f*(metric-2)))); -} - -/* Viterbi decoding trying to find the best frame size combination using look-ahead - - State numbering: - 0: unused - 1: 2.5 ms - 2: 5 ms (#1) - 3: 5 ms (#2) - 4: 10 ms (#1) - 5: 10 ms (#2) - 6: 10 ms (#3) - 7: 10 ms (#4) - 8: 20 ms (#1) - 9: 20 ms (#2) - 10: 20 ms (#3) - 11: 20 ms (#4) - 12: 20 ms (#5) - 13: 20 ms (#6) - 14: 20 ms (#7) - 15: 20 ms (#8) -*/ -static int transient_viterbi(const float *E, const float *E_1, int N, int frame_cost, int rate) -{ - int i; - float cost[MAX_DYNAMIC_FRAMESIZE][16]; - int states[MAX_DYNAMIC_FRAMESIZE][16]; - float best_cost; - int best_state; - float factor; - /* Take into account that we damp VBR in the 32 kb/s to 64 kb/s range. */ - if (rate<80) - factor=0; - else if (rate>160) - factor=1; - else - factor = (rate-80.f)/80.f; - /* Makes variable framesize less aggressive at lower bitrates, but I can't - find any valid theoretical justification for this (other than it seems - to help) */ - for (i=0;i<16;i++) - { - /* Impossible state */ - states[0][i] = -1; - cost[0][i] = 1e10; - } - for (i=0;i<4;i++) - { - cost[0][1<<i] = (frame_cost + rate*(1<<i))*(1+factor*transient_boost(E, E_1, i, N+1)); - states[0][1<<i] = i; - } - for (i=1;i<N;i++) - { - int j; - - /* Follow continuations */ - for (j=2;j<16;j++) - { - cost[i][j] = cost[i-1][j-1]; - states[i][j] = j-1; - } - - /* New frames */ - for(j=0;j<4;j++) - { - int k; - float min_cost; - float curr_cost; - states[i][1<<j] = 1; - min_cost = cost[i-1][1]; - for(k=1;k<4;k++) - { - float tmp = cost[i-1][(1<<(k+1))-1]; - if (tmp < min_cost) - { - states[i][1<<j] = (1<<(k+1))-1; - min_cost = tmp; - } - } - curr_cost = (frame_cost + rate*(1<<j))*(1+factor*transient_boost(E+i, E_1+i, j, N-i+1)); - cost[i][1<<j] = min_cost; - /* If part of the frame is outside the analysis window, only count part of the cost */ - if (N-i < (1<<j)) - cost[i][1<<j] += curr_cost*(float)(N-i)/(1<<j); - else - cost[i][1<<j] += curr_cost; - } - } - - best_state=1; - best_cost = cost[N-1][1]; - /* Find best end state (doesn't force a frame to end at N-1) */ - for (i=2;i<16;i++) - { - if (cost[N-1][i]<best_cost) - { - best_cost = cost[N-1][i]; - best_state = i; - } - } - - /* Follow transitions back */ - for (i=N-1;i>=0;i--) - { - /*printf("%d ", best_state);*/ - best_state = states[i][best_state]; - } - /*printf("%d\n", best_state);*/ - return best_state; -} - -static int optimize_framesize(const void *x, int len, int C, opus_int32 Fs, - int bitrate, opus_val16 tonality, float *mem, int buffering, - downmix_func downmix) -{ - int N; - int i; - float e[MAX_DYNAMIC_FRAMESIZE+4]; - float e_1[MAX_DYNAMIC_FRAMESIZE+3]; - opus_val32 memx; - int bestLM=0; - int subframe; - int pos; - int offset; - VARDECL(opus_val32, sub); - - subframe = Fs/400; - ALLOC(sub, subframe, opus_val32); - e[0]=mem[0]; - e_1[0]=1.f/(EPSILON+mem[0]); - if (buffering) - { - /* Consider the CELT delay when not in restricted-lowdelay */ - /* We assume the buffering is between 2.5 and 5 ms */ - offset = 2*subframe - buffering; - celt_assert(offset>=0 && offset <= subframe); - len -= offset; - e[1]=mem[1]; - e_1[1]=1.f/(EPSILON+mem[1]); - e[2]=mem[2]; - e_1[2]=1.f/(EPSILON+mem[2]); - pos = 3; - } else { - pos=1; - offset=0; - } - N=IMIN(len/subframe, MAX_DYNAMIC_FRAMESIZE); - /* Just silencing a warning, it's really initialized later */ - memx = 0; - for (i=0;i<N;i++) - { - float tmp; - opus_val32 tmpx; - int j; - tmp=EPSILON; - - downmix(x, sub, subframe, i*subframe+offset, 0, -2, C); - if (i==0) - memx = sub[0]; - for (j=0;j<subframe;j++) - { - tmpx = sub[j]; - tmp += (tmpx-memx)*(float)(tmpx-memx); - memx = tmpx; - } - e[i+pos] = tmp; - e_1[i+pos] = 1.f/tmp; - } - /* Hack to get 20 ms working with APPLICATION_AUDIO - The real problem is that the corresponding memory needs to use 1.5 ms - from this frame and 1 ms from the next frame */ - e[i+pos] = e[i+pos-1]; - if (buffering) - N=IMIN(MAX_DYNAMIC_FRAMESIZE, N+2); - bestLM = transient_viterbi(e, e_1, N, (int)((1.f+.5f*tonality)*(60*C+40)), bitrate/400); - mem[0] = e[1<<bestLM]; - if (buffering) - { - mem[1] = e[(1<<bestLM)+1]; - mem[2] = e[(1<<bestLM)+2]; - } - return bestLM; -} - -#endif - -#ifndef DISABLE_FLOAT_API -#ifdef OPUS_FIXED_POINT -#define PCM2VAL(x) FLOAT2INT16(x) -#else -#define PCM2VAL(x) SCALEIN(x) -#endif -void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C) -{ - const float *x; - opus_val32 scale; - int j; - x = (const float *)_x; - for (j=0;j<subframe;j++) - sub[j] = PCM2VAL(x[(j+offset)*C+c1]); - if (c2>-1) - { - for (j=0;j<subframe;j++) - sub[j] += PCM2VAL(x[(j+offset)*C+c2]); - } else if (c2==-2) - { - int c; - for (c=1;c<C;c++) - { - for (j=0;j<subframe;j++) - sub[j] += PCM2VAL(x[(j+offset)*C+c]); - } - } -#ifdef OPUS_FIXED_POINT - scale = (1<<SIG_SHIFT); -#else - scale = 1.f; -#endif - if (C==-2) - scale /= C; - else - scale /= 2; - for (j=0;j<subframe;j++) - sub[j] *= scale; -} -#endif - -void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C) -{ - const opus_int16 *x; - opus_val32 scale; - int j; - x = (const opus_int16 *)_x; - for (j=0;j<subframe;j++) - sub[j] = x[(j+offset)*C+c1]; - if (c2>-1) - { - for (j=0;j<subframe;j++) - sub[j] += x[(j+offset)*C+c2]; - } else if (c2==-2) - { - int c; - for (c=1;c<C;c++) - { - for (j=0;j<subframe;j++) - sub[j] += x[(j+offset)*C+c]; - } - } -#ifdef OPUS_FIXED_POINT - scale = (1<<SIG_SHIFT); -#else - scale = 1.f/32768; -#endif - if (C==-2) - scale /= C; - else - scale /= 2; - for (j=0;j<subframe;j++) - sub[j] *= scale; -} - -opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs) -{ - int new_size; - if (frame_size<Fs/400) - return -1; - if (variable_duration == OPUS_FRAMESIZE_ARG) - new_size = frame_size; - else if (variable_duration == OPUS_FRAMESIZE_VARIABLE) - new_size = Fs/50; - else if (variable_duration >= OPUS_FRAMESIZE_2_5_MS && variable_duration <= OPUS_FRAMESIZE_60_MS) - new_size = IMIN(3*Fs/50, (Fs/400)<<(variable_duration-OPUS_FRAMESIZE_2_5_MS)); - else - return -1; - if (new_size>frame_size) - return -1; - if (400*new_size!=Fs && 200*new_size!=Fs && 100*new_size!=Fs && - 50*new_size!=Fs && 25*new_size!=Fs && 50*new_size!=3*Fs) - return -1; - return new_size; -} - -opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size, - int variable_duration, int C, opus_int32 Fs, int bitrate_bps, - int delay_compensation, downmix_func downmix -#ifndef DISABLE_FLOAT_API - , float *subframe_mem -#endif - ) -{ -#ifndef DISABLE_FLOAT_API - if (variable_duration == OPUS_FRAMESIZE_VARIABLE && frame_size >= Fs/200) - { - int LM = 3; - LM = optimize_framesize(analysis_pcm, frame_size, C, Fs, bitrate_bps, - 0, subframe_mem, delay_compensation, downmix); - while ((Fs/400<<LM)>frame_size) - LM--; - frame_size = (Fs/400<<LM); - } else -#else - (void)analysis_pcm; - (void)C; - (void)bitrate_bps; - (void)delay_compensation; - (void)downmix; -#endif - { - frame_size = frame_size_select(frame_size, variable_duration, Fs); - } - if (frame_size<0) - return -1; - return frame_size; -} - -opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int32 Fs, StereoWidthState *mem) -{ - opus_val16 corr; - opus_val16 ldiff; - opus_val16 width; - opus_val32 xx, xy, yy; - opus_val16 sqrt_xx, sqrt_yy; - opus_val16 qrrt_xx, qrrt_yy; - int frame_rate; - int i; - opus_val16 short_alpha; - - frame_rate = Fs/frame_size; - short_alpha = Q15ONE - 25*Q15ONE/IMAX(50,frame_rate); - xx=xy=yy=0; - for (i=0;i<frame_size;i+=4) - { - opus_val32 pxx=0; - opus_val32 pxy=0; - opus_val32 pyy=0; - opus_val16 x, y; - x = pcm[2*i]; - y = pcm[2*i+1]; - pxx = SHR32(MULT16_16(x,x),2); - pxy = SHR32(MULT16_16(x,y),2); - pyy = SHR32(MULT16_16(y,y),2); - x = pcm[2*i+2]; - y = pcm[2*i+3]; - pxx += SHR32(MULT16_16(x,x),2); - pxy += SHR32(MULT16_16(x,y),2); - pyy += SHR32(MULT16_16(y,y),2); - x = pcm[2*i+4]; - y = pcm[2*i+5]; - pxx += SHR32(MULT16_16(x,x),2); - pxy += SHR32(MULT16_16(x,y),2); - pyy += SHR32(MULT16_16(y,y),2); - x = pcm[2*i+6]; - y = pcm[2*i+7]; - pxx += SHR32(MULT16_16(x,x),2); - pxy += SHR32(MULT16_16(x,y),2); - pyy += SHR32(MULT16_16(y,y),2); - - xx += SHR32(pxx, 10); - xy += SHR32(pxy, 10); - yy += SHR32(pyy, 10); - } - mem->XX += MULT16_32_Q15(short_alpha, xx-mem->XX); - mem->XY += MULT16_32_Q15(short_alpha, xy-mem->XY); - mem->YY += MULT16_32_Q15(short_alpha, yy-mem->YY); - mem->XX = MAX32(0, mem->XX); - mem->XY = MAX32(0, mem->XY); - mem->YY = MAX32(0, mem->YY); - if (MAX32(mem->XX, mem->YY)>QCONST16(8e-4f, 18)) - { - sqrt_xx = celt_sqrt(mem->XX); - sqrt_yy = celt_sqrt(mem->YY); - qrrt_xx = celt_sqrt(sqrt_xx); - qrrt_yy = celt_sqrt(sqrt_yy); - /* Inter-channel correlation */ - mem->XY = MIN32(mem->XY, sqrt_xx*sqrt_yy); - corr = SHR32(frac_div32(mem->XY,EPSILON+MULT16_16(sqrt_xx,sqrt_yy)),16); - /* Approximate loudness difference */ - ldiff = Q15ONE*ABS16(qrrt_xx-qrrt_yy)/(EPSILON+qrrt_xx+qrrt_yy); - width = MULT16_16_Q15(celt_sqrt(QCONST32(1.f,30)-MULT16_16(corr,corr)), ldiff); - /* Smoothing over one second */ - mem->smoothed_width += (width-mem->smoothed_width)/frame_rate; - /* Peak follower */ - mem->max_follower = MAX16(mem->max_follower-QCONST16(.02f,15)/frame_rate, mem->smoothed_width); - } else { - width = 0; - corr=Q15ONE; - ldiff=0; - } - /*printf("%f %f %f %f %f ", corr/(float)Q15ONE, ldiff/(float)Q15ONE, width/(float)Q15ONE, mem->smoothed_width/(float)Q15ONE, mem->max_follower/(float)Q15ONE);*/ - return EXTRACT16(MIN32(Q15ONE,20*mem->max_follower)); -} - -opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *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) -{ - void *silk_enc; - CELTEncoder *celt_enc; - int i; - int ret=0; - opus_int32 nBytes; - ec_enc enc; - int bytes_target; - int prefill=0; - int start_band = 0; - int redundancy = 0; - int redundancy_bytes = 0; /* Number of bytes to use for redundancy frame */ - int celt_to_silk = 0; - VARDECL(opus_val16, pcm_buf); - int nb_compr_bytes; - int to_celt = 0; - opus_uint32 redundant_rng = 0; - int cutoff_Hz, hp_freq_smth1; - int voice_est; /* Probability of voice in Q7 */ - opus_int32 equiv_rate; - int delay_compensation; - int frame_rate; - opus_int32 max_rate; /* Max bitrate we're allowed to use */ - int curr_bandwidth; - opus_val16 HB_gain; - opus_int32 max_data_bytes; /* Max number of bytes we're allowed to use */ - int total_buffer; - opus_val16 stereo_width; - const CELTMode *celt_mode; -#ifndef DISABLE_FLOAT_API - AnalysisInfo analysis_info; - int analysis_read_pos_bak=-1; - int analysis_read_subframe_bak=-1; -#endif - VARDECL(opus_val16, tmp_prefill); - - ALLOC_STACK; - - max_data_bytes = IMIN(1276, out_data_bytes); - - st->rangeFinal = 0; - if ((!st->variable_duration && 400*frame_size != st->Fs && 200*frame_size != st->Fs && 100*frame_size != st->Fs && - 50*frame_size != st->Fs && 25*frame_size != st->Fs && 50*frame_size != 3*st->Fs) - || (400*frame_size < st->Fs) - || max_data_bytes<=0 - ) - { - RESTORE_STACK; - return OPUS_BAD_ARG; - } - silk_enc = (char*)st+st->silk_enc_offset; - celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset); - if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) - delay_compensation = 0; - else - delay_compensation = st->delay_compensation; - - lsb_depth = IMIN(lsb_depth, st->lsb_depth); - - celt_encoder_ctl(celt_enc, CELT_GET_MODE(&celt_mode)); -#ifndef DISABLE_FLOAT_API - analysis_info.valid = 0; -#ifdef OPUS_FIXED_POINT - if (st->silk_mode.complexity >= 10 && st->Fs==48000) -#else - if (st->silk_mode.complexity >= 7 && st->Fs==48000) -#endif - { - analysis_read_pos_bak = st->analysis.read_pos; - analysis_read_subframe_bak = st->analysis.read_subframe; - run_analysis(&st->analysis, celt_mode, analysis_pcm, analysis_size, frame_size, - c1, c2, analysis_channels, st->Fs, - lsb_depth, downmix, &analysis_info); - } -#else - (void)analysis_pcm; - (void)analysis_size; -#endif - - st->voice_ratio = -1; - -#ifndef DISABLE_FLOAT_API - st->detected_bandwidth = 0; - if (analysis_info.valid) - { - int analysis_bandwidth; - if (st->signal_type == OPUS_AUTO) - st->voice_ratio = (int)floor(.5+100*(1-analysis_info.music_prob)); - - analysis_bandwidth = analysis_info.bandwidth; - if (analysis_bandwidth<=12) - st->detected_bandwidth = OPUS_BANDWIDTH_NARROWBAND; - else if (analysis_bandwidth<=14) - st->detected_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; - else if (analysis_bandwidth<=16) - st->detected_bandwidth = OPUS_BANDWIDTH_WIDEBAND; - else if (analysis_bandwidth<=18) - st->detected_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; - else - st->detected_bandwidth = OPUS_BANDWIDTH_FULLBAND; - } -#endif - - if (st->channels==2 && st->force_channels!=1) - stereo_width = compute_stereo_width(pcm, frame_size, st->Fs, &st->width_mem); - else - stereo_width = 0; - total_buffer = delay_compensation; - st->bitrate_bps = user_bitrate_to_bitrate(st, frame_size, max_data_bytes); - - frame_rate = st->Fs/frame_size; - if (max_data_bytes<3 || st->bitrate_bps < 3*frame_rate*8 - || (frame_rate<50 && (max_data_bytes*frame_rate<300 || st->bitrate_bps < 2400))) - { - /*If the space is too low to do something useful, emit 'PLC' frames.*/ - int tocmode = st->mode; - int bw = st->bandwidth == 0 ? OPUS_BANDWIDTH_NARROWBAND : st->bandwidth; - if (tocmode==0) - tocmode = MODE_SILK_ONLY; - if (frame_rate>100) - tocmode = MODE_CELT_ONLY; - if (frame_rate < 50) - tocmode = MODE_SILK_ONLY; - if(tocmode==MODE_SILK_ONLY&&bw>OPUS_BANDWIDTH_WIDEBAND) - bw=OPUS_BANDWIDTH_WIDEBAND; - else if (tocmode==MODE_CELT_ONLY&&bw==OPUS_BANDWIDTH_MEDIUMBAND) - bw=OPUS_BANDWIDTH_NARROWBAND; - else if (bw<=OPUS_BANDWIDTH_SUPERWIDEBAND) - bw=OPUS_BANDWIDTH_SUPERWIDEBAND; - data[0] = gen_toc(tocmode, frame_rate, bw, st->stream_channels); - RESTORE_STACK; - return 1; - } - if (!st->use_vbr) - { - int cbrBytes; - cbrBytes = IMIN( (st->bitrate_bps + 4*frame_rate)/(8*frame_rate) , max_data_bytes); - st->bitrate_bps = cbrBytes * (8*frame_rate); - max_data_bytes = cbrBytes; - } - max_rate = frame_rate*max_data_bytes*8; - - /* Equivalent 20-ms rate for mode/channel/bandwidth decisions */ - equiv_rate = st->bitrate_bps - (40*st->channels+20)*(st->Fs/frame_size - 50); - - if (st->signal_type == OPUS_SIGNAL_VOICE) - voice_est = 127; - else if (st->signal_type == OPUS_SIGNAL_MUSIC) - voice_est = 0; - else if (st->voice_ratio >= 0) - { - voice_est = st->voice_ratio*327>>8; - /* For AUDIO, never be more than 90% confident of having speech */ - if (st->application == OPUS_APPLICATION_AUDIO) - voice_est = IMIN(voice_est, 115); - } else if (st->application == OPUS_APPLICATION_VOIP) - voice_est = 115; - else - voice_est = 48; - - if (st->force_channels!=OPUS_AUTO && st->channels == 2) - { - st->stream_channels = st->force_channels; - } else { -#ifdef FUZZING - /* Random mono/stereo decision */ - if (st->channels == 2 && (rand()&0x1F)==0) - st->stream_channels = 3-st->stream_channels; -#else - /* Rate-dependent mono-stereo decision */ - if (st->channels == 2) - { - opus_int32 stereo_threshold; - stereo_threshold = stereo_music_threshold + ((voice_est*voice_est*(stereo_voice_threshold-stereo_music_threshold))>>14); - if (st->stream_channels == 2) - stereo_threshold -= 1000; - else - stereo_threshold += 1000; - st->stream_channels = (equiv_rate > stereo_threshold) ? 2 : 1; - } else { - st->stream_channels = st->channels; - } -#endif - } - equiv_rate = st->bitrate_bps - (40*st->stream_channels+20)*(st->Fs/frame_size - 50); - - /* Mode selection depending on application and signal type */ - if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) - { - st->mode = MODE_CELT_ONLY; - } else if (st->user_forced_mode == OPUS_AUTO) - { -#ifdef FUZZING - /* Random mode switching */ - if ((rand()&0xF)==0) - { - if ((rand()&0x1)==0) - st->mode = MODE_CELT_ONLY; - else - st->mode = MODE_SILK_ONLY; - } else { - if (st->prev_mode==MODE_CELT_ONLY) - st->mode = MODE_CELT_ONLY; - else - st->mode = MODE_SILK_ONLY; - } -#else - opus_int32 mode_voice, mode_music; - opus_int32 threshold; - - /* Interpolate based on stereo width */ - mode_voice = (opus_int32)(MULT16_32_Q15(Q15ONE-stereo_width,mode_thresholds[0][0]) - + MULT16_32_Q15(stereo_width,mode_thresholds[1][0])); - mode_music = (opus_int32)(MULT16_32_Q15(Q15ONE-stereo_width,mode_thresholds[1][1]) - + MULT16_32_Q15(stereo_width,mode_thresholds[1][1])); - /* Interpolate based on speech/music probability */ - threshold = mode_music + ((voice_est*voice_est*(mode_voice-mode_music))>>14); - /* Bias towards SILK for VoIP because of some useful features */ - if (st->application == OPUS_APPLICATION_VOIP) - threshold += 8000; - - /*printf("%f %d\n", stereo_width/(float)Q15ONE, threshold);*/ - /* Hysteresis */ - if (st->prev_mode == MODE_CELT_ONLY) - threshold -= 4000; - else if (st->prev_mode>0) - threshold += 4000; - - st->mode = (equiv_rate >= threshold) ? MODE_CELT_ONLY: MODE_SILK_ONLY; - - /* When FEC is enabled and there's enough packet loss, use SILK */ - if (st->silk_mode.useInBandFEC && st->silk_mode.packetLossPercentage > (128-voice_est)>>4) - st->mode = MODE_SILK_ONLY; - /* When encoding voice and DTX is enabled, set the encoder to SILK mode (at least for now) */ - if (st->silk_mode.useDTX && voice_est > 100) - st->mode = MODE_SILK_ONLY; -#endif - } else { - st->mode = st->user_forced_mode; - } - - /* Override the chosen mode to make sure we meet the requested frame size */ - if (st->mode != MODE_CELT_ONLY && frame_size < st->Fs/100) - st->mode = MODE_CELT_ONLY; - if (st->lfe) - st->mode = MODE_CELT_ONLY; - /* If max_data_bytes represents less than 8 kb/s, switch to CELT-only mode */ - if (max_data_bytes < (frame_rate > 50 ? 12000 : 8000)*frame_size / (st->Fs * 8)) - st->mode = MODE_CELT_ONLY; - - if (st->stream_channels == 1 && st->prev_channels ==2 && st->silk_mode.toMono==0 - && st->mode != MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY) - { - /* Delay stereo->mono transition by two frames so that SILK can do a smooth downmix */ - st->silk_mode.toMono = 1; - st->stream_channels = 2; - } else { - st->silk_mode.toMono = 0; - } - - if (st->prev_mode > 0 && - ((st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) || - (st->mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY))) - { - redundancy = 1; - celt_to_silk = (st->mode != MODE_CELT_ONLY); - if (!celt_to_silk) - { - /* Switch to SILK/hybrid if frame size is 10 ms or more*/ - if (frame_size >= st->Fs/100) - { - st->mode = st->prev_mode; - to_celt = 1; - } else { - redundancy=0; - } - } - } - /* For the first frame at a new SILK bandwidth */ - if (st->silk_bw_switch) - { - redundancy = 1; - celt_to_silk = 1; - st->silk_bw_switch = 0; - prefill=1; - } - - if (redundancy) - { - /* Fair share of the max size allowed */ - redundancy_bytes = IMIN(257, max_data_bytes*(opus_int32)(st->Fs/200)/(frame_size+st->Fs/200)); - /* For VBR, target the actual bitrate (subject to the limit above) */ - if (st->use_vbr) - redundancy_bytes = IMIN(redundancy_bytes, st->bitrate_bps/1600); - } - - if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) - { - silk_EncControlStruct dummy; - silk_InitEncoder( silk_enc, st->arch, &dummy); - prefill=1; - } - - /* Automatic (rate-dependent) bandwidth selection */ - if (st->mode == MODE_CELT_ONLY || st->first || st->silk_mode.allowBandwidthSwitch) - { - const opus_int32 *voice_bandwidth_thresholds, *music_bandwidth_thresholds; - opus_int32 bandwidth_thresholds[8]; - int bandwidth = OPUS_BANDWIDTH_FULLBAND; - opus_int32 equiv_rate2; - - equiv_rate2 = equiv_rate; - if (st->mode != MODE_CELT_ONLY) - { - /* Adjust the threshold +/- 10% depending on complexity */ - equiv_rate2 = equiv_rate2 * (45+st->silk_mode.complexity)/50; - /* CBR is less efficient by ~1 kb/s */ - if (!st->use_vbr) - equiv_rate2 -= 1000; - } - if (st->channels==2 && st->force_channels!=1) - { - voice_bandwidth_thresholds = stereo_voice_bandwidth_thresholds; - music_bandwidth_thresholds = stereo_music_bandwidth_thresholds; - } else { - voice_bandwidth_thresholds = mono_voice_bandwidth_thresholds; - music_bandwidth_thresholds = mono_music_bandwidth_thresholds; - } - /* Interpolate bandwidth thresholds depending on voice estimation */ - for (i=0;i<8;i++) - { - bandwidth_thresholds[i] = music_bandwidth_thresholds[i] - + ((voice_est*voice_est*(voice_bandwidth_thresholds[i]-music_bandwidth_thresholds[i]))>>14); - } - do { - int threshold, hysteresis; - threshold = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)]; - hysteresis = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)+1]; - if (!st->first) - { - if (st->bandwidth >= bandwidth) - threshold -= hysteresis; - else - threshold += hysteresis; - } - if (equiv_rate2 >= threshold) - break; - } while (--bandwidth>OPUS_BANDWIDTH_NARROWBAND); - st->bandwidth = bandwidth; - /* Prevents any transition to SWB/FB until the SILK layer has fully - switched to WB mode and turned the variable LP filter off */ - if (!st->first && st->mode != MODE_CELT_ONLY && !st->silk_mode.inWBmodeWithoutVariableLP && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND) - st->bandwidth = OPUS_BANDWIDTH_WIDEBAND; - } - - if (st->bandwidth>st->max_bandwidth) - st->bandwidth = st->max_bandwidth; - - if (st->user_bandwidth != OPUS_AUTO) - st->bandwidth = st->user_bandwidth; - - /* This prevents us from using hybrid at unsafe CBR/max rates */ - if (st->mode != MODE_CELT_ONLY && max_rate < 15000) - { - st->bandwidth = IMIN(st->bandwidth, OPUS_BANDWIDTH_WIDEBAND); - } - - /* Prevents Opus from wasting bits on frequencies that are above - the Nyquist rate of the input signal */ - if (st->Fs <= 24000 && st->bandwidth > OPUS_BANDWIDTH_SUPERWIDEBAND) - st->bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; - if (st->Fs <= 16000 && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND) - st->bandwidth = OPUS_BANDWIDTH_WIDEBAND; - if (st->Fs <= 12000 && st->bandwidth > OPUS_BANDWIDTH_MEDIUMBAND) - st->bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; - if (st->Fs <= 8000 && st->bandwidth > OPUS_BANDWIDTH_NARROWBAND) - st->bandwidth = OPUS_BANDWIDTH_NARROWBAND; -#ifndef DISABLE_FLOAT_API - /* Use detected bandwidth to reduce the encoded bandwidth. */ - if (st->detected_bandwidth && st->user_bandwidth == OPUS_AUTO) - { - int min_detected_bandwidth; - /* Makes bandwidth detection more conservative just in case the detector - gets it wrong when we could have coded a high bandwidth transparently. - When operating in SILK/hybrid mode, we don't go below wideband to avoid - more complicated switches that require redundancy. */ - if (equiv_rate <= 18000*st->stream_channels && st->mode == MODE_CELT_ONLY) - min_detected_bandwidth = OPUS_BANDWIDTH_NARROWBAND; - else if (equiv_rate <= 24000*st->stream_channels && st->mode == MODE_CELT_ONLY) - min_detected_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; - else if (equiv_rate <= 30000*st->stream_channels) - min_detected_bandwidth = OPUS_BANDWIDTH_WIDEBAND; - else if (equiv_rate <= 44000*st->stream_channels) - min_detected_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; - else - min_detected_bandwidth = OPUS_BANDWIDTH_FULLBAND; - - st->detected_bandwidth = IMAX(st->detected_bandwidth, min_detected_bandwidth); - st->bandwidth = IMIN(st->bandwidth, st->detected_bandwidth); - } -#endif - celt_encoder_ctl(celt_enc, OPUS_SET_LSB_DEPTH(lsb_depth)); - - /* CELT mode doesn't support mediumband, use wideband instead */ - if (st->mode == MODE_CELT_ONLY && st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) - st->bandwidth = OPUS_BANDWIDTH_WIDEBAND; - if (st->lfe) - st->bandwidth = OPUS_BANDWIDTH_NARROWBAND; - - /* Can't support higher than wideband for >20 ms frames */ - if (frame_size > st->Fs/50 && (st->mode == MODE_CELT_ONLY || st->bandwidth > OPUS_BANDWIDTH_WIDEBAND)) - { - VARDECL(unsigned char, tmp_data); - int nb_frames; - int bak_mode, bak_bandwidth, bak_channels, bak_to_mono; - VARDECL(OpusRepacketizer, rp); - opus_int32 bytes_per_frame; - opus_int32 repacketize_len; - -#ifndef DISABLE_FLOAT_API - if (analysis_read_pos_bak!= -1) - { - st->analysis.read_pos = analysis_read_pos_bak; - st->analysis.read_subframe = analysis_read_subframe_bak; - } -#endif - - nb_frames = frame_size > st->Fs/25 ? 3 : 2; - bytes_per_frame = IMIN(1276,(out_data_bytes-3)/nb_frames); - - ALLOC(tmp_data, nb_frames*bytes_per_frame, unsigned char); - - ALLOC(rp, 1, OpusRepacketizer); - opus_repacketizer_init(rp); - - bak_mode = st->user_forced_mode; - bak_bandwidth = st->user_bandwidth; - bak_channels = st->force_channels; - - st->user_forced_mode = st->mode; - st->user_bandwidth = st->bandwidth; - st->force_channels = st->stream_channels; - bak_to_mono = st->silk_mode.toMono; - - if (bak_to_mono) - st->force_channels = 1; - else - st->prev_channels = st->stream_channels; - for (i=0;i<nb_frames;i++) - { - int tmp_len; - st->silk_mode.toMono = 0; - /* When switching from SILK/Hybrid to CELT, only ask for a switch at the last frame */ - if (to_celt && i==nb_frames-1) - st->user_forced_mode = MODE_CELT_ONLY; - tmp_len = opus_encode_native(st, pcm+i*(st->channels*st->Fs/50), st->Fs/50, - tmp_data+i*bytes_per_frame, bytes_per_frame, lsb_depth, - NULL, 0, c1, c2, analysis_channels, downmix, float_api); - if (tmp_len<0) - { - RESTORE_STACK; - return OPUS_INTERNAL_ERROR; - } - ret = opus_repacketizer_cat(rp, tmp_data+i*bytes_per_frame, tmp_len); - if (ret<0) - { - RESTORE_STACK; - return OPUS_INTERNAL_ERROR; - } - } - if (st->use_vbr) - repacketize_len = out_data_bytes; - else - repacketize_len = IMIN(3*st->bitrate_bps/(3*8*50/nb_frames), out_data_bytes); - ret = opus_repacketizer_out_range_impl(rp, 0, nb_frames, data, repacketize_len, 0, !st->use_vbr); - if (ret<0) - { - RESTORE_STACK; - return OPUS_INTERNAL_ERROR; - } - st->user_forced_mode = bak_mode; - st->user_bandwidth = bak_bandwidth; - st->force_channels = bak_channels; - st->silk_mode.toMono = bak_to_mono; - RESTORE_STACK; - return ret; - } - curr_bandwidth = st->bandwidth; - - /* Chooses the appropriate mode for speech - *NEVER* switch to/from CELT-only mode here as this will invalidate some assumptions */ - if (st->mode == MODE_SILK_ONLY && curr_bandwidth > OPUS_BANDWIDTH_WIDEBAND) - st->mode = MODE_HYBRID; - if (st->mode == MODE_HYBRID && curr_bandwidth <= OPUS_BANDWIDTH_WIDEBAND) - st->mode = MODE_SILK_ONLY; - - /* printf("%d %d %d %d\n", st->bitrate_bps, st->stream_channels, st->mode, curr_bandwidth); */ - bytes_target = IMIN(max_data_bytes-redundancy_bytes, st->bitrate_bps * frame_size / (st->Fs * 8)) - 1; - - data += 1; - - ec_enc_init(&enc, data, max_data_bytes-1); - - ALLOC(pcm_buf, (total_buffer+frame_size)*st->channels, opus_val16); - OPUS_COPY(pcm_buf, &st->delay_buffer[(st->encoder_buffer-total_buffer)*st->channels], total_buffer*st->channels); - - if (st->mode == MODE_CELT_ONLY) - hp_freq_smth1 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ); - else - hp_freq_smth1 = ((silk_encoder*)silk_enc)->state_Fxx[0].sCmn.variable_HP_smth1_Q15; - - st->variable_HP_smth2_Q15 = silk_SMLAWB( st->variable_HP_smth2_Q15, - hp_freq_smth1 - st->variable_HP_smth2_Q15, SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF2, 16 ) ); - - /* convert from log scale to Hertz */ - cutoff_Hz = silk_log2lin( silk_RSHIFT( st->variable_HP_smth2_Q15, 8 ) ); - - if (st->application == OPUS_APPLICATION_VOIP) - { - hp_cutoff(pcm, cutoff_Hz, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs); - } else { - dc_reject(pcm, 3, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs); - } -#ifndef OPUS_FIXED_POINT - if (float_api) - { - opus_val32 sum; - sum = celt_inner_prod(&pcm_buf[total_buffer*st->channels], &pcm_buf[total_buffer*st->channels], frame_size*st->channels, st->arch); - /* This should filter out both NaNs and ridiculous signals that could - cause NaNs further down. */ - if (!(sum < 1e9f) || celt_isnan(sum)) - { - OPUS_CLEAR(&pcm_buf[total_buffer*st->channels], frame_size*st->channels); - st->hp_mem[0] = st->hp_mem[1] = st->hp_mem[2] = st->hp_mem[3] = 0; - } - } -#endif - - - /* SILK processing */ - HB_gain = Q15ONE; - if (st->mode != MODE_CELT_ONLY) - { - opus_int32 total_bitRate, celt_rate; -#ifdef OPUS_FIXED_POINT - const opus_int16 *pcm_silk; -#else - VARDECL(opus_int16, pcm_silk); - ALLOC(pcm_silk, st->channels*frame_size, opus_int16); -#endif - - /* Distribute bits between SILK and CELT */ - total_bitRate = 8 * bytes_target * frame_rate; - if( st->mode == MODE_HYBRID ) { - int HB_gain_ref; - /* Base rate for SILK */ - st->silk_mode.bitRate = st->stream_channels * ( 5000 + 1000 * ( st->Fs == 100 * frame_size ) ); - if( curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND ) { - /* SILK gets 2/3 of the remaining bits */ - st->silk_mode.bitRate += ( total_bitRate - st->silk_mode.bitRate ) * 2 / 3; - } else { /* FULLBAND */ - /* SILK gets 3/5 of the remaining bits */ - st->silk_mode.bitRate += ( total_bitRate - st->silk_mode.bitRate ) * 3 / 5; - } - /* Don't let SILK use more than 80% */ - if( st->silk_mode.bitRate > total_bitRate * 4/5 ) { - st->silk_mode.bitRate = total_bitRate * 4/5; - } - if (!st->energy_masking) - { - /* Increasingly attenuate high band when it gets allocated fewer bits */ - celt_rate = total_bitRate - st->silk_mode.bitRate; - HB_gain_ref = (curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND) ? 3000 : 3600; - HB_gain = SHL32((opus_val32)celt_rate, 9) / SHR32((opus_val32)celt_rate + st->stream_channels * HB_gain_ref, 6); - HB_gain = HB_gain < Q15ONE*6/7 ? HB_gain + Q15ONE/7 : Q15ONE; - } - } else { - /* SILK gets all bits */ - st->silk_mode.bitRate = total_bitRate; - } - - /* Surround masking for SILK */ - if (st->energy_masking && st->use_vbr && !st->lfe) - { - opus_val32 mask_sum=0; - opus_val16 masking_depth; - opus_int32 rate_offset; - int c; - int end = 17; - opus_int16 srate = 16000; - if (st->bandwidth == OPUS_BANDWIDTH_NARROWBAND) - { - end = 13; - srate = 8000; - } else if (st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) - { - end = 15; - srate = 12000; - } - for (c=0;c<st->channels;c++) - { - for(i=0;i<end;i++) - { - opus_val16 mask; - mask = MAX16(MIN16(st->energy_masking[21*c+i], - QCONST16(.5f, DB_SHIFT)), -QCONST16(2.0f, DB_SHIFT)); - if (mask > 0) - mask = HALF16(mask); - mask_sum += mask; - } - } - /* Conservative rate reduction, we cut the masking in half */ - masking_depth = mask_sum / end*st->channels; - masking_depth += QCONST16(.2f, DB_SHIFT); - rate_offset = (opus_int32)PSHR32(MULT16_16(srate, masking_depth), DB_SHIFT); - rate_offset = MAX32(rate_offset, -2*st->silk_mode.bitRate/3); - /* Split the rate change between the SILK and CELT part for hybrid. */ - if (st->bandwidth==OPUS_BANDWIDTH_SUPERWIDEBAND || st->bandwidth==OPUS_BANDWIDTH_FULLBAND) - st->silk_mode.bitRate += 3*rate_offset/5; - else - st->silk_mode.bitRate += rate_offset; - bytes_target += rate_offset * frame_size / (8 * st->Fs); - } - - st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs; - st->silk_mode.nChannelsAPI = st->channels; - st->silk_mode.nChannelsInternal = st->stream_channels; - if (curr_bandwidth == OPUS_BANDWIDTH_NARROWBAND) { - st->silk_mode.desiredInternalSampleRate = 8000; - } else if (curr_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) { - st->silk_mode.desiredInternalSampleRate = 12000; - } else { - silk_assert( st->mode == MODE_HYBRID || curr_bandwidth == OPUS_BANDWIDTH_WIDEBAND ); - st->silk_mode.desiredInternalSampleRate = 16000; - } - if( st->mode == MODE_HYBRID ) { - /* Don't allow bandwidth reduction at lowest bitrates in hybrid mode */ - st->silk_mode.minInternalSampleRate = 16000; - } else { - st->silk_mode.minInternalSampleRate = 8000; - } - - if (st->mode == MODE_SILK_ONLY) - { - opus_int32 effective_max_rate = max_rate; - st->silk_mode.maxInternalSampleRate = 16000; - if (frame_rate > 50) - effective_max_rate = effective_max_rate*2/3; - if (effective_max_rate < 13000) - { - st->silk_mode.maxInternalSampleRate = 12000; - st->silk_mode.desiredInternalSampleRate = IMIN(12000, st->silk_mode.desiredInternalSampleRate); - } - if (effective_max_rate < 9600) - { - st->silk_mode.maxInternalSampleRate = 8000; - st->silk_mode.desiredInternalSampleRate = IMIN(8000, st->silk_mode.desiredInternalSampleRate); - } - } else { - st->silk_mode.maxInternalSampleRate = 16000; - } - - st->silk_mode.useCBR = !st->use_vbr; - - /* Call SILK encoder for the low band */ - nBytes = IMIN(1275, max_data_bytes-1-redundancy_bytes); - - st->silk_mode.maxBits = nBytes*8; - /* Only allow up to 90% of the bits for hybrid mode*/ - if (st->mode == MODE_HYBRID) - st->silk_mode.maxBits = (opus_int32)st->silk_mode.maxBits*9/10; - if (st->silk_mode.useCBR) - { - st->silk_mode.maxBits = (st->silk_mode.bitRate * frame_size / (st->Fs * 8))*8; - /* Reduce the initial target to make it easier to reach the CBR rate */ - st->silk_mode.bitRate = IMAX(1, st->silk_mode.bitRate-2000); - } - - if (prefill) - { - opus_int32 zero=0; - int prefill_offset; - /* Use a smooth onset for the SILK prefill to avoid the encoder trying to encode - a discontinuity. The exact location is what we need to avoid leaving any "gap" - in the audio when mixing with the redundant CELT frame. Here we can afford to - overwrite st->delay_buffer because the only thing that uses it before it gets - rewritten is tmp_prefill[] and even then only the part after the ramp really - gets used (rather than sent to the encoder and discarded) */ - prefill_offset = st->channels*(st->encoder_buffer-st->delay_compensation-st->Fs/400); - gain_fade(st->delay_buffer+prefill_offset, st->delay_buffer+prefill_offset, - 0, Q15ONE, celt_mode->overlap, st->Fs/400, st->channels, celt_mode->window, st->Fs); - OPUS_CLEAR(st->delay_buffer, prefill_offset); -#ifdef OPUS_FIXED_POINT - pcm_silk = st->delay_buffer; -#else - for (i=0;i<st->encoder_buffer*st->channels;i++) - pcm_silk[i] = FLOAT2INT16(st->delay_buffer[i]); -#endif - silk_Encode( silk_enc, &st->silk_mode, pcm_silk, st->encoder_buffer, NULL, &zero, 1 ); - } - -#ifdef OPUS_FIXED_POINT - pcm_silk = pcm_buf+total_buffer*st->channels; -#else - for (i=0;i<frame_size*st->channels;i++) - pcm_silk[i] = FLOAT2INT16(pcm_buf[total_buffer*st->channels + i]); -#endif - ret = silk_Encode( silk_enc, &st->silk_mode, pcm_silk, frame_size, &enc, &nBytes, 0 ); - if( ret ) { - /*fprintf (stderr, "SILK encode error: %d\n", ret);*/ - /* Handle error */ - RESTORE_STACK; - return OPUS_INTERNAL_ERROR; - } - if (nBytes==0) - { - st->rangeFinal = 0; - data[-1] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels); - RESTORE_STACK; - return 1; - } - /* Extract SILK internal bandwidth for signaling in first byte */ - if( st->mode == MODE_SILK_ONLY ) { - if( st->silk_mode.internalSampleRate == 8000 ) { - curr_bandwidth = OPUS_BANDWIDTH_NARROWBAND; - } else if( st->silk_mode.internalSampleRate == 12000 ) { - curr_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; - } else if( st->silk_mode.internalSampleRate == 16000 ) { - curr_bandwidth = OPUS_BANDWIDTH_WIDEBAND; - } - } else { - silk_assert( st->silk_mode.internalSampleRate == 16000 ); - } - - st->silk_mode.opusCanSwitch = st->silk_mode.switchReady; - /* FIXME: How do we allocate the redundancy for CBR? */ - if (st->silk_mode.opusCanSwitch) - { - redundancy = 1; - celt_to_silk = 0; - st->silk_bw_switch = 1; - } - } - - /* CELT processing */ - { - int endband=21; - - switch(curr_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; - } - celt_encoder_ctl(celt_enc, CELT_SET_END_BAND(endband)); - celt_encoder_ctl(celt_enc, CELT_SET_CHANNELS(st->stream_channels)); - } - celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(OPUS_BITRATE_MAX)); - if (st->mode != MODE_SILK_ONLY) - { - opus_val32 celt_pred=2; - celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0)); - /* We may still decide to disable prediction later */ - if (st->silk_mode.reducedDependency) - celt_pred = 0; - celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(celt_pred)); - - if (st->mode == MODE_HYBRID) - { - int len; - - len = (ec_tell(&enc)+7)>>3; - if (redundancy) - len += st->mode == MODE_HYBRID ? 3 : 1; - if( st->use_vbr ) { - nb_compr_bytes = len + bytes_target - (st->silk_mode.bitRate * frame_size) / (8 * st->Fs); - } else { - /* check if SILK used up too much */ - nb_compr_bytes = len > bytes_target ? len : bytes_target; - } - } else { - if (st->use_vbr) - { - opus_int32 bonus=0; -#ifndef DISABLE_FLOAT_API - if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != st->Fs/50) - { - bonus = (60*st->stream_channels+40)*(st->Fs/frame_size-50); - if (analysis_info.valid) - bonus = (opus_int32)(bonus*(1.f+.5f*analysis_info.tonality)); - } -#endif - celt_encoder_ctl(celt_enc, OPUS_SET_VBR(1)); - celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(st->vbr_constraint)); - celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps+bonus)); - nb_compr_bytes = max_data_bytes-1-redundancy_bytes; - } else { - nb_compr_bytes = bytes_target; - } - } - - } else { - nb_compr_bytes = 0; - } - - ALLOC(tmp_prefill, st->channels*st->Fs/400, opus_val16); - if (st->mode != MODE_SILK_ONLY && st->mode != st->prev_mode && st->prev_mode > 0) - { - OPUS_COPY(tmp_prefill, &st->delay_buffer[(st->encoder_buffer-total_buffer-st->Fs/400)*st->channels], st->channels*st->Fs/400); - } - - if (st->channels*(st->encoder_buffer-(frame_size+total_buffer)) > 0) - { - OPUS_MOVE(st->delay_buffer, &st->delay_buffer[st->channels*frame_size], st->channels*(st->encoder_buffer-frame_size-total_buffer)); - OPUS_COPY(&st->delay_buffer[st->channels*(st->encoder_buffer-frame_size-total_buffer)], - &pcm_buf[0], - (frame_size+total_buffer)*st->channels); - } else { - OPUS_COPY(st->delay_buffer, &pcm_buf[(frame_size+total_buffer-st->encoder_buffer)*st->channels], st->encoder_buffer*st->channels); - } - /* gain_fade() and stereo_fade() need to be after the buffer copying - because we don't want any of this to affect the SILK part */ - if( st->prev_HB_gain < Q15ONE || HB_gain < Q15ONE ) { - gain_fade(pcm_buf, pcm_buf, - st->prev_HB_gain, HB_gain, celt_mode->overlap, frame_size, st->channels, celt_mode->window, st->Fs); - } - st->prev_HB_gain = HB_gain; - if (st->mode != MODE_HYBRID || st->stream_channels==1) - st->silk_mode.stereoWidth_Q14 = IMIN((1<<14),2*IMAX(0,equiv_rate-30000)); - if( !st->energy_masking && st->channels == 2 ) { - /* Apply stereo width reduction (at low bitrates) */ - if( st->hybrid_stereo_width_Q14 < (1 << 14) || st->silk_mode.stereoWidth_Q14 < (1 << 14) ) { - opus_val16 g1, g2; - g1 = st->hybrid_stereo_width_Q14; - g2 = (opus_val16)(st->silk_mode.stereoWidth_Q14); -#ifdef OPUS_FIXED_POINT - g1 = g1==16384 ? Q15ONE : SHL16(g1,1); - g2 = g2==16384 ? Q15ONE : SHL16(g2,1); -#else - g1 *= (1.f/16384); - g2 *= (1.f/16384); -#endif - stereo_fade(pcm_buf, pcm_buf, g1, g2, celt_mode->overlap, - frame_size, st->channels, celt_mode->window, st->Fs); - st->hybrid_stereo_width_Q14 = st->silk_mode.stereoWidth_Q14; - } - } - - if ( st->mode != MODE_CELT_ONLY && ec_tell(&enc)+17+20*(st->mode == MODE_HYBRID) <= 8*(max_data_bytes-1)) - { - /* For SILK mode, the redundancy is inferred from the length */ - if (st->mode == MODE_HYBRID && (redundancy || ec_tell(&enc)+37 <= 8*nb_compr_bytes)) - ec_enc_bit_logp(&enc, redundancy, 12); - if (redundancy) - { - int max_redundancy; - ec_enc_bit_logp(&enc, celt_to_silk, 1); - if (st->mode == MODE_HYBRID) - max_redundancy = (max_data_bytes-1)-nb_compr_bytes; - else - max_redundancy = (max_data_bytes-1)-((ec_tell(&enc)+7)>>3); - /* Target the same bit-rate for redundancy as for the rest, - up to a max of 257 bytes */ - redundancy_bytes = IMIN(max_redundancy, st->bitrate_bps/1600); - redundancy_bytes = IMIN(257, IMAX(2, redundancy_bytes)); - if (st->mode == MODE_HYBRID) - ec_enc_uint(&enc, redundancy_bytes-2, 256); - } - } else { - redundancy = 0; - } - - if (!redundancy) - { - st->silk_bw_switch = 0; - redundancy_bytes = 0; - } - if (st->mode != MODE_CELT_ONLY)start_band=17; - - if (st->mode == MODE_SILK_ONLY) - { - ret = (ec_tell(&enc)+7)>>3; - ec_enc_done(&enc); - nb_compr_bytes = ret; - } else { - nb_compr_bytes = IMIN((max_data_bytes-1)-redundancy_bytes, nb_compr_bytes); - ec_enc_shrink(&enc, nb_compr_bytes); - } - -#ifndef DISABLE_FLOAT_API - if (redundancy || st->mode != MODE_SILK_ONLY) - celt_encoder_ctl(celt_enc, CELT_SET_ANALYSIS(&analysis_info)); -#endif - - /* 5 ms redundant frame for CELT->SILK */ - if (redundancy && celt_to_silk) - { - int err; - celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0)); - celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0)); - err = celt_encode_with_ec(celt_enc, pcm_buf, st->Fs/200, data+nb_compr_bytes, redundancy_bytes, NULL); - if (err < 0) - { - RESTORE_STACK; - return OPUS_INTERNAL_ERROR; - } - celt_encoder_ctl(celt_enc, OPUS_GET_FINAL_RANGE(&redundant_rng)); - celt_encoder_ctl(celt_enc, OPUS_RESET_STATE); - } - - celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(start_band)); - - if (st->mode != MODE_SILK_ONLY) - { - if (st->mode != st->prev_mode && st->prev_mode > 0) - { - unsigned char dummy[2]; - celt_encoder_ctl(celt_enc, OPUS_RESET_STATE); - - /* Prefilling */ - celt_encode_with_ec(celt_enc, tmp_prefill, st->Fs/400, dummy, 2, NULL); - celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0)); - } - /* If false, we already busted the budget and we'll end up with a "PLC packet" */ - if (ec_tell(&enc) <= 8*nb_compr_bytes) - { - ret = celt_encode_with_ec(celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc); - if (ret < 0) - { - RESTORE_STACK; - return OPUS_INTERNAL_ERROR; - } - } - } - - /* 5 ms redundant frame for SILK->CELT */ - if (redundancy && !celt_to_silk) - { - int err; - unsigned char dummy[2]; - int N2, N4; - N2 = st->Fs/200; - N4 = st->Fs/400; - - celt_encoder_ctl(celt_enc, OPUS_RESET_STATE); - celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0)); - celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0)); - - /* NOTE: We could speed this up slightly (at the expense of code size) by just adding a function that prefills the buffer */ - celt_encode_with_ec(celt_enc, pcm_buf+st->channels*(frame_size-N2-N4), N4, dummy, 2, NULL); - - err = celt_encode_with_ec(celt_enc, pcm_buf+st->channels*(frame_size-N2), N2, data+nb_compr_bytes, redundancy_bytes, NULL); - if (err < 0) - { - RESTORE_STACK; - return OPUS_INTERNAL_ERROR; - } - celt_encoder_ctl(celt_enc, OPUS_GET_FINAL_RANGE(&redundant_rng)); - } - - - - /* Signalling the mode in the first byte */ - data--; - data[0] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels); - - st->rangeFinal = enc.rng ^ redundant_rng; - - if (to_celt) - st->prev_mode = MODE_CELT_ONLY; - else - st->prev_mode = st->mode; - st->prev_channels = st->stream_channels; - st->prev_framesize = frame_size; - - st->first = 0; - - /* In the unlikely case that the SILK encoder busted its target, tell - the decoder to call the PLC */ - if (ec_tell(&enc) > (max_data_bytes-1)*8) - { - if (max_data_bytes < 2) - { - RESTORE_STACK; - return OPUS_BUFFER_TOO_SMALL; - } - data[1] = 0; - ret = 1; - st->rangeFinal = 0; - } else if (st->mode==MODE_SILK_ONLY&&!redundancy) - { - /*When in LPC only mode it's perfectly - reasonable to strip off trailing zero bytes as - the required range decoder behavior is to - fill these in. This can't be done when the MDCT - modes are used because the decoder needs to know - the actual length for allocation purposes.*/ - while(ret>2&&data[ret]==0)ret--; - } - /* Count ToC and redundancy */ - ret += 1+redundancy_bytes; - if (!st->use_vbr) - { - if (opus_packet_pad(data, ret, max_data_bytes) != OPUS_OK) - - { - RESTORE_STACK; - return OPUS_INTERNAL_ERROR; - } - ret = max_data_bytes; - } - RESTORE_STACK; - return ret; -} - -#ifdef OPUS_FIXED_POINT - -#ifndef DISABLE_FLOAT_API -opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size, - unsigned char *data, opus_int32 max_data_bytes) -{ - int i, ret; - int frame_size; - int delay_compensation; - VARDECL(opus_int16, in); - ALLOC_STACK; - - if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) - delay_compensation = 0; - else - delay_compensation = st->delay_compensation; - frame_size = compute_frame_size(pcm, analysis_frame_size, - st->variable_duration, st->channels, st->Fs, st->bitrate_bps, - delay_compensation, downmix_float, st->analysis.subframe_mem); - - ALLOC(in, frame_size*st->channels, opus_int16); - - for (i=0;i<frame_size*st->channels;i++) - in[i] = FLOAT2INT16(pcm[i]); - ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, - pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1); - RESTORE_STACK; - return ret; -} -#endif - -opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size, - unsigned char *data, opus_int32 out_data_bytes) -{ - int frame_size; - int delay_compensation; - if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) - delay_compensation = 0; - else - delay_compensation = st->delay_compensation; - frame_size = compute_frame_size(pcm, analysis_frame_size, - st->variable_duration, st->channels, st->Fs, st->bitrate_bps, - delay_compensation, downmix_int -#ifndef DISABLE_FLOAT_API - , st->analysis.subframe_mem -#endif - ); - return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 16, - pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0); -} - -#else -opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size, - unsigned char *data, opus_int32 max_data_bytes) -{ - int i, ret; - int frame_size; - int delay_compensation; - VARDECL(float, in); - ALLOC_STACK; - - if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) - delay_compensation = 0; - else - delay_compensation = st->delay_compensation; - frame_size = compute_frame_size(pcm, analysis_frame_size, - st->variable_duration, st->channels, st->Fs, st->bitrate_bps, - delay_compensation, downmix_int, st->analysis.subframe_mem); - - ALLOC(in, frame_size*st->channels, float); - - for (i=0;i<frame_size*st->channels;i++) - in[i] = (1.0f/32768)*pcm[i]; - ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, - pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0); - RESTORE_STACK; - return ret; -} -opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size, - unsigned char *data, opus_int32 out_data_bytes) -{ - int frame_size; - int delay_compensation; - if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) - delay_compensation = 0; - else - delay_compensation = st->delay_compensation; - frame_size = compute_frame_size(pcm, analysis_frame_size, - st->variable_duration, st->channels, st->Fs, st->bitrate_bps, - delay_compensation, downmix_float, st->analysis.subframe_mem); - return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 24, - pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1); -} -#endif - - -int opus_encoder_ctl(OpusEncoder *st, int request, ...) -{ - int ret; - CELTEncoder *celt_enc; - va_list ap; - - ret = OPUS_OK; - va_start(ap, request); - - celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset); - - switch (request) - { - case OPUS_SET_APPLICATION_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if ( (value != OPUS_APPLICATION_VOIP && value != OPUS_APPLICATION_AUDIO - && value != OPUS_APPLICATION_RESTRICTED_LOWDELAY) - || (!st->first && st->application != value)) - { - ret = OPUS_BAD_ARG; - break; - } - st->application = value; - } - break; - case OPUS_GET_APPLICATION_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->application; - } - break; - case OPUS_SET_BITRATE_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX) - { - if (value <= 0) - goto bad_arg; - else if (value <= 500) - value = 500; - else if (value > (opus_int32)300000*st->channels) - value = (opus_int32)300000*st->channels; - } - st->user_bitrate_bps = value; - } - break; - case OPUS_GET_BITRATE_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = user_bitrate_to_bitrate(st, st->prev_framesize, 1276); - } - break; - case OPUS_SET_FORCE_CHANNELS_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if((value<1 || value>st->channels) && value != OPUS_AUTO) - { - goto bad_arg; - } - st->force_channels = value; - } - break; - case OPUS_GET_FORCE_CHANNELS_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->force_channels; - } - break; - case OPUS_SET_MAX_BANDWIDTH_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if (value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND) - { - goto bad_arg; - } - st->max_bandwidth = value; - if (st->max_bandwidth == OPUS_BANDWIDTH_NARROWBAND) { - st->silk_mode.maxInternalSampleRate = 8000; - } else if (st->max_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) { - st->silk_mode.maxInternalSampleRate = 12000; - } else { - st->silk_mode.maxInternalSampleRate = 16000; - } - } - break; - case OPUS_GET_MAX_BANDWIDTH_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->max_bandwidth; - } - break; - case OPUS_SET_BANDWIDTH_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if ((value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND) && value != OPUS_AUTO) - { - goto bad_arg; - } - st->user_bandwidth = value; - if (st->user_bandwidth == OPUS_BANDWIDTH_NARROWBAND) { - st->silk_mode.maxInternalSampleRate = 8000; - } else if (st->user_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) { - st->silk_mode.maxInternalSampleRate = 12000; - } else { - st->silk_mode.maxInternalSampleRate = 16000; - } - } - break; - 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_DTX_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if(value<0 || value>1) - { - goto bad_arg; - } - st->silk_mode.useDTX = value; - } - break; - case OPUS_GET_DTX_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->silk_mode.useDTX; - } - break; - case OPUS_SET_COMPLEXITY_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if(value<0 || value>10) - { - goto bad_arg; - } - st->silk_mode.complexity = value; - celt_encoder_ctl(celt_enc, 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->silk_mode.complexity; - } - break; - case OPUS_SET_INBAND_FEC_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if(value<0 || value>1) - { - goto bad_arg; - } - st->silk_mode.useInBandFEC = value; - } - break; - case OPUS_GET_INBAND_FEC_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->silk_mode.useInBandFEC; - } - break; - case OPUS_SET_PACKET_LOSS_PERC_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if (value < 0 || value > 100) - { - goto bad_arg; - } - st->silk_mode.packetLossPercentage = value; - celt_encoder_ctl(celt_enc, OPUS_SET_PACKET_LOSS_PERC(value)); - } - break; - case OPUS_GET_PACKET_LOSS_PERC_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->silk_mode.packetLossPercentage; - } - break; - case OPUS_SET_VBR_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if(value<0 || value>1) - { - goto bad_arg; - } - st->use_vbr = value; - st->silk_mode.useCBR = 1-value; - } - break; - case OPUS_GET_VBR_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->use_vbr; - } - break; - case OPUS_SET_VOICE_RATIO_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if (value<-1 || value>100) - { - goto bad_arg; - } - st->voice_ratio = value; - } - break; - case OPUS_GET_VOICE_RATIO_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->voice_ratio; - } - break; - case OPUS_SET_VBR_CONSTRAINT_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if(value<0 || value>1) - { - goto bad_arg; - } - st->vbr_constraint = value; - } - break; - case OPUS_GET_VBR_CONSTRAINT_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->vbr_constraint; - } - break; - case OPUS_SET_SIGNAL_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if(value!=OPUS_AUTO && value!=OPUS_SIGNAL_VOICE && value!=OPUS_SIGNAL_MUSIC) - { - goto bad_arg; - } - st->signal_type = value; - } - break; - case OPUS_GET_SIGNAL_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->signal_type; - } - break; - case OPUS_GET_LOOKAHEAD_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->Fs/400; - if (st->application != OPUS_APPLICATION_RESTRICTED_LOWDELAY) - *value += st->delay_compensation; - } - 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_FINAL_RANGE_REQUEST: - { - opus_uint32 *value = va_arg(ap, opus_uint32*); - if (!value) - { - goto bad_arg; - } - *value = st->rangeFinal; - } - break; - case OPUS_SET_LSB_DEPTH_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if (value<8 || value>24) - { - goto bad_arg; - } - st->lsb_depth=value; - } - break; - case OPUS_GET_LSB_DEPTH_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->lsb_depth; - } - break; - case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if (value != OPUS_FRAMESIZE_ARG && value != OPUS_FRAMESIZE_2_5_MS && - value != OPUS_FRAMESIZE_5_MS && value != OPUS_FRAMESIZE_10_MS && - value != OPUS_FRAMESIZE_20_MS && value != OPUS_FRAMESIZE_40_MS && - value != OPUS_FRAMESIZE_60_MS && value != OPUS_FRAMESIZE_VARIABLE) - { - goto bad_arg; - } - st->variable_duration = value; - celt_encoder_ctl(celt_enc, OPUS_SET_EXPERT_FRAME_DURATION(value)); - } - break; - case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->variable_duration; - } - break; - case OPUS_SET_PREDICTION_DISABLED_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if (value > 1 || value < 0) - goto bad_arg; - st->silk_mode.reducedDependency = value; - } - break; - case OPUS_GET_PREDICTION_DISABLED_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - goto bad_arg; - *value = st->silk_mode.reducedDependency; - } - break; - case OPUS_RESET_STATE: - { - void *silk_enc; - silk_EncControlStruct dummy; - char *start; - silk_enc = (char*)st+st->silk_enc_offset; -#ifndef DISABLE_FLOAT_API - tonality_analysis_reset(&st->analysis); -#endif - - start = (char*)&st->OPUS_ENCODER_RESET_START; - OPUS_CLEAR(start, sizeof(OpusEncoder) - (start - (char*)st)); - - celt_encoder_ctl(celt_enc, OPUS_RESET_STATE); - silk_InitEncoder( silk_enc, st->arch, &dummy ); - st->stream_channels = st->channels; - st->hybrid_stereo_width_Q14 = 1 << 14; - st->prev_HB_gain = Q15ONE; - st->first = 1; - st->mode = MODE_HYBRID; - st->bandwidth = OPUS_BANDWIDTH_FULLBAND; - st->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ); - } - break; - case OPUS_SET_FORCE_MODE_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if ((value < MODE_SILK_ONLY || value > MODE_CELT_ONLY) && value != OPUS_AUTO) - { - goto bad_arg; - } - st->user_forced_mode = value; - } - break; - case OPUS_SET_LFE_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - st->lfe = value; - ret = celt_encoder_ctl(celt_enc, OPUS_SET_LFE(value)); - } - break; - case OPUS_SET_ENERGY_MASK_REQUEST: - { - opus_val16 *value = va_arg(ap, opus_val16*); - st->energy_masking = value; - ret = celt_encoder_ctl(celt_enc, OPUS_SET_ENERGY_MASK(value)); - } - break; - - case CELT_GET_MODE_REQUEST: - { - const CELTMode ** value = va_arg(ap, const CELTMode**); - if (!value) - { - goto bad_arg; - } - ret = celt_encoder_ctl(celt_enc, CELT_GET_MODE(value)); - } - break; - default: - /* fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);*/ - ret = OPUS_UNIMPLEMENTED; - break; - } - va_end(ap); - return ret; -bad_arg: - va_end(ap); - return OPUS_BAD_ARG; -} - -void opus_encoder_destroy(OpusEncoder *st) -{ - opus_free(st); -} diff --git a/drivers/opus/opus_multistream.c b/drivers/opus/opus_multistream.c deleted file mode 100644 index aa94803779..0000000000 --- a/drivers/opus/opus_multistream.c +++ /dev/null @@ -1,89 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/opus_multistream.h" -#include "opus/opus.h" -#include "opus/opus_private.h" -#include "opus/celt/stack_alloc.h" -#include <stdarg.h> -#include "opus/celt/float_cast.h" -#include "opus/celt/os_support.h" - - -int validate_layout(const ChannelLayout *layout) -{ - int i, max_channel; - - max_channel = layout->nb_streams+layout->nb_coupled_streams; - if (max_channel>255) - return 0; - for (i=0;i<layout->nb_channels;i++) - { - if (layout->mapping[i] >= max_channel && layout->mapping[i] != 255) - return 0; - } - return 1; -} - - -int get_left_channel(const ChannelLayout *layout, int stream_id, int prev) -{ - int i; - i = (prev<0) ? 0 : prev+1; - for (;i<layout->nb_channels;i++) - { - if (layout->mapping[i]==stream_id*2) - return i; - } - return -1; -} - -int get_right_channel(const ChannelLayout *layout, int stream_id, int prev) -{ - int i; - i = (prev<0) ? 0 : prev+1; - for (;i<layout->nb_channels;i++) - { - if (layout->mapping[i]==stream_id*2+1) - return i; - } - return -1; -} - -int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev) -{ - int i; - i = (prev<0) ? 0 : prev+1; - for (;i<layout->nb_channels;i++) - { - if (layout->mapping[i]==stream_id+layout->nb_coupled_streams) - return i; - } - return -1; -} - diff --git a/drivers/opus/opus_multistream.h b/drivers/opus/opus_multistream.h deleted file mode 100644 index 5519c46a9f..0000000000 --- a/drivers/opus/opus_multistream.h +++ /dev/null @@ -1,660 +0,0 @@ -/* 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/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 the - * <a href="https://tools.ietf.org/html/draft-ietf-codec-oggopus">Ogg - * encapsulation specification</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 outputing 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(5); - -/** 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(6); - -/** 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 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); - -/** Intialize 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 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/drivers/opus/opus_multistream_decoder.c b/drivers/opus/opus_multistream_decoder.c deleted file mode 100644 index 25100edba2..0000000000 --- a/drivers/opus/opus_multistream_decoder.c +++ /dev/null @@ -1,534 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/opus_multistream.h" -#include "opus/opus.h" -#include "opus/opus_private.h" -#include "opus/celt/stack_alloc.h" -#include <stdarg.h> -#include "opus/celt/float_cast.h" -#include "opus/celt/os_support.h" - -struct OpusMSDecoder { - ChannelLayout layout; - /* Decoder states go here */ -}; - - - - -/* DECODER */ - -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; -} - -typedef void (*opus_copy_channel_out_func)( - void *dst, - int dst_stride, - int dst_channel, - const opus_val16 *src, - int src_stride, - int frame_size -); - -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); - 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; -} - -static 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 -) -{ - opus_int32 Fs; - int coupled_size; - int mono_size; - int s, c; - char *ptr; - int do_plc=0; - VARDECL(opus_val16, buf); - ALLOC_STACK; - - /* Limit frame_size to avoid excessive stack allocations. */ - opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)); - frame_size = IMIN(frame_size, Fs/25*3); - ALLOC(buf, 2*frame_size, opus_val16); - 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; - int packet_offset, 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); - 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); - 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); - 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); - 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); - } - } - 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_val16 *src, - int src_stride, - int frame_size -) -{ - float *float_dst; - opus_int32 i; - float_dst = (float*)dst; - if (src != NULL) - { - for (i=0;i<frame_size;i++) -#if defined(FIXED_POINT) - float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride]; -#else - float_dst[i*dst_stride+dst_channel] = src[i*src_stride]; -#endif - } - 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_val16 *src, - int src_stride, - int frame_size -) -{ - opus_int16 *short_dst; - opus_int32 i; - short_dst = (opus_int16*)dst; - if (src != NULL) - { - for (i=0;i<frame_size;i++) -#if defined(FIXED_POINT) - short_dst[i*dst_stride+dst_channel] = src[i*src_stride]; -#else - short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]); -#endif - } - else - { - for (i=0;i<frame_size;i++) - short_dst[i*dst_stride+dst_channel] = 0; - } -} - - - -#ifdef OPUS_FIXED_POINT -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, 0); -} - -#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); -} -#endif - -#else - -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, 1); -} - -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); -} -#endif - -int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) -{ - va_list ap; - int coupled_size, mono_size; - char *ptr; - int ret = OPUS_OK; - - va_start(ap, request); - - 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: - { - 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) - ret = OPUS_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: - { - 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; - } - - va_end(ap); - return ret; -bad_arg: - va_end(ap); - return OPUS_BAD_ARG; -} - - -void opus_multistream_decoder_destroy(OpusMSDecoder *st) -{ - opus_free(st); -} diff --git a/drivers/opus/opus_multistream_encoder.c b/drivers/opus/opus_multistream_encoder.c deleted file mode 100644 index 426c72e997..0000000000 --- a/drivers/opus/opus_multistream_encoder.c +++ /dev/null @@ -1,1217 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/opus_multistream.h" -#include "opus/opus.h" -#include "opus/opus_private.h" -#include "opus/celt/stack_alloc.h" -#include <stdarg.h> -#include "opus/celt/float_cast.h" -#include "opus/celt/os_support.h" -#include "opus/celt/mathops.h" -#include "opus/celt/mdct.h" -#include "opus/celt/modes.h" -#include "opus/celt/bands.h" -#include "opus/celt/quant_bands.h" -#include "opus/celt/pitch.h" - -typedef struct { - int nb_streams; - int nb_coupled_streams; - unsigned char mapping[8]; -} VorbisLayout; - -/* Index is nb_channel-1*/ -static const VorbisLayout vorbis_mappings[8] = { - {1, 0, {0}}, /* 1: mono */ - {1, 1, {0, 1}}, /* 2: stereo */ - {2, 1, {0, 2, 1}}, /* 3: 1-d surround */ - {2, 2, {0, 1, 2, 3}}, /* 4: quadraphonic surround */ - {3, 2, {0, 4, 1, 2, 3}}, /* 5: 5-channel surround */ - {4, 2, {0, 4, 1, 2, 3, 5}}, /* 6: 5.1 surround */ - {4, 3, {0, 4, 1, 2, 3, 5, 6}}, /* 7: 6.1 surround */ - {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */ -}; - -typedef void (*opus_copy_channel_in_func)( - opus_val16 *dst, - int dst_stride, - const void *src, - int src_stride, - int src_channel, - int frame_size -); - -struct OpusMSEncoder { - ChannelLayout layout; - int arch; - int lfe_stream; - int application; - int variable_duration; - int surround; - opus_int32 bitrate_bps; - float subframe_mem[3]; - /* Encoder states go here */ - /* then opus_val32 window_mem[channels*120]; */ - /* then opus_val32 preemph_mem[channels]; */ -}; - -static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st) -{ - int s; - char *ptr; - int coupled_size, mono_size; - - coupled_size = opus_encoder_get_size(2); - mono_size = opus_encoder_get_size(1); - ptr = (char*)st + align(sizeof(OpusMSEncoder)); - for (s=0;s<st->layout.nb_streams;s++) - { - if (s < st->layout.nb_coupled_streams) - ptr += align(coupled_size); - else - ptr += align(mono_size); - } - /* void* cast avoids clang -Wcast-align warning */ - return (opus_val32*)(void*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32)); -} - -static opus_val32 *ms_get_window_mem(OpusMSEncoder *st) -{ - int s; - char *ptr; - int coupled_size, mono_size; - - coupled_size = opus_encoder_get_size(2); - mono_size = opus_encoder_get_size(1); - ptr = (char*)st + align(sizeof(OpusMSEncoder)); - for (s=0;s<st->layout.nb_streams;s++) - { - if (s < st->layout.nb_coupled_streams) - ptr += align(coupled_size); - else - ptr += align(mono_size); - } - /* void* cast avoids clang -Wcast-align warning */ - return (opus_val32*)(void*)ptr; -} - -static int validate_encoder_layout(const ChannelLayout *layout) -{ - int s; - for (s=0;s<layout->nb_streams;s++) - { - if (s < layout->nb_coupled_streams) - { - if (get_left_channel(layout, s, -1)==-1) - return 0; - if (get_right_channel(layout, s, -1)==-1) - return 0; - } else { - if (get_mono_channel(layout, s, -1)==-1) - return 0; - } - } - return 1; -} - -static void channel_pos(int channels, int pos[8]) -{ - /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */ - if (channels==4) - { - pos[0]=1; - pos[1]=3; - pos[2]=1; - pos[3]=3; - } else if (channels==3||channels==5||channels==6) - { - pos[0]=1; - pos[1]=2; - pos[2]=3; - pos[3]=1; - pos[4]=3; - pos[5]=0; - } else if (channels==7) - { - pos[0]=1; - pos[1]=2; - pos[2]=3; - pos[3]=1; - pos[4]=3; - pos[5]=2; - pos[6]=0; - } else if (channels==8) - { - pos[0]=1; - pos[1]=2; - pos[2]=3; - pos[3]=1; - pos[4]=3; - pos[5]=1; - pos[6]=3; - pos[7]=0; - } -} - -#if 1 -/* Computes a rough approximation of log2(2^a + 2^b) */ -static opus_val16 logSum(opus_val16 a, opus_val16 b) -{ - opus_val16 max; - opus_val32 diff; - opus_val16 frac; - static const opus_val16 diff_table[17] = { - QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT), - QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT), - QCONST16(0.0028123f, DB_SHIFT) - }; - int low; - if (a>b) - { - max = a; - diff = SUB32(EXTEND32(a),EXTEND32(b)); - } else { - max = b; - diff = SUB32(EXTEND32(b),EXTEND32(a)); - } - if (!(diff < QCONST16(8.f, DB_SHIFT))) /* inverted to catch NaNs */ - return max; -#ifdef OPUS_FIXED_POINT - low = SHR32(diff, DB_SHIFT-1); - frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT); -#else - low = (int)floor(2*diff); - frac = 2*diff - low; -#endif - return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low])); -} -#else -opus_val16 logSum(opus_val16 a, opus_val16 b) -{ - return log2(pow(4, a)+ pow(4, b))/2; -} -#endif - -void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem, - int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in, int arch -) -{ - int c; - int i; - int LM; - int pos[8] = {0}; - int upsample; - int frame_size; - opus_val16 channel_offset; - opus_val32 bandE[21]; - opus_val16 maskLogE[3][21]; - VARDECL(opus_val32, in); - VARDECL(opus_val16, x); - VARDECL(opus_val32, freq); - SAVE_STACK; - - upsample = resampling_factor(rate); - frame_size = len*upsample; - - for (LM=0;LM<celt_mode->maxLM;LM++) - if (celt_mode->shortMdctSize<<LM==frame_size) - break; - - ALLOC(in, frame_size+overlap, opus_val32); - ALLOC(x, len, opus_val16); - ALLOC(freq, frame_size, opus_val32); - - channel_pos(channels, pos); - - for (c=0;c<3;c++) - for (i=0;i<21;i++) - maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT); - - for (c=0;c<channels;c++) - { - OPUS_COPY(in, mem+c*overlap, overlap); - (*copy_channel_in)(x, 1, pcm, channels, c, len); - celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0); -#ifndef OPUS_FIXED_POINT - { - opus_val32 sum; - sum = celt_inner_prod(in, in, frame_size+overlap, 0); - /* This should filter out both NaNs and ridiculous signals that could - cause NaNs further down. */ - if (!(sum < 1e9f) || celt_isnan(sum)) - { - OPUS_CLEAR(in, frame_size+overlap); - preemph_mem[c] = 0; - } - } -#endif - clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, - overlap, celt_mode->maxLM-LM, 1, arch); - if (upsample != 1) - { - int bound = len; - for (i=0;i<bound;i++) - freq[i] *= upsample; - for (;i<frame_size;i++) - freq[i] = 0; - } - - compute_band_energies(celt_mode, freq, bandE, 21, 1, LM); - amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1); - /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */ - for (i=1;i<21;i++) - bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT)); - for (i=19;i>=0;i--) - bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i+1]-QCONST16(2.f, DB_SHIFT)); - if (pos[c]==1) - { - for (i=0;i<21;i++) - maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]); - } else if (pos[c]==3) - { - for (i=0;i<21;i++) - maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]); - } else if (pos[c]==2) - { - for (i=0;i<21;i++) - { - maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT)); - maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT)); - } - } -#if 0 - for (i=0;i<21;i++) - printf("%f ", bandLogE[21*c+i]); - float sum=0; - for (i=0;i<21;i++) - sum += bandLogE[21*c+i]; - printf("%f ", sum/21); -#endif - OPUS_COPY(mem+c*overlap, in+frame_size, overlap); - } - for (i=0;i<21;i++) - maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]); - channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1))); - for (c=0;c<3;c++) - for (i=0;i<21;i++) - maskLogE[c][i] += channel_offset; -#if 0 - for (c=0;c<3;c++) - { - for (i=0;i<21;i++) - printf("%f ", maskLogE[c][i]); - } -#endif - for (c=0;c<channels;c++) - { - opus_val16 *mask; - if (pos[c]!=0) - { - mask = &maskLogE[pos[c]-1][0]; - for (i=0;i<21;i++) - bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i]; - } else { - for (i=0;i<21;i++) - bandLogE[21*c+i] = 0; - } -#if 0 - for (i=0;i<21;i++) - printf("%f ", bandLogE[21*c+i]); - printf("\n"); -#endif -#if 0 - float sum=0; - for (i=0;i<21;i++) - sum += bandLogE[21*c+i]; - printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT)); - printf("\n"); -#endif - } - RESTORE_STACK; -} - -opus_int32 opus_multistream_encoder_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_encoder_get_size(2); - mono_size = opus_encoder_get_size(1); - return align(sizeof(OpusMSEncoder)) - + nb_coupled_streams * align(coupled_size) - + (nb_streams-nb_coupled_streams) * align(mono_size); -} - -opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family) -{ - int nb_streams; - int nb_coupled_streams; - opus_int32 size; - - if (mapping_family==0) - { - if (channels==1) - { - nb_streams=1; - nb_coupled_streams=0; - } else if (channels==2) - { - nb_streams=1; - nb_coupled_streams=1; - } else - return 0; - } else if (mapping_family==1 && channels<=8 && channels>=1) - { - nb_streams=vorbis_mappings[channels-1].nb_streams; - nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams; - } else if (mapping_family==255) - { - nb_streams=channels; - nb_coupled_streams=0; - } else - return 0; - size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams); - if (channels>2) - { - size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32)); - } - return size; -} - - -static int opus_multistream_encoder_init_impl( - OpusMSEncoder *st, - opus_int32 Fs, - int channels, - int streams, - int coupled_streams, - const unsigned char *mapping, - int application, - int surround -) -{ - 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->arch = opus_select_arch(); - st->layout.nb_channels = channels; - st->layout.nb_streams = streams; - st->layout.nb_coupled_streams = coupled_streams; - st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0; - if (!surround) - st->lfe_stream = -1; - st->bitrate_bps = OPUS_AUTO; - st->application = application; - st->variable_duration = OPUS_FRAMESIZE_ARG; - for (i=0;i<st->layout.nb_channels;i++) - st->layout.mapping[i] = mapping[i]; - if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout)) - return OPUS_BAD_ARG; - ptr = (char*)st + align(sizeof(OpusMSEncoder)); - coupled_size = opus_encoder_get_size(2); - mono_size = opus_encoder_get_size(1); - - for (i=0;i<st->layout.nb_coupled_streams;i++) - { - ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application); - if(ret!=OPUS_OK)return ret; - if (i==st->lfe_stream) - opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1)); - ptr += align(coupled_size); - } - for (;i<st->layout.nb_streams;i++) - { - ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application); - if (i==st->lfe_stream) - opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1)); - if(ret!=OPUS_OK)return ret; - ptr += align(mono_size); - } - if (surround) - { - OPUS_CLEAR(ms_get_preemph_mem(st), channels); - OPUS_CLEAR(ms_get_window_mem(st), channels*120); - } - st->surround = surround; - return OPUS_OK; -} - -int opus_multistream_encoder_init( - OpusMSEncoder *st, - opus_int32 Fs, - int channels, - int streams, - int coupled_streams, - const unsigned char *mapping, - int application -) -{ - return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0); -} - -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 -) -{ - if ((channels>255) || (channels<1)) - return OPUS_BAD_ARG; - st->lfe_stream = -1; - if (mapping_family==0) - { - if (channels==1) - { - *streams=1; - *coupled_streams=0; - mapping[0]=0; - } else if (channels==2) - { - *streams=1; - *coupled_streams=1; - mapping[0]=0; - mapping[1]=1; - } else - return OPUS_UNIMPLEMENTED; - } else if (mapping_family==1 && channels<=8 && channels>=1) - { - int i; - *streams=vorbis_mappings[channels-1].nb_streams; - *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams; - for (i=0;i<channels;i++) - mapping[i] = vorbis_mappings[channels-1].mapping[i]; - if (channels>=6) - st->lfe_stream = *streams-1; - } else if (mapping_family==255) - { - int i; - *streams=channels; - *coupled_streams=0; - for(i=0;i<channels;i++) - mapping[i] = i; - } else - return OPUS_UNIMPLEMENTED; - return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams, - mapping, application, channels>2&&mapping_family==1); -} - -OpusMSEncoder *opus_multistream_encoder_create( - opus_int32 Fs, - int channels, - int streams, - int coupled_streams, - const unsigned char *mapping, - int application, - int *error -) -{ - int ret; - OpusMSEncoder *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 = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams)); - if (st==NULL) - { - if (error) - *error = OPUS_ALLOC_FAIL; - return NULL; - } - ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application); - if (ret != OPUS_OK) - { - opus_free(st); - st = NULL; - } - if (error) - *error = ret; - return st; -} - -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 -) -{ - int ret; - opus_int32 size; - OpusMSEncoder *st; - if ((channels>255) || (channels<1)) - { - if (error) - *error = OPUS_BAD_ARG; - return NULL; - } - size = opus_multistream_surround_encoder_get_size(channels, mapping_family); - if (!size) - { - if (error) - *error = OPUS_UNIMPLEMENTED; - return NULL; - } - st = (OpusMSEncoder *)opus_alloc(size); - if (st==NULL) - { - if (error) - *error = OPUS_ALLOC_FAIL; - return NULL; - } - ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application); - if (ret != OPUS_OK) - { - opus_free(st); - st = NULL; - } - if (error) - *error = ret; - return st; -} - -static opus_int32 surround_rate_allocation( - OpusMSEncoder *st, - opus_int32 *rate, - int frame_size - ) -{ - int i; - opus_int32 channel_rate; - opus_int32 Fs; - char *ptr; - int stream_offset; - int lfe_offset; - int coupled_ratio; /* Q8 */ - int lfe_ratio; /* Q8 */ - opus_int32 rate_sum=0; - - ptr = (char*)st + align(sizeof(OpusMSEncoder)); - opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs)); - - if (st->bitrate_bps > st->layout.nb_channels*40000) - stream_offset = 20000; - else - stream_offset = st->bitrate_bps/st->layout.nb_channels/2; - stream_offset += 60*(Fs/frame_size-50); - /* We start by giving each stream (coupled or uncoupled) the same bitrate. - This models the main saving of coupled channels over uncoupled. */ - /* The LFE stream is an exception to the above and gets fewer bits. */ - lfe_offset = 3500 + 60*(Fs/frame_size-50); - /* Coupled streams get twice the mono rate after the first 20 kb/s. */ - coupled_ratio = 512; - /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */ - lfe_ratio = 32; - - /* Compute bitrate allocation between streams */ - if (st->bitrate_bps==OPUS_AUTO) - { - channel_rate = Fs+60*Fs/frame_size; - } else if (st->bitrate_bps==OPUS_BITRATE_MAX) - { - channel_rate = 300000; - } else { - int nb_lfe; - int nb_uncoupled; - int nb_coupled; - int total; - nb_lfe = (st->lfe_stream!=-1); - nb_coupled = st->layout.nb_coupled_streams; - nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe; - total = (nb_uncoupled<<8) /* mono */ - + coupled_ratio*nb_coupled /* stereo */ - + nb_lfe*lfe_ratio; - channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total; - } -#ifndef OPUS_FIXED_POINT - if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50) - { - opus_int32 bonus; - bonus = 60*(Fs/frame_size-50); - channel_rate += bonus; - } -#endif - - for (i=0;i<st->layout.nb_streams;i++) - { - if (i<st->layout.nb_coupled_streams) - rate[i] = stream_offset+(channel_rate*coupled_ratio>>8); - else if (i!=st->lfe_stream) - rate[i] = stream_offset+channel_rate; - else - rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8); - rate[i] = IMAX(rate[i], 500); - rate_sum += rate[i]; - } - return rate_sum; -} - -/* Max size in case the encoder decides to return three frames */ -#define MS_FRAME_TMP (3*1275+7) -static int opus_multistream_encode_native -( - 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 -) -{ - opus_int32 Fs; - int coupled_size; - int mono_size; - int s; - char *ptr; - int tot_size; - VARDECL(opus_val16, buf); - VARDECL(opus_val16, bandSMR); - unsigned char tmp_data[MS_FRAME_TMP]; - OpusRepacketizer rp; - opus_int32 vbr; - const CELTMode *celt_mode; - opus_int32 bitrates[256]; - opus_val16 bandLogE[42]; - opus_val32 *mem = NULL; - opus_val32 *preemph_mem=NULL; - int frame_size; - opus_int32 rate_sum; - opus_int32 smallest_packet; - ALLOC_STACK; - - if (st->surround) - { - preemph_mem = ms_get_preemph_mem(st); - mem = ms_get_window_mem(st); - } - - ptr = (char*)st + align(sizeof(OpusMSEncoder)); - opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs)); - opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr)); - opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode)); - - { - opus_int32 delay_compensation; - int channels; - - channels = st->layout.nb_streams + st->layout.nb_coupled_streams; - opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation)); - delay_compensation -= Fs/400; - frame_size = compute_frame_size(pcm, analysis_frame_size, - st->variable_duration, channels, Fs, st->bitrate_bps, - delay_compensation, downmix -#ifndef DISABLE_FLOAT_API - , st->subframe_mem -#endif - ); - } - - if (400*frame_size < Fs) - { - RESTORE_STACK; - return OPUS_BAD_ARG; - } - /* Validate frame_size before using it to allocate stack space. - This mirrors the checks in opus_encode[_float](). */ - if (400*frame_size != Fs && 200*frame_size != Fs && - 100*frame_size != Fs && 50*frame_size != Fs && - 25*frame_size != Fs && 50*frame_size != 3*Fs) - { - RESTORE_STACK; - return OPUS_BAD_ARG; - } - - /* Smallest packet the encoder can produce. */ - smallest_packet = st->layout.nb_streams*2-1; - if (max_data_bytes < smallest_packet) - { - RESTORE_STACK; - return OPUS_BUFFER_TOO_SMALL; - } - ALLOC(buf, 2*frame_size, opus_val16); - coupled_size = opus_encoder_get_size(2); - mono_size = opus_encoder_get_size(1); - - ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16); - if (st->surround) - { - surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in, st->arch); - } - - /* Compute bitrate allocation between streams (this could be a lot better) */ - rate_sum = surround_rate_allocation(st, bitrates, frame_size); - - if (!vbr) - { - if (st->bitrate_bps == OPUS_AUTO) - { - max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size)); - } else if (st->bitrate_bps != OPUS_BITRATE_MAX) - { - max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet, - 3*st->bitrate_bps/(3*8*Fs/frame_size))); - } - } - ptr = (char*)st + align(sizeof(OpusMSEncoder)); - for (s=0;s<st->layout.nb_streams;s++) - { - OpusEncoder *enc; - enc = (OpusEncoder*)ptr; - if (s < st->layout.nb_coupled_streams) - ptr += align(coupled_size); - else - ptr += align(mono_size); - opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s])); - if (st->surround) - { - opus_int32 equiv_rate; - equiv_rate = st->bitrate_bps; - if (frame_size*50 < Fs) - equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels; - if (equiv_rate > 10000*st->layout.nb_channels) - opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND)); - else if (equiv_rate > 7000*st->layout.nb_channels) - opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND)); - else if (equiv_rate > 5000*st->layout.nb_channels) - opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND)); - else - opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND)); - if (s < st->layout.nb_coupled_streams) - { - /* To preserve the spatial image, force stereo CELT on coupled streams */ - opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY)); - opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2)); - } - } - } - - ptr = (char*)st + align(sizeof(OpusMSEncoder)); - /* Counting ToC */ - tot_size = 0; - for (s=0;s<st->layout.nb_streams;s++) - { - OpusEncoder *enc; - int len; - int curr_max; - int c1, c2; - - opus_repacketizer_init(&rp); - enc = (OpusEncoder*)ptr; - if (s < st->layout.nb_coupled_streams) - { - int i; - int left, right; - left = get_left_channel(&st->layout, s, -1); - right = get_right_channel(&st->layout, s, -1); - (*copy_channel_in)(buf, 2, - pcm, st->layout.nb_channels, left, frame_size); - (*copy_channel_in)(buf+1, 2, - pcm, st->layout.nb_channels, right, frame_size); - ptr += align(coupled_size); - if (st->surround) - { - for (i=0;i<21;i++) - { - bandLogE[i] = bandSMR[21*left+i]; - bandLogE[21+i] = bandSMR[21*right+i]; - } - } - c1 = left; - c2 = right; - } else { - int i; - int chan = get_mono_channel(&st->layout, s, -1); - (*copy_channel_in)(buf, 1, - pcm, st->layout.nb_channels, chan, frame_size); - ptr += align(mono_size); - if (st->surround) - { - for (i=0;i<21;i++) - bandLogE[i] = bandSMR[21*chan+i]; - } - c1 = chan; - c2 = -1; - } - if (st->surround) - opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE)); - /* number of bytes left (+Toc) */ - curr_max = max_data_bytes - tot_size; - /* Reserve one byte for the last stream and two for the others */ - curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1); - curr_max = IMIN(curr_max,MS_FRAME_TMP); - /* Repacketizer will add one or two bytes for self-delimited frames */ - if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1; - if (!vbr && s == st->layout.nb_streams-1) - opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size))); - len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth, - pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api); - if (len<0) - { - RESTORE_STACK; - return len; - } - /* We need to use the repacketizer to add the self-delimiting lengths - while taking into account the fact that the encoder can now return - more than one frame at a time (e.g. 60 ms CELT-only) */ - opus_repacketizer_cat(&rp, tmp_data, len); - len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp), - data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1); - data += len; - tot_size += len; - } - /*printf("\n");*/ - RESTORE_STACK; - return tot_size; -} - -#if !defined(DISABLE_FLOAT_API) -static void opus_copy_channel_in_float( - opus_val16 *dst, - int dst_stride, - const void *src, - int src_stride, - int src_channel, - int frame_size -) -{ - const float *float_src; - opus_int32 i; - float_src = (const float *)src; - for (i=0;i<frame_size;i++) -#if defined(FIXED_POINT) - dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]); -#else - dst[i*dst_stride] = float_src[i*src_stride+src_channel]; -#endif -} -#endif - -static void opus_copy_channel_in_short( - opus_val16 *dst, - int dst_stride, - const void *src, - int src_stride, - int src_channel, - int frame_size -) -{ - const opus_int16 *short_src; - opus_int32 i; - short_src = (const opus_int16 *)src; - for (i=0;i<frame_size;i++) -#if defined(FIXED_POINT) - dst[i*dst_stride] = short_src[i*src_stride+src_channel]; -#else - dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel]; -#endif -} - - -#ifdef OPUS_FIXED_POINT -int opus_multistream_encode( - OpusMSEncoder *st, - const opus_val16 *pcm, - int frame_size, - unsigned char *data, - opus_int32 max_data_bytes -) -{ - return opus_multistream_encode_native(st, opus_copy_channel_in_short, - pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0); -} - -#ifndef DISABLE_FLOAT_API -int opus_multistream_encode_float( - OpusMSEncoder *st, - const float *pcm, - int frame_size, - unsigned char *data, - opus_int32 max_data_bytes -) -{ - return opus_multistream_encode_native(st, opus_copy_channel_in_float, - pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1); -} -#endif - -#else - -int opus_multistream_encode_float -( - OpusMSEncoder *st, - const opus_val16 *pcm, - int frame_size, - unsigned char *data, - opus_int32 max_data_bytes -) -{ - return opus_multistream_encode_native(st, opus_copy_channel_in_float, - pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1); -} - -int opus_multistream_encode( - OpusMSEncoder *st, - const opus_int16 *pcm, - int frame_size, - unsigned char *data, - opus_int32 max_data_bytes -) -{ - return opus_multistream_encode_native(st, opus_copy_channel_in_short, - pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0); -} -#endif - -int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) -{ - va_list ap; - int coupled_size, mono_size; - char *ptr; - int ret = OPUS_OK; - - va_start(ap, request); - - coupled_size = opus_encoder_get_size(2); - mono_size = opus_encoder_get_size(1); - ptr = (char*)st + align(sizeof(OpusMSEncoder)); - switch (request) - { - case OPUS_SET_BITRATE_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX) - { - goto bad_arg; - } - st->bitrate_bps = value; - } - break; - case OPUS_GET_BITRATE_REQUEST: - { - int s; - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = 0; - for (s=0;s<st->layout.nb_streams;s++) - { - opus_int32 rate; - OpusEncoder *enc; - enc = (OpusEncoder*)ptr; - if (s < st->layout.nb_coupled_streams) - ptr += align(coupled_size); - else - ptr += align(mono_size); - opus_encoder_ctl(enc, request, &rate); - *value += rate; - } - } - break; - case OPUS_GET_LSB_DEPTH_REQUEST: - case OPUS_GET_VBR_REQUEST: - case OPUS_GET_APPLICATION_REQUEST: - case OPUS_GET_BANDWIDTH_REQUEST: - case OPUS_GET_COMPLEXITY_REQUEST: - case OPUS_GET_PACKET_LOSS_PERC_REQUEST: - case OPUS_GET_DTX_REQUEST: - case OPUS_GET_VOICE_RATIO_REQUEST: - case OPUS_GET_VBR_CONSTRAINT_REQUEST: - case OPUS_GET_SIGNAL_REQUEST: - case OPUS_GET_LOOKAHEAD_REQUEST: - case OPUS_GET_SAMPLE_RATE_REQUEST: - case OPUS_GET_INBAND_FEC_REQUEST: - case OPUS_GET_FORCE_CHANNELS_REQUEST: - case OPUS_GET_PREDICTION_DISABLED_REQUEST: - { - OpusEncoder *enc; - /* For int32* GET params, just query the first stream */ - opus_int32 *value = va_arg(ap, opus_int32*); - enc = (OpusEncoder*)ptr; - ret = opus_encoder_ctl(enc, 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++) - { - OpusEncoder *enc; - enc = (OpusEncoder*)ptr; - if (s < st->layout.nb_coupled_streams) - ptr += align(coupled_size); - else - ptr += align(mono_size); - ret = opus_encoder_ctl(enc, request, &tmp); - if (ret != OPUS_OK) break; - *value ^= tmp; - } - } - break; - case OPUS_SET_LSB_DEPTH_REQUEST: - case OPUS_SET_COMPLEXITY_REQUEST: - case OPUS_SET_VBR_REQUEST: - case OPUS_SET_VBR_CONSTRAINT_REQUEST: - case OPUS_SET_MAX_BANDWIDTH_REQUEST: - case OPUS_SET_BANDWIDTH_REQUEST: - case OPUS_SET_SIGNAL_REQUEST: - case OPUS_SET_APPLICATION_REQUEST: - case OPUS_SET_INBAND_FEC_REQUEST: - case OPUS_SET_PACKET_LOSS_PERC_REQUEST: - case OPUS_SET_DTX_REQUEST: - case OPUS_SET_FORCE_MODE_REQUEST: - case OPUS_SET_FORCE_CHANNELS_REQUEST: - case OPUS_SET_PREDICTION_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++) - { - OpusEncoder *enc; - - enc = (OpusEncoder*)ptr; - if (s < st->layout.nb_coupled_streams) - ptr += align(coupled_size); - else - ptr += align(mono_size); - ret = opus_encoder_ctl(enc, request, value); - if (ret != OPUS_OK) - break; - } - } - break; - case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST: - { - int s; - opus_int32 stream_id; - OpusEncoder **value; - stream_id = va_arg(ap, opus_int32); - if (stream_id<0 || stream_id >= st->layout.nb_streams) - ret = OPUS_BAD_ARG; - value = va_arg(ap, OpusEncoder**); - 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 = (OpusEncoder*)ptr; - } - break; - case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST: - { - opus_int32 value = va_arg(ap, opus_int32); - st->variable_duration = value; - } - break; - case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST: - { - opus_int32 *value = va_arg(ap, opus_int32*); - if (!value) - { - goto bad_arg; - } - *value = st->variable_duration; - } - break; - case OPUS_RESET_STATE: - { - int s; - st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0; - if (st->surround) - { - OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels); - OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120); - } - for (s=0;s<st->layout.nb_streams;s++) - { - OpusEncoder *enc; - enc = (OpusEncoder*)ptr; - if (s < st->layout.nb_coupled_streams) - ptr += align(coupled_size); - else - ptr += align(mono_size); - ret = opus_encoder_ctl(enc, OPUS_RESET_STATE); - if (ret != OPUS_OK) - break; - } - } - break; - default: - ret = OPUS_UNIMPLEMENTED; - break; - } - - va_end(ap); - return ret; -bad_arg: - va_end(ap); - return OPUS_BAD_ARG; -} - -void opus_multistream_encoder_destroy(OpusMSEncoder *st) -{ - opus_free(st); -} diff --git a/drivers/opus/opus_private.h b/drivers/opus/opus_private.h deleted file mode 100644 index 129977ed11..0000000000 --- a/drivers/opus/opus_private.h +++ /dev/null @@ -1,134 +0,0 @@ -/* 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 "opus/celt/arch.h" -#include "opus/opus.h" -#include "opus/celt/celt.h" - -#include <stddef.h> /* offsetof */ - -struct OpusRepacketizer { - unsigned char toc; - int nb_frames; - const unsigned char *frames[48]; - opus_int16 len[48]; - int framesize; -}; - -typedef struct ChannelLayout { - int nb_channels; - int nb_streams; - int nb_coupled_streams; - unsigned char mapping[256]; -} ChannelLayout; - -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); - - - -#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); - -int encode_size(int size, unsigned char *data); - -opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs); - -opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size, - int variable_duration, int C, opus_int32 Fs, int bitrate_bps, - int delay_compensation, downmix_func downmix -#ifndef DISABLE_FLOAT_API - , float *subframe_mem -#endif - ); - -opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *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_val16 *pcm, int frame_size, int decode_fec, int self_delimited, - opus_int32 *packet_offset, int soft_clip); - -/* 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); - -opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end, - unsigned char *data, opus_int32 maxlen, int self_delimited, int pad); - -int pad_frame(unsigned char *data, opus_int32 len, opus_int32 new_len); - -#endif /* OPUS_PRIVATE_H */ diff --git a/drivers/opus/opusfile.c b/drivers/opus/opusfile.c deleted file mode 100644 index a9d6cc4d63..0000000000 --- a/drivers/opus/opusfile.c +++ /dev/null @@ -1,3275 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: stdio-based convenience library for opening/seeking/decoding - last mod: $Id: vorbisfile.c 17573 2010-10-27 14:53:59Z xiphmont $ - - ********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/internal.h" -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <limits.h> -#include <string.h> -#include <math.h> - -#include "opus/opusfile.h" - -/*This implementation is largely based off of libvorbisfile. - All of the Ogg bits work roughly the same, though I have made some - "improvements" that have not been folded back there, yet.*/ - -/*A 'chained bitstream' is an Ogg Opus bitstream that contains more than one - logical bitstream arranged end to end (the only form of Ogg multiplexing - supported by this library. - Grouping (parallel multiplexing) is not supported, except to the extent that - if there are multiple logical Ogg streams in a single link of the chain, we - will ignore all but the first Opus stream we find.*/ - -/*An Ogg Opus file can be played beginning to end (streamed) without worrying - ahead of time about chaining (see opusdec from the opus-tools package). - If we have the whole file, however, and want random access - (seeking/scrubbing) or desire to know the total length/time of a file, we - need to account for the possibility of chaining.*/ - -/*We can handle things a number of ways. - We can determine the entire bitstream structure right off the bat, or find - pieces on demand. - This library determines and caches structure for the entire bitstream, but - builds a virtual decoder on the fly when moving between links in the chain.*/ - -/*There are also different ways to implement seeking. - Enough information exists in an Ogg bitstream to seek to sample-granularity - positions in the output. - Or, one can seek by picking some portion of the stream roughly in the desired - area if we only want coarse navigation through the stream. - We implement and expose both strategies.*/ - -/*The maximum number of bytes in a page (including the page headers).*/ -#define OP_PAGE_SIZE_MAX (65307) -/*The default amount to seek backwards per step when trying to find the - previous page. - This must be at least as large as the maximum size of a page.*/ -#define OP_CHUNK_SIZE (65536) -/*The maximum amount to seek backwards per step when trying to find the - previous page.*/ -#define OP_CHUNK_SIZE_MAX (1024*(opus_int32)1024) -/*A smaller read size is needed for low-rate streaming.*/ -#define OP_READ_SIZE (2048) - -int op_test(OpusHead *_head, - const unsigned char *_initial_data,size_t _initial_bytes){ - ogg_sync_state oy; - char *data; - int err; - /*The first page of a normal Opus file will be at most 57 bytes (27 Ogg - page header bytes + 1 lacing value + 21 Opus header bytes + 8 channel - mapping bytes). - It will be at least 47 bytes (27 Ogg page header bytes + 1 lacing value + - 19 Opus header bytes using channel mapping family 0). - If we don't have at least that much data, give up now.*/ - if(_initial_bytes<47)return OP_FALSE; - /*Only proceed if we start with the magic OggS string. - This is to prevent us spending a lot of time allocating memory and looking - for Ogg pages in non-Ogg files.*/ - if(memcmp(_initial_data,"OggS",4)!=0)return OP_ENOTFORMAT; - ogg_sync_init(&oy); - data=ogg_sync_buffer(&oy,_initial_bytes); - if(data!=NULL){ - ogg_stream_state os; - ogg_page og; - int ret; - memcpy(data,_initial_data,_initial_bytes); - ogg_sync_wrote(&oy,_initial_bytes); - ogg_stream_init(&os,-1); - err=OP_FALSE; - do{ - ogg_packet op; - ret=ogg_sync_pageout(&oy,&og); - /*Ignore holes.*/ - if(ret<0)continue; - /*Stop if we run out of data.*/ - if(!ret)break; - ogg_stream_reset_serialno(&os,ogg_page_serialno(&og)); - ogg_stream_pagein(&os,&og); - /*Only process the first packet on this page (if it's a BOS packet, - it's required to be the only one).*/ - if(ogg_stream_packetout(&os,&op)==1){ - if(op.b_o_s){ - ret=opus_head_parse(_head,op.packet,op.bytes); - /*If this didn't look like Opus, keep going.*/ - if(ret==OP_ENOTFORMAT)continue; - /*Otherwise we're done, one way or another.*/ - err=ret; - } - /*We finished parsing the headers. - There is no Opus to be found.*/ - else err=OP_ENOTFORMAT; - } - } - while(err==OP_FALSE); - ogg_stream_clear(&os); - } - else err=OP_EFAULT; - ogg_sync_clear(&oy); - return err; -} - -/*Many, many internal helpers. - The intention is not to be confusing. - Rampant duplication and monolithic function implementation (though we do have - some large, omnibus functions still) would be harder to understand anyway. - The high level functions are last. - Begin grokking near the end of the file if you prefer to read things - top-down.*/ - -/*The read/seek functions track absolute position within the stream.*/ - -/*Read a little more data from the file/pipe into the ogg_sync framer. - _nbytes: The maximum number of bytes to read. - Return: A positive number of bytes read on success, 0 on end-of-file, or a - negative value on failure.*/ -static int op_get_data(OggOpusFile *_of,int _nbytes){ - unsigned char *buffer; - int nbytes; - OP_ASSERT(_nbytes>0); - buffer=(unsigned char *)ogg_sync_buffer(&_of->oy,_nbytes); - nbytes=(int)(*_of->callbacks.read)(_of->source,buffer,_nbytes); - OP_ASSERT(nbytes<=_nbytes); - if(OP_LIKELY(nbytes>0))ogg_sync_wrote(&_of->oy,nbytes); - return nbytes; -} - -/*Save a tiny smidge of verbosity to make the code more readable.*/ -static int op_seek_helper(OggOpusFile *_of,opus_int64 _offset){ - if(_offset==_of->offset)return 0; - if(_of->callbacks.seek==NULL - ||(*_of->callbacks.seek)(_of->source,_offset,SEEK_SET)){ - return OP_EREAD; - } - _of->offset=_offset; - ogg_sync_reset(&_of->oy); - return 0; -} - -/*Get the current position indicator of the underlying source. - This should be the same as the value reported by tell().*/ -static opus_int64 op_position(const OggOpusFile *_of){ - /*The current position indicator is _not_ simply offset. - We may also have unprocessed, buffered data in the sync state.*/ - return _of->offset+_of->oy.fill-_of->oy.returned; -} - -/*From the head of the stream, get the next page. - _boundary specifies if the function is allowed to fetch more data from the - stream (and how much) or only use internally buffered data. - _boundary: -1: Unbounded search. - 0: Read no additional data. - Use only cached data. - n: Search for the start of a new page up to file position n. - Return: n>=0: Found a page at absolute offset n. - OP_FALSE: Hit the _boundary limit. - OP_EREAD: An underlying read operation failed. - OP_BADLINK: We hit end-of-file before reaching _boundary.*/ -static opus_int64 op_get_next_page(OggOpusFile *_of,ogg_page *_og, - opus_int64 _boundary){ - while(_boundary<=0||_of->offset<_boundary){ - int more; - more=ogg_sync_pageseek(&_of->oy,_og); - /*Skipped (-more) bytes.*/ - if(OP_UNLIKELY(more<0))_of->offset-=more; - else if(more==0){ - int read_nbytes; - int ret; - /*Send more paramedics.*/ - if(!_boundary)return OP_FALSE; - if(_boundary<0)read_nbytes=OP_READ_SIZE; - else{ - opus_int64 position; - position=op_position(_of); - if(position>=_boundary)return OP_FALSE; - read_nbytes=(int)OP_MIN(_boundary-position,OP_READ_SIZE); - } - ret=op_get_data(_of,read_nbytes); - if(OP_UNLIKELY(ret<0))return OP_EREAD; - if(OP_UNLIKELY(ret==0)){ - /*Only fail cleanly on EOF if we didn't have a known boundary. - Otherwise, we should have been able to reach that boundary, and this - is a fatal error.*/ - return OP_UNLIKELY(_boundary<0)?OP_FALSE:OP_EBADLINK; - } - } - else{ - /*Got a page. - Return the page start offset and advance the internal offset past the - page end.*/ - opus_int64 page_offset; - page_offset=_of->offset; - _of->offset+=more; - OP_ASSERT(page_offset>=0); - return page_offset; - } - } - return OP_FALSE; -} - -static int op_add_serialno(const ogg_page *_og, - ogg_uint32_t **_serialnos,int *_nserialnos,int *_cserialnos){ - ogg_uint32_t *serialnos; - int nserialnos; - int cserialnos; - ogg_uint32_t s; - s=ogg_page_serialno(_og); - serialnos=*_serialnos; - nserialnos=*_nserialnos; - cserialnos=*_cserialnos; - if(OP_UNLIKELY(nserialnos>=cserialnos)){ - if(OP_UNLIKELY(cserialnos>INT_MAX/(int)sizeof(*serialnos)-1>>1)){ - return OP_EFAULT; - } - cserialnos=2*cserialnos+1; - OP_ASSERT(nserialnos<cserialnos); - serialnos=(ogg_uint32_t *)_ogg_realloc(serialnos, - sizeof(*serialnos)*cserialnos); - if(OP_UNLIKELY(serialnos==NULL))return OP_EFAULT; - } - serialnos[nserialnos++]=s; - *_serialnos=serialnos; - *_nserialnos=nserialnos; - *_cserialnos=cserialnos; - return 0; -} - -/*Returns nonzero if found.*/ -static int op_lookup_serialno(ogg_uint32_t _s, - const ogg_uint32_t *_serialnos,int _nserialnos){ - int i; - for(i=0;i<_nserialnos&&_serialnos[i]!=_s;i++); - return i<_nserialnos; -} - -static int op_lookup_page_serialno(const ogg_page *_og, - const ogg_uint32_t *_serialnos,int _nserialnos){ - return op_lookup_serialno(ogg_page_serialno(_og),_serialnos,_nserialnos); -} - -typedef struct OpusSeekRecord OpusSeekRecord; - -/*We use this to remember the pages we found while enumerating the links of a - chained stream. - We keep track of the starting and ending offsets, as well as the point we - started searching from, so we know where to bisect. - We also keep the serial number, so we can tell if the page belonged to the - current link or not, as well as the granule position, to aid in estimating - the start of the link.*/ -struct OpusSeekRecord{ - /*The earliest byte we know of such that reading forward from it causes - capture to be regained at this page.*/ - opus_int64 search_start; - /*The offset of this page.*/ - opus_int64 offset; - /*The size of this page.*/ - opus_int32 size; - /*The serial number of this page.*/ - ogg_uint32_t serialno; - /*The granule position of this page.*/ - ogg_int64_t gp; -}; - -/*Find the last page beginning before _offset with a valid granule position. - There is no '_boundary' parameter as it will always have to read more data. - This is much dirtier than the above, as Ogg doesn't have any backward search - linkage. - This search prefers pages of the specified serial number. - If a page of the specified serial number is spotted during the - seek-back-and-read-forward, it will return the info of last page of the - matching serial number, instead of the very last page, unless the very last - page belongs to a different link than preferred serial number. - If no page of the specified serial number is seen, it will return the info of - the last page. - [out] _sr: Returns information about the page that was found on success. - _offset: The _offset before which to find a page. - Any page returned will consist of data entirely before _offset. - _serialno: The preferred serial number. - If a page with this serial number is found, it will be returned - even if another page in the same link is found closer to - _offset. - This is purely opportunistic: there is no guarantee such a page - will be found if it exists. - _serialnos: The list of serial numbers in the link that contains the - preferred serial number. - _nserialnos: The number of serial numbers in the current link. - Return: 0 on success, or a negative value on failure. - OP_EREAD: Failed to read more data (error or EOF). - OP_EBADLINK: We couldn't find a page even after seeking back to the - start of the stream.*/ -static int op_get_prev_page_serial(OggOpusFile *_of,OpusSeekRecord *_sr, - opus_int64 _offset,ogg_uint32_t _serialno, - const ogg_uint32_t *_serialnos,int _nserialnos){ - OpusSeekRecord preferred_sr; - ogg_page og; - opus_int64 begin; - opus_int64 end; - opus_int64 original_end; - opus_int32 chunk_size; - int preferred_found; - original_end=end=begin=_offset; - preferred_found=0; - _offset=-1; - chunk_size=OP_CHUNK_SIZE; - do{ - opus_int64 search_start; - int ret; - OP_ASSERT(chunk_size>=OP_PAGE_SIZE_MAX); - begin=OP_MAX(begin-chunk_size,0); - ret=op_seek_helper(_of,begin); - if(OP_UNLIKELY(ret<0))return ret; - search_start=begin; - while(_of->offset<end){ - opus_int64 llret; - ogg_uint32_t serialno; - llret=op_get_next_page(_of,&og,end); - if(OP_UNLIKELY(llret<OP_FALSE))return (int)llret; - else if(llret==OP_FALSE)break; - serialno=ogg_page_serialno(&og); - /*Save the information for this page. - We're not interested in the page itself... just the serial number, byte - offset, page size, and granule position.*/ - _sr->search_start=search_start; - _sr->offset=_offset=llret; - _sr->serialno=serialno; - OP_ASSERT(_of->offset-_offset>=0); - OP_ASSERT(_of->offset-_offset<=OP_PAGE_SIZE_MAX); - _sr->size=(opus_int32)(_of->offset-_offset); - _sr->gp=ogg_page_granulepos(&og); - /*If this page is from the stream we're looking for, remember it.*/ - if(serialno==_serialno){ - preferred_found=1; - *&preferred_sr=*_sr; - } - if(!op_lookup_serialno(serialno,_serialnos,_nserialnos)){ - /*We fell off the end of the link, which means we seeked back too far - and shouldn't have been looking in that link to begin with. - If we found the preferred serial number, forget that we saw it.*/ - preferred_found=0; - } - search_start=llret+1; - } - /*We started from the beginning of the stream and found nothing. - This should be impossible unless the contents of the source changed out - from under us after we read from it.*/ - if(OP_UNLIKELY(!begin)&&OP_UNLIKELY(_offset<0))return OP_EBADLINK; - /*Bump up the chunk size. - This is mildly helpful when seeks are very expensive (http).*/ - chunk_size=OP_MIN(2*chunk_size,OP_CHUNK_SIZE_MAX); - /*Avoid quadratic complexity if we hit an invalid patch of the file.*/ - end=OP_MIN(begin+OP_PAGE_SIZE_MAX-1,original_end); - } - while(_offset<0); - if(preferred_found)*_sr=*&preferred_sr; - return 0; -} - -/*Find the last page beginning before _offset with the given serial number and - a valid granule position. - Unlike the above search, this continues until it finds such a page, but does - not stray outside the current link. - We could implement it (inefficiently) by calling op_get_prev_page_serial() - repeatedly until it returned a page that had both our preferred serial - number and a valid granule position, but doing it with a separate function - allows us to avoid repeatedly re-scanning valid pages from other streams as - we seek-back-and-read-forward. - [out] _gp: Returns the granule position of the page that was found on - success. - _offset: The _offset before which to find a page. - Any page returned will consist of data entirely before _offset. - _serialno: The target serial number. - _serialnos: The list of serial numbers in the link that contains the - preferred serial number. - _nserialnos: The number of serial numbers in the current link. - Return: The offset of the page on success, or a negative value on failure. - OP_EREAD: Failed to read more data (error or EOF). - OP_EBADLINK: We couldn't find a page even after seeking back past the - beginning of the link.*/ -static opus_int64 op_get_last_page(OggOpusFile *_of,ogg_int64_t *_gp, - opus_int64 _offset,ogg_uint32_t _serialno, - const ogg_uint32_t *_serialnos,int _nserialnos){ - ogg_page og; - ogg_int64_t gp; - opus_int64 begin; - opus_int64 end; - opus_int64 original_end; - opus_int32 chunk_size; - /*The target serial number must belong to the current link.*/ - OP_ASSERT(op_lookup_serialno(_serialno,_serialnos,_nserialnos)); - original_end=end=begin=_offset; - _offset=-1; - /*We shouldn't have to initialize gp, but gcc is too dumb to figure out that - ret>=0 implies we entered the if(page_gp!=-1) block at least once.*/ - gp=-1; - chunk_size=OP_CHUNK_SIZE; - do{ - int left_link; - int ret; - OP_ASSERT(chunk_size>=OP_PAGE_SIZE_MAX); - begin=OP_MAX(begin-chunk_size,0); - ret=op_seek_helper(_of,begin); - if(OP_UNLIKELY(ret<0))return ret; - left_link=0; - while(_of->offset<end){ - opus_int64 llret; - ogg_uint32_t serialno; - llret=op_get_next_page(_of,&og,end); - if(OP_UNLIKELY(llret<OP_FALSE))return llret; - else if(llret==OP_FALSE)break; - serialno=ogg_page_serialno(&og); - if(serialno==_serialno){ - ogg_int64_t page_gp; - /*The page is from the right stream...*/ - page_gp=ogg_page_granulepos(&og); - if(page_gp!=-1){ - /*And has a valid granule position. - Let's remember it.*/ - _offset=llret; - gp=page_gp; - } - } - else if(OP_UNLIKELY(!op_lookup_serialno(serialno, - _serialnos,_nserialnos))){ - /*We fell off the start of the link, which means we don't need to keep - seeking any farther back.*/ - left_link=1; - } - } - /*We started from at or before the beginning of the link and found nothing. - This should be impossible unless the contents of the source changed out - from under us after we read from it.*/ - if((OP_UNLIKELY(left_link)||OP_UNLIKELY(!begin))&&OP_UNLIKELY(_offset<0)){ - return OP_EBADLINK; - } - /*Bump up the chunk size. - This is mildly helpful when seeks are very expensive (http).*/ - chunk_size=OP_MIN(2*chunk_size,OP_CHUNK_SIZE_MAX); - /*Avoid quadratic complexity if we hit an invalid patch of the file.*/ - end=OP_MIN(begin+OP_PAGE_SIZE_MAX-1,original_end); - } - while(_offset<0); - *_gp=gp; - return _offset; -} - -/*Uses the local ogg_stream storage in _of. - This is important for non-streaming input sources.*/ -static int op_fetch_headers_impl(OggOpusFile *_of,OpusHead *_head, - OpusTags *_tags,ogg_uint32_t **_serialnos,int *_nserialnos, - int *_cserialnos,ogg_page *_og){ - ogg_packet op; - int ret; - if(_serialnos!=NULL)*_nserialnos=0; - /*Extract the serialnos of all BOS pages plus the first set of Opus headers - we see in the link.*/ - while(ogg_page_bos(_og)){ - if(_serialnos!=NULL){ - if(OP_UNLIKELY(op_lookup_page_serialno(_og,*_serialnos,*_nserialnos))){ - /*A dupe serialnumber in an initial header packet set==invalid stream.*/ - return OP_EBADHEADER; - } - ret=op_add_serialno(_og,_serialnos,_nserialnos,_cserialnos); - if(OP_UNLIKELY(ret<0))return ret; - } - if(_of->ready_state<OP_STREAMSET){ - /*We don't have an Opus stream in this link yet, so begin prospective - stream setup. - We need a stream to get packets.*/ - ogg_stream_reset_serialno(&_of->os,ogg_page_serialno(_og)); - ogg_stream_pagein(&_of->os,_og); - if(OP_LIKELY(ogg_stream_packetout(&_of->os,&op)>0)){ - ret=opus_head_parse(_head,op.packet,op.bytes); - /*Found a valid Opus header. - Continue setup.*/ - if(OP_LIKELY(ret>=0))_of->ready_state=OP_STREAMSET; - /*If it's just a stream type we don't recognize, ignore it. - Everything else is fatal.*/ - else if(ret!=OP_ENOTFORMAT)return ret; - } - } - /*Get the next page. - No need to clamp the boundary offset against _of->end, as all errors - become OP_ENOTFORMAT or OP_EBADHEADER.*/ - if(OP_UNLIKELY(op_get_next_page(_of,_og, - OP_ADV_OFFSET(_of->offset,OP_CHUNK_SIZE))<0)){ - return _of->ready_state<OP_STREAMSET?OP_ENOTFORMAT:OP_EBADHEADER; - } - } - if(OP_UNLIKELY(_of->ready_state!=OP_STREAMSET))return OP_ENOTFORMAT; - /*If the first non-header page belonged to our Opus stream, submit it.*/ - if(_of->os.serialno==ogg_page_serialno(_og))ogg_stream_pagein(&_of->os,_og); - /*Loop getting packets.*/ - for(;;){ - switch(ogg_stream_packetout(&_of->os,&op)){ - case 0:{ - /*Loop getting pages.*/ - for(;;){ - /*No need to clamp the boundary offset against _of->end, as all - errors become OP_EBADHEADER.*/ - if(OP_UNLIKELY(op_get_next_page(_of,_og, - OP_ADV_OFFSET(_of->offset,OP_CHUNK_SIZE))<0)){ - return OP_EBADHEADER; - } - /*If this page belongs to the correct stream, go parse it.*/ - if(_of->os.serialno==ogg_page_serialno(_og)){ - ogg_stream_pagein(&_of->os,_og); - break; - } - /*If the link ends before we see the Opus comment header, abort.*/ - if(OP_UNLIKELY(ogg_page_bos(_og)))return OP_EBADHEADER; - /*Otherwise, keep looking.*/ - } - }break; - /*We shouldn't get a hole in the headers!*/ - case -1:return OP_EBADHEADER; - default:{ - /*Got a packet. - It should be the comment header.*/ - ret=opus_tags_parse(_tags,op.packet,op.bytes); - if(OP_UNLIKELY(ret<0))return ret; - /*Make sure the page terminated at the end of the comment header. - If there is another packet on the page, or part of a packet, then - reject the stream. - Otherwise seekable sources won't be able to seek back to the start - properly.*/ - ret=ogg_stream_packetout(&_of->os,&op); - if(OP_UNLIKELY(ret!=0) - ||OP_UNLIKELY(_og->header[_og->header_len-1]==255)){ - /*If we fail, the caller assumes our tags are uninitialized.*/ - opus_tags_clear(_tags); - return OP_EBADHEADER; - } - return 0; - } - } - } -} - -static int op_fetch_headers(OggOpusFile *_of,OpusHead *_head, - OpusTags *_tags,ogg_uint32_t **_serialnos,int *_nserialnos, - int *_cserialnos,ogg_page *_og){ - ogg_page og; - int ret; - if(!_og){ - /*No need to clamp the boundary offset against _of->end, as all errors - become OP_ENOTFORMAT.*/ - if(OP_UNLIKELY(op_get_next_page(_of,&og, - OP_ADV_OFFSET(_of->offset,OP_CHUNK_SIZE))<0)){ - return OP_ENOTFORMAT; - } - _og=&og; - } - _of->ready_state=OP_OPENED; - ret=op_fetch_headers_impl(_of,_head,_tags,_serialnos,_nserialnos, - _cserialnos,_og); - /*Revert back from OP_STREAMSET to OP_OPENED on failure, to prevent - double-free of the tags in an unseekable stream.*/ - if(OP_UNLIKELY(ret<0))_of->ready_state=OP_OPENED; - return ret; -} - -/*Granule position manipulation routines. - A granule position is defined to be an unsigned 64-bit integer, with the - special value -1 in two's complement indicating an unset or invalid granule - position. - We are not guaranteed to have an unsigned 64-bit type, so we construct the - following routines that - a) Properly order negative numbers as larger than positive numbers, and - b) Check for underflow or overflow past the special -1 value. - This lets us operate on the full, valid range of granule positions in a - consistent and safe manner. - This full range is organized into distinct regions: - [ -1 (invalid) ][ 0 ... OP_INT64_MAX ][ OP_INT64_MIN ... -2 ][-1 (invalid) ] - - No one should actually use granule positions so large that they're negative, - even if they are technically valid, as very little software handles them - correctly (including most of Xiph.Org's). - This library also refuses to support durations so large they won't fit in a - signed 64-bit integer (to avoid exposing this mess to the application, and - to simplify a good deal of internal arithmetic), so the only way to use them - successfully is if pcm_start is very large. - This means there isn't anything you can do with negative granule positions - that you couldn't have done with purely non-negative ones. - The main purpose of these routines is to allow us to think very explicitly - about the possible failure cases of all granule position manipulations.*/ - -/*Safely adds a small signed integer to a valid (not -1) granule position. - The result can use the full 64-bit range of values (both positive and - negative), but will fail on overflow (wrapping past -1; wrapping past - OP_INT64_MAX is explicitly okay). - [out] _dst_gp: The resulting granule position. - Only modified on success. - _src_gp: The granule position to add to. - This must not be -1. - _delta: The amount to add. - This is allowed to be up to 32 bits to support the maximum - duration of a single Ogg page (255 packets * 120 ms per - packet == 1,468,800 samples at 48 kHz). - Return: 0 on success, or OP_EINVAL if the result would wrap around past -1.*/ -static int op_granpos_add(ogg_int64_t *_dst_gp,ogg_int64_t _src_gp, - opus_int32 _delta){ - /*The code below handles this case correctly, but there's no reason we - should ever be called with these values, so make sure we aren't.*/ - OP_ASSERT(_src_gp!=-1); - if(_delta>0){ - /*Adding this amount to the granule position would overflow its 64-bit - range.*/ - if(OP_UNLIKELY(_src_gp<0)&&OP_UNLIKELY(_src_gp>=-1-_delta))return OP_EINVAL; - if(OP_UNLIKELY(_src_gp>OP_INT64_MAX-_delta)){ - /*Adding this amount to the granule position would overflow the positive - half of its 64-bit range. - Since signed overflow is undefined in C, do it in a way the compiler - isn't allowed to screw up.*/ - _delta-=(opus_int32)(OP_INT64_MAX-_src_gp)+1; - _src_gp=OP_INT64_MIN; - } - } - else if(_delta<0){ - /*Subtracting this amount from the granule position would underflow its - 64-bit range.*/ - if(_src_gp>=0&&OP_UNLIKELY(_src_gp<-_delta))return OP_EINVAL; - if(OP_UNLIKELY(_src_gp<OP_INT64_MIN-_delta)){ - /*Subtracting this amount from the granule position would underflow the - negative half of its 64-bit range. - Since signed underflow is undefined in C, do it in a way the compiler - isn't allowed to screw up.*/ - _delta+=(opus_int32)(_src_gp-OP_INT64_MIN)+1; - _src_gp=OP_INT64_MAX; - } - } - *_dst_gp=_src_gp+_delta; - return 0; -} - -/*Safely computes the difference between two granule positions. - The difference must fit in a signed 64-bit integer, or the function fails. - It correctly handles the case where the granule position has wrapped around - from positive values to negative ones. - [out] _delta: The difference between the granule positions. - Only modified on success. - _gp_a: The granule position to subtract from. - This must not be -1. - _gp_b: The granule position to subtract. - This must not be -1. - Return: 0 on success, or OP_EINVAL if the result would not fit in a signed - 64-bit integer.*/ -static int op_granpos_diff(ogg_int64_t *_delta, - ogg_int64_t _gp_a,ogg_int64_t _gp_b){ - int gp_a_negative; - int gp_b_negative; - /*The code below handles these cases correctly, but there's no reason we - should ever be called with these values, so make sure we aren't.*/ - OP_ASSERT(_gp_a!=-1); - OP_ASSERT(_gp_b!=-1); - gp_a_negative=OP_UNLIKELY(_gp_a<0); - gp_b_negative=OP_UNLIKELY(_gp_b<0); - if(OP_UNLIKELY(gp_a_negative^gp_b_negative)){ - ogg_int64_t da; - ogg_int64_t db; - if(gp_a_negative){ - /*_gp_a has wrapped to a negative value but _gp_b hasn't: the difference - should be positive.*/ - /*Step 1: Handle wrapping.*/ - /*_gp_a < 0 => da < 0.*/ - da=(OP_INT64_MIN-_gp_a)-1; - /*_gp_b >= 0 => db >= 0.*/ - db=OP_INT64_MAX-_gp_b; - /*Step 2: Check for overflow.*/ - if(OP_UNLIKELY(OP_INT64_MAX+da<db))return OP_EINVAL; - *_delta=db-da; - } - else{ - /*_gp_b has wrapped to a negative value but _gp_a hasn't: the difference - should be negative.*/ - /*Step 1: Handle wrapping.*/ - /*_gp_a >= 0 => da <= 0*/ - da=_gp_a+OP_INT64_MIN; - /*_gp_b < 0 => db <= 0*/ - db=OP_INT64_MIN-_gp_b; - /*Step 2: Check for overflow.*/ - if(OP_UNLIKELY(da<OP_INT64_MIN-db))return OP_EINVAL; - *_delta=da+db; - } - } - else *_delta=_gp_a-_gp_b; - return 0; -} - -static int op_granpos_cmp(ogg_int64_t _gp_a,ogg_int64_t _gp_b){ - /*The invalid granule position -1 should behave like NaN: neither greater - than nor less than any other granule position, nor equal to any other - granule position, including itself. - However, that means there isn't anything we could sensibly return from this - function for it.*/ - OP_ASSERT(_gp_a!=-1); - OP_ASSERT(_gp_b!=-1); - /*Handle the wrapping cases.*/ - if(OP_UNLIKELY(_gp_a<0)){ - if(_gp_b>=0)return 1; - /*Else fall through.*/ - } - else if(OP_UNLIKELY(_gp_b<0))return -1; - /*No wrapping case.*/ - return (_gp_a>_gp_b)-(_gp_b>_gp_a); -} - -/*Returns the duration of the packet (in samples at 48 kHz), or a negative - value on error.*/ -static int op_get_packet_duration(const unsigned char *_data,int _len){ - int nframes; - int frame_size; - int nsamples; - nframes=opus_packet_get_nb_frames(_data,_len); - if(OP_UNLIKELY(nframes<0))return OP_EBADPACKET; - frame_size=opus_packet_get_samples_per_frame(_data,48000); - nsamples=nframes*frame_size; - if(OP_UNLIKELY(nsamples>120*48))return OP_EBADPACKET; - return nsamples; -} - -/*This function more properly belongs in info.c, but we define it here to allow - the static granule position manipulation functions to remain static.*/ -ogg_int64_t opus_granule_sample(const OpusHead *_head,ogg_int64_t _gp){ - opus_int32 pre_skip; - pre_skip=_head->pre_skip; - if(_gp!=-1&&op_granpos_add(&_gp,_gp,-pre_skip))_gp=-1; - return _gp; -} - -/*Grab all the packets currently in the stream state, and compute their - durations. - _of->op_count is set to the number of packets collected. - [out] _durations: Returns the durations of the individual packets. - Return: The total duration of all packets, or OP_HOLE if there was a hole.*/ -static opus_int32 op_collect_audio_packets(OggOpusFile *_of, - int _durations[255]){ - opus_int32 total_duration; - int op_count; - /*Count the durations of all packets in the page.*/ - op_count=0; - total_duration=0; - for(;;){ - int ret; - /*This takes advantage of undocumented libogg behavior that returned - ogg_packet buffers are valid at least until the next page is - submitted. - Relying on this is not too terrible, as _none_ of the Ogg memory - ownership/lifetime rules are well-documented. - But I can read its code and know this will work.*/ - ret=ogg_stream_packetout(&_of->os,_of->op+op_count); - if(!ret)break; - if(OP_UNLIKELY(ret<0)){ - /*We shouldn't get holes in the middle of pages.*/ - OP_ASSERT(op_count==0); - /*Set the return value and break out of the loop. - We want to make sure op_count gets set to 0, because we've ingested a - page, so any previously loaded packets are now invalid.*/ - total_duration=OP_HOLE; - break; - } - /*Unless libogg is broken, we can't get more than 255 packets from a - single page.*/ - OP_ASSERT(op_count<255); - _durations[op_count]=op_get_packet_duration(_of->op[op_count].packet, - _of->op[op_count].bytes); - if(OP_LIKELY(_durations[op_count]>0)){ - /*With at most 255 packets on a page, this can't overflow.*/ - total_duration+=_durations[op_count++]; - } - /*Ignore packets with an invalid TOC sequence.*/ - else if(op_count>0){ - /*But save the granule position, if there was one.*/ - _of->op[op_count-1].granulepos=_of->op[op_count].granulepos; - } - } - _of->op_pos=0; - _of->op_count=op_count; - return total_duration; -} - -/*Starting from current cursor position, get the initial PCM offset of the next - page. - This also validates the granule position on the first page with a completed - audio data packet, as required by the spec. - If this link is completely empty (no pages with completed packets), then this - function sets pcm_start=pcm_end=0 and returns the BOS page of the next link - (if any). - In the seekable case, we initialize pcm_end=-1 before calling this function, - so that later we can detect that the link was empty before calling - op_find_final_pcm_offset(). - [inout] _link: The link for which to find pcm_start. - [out] _og: Returns the BOS page of the next link if this link was empty. - In the unseekable case, we can then feed this to - op_fetch_headers() to start the next link. - The caller may pass NULL (e.g., for seekable streams), in - which case this page will be discarded. - Return: 0 on success, 1 if there is a buffered BOS page available, or a - negative value on unrecoverable error.*/ -static int op_find_initial_pcm_offset(OggOpusFile *_of, - OggOpusLink *_link,ogg_page *_og){ - ogg_page og; - opus_int64 page_offset; - ogg_int64_t pcm_start; - ogg_int64_t prev_packet_gp; - ogg_int64_t cur_page_gp; - ogg_uint32_t serialno; - opus_int32 total_duration; - int durations[255]; - int cur_page_eos; - int op_count; - int pi; - if(_og==NULL)_og=&og; - serialno=_of->os.serialno; - op_count=0; - /*We shouldn't have to initialize total_duration, but gcc is too dumb to - figure out that op_count>0 implies we've been through the whole loop at - least once.*/ - total_duration=0; - do{ - page_offset=op_get_next_page(_of,_og,_of->end); - /*We should get a page unless the file is truncated or mangled. - Otherwise there are no audio data packets in the whole logical stream.*/ - if(OP_UNLIKELY(page_offset<0)){ - /*Fail if there was a read error.*/ - if(page_offset<OP_FALSE)return (int)page_offset; - /*Fail if the pre-skip is non-zero, since it's asking us to skip more - samples than exist.*/ - if(_link->head.pre_skip>0)return OP_EBADTIMESTAMP; - /*Set pcm_end and end_offset so we can skip the call to - op_find_final_pcm_offset().*/ - _link->pcm_start=_link->pcm_end=0; - _link->end_offset=_link->data_offset; - return 0; - } - /*Similarly, if we hit the next link in the chain, we've gone too far.*/ - if(OP_UNLIKELY(ogg_page_bos(_og))){ - if(_link->head.pre_skip>0)return OP_EBADTIMESTAMP; - /*Set pcm_end and end_offset so we can skip the call to - op_find_final_pcm_offset().*/ - _link->pcm_end=_link->pcm_start=0; - _link->end_offset=_link->data_offset; - /*Tell the caller we've got a buffered page for them.*/ - return 1; - } - /*Ignore pages from other streams (not strictly necessary, because of the - checks in ogg_stream_pagein(), but saves some work).*/ - if(serialno!=(ogg_uint32_t)ogg_page_serialno(_og))continue; - ogg_stream_pagein(&_of->os,_og); - /*Bitrate tracking: add the header's bytes here. - The body bytes are counted when we consume the packets.*/ - _of->bytes_tracked+=_og->header_len; - /*Count the durations of all packets in the page.*/ - do total_duration=op_collect_audio_packets(_of,durations); - /*Ignore holes.*/ - while(OP_UNLIKELY(total_duration<0)); - op_count=_of->op_count; - } - while(op_count<=0); - /*We found the first page with a completed audio data packet: actually look - at the granule position. - RFC 3533 says, "A special value of -1 (in two's complement) indicates that - no packets finish on this page," which does not say that a granule - position that is NOT -1 indicates that some packets DO finish on that page - (even though this was the intention, libogg itself violated this intention - for years before we fixed it). - The Ogg Opus specification only imposes its start-time requirements - on the granule position of the first page with completed packets, - so we ignore any set granule positions until then.*/ - cur_page_gp=_of->op[op_count-1].granulepos; - /*But getting a packet without a valid granule position on the page is not - okay.*/ - if(cur_page_gp==-1)return OP_EBADTIMESTAMP; - cur_page_eos=_of->op[op_count-1].e_o_s; - if(OP_LIKELY(!cur_page_eos)){ - /*The EOS flag wasn't set. - Work backwards from the provided granule position to get the starting PCM - offset.*/ - if(OP_UNLIKELY(op_granpos_add(&pcm_start,cur_page_gp,-total_duration)<0)){ - /*The starting granule position MUST not be smaller than the amount of - audio on the first page with completed packets.*/ - return OP_EBADTIMESTAMP; - } - } - else{ - /*The first page with completed packets was also the last.*/ - if(OP_LIKELY(op_granpos_add(&pcm_start,cur_page_gp,-total_duration)<0)){ - /*If there's less audio on the page than indicated by the granule - position, then we're doing end-trimming, and the starting PCM offset - is zero by spec mandate.*/ - pcm_start=0; - /*However, the end-trimming MUST not ask us to trim more samples than - exist after applying the pre-skip.*/ - if(OP_UNLIKELY(op_granpos_cmp(cur_page_gp,_link->head.pre_skip)<0)){ - return OP_EBADTIMESTAMP; - } - } - } - /*Timestamp the individual packets.*/ - prev_packet_gp=pcm_start; - for(pi=0;pi<op_count;pi++){ - if(cur_page_eos){ - ogg_int64_t diff; - OP_ALWAYS_TRUE(!op_granpos_diff(&diff,cur_page_gp,prev_packet_gp)); - diff=durations[pi]-diff; - /*If we have samples to trim...*/ - if(diff>0){ - /*If we trimmed the entire packet, stop (the spec says encoders - shouldn't do this, but we support it anyway).*/ - if(OP_UNLIKELY(diff>durations[pi]))break; - _of->op[pi].granulepos=prev_packet_gp=cur_page_gp; - /*Move the EOS flag to this packet, if necessary, so we'll trim the - samples.*/ - _of->op[pi].e_o_s=1; - continue; - } - } - /*Update the granule position as normal.*/ - OP_ALWAYS_TRUE(!op_granpos_add(&_of->op[pi].granulepos, - prev_packet_gp,durations[pi])); - prev_packet_gp=_of->op[pi].granulepos; - } - /*Update the packet count after end-trimming.*/ - _of->op_count=pi; - _of->cur_discard_count=_link->head.pre_skip; - _of->prev_packet_gp=_link->pcm_start=pcm_start; - _of->prev_page_offset=page_offset; - return 0; -} - -/*Starting from current cursor position, get the final PCM offset of the - previous page. - This also validates the duration of the link, which, while not strictly - required by the spec, we need to ensure duration calculations don't - overflow. - This is only done for seekable sources. - We must validate that op_find_initial_pcm_offset() succeeded for this link - before calling this function, otherwise it will scan the entire stream - backwards until it reaches the start, and then fail.*/ -static int op_find_final_pcm_offset(OggOpusFile *_of, - const ogg_uint32_t *_serialnos,int _nserialnos,OggOpusLink *_link, - opus_int64 _offset,ogg_uint32_t _end_serialno,ogg_int64_t _end_gp, - ogg_int64_t *_total_duration){ - ogg_int64_t total_duration; - ogg_int64_t duration; - ogg_uint32_t cur_serialno; - /*For the time being, fetch end PCM offset the simple way.*/ - cur_serialno=_link->serialno; - if(_end_serialno!=cur_serialno||_end_gp==-1){ - _offset=op_get_last_page(_of,&_end_gp,_offset, - cur_serialno,_serialnos,_nserialnos); - if(OP_UNLIKELY(_offset<0))return (int)_offset; - } - /*At worst we should have found the first page with completed packets.*/ - if(OP_UNLIKELY(_offset<_link->data_offset))return OP_EBADLINK; - /*This implementation requires that the difference between the first and last - granule positions in each link be representable in a signed, 64-bit - number, and that each link also have at least as many samples as the - pre-skip requires.*/ - if(OP_UNLIKELY(op_granpos_diff(&duration,_end_gp,_link->pcm_start)<0) - ||OP_UNLIKELY(duration<_link->head.pre_skip)){ - return OP_EBADTIMESTAMP; - } - /*We also require that the total duration be representable in a signed, - 64-bit number.*/ - duration-=_link->head.pre_skip; - total_duration=*_total_duration; - if(OP_UNLIKELY(OP_INT64_MAX-duration<total_duration))return OP_EBADTIMESTAMP; - *_total_duration=total_duration+duration; - _link->pcm_end=_end_gp; - _link->end_offset=_offset; - return 0; -} - -/*Rescale the number _x from the range [0,_from] to [0,_to]. - _from and _to must be positive.*/ -static opus_int64 op_rescale64(opus_int64 _x,opus_int64 _from,opus_int64 _to){ - opus_int64 frac; - opus_int64 ret; - int i; - if(_x>=_from)return _to; - if(_x<=0)return 0; - frac=0; - for(i=0;i<63;i++){ - frac<<=1; - OP_ASSERT(_x<=_from); - if(_x>=_from>>1){ - _x-=_from-_x; - frac|=1; - } - else _x<<=1; - } - ret=0; - for(i=0;i<63;i++){ - if(frac&1)ret=(ret&_to&1)+(ret>>1)+(_to>>1); - else ret>>=1; - frac>>=1; - } - return ret; -} - -/*The minimum granule position spacing allowed for making predictions. - This corresponds to about 1 second of audio at 48 kHz for both Opus and - Vorbis, or one keyframe interval in Theora with the default keyframe spacing - of 256.*/ -#define OP_GP_SPACING_MIN (48000) - -/*Try to estimate the location of the next link using the current seek - records, assuming the initial granule position of any streams we've found is - 0.*/ -static opus_int64 op_predict_link_start(const OpusSeekRecord *_sr,int _nsr, - opus_int64 _searched,opus_int64 _end_searched,opus_int32 _bias){ - opus_int64 bisect; - int sri; - int srj; - /*Require that we be at least OP_CHUNK_SIZE from the end. - We don't require that we be at least OP_CHUNK_SIZE from the beginning, - because if we are we'll just scan forward without seeking.*/ - _end_searched-=OP_CHUNK_SIZE; - if(_searched>=_end_searched)return -1; - bisect=_end_searched; - for(sri=0;sri<_nsr;sri++){ - ogg_int64_t gp1; - ogg_int64_t gp2_min; - ogg_uint32_t serialno1; - opus_int64 offset1; - /*If the granule position is negative, either it's invalid or we'd cause - overflow.*/ - gp1=_sr[sri].gp; - if(gp1<0)continue; - /*We require some minimum distance between granule positions to make an - estimate. - We don't actually know what granule position scheme is being used, - because we have no idea what kind of stream these came from. - Therefore we require a minimum spacing between them, with the - expectation that while bitrates and granule position increments might - vary locally in quite complex ways, they are globally smooth.*/ - if(OP_UNLIKELY(op_granpos_add(&gp2_min,gp1,OP_GP_SPACING_MIN)<0)){ - /*No granule position would satisfy us.*/ - continue; - } - offset1=_sr[sri].offset; - serialno1=_sr[sri].serialno; - for(srj=sri;srj-->0;){ - ogg_int64_t gp2; - opus_int64 offset2; - opus_int64 num; - ogg_int64_t den; - ogg_int64_t ipart; - gp2=_sr[srj].gp; - if(gp2<gp2_min)continue; - /*Oh, and also make sure these came from the same stream.*/ - if(_sr[srj].serialno!=serialno1)continue; - offset2=_sr[srj].offset; - /*For once, we can subtract with impunity.*/ - den=gp2-gp1; - ipart=gp2/den; - num=offset2-offset1; - OP_ASSERT(num>0); - if(ipart>0&&(offset2-_searched)/ipart<num)continue; - offset2-=ipart*num; - gp2-=ipart*den; - offset2-=op_rescale64(gp2,den,num)-_bias; - if(offset2<_searched)continue; - bisect=OP_MIN(bisect,offset2); - break; - } - } - return bisect>=_end_searched?-1:bisect; -} - -/*Finds each bitstream link, one at a time, using a bisection search. - This has to begin by knowing the offset of the first link's initial page.*/ -static int op_bisect_forward_serialno(OggOpusFile *_of, - opus_int64 _searched,OpusSeekRecord *_sr,int _csr, - ogg_uint32_t **_serialnos,int *_nserialnos,int *_cserialnos){ - ogg_page og; - OggOpusLink *links; - int nlinks; - int clinks; - ogg_uint32_t *serialnos; - int nserialnos; - ogg_int64_t total_duration; - int nsr; - int ret; - links=_of->links; - nlinks=clinks=_of->nlinks; - total_duration=0; - /*We start with one seek record, for the last page in the file. - We build up a list of records for places we seek to during link - enumeration. - This list is kept sorted in reverse order. - We only care about seek locations that were _not_ in the current link, - therefore we can add them one at a time to the end of the list as we - improve the lower bound on the location where the next link starts.*/ - nsr=1; - for(;;){ - opus_int64 end_searched; - opus_int64 bisect; - opus_int64 next; - opus_int64 last; - ogg_int64_t end_offset; - ogg_int64_t end_gp; - int sri; - serialnos=*_serialnos; - nserialnos=*_nserialnos; - if(OP_UNLIKELY(nlinks>=clinks)){ - if(OP_UNLIKELY(clinks>INT_MAX-1>>1))return OP_EFAULT; - clinks=2*clinks+1; - OP_ASSERT(nlinks<clinks); - links=(OggOpusLink *)_ogg_realloc(links,sizeof(*links)*clinks); - if(OP_UNLIKELY(links==NULL))return OP_EFAULT; - _of->links=links; - } - /*Invariants: - We have the headers and serial numbers for the link beginning at 'begin'. - We have the offset and granule position of the last page in the file - (potentially not a page we care about).*/ - /*Scan the seek records we already have to save us some bisection.*/ - for(sri=0;sri<nsr;sri++){ - if(op_lookup_serialno(_sr[sri].serialno,serialnos,nserialnos))break; - } - /*Is the last page in our current list of serial numbers?*/ - if(sri<=0)break; - /*Last page wasn't found. - We have at least one more link.*/ - last=-1; - end_searched=_sr[sri-1].search_start; - next=_sr[sri-1].offset; - end_gp=-1; - if(sri<nsr){ - _searched=_sr[sri].offset+_sr[sri].size; - if(_sr[sri].serialno==links[nlinks-1].serialno){ - end_gp=_sr[sri].gp; - end_offset=_sr[sri].offset; - } - } - nsr=sri; - bisect=-1; - /*If we've already found the end of at least one link, try to pick the - first bisection point at twice the average link size. - This is a good choice for files with lots of links that are all about the - same size.*/ - if(nlinks>1){ - opus_int64 last_offset; - opus_int64 avg_link_size; - opus_int64 upper_limit; - last_offset=links[nlinks-1].offset; - avg_link_size=last_offset/(nlinks-1); - upper_limit=end_searched-OP_CHUNK_SIZE-avg_link_size; - if(OP_LIKELY(last_offset>_searched-avg_link_size) - &&OP_LIKELY(last_offset<upper_limit)){ - bisect=last_offset+avg_link_size; - if(OP_LIKELY(bisect<upper_limit))bisect+=avg_link_size; - } - } - /*We guard against garbage separating the last and first pages of two - links below.*/ - while(_searched<end_searched){ - opus_int32 next_bias; - /*If we don't have a better estimate, use simple bisection.*/ - if(bisect==-1)bisect=_searched+(end_searched-_searched>>1); - /*If we're within OP_CHUNK_SIZE of the start, scan forward.*/ - if(bisect-_searched<OP_CHUNK_SIZE)bisect=_searched; - /*Otherwise we're skipping data. - Forget the end page, if we saw one, as we might miss a later one.*/ - else end_gp=-1; - ret=op_seek_helper(_of,bisect); - if(OP_UNLIKELY(ret<0))return ret; - last=op_get_next_page(_of,&og,_sr[nsr-1].offset); - if(OP_UNLIKELY(last<OP_FALSE))return (int)last; - next_bias=0; - if(last==OP_FALSE)end_searched=bisect; - else{ - ogg_uint32_t serialno; - ogg_int64_t gp; - serialno=ogg_page_serialno(&og); - gp=ogg_page_granulepos(&og); - if(!op_lookup_serialno(serialno,serialnos,nserialnos)){ - end_searched=bisect; - next=last; - /*In reality we should always have enough room, but be paranoid.*/ - if(OP_LIKELY(nsr<_csr)){ - _sr[nsr].search_start=bisect; - _sr[nsr].offset=last; - OP_ASSERT(_of->offset-last>=0); - OP_ASSERT(_of->offset-last<=OP_PAGE_SIZE_MAX); - _sr[nsr].size=(opus_int32)(_of->offset-last); - _sr[nsr].serialno=serialno; - _sr[nsr].gp=gp; - nsr++; - } - } - else{ - _searched=_of->offset; - next_bias=OP_CHUNK_SIZE; - if(serialno==links[nlinks-1].serialno){ - /*This page was from the stream we want, remember it. - If it's the last such page in the link, we won't have to go back - looking for it later.*/ - end_gp=gp; - end_offset=last; - } - } - } - bisect=op_predict_link_start(_sr,nsr,_searched,end_searched,next_bias); - } - /*Bisection point found. - Get the final granule position of the previous link, assuming - op_find_initial_pcm_offset() didn't already determine the link was - empty.*/ - if(OP_LIKELY(links[nlinks-1].pcm_end==-1)){ - if(end_gp==-1){ - /*If we don't know where the end page is, we'll have to seek back and - look for it, starting from the end of the link.*/ - end_offset=next; - /*Also forget the last page we read. - It won't be available after the seek.*/ - last=-1; - } - ret=op_find_final_pcm_offset(_of,serialnos,nserialnos, - links+nlinks-1,end_offset,links[nlinks-1].serialno,end_gp, - &total_duration); - if(OP_UNLIKELY(ret<0))return ret; - } - if(last!=next){ - /*The last page we read was not the first page the next link. - Move the cursor position to the offset of that first page. - This only performs an actual seek if the first page of the next link - does not start at the end of the last page from the current Opus - stream with a valid granule position.*/ - ret=op_seek_helper(_of,next); - if(OP_UNLIKELY(ret<0))return ret; - } - ret=op_fetch_headers(_of,&links[nlinks].head,&links[nlinks].tags, - _serialnos,_nserialnos,_cserialnos,last!=next?NULL:&og); - if(OP_UNLIKELY(ret<0))return ret; - links[nlinks].offset=next; - links[nlinks].data_offset=_of->offset; - links[nlinks].serialno=_of->os.serialno; - links[nlinks].pcm_end=-1; - /*This might consume a page from the next link, however the next bisection - always starts with a seek.*/ - ret=op_find_initial_pcm_offset(_of,links+nlinks,NULL); - if(OP_UNLIKELY(ret<0))return ret; - _searched=_of->offset; - /*Mark the current link count so it can be cleaned up on error.*/ - _of->nlinks=++nlinks; - } - /*Last page is in the starting serialno list, so we've reached the last link. - Now find the last granule position for it (if we didn't the first time we - looked at the end of the stream, and if op_find_initial_pcm_offset() - didn't already determine the link was empty).*/ - if(OP_LIKELY(links[nlinks-1].pcm_end==-1)){ - ret=op_find_final_pcm_offset(_of,serialnos,nserialnos, - links+nlinks-1,_sr[0].offset,_sr[0].serialno,_sr[0].gp,&total_duration); - if(OP_UNLIKELY(ret<0))return ret; - } - /*Trim back the links array if necessary.*/ - links=(OggOpusLink *)_ogg_realloc(links,sizeof(*links)*nlinks); - if(OP_LIKELY(links!=NULL))_of->links=links; - /*We also don't need these anymore.*/ - _ogg_free(*_serialnos); - *_serialnos=NULL; - *_cserialnos=*_nserialnos=0; - return 0; -} - -static void op_update_gain(OggOpusFile *_of){ - OpusHead *head; - opus_int32 gain_q8; - int li; - /*If decode isn't ready, then we'll apply the gain when we initialize the - decoder.*/ - if(_of->ready_state<OP_INITSET)return; - gain_q8=_of->gain_offset_q8; - li=_of->seekable?_of->cur_link:0; - head=&_of->links[li].head; - /*We don't have to worry about overflow here because the header gain and - track gain must lie in the range [-32768,32767], and the user-supplied - offset has been pre-clamped to [-98302,98303].*/ - switch(_of->gain_type){ - case OP_ALBUM_GAIN:{ - int album_gain_q8; - album_gain_q8=0; - opus_tags_get_album_gain(&_of->links[li].tags,&album_gain_q8); - gain_q8+=album_gain_q8; - gain_q8+=head->output_gain; - }break; - case OP_TRACK_GAIN:{ - int track_gain_q8; - track_gain_q8=0; - opus_tags_get_track_gain(&_of->links[li].tags,&track_gain_q8); - gain_q8+=track_gain_q8; - gain_q8+=head->output_gain; - }break; - case OP_HEADER_GAIN:gain_q8+=head->output_gain;break; - case OP_ABSOLUTE_GAIN:break; - default:OP_ASSERT(0); - } - gain_q8=OP_CLAMP(-32768,gain_q8,32767); - OP_ASSERT(_of->od!=NULL); -#if defined(OPUS_SET_GAIN) - opus_multistream_decoder_ctl(_of->od,OPUS_SET_GAIN(gain_q8)); -#else -/*A fallback that works with both float and fixed-point is a bunch of work, - so just force people to use a sufficiently new version. - This is deployed well enough at this point that this shouldn't be a burden.*/ -# error "libopus 1.0.1 or later required" -#endif -} - -static int op_make_decode_ready(OggOpusFile *_of){ - const OpusHead *head; - int li; - int stream_count; - int coupled_count; - int channel_count; - if(_of->ready_state>OP_STREAMSET)return 0; - if(OP_UNLIKELY(_of->ready_state<OP_STREAMSET))return OP_EFAULT; - li=_of->seekable?_of->cur_link:0; - head=&_of->links[li].head; - stream_count=head->stream_count; - coupled_count=head->coupled_count; - channel_count=head->channel_count; - /*Check to see if the current decoder is compatible with the current link.*/ - if(_of->od!=NULL&&_of->od_stream_count==stream_count - &&_of->od_coupled_count==coupled_count&&_of->od_channel_count==channel_count - &&memcmp(_of->od_mapping,head->mapping, - sizeof(*head->mapping)*channel_count)==0){ - opus_multistream_decoder_ctl(_of->od,OPUS_RESET_STATE); - } - else{ - int err; - opus_multistream_decoder_destroy(_of->od); - _of->od=opus_multistream_decoder_create(48000,channel_count, - stream_count,coupled_count,head->mapping,&err); - if(_of->od==NULL)return OP_EFAULT; - _of->od_stream_count=stream_count; - _of->od_coupled_count=coupled_count; - _of->od_channel_count=channel_count; - memcpy(_of->od_mapping,head->mapping,sizeof(*head->mapping)*channel_count); - } - _of->ready_state=OP_INITSET; - _of->bytes_tracked=0; - _of->samples_tracked=0; -#if !defined(OP_FIXED_POINT) - _of->state_channel_count=0; - /*Use the serial number for the PRNG seed to get repeatable output for - straight play-throughs.*/ - _of->dither_seed=_of->links[li].serialno; -#endif - op_update_gain(_of); - return 0; -} - -static int op_open_seekable2_impl(OggOpusFile *_of){ - /*64 seek records should be enough for anybody. - Actually, with a bisection search in a 63-bit range down to OP_CHUNK_SIZE - granularity, much more than enough.*/ - OpusSeekRecord sr[64]; - opus_int64 data_offset; - int ret; - /*We can seek, so set out learning all about this file.*/ - (*_of->callbacks.seek)(_of->source,0,SEEK_END); - _of->offset=_of->end=(*_of->callbacks.tell)(_of->source); - if(OP_UNLIKELY(_of->end<0))return OP_EREAD; - data_offset=_of->links[0].data_offset; - if(OP_UNLIKELY(_of->end<data_offset))return OP_EBADLINK; - /*Get the offset of the last page of the physical bitstream, or, if we're - lucky, the last Opus page of the first link, as most Ogg Opus files will - contain a single logical bitstream.*/ - ret=op_get_prev_page_serial(_of,sr,_of->end, - _of->links[0].serialno,_of->serialnos,_of->nserialnos); - if(OP_UNLIKELY(ret<0))return ret; - /*If there's any trailing junk, forget about it.*/ - _of->end=sr[0].offset+sr[0].size; - if(OP_UNLIKELY(_of->end<data_offset))return OP_EBADLINK; - /*Now enumerate the bitstream structure.*/ - return op_bisect_forward_serialno(_of,data_offset,sr,sizeof(sr)/sizeof(*sr), - &_of->serialnos,&_of->nserialnos,&_of->cserialnos); -} - -static int op_open_seekable2(OggOpusFile *_of){ - ogg_sync_state oy_start; - ogg_stream_state os_start; - ogg_packet *op_start; - opus_int64 prev_page_offset; - opus_int64 start_offset; - int start_op_count; - int ret; - /*We're partially open and have a first link header state in storage in _of. - Save off that stream state so we can come back to it. - It would be simpler to just dump all this state and seek back to - links[0].data_offset when we're done. - But we do the extra work to allow us to seek back to _exactly_ the same - stream position we're at now. - This allows, e.g., the HTTP backend to continue reading from the original - connection (if it's still available), instead of opening a new one. - This means we can open and start playing a normal Opus file with a single - link and reasonable packet sizes using only two HTTP requests.*/ - start_op_count=_of->op_count; - /*This is a bit too large to put on the stack unconditionally.*/ - op_start=(ogg_packet *)_ogg_malloc(sizeof(*op_start)*start_op_count); - if(op_start==NULL)return OP_EFAULT; - *&oy_start=_of->oy; - *&os_start=_of->os; - prev_page_offset=_of->prev_page_offset; - start_offset=_of->offset; - memcpy(op_start,_of->op,sizeof(*op_start)*start_op_count); - OP_ASSERT((*_of->callbacks.tell)(_of->source)==op_position(_of)); - ogg_sync_init(&_of->oy); - ogg_stream_init(&_of->os,-1); - ret=op_open_seekable2_impl(_of); - /*Restore the old stream state.*/ - ogg_stream_clear(&_of->os); - ogg_sync_clear(&_of->oy); - *&_of->oy=*&oy_start; - *&_of->os=*&os_start; - _of->offset=start_offset; - _of->op_count=start_op_count; - memcpy(_of->op,op_start,sizeof(*_of->op)*start_op_count); - _ogg_free(op_start); - _of->prev_packet_gp=_of->links[0].pcm_start; - _of->prev_page_offset=prev_page_offset; - _of->cur_discard_count=_of->links[0].head.pre_skip; - if(OP_UNLIKELY(ret<0))return ret; - /*And restore the position indicator.*/ - ret=(*_of->callbacks.seek)(_of->source,op_position(_of),SEEK_SET); - return OP_UNLIKELY(ret<0)?OP_EREAD:0; -} - -/*Clear out the current logical bitstream decoder.*/ -static void op_decode_clear(OggOpusFile *_of){ - /*We don't actually free the decoder. - We might be able to re-use it for the next link.*/ - _of->op_count=0; - _of->od_buffer_size=0; - _of->prev_packet_gp=-1; - _of->prev_page_offset=-1; - if(!_of->seekable){ - OP_ASSERT(_of->ready_state>=OP_INITSET); - opus_tags_clear(&_of->links[0].tags); - } - _of->ready_state=OP_OPENED; -} - -static void op_clear(OggOpusFile *_of){ - OggOpusLink *links; - _ogg_free(_of->od_buffer); - if(_of->od!=NULL)opus_multistream_decoder_destroy(_of->od); - links=_of->links; - if(!_of->seekable){ - if(_of->ready_state>OP_OPENED||_of->ready_state==OP_PARTOPEN){ - opus_tags_clear(&links[0].tags); - } - } - else if(OP_LIKELY(links!=NULL)){ - int nlinks; - int link; - nlinks=_of->nlinks; - for(link=0;link<nlinks;link++)opus_tags_clear(&links[link].tags); - } - _ogg_free(links); - _ogg_free(_of->serialnos); - ogg_stream_clear(&_of->os); - ogg_sync_clear(&_of->oy); - if(_of->callbacks.close!=NULL)(*_of->callbacks.close)(_of->source); -} - -static int op_open1(OggOpusFile *_of, - void *_source,const OpusFileCallbacks *_cb, - const unsigned char *_initial_data,size_t _initial_bytes){ - ogg_page og; - ogg_page *pog; - int seekable; - int ret; - memset(_of,0,sizeof(*_of)); - _of->end=-1; - _of->source=_source; - *&_of->callbacks=*_cb; - /*At a minimum, we need to be able to read data.*/ - if(OP_UNLIKELY(_of->callbacks.read==NULL))return OP_EREAD; - /*Initialize the framing state.*/ - ogg_sync_init(&_of->oy); - /*Perhaps some data was previously read into a buffer for testing against - other stream types. - Allow initialization from this previously read data (especially as we may - be reading from a non-seekable stream). - This requires copying it into a buffer allocated by ogg_sync_buffer() and - doesn't support seeking, so this is not a good mechanism to use for - decoding entire files from RAM.*/ - if(_initial_bytes>0){ - char *buffer; - buffer=ogg_sync_buffer(&_of->oy,_initial_bytes); - memcpy(buffer,_initial_data,_initial_bytes*sizeof(*buffer)); - ogg_sync_wrote(&_of->oy,_initial_bytes); - } - /*Can we seek? - Stevens suggests the seek test is portable.*/ - seekable=_cb->seek!=NULL&&(*_cb->seek)(_source,0,SEEK_CUR)!=-1; - /*If seek is implemented, tell must also be implemented.*/ - if(seekable){ - opus_int64 pos; - if(OP_UNLIKELY(_of->callbacks.tell==NULL))return OP_EINVAL; - pos=(*_of->callbacks.tell)(_of->source); - /*If the current position is not equal to the initial bytes consumed, - absolute seeking will not work.*/ - if(OP_UNLIKELY(pos!=(opus_int64)_initial_bytes))return OP_EINVAL; - } - _of->seekable=seekable; - /*Don't seek yet. - Set up a 'single' (current) logical bitstream entry for partial open.*/ - _of->links=(OggOpusLink *)_ogg_malloc(sizeof(*_of->links)); - /*The serialno gets filled in later by op_fetch_headers().*/ - ogg_stream_init(&_of->os,-1); - pog=NULL; - for(;;){ - /*Fetch all BOS pages, store the Opus header and all seen serial numbers, - and load subsequent Opus setup headers.*/ - ret=op_fetch_headers(_of,&_of->links[0].head,&_of->links[0].tags, - &_of->serialnos,&_of->nserialnos,&_of->cserialnos,pog); - if(OP_UNLIKELY(ret<0))break; - _of->nlinks=1; - _of->links[0].offset=0; - _of->links[0].data_offset=_of->offset; - _of->links[0].pcm_end=-1; - _of->links[0].serialno=_of->os.serialno; - /*Fetch the initial PCM offset.*/ - ret=op_find_initial_pcm_offset(_of,_of->links,&og); - if(seekable||OP_LIKELY(ret<=0))break; - /*This link was empty, but we already have the BOS page for the next one in - og. - We can't seek, so start processing the next link right now.*/ - opus_tags_clear(&_of->links[0].tags); - _of->nlinks=0; - if(!seekable)_of->cur_link++; - pog=&og; - } - if(OP_LIKELY(ret>=0))_of->ready_state=OP_PARTOPEN; - return ret; -} - -static int op_open2(OggOpusFile *_of){ - int ret; - OP_ASSERT(_of->ready_state==OP_PARTOPEN); - if(_of->seekable){ - _of->ready_state=OP_OPENED; - ret=op_open_seekable2(_of); - } - else ret=0; - if(OP_LIKELY(ret>=0)){ - /*We have buffered packets from op_find_initial_pcm_offset(). - Move to OP_INITSET so we can use them.*/ - _of->ready_state=OP_STREAMSET; - ret=op_make_decode_ready(_of); - if(OP_LIKELY(ret>=0))return 0; - } - /*Don't auto-close the stream on failure.*/ - _of->callbacks.close=NULL; - op_clear(_of); - return ret; -} - -OggOpusFile *op_test_callbacks(void *_source,const OpusFileCallbacks *_cb, - const unsigned char *_initial_data,size_t _initial_bytes,int *_error){ - OggOpusFile *of; - int ret; - of=(OggOpusFile *)_ogg_malloc(sizeof(*of)); - ret=OP_EFAULT; - if(OP_LIKELY(of!=NULL)){ - ret=op_open1(of,_source,_cb,_initial_data,_initial_bytes); - if(OP_LIKELY(ret>=0)){ - if(_error!=NULL)*_error=0; - return of; - } - /*Don't auto-close the stream on failure.*/ - of->callbacks.close=NULL; - op_clear(of); - _ogg_free(of); - } - if(_error!=NULL)*_error=ret; - return NULL; -} - -OggOpusFile *op_open_callbacks(void *_source,const OpusFileCallbacks *_cb, - const unsigned char *_initial_data,size_t _initial_bytes,int *_error){ - OggOpusFile *of; - of=op_test_callbacks(_source,_cb,_initial_data,_initial_bytes,_error); - if(OP_LIKELY(of!=NULL)){ - int ret; - ret=op_open2(of); - if(OP_LIKELY(ret>=0))return of; - if(_error!=NULL)*_error=ret; - _ogg_free(of); - } - return NULL; -} - -/*Convenience routine to clean up from failure for the open functions that - create their own streams.*/ -static OggOpusFile *op_open_close_on_failure(void *_source, - const OpusFileCallbacks *_cb,int *_error){ - OggOpusFile *of; - if(OP_UNLIKELY(_source==NULL)){ - if(_error!=NULL)*_error=OP_EFAULT; - return NULL; - } - of=op_open_callbacks(_source,_cb,NULL,0,_error); - if(OP_UNLIKELY(of==NULL))(*_cb->close)(_source); - return of; -} - -OggOpusFile *op_open_file(const char *_path,int *_error){ - OpusFileCallbacks cb; - return op_open_close_on_failure(op_fopen(&cb,_path,"rb"),&cb,_error); -} - -OggOpusFile *op_open_memory(const unsigned char *_data,size_t _size, - int *_error){ - OpusFileCallbacks cb; - return op_open_close_on_failure(op_mem_stream_create(&cb,_data,_size),&cb, - _error); -} - -/*Convenience routine to clean up from failure for the open functions that - create their own streams.*/ -static OggOpusFile *op_test_close_on_failure(void *_source, - const OpusFileCallbacks *_cb,int *_error){ - OggOpusFile *of; - if(OP_UNLIKELY(_source==NULL)){ - if(_error!=NULL)*_error=OP_EFAULT; - return NULL; - } - of=op_test_callbacks(_source,_cb,NULL,0,_error); - if(OP_UNLIKELY(of==NULL))(*_cb->close)(_source); - return of; -} - -OggOpusFile *op_test_file(const char *_path,int *_error){ - OpusFileCallbacks cb; - return op_test_close_on_failure(op_fopen(&cb,_path,"rb"),&cb,_error); -} - -OggOpusFile *op_test_memory(const unsigned char *_data,size_t _size, - int *_error){ - OpusFileCallbacks cb; - return op_test_close_on_failure(op_mem_stream_create(&cb,_data,_size),&cb, - _error); -} - -int op_test_open(OggOpusFile *_of){ - int ret; - if(OP_UNLIKELY(_of->ready_state!=OP_PARTOPEN))return OP_EINVAL; - ret=op_open2(_of); - /*op_open2() will clear this structure on failure. - Reset its contents to prevent double-frees in op_free().*/ - if(OP_UNLIKELY(ret<0))memset(_of,0,sizeof(*_of)); - return ret; -} - -void op_free(OggOpusFile *_of){ - if(OP_LIKELY(_of!=NULL)){ - op_clear(_of); - _ogg_free(_of); - } -} - -int op_seekable(const OggOpusFile *_of){ - return _of->seekable; -} - -int op_link_count(const OggOpusFile *_of){ - return _of->nlinks; -} - -ogg_uint32_t op_serialno(const OggOpusFile *_of,int _li){ - if(OP_UNLIKELY(_li>=_of->nlinks))_li=_of->nlinks-1; - if(!_of->seekable)_li=0; - return _of->links[_li<0?_of->cur_link:_li].serialno; -} - -int op_channel_count(const OggOpusFile *_of,int _li){ - return op_head(_of,_li)->channel_count; -} - -opus_int64 op_raw_total(const OggOpusFile *_of,int _li){ - if(OP_UNLIKELY(_of->ready_state<OP_OPENED) - ||OP_UNLIKELY(!_of->seekable) - ||OP_UNLIKELY(_li>=_of->nlinks)){ - return OP_EINVAL; - } - if(_li<0)return _of->end-_of->links[0].offset; - return (_li+1>=_of->nlinks?_of->end:_of->links[_li+1].offset) - -_of->links[_li].offset; -} - -ogg_int64_t op_pcm_total(const OggOpusFile *_of,int _li){ - OggOpusLink *links; - ogg_int64_t diff; - int nlinks; - nlinks=_of->nlinks; - if(OP_UNLIKELY(_of->ready_state<OP_OPENED) - ||OP_UNLIKELY(!_of->seekable) - ||OP_UNLIKELY(_li>=nlinks)){ - return OP_EINVAL; - } - links=_of->links; - /*We verify that the granule position differences are larger than the - pre-skip and that the total duration does not overflow during link - enumeration, so we don't have to check here.*/ - if(_li<0){ - ogg_int64_t pcm_total; - int li; - pcm_total=0; - for(li=0;li<nlinks;li++){ - OP_ALWAYS_TRUE(!op_granpos_diff(&diff, - links[li].pcm_end,links[li].pcm_start)); - pcm_total+=diff-links[li].head.pre_skip; - } - return pcm_total; - } - OP_ALWAYS_TRUE(!op_granpos_diff(&diff, - links[_li].pcm_end,links[_li].pcm_start)); - return diff-links[_li].head.pre_skip; -} - -const OpusHead *op_head(const OggOpusFile *_of,int _li){ - if(OP_UNLIKELY(_li>=_of->nlinks))_li=_of->nlinks-1; - if(!_of->seekable)_li=0; - return &_of->links[_li<0?_of->cur_link:_li].head; -} - -const OpusTags *op_tags(const OggOpusFile *_of,int _li){ - if(OP_UNLIKELY(_li>=_of->nlinks))_li=_of->nlinks-1; - if(!_of->seekable){ - if(_of->ready_state<OP_STREAMSET&&_of->ready_state!=OP_PARTOPEN){ - return NULL; - } - _li=0; - } - else if(_li<0)_li=_of->ready_state>=OP_STREAMSET?_of->cur_link:0; - return &_of->links[_li].tags; -} - -int op_current_link(const OggOpusFile *_of){ - if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL; - return _of->cur_link; -} - -/*Compute an average bitrate given a byte and sample count. - Return: The bitrate in bits per second.*/ -static opus_int32 op_calc_bitrate(opus_int64 _bytes,ogg_int64_t _samples){ - /*These rates are absurd, but let's handle them anyway.*/ - if(OP_UNLIKELY(_bytes>(OP_INT64_MAX-(_samples>>1))/(48000*8))){ - ogg_int64_t den; - if(OP_UNLIKELY(_bytes/(OP_INT32_MAX/(48000*8))>=_samples)){ - return OP_INT32_MAX; - } - den=_samples/(48000*8); - return (opus_int32)((_bytes+(den>>1))/den); - } - if(OP_UNLIKELY(_samples<=0))return OP_INT32_MAX; - /*This can't actually overflow in normal operation: even with a pre-skip of - 545 2.5 ms frames with 8 streams running at 1282*8+1 bytes per packet - (1275 byte frames + Opus framing overhead + Ogg lacing values), that all - produce a single sample of decoded output, we still don't top 45 Mbps. - The only way to get bitrates larger than that is with excessive Opus - padding, more encoded streams than output channels, or lots and lots of - Ogg pages with no packets on them.*/ - return (opus_int32)OP_MIN((_bytes*48000*8+(_samples>>1))/_samples, - OP_INT32_MAX); -} - -opus_int32 op_bitrate(const OggOpusFile *_of,int _li){ - if(OP_UNLIKELY(_of->ready_state<OP_OPENED)||OP_UNLIKELY(!_of->seekable) - ||OP_UNLIKELY(_li>=_of->nlinks)){ - return OP_EINVAL; - } - return op_calc_bitrate(op_raw_total(_of,_li),op_pcm_total(_of,_li)); -} - -opus_int32 op_bitrate_instant(OggOpusFile *_of){ - ogg_int64_t samples_tracked; - opus_int32 ret; - if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL; - samples_tracked=_of->samples_tracked; - if(OP_UNLIKELY(samples_tracked==0))return OP_FALSE; - ret=op_calc_bitrate(_of->bytes_tracked,samples_tracked); - _of->bytes_tracked=0; - _of->samples_tracked=0; - return ret; -} - -/*Fetch and process a page. - This handles the case where we're at a bitstream boundary and dumps the - decoding machine. - If the decoding machine is unloaded, it loads it. - It also keeps prev_packet_gp up to date (seek and read both use this; seek - uses a special hack with _readp). - Return: <0) Error, OP_HOLE (lost packet), or OP_EOF. - 0) Need more data (only if _readp==0). - 1) Got at least one audio data packet.*/ -static int op_fetch_and_process_page(OggOpusFile *_of, - ogg_page *_og,opus_int64 _page_offset, - int _readp,int _spanp,int _ignore_holes){ - OggOpusLink *links; - ogg_uint32_t cur_serialno; - int seekable; - int cur_link; - int ret; - /*We shouldn't get here if we have unprocessed packets.*/ - OP_ASSERT(_of->ready_state<OP_INITSET||_of->op_pos>=_of->op_count); - if(!_readp)return 0; - seekable=_of->seekable; - links=_of->links; - cur_link=seekable?_of->cur_link:0; - cur_serialno=links[cur_link].serialno; - /*Handle one page.*/ - for(;;){ - ogg_page og; - OP_ASSERT(_of->ready_state>=OP_OPENED); - /*This loop is not strictly necessary, but there's no sense in doing the - extra checks of the larger loop for the common case in a multiplexed - bistream where the page is simply part of a different logical - bitstream.*/ - do{ - /*If we were given a page to use, use it.*/ - if(_og!=NULL){ - *&og=*_og; - _og=NULL; - } - /*Keep reading until we get a page with the correct serialno.*/ - else _page_offset=op_get_next_page(_of,&og,_of->end); - /*EOF: Leave uninitialized.*/ - if(_page_offset<0)return _page_offset<OP_FALSE?(int)_page_offset:OP_EOF; - if(OP_LIKELY(_of->ready_state>=OP_STREAMSET)){ - if(cur_serialno!=(ogg_uint32_t)ogg_page_serialno(&og)){ - /*Two possibilities: - 1) Another stream is multiplexed into this logical section, or*/ - if(OP_LIKELY(!ogg_page_bos(&og)))continue; - /* 2) Our decoding just traversed a bitstream boundary.*/ - if(!_spanp)return OP_EOF; - if(OP_LIKELY(_of->ready_state>=OP_INITSET))op_decode_clear(_of); - break; - } - } - /*Bitrate tracking: add the header's bytes here. - The body bytes are counted when we consume the packets.*/ - _of->bytes_tracked+=og.header_len; - } - while(0); - /*Do we need to load a new machine before submitting the page? - This is different in the seekable and non-seekable cases. - In the seekable case, we already have all the header information loaded - and cached. - We just initialize the machine with it and continue on our merry way. - In the non-seekable (streaming) case, we'll only be at a boundary if we - just left the previous logical bitstream, and we're now nominally at the - header of the next bitstream.*/ - if(OP_UNLIKELY(_of->ready_state<OP_STREAMSET)){ - if(seekable){ - ogg_uint32_t serialno; - int nlinks; - int li; - serialno=ogg_page_serialno(&og); - /*Match the serialno to bitstream section. - We use this rather than offset positions to avoid problems near - logical bitstream boundaries.*/ - nlinks=_of->nlinks; - for(li=0;li<nlinks&&links[li].serialno!=serialno;li++); - /*Not a desired Opus bitstream section. - Keep trying.*/ - if(li>=nlinks)continue; - cur_serialno=serialno; - _of->cur_link=cur_link=li; - ogg_stream_reset_serialno(&_of->os,serialno); - _of->ready_state=OP_STREAMSET; - /*If we're at the start of this link, initialize the granule position - and pre-skip tracking.*/ - if(_page_offset<=links[cur_link].data_offset){ - _of->prev_packet_gp=links[cur_link].pcm_start; - _of->prev_page_offset=-1; - _of->cur_discard_count=links[cur_link].head.pre_skip; - /*Ignore a hole at the start of a new link (this is common for - streams joined in the middle) or after seeking.*/ - _ignore_holes=1; - } - } - else{ - do{ - /*We're streaming. - Fetch the two header packets, build the info struct.*/ - ret=op_fetch_headers(_of,&links[0].head,&links[0].tags, - NULL,NULL,NULL,&og); - if(OP_UNLIKELY(ret<0))return ret; - /*op_find_initial_pcm_offset() will suppress any initial hole for us, - so no need to set _ignore_holes.*/ - ret=op_find_initial_pcm_offset(_of,links,&og); - if(OP_UNLIKELY(ret<0))return ret; - _of->links[0].serialno=cur_serialno=_of->os.serialno; - _of->cur_link++; - } - /*If the link was empty, keep going, because we already have the - BOS page of the next one in og.*/ - while(OP_UNLIKELY(ret>0)); - /*If we didn't get any packets out of op_find_initial_pcm_offset(), - keep going (this is possible if end-trimming trimmed them all).*/ - if(_of->op_count<=0)continue; - /*Otherwise, we're done.*/ - ret=op_make_decode_ready(_of); - if(OP_UNLIKELY(ret<0))return ret; - return 1; - } - } - /*The buffered page is the data we want, and we're ready for it. - Add it to the stream state.*/ - if(OP_UNLIKELY(_of->ready_state==OP_STREAMSET)){ - ret=op_make_decode_ready(_of); - if(OP_UNLIKELY(ret<0))return ret; - } - /*Extract all the packets from the current page.*/ - ogg_stream_pagein(&_of->os,&og); - if(OP_LIKELY(_of->ready_state>=OP_INITSET)){ - opus_int32 total_duration; - int durations[255]; - int op_count; - total_duration=op_collect_audio_packets(_of,durations); - if(OP_UNLIKELY(total_duration<0)){ - /*Drain the packets from the page anyway.*/ - total_duration=op_collect_audio_packets(_of,durations); - OP_ASSERT(total_duration>=0); - /*Report holes to the caller.*/ - if(!_ignore_holes)return OP_HOLE; - } - op_count=_of->op_count; - /*If we found at least one audio data packet, compute per-packet granule - positions for them.*/ - if(op_count>0){ - ogg_int64_t diff; - ogg_int64_t prev_packet_gp; - ogg_int64_t cur_packet_gp; - ogg_int64_t cur_page_gp; - int cur_page_eos; - int pi; - cur_page_gp=_of->op[op_count-1].granulepos; - cur_page_eos=_of->op[op_count-1].e_o_s; - prev_packet_gp=_of->prev_packet_gp; - if(OP_UNLIKELY(prev_packet_gp==-1)){ - opus_int32 cur_discard_count; - /*This is the first call after a raw seek. - Try to reconstruct prev_packet_gp from scratch.*/ - OP_ASSERT(seekable); - if(OP_UNLIKELY(cur_page_eos)){ - /*If the first page we hit after our seek was the EOS page, and - we didn't start from data_offset or before, we don't have - enough information to do end-trimming. - Proceed to the next link, rather than risk playing back some - samples that shouldn't have been played.*/ - _of->op_count=0; - continue; - } - /*By default discard 80 ms of data after a seek, unless we seek - into the pre-skip region.*/ - cur_discard_count=80*48; - cur_page_gp=_of->op[op_count-1].granulepos; - /*Try to initialize prev_packet_gp. - If the current page had packets but didn't have a granule - position, or the granule position it had was too small (both - illegal), just use the starting granule position for the link.*/ - prev_packet_gp=links[cur_link].pcm_start; - if(OP_LIKELY(cur_page_gp!=-1)){ - op_granpos_add(&prev_packet_gp,cur_page_gp,-total_duration); - } - if(OP_LIKELY(!op_granpos_diff(&diff, - prev_packet_gp,links[cur_link].pcm_start))){ - opus_int32 pre_skip; - /*If we start at the beginning of the pre-skip region, or we're - at least 80 ms from the end of the pre-skip region, we discard - to the end of the pre-skip region. - Otherwise, we still use the 80 ms default, which will discard - past the end of the pre-skip region.*/ - pre_skip=links[cur_link].head.pre_skip; - if(diff>=0&&diff<=OP_MAX(0,pre_skip-80*48)){ - cur_discard_count=pre_skip-(int)diff; - } - } - _of->cur_discard_count=cur_discard_count; - } - if(OP_UNLIKELY(cur_page_gp==-1)){ - /*This page had completed packets but didn't have a valid granule - position. - This is illegal, but we'll try to handle it by continuing to count - forwards from the previous page.*/ - if(op_granpos_add(&cur_page_gp,prev_packet_gp,total_duration)<0){ - /*The timestamp for this page overflowed.*/ - cur_page_gp=links[cur_link].pcm_end; - } - } - /*If we hit the last page, handle end-trimming.*/ - if(OP_UNLIKELY(cur_page_eos) - &&OP_LIKELY(!op_granpos_diff(&diff,cur_page_gp,prev_packet_gp)) - &&OP_LIKELY(diff<total_duration)){ - cur_packet_gp=prev_packet_gp; - for(pi=0;pi<op_count;pi++){ - diff=durations[pi]-diff; - /*If we have samples to trim...*/ - if(diff>0){ - /*If we trimmed the entire packet, stop (the spec says encoders - shouldn't do this, but we support it anyway).*/ - if(OP_UNLIKELY(diff>durations[pi]))break; - cur_packet_gp=cur_page_gp; - /*Move the EOS flag to this packet, if necessary, so we'll trim - the samples during decode.*/ - _of->op[pi].e_o_s=1; - } - else{ - /*Update the granule position as normal.*/ - OP_ALWAYS_TRUE(!op_granpos_add(&cur_packet_gp, - cur_packet_gp,durations[pi])); - } - _of->op[pi].granulepos=cur_packet_gp; - OP_ALWAYS_TRUE(!op_granpos_diff(&diff,cur_page_gp,cur_packet_gp)); - } - } - else{ - /*Propagate timestamps to earlier packets. - op_granpos_add(&prev_packet_gp,prev_packet_gp,total_duration) - should succeed and give prev_packet_gp==cur_page_gp. - But we don't bother to check that, as there isn't much we can do - if it's not true, and it actually will not be true on the first - page after a seek, if there was a continued packet. - The only thing we guarantee is that the start and end granule - positions of the packets are valid, and that they are monotonic - within a page. - They might be completely out of range for this link (we'll check - that elsewhere), or non-monotonic between pages.*/ - if(OP_UNLIKELY(op_granpos_add(&prev_packet_gp, - cur_page_gp,-total_duration)<0)){ - /*The starting timestamp for the first packet on this page - underflowed. - This is illegal, but we ignore it.*/ - prev_packet_gp=0; - } - for(pi=0;pi<op_count;pi++){ - if(OP_UNLIKELY(op_granpos_add(&cur_packet_gp, - cur_page_gp,-total_duration)<0)){ - /*The start timestamp for this packet underflowed. - This is illegal, but we ignore it.*/ - cur_packet_gp=0; - } - total_duration-=durations[pi]; - OP_ASSERT(total_duration>=0); - OP_ALWAYS_TRUE(!op_granpos_add(&cur_packet_gp, - cur_packet_gp,durations[pi])); - _of->op[pi].granulepos=cur_packet_gp; - } - OP_ASSERT(total_duration==0); - } - _of->prev_packet_gp=prev_packet_gp; - _of->prev_page_offset=_page_offset; - _of->op_count=pi; - /*If end-trimming didn't trim all the packets, we're done.*/ - if(OP_LIKELY(pi>0))return 1; - } - } - } -} - -int op_raw_seek(OggOpusFile *_of,opus_int64 _pos){ - int ret; - if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL; - /*Don't dump the decoder state if we can't seek.*/ - if(OP_UNLIKELY(!_of->seekable))return OP_ENOSEEK; - if(OP_UNLIKELY(_pos<0)||OP_UNLIKELY(_pos>_of->end))return OP_EINVAL; - /*Clear out any buffered, decoded data.*/ - op_decode_clear(_of); - _of->bytes_tracked=0; - _of->samples_tracked=0; - ret=op_seek_helper(_of,_pos); - if(OP_UNLIKELY(ret<0))return OP_EREAD; - ret=op_fetch_and_process_page(_of,NULL,-1,1,1,1); - /*If we hit EOF, op_fetch_and_process_page() leaves us uninitialized. - Instead, jump to the end.*/ - if(ret==OP_EOF){ - int cur_link; - op_decode_clear(_of); - cur_link=_of->nlinks-1; - _of->cur_link=cur_link; - _of->prev_packet_gp=_of->links[cur_link].pcm_end; - _of->cur_discard_count=0; - ret=0; - } - else if(ret>0)ret=0; - return ret; -} - -/*Convert a PCM offset relative to the start of the whole stream to a granule - position in an individual link.*/ -static ogg_int64_t op_get_granulepos(const OggOpusFile *_of, - ogg_int64_t _pcm_offset,int *_li){ - const OggOpusLink *links; - ogg_int64_t duration; - int nlinks; - int li; - OP_ASSERT(_pcm_offset>=0); - nlinks=_of->nlinks; - links=_of->links; - for(li=0;OP_LIKELY(li<nlinks);li++){ - ogg_int64_t pcm_start; - opus_int32 pre_skip; - pcm_start=links[li].pcm_start; - pre_skip=links[li].head.pre_skip; - OP_ALWAYS_TRUE(!op_granpos_diff(&duration,links[li].pcm_end,pcm_start)); - duration-=pre_skip; - if(_pcm_offset<duration){ - _pcm_offset+=pre_skip; - if(OP_UNLIKELY(pcm_start>OP_INT64_MAX-_pcm_offset)){ - /*Adding this amount to the granule position would overflow the positive - half of its 64-bit range. - Since signed overflow is undefined in C, do it in a way the compiler - isn't allowed to screw up.*/ - _pcm_offset-=OP_INT64_MAX-pcm_start+1; - pcm_start=OP_INT64_MIN; - } - pcm_start+=_pcm_offset; - *_li=li; - return pcm_start; - } - _pcm_offset-=duration; - } - return -1; -} - -/*A small helper to determine if an Ogg page contains data that continues onto - a subsequent page.*/ -static int op_page_continues(const ogg_page *_og){ - int nlacing; - OP_ASSERT(_og->header_len>=27); - nlacing=_og->header[26]; - OP_ASSERT(_og->header_len>=27+nlacing); - /*This also correctly handles the (unlikely) case of nlacing==0, because - 0!=255.*/ - return _og->header[27+nlacing-1]==255; -} - -/*A small helper to buffer the continued packet data from a page.*/ -static void op_buffer_continued_data(OggOpusFile *_of,ogg_page *_og){ - ogg_packet op; - ogg_stream_pagein(&_of->os,_og); - /*Drain any packets that did end on this page (and ignore holes). - We only care about the continued packet data.*/ - while(ogg_stream_packetout(&_of->os,&op)); -} - -/*This controls how close the target has to be to use the current stream - position to subdivide the initial range. - Two minutes seems to be a good default.*/ -#define OP_CUR_TIME_THRESH (120*48*(opus_int32)1000) - -/*Note: The OP_SMALL_FOOTPRINT #define doesn't (currently) save much code size, - but it's meant to serve as documentation for portions of the seeking - algorithm that are purely optional, to aid others learning from/porting this - code to other contexts.*/ -/*#define OP_SMALL_FOOTPRINT (1)*/ - -/*Search within link _li for the page with the highest granule position - preceding (or equal to) _target_gp. - There is a danger here: missing pages or incorrect frame number information - in the bitstream could make our task impossible. - Account for that (and report it as an error condition).*/ -static int op_pcm_seek_page(OggOpusFile *_of, - ogg_int64_t _target_gp,int _li){ - const OggOpusLink *link; - ogg_page og; - ogg_int64_t pcm_pre_skip; - ogg_int64_t pcm_start; - ogg_int64_t pcm_end; - ogg_int64_t best_gp; - ogg_int64_t diff; - ogg_uint32_t serialno; - opus_int32 pre_skip; - opus_int64 begin; - opus_int64 end; - opus_int64 boundary; - opus_int64 best; - opus_int64 best_start; - opus_int64 page_offset; - opus_int64 d0; - opus_int64 d1; - opus_int64 d2; - int force_bisect; - int buffering; - int ret; - _of->bytes_tracked=0; - _of->samples_tracked=0; - link=_of->links+_li; - best_gp=pcm_start=link->pcm_start; - pcm_end=link->pcm_end; - serialno=link->serialno; - best=best_start=begin=link->data_offset; - page_offset=-1; - buffering=0; - /*We discard the first 80 ms of data after a seek, so seek back that much - farther. - If we can't, simply seek to the beginning of the link.*/ - if(OP_UNLIKELY(op_granpos_add(&_target_gp,_target_gp,-80*48)<0) - ||OP_UNLIKELY(op_granpos_cmp(_target_gp,pcm_start)<0)){ - _target_gp=pcm_start; - } - /*Special case seeking to the start of the link.*/ - pre_skip=link->head.pre_skip; - OP_ALWAYS_TRUE(!op_granpos_add(&pcm_pre_skip,pcm_start,pre_skip)); - if(op_granpos_cmp(_target_gp,pcm_pre_skip)<0)end=boundary=begin; - else{ - end=boundary=link->end_offset; -#if !defined(OP_SMALL_FOOTPRINT) - /*If we were decoding from this link, we can narrow the range a bit.*/ - if(_li==_of->cur_link&&_of->ready_state>=OP_INITSET){ - opus_int64 offset; - int op_count; - op_count=_of->op_count; - /*The only way the offset can be invalid _and_ we can fail the granule - position checks below is if someone changed the contents of the last - page since we read it. - We'd be within our rights to just return OP_EBADLINK in that case, but - we'll simply ignore the current position instead.*/ - offset=_of->offset; - if(op_count>0&&OP_LIKELY(offset<=end)){ - ogg_int64_t gp; - /*Make sure the timestamp is valid. - The granule position might be -1 if we collected the packets from a - page without a granule position after reporting a hole.*/ - gp=_of->op[op_count-1].granulepos; - if(OP_LIKELY(gp!=-1)&&OP_LIKELY(op_granpos_cmp(pcm_start,gp)<0) - &&OP_LIKELY(op_granpos_cmp(pcm_end,gp)>0)){ - OP_ALWAYS_TRUE(!op_granpos_diff(&diff,gp,_target_gp)); - /*We only actually use the current time if either - a) We can cut off at least half the range, or - b) We're seeking sufficiently close to the current position that - it's likely to be informative. - Otherwise it appears using the whole link range to estimate the - first seek location gives better results, on average.*/ - if(diff<0){ - OP_ASSERT(offset>=begin); - if(offset-begin>=end-begin>>1||diff>-OP_CUR_TIME_THRESH){ - best=begin=offset; - best_gp=pcm_start=gp; - /*If we have buffered data from a continued packet, remember the - offset of the previous page's start, so that if we do wind up - having to seek back here later, we can prime the stream with - the continued packet data. - With no continued packet, we remember the end of the page.*/ - best_start=_of->os.body_returned<_of->os.body_fill? - _of->prev_page_offset:best; - /*If there's completed packets and data in the stream state, - prev_page_offset should always be set.*/ - OP_ASSERT(best_start>=0); - /*Buffer any continued packet data starting from here.*/ - buffering=1; - } - } - else{ - ogg_int64_t prev_page_gp; - /*We might get lucky and already have the packet with the target - buffered. - Worth checking. - For very small files (with all of the data in a single page, - generally 1 second or less), we can loop them continuously - without seeking at all.*/ - OP_ALWAYS_TRUE(!op_granpos_add(&prev_page_gp,_of->op[0].granulepos, - -op_get_packet_duration(_of->op[0].packet,_of->op[0].bytes))); - if(op_granpos_cmp(prev_page_gp,_target_gp)<=0){ - /*Don't call op_decode_clear(), because it will dump our - packets.*/ - _of->op_pos=0; - _of->od_buffer_size=0; - _of->prev_packet_gp=prev_page_gp; - /*_of->prev_page_offset already points to the right place.*/ - _of->ready_state=OP_STREAMSET; - return op_make_decode_ready(_of); - } - /*No such luck. - Check if we can cut off at least half the range, though.*/ - if(offset-begin<=end-begin>>1||diff<OP_CUR_TIME_THRESH){ - /*We really want the page start here, but this will do.*/ - end=boundary=offset; - pcm_end=gp; - } - } - } - } - } -#endif - } - /*This code was originally based on the "new search algorithm by HB (Nicholas - Vinen)" from libvorbisfile. - It has been modified substantially since.*/ - op_decode_clear(_of); - if(!buffering)ogg_stream_reset_serialno(&_of->os,serialno); - _of->cur_link=_li; - _of->ready_state=OP_STREAMSET; - /*Initialize the interval size history.*/ - d2=d1=d0=end-begin; - force_bisect=0; - while(begin<end){ - opus_int64 bisect; - opus_int64 next_boundary; - opus_int32 chunk_size; - if(end-begin<OP_CHUNK_SIZE)bisect=begin; - else{ - /*Update the interval size history.*/ - d0=d1>>1; - d1=d2>>1; - d2=end-begin>>1; - if(force_bisect)bisect=begin+(end-begin>>1); - else{ - ogg_int64_t diff2; - OP_ALWAYS_TRUE(!op_granpos_diff(&diff,_target_gp,pcm_start)); - OP_ALWAYS_TRUE(!op_granpos_diff(&diff2,pcm_end,pcm_start)); - /*Take a (pretty decent) guess.*/ - bisect=begin+op_rescale64(diff,diff2,end-begin)-OP_CHUNK_SIZE; - } - if(bisect-OP_CHUNK_SIZE<begin)bisect=begin; - force_bisect=0; - } - if(bisect!=_of->offset){ - /*Discard any buffered continued packet data.*/ - if(buffering)ogg_stream_reset(&_of->os); - buffering=0; - page_offset=-1; - ret=op_seek_helper(_of,bisect); - if(OP_UNLIKELY(ret<0))return ret; - } - chunk_size=OP_CHUNK_SIZE; - next_boundary=boundary; - /*Now scan forward and figure out where we landed. - In the ideal case, we will see a page with a granule position at or - before our target, followed by a page with a granule position after our - target (or the end of the search interval). - Then we can just drop out and will have all of the data we need with no - additional seeking. - If we landed too far before, or after, we'll break out and do another - bisection.*/ - while(begin<end){ - page_offset=op_get_next_page(_of,&og,boundary); - if(page_offset<0){ - if(page_offset<OP_FALSE)return (int)page_offset; - /*There are no more pages in our interval from our stream with a valid - timestamp that start at position bisect or later.*/ - /*If we scanned the whole interval, we're done.*/ - if(bisect<=begin+1)end=begin; - else{ - /*Otherwise, back up one chunk. - First, discard any data from a continued packet.*/ - if(buffering)ogg_stream_reset(&_of->os); - buffering=0; - bisect=OP_MAX(bisect-chunk_size,begin); - ret=op_seek_helper(_of,bisect); - if(OP_UNLIKELY(ret<0))return ret; - /*Bump up the chunk size.*/ - chunk_size=OP_MIN(2*chunk_size,OP_CHUNK_SIZE_MAX); - /*If we did find a page from another stream or without a timestamp, - don't read past it.*/ - boundary=next_boundary; - } - } - else{ - ogg_int64_t gp; - int has_packets; - /*Save the offset of the first page we found after the seek, regardless - of the stream it came from or whether or not it has a timestamp.*/ - next_boundary=OP_MIN(page_offset,next_boundary); - if(serialno!=(ogg_uint32_t)ogg_page_serialno(&og))continue; - has_packets=ogg_page_packets(&og)>0; - /*Force the gp to -1 (as it should be per spec) if no packets end on - this page. - Otherwise we might get confused when we try to pull out a packet - with that timestamp and can't find it.*/ - gp=has_packets?ogg_page_granulepos(&og):-1; - if(gp==-1){ - if(buffering){ - if(OP_LIKELY(!has_packets))ogg_stream_pagein(&_of->os,&og); - else{ - /*If packets did end on this page, but we still didn't have a - valid granule position (in violation of the spec!), stop - buffering continued packet data. - Otherwise we might continue past the packet we actually - wanted.*/ - ogg_stream_reset(&_of->os); - buffering=0; - } - } - continue; - } - if(op_granpos_cmp(gp,_target_gp)<0){ - /*We found a page that ends before our target. - Advance to the raw offset of the next page.*/ - begin=_of->offset; - if(OP_UNLIKELY(op_granpos_cmp(pcm_start,gp)>0) - ||OP_UNLIKELY(op_granpos_cmp(pcm_end,gp)<0)){ - /*Don't let pcm_start get out of range! - That could happen with an invalid timestamp.*/ - break; - } - /*Save the byte offset of the end of the page with this granule - position.*/ - best=best_start=begin; - /*Buffer any data from a continued packet, if necessary. - This avoids the need to seek back here if the next timestamp we - encounter while scanning forward lies after our target.*/ - if(buffering)ogg_stream_reset(&_of->os); - if(op_page_continues(&og)){ - op_buffer_continued_data(_of,&og); - /*If we have a continued packet, remember the offset of this - page's start, so that if we do wind up having to seek back here - later, we can prime the stream with the continued packet data. - With no continued packet, we remember the end of the page.*/ - best_start=page_offset; - } - /*Then force buffering on, so that if a packet starts (but does not - end) on the next page, we still avoid the extra seek back.*/ - buffering=1; - best_gp=pcm_start=gp; - OP_ALWAYS_TRUE(!op_granpos_diff(&diff,_target_gp,pcm_start)); - /*If we're more than a second away from our target, break out and - do another bisection.*/ - if(diff>48000)break; - /*Otherwise, keep scanning forward (do NOT use begin+1).*/ - bisect=begin; - } - else{ - /*We found a page that ends after our target.*/ - /*If we scanned the whole interval before we found it, we're done.*/ - if(bisect<=begin+1)end=begin; - else{ - end=bisect; - /*In later iterations, don't read past the first page we found.*/ - boundary=next_boundary; - /*If we're not making much progress shrinking the interval size, - start forcing straight bisection to limit the worst case.*/ - force_bisect=end-begin>d0*2; - /*Don't let pcm_end get out of range! - That could happen with an invalid timestamp.*/ - if(OP_LIKELY(op_granpos_cmp(pcm_end,gp)>0) - &&OP_LIKELY(op_granpos_cmp(pcm_start,gp)<=0)){ - pcm_end=gp; - } - break; - } - } - } - } - } - /*Found our page.*/ - OP_ASSERT(op_granpos_cmp(best_gp,pcm_start)>=0); - /*Seek, if necessary. - If we were buffering data from a continued packet, we should be able to - continue to scan forward to get the rest of the data (even if - page_offset==-1). - Otherwise, we need to seek back to best_start.*/ - if(!buffering){ - if(best_start!=page_offset){ - page_offset=-1; - ret=op_seek_helper(_of,best_start); - if(OP_UNLIKELY(ret<0))return ret; - } - if(best_start<best){ - /*Retrieve the page at best_start, if we do not already have it.*/ - if(page_offset<0){ - page_offset=op_get_next_page(_of,&og,link->end_offset); - if(OP_UNLIKELY(page_offset<OP_FALSE))return (int)page_offset; - if(OP_UNLIKELY(page_offset!=best_start))return OP_EBADLINK; - } - op_buffer_continued_data(_of,&og); - page_offset=-1; - } - } - /*Update prev_packet_gp to allow per-packet granule position assignment.*/ - _of->prev_packet_gp=best_gp; - _of->prev_page_offset=best_start; - ret=op_fetch_and_process_page(_of,page_offset<0?NULL:&og,page_offset,1,0,1); - if(OP_UNLIKELY(ret<=0))return OP_EBADLINK; - /*Verify result.*/ - if(OP_UNLIKELY(op_granpos_cmp(_of->prev_packet_gp,_target_gp)>0)){ - return OP_EBADLINK; - } - /*Our caller will set cur_discard_count to handle pre-roll.*/ - return 0; -} - -int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset){ - const OggOpusLink *link; - ogg_int64_t pcm_start; - ogg_int64_t target_gp; - ogg_int64_t prev_packet_gp; - ogg_int64_t skip; - ogg_int64_t diff; - int op_count; - int op_pos; - int ret; - int li; - if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL; - if(OP_UNLIKELY(!_of->seekable))return OP_ENOSEEK; - if(OP_UNLIKELY(_pcm_offset<0))return OP_EINVAL; - target_gp=op_get_granulepos(_of,_pcm_offset,&li); - if(OP_UNLIKELY(target_gp==-1))return OP_EINVAL; - link=_of->links+li; - pcm_start=link->pcm_start; - OP_ALWAYS_TRUE(!op_granpos_diff(&_pcm_offset,target_gp,pcm_start)); -#if !defined(OP_SMALL_FOOTPRINT) - /*For small (90 ms or less) forward seeks within the same link, just decode - forward. - This also optimizes the case of seeking to the current position.*/ - if(li==_of->cur_link&&_of->ready_state>=OP_INITSET){ - ogg_int64_t gp; - gp=_of->prev_packet_gp; - if(OP_LIKELY(gp!=-1)){ - int nbuffered; - nbuffered=OP_MAX(_of->od_buffer_size-_of->od_buffer_pos,0); - OP_ALWAYS_TRUE(!op_granpos_add(&gp,gp,-nbuffered)); - /*We do _not_ add cur_discard_count to gp. - Otherwise the total amount to discard could grow without bound, and it - would be better just to do a full seek.*/ - if(OP_LIKELY(!op_granpos_diff(&diff,gp,pcm_start))){ - ogg_int64_t discard_count; - discard_count=_pcm_offset-diff; - /*We use a threshold of 90 ms instead of 80, since 80 ms is the - _minimum_ we would have discarded after a full seek. - Assuming 20 ms frames (the default), we'd discard 90 ms on average.*/ - if(discard_count>=0&&OP_UNLIKELY(discard_count<90*48)){ - _of->cur_discard_count=(opus_int32)discard_count; - return 0; - } - } - } - } -#endif - ret=op_pcm_seek_page(_of,target_gp,li); - if(OP_UNLIKELY(ret<0))return ret; - /*Now skip samples until we actually get to our target.*/ - /*Figure out where we should skip to.*/ - if(_pcm_offset<=link->head.pre_skip)skip=0; - else skip=OP_MAX(_pcm_offset-80*48,0); - OP_ASSERT(_pcm_offset-skip>=0); - OP_ASSERT(_pcm_offset-skip<OP_INT32_MAX-120*48); - /*Skip packets until we find one with samples past our skip target.*/ - for(;;){ - op_count=_of->op_count; - prev_packet_gp=_of->prev_packet_gp; - for(op_pos=_of->op_pos;op_pos<op_count;op_pos++){ - ogg_int64_t cur_packet_gp; - cur_packet_gp=_of->op[op_pos].granulepos; - if(OP_LIKELY(!op_granpos_diff(&diff,cur_packet_gp,pcm_start)) - &&diff>skip){ - break; - } - prev_packet_gp=cur_packet_gp; - } - _of->prev_packet_gp=prev_packet_gp; - _of->op_pos=op_pos; - if(op_pos<op_count)break; - /*We skipped all the packets on this page. - Fetch another.*/ - ret=op_fetch_and_process_page(_of,NULL,-1,1,0,1); - if(OP_UNLIKELY(ret<=0))return OP_EBADLINK; - } - OP_ALWAYS_TRUE(!op_granpos_diff(&diff,prev_packet_gp,pcm_start)); - /*We skipped too far. - Either the timestamps were illegal or there was a hole in the data.*/ - if(diff>skip)return OP_EBADLINK; - OP_ASSERT(_pcm_offset-diff<OP_INT32_MAX); - /*TODO: If there are further holes/illegal timestamps, we still won't decode - to the correct sample. - However, at least op_pcm_tell() will report the correct value immediately - after returning.*/ - _of->cur_discard_count=(opus_int32)(_pcm_offset-diff); - return 0; -} - -opus_int64 op_raw_tell(const OggOpusFile *_of){ - if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL; - return _of->offset; -} - -/*Convert a granule position from a given link to a PCM offset relative to the - start of the whole stream. - For unseekable sources, this gets reset to 0 at the beginning of each link.*/ -static ogg_int64_t op_get_pcm_offset(const OggOpusFile *_of, - ogg_int64_t _gp,int _li){ - const OggOpusLink *links; - ogg_int64_t pcm_offset; - ogg_int64_t delta; - int li; - links=_of->links; - pcm_offset=0; - OP_ASSERT(_li<_of->nlinks); - for(li=0;li<_li;li++){ - OP_ALWAYS_TRUE(!op_granpos_diff(&delta, - links[li].pcm_end,links[li].pcm_start)); - delta-=links[li].head.pre_skip; - pcm_offset+=delta; - } - OP_ASSERT(_li>=0); - if(_of->seekable&&OP_UNLIKELY(op_granpos_cmp(_gp,links[_li].pcm_end)>0)){ - _gp=links[_li].pcm_end; - } - if(OP_LIKELY(op_granpos_cmp(_gp,links[_li].pcm_start)>0)){ - if(OP_UNLIKELY(op_granpos_diff(&delta,_gp,links[_li].pcm_start)<0)){ - /*This means an unseekable stream claimed to have a page from more than - 2 billion days after we joined.*/ - OP_ASSERT(!_of->seekable); - return OP_INT64_MAX; - } - if(delta<links[_li].head.pre_skip)delta=0; - else delta-=links[_li].head.pre_skip; - /*In the seekable case, _gp was limited by pcm_end. - In the unseekable case, pcm_offset should be 0.*/ - OP_ASSERT(pcm_offset<=OP_INT64_MAX-delta); - pcm_offset+=delta; - } - return pcm_offset; -} - -ogg_int64_t op_pcm_tell(const OggOpusFile *_of){ - ogg_int64_t gp; - int nbuffered; - int li; - if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL; - gp=_of->prev_packet_gp; - if(gp==-1)return 0; - nbuffered=OP_MAX(_of->od_buffer_size-_of->od_buffer_pos,0); - OP_ALWAYS_TRUE(!op_granpos_add(&gp,gp,-nbuffered)); - li=_of->seekable?_of->cur_link:0; - if(op_granpos_add(&gp,gp,_of->cur_discard_count)<0){ - gp=_of->links[li].pcm_end; - } - return op_get_pcm_offset(_of,gp,li); -} - -void op_set_decode_callback(OggOpusFile *_of, - op_decode_cb_func _decode_cb,void *_ctx){ - _of->decode_cb=_decode_cb; - _of->decode_cb_ctx=_ctx; -} - -int op_set_gain_offset(OggOpusFile *_of, - int _gain_type,opus_int32 _gain_offset_q8){ - if(_gain_type!=OP_HEADER_GAIN&&_gain_type!=OP_ALBUM_GAIN - &&_gain_type!=OP_TRACK_GAIN&&_gain_type!=OP_ABSOLUTE_GAIN){ - return OP_EINVAL; - } - _of->gain_type=_gain_type; - /*The sum of header gain and track gain lies in the range [-65536,65534]. - These bounds allow the offset to set the final value to anywhere in the - range [-32768,32767], which is what we'll clamp it to before applying.*/ - _of->gain_offset_q8=OP_CLAMP(-98302,_gain_offset_q8,98303); - op_update_gain(_of); - return 0; -} - -void op_set_dither_enabled(OggOpusFile *_of,int _enabled){ -#if !defined(OP_FIXED_POINT) - _of->dither_disabled=!_enabled; - if(!_enabled)_of->dither_mute=65; -#endif -} - -/*Allocate the decoder scratch buffer. - This is done lazily, since if the user provides large enough buffers, we'll - never need it.*/ -static int op_init_buffer(OggOpusFile *_of){ - int nchannels_max; - if(_of->seekable){ - const OggOpusLink *links; - int nlinks; - int li; - links=_of->links; - nlinks=_of->nlinks; - nchannels_max=1; - for(li=0;li<nlinks;li++){ - nchannels_max=OP_MAX(nchannels_max,links[li].head.channel_count); - } - } - else nchannels_max=OP_NCHANNELS_MAX; - _of->od_buffer=(op_sample *)_ogg_malloc( - sizeof(*_of->od_buffer)*nchannels_max*120*48); - if(_of->od_buffer==NULL)return OP_EFAULT; - return 0; -} - -/*Decode a single packet into the target buffer.*/ -static int op_decode(OggOpusFile *_of,op_sample *_pcm, - const ogg_packet *_op,int _nsamples,int _nchannels){ - int ret; - /*First we try using the application-provided decode callback.*/ - if(_of->decode_cb!=NULL){ -#if defined(OP_FIXED_POINT) - ret=(*_of->decode_cb)(_of->decode_cb_ctx,_of->od,_pcm,_op, - _nsamples,_nchannels,OP_DEC_FORMAT_SHORT,_of->cur_link); -#else - ret=(*_of->decode_cb)(_of->decode_cb_ctx,_of->od,_pcm,_op, - _nsamples,_nchannels,OP_DEC_FORMAT_FLOAT,_of->cur_link); -#endif - } - else ret=OP_DEC_USE_DEFAULT; - /*If the application didn't want to handle decoding, do it ourselves.*/ - if(ret==OP_DEC_USE_DEFAULT){ -#if defined(OP_FIXED_POINT) - ret=opus_multistream_decode(_of->od, - _op->packet,_op->bytes,_pcm,_nsamples,0); -#else - ret=opus_multistream_decode_float(_of->od, - _op->packet,_op->bytes,_pcm,_nsamples,0); -#endif - OP_ASSERT(ret<0||ret==_nsamples); - } - /*If the application returned a positive value other than 0 or - OP_DEC_USE_DEFAULT, fail.*/ - else if(OP_UNLIKELY(ret>0))return OP_EBADPACKET; - if(OP_UNLIKELY(ret<0))return OP_EBADPACKET; - return ret; -} - -/*Read more samples from the stream, using the same API as op_read() or - op_read_float().*/ -static int op_read_native(OggOpusFile *_of, - op_sample *_pcm,int _buf_size,int *_li){ - if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL; - for(;;){ - int ret; - if(OP_LIKELY(_of->ready_state>=OP_INITSET)){ - int nchannels; - int od_buffer_pos; - int nsamples; - int op_pos; - nchannels=_of->links[_of->seekable?_of->cur_link:0].head.channel_count; - od_buffer_pos=_of->od_buffer_pos; - nsamples=_of->od_buffer_size-od_buffer_pos; - /*If we have buffered samples, return them.*/ - if(nsamples>0){ - if(nsamples*nchannels>_buf_size)nsamples=_buf_size/nchannels; - memcpy(_pcm,_of->od_buffer+nchannels*od_buffer_pos, - sizeof(*_pcm)*nchannels*nsamples); - od_buffer_pos+=nsamples; - _of->od_buffer_pos=od_buffer_pos; - if(_li!=NULL)*_li=_of->cur_link; - return nsamples; - } - /*If we have buffered packets, decode one.*/ - op_pos=_of->op_pos; - if(OP_LIKELY(op_pos<_of->op_count)){ - const ogg_packet *pop; - ogg_int64_t diff; - opus_int32 cur_discard_count; - int duration; - int trimmed_duration; - pop=_of->op+op_pos++; - _of->op_pos=op_pos; - cur_discard_count=_of->cur_discard_count; - duration=op_get_packet_duration(pop->packet,pop->bytes); - /*We don't buffer packets with an invalid TOC sequence.*/ - OP_ASSERT(duration>0); - trimmed_duration=duration; - /*Perform end-trimming.*/ - if(OP_UNLIKELY(pop->e_o_s)){ - if(OP_UNLIKELY(op_granpos_cmp(pop->granulepos, - _of->prev_packet_gp)<=0)){ - trimmed_duration=0; - } - else if(OP_LIKELY(!op_granpos_diff(&diff, - pop->granulepos,_of->prev_packet_gp))){ - trimmed_duration=(int)OP_MIN(diff,trimmed_duration); - } - } - _of->prev_packet_gp=pop->granulepos; - if(OP_UNLIKELY(duration*nchannels>_buf_size)){ - op_sample *buf; - /*If the user's buffer is too small, decode into a scratch buffer.*/ - buf=_of->od_buffer; - if(OP_UNLIKELY(buf==NULL)){ - ret=op_init_buffer(_of); - if(OP_UNLIKELY(ret<0))return ret; - buf=_of->od_buffer; - } - ret=op_decode(_of,buf,pop,duration,nchannels); - if(OP_UNLIKELY(ret<0))return ret; - /*Perform pre-skip/pre-roll.*/ - od_buffer_pos=(int)OP_MIN(trimmed_duration,cur_discard_count); - cur_discard_count-=od_buffer_pos; - _of->cur_discard_count=cur_discard_count; - _of->od_buffer_pos=od_buffer_pos; - _of->od_buffer_size=trimmed_duration; - /*Update bitrate tracking based on the actual samples we used from - what was decoded.*/ - _of->bytes_tracked+=pop->bytes; - _of->samples_tracked+=trimmed_duration-od_buffer_pos; - } - else{ - /*Otherwise decode directly into the user's buffer.*/ - ret=op_decode(_of,_pcm,pop,duration,nchannels); - if(OP_UNLIKELY(ret<0))return ret; - if(OP_LIKELY(trimmed_duration>0)){ - /*Perform pre-skip/pre-roll.*/ - od_buffer_pos=(int)OP_MIN(trimmed_duration,cur_discard_count); - cur_discard_count-=od_buffer_pos; - _of->cur_discard_count=cur_discard_count; - trimmed_duration-=od_buffer_pos; - if(OP_LIKELY(trimmed_duration>0) - &&OP_UNLIKELY(od_buffer_pos>0)){ - memmove(_pcm,_pcm+od_buffer_pos*nchannels, - sizeof(*_pcm)*trimmed_duration*nchannels); - } - /*Update bitrate tracking based on the actual samples we used from - what was decoded.*/ - _of->bytes_tracked+=pop->bytes; - _of->samples_tracked+=trimmed_duration; - if(OP_LIKELY(trimmed_duration>0)){ - if(_li!=NULL)*_li=_of->cur_link; - return trimmed_duration; - } - } - } - /*Don't grab another page yet. - This one might have more packets, or might have buffered data now.*/ - continue; - } - } - /*Suck in another page.*/ - ret=op_fetch_and_process_page(_of,NULL,-1,1,1,0); - if(OP_UNLIKELY(ret==OP_EOF)){ - if(_li!=NULL)*_li=_of->cur_link; - return 0; - } - if(OP_UNLIKELY(ret<0))return ret; - } -} - -/*A generic filter to apply to the decoded audio data. - _src is non-const because we will destructively modify the contents of the - source buffer that we consume in some cases.*/ -typedef int (*op_read_filter_func)(OggOpusFile *_of,void *_dst,int _dst_sz, - op_sample *_src,int _nsamples,int _nchannels); - -/*Decode some samples and then apply a custom filter to them. - This is used to convert to different output formats.*/ -static int op_filter_read_native(OggOpusFile *_of,void *_dst,int _dst_sz, - op_read_filter_func _filter,int *_li){ - int ret; - /*Ensure we have some decoded samples in our buffer.*/ - ret=op_read_native(_of,NULL,0,_li); - /*Now apply the filter to them.*/ - if(OP_LIKELY(ret>=0)&&OP_LIKELY(_of->ready_state>=OP_INITSET)){ - int od_buffer_pos; - od_buffer_pos=_of->od_buffer_pos; - ret=_of->od_buffer_size-od_buffer_pos; - if(OP_LIKELY(ret>0)){ - int nchannels; - nchannels=_of->links[_of->seekable?_of->cur_link:0].head.channel_count; - ret=(*_filter)(_of,_dst,_dst_sz, - _of->od_buffer+nchannels*od_buffer_pos,ret,nchannels); - OP_ASSERT(ret>=0); - OP_ASSERT(ret<=_of->od_buffer_size-od_buffer_pos); - od_buffer_pos+=ret; - _of->od_buffer_pos=od_buffer_pos; - } - } - return ret; -} - -#if !defined(OP_FIXED_POINT)||!defined(OP_DISABLE_FLOAT_API) - -/*Matrices for downmixing from the supported channel counts to stereo. - The matrices with 5 or more channels are normalized to a total volume of 2.0, - since most mixes sound too quiet if normalized to 1.0 (as there is generally - little volume in the side/rear channels).*/ -static const float OP_STEREO_DOWNMIX[OP_NCHANNELS_MAX-2][OP_NCHANNELS_MAX][2]={ - /*3.0*/ - { - {0.5858F,0.0F},{0.4142F,0.4142F},{0.0F,0.5858F} - }, - /*quadrophonic*/ - { - {0.4226F,0.0F},{0.0F,0.4226F},{0.366F,0.2114F},{0.2114F,0.336F} - }, - /*5.0*/ - { - {0.651F,0.0F},{0.46F,0.46F},{0.0F,0.651F},{0.5636F,0.3254F}, - {0.3254F,0.5636F} - }, - /*5.1*/ - { - {0.529F,0.0F},{0.3741F,0.3741F},{0.0F,0.529F},{0.4582F,0.2645F}, - {0.2645F,0.4582F},{0.3741F,0.3741F} - }, - /*6.1*/ - { - {0.4553F,0.0F},{0.322F,0.322F},{0.0F,0.4553F},{0.3943F,0.2277F}, - {0.2277F,0.3943F},{0.2788F,0.2788F},{0.322F,0.322F} - }, - /*7.1*/ - { - {0.3886F,0.0F},{0.2748F,0.2748F},{0.0F,0.3886F},{0.3366F,0.1943F}, - {0.1943F,0.3366F},{0.3366F,0.1943F},{0.1943F,0.3366F},{0.2748F,0.2748F} - } -}; - -#endif - -#if defined(OP_FIXED_POINT) - -/*Matrices for downmixing from the supported channel counts to stereo. - The matrices with 5 or more channels are normalized to a total volume of 2.0, - since most mixes sound too quiet if normalized to 1.0 (as there is generally - little volume in the side/rear channels). - Hence we keep the coefficients in Q14, so the downmix values won't overflow a - 32-bit number.*/ -static const opus_int16 OP_STEREO_DOWNMIX_Q14 - [OP_NCHANNELS_MAX-2][OP_NCHANNELS_MAX][2]={ - /*3.0*/ - { - {9598,0},{6786,6786},{0,9598} - }, - /*quadrophonic*/ - { - {6924,0},{0,6924},{5996,3464},{3464,5996} - }, - /*5.0*/ - { - {10666,0},{7537,7537},{0,10666},{9234,5331},{5331,9234} - }, - /*5.1*/ - { - {8668,0},{6129,6129},{0,8668},{7507,4335},{4335,7507},{6129,6129} - }, - /*6.1*/ - { - {7459,0},{5275,5275},{0,7459},{6460,3731},{3731,6460},{4568,4568}, - {5275,5275} - }, - /*7.1*/ - { - {6368,0},{4502,4502},{0,6368},{5515,3183},{3183,5515},{5515,3183}, - {3183,5515},{4502,4502} - } -}; - -int op_read(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size,int *_li){ - return op_read_native(_of,_pcm,_buf_size,_li); -} - -static int op_stereo_filter(OggOpusFile *_of,void *_dst,int _dst_sz, - op_sample *_src,int _nsamples,int _nchannels){ - (void)_of; - _nsamples=OP_MIN(_nsamples,_dst_sz>>1); - if(_nchannels==2)memcpy(_dst,_src,_nsamples*2*sizeof(*_src)); - else{ - opus_int16 *dst; - int i; - dst=(opus_int16 *)_dst; - if(_nchannels==1){ - for(i=0;i<_nsamples;i++)dst[2*i+0]=dst[2*i+1]=_src[i]; - } - else{ - for(i=0;i<_nsamples;i++){ - opus_int32 l; - opus_int32 r; - int ci; - l=r=0; - for(ci=0;ci<_nchannels;ci++){ - opus_int32 s; - s=_src[_nchannels*i+ci]; - l+=OP_STEREO_DOWNMIX_Q14[_nchannels-3][ci][0]*s; - r+=OP_STEREO_DOWNMIX_Q14[_nchannels-3][ci][1]*s; - } - /*TODO: For 5 or more channels, we should do soft clipping here.*/ - dst[2*i+0]=(opus_int16)OP_CLAMP(-32768,l+8192>>14,32767); - dst[2*i+1]=(opus_int16)OP_CLAMP(-32768,r+8192>>14,32767); - } - } - } - return _nsamples; -} - -int op_read_stereo(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size){ - return op_filter_read_native(_of,_pcm,_buf_size,op_stereo_filter,NULL); -} - -# if !defined(OP_DISABLE_FLOAT_API) - -static int op_short2float_filter(OggOpusFile *_of,void *_dst,int _dst_sz, - op_sample *_src,int _nsamples,int _nchannels){ - float *dst; - int i; - (void)_of; - dst=(float *)_dst; - if(OP_UNLIKELY(_nsamples*_nchannels>_dst_sz))_nsamples=_dst_sz/_nchannels; - _dst_sz=_nsamples*_nchannels; - for(i=0;i<_dst_sz;i++)dst[i]=(1.0F/32768)*_src[i]; - return _nsamples; -} - -int op_read_float(OggOpusFile *_of,float *_pcm,int _buf_size,int *_li){ - return op_filter_read_native(_of,_pcm,_buf_size,op_short2float_filter,_li); -} - -static int op_short2float_stereo_filter(OggOpusFile *_of, - void *_dst,int _dst_sz,op_sample *_src,int _nsamples,int _nchannels){ - float *dst; - int i; - dst=(float *)_dst; - _nsamples=OP_MIN(_nsamples,_dst_sz>>1); - if(_nchannels==1){ - _nsamples=op_short2float_filter(_of,dst,_nsamples,_src,_nsamples,1); - for(i=_nsamples;i-->0;)dst[2*i+0]=dst[2*i+1]=dst[i]; - } - else if(_nchannels<5){ - /*For 3 or 4 channels, we can downmix in fixed point without risk of - clipping.*/ - if(_nchannels>2){ - _nsamples=op_stereo_filter(_of,_src,_nsamples*2, - _src,_nsamples,_nchannels); - } - return op_short2float_filter(_of,dst,_dst_sz,_src,_nsamples,2); - } - else{ - /*For 5 or more channels, we convert to floats and then downmix (so that we - don't risk clipping).*/ - for(i=0;i<_nsamples;i++){ - float l; - float r; - int ci; - l=r=0; - for(ci=0;ci<_nchannels;ci++){ - float s; - s=(1.0F/32768)*_src[_nchannels*i+ci]; - l+=OP_STEREO_DOWNMIX[_nchannels-3][ci][0]*s; - r+=OP_STEREO_DOWNMIX[_nchannels-3][ci][1]*s; - } - dst[2*i+0]=l; - dst[2*i+1]=r; - } - } - return _nsamples; -} - -int op_read_float_stereo(OggOpusFile *_of,float *_pcm,int _buf_size){ - return op_filter_read_native(_of,_pcm,_buf_size, - op_short2float_stereo_filter,NULL); -} - -# endif - -#else - -# if defined(OP_HAVE_LRINTF) -# include <math.h> -# define op_float2int(_x) (lrintf(_x)) -# else -# define op_float2int(_x) ((int)((_x)+((_x)<0?-0.5F:0.5F))) -# endif - -/*The dithering code here is adapted from opusdec, part of opus-tools. - It was originally written by Greg Maxwell.*/ - -static opus_uint32 op_rand(opus_uint32 _seed){ - return _seed*96314165+907633515&0xFFFFFFFFU; -} - -/*This implements 16-bit quantization with full triangular dither and IIR noise - shaping. - The noise shaping filters were designed by Sebastian Gesemann, and are based - on the LAME ATH curves with flattening to limit their peak gain to 20 dB. - Everyone else's noise shaping filters are mildly crazy. - The 48 kHz version of this filter is just a warped version of the 44.1 kHz - filter and probably could be improved by shifting the HF shelf up in - frequency a little bit, since 48 kHz has a bit more room and being more - conservative against bat-ears is probably more important than more noise - suppression. - This process can increase the peak level of the signal (in theory by the peak - error of 1.5 +20 dB, though that is unobservably rare). - To avoid clipping, the signal is attenuated by a couple thousandths of a dB. - Initially, the approach taken here was to only attenuate by the 99.9th - percentile, making clipping rare but not impossible (like SoX), but the - limited gain of the filter means that the worst case was only two - thousandths of a dB more, so this just uses the worst case. - The attenuation is probably also helpful to prevent clipping in the DAC - reconstruction filters or downstream resampling, in any case.*/ - -# define OP_GAIN (32753.0F) - -# define OP_PRNG_GAIN (1.0F/0xFFFFFFFF) - -/*48 kHz noise shaping filter, sd=2.34.*/ - -static const float OP_FCOEF_B[4]={ - 2.2374F,-0.7339F,-0.1251F,-0.6033F -}; - -static const float OP_FCOEF_A[4]={ - 0.9030F,0.0116F,-0.5853F,-0.2571F -}; - -static int op_float2short_filter(OggOpusFile *_of,void *_dst,int _dst_sz, - float *_src,int _nsamples,int _nchannels){ - opus_int16 *dst; - int ci; - int i; - dst=(opus_int16 *)_dst; - if(OP_UNLIKELY(_nsamples*_nchannels>_dst_sz))_nsamples=_dst_sz/_nchannels; -# if defined(OP_SOFT_CLIP) - if(_of->state_channel_count!=_nchannels){ - for(ci=0;ci<_nchannels;ci++)_of->clip_state[ci]=0; - } - opus_pcm_soft_clip(_src,_nsamples,_nchannels,_of->clip_state); -# endif - if(_of->dither_disabled){ - for(i=0;i<_nchannels*_nsamples;i++){ - dst[i]=op_float2int(OP_CLAMP(-32768,32768.0F*_src[i],32767)); - } - } - else{ - opus_uint32 seed; - int mute; - seed=_of->dither_seed; - mute=_of->dither_mute; - if(_of->state_channel_count!=_nchannels)mute=65; - /*In order to avoid replacing digital silence with quiet dither noise, we - mute if the output has been silent for a while.*/ - if(mute>64)memset(_of->dither_a,0,sizeof(*_of->dither_a)*4*_nchannels); - for(i=0;i<_nsamples;i++){ - int silent; - silent=1; - for(ci=0;ci<_nchannels;ci++){ - float r; - float s; - float err; - int si; - int j; - s=_src[_nchannels*i+ci]; - silent&=s==0; - s*=OP_GAIN; - err=0; - for(j=0;j<4;j++){ - err+=OP_FCOEF_B[j]*_of->dither_b[ci*4+j] - -OP_FCOEF_A[j]*_of->dither_a[ci*4+j]; - } - for(j=3;j-->0;)_of->dither_a[ci*4+j+1]=_of->dither_a[ci*4+j]; - for(j=3;j-->0;)_of->dither_b[ci*4+j+1]=_of->dither_b[ci*4+j]; - _of->dither_a[ci*4]=err; - s-=err; - if(mute>16)r=0; - else{ - seed=op_rand(seed); - r=seed*OP_PRNG_GAIN; - seed=op_rand(seed); - r-=seed*OP_PRNG_GAIN; - } - /*Clamp in float out of paranoia that the input will be > 96 dBFS and - wrap if the integer is clamped.*/ - si=op_float2int(OP_CLAMP(-32768,s+r,32767)); - dst[_nchannels*i+ci]=(opus_int16)si; - /*Including clipping in the noise shaping is generally disastrous: the - futile effort to restore the clipped energy results in more clipping. - However, small amounts---at the level which could normally be created - by dither and rounding---are harmless and can even reduce clipping - somewhat due to the clipping sometimes reducing the dither + rounding - error.*/ - _of->dither_b[ci*4]=mute>16?0:OP_CLAMP(-1.5F,si-s,1.5F); - } - mute++; - if(!silent)mute=0; - } - _of->dither_mute=OP_MIN(mute,65); - _of->dither_seed=seed; - } - _of->state_channel_count=_nchannels; - return _nsamples; -} - -int op_read(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size,int *_li){ - return op_filter_read_native(_of,_pcm,_buf_size,op_float2short_filter,_li); -} - -int op_read_float(OggOpusFile *_of,float *_pcm,int _buf_size,int *_li){ - _of->state_channel_count=0; - return op_read_native(_of,_pcm,_buf_size,_li); -} - -static int op_stereo_filter(OggOpusFile *_of,void *_dst,int _dst_sz, - op_sample *_src,int _nsamples,int _nchannels){ - (void)_of; - _nsamples=OP_MIN(_nsamples,_dst_sz>>1); - if(_nchannels==2)memcpy(_dst,_src,_nsamples*2*sizeof(*_src)); - else{ - float *dst; - int i; - dst=(float *)_dst; - if(_nchannels==1){ - for(i=0;i<_nsamples;i++)dst[2*i+0]=dst[2*i+1]=_src[i]; - } - else{ - for(i=0;i<_nsamples;i++){ - float l; - float r; - int ci; - l=r=0; - for(ci=0;ci<_nchannels;ci++){ - l+=OP_STEREO_DOWNMIX[_nchannels-3][ci][0]*_src[_nchannels*i+ci]; - r+=OP_STEREO_DOWNMIX[_nchannels-3][ci][1]*_src[_nchannels*i+ci]; - } - dst[2*i+0]=l; - dst[2*i+1]=r; - } - } - } - return _nsamples; -} - -static int op_float2short_stereo_filter(OggOpusFile *_of, - void *_dst,int _dst_sz,op_sample *_src,int _nsamples,int _nchannels){ - opus_int16 *dst; - dst=(opus_int16 *)_dst; - if(_nchannels==1){ - int i; - _nsamples=op_float2short_filter(_of,dst,_dst_sz>>1,_src,_nsamples,1); - for(i=_nsamples;i-->0;)dst[2*i+0]=dst[2*i+1]=dst[i]; - } - else{ - if(_nchannels>2){ - _nsamples=OP_MIN(_nsamples,_dst_sz>>1); - _nsamples=op_stereo_filter(_of,_src,_nsamples*2, - _src,_nsamples,_nchannels); - } - _nsamples=op_float2short_filter(_of,dst,_dst_sz,_src,_nsamples,2); - } - return _nsamples; -} - -int op_read_stereo(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size){ - return op_filter_read_native(_of,_pcm,_buf_size, - op_float2short_stereo_filter,NULL); -} - -int op_read_float_stereo(OggOpusFile *_of,float *_pcm,int _buf_size){ - _of->state_channel_count=0; - return op_filter_read_native(_of,_pcm,_buf_size,op_stereo_filter,NULL); -} - -#endif diff --git a/drivers/opus/opusfile.h b/drivers/opus/opusfile.h deleted file mode 100644 index da31a29769..0000000000 --- a/drivers/opus/opusfile.h +++ /dev/null @@ -1,2148 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: stdio-based convenience library for opening/seeking/decoding - last mod: $Id: vorbisfile.h 17182 2010-04-29 03:48:32Z xiphmont $ - - ********************************************************************/ -#if !defined(_opusfile_h) -# define _opusfile_h (1) - -/**\mainpage - \section Introduction - - This is the documentation for the <tt>libopusfile</tt> C API. - - The <tt>libopusfile</tt> package provides a convenient high-level API for - decoding and basic manipulation of all Ogg Opus audio streams. - <tt>libopusfile</tt> is implemented as a layer on top of Xiph.Org's - reference - <tt><a href="https://www.xiph.org/ogg/doc/libogg/reference.html">libogg</a></tt> - and - <tt><a href="https://mf4.xiph.org/jenkins/view/opus/job/opus/ws/doc/html/index.html">libopus</a></tt> - libraries. - - <tt>libopusfile</tt> provides several sets of built-in routines for - file/stream access, and may also use custom stream I/O routines provided by - the embedded environment. - There are built-in I/O routines provided for ANSI-compliant - <code>stdio</code> (<code>FILE *</code>), memory buffers, and URLs - (including <file:> URLs, plus optionally <http:> and <https:> URLs). - - \section Organization - - The main API is divided into several sections: - - \ref stream_open_close - - \ref stream_info - - \ref stream_decoding - - \ref stream_seeking - - Several additional sections are not tied to the main API. - - \ref stream_callbacks - - \ref header_info - - \ref error_codes - - \section Overview - - The <tt>libopusfile</tt> API always decodes files to 48 kHz. - The original sample rate is not preserved by the lossy compression, though - it is stored in the header to allow you to resample to it after decoding - (the <tt>libopusfile</tt> API does not currently provide a resampler, - but the - <a href="http://www.speex.org/docs/manual/speex-manual/node7.html#SECTION00760000000000000000">the - Speex resampler</a> is a good choice if you need one). - In general, if you are playing back the audio, you should leave it at - 48 kHz, provided your audio hardware supports it. - When decoding to a file, it may be worth resampling back to the original - sample rate, so as not to surprise users who might not expect the sample - rate to change after encoding to Opus and decoding. - - Opus files can contain anywhere from 1 to 255 channels of audio. - The channel mappings for up to 8 channels are the same as the - <a href="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">Vorbis - mappings</a>. - A special stereo API can convert everything to 2 channels, making it simple - to support multichannel files in an application which only has stereo - output. - Although the <tt>libopusfile</tt> ABI provides support for the theoretical - maximum number of channels, the current implementation does not support - files with more than 8 channels, as they do not have well-defined channel - mappings. - - Like all Ogg files, Opus files may be "chained". - That is, multiple Opus files may be combined into a single, longer file just - by concatenating the original files. - This is commonly done in internet radio streaming, as it allows the title - and artist to be updated each time the song changes, since each link in the - chain includes its own set of metadata. - - <tt>libopusfile</tt> fully supports chained files. - It will decode the first Opus stream found in each link of a chained file - (ignoring any other streams that might be concurrently multiplexed with it, - such as a video stream). - - The channel count can also change between links. - If your application is not prepared to deal with this, it can use the stereo - API to ensure the audio from all links will always get decoded into a - common format. - Since <tt>libopusfile</tt> always decodes to 48 kHz, you do not have to - worry about the sample rate changing between links (as was possible with - Vorbis). - This makes application support for chained files with <tt>libopusfile</tt> - very easy.*/ - -# if defined(__cplusplus) -extern "C" { -# endif - -# include <stdarg.h> -# include <stdio.h> -# include <ogg/ogg.h> -# include "opus/opus_multistream.h" - -/**@cond PRIVATE*/ - -/*Enable special features for gcc and gcc-compatible compilers.*/ -# if !defined(OP_GNUC_PREREQ) -# if defined(__GNUC__)&&defined(__GNUC_MINOR__) -# define OP_GNUC_PREREQ(_maj,_min) \ - ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) -# else -# define OP_GNUC_PREREQ(_maj,_min) 0 -# endif -# endif - -# if OP_GNUC_PREREQ(4,0) -# pragma GCC visibility push(default) -# endif - -typedef struct OpusHead OpusHead; -typedef struct OpusTags OpusTags; -typedef struct OpusPictureTag OpusPictureTag; -typedef struct OpusServerInfo OpusServerInfo; -typedef struct OpusFileCallbacks OpusFileCallbacks; -typedef struct OggOpusFile OggOpusFile; - -/*Warning attributes for libopusfile functions.*/ -# if OP_GNUC_PREREQ(3,4) -# define OP_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) -# else -# define OP_WARN_UNUSED_RESULT -# endif -# if OP_GNUC_PREREQ(3,4) -# define OP_ARG_NONNULL(_x) __attribute__((__nonnull__(_x))) -# else -# define OP_ARG_NONNULL(_x) -# endif - -/**@endcond*/ - -/**\defgroup error_codes Error Codes*/ -/*@{*/ -/**\name List of possible error codes - Many of the functions in this library return a negative error code when a - function fails. - This list provides a brief explanation of the common errors. - See each individual function for more details on what a specific error code - means in that context.*/ -/*@{*/ - -/**A request did not succeed.*/ -#define OP_FALSE (-1) -/*Currently not used externally.*/ -#define OP_EOF (-2) -/**There was a hole in the page sequence numbers (e.g., a page was corrupt or - missing).*/ -#define OP_HOLE (-3) -/**An underlying read, seek, or tell operation failed when it should have - succeeded.*/ -#define OP_EREAD (-128) -/**A <code>NULL</code> pointer was passed where one was unexpected, or an - internal memory allocation failed, or an internal library error was - encountered.*/ -#define OP_EFAULT (-129) -/**The stream used a feature that is not implemented, such as an unsupported - channel family.*/ -#define OP_EIMPL (-130) -/**One or more parameters to a function were invalid.*/ -#define OP_EINVAL (-131) -/**A purported Ogg Opus stream did not begin with an Ogg page, a purported - header packet did not start with one of the required strings, "OpusHead" or - "OpusTags", or a link in a chained file was encountered that did not - contain any logical Opus streams.*/ -#define OP_ENOTFORMAT (-132) -/**A required header packet was not properly formatted, contained illegal - values, or was missing altogether.*/ -#define OP_EBADHEADER (-133) -/**The ID header contained an unrecognized version number.*/ -#define OP_EVERSION (-134) -/*Currently not used at all.*/ -#define OP_ENOTAUDIO (-135) -/**An audio packet failed to decode properly. - This is usually caused by a multistream Ogg packet where the durations of - the individual Opus packets contained in it are not all the same.*/ -#define OP_EBADPACKET (-136) -/**We failed to find data we had seen before, or the bitstream structure was - sufficiently malformed that seeking to the target destination was - impossible.*/ -#define OP_EBADLINK (-137) -/**An operation that requires seeking was requested on an unseekable stream.*/ -#define OP_ENOSEEK (-138) -/**The first or last granule position of a link failed basic validity checks.*/ -#define OP_EBADTIMESTAMP (-139) - -/*@}*/ -/*@}*/ - -/**\defgroup header_info Header Information*/ -/*@{*/ - -/**The maximum number of channels in an Ogg Opus stream.*/ -#define OPUS_CHANNEL_COUNT_MAX (255) - -/**Ogg Opus bitstream information. - This contains the basic playback parameters for a stream, and corresponds to - the initial ID header packet of an Ogg Opus stream.*/ -struct OpusHead{ - /**The Ogg Opus format version, in the range 0...255. - The top 4 bits represent a "major" version, and the bottom four bits - represent backwards-compatible "minor" revisions. - The current specification describes version 1. - This library will recognize versions up through 15 as backwards compatible - with the current specification. - An earlier draft of the specification described a version 0, but the only - difference between version 1 and version 0 is that version 0 did - not specify the semantics for handling the version field.*/ - int version; - /**The number of channels, in the range 1...255.*/ - int channel_count; - /**The number of samples that should be discarded from the beginning of the - stream.*/ - unsigned pre_skip; - /**The sampling rate of the original input. - All Opus audio is coded at 48 kHz, and should also be decoded at 48 kHz - for playback (unless the target hardware does not support this sampling - rate). - However, this field may be used to resample the audio back to the original - sampling rate, for example, when saving the output to a file.*/ - opus_uint32 input_sample_rate; - /**The gain to apply to the decoded output, in dB, as a Q8 value in the range - -32768...32767. - The <tt>libopusfile</tt> API will automatically apply this gain to the - decoded output before returning it, scaling it by - <code>pow(10,output_gain/(20.0*256))</code>.*/ - int output_gain; - /**The channel mapping family, in the range 0...255. - Channel mapping family 0 covers mono or stereo in a single stream. - Channel mapping family 1 covers 1 to 8 channels in one or more streams, - using the Vorbis speaker assignments. - Channel mapping family 255 covers 1 to 255 channels in one or more - streams, but without any defined speaker assignment.*/ - int mapping_family; - /**The number of Opus streams in each Ogg packet, in the range 1...255.*/ - int stream_count; - /**The number of coupled Opus streams in each Ogg packet, in the range - 0...127. - This must satisfy <code>0 <= coupled_count <= stream_count</code> and - <code>coupled_count + stream_count <= 255</code>. - The coupled streams appear first, before all uncoupled streams, in an Ogg - Opus packet.*/ - int coupled_count; - /**The mapping from coded stream channels to output channels. - Let <code>index=mapping[k]</code> be the value for channel <code>k</code>. - If <code>index<2*coupled_count</code>, then it refers to the left channel - from stream <code>(index/2)</code> if even, and the right channel from - stream <code>(index/2)</code> if odd. - Otherwise, it refers to the output of the uncoupled stream - <code>(index-coupled_count)</code>.*/ - unsigned char mapping[OPUS_CHANNEL_COUNT_MAX]; -}; - -/**The metadata from an Ogg Opus stream. - - This structure holds the in-stream metadata corresponding to the 'comment' - header packet of an Ogg Opus stream. - The comment header is meant to be used much like someone jotting a quick - note on the label of a CD. - It should be a short, to the point text note that can be more than a couple - words, but not more than a short paragraph. - - The metadata is stored as a series of (tag, value) pairs, in length-encoded - string vectors, using the same format as Vorbis (without the final "framing - bit"), Theora, and Speex, except for the packet header. - The first occurrence of the '=' character delimits the tag and value. - A particular tag may occur more than once, and order is significant. - The character set encoding for the strings is always UTF-8, but the tag - names are limited to ASCII, and treated as case-insensitive. - See <a href="http://www.xiph.org/vorbis/doc/v-comment.html">the Vorbis - comment header specification</a> for details. - - In filling in this structure, <tt>libopusfile</tt> will null-terminate the - #user_comments strings for safety. - However, the bitstream format itself treats them as 8-bit clean vectors, - possibly containing NUL characters, so the #comment_lengths array should be - treated as their authoritative length. - - This structure is binary and source-compatible with a - <code>vorbis_comment</code>, and pointers to it may be freely cast to - <code>vorbis_comment</code> pointers, and vice versa. - It is provided as a separate type to avoid introducing a compile-time - dependency on the libvorbis headers.*/ -struct OpusTags{ - /**The array of comment string vectors.*/ - char **user_comments; - /**An array of the corresponding length of each vector, in bytes.*/ - int *comment_lengths; - /**The total number of comment streams.*/ - int comments; - /**The null-terminated vendor string. - This identifies the software used to encode the stream.*/ - char *vendor; -}; - -/**\name Picture tag image formats*/ -/*@{*/ - -/**The MIME type was not recognized, or the image data did not match the - declared MIME type.*/ -#define OP_PIC_FORMAT_UNKNOWN (-1) -/**The MIME type indicates the image data is really a URL.*/ -#define OP_PIC_FORMAT_URL (0) -/**The image is a JPEG.*/ -#define OP_PIC_FORMAT_JPEG (1) -/**The image is a PNG.*/ -#define OP_PIC_FORMAT_PNG (2) -/**The image is a GIF.*/ -#define OP_PIC_FORMAT_GIF (3) - -/*@}*/ - -/**The contents of a METADATA_BLOCK_PICTURE tag.*/ -struct OpusPictureTag{ - /**The picture type according to the ID3v2 APIC frame: - <ol start="0"> - <li>Other</li> - <li>32x32 pixels 'file icon' (PNG only)</li> - <li>Other file icon</li> - <li>Cover (front)</li> - <li>Cover (back)</li> - <li>Leaflet page</li> - <li>Media (e.g. label side of CD)</li> - <li>Lead artist/lead performer/soloist</li> - <li>Artist/performer</li> - <li>Conductor</li> - <li>Band/Orchestra</li> - <li>Composer</li> - <li>Lyricist/text writer</li> - <li>Recording Location</li> - <li>During recording</li> - <li>During performance</li> - <li>Movie/video screen capture</li> - <li>A bright colored fish</li> - <li>Illustration</li> - <li>Band/artist logotype</li> - <li>Publisher/Studio logotype</li> - </ol> - Others are reserved and should not be used. - There may only be one each of picture type 1 and 2 in a file.*/ - opus_int32 type; - /**The MIME type of the picture, in printable ASCII characters 0x20-0x7E. - The MIME type may also be <code>"-->"</code> to signify that the data part - is a URL pointing to the picture instead of the picture data itself. - In this case, a terminating NUL is appended to the URL string in #data, - but #data_length is set to the length of the string excluding that - terminating NUL.*/ - char *mime_type; - /**The description of the picture, in UTF-8.*/ - char *description; - /**The width of the picture in pixels.*/ - opus_uint32 width; - /**The height of the picture in pixels.*/ - opus_uint32 height; - /**The color depth of the picture in bits-per-pixel (<em>not</em> - bits-per-channel).*/ - opus_uint32 depth; - /**For indexed-color pictures (e.g., GIF), the number of colors used, or 0 - for non-indexed pictures.*/ - opus_uint32 colors; - /**The length of the picture data in bytes.*/ - opus_uint32 data_length; - /**The binary picture data.*/ - unsigned char *data; - /**The format of the picture data, if known. - One of - <ul> - <li>#OP_PIC_FORMAT_UNKNOWN,</li> - <li>#OP_PIC_FORMAT_URL,</li> - <li>#OP_PIC_FORMAT_JPEG,</li> - <li>#OP_PIC_FORMAT_PNG, or</li> - <li>#OP_PIC_FORMAT_GIF.</li> - </ul>*/ - int format; -}; - -/**\name Functions for manipulating header data - - These functions manipulate the #OpusHead and #OpusTags structures, - which describe the audio parameters and tag-value metadata, respectively. - These can be used to query the headers returned by <tt>libopusfile</tt>, or - to parse Opus headers from sources other than an Ogg Opus stream, provided - they use the same format.*/ -/*@{*/ - -/**Parses the contents of the ID header packet of an Ogg Opus stream. - \param[out] _head Returns the contents of the parsed packet. - The contents of this structure are untouched on error. - This may be <code>NULL</code> to merely test the header - for validity. - \param[in] _data The contents of the ID header packet. - \param _len The number of bytes of data in the ID header packet. - \return 0 on success or a negative value on error. - \retval #OP_ENOTFORMAT If the data does not start with the "OpusHead" - string. - \retval #OP_EVERSION If the version field signaled a version this library - does not know how to parse. - \retval #OP_EIMPL If the channel mapping family was 255, which general - purpose players should not attempt to play. - \retval #OP_EBADHEADER If the contents of the packet otherwise violate the - Ogg Opus specification: - <ul> - <li>Insufficient data,</li> - <li>Too much data for the known minor versions,</li> - <li>An unrecognized channel mapping family,</li> - <li>Zero channels or too many channels,</li> - <li>Zero coded streams,</li> - <li>Too many coupled streams, or</li> - <li>An invalid channel mapping index.</li> - </ul>*/ -OP_WARN_UNUSED_RESULT int opus_head_parse(OpusHead *_head, - const unsigned char *_data,size_t _len) OP_ARG_NONNULL(2); - -/**Converts a granule position to a sample offset for a given Ogg Opus stream. - The sample offset is simply <code>_gp-_head->pre_skip</code>. - Granule position values smaller than OpusHead#pre_skip correspond to audio - that should never be played, and thus have no associated sample offset. - This function returns -1 for such values. - This function also correctly handles extremely large granule positions, - which may have wrapped around to a negative number when stored in a signed - ogg_int64_t value. - \param _head The #OpusHead information from the ID header of the stream. - \param _gp The granule position to convert. - \return The sample offset associated with the given granule position - (counting at a 48 kHz sampling rate), or the special value -1 on - error (i.e., the granule position was smaller than the pre-skip - amount).*/ -ogg_int64_t opus_granule_sample(const OpusHead *_head,ogg_int64_t _gp) - OP_ARG_NONNULL(1); - -/**Parses the contents of the 'comment' header packet of an Ogg Opus stream. - \param[out] _tags An uninitialized #OpusTags structure. - This returns the contents of the parsed packet. - The contents of this structure are untouched on error. - This may be <code>NULL</code> to merely test the header - for validity. - \param[in] _data The contents of the 'comment' header packet. - \param _len The number of bytes of data in the 'info' header packet. - \retval 0 Success. - \retval #OP_ENOTFORMAT If the data does not start with the "OpusTags" - string. - \retval #OP_EBADHEADER If the contents of the packet otherwise violate the - Ogg Opus specification. - \retval #OP_EFAULT If there wasn't enough memory to store the tags.*/ -OP_WARN_UNUSED_RESULT int opus_tags_parse(OpusTags *_tags, - const unsigned char *_data,size_t _len) OP_ARG_NONNULL(2); - -/**Performs a deep copy of an #OpusTags structure. - \param _dst The #OpusTags structure to copy into. - If this function fails, the contents of this structure remain - untouched. - \param _src The #OpusTags structure to copy from. - \retval 0 Success. - \retval #OP_EFAULT If there wasn't enough memory to copy the tags.*/ -int opus_tags_copy(OpusTags *_dst,const OpusTags *_src) OP_ARG_NONNULL(1); - -/**Initializes an #OpusTags structure. - This should be called on a freshly allocated #OpusTags structure before - attempting to use it. - \param _tags The #OpusTags structure to initialize.*/ -void opus_tags_init(OpusTags *_tags) OP_ARG_NONNULL(1); - -/**Add a (tag, value) pair to an initialized #OpusTags structure. - \note Neither opus_tags_add() nor opus_tags_add_comment() support values - containing embedded NULs, although the bitstream format does support them. - To add such tags, you will need to manipulate the #OpusTags structure - directly. - \param _tags The #OpusTags structure to add the (tag, value) pair to. - \param _tag A NUL-terminated, case-insensitive, ASCII string containing - the tag to add (without an '=' character). - \param _value A NUL-terminated UTF-8 containing the corresponding value. - \return 0 on success, or a negative value on failure. - \retval #OP_EFAULT An internal memory allocation failed.*/ -int opus_tags_add(OpusTags *_tags,const char *_tag,const char *_value) - OP_ARG_NONNULL(1) OP_ARG_NONNULL(2) OP_ARG_NONNULL(3); - -/**Add a comment to an initialized #OpusTags structure. - \note Neither opus_tags_add_comment() nor opus_tags_add() support comments - containing embedded NULs, although the bitstream format does support them. - To add such tags, you will need to manipulate the #OpusTags structure - directly. - \param _tags The #OpusTags structure to add the comment to. - \param _comment A NUL-terminated UTF-8 string containing the comment in - "TAG=value" form. - \return 0 on success, or a negative value on failure. - \retval #OP_EFAULT An internal memory allocation failed.*/ -int opus_tags_add_comment(OpusTags *_tags,const char *_comment) - OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); - -/**Replace the binary suffix data at the end of the packet (if any). - \param _tags An initialized #OpusTags structure. - \param _data A buffer of binary data to append after the encoded user - comments. - The least significant bit of the first byte of this data must - be set (to ensure the data is preserved by other editors). - \param _len The number of bytes of binary data to append. - This may be zero to remove any existing binary suffix data. - \return 0 on success, or a negative value on error. - \retval #OP_EINVAL \a _len was negative, or \a _len was positive but - \a _data was <code>NULL</code> or the least significant - bit of the first byte was not set. - \retval #OP_EFAULT An internal memory allocation failed.*/ -int opus_tags_set_binary_suffix(OpusTags *_tags, - const unsigned char *_data,int _len) OP_ARG_NONNULL(1); - -/**Look up a comment value by its tag. - \param _tags An initialized #OpusTags structure. - \param _tag The tag to look up. - \param _count The instance of the tag. - The same tag can appear multiple times, each with a distinct - value, so an index is required to retrieve them all. - The order in which these values appear is significant and - should be preserved. - Use opus_tags_query_count() to get the legal range for the - \a _count parameter. - \return A pointer to the queried tag's value. - This points directly to data in the #OpusTags structure. - It should not be modified or freed by the application, and - modifications to the structure may invalidate the pointer. - \retval NULL If no matching tag is found.*/ -const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count) - OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); - -/**Look up the number of instances of a tag. - Call this first when querying for a specific tag and then iterate over the - number of instances with separate calls to opus_tags_query() to retrieve - all the values for that tag in order. - \param _tags An initialized #OpusTags structure. - \param _tag The tag to look up. - \return The number of instances of this particular tag.*/ -int opus_tags_query_count(const OpusTags *_tags,const char *_tag) - OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); - -/**Retrieve the binary suffix data at the end of the packet (if any). - \param _tags An initialized #OpusTags structure. - \param[out] _len Returns the number of bytes of binary suffix data returned. - \return A pointer to the binary suffix data, or <code>NULL</code> if none - was present.*/ -const unsigned char *opus_tags_get_binary_suffix(const OpusTags *_tags, - int *_len) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); - -/**Get the album gain from an R128_ALBUM_GAIN tag, if one was specified. - This searches for the first R128_ALBUM_GAIN tag with a valid signed, - 16-bit decimal integer value and returns the value. - This routine is exposed merely for convenience for applications which wish - to do something special with the album gain (i.e., display it). - If you simply wish to apply the album gain instead of the header gain, you - can use op_set_gain_offset() with an #OP_ALBUM_GAIN type and no offset. - \param _tags An initialized #OpusTags structure. - \param[out] _gain_q8 The album gain, in 1/256ths of a dB. - This will lie in the range [-32768,32767], and should - be applied in <em>addition</em> to the header gain. - On error, no value is returned, and the previous - contents remain unchanged. - \return 0 on success, or a negative value on error. - \retval #OP_FALSE There was no album gain available in the given tags.*/ -int opus_tags_get_album_gain(const OpusTags *_tags,int *_gain_q8) - OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); - -/**Get the track gain from an R128_TRACK_GAIN tag, if one was specified. - This searches for the first R128_TRACK_GAIN tag with a valid signed, - 16-bit decimal integer value and returns the value. - This routine is exposed merely for convenience for applications which wish - to do something special with the track gain (i.e., display it). - If you simply wish to apply the track gain instead of the header gain, you - can use op_set_gain_offset() with an #OP_TRACK_GAIN type and no offset. - \param _tags An initialized #OpusTags structure. - \param[out] _gain_q8 The track gain, in 1/256ths of a dB. - This will lie in the range [-32768,32767], and should - be applied in <em>addition</em> to the header gain. - On error, no value is returned, and the previous - contents remain unchanged. - \return 0 on success, or a negative value on error. - \retval #OP_FALSE There was no track gain available in the given tags.*/ -int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8) - OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); - -/**Clears the #OpusTags structure. - This should be called on an #OpusTags structure after it is no longer - needed. - It will free all memory used by the structure members. - \param _tags The #OpusTags structure to clear.*/ -void opus_tags_clear(OpusTags *_tags) OP_ARG_NONNULL(1); - -/**Check if \a _comment is an instance of a \a _tag_name tag. - \see opus_tagncompare - \param _tag_name A NUL-terminated, case-insensitive, ASCII string containing - the name of the tag to check for (without the terminating - '=' character). - \param _comment The comment string to check. - \return An integer less than, equal to, or greater than zero if \a _comment - is found respectively, to be less than, to match, or be greater - than a "tag=value" string whose tag matches \a _tag_name.*/ -int opus_tagcompare(const char *_tag_name,const char *_comment); - -/**Check if \a _comment is an instance of a \a _tag_name tag. - This version is slightly more efficient than opus_tagcompare() if the length - of the tag name is already known (e.g., because it is a constant). - \see opus_tagcompare - \param _tag_name A case-insensitive ASCII string containing the name of the - tag to check for (without the terminating '=' character). - \param _tag_len The number of characters in the tag name. - This must be non-negative. - \param _comment The comment string to check. - \return An integer less than, equal to, or greater than zero if \a _comment - is found respectively, to be less than, to match, or be greater - than a "tag=value" string whose tag matches the first \a _tag_len - characters of \a _tag_name.*/ -int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment); - -/**Parse a single METADATA_BLOCK_PICTURE tag. - This decodes the BASE64-encoded content of the tag and returns a structure - with the MIME type, description, image parameters (if known), and the - compressed image data. - If the MIME type indicates the presence of an image format we recognize - (JPEG, PNG, or GIF) and the actual image data contains the magic signature - associated with that format, then the OpusPictureTag::format field will be - set to the corresponding format. - This is provided as a convenience to avoid requiring applications to parse - the MIME type and/or do their own format detection for the commonly used - formats. - In this case, we also attempt to extract the image parameters directly from - the image data (overriding any that were present in the tag, which the - specification says applications are not meant to rely on). - The application must still provide its own support for actually decoding the - image data and, if applicable, retrieving that data from URLs. - \param[out] _pic Returns the parsed picture data. - No sanitation is done on the type, MIME type, or - description fields, so these might return invalid values. - The contents of this structure are left unmodified on - failure. - \param _tag The METADATA_BLOCK_PICTURE tag contents. - The leading "METADATA_BLOCK_PICTURE=" portion is optional, - to allow the function to be used on either directly on the - values in OpusTags::user_comments or on the return value - of opus_tags_query(). - \return 0 on success or a negative value on error. - \retval #OP_ENOTFORMAT The METADATA_BLOCK_PICTURE contents were not valid. - \retval #OP_EFAULT There was not enough memory to store the picture tag - contents.*/ -OP_WARN_UNUSED_RESULT int opus_picture_tag_parse(OpusPictureTag *_pic, - const char *_tag) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); - -/**Initializes an #OpusPictureTag structure. - This should be called on a freshly allocated #OpusPictureTag structure - before attempting to use it. - \param _pic The #OpusPictureTag structure to initialize.*/ -void opus_picture_tag_init(OpusPictureTag *_pic) OP_ARG_NONNULL(1); - -/**Clears the #OpusPictureTag structure. - This should be called on an #OpusPictureTag structure after it is no longer - needed. - It will free all memory used by the structure members. - \param _pic The #OpusPictureTag structure to clear.*/ -void opus_picture_tag_clear(OpusPictureTag *_pic) OP_ARG_NONNULL(1); - -/*@}*/ - -/*@}*/ - -/**\defgroup url_options URL Reading Options*/ -/*@{*/ -/**\name URL reading options - Options for op_url_stream_create() and associated functions. - These allow you to provide proxy configuration parameters, skip SSL - certificate checks, etc. - Options are processed in order, and if the same option is passed multiple - times, only the value specified by the last occurrence has an effect - (unless otherwise specified). - They may be expanded in the future.*/ -/*@{*/ - -/**@cond PRIVATE*/ - -/*These are the raw numbers used to define the request codes. - They should not be used directly.*/ -#define OP_SSL_SKIP_CERTIFICATE_CHECK_REQUEST (6464) -#define OP_HTTP_PROXY_HOST_REQUEST (6528) -#define OP_HTTP_PROXY_PORT_REQUEST (6592) -#define OP_HTTP_PROXY_USER_REQUEST (6656) -#define OP_HTTP_PROXY_PASS_REQUEST (6720) -#define OP_GET_SERVER_INFO_REQUEST (6784) - -#define OP_URL_OPT(_request) ((_request)+(char *)0) - -/*These macros trigger compilation errors or warnings if the wrong types are - provided to one of the URL options.*/ -#define OP_CHECK_INT(_x) ((void)((_x)==(opus_int32)0),(opus_int32)(_x)) -#define OP_CHECK_CONST_CHAR_PTR(_x) ((_x)+((_x)-(const char *)(_x))) -#define OP_CHECK_SERVER_INFO_PTR(_x) ((_x)+((_x)-(OpusServerInfo *)(_x))) - -/**@endcond*/ - -/**HTTP/Shoutcast/Icecast server information associated with a URL.*/ -struct OpusServerInfo{ - /**The name of the server (icy-name/ice-name). - This is <code>NULL</code> if there was no <code>icy-name</code> or - <code>ice-name</code> header.*/ - char *name; - /**A short description of the server (icy-description/ice-description). - This is <code>NULL</code> if there was no <code>icy-description</code> or - <code>ice-description</code> header.*/ - char *description; - /**The genre the server falls under (icy-genre/ice-genre). - This is <code>NULL</code> if there was no <code>icy-genre</code> or - <code>ice-genre</code> header.*/ - char *genre; - /**The homepage for the server (icy-url/ice-url). - This is <code>NULL</code> if there was no <code>icy-url</code> or - <code>ice-url</code> header.*/ - char *url; - /**The software used by the origin server (Server). - This is <code>NULL</code> if there was no <code>Server</code> header.*/ - char *server; - /**The media type of the entity sent to the recepient (Content-Type). - This is <code>NULL</code> if there was no <code>Content-Type</code> - header.*/ - char *content_type; - /**The nominal stream bitrate in kbps (icy-br/ice-bitrate). - This is <code>-1</code> if there was no <code>icy-br</code> or - <code>ice-bitrate</code> header.*/ - opus_int32 bitrate_kbps; - /**Flag indicating whether the server is public (<code>1</code>) or not - (<code>0</code>) (icy-pub/ice-public). - This is <code>-1</code> if there was no <code>icy-pub</code> or - <code>ice-public</code> header.*/ - int is_public; - /**Flag indicating whether the server is using HTTPS instead of HTTP. - This is <code>0</code> unless HTTPS is being used. - This may not match the protocol used in the original URL if there were - redirections.*/ - int is_ssl; -}; - -/**Initializes an #OpusServerInfo structure. - All fields are set as if the corresponding header was not available. - \param _info The #OpusServerInfo structure to initialize. - \note If you use this function, you must link against <tt>libopusurl</tt>.*/ -void opus_server_info_init(OpusServerInfo *_info) OP_ARG_NONNULL(1); - -/**Clears the #OpusServerInfo structure. - This should be called on an #OpusServerInfo structure after it is no longer - needed. - It will free all memory used by the structure members. - \param _info The #OpusServerInfo structure to clear. - \note If you use this function, you must link against <tt>libopusurl</tt>.*/ -void opus_server_info_clear(OpusServerInfo *_info) OP_ARG_NONNULL(1); - -/**Skip the certificate check when connecting via TLS/SSL (https). - \param _b <code>opus_int32</code>: Whether or not to skip the certificate - check. - The check will be skipped if \a _b is non-zero, and will not be - skipped if \a _b is zero. - \hideinitializer*/ -#define OP_SSL_SKIP_CERTIFICATE_CHECK(_b) \ - OP_URL_OPT(OP_SSL_SKIP_CERTIFICATE_CHECK_REQUEST),OP_CHECK_INT(_b) - -/**Proxy connections through the given host. - If no port is specified via #OP_HTTP_PROXY_PORT, the port number defaults - to 8080 (http-alt). - All proxy parameters are ignored for non-http and non-https URLs. - \param _host <code>const char *</code>: The proxy server hostname. - This may be <code>NULL</code> to disable the use of a proxy - server. - \hideinitializer*/ -#define OP_HTTP_PROXY_HOST(_host) \ - OP_URL_OPT(OP_HTTP_PROXY_HOST_REQUEST),OP_CHECK_CONST_CHAR_PTR(_host) - -/**Use the given port when proxying connections. - This option only has an effect if #OP_HTTP_PROXY_HOST is specified with a - non-<code>NULL</code> \a _host. - If this option is not provided, the proxy port number defaults to 8080 - (http-alt). - All proxy parameters are ignored for non-http and non-https URLs. - \param _port <code>opus_int32</code>: The proxy server port. - This must be in the range 0...65535 (inclusive), or the - URL function this is passed to will fail. - \hideinitializer*/ -#define OP_HTTP_PROXY_PORT(_port) \ - OP_URL_OPT(OP_HTTP_PROXY_PORT_REQUEST),OP_CHECK_INT(_port) - -/**Use the given user name for authentication when proxying connections. - All proxy parameters are ignored for non-http and non-https URLs. - \param _user const char *: The proxy server user name. - This may be <code>NULL</code> to disable proxy - authentication. - A non-<code>NULL</code> value only has an effect - if #OP_HTTP_PROXY_HOST and #OP_HTTP_PROXY_PASS - are also specified with non-<code>NULL</code> - arguments. - \hideinitializer*/ -#define OP_HTTP_PROXY_USER(_user) \ - OP_URL_OPT(OP_HTTP_PROXY_USER_REQUEST),OP_CHECK_CONST_CHAR_PTR(_user) - -/**Use the given password for authentication when proxying connections. - All proxy parameters are ignored for non-http and non-https URLs. - \param _pass const char *: The proxy server password. - This may be <code>NULL</code> to disable proxy - authentication. - A non-<code>NULL</code> value only has an effect - if #OP_HTTP_PROXY_HOST and #OP_HTTP_PROXY_USER - are also specified with non-<code>NULL</code> - arguments. - \hideinitializer*/ -#define OP_HTTP_PROXY_PASS(_pass) \ - OP_URL_OPT(OP_HTTP_PROXY_PASS_REQUEST),OP_CHECK_CONST_CHAR_PTR(_pass) - -/**Parse information about the streaming server (if any) and return it. - Very little validation is done. - In particular, OpusServerInfo::url may not be a valid URL, - OpusServerInfo::bitrate_kbps may not really be in kbps, and - OpusServerInfo::content_type may not be a valid MIME type. - The character set of the string fields is not specified anywhere, and should - not be assumed to be valid UTF-8. - \param _info OpusServerInfo *: Returns information about the server. - If there is any error opening the stream, the - contents of this structure remain - unmodified. - On success, fills in the structure with the - server information that was available, if - any. - After a successful return, the contents of - this structure should be freed by calling - opus_server_info_clear(). - \hideinitializer*/ -#define OP_GET_SERVER_INFO(_info) \ - OP_URL_OPT(OP_GET_SERVER_INFO_REQUEST),OP_CHECK_SERVER_INFO_PTR(_info) - -/*@}*/ -/*@}*/ - -/**\defgroup stream_callbacks Abstract Stream Reading Interface*/ -/*@{*/ -/**\name Functions for reading from streams - These functions define the interface used to read from and seek in a stream - of data. - A stream does not need to implement seeking, but the decoder will not be - able to seek if it does not do so. - These functions also include some convenience routines for working with - standard <code>FILE</code> pointers, complete streams stored in a single - block of memory, or URLs.*/ -/*@{*/ - -/**Reads up to \a _nbytes bytes of data from \a _stream. - \param _stream The stream to read from. - \param[out] _ptr The buffer to store the data in. - \param _nbytes The maximum number of bytes to read. - This function may return fewer, though it will not - return zero unless it reaches end-of-file. - \return The number of bytes successfully read, or a negative value on - error.*/ -typedef int (*op_read_func)(void *_stream,unsigned char *_ptr,int _nbytes); - -/**Sets the position indicator for \a _stream. - The new position, measured in bytes, is obtained by adding \a _offset - bytes to the position specified by \a _whence. - If \a _whence is set to <code>SEEK_SET</code>, <code>SEEK_CUR</code>, or - <code>SEEK_END</code>, the offset is relative to the start of the stream, - the current position indicator, or end-of-file, respectively. - \retval 0 Success. - \retval -1 Seeking is not supported or an error occurred. - <code>errno</code> need not be set.*/ -typedef int (*op_seek_func)(void *_stream,opus_int64 _offset,int _whence); - -/**Obtains the current value of the position indicator for \a _stream. - \return The current position indicator.*/ -typedef opus_int64 (*op_tell_func)(void *_stream); - -/**Closes the underlying stream. - \retval 0 Success. - \retval EOF An error occurred. - <code>errno</code> need not be set.*/ -typedef int (*op_close_func)(void *_stream); - -/**The callbacks used to access non-<code>FILE</code> stream resources. - The function prototypes are basically the same as for the stdio functions - <code>fread()</code>, <code>fseek()</code>, <code>ftell()</code>, and - <code>fclose()</code>. - The differences are that the <code>FILE *</code> arguments have been - replaced with a <code>void *</code>, which is to be used as a pointer to - whatever internal data these functions might need, that #seek and #tell - take and return 64-bit offsets, and that #seek <em>must</em> return -1 if - the stream is unseekable.*/ -struct OpusFileCallbacks{ - /**Used to read data from the stream. - This must not be <code>NULL</code>.*/ - op_read_func read; - /**Used to seek in the stream. - This may be <code>NULL</code> if seeking is not implemented.*/ - op_seek_func seek; - /**Used to return the current read position in the stream. - This may be <code>NULL</code> if seeking is not implemented.*/ - op_tell_func tell; - /**Used to close the stream when the decoder is freed. - This may be <code>NULL</code> to leave the stream open.*/ - op_close_func close; -}; - -/**Opens a stream with <code>fopen()</code> and fills in a set of callbacks - that can be used to access it. - This is useful to avoid writing your own portable 64-bit seeking wrappers, - and also avoids cross-module linking issues on Windows, where a - <code>FILE *</code> must be accessed by routines defined in the same module - that opened it. - \param[out] _cb The callbacks to use for this file. - If there is an error opening the file, nothing will be - filled in here. - \param _path The path to the file to open. - On Windows, this string must be UTF-8 (to allow access to - files whose names cannot be represented in the current - MBCS code page). - All other systems use the native character encoding. - \param _mode The mode to open the file in. - \return A stream handle to use with the callbacks, or <code>NULL</code> on - error.*/ -OP_WARN_UNUSED_RESULT void *op_fopen(OpusFileCallbacks *_cb, - const char *_path,const char *_mode) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2) - OP_ARG_NONNULL(3); - -/**Opens a stream with <code>fdopen()</code> and fills in a set of callbacks - that can be used to access it. - This is useful to avoid writing your own portable 64-bit seeking wrappers, - and also avoids cross-module linking issues on Windows, where a - <code>FILE *</code> must be accessed by routines defined in the same module - that opened it. - \param[out] _cb The callbacks to use for this file. - If there is an error opening the file, nothing will be - filled in here. - \param _fd The file descriptor to open. - \param _mode The mode to open the file in. - \return A stream handle to use with the callbacks, or <code>NULL</code> on - error.*/ -OP_WARN_UNUSED_RESULT void *op_fdopen(OpusFileCallbacks *_cb, - int _fd,const char *_mode) OP_ARG_NONNULL(1) OP_ARG_NONNULL(3); - -/**Opens a stream with <code>freopen()</code> and fills in a set of callbacks - that can be used to access it. - This is useful to avoid writing your own portable 64-bit seeking wrappers, - and also avoids cross-module linking issues on Windows, where a - <code>FILE *</code> must be accessed by routines defined in the same module - that opened it. - \param[out] _cb The callbacks to use for this file. - If there is an error opening the file, nothing will be - filled in here. - \param _path The path to the file to open. - On Windows, this string must be UTF-8 (to allow access - to files whose names cannot be represented in the - current MBCS code page). - All other systems use the native character encoding. - \param _mode The mode to open the file in. - \param _stream A stream previously returned by op_fopen(), op_fdopen(), - or op_freopen(). - \return A stream handle to use with the callbacks, or <code>NULL</code> on - error.*/ -OP_WARN_UNUSED_RESULT void *op_freopen(OpusFileCallbacks *_cb, - const char *_path,const char *_mode,void *_stream) OP_ARG_NONNULL(1) - OP_ARG_NONNULL(2) OP_ARG_NONNULL(3) OP_ARG_NONNULL(4); - -/**Creates a stream that reads from the given block of memory. - This block of memory must contain the complete stream to decode. - This is useful for caching small streams (e.g., sound effects) in RAM. - \param[out] _cb The callbacks to use for this stream. - If there is an error creating the stream, nothing will be - filled in here. - \param _data The block of memory to read from. - \param _size The size of the block of memory. - \return A stream handle to use with the callbacks, or <code>NULL</code> on - error.*/ -OP_WARN_UNUSED_RESULT void *op_mem_stream_create(OpusFileCallbacks *_cb, - const unsigned char *_data,size_t _size) OP_ARG_NONNULL(1); - -/**Creates a stream that reads from the given URL. - This function behaves identically to op_url_stream_create(), except that it - takes a va_list instead of a variable number of arguments. - It does not call the <code>va_end</code> macro, and because it invokes the - <code>va_arg</code> macro, the value of \a _ap is undefined after the call. - \note If you use this function, you must link against <tt>libopusurl</tt>. - \param[out] _cb The callbacks to use for this stream. - If there is an error creating the stream, nothing will - be filled in here. - \param _url The URL to read from. - Currently only the <file:>, <http:>, and <https:> - schemes are supported. - Both <http:> and <https:> may be disabled at compile - time, in which case opening such URLs will always fail. - Currently this only supports URIs. - IRIs should be converted to UTF-8 and URL-escaped, with - internationalized domain names encoded in punycode, - before passing them to this function. - \param[in,out] _ap A list of the \ref url_options "optional flags" to use. - This is a variable-length list of options terminated - with <code>NULL</code>. - \return A stream handle to use with the callbacks, or <code>NULL</code> on - error.*/ -OP_WARN_UNUSED_RESULT void *op_url_stream_vcreate(OpusFileCallbacks *_cb, - const char *_url,va_list _ap) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); - -/**Creates a stream that reads from the given URL. - \note If you use this function, you must link against <tt>libopusurl</tt>. - \param[out] _cb The callbacks to use for this stream. - If there is an error creating the stream, nothing will be - filled in here. - \param _url The URL to read from. - Currently only the <file:>, <http:>, and <https:> schemes - are supported. - Both <http:> and <https:> may be disabled at compile time, - in which case opening such URLs will always fail. - Currently this only supports URIs. - IRIs should be converted to UTF-8 and URL-escaped, with - internationalized domain names encoded in punycode, before - passing them to this function. - \param ... The \ref url_options "optional flags" to use. - This is a variable-length list of options terminated with - <code>NULL</code>. - \return A stream handle to use with the callbacks, or <code>NULL</code> on - error.*/ -OP_WARN_UNUSED_RESULT void *op_url_stream_create(OpusFileCallbacks *_cb, - const char *_url,...) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); - -/*@}*/ -/*@}*/ - -/**\defgroup stream_open_close Opening and Closing*/ -/*@{*/ -/**\name Functions for opening and closing streams - - These functions allow you to test a stream to see if it is Opus, open it, - and close it. - Several flavors are provided for each of the built-in stream types, plus a - more general version which takes a set of application-provided callbacks.*/ -/*@{*/ - -/**Test to see if this is an Opus stream. - For good results, you will need at least 57 bytes (for a pure Opus-only - stream). - Something like 512 bytes will give more reliable results for multiplexed - streams. - This function is meant to be a quick-rejection filter. - Its purpose is not to guarantee that a stream is a valid Opus stream, but to - ensure that it looks enough like Opus that it isn't going to be recognized - as some other format (except possibly an Opus stream that is also - multiplexed with other codecs, such as video). - \param[out] _head The parsed ID header contents. - You may pass <code>NULL</code> if you do not need - this information. - If the function fails, the contents of this structure - remain untouched. - \param _initial_data An initial buffer of data from the start of the - stream. - \param _initial_bytes The number of bytes in \a _initial_data. - \return 0 if the data appears to be Opus, or a negative value on error. - \retval #OP_FALSE There was not enough data to tell if this was an Opus - stream or not. - \retval #OP_EFAULT An internal memory allocation failed. - \retval #OP_EIMPL The stream used a feature that is not implemented, - such as an unsupported channel family. - \retval #OP_ENOTFORMAT If the data did not contain a recognizable ID - header for an Opus stream. - \retval #OP_EVERSION If the version field signaled a version this library - does not know how to parse. - \retval #OP_EBADHEADER The ID header was not properly formatted or contained - illegal values.*/ -int op_test(OpusHead *_head, - const unsigned char *_initial_data,size_t _initial_bytes); - -/**Open a stream from the given file path. - \param _path The path to the file to open. - \param[out] _error Returns 0 on success, or a failure code on error. - You may pass in <code>NULL</code> if you don't want the - failure code. - The failure code will be #OP_EFAULT if the file could not - be opened, or one of the other failure codes from - op_open_callbacks() otherwise. - \return A freshly opened \c OggOpusFile, or <code>NULL</code> on error.*/ -OP_WARN_UNUSED_RESULT OggOpusFile *op_open_file(const char *_path,int *_error) - OP_ARG_NONNULL(1); - -/**Open a stream from a memory buffer. - \param _data The memory buffer to open. - \param _size The number of bytes in the buffer. - \param[out] _error Returns 0 on success, or a failure code on error. - You may pass in <code>NULL</code> if you don't want the - failure code. - See op_open_callbacks() for a full list of failure codes. - \return A freshly opened \c OggOpusFile, or <code>NULL</code> on error.*/ -OP_WARN_UNUSED_RESULT OggOpusFile *op_open_memory(const unsigned char *_data, - size_t _size,int *_error); - -/**Open a stream from a URL. - This function behaves identically to op_open_url(), except that it - takes a va_list instead of a variable number of arguments. - It does not call the <code>va_end</code> macro, and because it invokes the - <code>va_arg</code> macro, the value of \a _ap is undefined after the call. - \note If you use this function, you must link against <tt>libopusurl</tt>. - \param _url The URL to open. - Currently only the <file:>, <http:>, and <https:> - schemes are supported. - Both <http:> and <https:> may be disabled at compile - time, in which case opening such URLs will always - fail. - Currently this only supports URIs. - IRIs should be converted to UTF-8 and URL-escaped, - with internationalized domain names encoded in - punycode, before passing them to this function. - \param[out] _error Returns 0 on success, or a failure code on error. - You may pass in <code>NULL</code> if you don't want - the failure code. - See op_open_callbacks() for a full list of failure - codes. - \param[in,out] _ap A list of the \ref url_options "optional flags" to - use. - This is a variable-length list of options terminated - with <code>NULL</code>. - \return A freshly opened \c OggOpusFile, or <code>NULL</code> on error.*/ -OP_WARN_UNUSED_RESULT OggOpusFile *op_vopen_url(const char *_url, - int *_error,va_list _ap) OP_ARG_NONNULL(1); - -/**Open a stream from a URL. - \note If you use this function, you must link against <tt>libopusurl</tt>. - \param _url The URL to open. - Currently only the <file:>, <http:>, and <https:> schemes - are supported. - Both <http:> and <https:> may be disabled at compile - time, in which case opening such URLs will always fail. - Currently this only supports URIs. - IRIs should be converted to UTF-8 and URL-escaped, with - internationalized domain names encoded in punycode, - before passing them to this function. - \param[out] _error Returns 0 on success, or a failure code on error. - You may pass in <code>NULL</code> if you don't want the - failure code. - See op_open_callbacks() for a full list of failure codes. - \param ... The \ref url_options "optional flags" to use. - This is a variable-length list of options terminated with - <code>NULL</code>. - \return A freshly opened \c OggOpusFile, or <code>NULL</code> on error.*/ -OP_WARN_UNUSED_RESULT OggOpusFile *op_open_url(const char *_url, - int *_error,...) OP_ARG_NONNULL(1); - -/**Open a stream using the given set of callbacks to access it. - \param _source The stream to read from (e.g., a <code>FILE *</code>). - \param _cb The callbacks with which to access the stream. - <code><a href="#op_read_func">read()</a></code> must - be implemented. - <code><a href="#op_seek_func">seek()</a></code> and - <code><a href="#op_tell_func">tell()</a></code> may - be <code>NULL</code>, or may always return -1 to - indicate a source is unseekable, but if - <code><a href="#op_seek_func">seek()</a></code> is - implemented and succeeds on a particular source, then - <code><a href="#op_tell_func">tell()</a></code> must - also. - <code><a href="#op_close_func">close()</a></code> may - be <code>NULL</code>, but if it is not, it will be - called when the \c OggOpusFile is destroyed by - op_free(). - It will not be called if op_open_callbacks() fails - with an error. - \param _initial_data An initial buffer of data from the start of the - stream. - Applications can read some number of bytes from the - start of the stream to help identify this as an Opus - stream, and then provide them here to allow the - stream to be opened, even if it is unseekable. - \param _initial_bytes The number of bytes in \a _initial_data. - If the stream is seekable, its current position (as - reported by - <code><a href="#opus_tell_func">tell()</a></code> - at the start of this function) must be equal to - \a _initial_bytes. - Otherwise, seeking to absolute positions will - generate inconsistent results. - \param[out] _error Returns 0 on success, or a failure code on error. - You may pass in <code>NULL</code> if you don't want - the failure code. - The failure code will be one of - <dl> - <dt>#OP_EREAD</dt> - <dd>An underlying read, seek, or tell operation - failed when it should have succeeded, or we failed - to find data in the stream we had seen before.</dd> - <dt>#OP_EFAULT</dt> - <dd>There was a memory allocation failure, or an - internal library error.</dd> - <dt>#OP_EIMPL</dt> - <dd>The stream used a feature that is not - implemented, such as an unsupported channel - family.</dd> - <dt>#OP_EINVAL</dt> - <dd><code><a href="#op_seek_func">seek()</a></code> - was implemented and succeeded on this source, but - <code><a href="#op_tell_func">tell()</a></code> - did not, or the starting position indicator was - not equal to \a _initial_bytes.</dd> - <dt>#OP_ENOTFORMAT</dt> - <dd>The stream contained a link that did not have - any logical Opus streams in it.</dd> - <dt>#OP_EBADHEADER</dt> - <dd>A required header packet was not properly - formatted, contained illegal values, or was missing - altogether.</dd> - <dt>#OP_EVERSION</dt> - <dd>An ID header contained an unrecognized version - number.</dd> - <dt>#OP_EBADLINK</dt> - <dd>We failed to find data we had seen before after - seeking.</dd> - <dt>#OP_EBADTIMESTAMP</dt> - <dd>The first or last timestamp in a link failed - basic validity checks.</dd> - </dl> - \return A freshly opened \c OggOpusFile, or <code>NULL</code> on error. - <tt>libopusfile</tt> does <em>not</em> take ownership of the source - if the call fails. - The calling application is responsible for closing the source if - this call returns an error.*/ -OP_WARN_UNUSED_RESULT OggOpusFile *op_open_callbacks(void *_source, - const OpusFileCallbacks *_cb,const unsigned char *_initial_data, - size_t _initial_bytes,int *_error) OP_ARG_NONNULL(2); - -/**Partially open a stream from the given file path. - \see op_test_callbacks - \param _path The path to the file to open. - \param[out] _error Returns 0 on success, or a failure code on error. - You may pass in <code>NULL</code> if you don't want the - failure code. - The failure code will be #OP_EFAULT if the file could not - be opened, or one of the other failure codes from - op_open_callbacks() otherwise. - \return A partially opened \c OggOpusFile, or <code>NULL</code> on error.*/ -OP_WARN_UNUSED_RESULT OggOpusFile *op_test_file(const char *_path,int *_error) - OP_ARG_NONNULL(1); - -/**Partially open a stream from a memory buffer. - \see op_test_callbacks - \param _data The memory buffer to open. - \param _size The number of bytes in the buffer. - \param[out] _error Returns 0 on success, or a failure code on error. - You may pass in <code>NULL</code> if you don't want the - failure code. - See op_open_callbacks() for a full list of failure codes. - \return A partially opened \c OggOpusFile, or <code>NULL</code> on error.*/ -OP_WARN_UNUSED_RESULT OggOpusFile *op_test_memory(const unsigned char *_data, - size_t _size,int *_error); - -/**Partially open a stream from a URL. - This function behaves identically to op_test_url(), except that it - takes a va_list instead of a variable number of arguments. - It does not call the <code>va_end</code> macro, and because it invokes the - <code>va_arg</code> macro, the value of \a _ap is undefined after the call. - \note If you use this function, you must link against <tt>libopusurl</tt>. - \see op_test_url - \see op_test_callbacks - \param _url The URL to open. - Currently only the <file:>, <http:>, and <https:> - schemes are supported. - Both <http:> and <https:> may be disabled at compile - time, in which case opening such URLs will always - fail. - Currently this only supports URIs. - IRIs should be converted to UTF-8 and URL-escaped, - with internationalized domain names encoded in - punycode, before passing them to this function. - \param[out] _error Returns 0 on success, or a failure code on error. - You may pass in <code>NULL</code> if you don't want - the failure code. - See op_open_callbacks() for a full list of failure - codes. - \param[in,out] _ap A list of the \ref url_options "optional flags" to - use. - This is a variable-length list of options terminated - with <code>NULL</code>. - \return A partially opened \c OggOpusFile, or <code>NULL</code> on error.*/ -OP_WARN_UNUSED_RESULT OggOpusFile *op_vtest_url(const char *_url, - int *_error,va_list _ap) OP_ARG_NONNULL(1); - -/**Partially open a stream from a URL. - \note If you use this function, you must link against <tt>libopusurl</tt>. - \see op_test_callbacks - \param _url The URL to open. - Currently only the <file:>, <http:>, and <https:> - schemes are supported. - Both <http:> and <https:> may be disabled at compile - time, in which case opening such URLs will always fail. - Currently this only supports URIs. - IRIs should be converted to UTF-8 and URL-escaped, with - internationalized domain names encoded in punycode, - before passing them to this function. - \param[out] _error Returns 0 on success, or a failure code on error. - You may pass in <code>NULL</code> if you don't want the - failure code. - See op_open_callbacks() for a full list of failure - codes. - \param ... The \ref url_options "optional flags" to use. - This is a variable-length list of options terminated - with <code>NULL</code>. - \return A partially opened \c OggOpusFile, or <code>NULL</code> on error.*/ -OP_WARN_UNUSED_RESULT OggOpusFile *op_test_url(const char *_url, - int *_error,...) OP_ARG_NONNULL(1); - -/**Partially open a stream using the given set of callbacks to access it. - This tests for Opusness and loads the headers for the first link. - It does not seek (although it tests for seekability). - You can query a partially open stream for the few pieces of basic - information returned by op_serialno(), op_channel_count(), op_head(), and - op_tags() (but only for the first link). - You may also determine if it is seekable via a call to op_seekable(). - You cannot read audio from the stream, seek, get the size or duration, - get information from links other than the first one, or even get the total - number of links until you finish opening the stream with op_test_open(). - If you do not need to do any of these things, you can dispose of it with - op_free() instead. - - This function is provided mostly to simplify porting existing code that used - <tt>libvorbisfile</tt>. - For new code, you are likely better off using op_test() instead, which - is less resource-intensive, requires less data to succeed, and imposes a - hard limit on the amount of data it examines (important for unseekable - sources, where all such data must be buffered until you are sure of the - stream type). - \param _source The stream to read from (e.g., a <code>FILE *</code>). - \param _cb The callbacks with which to access the stream. - <code><a href="#op_read_func">read()</a></code> must - be implemented. - <code><a href="#op_seek_func">seek()</a></code> and - <code><a href="#op_tell_func">tell()</a></code> may - be <code>NULL</code>, or may always return -1 to - indicate a source is unseekable, but if - <code><a href="#op_seek_func">seek()</a></code> is - implemented and succeeds on a particular source, then - <code><a href="#op_tell_func">tell()</a></code> must - also. - <code><a href="#op_close_func">close()</a></code> may - be <code>NULL</code>, but if it is not, it will be - called when the \c OggOpusFile is destroyed by - op_free(). - It will not be called if op_open_callbacks() fails - with an error. - \param _initial_data An initial buffer of data from the start of the - stream. - Applications can read some number of bytes from the - start of the stream to help identify this as an Opus - stream, and then provide them here to allow the - stream to be tested more thoroughly, even if it is - unseekable. - \param _initial_bytes The number of bytes in \a _initial_data. - If the stream is seekable, its current position (as - reported by - <code><a href="#opus_tell_func">tell()</a></code> - at the start of this function) must be equal to - \a _initial_bytes. - Otherwise, seeking to absolute positions will - generate inconsistent results. - \param[out] _error Returns 0 on success, or a failure code on error. - You may pass in <code>NULL</code> if you don't want - the failure code. - See op_open_callbacks() for a full list of failure - codes. - \return A partially opened \c OggOpusFile, or <code>NULL</code> on error. - <tt>libopusfile</tt> does <em>not</em> take ownership of the source - if the call fails. - The calling application is responsible for closing the source if - this call returns an error.*/ -OP_WARN_UNUSED_RESULT OggOpusFile *op_test_callbacks(void *_source, - const OpusFileCallbacks *_cb,const unsigned char *_initial_data, - size_t _initial_bytes,int *_error) OP_ARG_NONNULL(2); - -/**Finish opening a stream partially opened with op_test_callbacks() or one of - the associated convenience functions. - If this function fails, you are still responsible for freeing the - \c OggOpusFile with op_free(). - \param _of The \c OggOpusFile to finish opening. - \return 0 on success, or a negative value on error. - \retval #OP_EREAD An underlying read, seek, or tell operation failed - when it should have succeeded. - \retval #OP_EFAULT There was a memory allocation failure, or an - internal library error. - \retval #OP_EIMPL The stream used a feature that is not implemented, - such as an unsupported channel family. - \retval #OP_EINVAL The stream was not partially opened with - op_test_callbacks() or one of the associated - convenience functions. - \retval #OP_ENOTFORMAT The stream contained a link that did not have any - logical Opus streams in it. - \retval #OP_EBADHEADER A required header packet was not properly - formatted, contained illegal values, or was - missing altogether. - \retval #OP_EVERSION An ID header contained an unrecognized version - number. - \retval #OP_EBADLINK We failed to find data we had seen before after - seeking. - \retval #OP_EBADTIMESTAMP The first or last timestamp in a link failed basic - validity checks.*/ -int op_test_open(OggOpusFile *_of) OP_ARG_NONNULL(1); - -/**Release all memory used by an \c OggOpusFile. - \param _of The \c OggOpusFile to free.*/ -void op_free(OggOpusFile *_of); - -/*@}*/ -/*@}*/ - -/**\defgroup stream_info Stream Information*/ -/*@{*/ -/**\name Functions for obtaining information about streams - - These functions allow you to get basic information about a stream, including - seekability, the number of links (for chained streams), plus the size, - duration, bitrate, header parameters, and meta information for each link - (or, where available, the stream as a whole). - Some of these (size, duration) are only available for seekable streams. - You can also query the current stream position, link, and playback time, - and instantaneous bitrate during playback. - - Some of these functions may be used successfully on the partially open - streams returned by op_test_callbacks() or one of the associated - convenience functions. - Their documention will indicate so explicitly.*/ -/*@{*/ - -/**Returns whether or not the data source being read is seekable. - This is true if - <ol> - <li>The <code><a href="#op_seek_func">seek()</a></code> and - <code><a href="#op_tell_func">tell()</a></code> callbacks are both - non-<code>NULL</code>,</li> - <li>The <code><a href="#op_seek_func">seek()</a></code> callback was - successfully executed at least once, and</li> - <li>The <code><a href="#op_tell_func">tell()</a></code> callback was - successfully able to report the position indicator afterwards.</li> - </ol> - This function may be called on partially-opened streams. - \param _of The \c OggOpusFile whose seekable status is to be returned. - \return A non-zero value if seekable, and 0 if unseekable.*/ -int op_seekable(const OggOpusFile *_of) OP_ARG_NONNULL(1); - -/**Returns the number of links in this chained stream. - This function may be called on partially-opened streams, but it will always - return 1. - The actual number of links is not known until the stream is fully opened. - \param _of The \c OggOpusFile from which to retrieve the link count. - \return For fully-open seekable sources, this returns the total number of - links in the whole stream, which will be at least 1. - For partially-open or unseekable sources, this always returns 1.*/ -int op_link_count(const OggOpusFile *_of) OP_ARG_NONNULL(1); - -/**Get the serial number of the given link in a (possibly-chained) Ogg Opus - stream. - This function may be called on partially-opened streams, but it will always - return the serial number of the Opus stream in the first link. - \param _of The \c OggOpusFile from which to retrieve the serial number. - \param _li The index of the link whose serial number should be retrieved. - Use a negative number to get the serial number of the current - link. - \return The serial number of the given link. - If \a _li is greater than the total number of links, this returns - the serial number of the last link. - If the source is not seekable, this always returns the serial number - of the current link.*/ -opus_uint32 op_serialno(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); - -/**Get the channel count of the given link in a (possibly-chained) Ogg Opus - stream. - This is equivalent to <code>op_head(_of,_li)->channel_count</code>, but - is provided for convenience. - This function may be called on partially-opened streams, but it will always - return the channel count of the Opus stream in the first link. - \param _of The \c OggOpusFile from which to retrieve the channel count. - \param _li The index of the link whose channel count should be retrieved. - Use a negative number to get the channel count of the current - link. - \return The channel count of the given link. - If \a _li is greater than the total number of links, this returns - the channel count of the last link. - If the source is not seekable, this always returns the channel count - of the current link.*/ -int op_channel_count(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); - -/**Get the total (compressed) size of the stream, or of an individual link in - a (possibly-chained) Ogg Opus stream, including all headers and Ogg muxing - overhead. - \warning If the Opus stream (or link) is concurrently multiplexed with other - logical streams (e.g., video), this returns the size of the entire stream - (or link), not just the number of bytes in the first logical Opus stream. - Returning the latter would require scanning the entire file. - \param _of The \c OggOpusFile from which to retrieve the compressed size. - \param _li The index of the link whose compressed size should be computed. - Use a negative number to get the compressed size of the entire - stream. - \return The compressed size of the entire stream if \a _li is negative, the - compressed size of link \a _li if it is non-negative, or a negative - value on error. - The compressed size of the entire stream may be smaller than that - of the underlying source if trailing garbage was detected in the - file. - \retval #OP_EINVAL The source is not seekable (so we can't know the length), - \a _li wasn't less than the total number of links in - the stream, or the stream was only partially open.*/ -opus_int64 op_raw_total(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); - -/**Get the total PCM length (number of samples at 48 kHz) of the stream, or of - an individual link in a (possibly-chained) Ogg Opus stream. - Users looking for <code>op_time_total()</code> should use op_pcm_total() - instead. - Because timestamps in Opus are fixed at 48 kHz, there is no need for a - separate function to convert this to seconds (and leaving it out avoids - introducing floating point to the API, for those that wish to avoid it). - \param _of The \c OggOpusFile from which to retrieve the PCM offset. - \param _li The index of the link whose PCM length should be computed. - Use a negative number to get the PCM length of the entire stream. - \return The PCM length of the entire stream if \a _li is negative, the PCM - length of link \a _li if it is non-negative, or a negative value on - error. - \retval #OP_EINVAL The source is not seekable (so we can't know the length), - \a _li wasn't less than the total number of links in - the stream, or the stream was only partially open.*/ -ogg_int64_t op_pcm_total(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); - -/**Get the ID header information for the given link in a (possibly chained) Ogg - Opus stream. - This function may be called on partially-opened streams, but it will always - return the ID header information of the Opus stream in the first link. - \param _of The \c OggOpusFile from which to retrieve the ID header - information. - \param _li The index of the link whose ID header information should be - retrieved. - Use a negative number to get the ID header information of the - current link. - For an unseekable stream, \a _li is ignored, and the ID header - information for the current link is always returned, if - available. - \return The contents of the ID header for the given link.*/ -const OpusHead *op_head(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); - -/**Get the comment header information for the given link in a (possibly - chained) Ogg Opus stream. - This function may be called on partially-opened streams, but it will always - return the tags from the Opus stream in the first link. - \param _of The \c OggOpusFile from which to retrieve the comment header - information. - \param _li The index of the link whose comment header information should be - retrieved. - Use a negative number to get the comment header information of - the current link. - For an unseekable stream, \a _li is ignored, and the comment - header information for the current link is always returned, if - available. - \return The contents of the comment header for the given link, or - <code>NULL</code> if this is an unseekable stream that encountered - an invalid link.*/ -const OpusTags *op_tags(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); - -/**Retrieve the index of the current link. - This is the link that produced the data most recently read by - op_read_float() or its associated functions, or, after a seek, the link - that the seek target landed in. - Reading more data may advance the link index (even on the first read after a - seek). - \param _of The \c OggOpusFile from which to retrieve the current link index. - \return The index of the current link on success, or a negative value on - failure. - For seekable streams, this is a number between 0 and the value - returned by op_link_count(). - For unseekable streams, this value starts at 0 and increments by one - each time a new link is encountered (even though op_link_count() - always returns 1). - \retval #OP_EINVAL The stream was only partially open.*/ -int op_current_link(const OggOpusFile *_of) OP_ARG_NONNULL(1); - -/**Computes the bitrate of the stream, or of an individual link in a - (possibly-chained) Ogg Opus stream. - The stream must be seekable to compute the bitrate. - For unseekable streams, use op_bitrate_instant() to get periodic estimates. - \warning If the Opus stream (or link) is concurrently multiplexed with other - logical streams (e.g., video), this uses the size of the entire stream (or - link) to compute the bitrate, not just the number of bytes in the first - logical Opus stream. - Returning the latter requires scanning the entire file, but this may be done - by decoding the whole file and calling op_bitrate_instant() once at the - end. - Install a trivial decoding callback with op_set_decode_callback() if you - wish to skip actual decoding during this process. - \param _of The \c OggOpusFile from which to retrieve the bitrate. - \param _li The index of the link whose bitrate should be computed. - Use a negative number to get the bitrate of the whole stream. - \return The bitrate on success, or a negative value on error. - \retval #OP_EINVAL The stream was only partially open, the stream was not - seekable, or \a _li was larger than the number of - links.*/ -opus_int32 op_bitrate(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); - -/**Compute the instantaneous bitrate, measured as the ratio of bits to playable - samples decoded since a) the last call to op_bitrate_instant(), b) the last - seek, or c) the start of playback, whichever was most recent. - This will spike somewhat after a seek or at the start/end of a chain - boundary, as pre-skip, pre-roll, and end-trimming causes samples to be - decoded but not played. - \param _of The \c OggOpusFile from which to retrieve the bitrate. - \return The bitrate, in bits per second, or a negative value on error. - \retval #OP_FALSE No data has been decoded since any of the events - described above. - \retval #OP_EINVAL The stream was only partially open.*/ -opus_int32 op_bitrate_instant(OggOpusFile *_of) OP_ARG_NONNULL(1); - -/**Obtain the current value of the position indicator for \a _of. - \param _of The \c OggOpusFile from which to retrieve the position indicator. - \return The byte position that is currently being read from. - \retval #OP_EINVAL The stream was only partially open.*/ -opus_int64 op_raw_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1); - -/**Obtain the PCM offset of the next sample to be read. - If the stream is not properly timestamped, this might not increment by the - proper amount between reads, or even return monotonically increasing - values. - \param _of The \c OggOpusFile from which to retrieve the PCM offset. - \return The PCM offset of the next sample to be read. - \retval #OP_EINVAL The stream was only partially open.*/ -ogg_int64_t op_pcm_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1); - -/*@}*/ -/*@}*/ - -/**\defgroup stream_seeking Seeking*/ -/*@{*/ -/**\name Functions for seeking in Opus streams - - These functions let you seek in Opus streams, if the underlying source - support it. - Seeking is implemented for all built-in stream I/O routines, though some - individual sources may not be seekable (pipes, live HTTP streams, or HTTP - streams from a server that does not support <code>Range</code> requests). - - op_raw_seek() is the fastest: it is guaranteed to perform at most one - physical seek, but, since the target is a byte position, makes no guarantee - how close to a given time it will come. - op_pcm_seek() provides sample-accurate seeking. - The number of physical seeks it requires is still quite small (often 1 or - 2, even in highly variable bitrate streams). - - Seeking in Opus requires decoding some pre-roll amount before playback to - allow the internal state to converge (as if recovering from packet loss). - This is handled internally by <tt>libopusfile</tt>, but means there is - little extra overhead for decoding up to the exact position requested - (since it must decode some amount of audio anyway). - It also means that decoding after seeking may not return exactly the same - values as would be obtained by decoding the stream straight through. - However, such differences are expected to be smaller than the loss - introduced by Opus's lossy compression.*/ -/*@{*/ - -/**Seek to a byte offset relative to the <b>compressed</b> data. - This also scans packets to update the PCM cursor. - It will cross a logical bitstream boundary, but only if it can't get any - packets out of the tail of the link to which it seeks. - \param _of The \c OggOpusFile in which to seek. - \param _byte_offset The byte position to seek to. - \return 0 on success, or a negative error code on failure. - \retval #OP_EREAD The underlying seek operation failed. - \retval #OP_EINVAL The stream was only partially open, or the target was - outside the valid range for the stream. - \retval #OP_ENOSEEK This stream is not seekable. - \retval #OP_EBADLINK Failed to initialize a decoder for a stream for an - unknown reason.*/ -int op_raw_seek(OggOpusFile *_of,opus_int64 _byte_offset) OP_ARG_NONNULL(1); - -/**Seek to the specified PCM offset, such that decoding will begin at exactly - the requested position. - \param _of The \c OggOpusFile in which to seek. - \param _pcm_offset The PCM offset to seek to. - This is in samples at 48 kHz relative to the start of the - stream. - \return 0 on success, or a negative value on error. - \retval #OP_EREAD An underlying read or seek operation failed. - \retval #OP_EINVAL The stream was only partially open, or the target was - outside the valid range for the stream. - \retval #OP_ENOSEEK This stream is not seekable. - \retval #OP_EBADLINK We failed to find data we had seen before, or the - bitstream structure was sufficiently malformed that - seeking to the target destination was impossible.*/ -int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset) OP_ARG_NONNULL(1); - -/*@}*/ -/*@}*/ - -/**\defgroup stream_decoding Decoding*/ -/*@{*/ -/**\name Functions for decoding audio data - - These functions retrieve actual decoded audio data from the stream. - The general functions, op_read() and op_read_float() return 16-bit or - floating-point output, both using native endian ordering. - The number of channels returned can change from link to link in a chained - stream. - There are special functions, op_read_stereo() and op_read_float_stereo(), - which always output two channels, to simplify applications which do not - wish to handle multichannel audio. - These downmix multichannel files to two channels, so they can always return - samples in the same format for every link in a chained file. - - If the rest of your audio processing chain can handle floating point, those - routines should be preferred, as floating point output avoids introducing - clipping and other issues which might be avoided entirely if, e.g., you - scale down the volume at some other stage. - However, if you intend to direct consume 16-bit samples, the conversion in - <tt>libopusfile</tt> provides noise-shaping dithering and, if compiled - against <tt>libopus</tt> 1.1 or later, soft-clipping prevention. - - <tt>libopusfile</tt> can also be configured at compile time to use the - fixed-point <tt>libopus</tt> API. - If so, <tt>libopusfile</tt>'s floating-point API may also be disabled. - In that configuration, nothing in <tt>libopusfile</tt> will use any - floating-point operations, to simplify support on devices without an - adequate FPU. - - \warning HTTPS streams may be be vulnerable to truncation attacks if you do - not check the error return code from op_read_float() or its associated - functions. - If the remote peer does not close the connection gracefully (with a TLS - "close notify" message), these functions will return #OP_EREAD instead of 0 - when they reach the end of the file. - If you are reading from an <https:> URL (particularly if seeking is not - supported), you should make sure to check for this error and warn the user - appropriately.*/ -/*@{*/ - -/**Indicates that the decoding callback should produce signed 16-bit - native-endian output samples.*/ -#define OP_DEC_FORMAT_SHORT (7008) -/**Indicates that the decoding callback should produce 32-bit native-endian - float samples.*/ -#define OP_DEC_FORMAT_FLOAT (7040) - -/**Indicates that the decoding callback did not decode anything, and that - <tt>libopusfile</tt> should decode normally instead.*/ -#define OP_DEC_USE_DEFAULT (6720) - -/**Called to decode an Opus packet. - This should invoke the functional equivalent of opus_multistream_decode() or - opus_multistream_decode_float(), except that it returns 0 on success - instead of the number of decoded samples (which is known a priori). - \param _ctx The application-provided callback context. - \param _decoder The decoder to use to decode the packet. - \param[out] _pcm The buffer to decode into. - This will always have enough room for \a _nchannels of - \a _nsamples samples, which should be placed into this - buffer interleaved. - \param _op The packet to decode. - This will always have its granule position set to a valid - value. - \param _nsamples The number of samples expected from the packet. - \param _nchannels The number of channels expected from the packet. - \param _format The desired sample output format. - This is either #OP_DEC_FORMAT_SHORT or - #OP_DEC_FORMAT_FLOAT. - \param _li The index of the link from which this packet was decoded. - \return A non-negative value on success, or a negative value on error. - The error codes should be the same as those returned by - opus_multistream_decode() or opus_multistream_decode_float(). - \retval 0 Decoding was successful. - The application has filled the buffer with - exactly <code>\a _nsamples*\a - _nchannels</code> samples in the requested - format. - \retval #OP_DEC_USE_DEFAULT No decoding was done. - <tt>libopusfile</tt> should decode normally - instead.*/ -typedef int (*op_decode_cb_func)(void *_ctx,OpusMSDecoder *_decoder,void *_pcm, - const ogg_packet *_op,int _nsamples,int _nchannels,int _format,int _li); - -/**Sets the packet decode callback function. - This is called once for each packet that needs to be decoded. - A call to this function is no guarantee that the audio will eventually be - delivered to the application. - Some or all of the data from the packet may be discarded (i.e., at the - beginning or end of a link, or after a seek), however the callback is - required to provide all of it. - \param _of The \c OggOpusFile on which to set the decode callback. - \param _decode_cb The callback function to call. - This may be <code>NULL</code> to disable calling the - callback. - \param _ctx The application-provided context pointer to pass to the - callback on each call.*/ -void op_set_decode_callback(OggOpusFile *_of, - op_decode_cb_func _decode_cb,void *_ctx) OP_ARG_NONNULL(1); - -/**Gain offset type that indicates that the provided offset is relative to the - header gain. - This is the default.*/ -#define OP_HEADER_GAIN (0) - -/**Gain offset type that indicates that the provided offset is relative to the - R128_ALBUM_GAIN value (if any), in addition to the header gain.*/ -#define OP_ALBUM_GAIN (3007) - -/**Gain offset type that indicates that the provided offset is relative to the - R128_TRACK_GAIN value (if any), in addition to the header gain.*/ -#define OP_TRACK_GAIN (3008) - -/**Gain offset type that indicates that the provided offset should be used as - the gain directly, without applying any the header or track gains.*/ -#define OP_ABSOLUTE_GAIN (3009) - -/**Sets the gain to be used for decoded output. - By default, the gain in the header is applied with no additional offset. - The total gain (including header gain and/or track gain, if applicable, and - this offset), will be clamped to [-32768,32767]/256 dB. - This is more than enough to saturate or underflow 16-bit PCM. - \note The new gain will not be applied to any already buffered, decoded - output. - This means you cannot change it sample-by-sample, as at best it will be - updated packet-by-packet. - It is meant for setting a target volume level, rather than applying smooth - fades, etc. - \param _of The \c OggOpusFile on which to set the gain offset. - \param _gain_type One of #OP_HEADER_GAIN, #OP_ALBUM_GAIN, - #OP_TRACK_GAIN, or #OP_ABSOLUTE_GAIN. - \param _gain_offset_q8 The gain offset to apply, in 1/256ths of a dB. - \return 0 on success or a negative value on error. - \retval #OP_EINVAL The \a _gain_type was unrecognized.*/ -int op_set_gain_offset(OggOpusFile *_of, - int _gain_type,opus_int32 _gain_offset_q8) OP_ARG_NONNULL(1); - -/**Sets whether or not dithering is enabled for 16-bit decoding. - By default, when <tt>libopusfile</tt> is compiled to use floating-point - internally, calling op_read() or op_read_stereo() will first decode to - float, and then convert to fixed-point using noise-shaping dithering. - This flag can be used to disable that dithering. - When the application uses op_read_float() or op_read_float_stereo(), or when - the library has been compiled to decode directly to fixed point, this flag - has no effect. - \param _of The \c OggOpusFile on which to enable or disable dithering. - \param _enabled A non-zero value to enable dithering, or 0 to disable it.*/ -void op_set_dither_enabled(OggOpusFile *_of,int _enabled) OP_ARG_NONNULL(1); - -/**Reads more samples from the stream. - \note Although \a _buf_size must indicate the total number of values that - can be stored in \a _pcm, the return value is the number of samples - <em>per channel</em>. - This is done because - <ol> - <li>The channel count cannot be known a priori (reading more samples might - advance us into the next link, with a different channel count), so - \a _buf_size cannot also be in units of samples per channel,</li> - <li>Returning the samples per channel matches the <code>libopus</code> API - as closely as we're able,</li> - <li>Returning the total number of values instead of samples per channel - would mean the caller would need a division to compute the samples per - channel, and might worry about the possibility of getting back samples - for some channels and not others, and</li> - <li>This approach is relatively fool-proof: if an application passes too - small a value to \a _buf_size, they will simply get fewer samples back, - and if they assume the return value is the total number of values, then - they will simply read too few (rather than reading too many and going - off the end of the buffer).</li> - </ol> - \param _of The \c OggOpusFile from which to read. - \param[out] _pcm A buffer in which to store the output PCM samples, as - signed native-endian 16-bit values at 48 kHz - with a nominal range of <code>[-32768,32767)</code>. - Multiple channels are interleaved using the - <a href="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">Vorbis - channel ordering</a>. - This must have room for at least \a _buf_size values. - \param _buf_size The number of values that can be stored in \a _pcm. - It is recommended that this be large enough for at - least 120 ms of data at 48 kHz per channel (5760 - values per channel). - Smaller buffers will simply return less data, possibly - consuming more memory to buffer the data internally. - <tt>libopusfile</tt> may return less data than - requested. - If so, there is no guarantee that the remaining data - in \a _pcm will be unmodified. - \param[out] _li The index of the link this data was decoded from. - You may pass <code>NULL</code> if you do not need this - information. - If this function fails (returning a negative value), - this parameter is left unset. - \return The number of samples read per channel on success, or a negative - value on failure. - The channel count can be retrieved on success by calling - <code>op_head(_of,*_li)</code>. - The number of samples returned may be 0 if the buffer was too small - to store even a single sample for all channels, or if end-of-file - was reached. - The list of possible failure codes follows. - Most of them can only be returned by unseekable, chained streams - that encounter a new link. - \retval #OP_HOLE There was a hole in the data, and some samples - may have been skipped. - Call this function again to continue decoding - past the hole. - \retval #OP_EREAD An underlying read operation failed. - This may signal a truncation attack from an - <https:> source. - \retval #OP_EFAULT An internal memory allocation failed. - \retval #OP_EIMPL An unseekable stream encountered a new link that - used a feature that is not implemented, such as - an unsupported channel family. - \retval #OP_EINVAL The stream was only partially open. - \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that - did not have any logical Opus streams in it. - \retval #OP_EBADHEADER An unseekable stream encountered a new link with a - required header packet that was not properly - formatted, contained illegal values, or was - missing altogether. - \retval #OP_EVERSION An unseekable stream encountered a new link with - an ID header that contained an unrecognized - version number. - \retval #OP_EBADPACKET Failed to properly decode the next packet. - \retval #OP_EBADLINK We failed to find data we had seen before. - \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with - a starting timestamp that failed basic validity - checks.*/ -OP_WARN_UNUSED_RESULT int op_read(OggOpusFile *_of, - opus_int16 *_pcm,int _buf_size,int *_li) OP_ARG_NONNULL(1); - -/**Reads more samples from the stream. - \note Although \a _buf_size must indicate the total number of values that - can be stored in \a _pcm, the return value is the number of samples - <em>per channel</em>. - <ol> - <li>The channel count cannot be known a priori (reading more samples might - advance us into the next link, with a different channel count), so - \a _buf_size cannot also be in units of samples per channel,</li> - <li>Returning the samples per channel matches the <code>libopus</code> API - as closely as we're able,</li> - <li>Returning the total number of values instead of samples per channel - would mean the caller would need a division to compute the samples per - channel, and might worry about the possibility of getting back samples - for some channels and not others, and</li> - <li>This approach is relatively fool-proof: if an application passes too - small a value to \a _buf_size, they will simply get fewer samples back, - and if they assume the return value is the total number of values, then - they will simply read too few (rather than reading too many and going - off the end of the buffer).</li> - </ol> - \param _of The \c OggOpusFile from which to read. - \param[out] _pcm A buffer in which to store the output PCM samples as - signed floats at 48 kHz with a nominal range of - <code>[-1.0,1.0]</code>. - Multiple channels are interleaved using the - <a href="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">Vorbis - channel ordering</a>. - This must have room for at least \a _buf_size floats. - \param _buf_size The number of floats that can be stored in \a _pcm. - It is recommended that this be large enough for at - least 120 ms of data at 48 kHz per channel (5760 - samples per channel). - Smaller buffers will simply return less data, possibly - consuming more memory to buffer the data internally. - If less than \a _buf_size values are returned, - <tt>libopusfile</tt> makes no guarantee that the - remaining data in \a _pcm will be unmodified. - \param[out] _li The index of the link this data was decoded from. - You may pass <code>NULL</code> if you do not need this - information. - If this function fails (returning a negative value), - this parameter is left unset. - \return The number of samples read per channel on success, or a negative - value on failure. - The channel count can be retrieved on success by calling - <code>op_head(_of,*_li)</code>. - The number of samples returned may be 0 if the buffer was too small - to store even a single sample for all channels, or if end-of-file - was reached. - The list of possible failure codes follows. - Most of them can only be returned by unseekable, chained streams - that encounter a new link. - \retval #OP_HOLE There was a hole in the data, and some samples - may have been skipped. - Call this function again to continue decoding - past the hole. - \retval #OP_EREAD An underlying read operation failed. - This may signal a truncation attack from an - <https:> source. - \retval #OP_EFAULT An internal memory allocation failed. - \retval #OP_EIMPL An unseekable stream encountered a new link that - used a feature that is not implemented, such as - an unsupported channel family. - \retval #OP_EINVAL The stream was only partially open. - \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that - did not have any logical Opus streams in it. - \retval #OP_EBADHEADER An unseekable stream encountered a new link with a - required header packet that was not properly - formatted, contained illegal values, or was - missing altogether. - \retval #OP_EVERSION An unseekable stream encountered a new link with - an ID header that contained an unrecognized - version number. - \retval #OP_EBADPACKET Failed to properly decode the next packet. - \retval #OP_EBADLINK We failed to find data we had seen before. - \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with - a starting timestamp that failed basic validity - checks.*/ -OP_WARN_UNUSED_RESULT int op_read_float(OggOpusFile *_of, - float *_pcm,int _buf_size,int *_li) OP_ARG_NONNULL(1); - -/**Reads more samples from the stream and downmixes to stereo, if necessary. - This function is intended for simple players that want a uniform output - format, even if the channel count changes between links in a chained - stream. - \note \a _buf_size indicates the total number of values that can be stored - in \a _pcm, while the return value is the number of samples <em>per - channel</em>, even though the channel count is known, for consistency with - op_read(). - \param _of The \c OggOpusFile from which to read. - \param[out] _pcm A buffer in which to store the output PCM samples, as - signed native-endian 16-bit values at 48 kHz - with a nominal range of <code>[-32768,32767)</code>. - The left and right channels are interleaved in the - buffer. - This must have room for at least \a _buf_size values. - \param _buf_size The number of values that can be stored in \a _pcm. - It is recommended that this be large enough for at - least 120 ms of data at 48 kHz per channel (11520 - values total). - Smaller buffers will simply return less data, possibly - consuming more memory to buffer the data internally. - If less than \a _buf_size values are returned, - <tt>libopusfile</tt> makes no guarantee that the - remaining data in \a _pcm will be unmodified. - \return The number of samples read per channel on success, or a negative - value on failure. - The number of samples returned may be 0 if the buffer was too small - to store even a single sample for both channels, or if end-of-file - was reached. - The list of possible failure codes follows. - Most of them can only be returned by unseekable, chained streams - that encounter a new link. - \retval #OP_HOLE There was a hole in the data, and some samples - may have been skipped. - Call this function again to continue decoding - past the hole. - \retval #OP_EREAD An underlying read operation failed. - This may signal a truncation attack from an - <https:> source. - \retval #OP_EFAULT An internal memory allocation failed. - \retval #OP_EIMPL An unseekable stream encountered a new link that - used a feature that is not implemented, such as - an unsupported channel family. - \retval #OP_EINVAL The stream was only partially open. - \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that - did not have any logical Opus streams in it. - \retval #OP_EBADHEADER An unseekable stream encountered a new link with a - required header packet that was not properly - formatted, contained illegal values, or was - missing altogether. - \retval #OP_EVERSION An unseekable stream encountered a new link with - an ID header that contained an unrecognized - version number. - \retval #OP_EBADPACKET Failed to properly decode the next packet. - \retval #OP_EBADLINK We failed to find data we had seen before. - \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with - a starting timestamp that failed basic validity - checks.*/ -OP_WARN_UNUSED_RESULT int op_read_stereo(OggOpusFile *_of, - opus_int16 *_pcm,int _buf_size) OP_ARG_NONNULL(1); - -/**Reads more samples from the stream and downmixes to stereo, if necessary. - This function is intended for simple players that want a uniform output - format, even if the channel count changes between links in a chained - stream. - \note \a _buf_size indicates the total number of values that can be stored - in \a _pcm, while the return value is the number of samples <em>per - channel</em>, even though the channel count is known, for consistency with - op_read_float(). - \param _of The \c OggOpusFile from which to read. - \param[out] _pcm A buffer in which to store the output PCM samples, as - signed floats at 48 kHz with a nominal range of - <code>[-1.0,1.0]</code>. - The left and right channels are interleaved in the - buffer. - This must have room for at least \a _buf_size values. - \param _buf_size The number of values that can be stored in \a _pcm. - It is recommended that this be large enough for at - least 120 ms of data at 48 kHz per channel (11520 - values total). - Smaller buffers will simply return less data, possibly - consuming more memory to buffer the data internally. - If less than \a _buf_size values are returned, - <tt>libopusfile</tt> makes no guarantee that the - remaining data in \a _pcm will be unmodified. - \return The number of samples read per channel on success, or a negative - value on failure. - The number of samples returned may be 0 if the buffer was too small - to store even a single sample for both channels, or if end-of-file - was reached. - The list of possible failure codes follows. - Most of them can only be returned by unseekable, chained streams - that encounter a new link. - \retval #OP_HOLE There was a hole in the data, and some samples - may have been skipped. - Call this function again to continue decoding - past the hole. - \retval #OP_EREAD An underlying read operation failed. - This may signal a truncation attack from an - <https:> source. - \retval #OP_EFAULT An internal memory allocation failed. - \retval #OP_EIMPL An unseekable stream encountered a new link that - used a feature that is not implemented, such as - an unsupported channel family. - \retval #OP_EINVAL The stream was only partially open. - \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that - that did not have any logical Opus streams in it. - \retval #OP_EBADHEADER An unseekable stream encountered a new link with a - required header packet that was not properly - formatted, contained illegal values, or was - missing altogether. - \retval #OP_EVERSION An unseekable stream encountered a new link with - an ID header that contained an unrecognized - version number. - \retval #OP_EBADPACKET Failed to properly decode the next packet. - \retval #OP_EBADLINK We failed to find data we had seen before. - \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with - a starting timestamp that failed basic validity - checks.*/ -OP_WARN_UNUSED_RESULT int op_read_float_stereo(OggOpusFile *_of, - float *_pcm,int _buf_size) OP_ARG_NONNULL(1); - -/*@}*/ -/*@}*/ - -# if OP_GNUC_PREREQ(4,0) -# pragma GCC visibility pop -# endif - -# if defined(__cplusplus) -} -# endif - -#endif diff --git a/drivers/opus/repacketizer.c b/drivers/opus/repacketizer.c deleted file mode 100644 index 3822f9c86f..0000000000 --- a/drivers/opus/repacketizer.c +++ /dev/null @@ -1,343 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/opus.h" -#include "opus/opus_private.h" -#include "opus/celt/os_support.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); - if(ret<1)return ret; - - rp->nb_frames += curr_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) -{ - int i, count; - opus_int32 tot_size; - opus_int16 *len; - const unsigned char **frames; - unsigned char * ptr; - - if (begin<0 || begin>=end || end>rp->nb_frames) - { - /*fprintf(stderr, "%d %d %d\n", begin, end, rp->nb_frames);*/ - 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; - - ptr = data; - if (count==1) - { - /* Code 0 */ - tot_size += len[0]+1; - if (tot_size > maxlen) - 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) - 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) - return OPUS_BUFFER_TOO_SMALL; - *ptr++ = (rp->toc&0xFC) | 0x2; - ptr += encode_size(len[0], ptr); - } - } - if (count > 2 || (pad && tot_size < maxlen)) - { - /* 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) - return OPUS_BUFFER_TOO_SMALL; - *ptr++ = (rp->toc&0xFC) | 0x3; - *ptr++ = count | 0x80; - } else { - tot_size += count*len[0]+2; - if (tot_size > maxlen) - return OPUS_BUFFER_TOO_SMALL; - *ptr++ = (rp->toc&0xFC) | 0x3; - *ptr++ = count; - } - pad_amount = pad ? (maxlen-tot_size) : 0; - if (pad_amount != 0) - { - int nb_255s; - data[1] |= 0x40; - nb_255s = (pad_amount-1)/255; - 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(). */ - celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]); - OPUS_MOVE(ptr, frames[i], len[i]); - ptr += len[i]; - } - if (pad) - { - /* Fill padding with zeros. */ - while (ptr<data+maxlen) - *ptr++=0; - } - 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); -} - -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); -} - -int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len) -{ - OpusRepacketizer rp; - opus_int32 ret; - if (len < 1) - return OPUS_BAD_ARG; - if (len==new_len) - return OPUS_OK; - else if (len > new_len) - return OPUS_BAD_ARG; - opus_repacketizer_init(&rp); - /* Moving payload to the end of the packet so we can do in-place padding */ - OPUS_MOVE(data+new_len-len, data, len); - opus_repacketizer_cat(&rp, data+new_len-len, len); - ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, 1); - 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; - if (len < 1) - return OPUS_BAD_ARG; - opus_repacketizer_init(&rp); - ret = opus_repacketizer_cat(&rp, data, len); - if (ret < 0) - return ret; - ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, len, 0, 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); - 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 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); - if (ret<0) - return ret; - ret = opus_repacketizer_cat_impl(&rp, data, packet_offset, self_delimited); - if (ret < 0) - return ret; - ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, dst, len, self_delimited, 0); - if (ret < 0) - return ret; - else - dst_len += ret; - dst += ret; - data += packet_offset; - len -= packet_offset; - } - return dst_len; -} - diff --git a/drivers/opus/repacketizer_demo.c b/drivers/opus/repacketizer_demo.c deleted file mode 100644 index 57acf6a53f..0000000000 --- a/drivers/opus/repacketizer_demo.c +++ /dev/null @@ -1,214 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/opus.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#define MAX_PACKETOUT 32000 - -void usage(char *argv0) -{ - fprintf(stderr, "usage: %s [options] input_file output_file\n", argv0); -} - -static void int_to_char(opus_uint32 i, unsigned char ch[4]) -{ - ch[0] = i>>24; - ch[1] = (i>>16)&0xFF; - ch[2] = (i>>8)&0xFF; - ch[3] = i&0xFF; -} - -static opus_uint32 char_to_int(unsigned char ch[4]) -{ - return ((opus_uint32)ch[0]<<24) | ((opus_uint32)ch[1]<<16) - | ((opus_uint32)ch[2]<< 8) | (opus_uint32)ch[3]; -} - -int main(int argc, char *argv[]) -{ - int i, eof=0; - FILE *fin, *fout; - unsigned char packets[48][1500]; - int len[48]; - int rng[48]; - OpusRepacketizer *rp; - unsigned char output_packet[MAX_PACKETOUT]; - int merge = 1, split=0; - - if (argc < 3) - { - usage(argv[0]); - return EXIT_FAILURE; - } - for (i=1;i<argc-2;i++) - { - if (strcmp(argv[i], "-merge")==0) - { - merge = atoi(argv[i+1]); - if(merge<1) - { - fprintf(stderr, "-merge parameter must be at least 1.\n"); - return EXIT_FAILURE; - } - if(merge>48) - { - fprintf(stderr, "-merge parameter must be less than 48.\n"); - return EXIT_FAILURE; - } - i++; - } else if (strcmp(argv[i], "-split")==0) - split = 1; - else - { - fprintf(stderr, "Unknown option: %s\n", argv[i]); - usage(argv[0]); - return EXIT_FAILURE; - } - } - fin = fopen(argv[argc-2], "r"); - if(fin==NULL) - { - fprintf(stderr, "Error opening input file: %s\n", argv[argc-2]); - return EXIT_FAILURE; - } - fout = fopen(argv[argc-1], "w"); - if(fout==NULL) - { - fprintf(stderr, "Error opening output file: %s\n", argv[argc-1]); - fclose(fin); - return EXIT_FAILURE; - } - - rp = opus_repacketizer_create(); - while (!eof) - { - int err; - int nb_packets=merge; - opus_repacketizer_init(rp); - for (i=0;i<nb_packets;i++) - { - unsigned char ch[4]; - err = fread(ch, 1, 4, fin); - len[i] = char_to_int(ch); - /*fprintf(stderr, "in len = %d\n", len[i]);*/ - if (len[i]>1500 || len[i]<0) - { - if (feof(fin)) - { - eof = 1; - } else { - fprintf(stderr, "Invalid payload length\n"); - fclose(fin); - fclose(fout); - return EXIT_FAILURE; - } - break; - } - err = fread(ch, 1, 4, fin); - rng[i] = char_to_int(ch); - err = fread(packets[i], 1, len[i], fin); - if (feof(fin)) - { - eof = 1; - break; - } - err = opus_repacketizer_cat(rp, packets[i], len[i]); - if (err!=OPUS_OK) - { - fprintf(stderr, "opus_repacketizer_cat() failed: %s\n", opus_strerror(err)); - break; - } - } - nb_packets = i; - - if (eof) - break; - - if (!split) - { - err = opus_repacketizer_out(rp, output_packet, MAX_PACKETOUT); - if (err>0) { - unsigned char int_field[4]; - int_to_char(err, int_field); - if(fwrite(int_field, 1, 4, fout)!=4){ - fprintf(stderr, "Error writing.\n"); - return EXIT_FAILURE; - } - int_to_char(rng[nb_packets-1], int_field); - if (fwrite(int_field, 1, 4, fout)!=4) { - fprintf(stderr, "Error writing.\n"); - return EXIT_FAILURE; - } - if (fwrite(output_packet, 1, err, fout)!=(unsigned)err) { - fprintf(stderr, "Error writing.\n"); - return EXIT_FAILURE; - } - /*fprintf(stderr, "out len = %d\n", err);*/ - } else { - fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err)); - } - } else { - int nb_frames = opus_repacketizer_get_nb_frames(rp); - for (i=0;i<nb_frames;i++) - { - err = opus_repacketizer_out_range(rp, i, i+1, output_packet, MAX_PACKETOUT); - if (err>0) { - unsigned char int_field[4]; - int_to_char(err, int_field); - if (fwrite(int_field, 1, 4, fout)!=4) { - fprintf(stderr, "Error writing.\n"); - return EXIT_FAILURE; - } - if (i==nb_frames-1) - int_to_char(rng[nb_packets-1], int_field); - else - int_to_char(0, int_field); - if (fwrite(int_field, 1, 4, fout)!=4) { - fprintf(stderr, "Error writing.\n"); - return EXIT_FAILURE; - } - if (fwrite(output_packet, 1, err, fout)!=(unsigned)err) { - fprintf(stderr, "Error writing.\n"); - return EXIT_FAILURE; - } - /*fprintf(stderr, "out len = %d\n", err);*/ - } else { - fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err)); - } - - } - } - } - - fclose(fin); - fclose(fout); - return EXIT_SUCCESS; -} diff --git a/drivers/opus/silk/A2NLSF.c b/drivers/opus/silk/A2NLSF.c deleted file mode 100644 index 38dbefc3bf..0000000000 --- a/drivers/opus/silk/A2NLSF.c +++ /dev/null @@ -1,264 +0,0 @@ -/*********************************************************************** -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 */ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/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 30 - -/* 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_SMULBB( k + 1, NLSF[ 0 ] ); - } - return; - } - - /* Error: Apply progressively more bandwidth expansion and run again */ - silk_bwexpander_32( a_Q16, d, 65536 - silk_SMULBB( 10 + i, i ) ); /* 10_Q16 = 0.00015*/ - - 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/drivers/opus/silk/API.h b/drivers/opus/silk/API.h deleted file mode 100644 index ce868c0c99..0000000000 --- a/drivers/opus/silk/API.h +++ /dev/null @@ -1,134 +0,0 @@ -/*********************************************************************** -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 "opus/silk/control.h" -#include "opus/silk/typedef.h" -#include "opus/silk/errors.h" -#include "opus/celt/entenc.h" -#include "opus/celt/entdec.h" - -#ifdef __cplusplus -extern "C" -{ -#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 */ -); - -/*************************/ -/* Init or reset encoder */ -/*************************/ -opus_int silk_InitEncoder( /* O Returns error code */ - void *encState, /* I/O State */ - 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_int16 *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 */ -); - -/****************************************/ -/* Decoder functions */ -/****************************************/ - -/***********************************************/ -/* 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 or Reset decoder */ -/*************************/ -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_int16 *samplesOut, /* O Decoded output speech vector */ - opus_int32 *nSamplesOut, /* O Number of samples decoded */ - 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 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/opus/silk/CNG.c b/drivers/opus/silk/CNG.c deleted file mode 100644 index 595a288865..0000000000 --- a/drivers/opus/silk/CNG.c +++ /dev/null @@ -1,178 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/celt/stack_alloc.h" - -/* Generates excitation for CNG LPC synthesis */ -static OPUS_INLINE void silk_CNG_exc( - opus_int32 exc_Q10[], /* O CNG excitation signal Q10 */ - opus_int32 exc_buf_Q14[], /* I Random samples buffer Q10 */ - opus_int32 Gain_Q16, /* I Gain to apply */ - 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_Q10[ i ] = (opus_int16)silk_SAT16( silk_SMULWW( exc_buf_Q14[ idx ], Gain_Q16 >> 4 ) ); - } - *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 sum_Q6, max_Gain_Q16, gain_Q16; - 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 ); - } - } - - /* Add CNG when packet is lost or during DTX */ - if( psDec->lossCnt ) { - VARDECL( opus_int32, CNG_sig_Q10 ); - ALLOC( CNG_sig_Q10, 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 ); - } - silk_CNG_exc( CNG_sig_Q10 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, gain_Q16, length, &psCNG->rand_seed ); - - /* Convert CNG NLSF to filter representation */ - silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order ); - - /* Generate CNG signal, by synthesis filtering */ - silk_memcpy( CNG_sig_Q10, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) ); - for( i = 0; i < length; i++ ) { - silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 ); - /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ - sum_Q6 = silk_RSHIFT( psDec->LPC_order, 1 ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] ); - if( psDec->LPC_order == 16 ) { - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] ); - sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] ); - } - - /* Update states */ - CNG_sig_Q10[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q10[ MAX_LPC_ORDER + i ], sum_Q6, 4 ); - - frame[ i ] = silk_ADD_SAT16( frame[ i ], silk_RSHIFT_ROUND( CNG_sig_Q10[ MAX_LPC_ORDER + i ], 10 ) ); - } - silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q10[ 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/drivers/opus/silk/HP_variable_cutoff.c b/drivers/opus/silk/HP_variable_cutoff.c deleted file mode 100644 index 6b93fdb5a3..0000000000 --- a/drivers/opus/silk/HP_variable_cutoff.c +++ /dev/null @@ -1,74 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" -#ifdef OPUS_FIXED_POINT -#include "opus/silk/fixed/main_FIX.h" -#else -#include "opus/silk/float/main_FLP.h" -#endif -#include "opus/silk/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/drivers/opus/silk/LPC_analysis_filter.c b/drivers/opus/silk/LPC_analysis_filter.c deleted file mode 100644 index f3c34b5482..0000000000 --- a/drivers/opus/silk/LPC_analysis_filter.c +++ /dev/null @@ -1,105 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" -#include "opus/celt/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 */ -/*******************************************/ - -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; -#ifdef OPUS_FIXED_POINT - opus_int16 mem[SILK_MAX_ORDER_LPC]; - opus_int16 num[SILK_MAX_ORDER_LPC]; -#else - int ix; - opus_int32 out32_Q12, out32; - const opus_int16 *in_ptr; -#endif - - silk_assert( d >= 6 ); - silk_assert( (d & 1) == 0 ); - silk_assert( d <= len ); - -#ifdef OPUS_FIXED_POINT - silk_assert( d <= SILK_MAX_ORDER_LPC ); - for ( j = 0; j < d; j++ ) { - num[ j ] = -B[ j ]; - } - for (j=0;j<d;j++) { - mem[ j ] = in[ d - j - 1 ]; - } - celt_fir( in + d, num, out + d, len - d, d, mem, 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/drivers/opus/silk/LPC_inv_pred_gain.c b/drivers/opus/silk/LPC_inv_pred_gain.c deleted file mode 100644 index 8ace51500c..0000000000 --- a/drivers/opus/silk/LPC_inv_pred_gain.c +++ /dev/null @@ -1,151 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.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( /* O Returns inverse prediction gain in energy domain, Q30 */ - opus_int32 A_QA[ 2 ][ 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, tmp_QA; - opus_int32 *Aold_QA, *Anew_QA; - - Anew_QA = A_QA[ order & 1 ]; - - invGain_Q30 = (opus_int32)1 << 30; - for( k = order - 1; k > 0; k-- ) { - /* Check for stability */ - if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) { - return 0; - } - - /* Set RC equal to negated AR coef */ - rc_Q31 = -silk_LSHIFT( Anew_QA[ k ], 31 - QA ); - - /* rc_mult1_Q30 range: [ 1 : 2^30 ] */ - rc_mult1_Q30 = ( (opus_int32)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 ) ); - - /* 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 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 ) ); - - /* Swap pointers */ - Aold_QA = Anew_QA; - Anew_QA = A_QA[ k & 1 ]; - - /* Update AR coefficient */ - for( n = 0; n < k; n++ ) { - tmp_QA = Aold_QA[ n ] - MUL32_FRAC_Q( Aold_QA[ k - n - 1 ], rc_Q31, 31 ); - Anew_QA[ n ] = MUL32_FRAC_Q( tmp_QA, rc_mult2 , mult2Q ); - } - } - - /* Check for stability */ - if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) { - return 0; - } - - /* Set RC equal to negated AR coef */ - rc_Q31 = -silk_LSHIFT( Anew_QA[ 0 ], 31 - QA ); - - /* Range: [ 1 : 2^30 ] */ - rc_mult1_Q30 = ( (opus_int32)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 ); - - return invGain_Q30; -} - -/* For input in Q12 domain */ -opus_int32 silk_LPC_inverse_pred_gain( /* 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[ 2 ][ SILK_MAX_ORDER_LPC ]; - opus_int32 *Anew_QA; - opus_int32 DC_resp = 0; - - Anew_QA = Atmp_QA[ order & 1 ]; - - /* Increase Q domain of the AR coefficients */ - for( k = 0; k < order; k++ ) { - DC_resp += (opus_int32)A_Q12[ k ]; - Anew_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( Atmp_QA, order ); -} - -#ifdef OPUS_FIXED_POINT - -/* For input in Q24 domain */ -opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */ - const opus_int32 *A_Q24, /* I Prediction coefficients [order] */ - const opus_int order /* I Prediction order */ -) -{ - opus_int k; - opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ]; - opus_int32 *Anew_QA; - - Anew_QA = Atmp_QA[ order & 1 ]; - - /* Increase Q domain of the AR coefficients */ - for( k = 0; k < order; k++ ) { - Anew_QA[ k ] = silk_RSHIFT32( A_Q24[ k ], 24 - QA ); - } - - return LPC_inverse_pred_gain_QA( Atmp_QA, order ); -} -#endif diff --git a/drivers/opus/silk/LP_variable_cutoff.c b/drivers/opus/silk/LP_variable_cutoff.c deleted file mode 100644 index b39497c4d9..0000000000 --- a/drivers/opus/silk/LP_variable_cutoff.c +++ /dev/null @@ -1,132 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -/* - 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 "opus/silk/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( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length, 1); - } -} diff --git a/drivers/opus/silk/NLSF2A.c b/drivers/opus/silk/NLSF2A.c deleted file mode 100644 index 09db1c1c3f..0000000000 --- a/drivers/opus/silk/NLSF2A.c +++ /dev/null @@ -1,175 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -/* 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 "opus/silk/SigProc_FIX.h" -#include "opus/silk/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) */ -) -{ - /* 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 ]; - opus_int32 maxabs, absval, idx=0, sc_Q16; - - silk_assert( LSF_COS_TAB_SZ_FIX == 128 ); - silk_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 */ - } - - /* 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( a32_QA1[k] ); - if( absval > maxabs ) { - maxabs = absval; - idx = k; - } - } - maxabs = silk_RSHIFT_ROUND( maxabs, QA + 1 - 12 ); /* QA+1 -> Q12 */ - - if( maxabs > silk_int16_MAX ) { - /* Reduce magnitude of prediction coefficients */ - maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */ - sc_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( a32_QA1, d, sc_Q16 ); - } else { - break; - } - } - - if( i == 10 ) { - /* Reached the last iteration, clip the coefficients */ - for( k = 0; k < d; k++ ) { - a_Q12[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) ); /* QA+1 -> Q12 */ - a32_QA1[ k ] = silk_LSHIFT( (opus_int32)a_Q12[ k ], QA + 1 - 12 ); - } - } else { - for( k = 0; k < d; k++ ) { - a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */ - } - } - - for( i = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) { - if( silk_LPC_inverse_pred_gain( a_Q12, d ) < SILK_FIX_CONST( 1.0 / MAX_PREDICTION_POWER_GAIN, 30 ) ) { - /* 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 */ - } - } else { - break; - } - } -} - diff --git a/drivers/opus/silk/NLSF_VQ.c b/drivers/opus/silk/NLSF_VQ.c deleted file mode 100644 index 99a37d4e0d..0000000000 --- a/drivers/opus/silk/NLSF_VQ.c +++ /dev/null @@ -1,65 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" - -/* 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_int K, /* I Number of codebook vectors */ - const opus_int LPC_order /* I Number of LPCs */ -) -{ - opus_int i, m; - opus_int32 diff_Q15, sum_error_Q30, sum_error_Q26; - - silk_assert( LPC_order <= 16 ); - silk_assert( ( LPC_order & 1 ) == 0 ); - - /* Loop over codebook */ - for( i = 0; i < K; i++ ) { - sum_error_Q26 = 0; - for( m = 0; m < LPC_order; m += 2 ) { - /* Compute weighted squared quantization error for index m */ - diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/ - sum_error_Q30 = silk_SMULBB( diff_Q15, diff_Q15 ); - - /* Compute weighted squared quantization error for index m + 1 */ - diff_Q15 = silk_SUB_LSHIFT32( in_Q15[m + 1], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/ - sum_error_Q30 = silk_SMLABB( sum_error_Q30, diff_Q15, diff_Q15 ); - - sum_error_Q26 = silk_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 ); - - silk_assert( sum_error_Q26 >= 0 ); - silk_assert( sum_error_Q30 >= 0 ); - } - err_Q26[ i ] = sum_error_Q26; - } -} diff --git a/drivers/opus/silk/NLSF_VQ_weights_laroia.c b/drivers/opus/silk/NLSF_VQ_weights_laroia.c deleted file mode 100644 index 5743a4dee9..0000000000 --- a/drivers/opus/silk/NLSF_VQ_weights_laroia.c +++ /dev/null @@ -1,77 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/define.h" -#include "opus/silk/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; - - silk_assert( D > 0 ); - silk_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/drivers/opus/silk/NLSF_decode.c b/drivers/opus/silk/NLSF_decode.c deleted file mode 100644 index 6b922f3eee..0000000000 --- a/drivers/opus/silk/NLSF_decode.c +++ /dev/null @@ -1,98 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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_int16 W_tmp_QW[ MAX_LPC_ORDER ]; - opus_int32 W_tmp_Q9, NLSF_Q15_tmp; - const opus_uint8 *pCB_element; - - /* Decode first stage */ - pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ]; - for( i = 0; i < psNLSF_CB->order; i++ ) { - pNLSF_Q15[ i ] = silk_LSHIFT( (opus_int16)pCB_element[ i ], 7 ); - } - - /* 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 ); - - /* Weights from codebook vector */ - silk_NLSF_VQ_weights_laroia( W_tmp_QW, pNLSF_Q15, psNLSF_CB->order ); - - /* Apply inverse square-rooted weights and add to output */ - for( i = 0; i < psNLSF_CB->order; i++ ) { - W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) ); - NLSF_Q15_tmp = silk_ADD32( pNLSF_Q15[ i ], silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), W_tmp_Q9 ) ); - 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/drivers/opus/silk/NLSF_del_dec_quant.c b/drivers/opus/silk/NLSF_del_dec_quant.c deleted file mode 100644 index 3f81b2028c..0000000000 --- a/drivers/opus/silk/NLSF_del_dec_quant.c +++ /dev/null @@ -1,214 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" - -/* 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 */ -) -{ - opus_int i, j, nStates, ind_tmp, ind_min_max, ind_max_min, in_Q10, res_Q10; - opus_int pred_Q10, diff_Q10, out0_Q10, out1_Q10, rate0_Q5, rate1_Q5; - opus_int32 RD_tmp_Q25, min_Q25, min_max_Q25, max_min_Q25, pred_coef_Q16; - opus_int ind_sort[ NLSF_QUANT_DEL_DEC_STATES ]; - opus_int8 ind[ NLSF_QUANT_DEL_DEC_STATES ][ MAX_LPC_ORDER ]; - opus_int16 prev_out_Q10[ 2 * NLSF_QUANT_DEL_DEC_STATES ]; - opus_int32 RD_Q25[ 2 * NLSF_QUANT_DEL_DEC_STATES ]; - opus_int32 RD_min_Q25[ NLSF_QUANT_DEL_DEC_STATES ]; - opus_int32 RD_max_Q25[ NLSF_QUANT_DEL_DEC_STATES ]; - const opus_uint8 *rates_Q5; - - opus_int out0_Q10_table[2 * NLSF_QUANT_MAX_AMPLITUDE_EXT]; - opus_int out1_Q10_table[2 * NLSF_QUANT_MAX_AMPLITUDE_EXT]; - - for (i = -NLSF_QUANT_MAX_AMPLITUDE_EXT; i <= NLSF_QUANT_MAX_AMPLITUDE_EXT-1; i++) - { - out0_Q10 = silk_LSHIFT( i, 10 ); - out1_Q10 = silk_ADD16( out0_Q10, 1024 ); - if( i > 0 ) { - out0_Q10 = silk_SUB16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); - out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); - } else if( i == 0 ) { - out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); - } else if( i == -1 ) { - out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); - } else { - out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); - out1_Q10 = silk_ADD16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); - } - out0_Q10_table[ i + NLSF_QUANT_MAX_AMPLITUDE_EXT ] = silk_SMULWB( (opus_int32)out0_Q10, quant_step_size_Q16 ); - out1_Q10_table[ i + NLSF_QUANT_MAX_AMPLITUDE_EXT ] = silk_SMULWB( (opus_int32)out1_Q10, quant_step_size_Q16 ); - } - - silk_assert( (NLSF_QUANT_DEL_DEC_STATES & (NLSF_QUANT_DEL_DEC_STATES-1)) == 0 ); /* must be power of two */ - - nStates = 1; - RD_Q25[ 0 ] = 0; - prev_out_Q10[ 0 ] = 0; - for( i = order - 1; ; i-- ) { - rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ]; - pred_coef_Q16 = silk_LSHIFT( (opus_int32)pred_coef_Q8[ i ], 8 ); - in_Q10 = x_Q10[ i ]; - for( j = 0; j < nStates; j++ ) { - pred_Q10 = silk_SMULWB( pred_coef_Q16, prev_out_Q10[ j ] ); - res_Q10 = silk_SUB16( in_Q10, pred_Q10 ); - ind_tmp = silk_SMULWB( (opus_int32)inv_quant_step_size_Q6, res_Q10 ); - ind_tmp = silk_LIMIT( ind_tmp, -NLSF_QUANT_MAX_AMPLITUDE_EXT, NLSF_QUANT_MAX_AMPLITUDE_EXT-1 ); - ind[ j ][ i ] = (opus_int8)ind_tmp; - - /* compute outputs for ind_tmp and ind_tmp + 1 */ - out0_Q10 = out0_Q10_table[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE_EXT ]; - out1_Q10 = out1_Q10_table[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE_EXT ]; - - out0_Q10 = silk_ADD16( out0_Q10, pred_Q10 ); - out1_Q10 = silk_ADD16( out1_Q10, pred_Q10 ); - prev_out_Q10[ j ] = out0_Q10; - prev_out_Q10[ j + nStates ] = out1_Q10; - - /* compute RD for ind_tmp and ind_tmp + 1 */ - if( ind_tmp + 1 >= NLSF_QUANT_MAX_AMPLITUDE ) { - if( ind_tmp + 1 == NLSF_QUANT_MAX_AMPLITUDE ) { - rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ]; - rate1_Q5 = 280; - } else { - rate0_Q5 = silk_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, 43, ind_tmp ); - rate1_Q5 = silk_ADD16( rate0_Q5, 43 ); - } - } else if( ind_tmp <= -NLSF_QUANT_MAX_AMPLITUDE ) { - if( ind_tmp == -NLSF_QUANT_MAX_AMPLITUDE ) { - rate0_Q5 = 280; - rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ]; - } else { - rate0_Q5 = silk_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, -43, ind_tmp ); - rate1_Q5 = silk_SUB16( rate0_Q5, 43 ); - } - } else { - rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ]; - rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ]; - } - RD_tmp_Q25 = RD_Q25[ j ]; - diff_Q10 = silk_SUB16( in_Q10, out0_Q10 ); - RD_Q25[ j ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate0_Q5 ); - diff_Q10 = silk_SUB16( in_Q10, out1_Q10 ); - RD_Q25[ j + nStates ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate1_Q5 ); - } - - if( nStates <= ( NLSF_QUANT_DEL_DEC_STATES >> 1 ) ) { - /* double number of states and copy */ - for( j = 0; j < nStates; j++ ) { - ind[ j + nStates ][ i ] = ind[ j ][ i ] + 1; - } - nStates = silk_LSHIFT( nStates, 1 ); - for( j = nStates; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { - ind[ j ][ i ] = ind[ j - nStates ][ i ]; - } - } else if( i > 0 ) { - /* sort lower and upper half of RD_Q25, pairwise */ - for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { - if( RD_Q25[ j ] > RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] ) { - RD_max_Q25[ j ] = RD_Q25[ j ]; - RD_min_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ]; - RD_Q25[ j ] = RD_min_Q25[ j ]; - RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] = RD_max_Q25[ j ]; - /* swap prev_out values */ - out0_Q10 = prev_out_Q10[ j ]; - prev_out_Q10[ j ] = prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ]; - prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ] = out0_Q10; - ind_sort[ j ] = j + NLSF_QUANT_DEL_DEC_STATES; - } else { - RD_min_Q25[ j ] = RD_Q25[ j ]; - RD_max_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ]; - ind_sort[ j ] = j; - } - } - /* compare the highest RD values of the winning half with the lowest one in the losing half, and copy if necessary */ - /* afterwards ind_sort[] will contain the indices of the NLSF_QUANT_DEL_DEC_STATES winning RD values */ - while( 1 ) { - min_max_Q25 = silk_int32_MAX; - max_min_Q25 = 0; - ind_min_max = 0; - ind_max_min = 0; - for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { - if( min_max_Q25 > RD_max_Q25[ j ] ) { - min_max_Q25 = RD_max_Q25[ j ]; - ind_min_max = j; - } - if( max_min_Q25 < RD_min_Q25[ j ] ) { - max_min_Q25 = RD_min_Q25[ j ]; - ind_max_min = j; - } - } - if( min_max_Q25 >= max_min_Q25 ) { - break; - } - /* copy ind_min_max to ind_max_min */ - ind_sort[ ind_max_min ] = ind_sort[ ind_min_max ] ^ NLSF_QUANT_DEL_DEC_STATES; - RD_Q25[ ind_max_min ] = RD_Q25[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ]; - prev_out_Q10[ ind_max_min ] = prev_out_Q10[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ]; - RD_min_Q25[ ind_max_min ] = 0; - RD_max_Q25[ ind_min_max ] = silk_int32_MAX; - silk_memcpy( ind[ ind_max_min ], ind[ ind_min_max ], MAX_LPC_ORDER * sizeof( opus_int8 ) ); - } - /* increment index if it comes from the upper half */ - for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { - ind[ j ][ i ] += silk_RSHIFT( ind_sort[ j ], NLSF_QUANT_DEL_DEC_STATES_LOG2 ); - } - } else { /* i == 0 */ - break; - } - } - - /* last sample: find winner, copy indices and return RD value */ - ind_tmp = 0; - min_Q25 = silk_int32_MAX; - for( j = 0; j < 2 * NLSF_QUANT_DEL_DEC_STATES; j++ ) { - if( min_Q25 > RD_Q25[ j ] ) { - min_Q25 = RD_Q25[ j ]; - ind_tmp = j; - } - } - for( j = 0; j < order; j++ ) { - indices[ j ] = ind[ ind_tmp & ( NLSF_QUANT_DEL_DEC_STATES - 1 ) ][ j ]; - silk_assert( indices[ j ] >= -NLSF_QUANT_MAX_AMPLITUDE_EXT ); - silk_assert( indices[ j ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT ); - } - indices[ 0 ] += silk_RSHIFT( ind_tmp, NLSF_QUANT_DEL_DEC_STATES_LOG2 ); - silk_assert( indices[ 0 ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT ); - silk_assert( min_Q25 >= 0 ); - return min_Q25; -} diff --git a/drivers/opus/silk/NLSF_encode.c b/drivers/opus/silk/NLSF_encode.c deleted file mode 100644 index 9efb3e5158..0000000000 --- a/drivers/opus/silk/NLSF_encode.c +++ /dev/null @@ -1,133 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/celt/stack_alloc.h" - -/***********************/ -/* NLSF vector encoder */ -/***********************/ -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 */ -) -{ - opus_int i, s, ind1, bestIndex, prob_Q8, bits_q7; - opus_int32 W_tmp_Q9; - VARDECL( opus_int32, err_Q26 ); - VARDECL( opus_int32, RD_Q25 ); - VARDECL( opus_int, tempIndices1 ); - VARDECL( opus_int8, tempIndices2 ); - opus_int16 res_Q15[ MAX_LPC_ORDER ]; - opus_int16 res_Q10[ MAX_LPC_ORDER ]; - opus_int16 NLSF_tmp_Q15[ MAX_LPC_ORDER ]; - opus_int16 W_tmp_QW[ MAX_LPC_ORDER ]; - opus_int16 W_adj_Q5[ MAX_LPC_ORDER ]; - opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; - opus_int16 ec_ix[ MAX_LPC_ORDER ]; - const opus_uint8 *pCB_element, *iCDF_ptr; - SAVE_STACK; - - silk_assert( nSurvivors <= NLSF_VQ_MAX_SURVIVORS ); - silk_assert( signalType >= 0 && signalType <= 2 ); - silk_assert( NLSF_mu_Q20 <= 32767 && NLSF_mu_Q20 >= 0 ); - - /* NLSF stabilization */ - silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order ); - - /* First stage: VQ */ - ALLOC( err_Q26, psNLSF_CB->nVectors, opus_int32 ); - silk_NLSF_VQ( err_Q26, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->nVectors, psNLSF_CB->order ); - - /* Sort the quantization errors */ - ALLOC( tempIndices1, nSurvivors, opus_int ); - silk_insertion_sort_increasing( err_Q26, tempIndices1, psNLSF_CB->nVectors, nSurvivors ); - - ALLOC( RD_Q25, nSurvivors, opus_int32 ); - ALLOC( tempIndices2, nSurvivors * MAX_LPC_ORDER, opus_int8 ); - - /* Loop over survivors */ - for( s = 0; s < nSurvivors; s++ ) { - ind1 = tempIndices1[ s ]; - - /* Residual after first stage */ - pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ]; - for( i = 0; i < psNLSF_CB->order; i++ ) { - NLSF_tmp_Q15[ i ] = silk_LSHIFT16( (opus_int16)pCB_element[ i ], 7 ); - res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ]; - } - - /* Weights from codebook vector */ - silk_NLSF_VQ_weights_laroia( W_tmp_QW, NLSF_tmp_Q15, psNLSF_CB->order ); - - /* Apply square-rooted weights */ - for( i = 0; i < psNLSF_CB->order; i++ ) { - W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) ); - res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 ); - } - - /* Modify input weights accordingly */ - for( i = 0; i < psNLSF_CB->order; i++ ) { - W_adj_Q5[ i ] = silk_DIV32_16( silk_LSHIFT( (opus_int32)pW_QW[ i ], 5 ), W_tmp_QW[ i ] ); - } - - /* Unpack entropy table indices and predictor for current CB1 index */ - silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, ind1 ); - - /* Trellis quantizer */ - RD_Q25[ s ] = silk_NLSF_del_dec_quant( &tempIndices2[ s * MAX_LPC_ORDER ], res_Q10, W_adj_Q5, pred_Q8, ec_ix, - psNLSF_CB->ec_Rates_Q5, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->invQuantStepSize_Q6, NLSF_mu_Q20, psNLSF_CB->order ); - - /* Add rate for first stage */ - iCDF_ptr = &psNLSF_CB->CB1_iCDF[ ( signalType >> 1 ) * psNLSF_CB->nVectors ]; - if( ind1 == 0 ) { - prob_Q8 = 256 - iCDF_ptr[ ind1 ]; - } else { - prob_Q8 = iCDF_ptr[ ind1 - 1 ] - iCDF_ptr[ ind1 ]; - } - bits_q7 = ( 8 << 7 ) - silk_lin2log( prob_Q8 ); - RD_Q25[ s ] = silk_SMLABB( RD_Q25[ s ], bits_q7, silk_RSHIFT( NLSF_mu_Q20, 2 ) ); - } - - /* Find the lowest rate-distortion error */ - silk_insertion_sort_increasing( RD_Q25, &bestIndex, nSurvivors, 1 ); - - NLSFIndices[ 0 ] = (opus_int8)tempIndices1[ bestIndex ]; - silk_memcpy( &NLSFIndices[ 1 ], &tempIndices2[ bestIndex * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) ); - - /* Decode */ - silk_NLSF_decode( pNLSF_Q15, NLSFIndices, psNLSF_CB ); - - RESTORE_STACK; - return RD_Q25[ 0 ]; -} diff --git a/drivers/opus/silk/NLSF_stabilize.c b/drivers/opus/silk/NLSF_stabilize.c deleted file mode 100644 index 1a45e16925..0000000000 --- a/drivers/opus/silk/NLSF_stabilize.c +++ /dev/null @@ -1,139 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -/* 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 "opus/silk/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], 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/drivers/opus/silk/NLSF_unpack.c b/drivers/opus/silk/NLSF_unpack.c deleted file mode 100644 index c958f4a6ef..0000000000 --- a/drivers/opus/silk/NLSF_unpack.c +++ /dev/null @@ -1,52 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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/drivers/opus/silk/NSQ.c b/drivers/opus/silk/NSQ.c deleted file mode 100644 index e41e533bde..0000000000 --- a/drivers/opus/silk/NSQ.c +++ /dev/null @@ -1,450 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/celt/stack_alloc.h" - -static OPUS_INLINE void silk_nsq_scale_states( - const silk_encoder_state *psEncC, /* I Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - const opus_int32 x_Q3[], /* I input in Q3 */ - opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */ - const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */ - opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ - opus_int subfr, /* I subframe number */ - const opus_int LTP_scale_Q14, /* I */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ - const opus_int signal_type /* I Signal type */ -); - -#if !defined(OPUS_X86_MAY_HAVE_SSE4_1) -static OPUS_INLINE 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 */ -); -#endif - -void silk_NSQ_c -( - const silk_encoder_state *psEncC, /* I/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int32 x_Q3[], /* I Prefiltered input signal */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ - const opus_int16 AR2_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 */ -) -{ - opus_int k, lag, start_idx, LSF_interpolation_flag; - const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; - opus_int16 *pxq; - VARDECL( opus_int32, sLTP_Q15 ); - VARDECL( opus_int16, sLTP ); - opus_int32 HarmShapeFIRPacked_Q14; - opus_int offset_Q10; - VARDECL( opus_int32, x_sc_Q10 ); - SAVE_STACK; - - NSQ->rand_seed = psIndices->Seed; - - /* Set unvoiced lag to the previous one, overwrite later for voiced */ - lag = NSQ->lagPrev; - - silk_assert( NSQ->prev_gain_Q16 != 0 ); - - offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; - - if( psIndices->NLSFInterpCoef_Q2 == 4 ) { - LSF_interpolation_flag = 0; - } else { - LSF_interpolation_flag = 1; - } - - ALLOC( sLTP_Q15, - psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 ); - ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 ); - ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 ); - /* Set up pointers to start of sub frame */ - NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; - NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; - pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; - for( k = 0; k < psEncC->nb_subfr; k++ ) { - A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ]; - B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; - AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; - - /* Noise shape parameters */ - silk_assert( HarmShapeGain_Q14[ k ] >= 0 ); - HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); - HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); - - NSQ->rewhite_flag = 0; - if( psIndices->signalType == TYPE_VOICED ) { - /* Voiced */ - lag = pitchL[ k ]; - - /* Re-whitening */ - if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { - /* Rewhiten with new A coefs */ - start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; - silk_assert( start_idx > 0 ); - - silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], - A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch ); - - NSQ->rewhite_flag = 1; - NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; - } - } - - silk_nsq_scale_states( psEncC, NSQ, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType ); - - silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14, - AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10, - offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder ); - - x_Q3 += psEncC->subfr_length; - pulses += psEncC->subfr_length; - pxq += psEncC->subfr_length; - } - - /* Update lagPrev for next frame */ - NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; - - /* Save quantized speech and noise shaping signals */ - /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */ - silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); - silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); - RESTORE_STACK; -} - -/***********************************/ -/* silk_noise_shape_quantizer */ -/***********************************/ - -#if !defined(OPUS_X86_MAY_HAVE_SSE4_1) -static OPUS_INLINE -#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 */ -) -{ - opus_int i, j; - opus_int32 LTP_pred_Q13, LPC_pred_Q10, n_AR_Q12, n_LTP_Q13; - opus_int32 n_LF_Q12, r_Q10, rr_Q10, q1_Q0, q1_Q10, q2_Q10, rd1_Q20, rd2_Q20; - opus_int32 exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10; - opus_int32 tmp1, tmp2, sLF_AR_shp_Q14; - opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr; - - shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; - pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; - Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 ); - - /* Set up short term AR state */ - psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ]; - - for( i = 0; i < length; i++ ) { - /* Generate dither */ - NSQ->rand_seed = silk_RAND( NSQ->rand_seed ); - - /* Short-term prediction */ - silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 ); - /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ - LPC_pred_Q10 = silk_RSHIFT( predictLPCOrder, 1 ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ 0 ], a_Q12[ 0 ] ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); - if( predictLPCOrder == 16 ) { - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -10 ], a_Q12[ 10 ] ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -11 ], a_Q12[ 11 ] ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -12 ], a_Q12[ 12 ] ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -13 ], a_Q12[ 13 ] ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -14 ], a_Q12[ 14 ] ); - LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -15 ], a_Q12[ 15 ] ); - } - - /* Long-term prediction */ - if( signalType == TYPE_VOICED ) { - /* 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++; - } else { - LTP_pred_Q13 = 0; - } - - /* Noise shape feedback */ - silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ - tmp2 = psLPC_Q14[ 0 ]; - tmp1 = NSQ->sAR2_Q14[ 0 ]; - NSQ->sAR2_Q14[ 0 ] = tmp2; - n_AR_Q12 = silk_RSHIFT( shapingLPCOrder, 1 ); - n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp2, AR_shp_Q13[ 0 ] ); - for( j = 2; j < shapingLPCOrder; j += 2 ) { - tmp2 = NSQ->sAR2_Q14[ j - 1 ]; - NSQ->sAR2_Q14[ j - 1 ] = tmp1; - n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp1, AR_shp_Q13[ j - 1 ] ); - tmp1 = NSQ->sAR2_Q14[ j + 0 ]; - NSQ->sAR2_Q14[ j + 0 ] = tmp2; - n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp2, AR_shp_Q13[ j ] ); - } - NSQ->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1; - n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] ); - - n_AR_Q12 = silk_LSHIFT32( n_AR_Q12, 1 ); /* Q11 -> Q12 */ - n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sLF_AR_shp_Q14, Tilt_Q14 ); - - n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 ); - n_LF_Q12 = silk_SMLAWT( n_LF_Q12, NSQ->sLF_AR_shp_Q14, LF_shp_Q14 ); - - silk_assert( lag > 0 || signalType != TYPE_VOICED ); - - /* Combine prediction and noise shaping signals */ - tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */ - tmp1 = silk_SUB32( tmp1, n_LF_Q12 ); /* Q12 */ - if( lag > 0 ) { - /* Symmetric, packed FIR coefficients */ - n_LTP_Q13 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); - n_LTP_Q13 = silk_SMLAWT( n_LTP_Q13, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); - n_LTP_Q13 = silk_LSHIFT( n_LTP_Q13, 1 ); - shp_lag_ptr++; - - tmp2 = silk_SUB32( LTP_pred_Q13, n_LTP_Q13 ); /* Q13 */ - tmp1 = silk_ADD_LSHIFT32( tmp2, tmp1, 1 ); /* Q13 */ - tmp1 = silk_RSHIFT_ROUND( tmp1, 3 ); /* Q10 */ - } else { - tmp1 = silk_RSHIFT_ROUND( tmp1, 2 ); /* Q10 */ - } - - r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */ - - /* Flip sign depending on dither */ - if ( NSQ->rand_seed < 0 ) { - r_Q10 = -r_Q10; - } - r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 ); - - /* Find two quantization level candidates and measure their rate-distortion */ - q1_Q10 = silk_SUB32( r_Q10, offset_Q10 ); - q1_Q0 = silk_RSHIFT( q1_Q10, 10 ); - if( q1_Q0 > 0 ) { - q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); - q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); - q2_Q10 = silk_ADD32( q1_Q10, 1024 ); - rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 ); - rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 ); - } else if( q1_Q0 == 0 ) { - q1_Q10 = offset_Q10; - q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); - rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 ); - rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 ); - } else if( q1_Q0 == -1 ) { - q2_Q10 = offset_Q10; - q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); - rd1_Q20 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); - rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 ); - } else { /* Q1_Q0 < -1 */ - q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); - q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); - q2_Q10 = silk_ADD32( q1_Q10, 1024 ); - rd1_Q20 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); - rd2_Q20 = silk_SMULBB( -q2_Q10, Lambda_Q10 ); - } - rr_Q10 = silk_SUB32( r_Q10, q1_Q10 ); - rd1_Q20 = silk_SMLABB( rd1_Q20, rr_Q10, rr_Q10 ); - rr_Q10 = silk_SUB32( r_Q10, q2_Q10 ); - rd2_Q20 = silk_SMLABB( rd2_Q20, rr_Q10, rr_Q10 ); - - if( rd2_Q20 < rd1_Q20 ) { - q1_Q10 = q2_Q10; - } - - pulses[ i ] = (opus_int8)silk_RSHIFT_ROUND( q1_Q10, 10 ); - - /* Excitation */ - exc_Q14 = silk_LSHIFT( q1_Q10, 4 ); - if ( NSQ->rand_seed < 0 ) { - exc_Q14 = -exc_Q14; - } - - /* Add predictions */ - LPC_exc_Q14 = silk_ADD_LSHIFT32( exc_Q14, LTP_pred_Q13, 1 ); - xq_Q14 = silk_ADD_LSHIFT32( LPC_exc_Q14, LPC_pred_Q10, 4 ); - - /* Scale XQ back to normal level before saving */ - xq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( xq_Q14, Gain_Q10 ), 8 ) ); - - /* Update states */ - psLPC_Q14++; - *psLPC_Q14 = xq_Q14; - sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, n_AR_Q12, 2 ); - NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14; - - NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 ); - sLTP_Q15[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q14, 1 ); - NSQ->sLTP_shp_buf_idx++; - NSQ->sLTP_buf_idx++; - - /* Make dither dependent on quantized signal */ - NSQ->rand_seed = silk_ADD32_ovflw( NSQ->rand_seed, pulses[ i ] ); - } - - /* Update LPC synth buffer */ - silk_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); -} - -static OPUS_INLINE void silk_nsq_scale_states( - const silk_encoder_state *psEncC, /* I Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - const opus_int32 x_Q3[], /* I input in Q3 */ - opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */ - const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */ - opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ - opus_int subfr, /* I subframe number */ - const opus_int LTP_scale_Q14, /* I */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ - const opus_int signal_type /* I Signal type */ -) -{ - opus_int i, lag; - opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23; - - lag = pitchL[ subfr ]; - inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 ); - silk_assert( inv_gain_Q31 != 0 ); - - /* Calculate gain adjustment factor */ - if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) { - gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 ); - } else { - gain_adj_Q16 = (opus_int32)1 << 16; - } - - /* Scale input */ - inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 ); - for( i = 0; i < psEncC->subfr_length; i++ ) { - x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 ); - } - - /* Save inverse gain */ - NSQ->prev_gain_Q16 = Gains_Q16[ subfr ]; - - /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ - if( NSQ->rewhite_flag ) { - if( subfr == 0 ) { - /* Do LTP downscaling */ - inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 ); - } - for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { - silk_assert( i < MAX_FRAME_LENGTH ); - sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] ); - } - } - - /* Adjust for changing gain */ - if( gain_adj_Q16 != (opus_int32)1 << 16 ) { - /* Scale long-term shaping state */ - for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) { - NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] ); - } - - /* Scale long-term prediction state */ - if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) { - for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { - sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] ); - } - } - - NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 ); - - /* Scale short-term prediction and shaping states */ - for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { - NSQ->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] ); - } - for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { - NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] ); - } - } -} diff --git a/drivers/opus/silk/NSQ_del_dec.c b/drivers/opus/silk/NSQ_del_dec.c deleted file mode 100644 index 28b385e415..0000000000 --- a/drivers/opus/silk/NSQ_del_dec.c +++ /dev/null @@ -1,721 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/celt/stack_alloc.h" - -typedef struct { - opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ]; - opus_int32 RandState[ DECISION_DELAY ]; - opus_int32 Q_Q10[ DECISION_DELAY ]; - opus_int32 Xq_Q14[ DECISION_DELAY ]; - opus_int32 Pred_Q15[ DECISION_DELAY ]; - opus_int32 Shape_Q14[ DECISION_DELAY ]; - opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ]; - opus_int32 LF_AR_Q14; - opus_int32 Seed; - opus_int32 SeedInit; - opus_int32 RD_Q10; -} NSQ_del_dec_struct; - -typedef struct { - opus_int32 Q_Q10; - opus_int32 RD_Q10; - opus_int32 xq_Q14; - opus_int32 LF_AR_Q14; - opus_int32 sLTP_shp_Q14; - opus_int32 LPC_exc_Q14; -} NSQ_sample_struct; - -typedef NSQ_sample_struct NSQ_sample_pair[ 2 ]; - -#if defined(MIPSr1_ASM) -#include "opus/silk/mips/NSQ_del_dec_mipsr1.h" -#endif -static OPUS_INLINE void silk_nsq_del_dec_scale_states( - const silk_encoder_state *psEncC, /* I Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ - const opus_int32 x_Q3[], /* I Input in Q3 */ - opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */ - const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ - opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ - opus_int subfr, /* I Subframe number */ - opus_int nStatesDelayedDecision, /* I Number of del dec states */ - const opus_int LTP_scale_Q14, /* I LTP state scaling */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ - const opus_int signal_type, /* I Signal type */ - const opus_int decisionDelay /* I Decision delay */ -); - -/******************************************/ -/* Noise shape quantizer for one subframe */ -/******************************************/ -static OPUS_INLINE void silk_noise_shape_quantizer_del_dec( - silk_nsq_state *NSQ, /* I/O NSQ state */ - NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ - opus_int signalType, /* I Signal type */ - const opus_int32 x_Q10[], /* I */ - opus_int8 pulses[], /* O */ - opus_int16 xq[], /* O */ - opus_int32 sLTP_Q15[], /* I/O LTP filter state */ - opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */ - 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 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 subfr, /* I Subframe number */ - opus_int shapingLPCOrder, /* I Shaping LPC filter order */ - opus_int predictLPCOrder, /* I Prediction filter order */ - opus_int warping_Q16, /* I */ - opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ - opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ - opus_int decisionDelay /* I */ -); - -void silk_NSQ_del_dec_c( - const silk_encoder_state *psEncC, /* I/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int32 x_Q3[], /* I Prefiltered input signal */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ - const opus_int16 AR2_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 */ -) -{ - opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr; - opus_int last_smple_idx, smpl_buf_idx, decisionDelay; - const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; - opus_int16 *pxq; - VARDECL( opus_int32, sLTP_Q15 ); - VARDECL( opus_int16, sLTP ); - opus_int32 HarmShapeFIRPacked_Q14; - opus_int offset_Q10; - opus_int32 RDmin_Q10, Gain_Q10; - VARDECL( opus_int32, x_sc_Q10 ); - VARDECL( opus_int32, delayedGain_Q10 ); - VARDECL( NSQ_del_dec_struct, psDelDec ); - NSQ_del_dec_struct *psDD; - SAVE_STACK; - - /* Set unvoiced lag to the previous one, overwrite later for voiced */ - lag = NSQ->lagPrev; - - silk_assert( NSQ->prev_gain_Q16 != 0 ); - - /* Initialize delayed decision states */ - ALLOC( psDelDec, psEncC->nStatesDelayedDecision, NSQ_del_dec_struct ); - silk_memset( psDelDec, 0, psEncC->nStatesDelayedDecision * sizeof( NSQ_del_dec_struct ) ); - for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) { - psDD = &psDelDec[ k ]; - psDD->Seed = ( k + psIndices->Seed ) & 3; - psDD->SeedInit = psDD->Seed; - psDD->RD_Q10 = 0; - psDD->LF_AR_Q14 = NSQ->sLF_AR_shp_Q14; - psDD->Shape_Q14[ 0 ] = NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ]; - silk_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); - silk_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) ); - } - - offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; - smpl_buf_idx = 0; /* index of oldest samples */ - - decisionDelay = silk_min_int( DECISION_DELAY, psEncC->subfr_length ); - - /* For voiced frames limit the decision delay to lower than the pitch lag */ - if( psIndices->signalType == TYPE_VOICED ) { - for( k = 0; k < psEncC->nb_subfr; k++ ) { - decisionDelay = silk_min_int( decisionDelay, pitchL[ k ] - LTP_ORDER / 2 - 1 ); - } - } else { - if( lag > 0 ) { - decisionDelay = silk_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 ); - } - } - - if( psIndices->NLSFInterpCoef_Q2 == 4 ) { - LSF_interpolation_flag = 0; - } else { - LSF_interpolation_flag = 1; - } - - ALLOC( sLTP_Q15, - psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 ); - ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 ); - ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 ); - ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 ); - /* Set up pointers to start of sub frame */ - pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; - NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; - NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; - subfr = 0; - for( k = 0; k < psEncC->nb_subfr; k++ ) { - A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ]; - B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; - AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; - - /* Noise shape parameters */ - silk_assert( HarmShapeGain_Q14[ k ] >= 0 ); - HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); - HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); - - NSQ->rewhite_flag = 0; - if( psIndices->signalType == TYPE_VOICED ) { - /* Voiced */ - lag = pitchL[ k ]; - - /* Re-whitening */ - if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { - if( k == 2 ) { - /* RESET DELAYED DECISIONS */ - /* Find winner */ - RDmin_Q10 = psDelDec[ 0 ].RD_Q10; - Winner_ind = 0; - for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) { - if( psDelDec[ i ].RD_Q10 < RDmin_Q10 ) { - RDmin_Q10 = psDelDec[ i ].RD_Q10; - Winner_ind = i; - } - } - for( i = 0; i < psEncC->nStatesDelayedDecision; i++ ) { - if( i != Winner_ind ) { - psDelDec[ i ].RD_Q10 += ( silk_int32_MAX >> 4 ); - silk_assert( psDelDec[ i ].RD_Q10 >= 0 ); - } - } - - /* Copy final part of signals from winner state to output and long-term filter states */ - psDD = &psDelDec[ Winner_ind ]; - last_smple_idx = smpl_buf_idx + decisionDelay; - for( i = 0; i < decisionDelay; i++ ) { - last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; - pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); - pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( - silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) ); - NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ]; - } - - subfr = 0; - } - - /* Rewhiten with new A coefs */ - start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; - silk_assert( start_idx > 0 ); - - silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], - A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch ); - - NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; - NSQ->rewhite_flag = 1; - } - } - - silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, - psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay ); - - silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, - delayedGain_Q10, A_Q12, B_Q14, AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], - Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder, - psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay ); - - x_Q3 += psEncC->subfr_length; - pulses += psEncC->subfr_length; - pxq += psEncC->subfr_length; - } - - /* Find winner */ - RDmin_Q10 = psDelDec[ 0 ].RD_Q10; - Winner_ind = 0; - for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) { - if( psDelDec[ k ].RD_Q10 < RDmin_Q10 ) { - RDmin_Q10 = psDelDec[ k ].RD_Q10; - Winner_ind = k; - } - } - - /* Copy final part of signals from winner state to output and long-term filter states */ - psDD = &psDelDec[ Winner_ind ]; - psIndices->Seed = psDD->SeedInit; - last_smple_idx = smpl_buf_idx + decisionDelay; - Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 ); - for( i = 0; i < decisionDelay; i++ ) { - last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; - pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); - pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( - silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) ); - NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ]; - } - silk_memcpy( NSQ->sLPC_Q14, &psDD->sLPC_Q14[ psEncC->subfr_length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); - silk_memcpy( NSQ->sAR2_Q14, psDD->sAR2_Q14, sizeof( psDD->sAR2_Q14 ) ); - - /* Update states */ - NSQ->sLF_AR_shp_Q14 = psDD->LF_AR_Q14; - NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; - - /* Save quantized speech signal */ - /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */ - silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); - silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); - RESTORE_STACK; -} - -/******************************************/ -/* Noise shape quantizer for one subframe */ -/******************************************/ -#ifndef OVERRIDE_silk_noise_shape_quantizer_del_dec -static OPUS_INLINE void silk_noise_shape_quantizer_del_dec( - silk_nsq_state *NSQ, /* I/O NSQ state */ - NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ - opus_int signalType, /* I Signal type */ - const opus_int32 x_Q10[], /* I */ - opus_int8 pulses[], /* O */ - opus_int16 xq[], /* O */ - opus_int32 sLTP_Q15[], /* I/O LTP filter state */ - opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */ - 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 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 subfr, /* I Subframe number */ - opus_int shapingLPCOrder, /* I Shaping LPC filter order */ - opus_int predictLPCOrder, /* I Prediction filter order */ - opus_int warping_Q16, /* I */ - opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ - opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ - opus_int decisionDelay /* I */ -) -{ - opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx; - opus_int32 Winner_rand_state; - opus_int32 LTP_pred_Q14, LPC_pred_Q14, n_AR_Q14, n_LTP_Q14; - opus_int32 n_LF_Q14, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10; - opus_int32 q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10; - opus_int32 tmp1, tmp2, sLF_AR_shp_Q14; - opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14; - VARDECL( NSQ_sample_pair, psSampleState ); - NSQ_del_dec_struct *psDD; - NSQ_sample_struct *psSS; - SAVE_STACK; - - silk_assert( nStatesDelayedDecision > 0 ); - ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair ); - - shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; - pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; - Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 ); - - for( i = 0; i < length; i++ ) { - /* Perform common calculations used in all states */ - - /* Long-term prediction */ - if( signalType == TYPE_VOICED ) { - /* Unrolled loop */ - /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ - LTP_pred_Q14 = 2; - LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ 0 ], b_Q14[ 0 ] ); - LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] ); - LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] ); - LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] ); - LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); - LTP_pred_Q14 = silk_LSHIFT( LTP_pred_Q14, 1 ); /* Q13 -> Q14 */ - pred_lag_ptr++; - } else { - LTP_pred_Q14 = 0; - } - - /* Long-term shaping */ - if( lag > 0 ) { - /* Symmetric, packed FIR coefficients */ - n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); - n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); - n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */ - shp_lag_ptr++; - } else { - n_LTP_Q14 = 0; - } - - for( k = 0; k < nStatesDelayedDecision; k++ ) { - /* Delayed decision state */ - psDD = &psDelDec[ k ]; - - /* Sample state */ - psSS = psSampleState[ k ]; - - /* Generate dither */ - psDD->Seed = silk_RAND( psDD->Seed ); - - /* Pointer used in short term prediction and shaping */ - psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ]; - /* Short-term prediction */ - silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 ); - /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ - LPC_pred_Q14 = silk_RSHIFT( predictLPCOrder, 1 ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ 0 ], a_Q12[ 0 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -1 ], a_Q12[ 1 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -2 ], a_Q12[ 2 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -3 ], a_Q12[ 3 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -4 ], a_Q12[ 4 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -5 ], a_Q12[ 5 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -6 ], a_Q12[ 6 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -7 ], a_Q12[ 7 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -8 ], a_Q12[ 8 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); - if( predictLPCOrder == 16 ) { - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -10 ], a_Q12[ 10 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -11 ], a_Q12[ 11 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -12 ], a_Q12[ 12 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -13 ], a_Q12[ 13 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -14 ], a_Q12[ 14 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -15 ], a_Q12[ 15 ] ); - } - LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */ - - /* Noise shape feedback */ - silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ - /* Output of lowpass section */ - tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 ); - /* Output of allpass section */ - tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 ); - psDD->sAR2_Q14[ 0 ] = tmp2; - n_AR_Q14 = silk_RSHIFT( shapingLPCOrder, 1 ); - n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ 0 ] ); - /* Loop over allpass sections */ - for( j = 2; j < shapingLPCOrder; j += 2 ) { - /* Output of allpass section */ - tmp2 = silk_SMLAWB( psDD->sAR2_Q14[ j - 1 ], psDD->sAR2_Q14[ j + 0 ] - tmp1, warping_Q16 ); - psDD->sAR2_Q14[ j - 1 ] = tmp1; - n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ j - 1 ] ); - /* Output of allpass section */ - tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ j + 0 ], psDD->sAR2_Q14[ j + 1 ] - tmp2, warping_Q16 ); - psDD->sAR2_Q14[ j + 0 ] = tmp2; - n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ j ] ); - } - psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1; - n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] ); - - n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 1 ); /* Q11 -> Q12 */ - n_AR_Q14 = silk_SMLAWB( n_AR_Q14, psDD->LF_AR_Q14, Tilt_Q14 ); /* Q12 */ - n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 2 ); /* Q12 -> Q14 */ - - n_LF_Q14 = silk_SMULWB( psDD->Shape_Q14[ *smpl_buf_idx ], LF_shp_Q14 ); /* Q12 */ - n_LF_Q14 = silk_SMLAWT( n_LF_Q14, psDD->LF_AR_Q14, LF_shp_Q14 ); /* Q12 */ - n_LF_Q14 = silk_LSHIFT( n_LF_Q14, 2 ); /* Q12 -> Q14 */ - - /* Input minus prediction plus noise feedback */ - /* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */ - tmp1 = silk_ADD32( n_AR_Q14, n_LF_Q14 ); /* Q14 */ - tmp2 = silk_ADD32( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */ - tmp1 = silk_SUB32( tmp2, tmp1 ); /* Q13 */ - tmp1 = silk_RSHIFT_ROUND( tmp1, 4 ); /* Q10 */ - - r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */ - - /* Flip sign depending on dither */ - if ( psDD->Seed < 0 ) { - r_Q10 = -r_Q10; - } - r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 ); - - /* Find two quantization level candidates and measure their rate-distortion */ - q1_Q10 = silk_SUB32( r_Q10, offset_Q10 ); - q1_Q0 = silk_RSHIFT( q1_Q10, 10 ); - if( q1_Q0 > 0 ) { - q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); - q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); - q2_Q10 = silk_ADD32( q1_Q10, 1024 ); - rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 ); - rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); - } else if( q1_Q0 == 0 ) { - q1_Q10 = offset_Q10; - q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); - rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 ); - rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); - } else if( q1_Q0 == -1 ) { - q2_Q10 = offset_Q10; - q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); - rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); - rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); - } else { /* q1_Q0 < -1 */ - q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); - q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); - q2_Q10 = silk_ADD32( q1_Q10, 1024 ); - rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); - rd2_Q10 = silk_SMULBB( -q2_Q10, Lambda_Q10 ); - } - rr_Q10 = silk_SUB32( r_Q10, q1_Q10 ); - rd1_Q10 = silk_RSHIFT( silk_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 ); - rr_Q10 = silk_SUB32( r_Q10, q2_Q10 ); - rd2_Q10 = silk_RSHIFT( silk_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 ); - - if( rd1_Q10 < rd2_Q10 ) { - psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 ); - psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 ); - psSS[ 0 ].Q_Q10 = q1_Q10; - psSS[ 1 ].Q_Q10 = q2_Q10; - } else { - psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 ); - psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 ); - psSS[ 0 ].Q_Q10 = q2_Q10; - psSS[ 1 ].Q_Q10 = q1_Q10; - } - - /* Update states for best quantization */ - - /* Quantized excitation */ - exc_Q14 = silk_LSHIFT32( psSS[ 0 ].Q_Q10, 4 ); - if ( psDD->Seed < 0 ) { - exc_Q14 = -exc_Q14; - } - - /* Add predictions */ - LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 ); - xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 ); - - /* Update states */ - sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 ); - psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 ); - psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14; - psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14; - psSS[ 0 ].xq_Q14 = xq_Q14; - - /* Update states for second best quantization */ - - /* Quantized excitation */ - exc_Q14 = silk_LSHIFT32( psSS[ 1 ].Q_Q10, 4 ); - if ( psDD->Seed < 0 ) { - exc_Q14 = -exc_Q14; - } - - - /* Add predictions */ - LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 ); - xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 ); - - /* Update states */ - sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 ); - psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 ); - psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14; - psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14; - psSS[ 1 ].xq_Q14 = xq_Q14; - } - - *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */ - last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */ - - /* Find winner */ - RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; - Winner_ind = 0; - for( k = 1; k < nStatesDelayedDecision; k++ ) { - if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) { - RDmin_Q10 = psSampleState[ k ][ 0 ].RD_Q10; - Winner_ind = k; - } - } - - /* Increase RD values of expired states */ - Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ]; - for( k = 0; k < nStatesDelayedDecision; k++ ) { - if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) { - psSampleState[ k ][ 0 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 0 ].RD_Q10, silk_int32_MAX >> 4 ); - psSampleState[ k ][ 1 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 1 ].RD_Q10, silk_int32_MAX >> 4 ); - silk_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 ); - } - } - - /* Find worst in first set and best in second set */ - RDmax_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; - RDmin_Q10 = psSampleState[ 0 ][ 1 ].RD_Q10; - RDmax_ind = 0; - RDmin_ind = 0; - for( k = 1; k < nStatesDelayedDecision; k++ ) { - /* find worst in first set */ - if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) { - RDmax_Q10 = psSampleState[ k ][ 0 ].RD_Q10; - RDmax_ind = k; - } - /* find best in second set */ - if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) { - RDmin_Q10 = psSampleState[ k ][ 1 ].RD_Q10; - RDmin_ind = k; - } - } - - /* Replace a state if best from second set outperforms worst in first set */ - if( RDmin_Q10 < RDmax_Q10 ) { - silk_memcpy( ( (opus_int32 *)&psDelDec[ RDmax_ind ] ) + i, - ( (opus_int32 *)&psDelDec[ RDmin_ind ] ) + i, sizeof( NSQ_del_dec_struct ) - i * sizeof( opus_int32) ); - silk_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) ); - } - - /* Write samples from winner to output and long-term filter states */ - psDD = &psDelDec[ Winner_ind ]; - if( subfr > 0 || i >= decisionDelay ) { - pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); - xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( - silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], delayedGain_Q10[ last_smple_idx ] ), 8 ) ); - NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q14[ last_smple_idx ]; - sLTP_Q15[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q15[ last_smple_idx ]; - } - NSQ->sLTP_shp_buf_idx++; - NSQ->sLTP_buf_idx++; - - /* Update states */ - for( k = 0; k < nStatesDelayedDecision; k++ ) { - psDD = &psDelDec[ k ]; - psSS = &psSampleState[ k ][ 0 ]; - psDD->LF_AR_Q14 = psSS->LF_AR_Q14; - psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14; - psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14; - psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10; - psDD->Pred_Q15[ *smpl_buf_idx ] = silk_LSHIFT32( psSS->LPC_exc_Q14, 1 ); - psDD->Shape_Q14[ *smpl_buf_idx ] = psSS->sLTP_shp_Q14; - psDD->Seed = silk_ADD32_ovflw( psDD->Seed, silk_RSHIFT_ROUND( psSS->Q_Q10, 10 ) ); - psDD->RandState[ *smpl_buf_idx ] = psDD->Seed; - psDD->RD_Q10 = psSS->RD_Q10; - } - delayedGain_Q10[ *smpl_buf_idx ] = Gain_Q10; - } - /* Update LPC states */ - for( k = 0; k < nStatesDelayedDecision; k++ ) { - psDD = &psDelDec[ k ]; - silk_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); - } - RESTORE_STACK; -} -#endif /* OVERRIDE_silk_noise_shape_quantizer_del_dec */ - -static OPUS_INLINE void silk_nsq_del_dec_scale_states( - const silk_encoder_state *psEncC, /* I Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ - const opus_int32 x_Q3[], /* I Input in Q3 */ - opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */ - const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ - opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ - opus_int subfr, /* I Subframe number */ - opus_int nStatesDelayedDecision, /* I Number of del dec states */ - const opus_int LTP_scale_Q14, /* I LTP state scaling */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ - const opus_int signal_type, /* I Signal type */ - const opus_int decisionDelay /* I Decision delay */ -) -{ - opus_int i, k, lag; - opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23; - NSQ_del_dec_struct *psDD; - - lag = pitchL[ subfr ]; - inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 ); - silk_assert( inv_gain_Q31 != 0 ); - - /* Calculate gain adjustment factor */ - if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) { - gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 ); - } else { - gain_adj_Q16 = (opus_int32)1 << 16; - } - - /* Scale input */ - inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 ); - for( i = 0; i < psEncC->subfr_length; i++ ) { - x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 ); - } - - /* Save inverse gain */ - NSQ->prev_gain_Q16 = Gains_Q16[ subfr ]; - - /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ - if( NSQ->rewhite_flag ) { - if( subfr == 0 ) { - /* Do LTP downscaling */ - inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 ); - } - for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { - silk_assert( i < MAX_FRAME_LENGTH ); - sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] ); - } - } - - /* Adjust for changing gain */ - if( gain_adj_Q16 != (opus_int32)1 << 16 ) { - /* Scale long-term shaping state */ - for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) { - NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] ); - } - - /* Scale long-term prediction state */ - if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) { - for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) { - sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] ); - } - } - - for( k = 0; k < nStatesDelayedDecision; k++ ) { - psDD = &psDelDec[ k ]; - - /* Scale scalar states */ - psDD->LF_AR_Q14 = silk_SMULWW( gain_adj_Q16, psDD->LF_AR_Q14 ); - - /* Scale short-term prediction and shaping states */ - for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { - psDD->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sLPC_Q14[ i ] ); - } - for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { - psDD->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sAR2_Q14[ i ] ); - } - for( i = 0; i < DECISION_DELAY; i++ ) { - psDD->Pred_Q15[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Pred_Q15[ i ] ); - psDD->Shape_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Shape_Q14[ i ] ); - } - } - } -} diff --git a/drivers/opus/silk/PLC.c b/drivers/opus/silk/PLC.c deleted file mode 100644 index 4007112c5a..0000000000 --- a/drivers/opus/silk/PLC.c +++ /dev/null @@ -1,442 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/celt/stack_alloc.h" -#include "opus/silk/PLC.h" - -#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 */ - 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 */ - 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, arch ); - - psDec->lossCnt++; - } else { - /****************************/ - /* Update state */ - /****************************/ - silk_PLC_update( psDec, psDecCtrl ); - } -} - -/**************************************************/ -/* 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 coeficients */ - 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 */ - 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 coeficients 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 ); - - 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; - silk_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 ) ); - - silk_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_LSHIFT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], 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 ) ) ); - } - - /* 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 ); - - 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/drivers/opus/silk/PLC.h b/drivers/opus/silk/PLC.h deleted file mode 100644 index 209c2de48f..0000000000 --- a/drivers/opus/silk/PLC.h +++ /dev/null @@ -1,62 +0,0 @@ -/*********************************************************************** -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 "opus/silk/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 */ - 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/drivers/opus/silk/SigProc_FIX.h b/drivers/opus/silk/SigProc_FIX.h deleted file mode 100644 index 743cf7800c..0000000000 --- a/drivers/opus/silk/SigProc_FIX.h +++ /dev/null @@ -1,615 +0,0 @@ -/*********************************************************************** -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 - -#ifdef __cplusplus -extern "C" -{ -#endif - -/*#define silk_MACRO_COUNT */ /* Used to enable WMOPS counting */ - -#define SILK_MAX_ORDER_LPC 16 /* max order of the LPC analysis in schur() and k2a() */ - -#include <string.h> /* for memset(), memcpy(), memmove() */ -#include "opus/silk/typedef.h" -#include "opus/silk/resampler_structs.h" -#include "opus/silk/macros.h" -#include "opus/celt/cpu_support.h" - -#if defined(OPUS_X86_MAY_HAVE_SSE4_1) -#include "opus/silk/x86/SigProc_FIX_sse.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( - 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) */ - opus_int stride /* I Operate on interleaved signal if > 1 */ -); - -/* 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( /* 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 */ -); - -/* For input in Q24 domain */ -opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */ - const opus_int32 *A_Q24, /* I Prediction coefficients [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 */ -); - -/********************************************************************/ -/* 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) */ -); - -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_aligned_64_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) ((((a)+(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b))) -#define silk_ADD_POS_SAT64(a, b) ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_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 silk_RAND(seed) (silk_MLA_ovflw(907633515, (seed), 196314165)) - -/* Add some multiplication functions that can be easily mapped to ARM. */ - -/* silk_SMMUL: Signed top word multiply. - ARMv6 2 instruction cycles. - ARMv3M+ 3 instruction cycles. use SMULL and ignore LSB registers.(except xM)*/ -/*#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(OPUS_X86_MAY_HAVE_SSE4_1) -#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)) - -#define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \ - ((void)(arch),silk_inner_prod16_aligned_64_c(inVec1, inVec2, len)) -#endif - -#include "opus/silk/Inlines.h" -#include "opus/silk/MacroCount.h" -#include "opus/silk/MacroDebug.h" - -#ifdef OPUS_ARM_INLINE_ASM -#include "opus/silk/arm/SigProc_FIX_armv4.h" -#endif - -#ifdef OPUS_ARM_INLINE_EDSP -#include "opus/silk/arm/SigProc_FIX_armv5e.h" -#endif - -#if defined(MIPSr1_ASM) -#include "opus/silk/mips/sigproc_fix_mipsr1.h" -#endif - - -#ifdef __cplusplus -} -#endif - -#endif /* SILK_SIGPROC_FIX_H */ diff --git a/drivers/opus/silk/VAD.c b/drivers/opus/silk/VAD.c deleted file mode 100644 index bb664cff87..0000000000 --- a/drivers/opus/silk/VAD.c +++ /dev/null @@ -1,359 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/celt/stack_alloc.h" - -/* Silk VAD noise level estimation */ -# if !defined(OPUS_X86_MAY_HAVE_SSE4_1) -static OPUS_INLINE 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 */ -); -#endif - -/**********************************/ -/* Initialization of 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 */ -) -{ - opus_int b, ret = 0; - - /* reset state memory */ - silk_memset( psSilk_VAD, 0, sizeof( silk_VAD_state ) ); - - /* init noise levels */ - /* Initialize array with approx pink noise levels (psd proportional to inverse of frequency) */ - for( b = 0; b < VAD_N_BANDS; b++ ) { - psSilk_VAD->NoiseLevelBias[ b ] = silk_max_32( silk_DIV32_16( VAD_NOISE_LEVELS_BIAS, b + 1 ), 1 ); - } - - /* Initialize state */ - for( b = 0; b < VAD_N_BANDS; b++ ) { - psSilk_VAD->NL[ b ] = silk_MUL( 100, psSilk_VAD->NoiseLevelBias[ b ] ); - psSilk_VAD->inv_NL[ b ] = silk_DIV32( silk_int32_MAX, psSilk_VAD->NL[ b ] ); - } - psSilk_VAD->counter = 15; - - /* init smoothed energy-to-noise ratio*/ - for( b = 0; b < VAD_N_BANDS; b++ ) { - psSilk_VAD->NrgRatioSmth_Q8[ b ] = 100 * 256; /* 100 * 256 --> 20 dB SNR */ - } - - return( ret ); -} - -/* Weighting factors for tilt measure */ -static const opus_int32 tiltWeights[ VAD_N_BANDS ] = { 30000, 6000, -12000, -12000 }; - -/***************************************/ -/* Get the 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 */ -) -{ - opus_int SA_Q15, pSNR_dB_Q7, input_tilt; - opus_int decimated_framelength1, decimated_framelength2; - opus_int decimated_framelength; - opus_int dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s; - opus_int32 sumSquared, smooth_coef_Q16; - opus_int16 HPstateTmp; - VARDECL( opus_int16, X ); - opus_int32 Xnrg[ VAD_N_BANDS ]; - opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ]; - opus_int32 speech_nrg, x_tmp; - opus_int X_offset[ VAD_N_BANDS ]; - opus_int ret = 0; - silk_VAD_state *psSilk_VAD = &psEncC->sVAD; - SAVE_STACK; - - /* Safety checks */ - silk_assert( VAD_N_BANDS == 4 ); - silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length ); - silk_assert( psEncC->frame_length <= 512 ); - silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) ); - - /***********************/ - /* Filter and Decimate */ - /***********************/ - decimated_framelength1 = silk_RSHIFT( psEncC->frame_length, 1 ); - decimated_framelength2 = silk_RSHIFT( psEncC->frame_length, 2 ); - decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 ); - /* Decimate into 4 bands: - 0 L 3L L 3L 5L - - -- - -- -- - 8 8 2 4 4 - - [0-1 kHz| temp. |1-2 kHz| 2-4 kHz | 4-8 kHz | - - They're arranged to allow the minimal ( frame_length / 4 ) extra - scratch space during the downsampling process */ - X_offset[ 0 ] = 0; - X_offset[ 1 ] = decimated_framelength + decimated_framelength2; - X_offset[ 2 ] = X_offset[ 1 ] + decimated_framelength; - X_offset[ 3 ] = X_offset[ 2 ] + decimated_framelength2; - ALLOC( X, X_offset[ 3 ] + decimated_framelength1, opus_int16 ); - - /* 0-8 kHz to 0-4 kHz and 4-8 kHz */ - silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ], - X, &X[ X_offset[ 3 ] ], psEncC->frame_length ); - - /* 0-4 kHz to 0-2 kHz and 2-4 kHz */ - silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState1[ 0 ], - X, &X[ X_offset[ 2 ] ], decimated_framelength1 ); - - /* 0-2 kHz to 0-1 kHz and 1-2 kHz */ - silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState2[ 0 ], - X, &X[ X_offset[ 1 ] ], decimated_framelength2 ); - - /*********************************************/ - /* HP filter on lowest band (differentiator) */ - /*********************************************/ - X[ decimated_framelength - 1 ] = silk_RSHIFT( X[ decimated_framelength - 1 ], 1 ); - HPstateTmp = X[ decimated_framelength - 1 ]; - for( i = decimated_framelength - 1; i > 0; i-- ) { - X[ i - 1 ] = silk_RSHIFT( X[ i - 1 ], 1 ); - X[ i ] -= X[ i - 1 ]; - } - X[ 0 ] -= psSilk_VAD->HPstate; - psSilk_VAD->HPstate = HPstateTmp; - - /*************************************/ - /* Calculate the energy in each band */ - /*************************************/ - for( b = 0; b < VAD_N_BANDS; b++ ) { - /* Find the decimated framelength in the non-uniformly divided bands */ - decimated_framelength = silk_RSHIFT( psEncC->frame_length, silk_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) ); - - /* Split length into subframe lengths */ - dec_subframe_length = silk_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 ); - dec_subframe_offset = 0; - - /* Compute energy per sub-frame */ - /* initialize with summed energy of last subframe */ - Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ]; - for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) { - sumSquared = 0; - for( i = 0; i < dec_subframe_length; i++ ) { - /* The energy will be less than dec_subframe_length * ( silk_int16_MIN / 8 ) ^ 2. */ - /* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */ - x_tmp = silk_RSHIFT( - X[ X_offset[ b ] + i + dec_subframe_offset ], 3 ); - sumSquared = silk_SMLABB( sumSquared, x_tmp, x_tmp ); - - /* Safety check */ - silk_assert( sumSquared >= 0 ); - } - - /* Add/saturate summed energy of current subframe */ - if( s < VAD_INTERNAL_SUBFRAMES - 1 ) { - Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], sumSquared ); - } else { - /* Look-ahead subframe */ - Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], silk_RSHIFT( sumSquared, 1 ) ); - } - - dec_subframe_offset += dec_subframe_length; - } - psSilk_VAD->XnrgSubfr[ b ] = sumSquared; - } - - /********************/ - /* Noise estimation */ - /********************/ - silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD ); - - /***********************************************/ - /* Signal-plus-noise to noise ratio estimation */ - /***********************************************/ - sumSquared = 0; - input_tilt = 0; - for( b = 0; b < VAD_N_BANDS; b++ ) { - speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ]; - if( speech_nrg > 0 ) { - /* Divide, with sufficient resolution */ - if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) { - NrgToNoiseRatio_Q8[ b ] = silk_DIV32( silk_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 ); - } else { - NrgToNoiseRatio_Q8[ b ] = silk_DIV32( Xnrg[ b ], silk_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 ); - } - - /* Convert to log domain */ - SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128; - - /* Sum-of-squares */ - sumSquared = silk_SMLABB( sumSquared, SNR_Q7, SNR_Q7 ); /* Q14 */ - - /* Tilt measure */ - if( speech_nrg < ( (opus_int32)1 << 20 ) ) { - /* Scale down SNR value for small subband speech energies */ - SNR_Q7 = silk_SMULWB( silk_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 ); - } - input_tilt = silk_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 ); - } else { - NrgToNoiseRatio_Q8[ b ] = 256; - } - } - - /* Mean-of-squares */ - sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */ - - /* Root-mean-square approximation, scale to dBs, and write to output pointer */ - pSNR_dB_Q7 = (opus_int16)( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */ - - /*********************************/ - /* Speech Probability Estimation */ - /*********************************/ - SA_Q15 = silk_sigm_Q15( silk_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 ); - - /**************************/ - /* Frequency Tilt Measure */ - /**************************/ - psEncC->input_tilt_Q15 = silk_LSHIFT( silk_sigm_Q15( input_tilt ) - 16384, 1 ); - - /**************************************************/ - /* Scale the sigmoid output based on power levels */ - /**************************************************/ - speech_nrg = 0; - for( b = 0; b < VAD_N_BANDS; b++ ) { - /* Accumulate signal-without-noise energies, higher frequency bands have more weight */ - speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 ); - } - - /* Power scaling */ - if( speech_nrg <= 0 ) { - SA_Q15 = silk_RSHIFT( SA_Q15, 1 ); - } else if( speech_nrg < 32768 ) { - if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { - speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 16 ); - } else { - speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 15 ); - } - - /* square-root */ - speech_nrg = silk_SQRT_APPROX( speech_nrg ); - SA_Q15 = silk_SMULWB( 32768 + speech_nrg, SA_Q15 ); - } - - /* Copy the resulting speech activity in Q8 */ - psEncC->speech_activity_Q8 = silk_min_int( silk_RSHIFT( SA_Q15, 7 ), silk_uint8_MAX ); - - /***********************************/ - /* Energy Level and SNR estimation */ - /***********************************/ - /* Smoothing coefficient */ - smooth_coef_Q16 = silk_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, silk_SMULWB( (opus_int32)SA_Q15, SA_Q15 ) ); - - if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { - smooth_coef_Q16 >>= 1; - } - - for( b = 0; b < VAD_N_BANDS; b++ ) { - /* compute smoothed energy-to-noise ratio per band */ - psSilk_VAD->NrgRatioSmth_Q8[ b ] = silk_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ], - NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 ); - - /* signal to noise ratio in dB per band */ - SNR_Q7 = 3 * ( silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 ); - /* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */ - psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( silk_RSHIFT( SNR_Q7 - 16 * 128, 4 ) ); - } - - RESTORE_STACK; - return( ret ); -} - -/**************************/ -/* Noise level estimation */ -/**************************/ -# if !defined(OPUS_X86_MAY_HAVE_SSE4_1) -static OPUS_INLINE -#endif -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 k; - opus_int32 nl, nrg, inv_nrg; - opus_int coef, min_coef; - - /* Initially faster smoothing */ - if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */ - min_coef = silk_DIV32_16( silk_int16_MAX, silk_RSHIFT( psSilk_VAD->counter, 4 ) + 1 ); - } else { - min_coef = 0; - } - - for( k = 0; k < VAD_N_BANDS; k++ ) { - /* Get old noise level estimate for current band */ - nl = psSilk_VAD->NL[ k ]; - silk_assert( nl >= 0 ); - - /* Add bias */ - nrg = silk_ADD_POS_SAT32( pX[ k ], psSilk_VAD->NoiseLevelBias[ k ] ); - silk_assert( nrg > 0 ); - - /* Invert energies */ - inv_nrg = silk_DIV32( silk_int32_MAX, nrg ); - silk_assert( inv_nrg >= 0 ); - - /* Less update when subband energy is high */ - if( nrg > silk_LSHIFT( nl, 3 ) ) { - coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 >> 3; - } else if( nrg < nl ) { - coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16; - } else { - coef = silk_SMULWB( silk_SMULWW( inv_nrg, nl ), VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 << 1 ); - } - - /* Initially faster smoothing */ - coef = silk_max_int( coef, min_coef ); - - /* Smooth inverse energies */ - psSilk_VAD->inv_NL[ k ] = silk_SMLAWB( psSilk_VAD->inv_NL[ k ], inv_nrg - psSilk_VAD->inv_NL[ k ], coef ); - silk_assert( psSilk_VAD->inv_NL[ k ] >= 0 ); - - /* Compute noise level by inverting again */ - nl = silk_DIV32( silk_int32_MAX, psSilk_VAD->inv_NL[ k ] ); - silk_assert( nl >= 0 ); - - /* Limit noise levels (guarantee 7 bits of head room) */ - nl = silk_min( nl, 0x00FFFFFF ); - - /* Store as part of state */ - psSilk_VAD->NL[ k ] = nl; - } - - /* Increment frame counter */ - psSilk_VAD->counter++; -} diff --git a/drivers/opus/silk/VQ_WMat_EC.c b/drivers/opus/silk/VQ_WMat_EC.c deleted file mode 100644 index fec9ee8dde..0000000000 --- a/drivers/opus/silk/VQ_WMat_EC.c +++ /dev/null @@ -1,117 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" - -/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */ -void silk_VQ_WMat_EC_c( - opus_int8 *ind, /* O index of best codebook vector */ - opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */ - opus_int *gain_Q7, /* O sum of absolute LTP coefficients */ - const opus_int16 *in_Q14, /* I input vector to be quantized */ - const opus_int32 *W_Q18, /* I weighting matrix */ - 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 mu_Q9, /* I tradeoff betw. weighted error and rate */ - const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ - opus_int L /* I number of vectors in codebook */ -) -{ - opus_int k, gain_tmp_Q7; - const opus_int8 *cb_row_Q7; - opus_int16 diff_Q14[ 5 ]; - opus_int32 sum1_Q14, sum2_Q16; - - /* Loop over codebook */ - *rate_dist_Q14 = silk_int32_MAX; - cb_row_Q7 = cb_Q7; - for( k = 0; k < L; k++ ) { - gain_tmp_Q7 = cb_gain_Q7[k]; - - diff_Q14[ 0 ] = in_Q14[ 0 ] - silk_LSHIFT( cb_row_Q7[ 0 ], 7 ); - diff_Q14[ 1 ] = in_Q14[ 1 ] - silk_LSHIFT( cb_row_Q7[ 1 ], 7 ); - diff_Q14[ 2 ] = in_Q14[ 2 ] - silk_LSHIFT( cb_row_Q7[ 2 ], 7 ); - diff_Q14[ 3 ] = in_Q14[ 3 ] - silk_LSHIFT( cb_row_Q7[ 3 ], 7 ); - diff_Q14[ 4 ] = in_Q14[ 4 ] - silk_LSHIFT( cb_row_Q7[ 4 ], 7 ); - - /* Weighted rate */ - sum1_Q14 = silk_SMULBB( mu_Q9, cl_Q5[ k ] ); - - /* Penalty for too large gain */ - sum1_Q14 = silk_ADD_LSHIFT32( sum1_Q14, silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 10 ); - - silk_assert( sum1_Q14 >= 0 ); - - /* first row of W_Q18 */ - sum2_Q16 = silk_SMULWB( W_Q18[ 1 ], diff_Q14[ 1 ] ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 2 ], diff_Q14[ 2 ] ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 3 ], diff_Q14[ 3 ] ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 4 ], diff_Q14[ 4 ] ); - sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] ); - sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] ); - - /* second row of W_Q18 */ - sum2_Q16 = silk_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] ); - sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] ); - sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] ); - - /* third row of W_Q18 */ - sum2_Q16 = silk_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] ); - sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] ); - sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] ); - - /* fourth row of W_Q18 */ - sum2_Q16 = silk_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] ); - sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] ); - sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] ); - - /* last row of W_Q18 */ - sum2_Q16 = silk_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] ); - sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] ); - - silk_assert( sum1_Q14 >= 0 ); - - /* find best */ - if( sum1_Q14 < *rate_dist_Q14 ) { - *rate_dist_Q14 = sum1_Q14; - *ind = (opus_int8)k; - *gain_Q7 = gain_tmp_Q7; - } - - /* Go to next cbk vector */ - cb_row_Q7 += LTP_ORDER; - } -} diff --git a/drivers/opus/silk/ana_filt_bank_1.c b/drivers/opus/silk/ana_filt_bank_1.c deleted file mode 100644 index b49bdd90be..0000000000 --- a/drivers/opus/silk/ana_filt_bank_1.c +++ /dev/null @@ -1,71 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" - -/* Coefficients for 2-band filter bank based on first-order allpass filters */ -static opus_int16 A_fb1_20 = 5394 << 1; -static opus_int16 A_fb1_21 = -24290; /* (opus_int16)(20623 << 1) */ - -/* Split signal into 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 */ -) -{ - opus_int k, N2 = silk_RSHIFT( N, 1 ); - opus_int32 in32, X, Y, out_1, out_2; - - /* Internal variables and state are in Q10 format */ - for( k = 0; k < N2; 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, A_fb1_21 ); - out_1 = 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, A_fb1_20 ); - out_2 = silk_ADD32( S[ 1 ], X ); - S[ 1 ] = silk_ADD32( in32, X ); - - /* Add/subtract, convert back to int16 and store to output */ - outL[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_ADD32( out_2, out_1 ), 11 ) ); - outH[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SUB32( out_2, out_1 ), 11 ) ); - } -} diff --git a/drivers/opus/silk/biquad_alt.c b/drivers/opus/silk/biquad_alt.c deleted file mode 100644 index f797d1e709..0000000000 --- a/drivers/opus/silk/biquad_alt.c +++ /dev/null @@ -1,75 +0,0 @@ -/*********************************************************************** -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 * - * */ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" - -/* Second order ARMA filter, alternative implementation */ -void silk_biquad_alt( - 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) */ - opus_int stride /* I Operate on interleaved signal if > 1 */ -) -{ - /* 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 * stride ]; - 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 * stride ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) ); - } -} diff --git a/drivers/opus/silk/bwexpander.c b/drivers/opus/silk/bwexpander.c deleted file mode 100644 index e7cc448520..0000000000 --- a/drivers/opus/silk/bwexpander.c +++ /dev/null @@ -1,48 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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/drivers/opus/silk/bwexpander_32.c b/drivers/opus/silk/bwexpander_32.c deleted file mode 100644 index dedd213b3e..0000000000 --- a/drivers/opus/silk/bwexpander_32.c +++ /dev/null @@ -1,47 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" - -/* 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 */ -) -{ - 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/drivers/opus/silk/check_control_input.c b/drivers/opus/silk/check_control_input.c deleted file mode 100644 index 61a7cc1f33..0000000000 --- a/drivers/opus/silk/check_control_input.c +++ /dev/null @@ -1,103 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/silk/control.h" -#include "opus/silk/errors.h" - -/* Check encoder control struct */ -opus_int check_control_input( - silk_EncControlStruct *encControl /* I Control structure */ -) -{ - silk_assert( encControl != NULL ); - - if( ( ( encControl->API_sampleRate != 8000 ) && - ( encControl->API_sampleRate != 12000 ) && - ( encControl->API_sampleRate != 16000 ) && - ( encControl->API_sampleRate != 24000 ) && - ( encControl->API_sampleRate != 32000 ) && - ( encControl->API_sampleRate != 44100 ) && - ( encControl->API_sampleRate != 48000 ) ) || - ( ( encControl->desiredInternalSampleRate != 8000 ) && - ( encControl->desiredInternalSampleRate != 12000 ) && - ( encControl->desiredInternalSampleRate != 16000 ) ) || - ( ( encControl->maxInternalSampleRate != 8000 ) && - ( encControl->maxInternalSampleRate != 12000 ) && - ( encControl->maxInternalSampleRate != 16000 ) ) || - ( ( encControl->minInternalSampleRate != 8000 ) && - ( encControl->minInternalSampleRate != 12000 ) && - ( encControl->minInternalSampleRate != 16000 ) ) || - ( encControl->minInternalSampleRate > encControl->desiredInternalSampleRate ) || - ( encControl->maxInternalSampleRate < encControl->desiredInternalSampleRate ) || - ( encControl->minInternalSampleRate > encControl->maxInternalSampleRate ) ) { - silk_assert( 0 ); - return SILK_ENC_FS_NOT_SUPPORTED; - } - if( encControl->payloadSize_ms != 10 && - encControl->payloadSize_ms != 20 && - encControl->payloadSize_ms != 40 && - encControl->payloadSize_ms != 60 ) { - silk_assert( 0 ); - return SILK_ENC_PACKET_SIZE_NOT_SUPPORTED; - } - if( encControl->packetLossPercentage < 0 || encControl->packetLossPercentage > 100 ) { - silk_assert( 0 ); - return SILK_ENC_INVALID_LOSS_RATE; - } - if( encControl->useDTX < 0 || encControl->useDTX > 1 ) { - silk_assert( 0 ); - return SILK_ENC_INVALID_DTX_SETTING; - } - if( encControl->useCBR < 0 || encControl->useCBR > 1 ) { - silk_assert( 0 ); - return SILK_ENC_INVALID_CBR_SETTING; - } - if( encControl->useInBandFEC < 0 || encControl->useInBandFEC > 1 ) { - silk_assert( 0 ); - return SILK_ENC_INVALID_INBAND_FEC_SETTING; - } - if( encControl->nChannelsAPI < 1 || encControl->nChannelsAPI > ENCODER_NUM_CHANNELS ) { - silk_assert( 0 ); - return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; - } - if( encControl->nChannelsInternal < 1 || encControl->nChannelsInternal > ENCODER_NUM_CHANNELS ) { - silk_assert( 0 ); - return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; - } - if( encControl->nChannelsInternal > encControl->nChannelsAPI ) { - silk_assert( 0 ); - return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; - } - if( encControl->complexity < 0 || encControl->complexity > 10 ) { - silk_assert( 0 ); - return SILK_ENC_INVALID_COMPLEXITY_SETTING; - } - - return SILK_NO_ERROR; -} diff --git a/drivers/opus/silk/code_signs.c b/drivers/opus/silk/code_signs.c deleted file mode 100644 index 79c1893514..0000000000 --- a/drivers/opus/silk/code_signs.c +++ /dev/null @@ -1,112 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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/drivers/opus/silk/control.h b/drivers/opus/silk/control.h deleted file mode 100644 index 4b20c4a8b8..0000000000 --- a/drivers/opus/silk/control.h +++ /dev/null @@ -1,142 +0,0 @@ -/*********************************************************************** -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 "opus/silk/typedef.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* 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 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; - -} 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; -} silk_DecControlStruct; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/opus/silk/control_SNR.c b/drivers/opus/silk/control_SNR.c deleted file mode 100644 index 5aebfcf385..0000000000 --- a/drivers/opus/silk/control_SNR.c +++ /dev/null @@ -1,73 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/silk/tuning_parameters.h" - -/* Control SNR of redidual 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) */ -) -{ - opus_int k, ret = SILK_NO_ERROR; - opus_int32 frac_Q6; - const opus_int32 *rateTable; - - /* Set bitrate/coding quality */ - TargetRate_bps = silk_LIMIT( TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS ); - if( TargetRate_bps != psEncC->TargetRate_bps ) { - psEncC->TargetRate_bps = TargetRate_bps; - - /* If new TargetRate_bps, translate to SNR_dB value */ - if( psEncC->fs_kHz == 8 ) { - rateTable = silk_TargetRate_table_NB; - } else if( psEncC->fs_kHz == 12 ) { - rateTable = silk_TargetRate_table_MB; - } else { - rateTable = silk_TargetRate_table_WB; - } - - /* Reduce bitrate for 10 ms modes in these calculations */ - if( psEncC->nb_subfr == 2 ) { - TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS; - } - - /* Find bitrate interval in table and interpolate */ - for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) { - if( TargetRate_bps <= rateTable[ k ] ) { - frac_Q6 = silk_DIV32( silk_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ), - rateTable[ k ] - rateTable[ k - 1 ] ); - psEncC->SNR_dB_Q7 = silk_LSHIFT( silk_SNR_table_Q1[ k - 1 ], 6 ) + silk_MUL( frac_Q6, silk_SNR_table_Q1[ k ] - silk_SNR_table_Q1[ k - 1 ] ); - break; - } - } - } - - return ret; -} diff --git a/drivers/opus/silk/control_audio_bandwidth.c b/drivers/opus/silk/control_audio_bandwidth.c deleted file mode 100644 index 04640f53fe..0000000000 --- a/drivers/opus/silk/control_audio_bandwidth.c +++ /dev/null @@ -1,123 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/silk/tuning_parameters.h" - -/* 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 */ -) -{ - opus_int fs_kHz; - opus_int32 fs_Hz; - - fs_kHz = psEncC->fs_kHz; - fs_Hz = silk_SMULBB( fs_kHz, 1000 ); - if( fs_Hz == 0 ) { - /* Encoder has just been initialized */ - fs_Hz = silk_min( psEncC->desiredInternal_fs_Hz, psEncC->API_fs_Hz ); - fs_kHz = silk_DIV32_16( fs_Hz, 1000 ); - } else if( fs_Hz > psEncC->API_fs_Hz || fs_Hz > psEncC->maxInternal_fs_Hz || fs_Hz < psEncC->minInternal_fs_Hz ) { - /* Make sure internal rate is not higher than external rate or maximum allowed, or lower than minimum allowed */ - fs_Hz = psEncC->API_fs_Hz; - fs_Hz = silk_min( fs_Hz, psEncC->maxInternal_fs_Hz ); - fs_Hz = silk_max( fs_Hz, psEncC->minInternal_fs_Hz ); - fs_kHz = silk_DIV32_16( fs_Hz, 1000 ); - } else { - /* State machine for the internal sampling rate switching */ - if( psEncC->sLP.transition_frame_no >= TRANSITION_FRAMES ) { - /* Stop transition phase */ - psEncC->sLP.mode = 0; - } - if( psEncC->allow_bandwidth_switch || encControl->opusCanSwitch ) { - /* Check if we should switch down */ - if( silk_SMULBB( psEncC->fs_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz ) - { - /* Switch down */ - if( psEncC->sLP.mode == 0 ) { - /* New transition */ - psEncC->sLP.transition_frame_no = TRANSITION_FRAMES; - - /* Reset transition filter state */ - silk_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) ); - } - if( encControl->opusCanSwitch ) { - /* Stop transition phase */ - psEncC->sLP.mode = 0; - - /* Switch to a lower sample frequency */ - fs_kHz = psEncC->fs_kHz == 16 ? 12 : 8; - } else { - if( psEncC->sLP.transition_frame_no <= 0 ) { - encControl->switchReady = 1; - /* Make room for redundancy */ - encControl->maxBits -= encControl->maxBits * 5 / ( encControl->payloadSize_ms + 5 ); - } else { - /* Direction: down (at double speed) */ - psEncC->sLP.mode = -2; - } - } - } - else - /* Check if we should switch up */ - if( silk_SMULBB( psEncC->fs_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz ) - { - /* Switch up */ - if( encControl->opusCanSwitch ) { - /* Switch to a higher sample frequency */ - fs_kHz = psEncC->fs_kHz == 8 ? 12 : 16; - - /* New transition */ - psEncC->sLP.transition_frame_no = 0; - - /* Reset transition filter state */ - silk_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) ); - - /* Direction: up */ - psEncC->sLP.mode = 1; - } else { - if( psEncC->sLP.mode == 0 ) { - encControl->switchReady = 1; - /* Make room for redundancy */ - encControl->maxBits -= encControl->maxBits * 5 / ( encControl->payloadSize_ms + 5 ); - } else { - /* Direction: up */ - psEncC->sLP.mode = 1; - } - } - } else { - if (psEncC->sLP.mode<0) - psEncC->sLP.mode = 1; - } - } - } - - return fs_kHz; -} diff --git a/drivers/opus/silk/control_codec.c b/drivers/opus/silk/control_codec.c deleted file mode 100644 index 03caab36a9..0000000000 --- a/drivers/opus/silk/control_codec.c +++ /dev/null @@ -1,425 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" -#ifdef OPUS_FIXED_POINT -#include "opus/silk/fixed/main_FIX.h" -#define silk_encoder_state_Fxx silk_encoder_state_FIX -#else -#include "opus/silk/float/main_FLP.h" -#define silk_encoder_state_Fxx silk_encoder_state_FLP -#endif -#include "opus/celt/stack_alloc.h" -#include "opus/silk/tuning_parameters.h" -#include "opus/silk/pitch_est_defines.h" - -static opus_int silk_setup_resamplers( - silk_encoder_state_Fxx *psEnc, /* I/O */ - opus_int fs_kHz /* I */ -); - -static opus_int silk_setup_fs( - silk_encoder_state_Fxx *psEnc, /* I/O */ - opus_int fs_kHz, /* I */ - opus_int PacketSize_ms /* I */ -); - -static opus_int silk_setup_complexity( - silk_encoder_state *psEncC, /* I/O */ - opus_int Complexity /* I */ -); - -static OPUS_INLINE opus_int silk_setup_LBRR( - silk_encoder_state *psEncC, /* I/O */ - const opus_int32 TargetRate_bps /* I */ -); - - -/* Control 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_int32 TargetRate_bps, /* I Target max bitrate (bps) */ - 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 -) -{ - opus_int fs_kHz, ret = 0; - - psEnc->sCmn.useDTX = encControl->useDTX; - psEnc->sCmn.useCBR = encControl->useCBR; - psEnc->sCmn.API_fs_Hz = encControl->API_sampleRate; - psEnc->sCmn.maxInternal_fs_Hz = encControl->maxInternalSampleRate; - psEnc->sCmn.minInternal_fs_Hz = encControl->minInternalSampleRate; - psEnc->sCmn.desiredInternal_fs_Hz = encControl->desiredInternalSampleRate; - psEnc->sCmn.useInBandFEC = encControl->useInBandFEC; - psEnc->sCmn.nChannelsAPI = encControl->nChannelsAPI; - psEnc->sCmn.nChannelsInternal = encControl->nChannelsInternal; - psEnc->sCmn.allow_bandwidth_switch = allow_bw_switch; - psEnc->sCmn.channelNb = channelNb; - - if( psEnc->sCmn.controlled_since_last_payload != 0 && psEnc->sCmn.prefillFlag == 0 ) { - if( psEnc->sCmn.API_fs_Hz != psEnc->sCmn.prev_API_fs_Hz && psEnc->sCmn.fs_kHz > 0 ) { - /* Change in API sampling rate in the middle of encoding a packet */ - ret += silk_setup_resamplers( psEnc, psEnc->sCmn.fs_kHz ); - } - return ret; - } - - /* Beyond this point we know that there are no previously coded frames in the payload buffer */ - - /********************************************/ - /* Determine internal sampling rate */ - /********************************************/ - fs_kHz = silk_control_audio_bandwidth( &psEnc->sCmn, encControl ); - if( force_fs_kHz ) { - fs_kHz = force_fs_kHz; - } - /********************************************/ - /* Prepare resampler and buffered data */ - /********************************************/ - ret += silk_setup_resamplers( psEnc, fs_kHz ); - - /********************************************/ - /* Set internal sampling frequency */ - /********************************************/ - ret += silk_setup_fs( psEnc, fs_kHz, encControl->payloadSize_ms ); - - /********************************************/ - /* Set encoding complexity */ - /********************************************/ - ret += silk_setup_complexity( &psEnc->sCmn, encControl->complexity ); - - /********************************************/ - /* Set packet loss rate measured by farend */ - /********************************************/ - psEnc->sCmn.PacketLoss_perc = encControl->packetLossPercentage; - - /********************************************/ - /* Set LBRR usage */ - /********************************************/ - ret += silk_setup_LBRR( &psEnc->sCmn, TargetRate_bps ); - - psEnc->sCmn.controlled_since_last_payload = 1; - - return ret; -} - -static opus_int silk_setup_resamplers( - silk_encoder_state_Fxx *psEnc, /* I/O */ - opus_int fs_kHz /* I */ -) -{ - opus_int ret = SILK_NO_ERROR; - SAVE_STACK; - - if( psEnc->sCmn.fs_kHz != fs_kHz || psEnc->sCmn.prev_API_fs_Hz != psEnc->sCmn.API_fs_Hz ) - { - if( psEnc->sCmn.fs_kHz == 0 ) { - /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ - ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000, 1 ); - } else { - VARDECL( opus_int16, x_buf_API_fs_Hz ); - VARDECL( silk_resampler_state_struct, temp_resampler_state ); -#ifdef OPUS_FIXED_POINT - opus_int16 *x_bufFIX = psEnc->x_buf; -#else - VARDECL( opus_int16, x_bufFIX ); - opus_int32 new_buf_samples; -#endif - opus_int32 api_buf_samples; - opus_int32 old_buf_samples; - opus_int32 buf_length_ms; - - buf_length_ms = silk_LSHIFT( psEnc->sCmn.nb_subfr * 5, 1 ) + LA_SHAPE_MS; - old_buf_samples = buf_length_ms * psEnc->sCmn.fs_kHz; - -#ifndef OPUS_FIXED_POINT - new_buf_samples = buf_length_ms * fs_kHz; - ALLOC( x_bufFIX, silk_max( old_buf_samples, new_buf_samples ), - opus_int16 ); - silk_float2short_array( x_bufFIX, psEnc->x_buf, old_buf_samples ); -#endif - - /* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */ - ALLOC( temp_resampler_state, 1, silk_resampler_state_struct ); - ret += silk_resampler_init( temp_resampler_state, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz, 0 ); - - /* Calculate number of samples to temporarily upsample */ - api_buf_samples = buf_length_ms * silk_DIV32_16( psEnc->sCmn.API_fs_Hz, 1000 ); - - /* Temporary resampling of x_buf data to API_fs_Hz */ - ALLOC( x_buf_API_fs_Hz, api_buf_samples, opus_int16 ); - ret += silk_resampler( temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, old_buf_samples ); - - /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ - ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, silk_SMULBB( fs_kHz, 1000 ), 1 ); - - /* Correct resampler state by resampling buffered data from API_fs_Hz to fs_kHz */ - ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, api_buf_samples ); - -#ifndef OPUS_FIXED_POINT - silk_short2float_array( psEnc->x_buf, x_bufFIX, new_buf_samples); -#endif - } - } - - psEnc->sCmn.prev_API_fs_Hz = psEnc->sCmn.API_fs_Hz; - - RESTORE_STACK; - return ret; -} - -static opus_int silk_setup_fs( - silk_encoder_state_Fxx *psEnc, /* I/O */ - opus_int fs_kHz, /* I */ - opus_int PacketSize_ms /* I */ -) -{ - opus_int ret = SILK_NO_ERROR; - - /* Set packet size */ - if( PacketSize_ms != psEnc->sCmn.PacketSize_ms ) { - if( ( PacketSize_ms != 10 ) && - ( PacketSize_ms != 20 ) && - ( PacketSize_ms != 40 ) && - ( PacketSize_ms != 60 ) ) { - ret = SILK_ENC_PACKET_SIZE_NOT_SUPPORTED; - } - if( PacketSize_ms <= 10 ) { - psEnc->sCmn.nFramesPerPacket = 1; - psEnc->sCmn.nb_subfr = PacketSize_ms == 10 ? 2 : 1; - psEnc->sCmn.frame_length = silk_SMULBB( PacketSize_ms, fs_kHz ); - psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz ); - if( psEnc->sCmn.fs_kHz == 8 ) { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; - } else { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; - } - } else { - psEnc->sCmn.nFramesPerPacket = silk_DIV32_16( PacketSize_ms, MAX_FRAME_LENGTH_MS ); - psEnc->sCmn.nb_subfr = MAX_NB_SUBFR; - psEnc->sCmn.frame_length = silk_SMULBB( 20, fs_kHz ); - psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz ); - if( psEnc->sCmn.fs_kHz == 8 ) { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; - } else { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF; - } - } - psEnc->sCmn.PacketSize_ms = PacketSize_ms; - psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */ - } - - /* Set internal sampling frequency */ - silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 ); - silk_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 ); - if( psEnc->sCmn.fs_kHz != fs_kHz ) { - /* reset part of the state */ - silk_memset( &psEnc->sShape, 0, sizeof( psEnc->sShape ) ); - silk_memset( &psEnc->sPrefilt, 0, sizeof( psEnc->sPrefilt ) ); - silk_memset( &psEnc->sCmn.sNSQ, 0, sizeof( psEnc->sCmn.sNSQ ) ); - silk_memset( psEnc->sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) ); - silk_memset( &psEnc->sCmn.sLP.In_LP_State, 0, sizeof( psEnc->sCmn.sLP.In_LP_State ) ); - psEnc->sCmn.inputBufIx = 0; - psEnc->sCmn.nFramesEncoded = 0; - psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */ - - /* Initialize non-zero parameters */ - psEnc->sCmn.prevLag = 100; - psEnc->sCmn.first_frame_after_reset = 1; - psEnc->sPrefilt.lagPrev = 100; - psEnc->sShape.LastGainIndex = 10; - psEnc->sCmn.sNSQ.lagPrev = 100; - psEnc->sCmn.sNSQ.prev_gain_Q16 = 65536; - psEnc->sCmn.prevSignalType = TYPE_NO_VOICE_ACTIVITY; - - psEnc->sCmn.fs_kHz = fs_kHz; - if( psEnc->sCmn.fs_kHz == 8 ) { - if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; - } else { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; - } - } else { - if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF; - } else { - psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; - } - } - if( psEnc->sCmn.fs_kHz == 8 || psEnc->sCmn.fs_kHz == 12 ) { - psEnc->sCmn.predictLPCOrder = MIN_LPC_ORDER; - psEnc->sCmn.psNLSF_CB = &silk_NLSF_CB_NB_MB; - } else { - psEnc->sCmn.predictLPCOrder = MAX_LPC_ORDER; - psEnc->sCmn.psNLSF_CB = &silk_NLSF_CB_WB; - } - psEnc->sCmn.subfr_length = SUB_FRAME_LENGTH_MS * fs_kHz; - psEnc->sCmn.frame_length = silk_SMULBB( psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr ); - psEnc->sCmn.ltp_mem_length = silk_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz ); - psEnc->sCmn.la_pitch = silk_SMULBB( LA_PITCH_MS, fs_kHz ); - psEnc->sCmn.max_pitch_lag = silk_SMULBB( 18, fs_kHz ); - if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { - psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz ); - } else { - psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz ); - } - if( psEnc->sCmn.fs_kHz == 16 ) { - psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_WB, 9 ); - psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform8_iCDF; - } else if( psEnc->sCmn.fs_kHz == 12 ) { - psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_MB, 9 ); - psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform6_iCDF; - } else { - psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_NB, 9 ); - psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform4_iCDF; - } - } - - /* Check that settings are valid */ - silk_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length ); - - return ret; -} - -static opus_int silk_setup_complexity( - silk_encoder_state *psEncC, /* I/O */ - opus_int Complexity /* I */ -) -{ - opus_int ret = 0; - - /* Set encoding complexity */ - silk_assert( Complexity >= 0 && Complexity <= 10 ); - if( Complexity < 2 ) { - psEncC->pitchEstimationComplexity = SILK_PE_MIN_COMPLEX; - psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.8, 16 ); - psEncC->pitchEstimationLPCOrder = 6; - psEncC->shapingLPCOrder = 8; - psEncC->la_shape = 3 * psEncC->fs_kHz; - psEncC->nStatesDelayedDecision = 1; - psEncC->useInterpolatedNLSFs = 0; - psEncC->LTPQuantLowComplexity = 1; - psEncC->NLSF_MSVQ_Survivors = 2; - psEncC->warping_Q16 = 0; - } else if( Complexity < 4 ) { - psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; - psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.76, 16 ); - psEncC->pitchEstimationLPCOrder = 8; - psEncC->shapingLPCOrder = 10; - psEncC->la_shape = 5 * psEncC->fs_kHz; - psEncC->nStatesDelayedDecision = 1; - psEncC->useInterpolatedNLSFs = 0; - psEncC->LTPQuantLowComplexity = 0; - psEncC->NLSF_MSVQ_Survivors = 4; - psEncC->warping_Q16 = 0; - } else if( Complexity < 6 ) { - psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; - psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.74, 16 ); - psEncC->pitchEstimationLPCOrder = 10; - psEncC->shapingLPCOrder = 12; - psEncC->la_shape = 5 * psEncC->fs_kHz; - psEncC->nStatesDelayedDecision = 2; - psEncC->useInterpolatedNLSFs = 1; - psEncC->LTPQuantLowComplexity = 0; - psEncC->NLSF_MSVQ_Survivors = 8; - psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); - } else if( Complexity < 8 ) { - psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; - psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.72, 16 ); - psEncC->pitchEstimationLPCOrder = 12; - psEncC->shapingLPCOrder = 14; - psEncC->la_shape = 5 * psEncC->fs_kHz; - psEncC->nStatesDelayedDecision = 3; - psEncC->useInterpolatedNLSFs = 1; - psEncC->LTPQuantLowComplexity = 0; - psEncC->NLSF_MSVQ_Survivors = 16; - psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); - } else { - psEncC->pitchEstimationComplexity = SILK_PE_MAX_COMPLEX; - psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.7, 16 ); - psEncC->pitchEstimationLPCOrder = 16; - psEncC->shapingLPCOrder = 16; - psEncC->la_shape = 5 * psEncC->fs_kHz; - psEncC->nStatesDelayedDecision = MAX_DEL_DEC_STATES; - psEncC->useInterpolatedNLSFs = 1; - psEncC->LTPQuantLowComplexity = 0; - psEncC->NLSF_MSVQ_Survivors = 32; - psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); - } - - /* Do not allow higher pitch estimation LPC order than predict LPC order */ - psEncC->pitchEstimationLPCOrder = silk_min_int( psEncC->pitchEstimationLPCOrder, psEncC->predictLPCOrder ); - psEncC->shapeWinLength = SUB_FRAME_LENGTH_MS * psEncC->fs_kHz + 2 * psEncC->la_shape; - psEncC->Complexity = Complexity; - - silk_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER ); - silk_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER ); - silk_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES ); - silk_assert( psEncC->warping_Q16 <= 32767 ); - silk_assert( psEncC->la_shape <= LA_SHAPE_MAX ); - silk_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX ); - silk_assert( psEncC->NLSF_MSVQ_Survivors <= NLSF_VQ_MAX_SURVIVORS ); - - return ret; -} - -static OPUS_INLINE opus_int silk_setup_LBRR( - silk_encoder_state *psEncC, /* I/O */ - const opus_int32 TargetRate_bps /* I */ -) -{ - opus_int LBRR_in_previous_packet, ret = SILK_NO_ERROR; - opus_int32 LBRR_rate_thres_bps; - - LBRR_in_previous_packet = psEncC->LBRR_enabled; - psEncC->LBRR_enabled = 0; - if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) { - if( psEncC->fs_kHz == 8 ) { - LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS; - } else if( psEncC->fs_kHz == 12 ) { - LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS; - } else { - LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS; - } - LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps, 125 - silk_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) ); - - if( TargetRate_bps > LBRR_rate_thres_bps ) { - /* Set gain increase for coding LBRR excitation */ - if( LBRR_in_previous_packet == 0 ) { - /* Previous packet did not have LBRR, and was therefore coded at a higher bitrate */ - psEncC->LBRR_GainIncreases = 7; - } else { - psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 ); - } - psEncC->LBRR_enabled = 1; - } - } - - return ret; -} diff --git a/drivers/opus/silk/debug.c b/drivers/opus/silk/debug.c deleted file mode 100644 index ffb3f811a1..0000000000 --- a/drivers/opus/silk/debug.c +++ /dev/null @@ -1,167 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/debug.h" -#include "opus/silk/SigProc_FIX.h" - -#if SILK_TIC_TOC - -#ifdef _WIN32 - -#if (defined(_WIN32) || defined(_WINCE)) -#include <windows.h> /* timer */ -#else /* Linux or Mac*/ -#include <sys/time.h> -#endif - -unsigned long silk_GetHighResolutionTime(void) /* O time in usec*/ -{ - /* Returns a time counter in microsec */ - /* the resolution is platform dependent */ - /* but is typically 1.62 us resolution */ - LARGE_INTEGER lpPerformanceCount; - LARGE_INTEGER lpFrequency; - QueryPerformanceCounter(&lpPerformanceCount); - QueryPerformanceFrequency(&lpFrequency); - return (unsigned long)((1000000*(lpPerformanceCount.QuadPart)) / lpFrequency.QuadPart); -} -#else /* Linux or Mac*/ -unsigned long GetHighResolutionTime(void) /* O time in usec*/ -{ - struct timeval tv; - gettimeofday(&tv, 0); - return((tv.tv_sec*1000000)+(tv.tv_usec)); -} -#endif - -int silk_Timer_nTimers = 0; -int silk_Timer_depth_ctr = 0; -char silk_Timer_tags[silk_NUM_TIMERS_MAX][silk_NUM_TIMERS_MAX_TAG_LEN]; -#ifdef WIN32 -LARGE_INTEGER silk_Timer_start[silk_NUM_TIMERS_MAX]; -#else -unsigned long silk_Timer_start[silk_NUM_TIMERS_MAX]; -#endif -unsigned int silk_Timer_cnt[silk_NUM_TIMERS_MAX]; -opus_int64 silk_Timer_min[silk_NUM_TIMERS_MAX]; -opus_int64 silk_Timer_sum[silk_NUM_TIMERS_MAX]; -opus_int64 silk_Timer_max[silk_NUM_TIMERS_MAX]; -opus_int64 silk_Timer_depth[silk_NUM_TIMERS_MAX]; - -#ifdef WIN32 -void silk_TimerSave(char *file_name) -{ - if( silk_Timer_nTimers > 0 ) - { - int k; - FILE *fp; - LARGE_INTEGER lpFrequency; - LARGE_INTEGER lpPerformanceCount1, lpPerformanceCount2; - int del = 0x7FFFFFFF; - double avg, sum_avg; - /* estimate overhead of calling performance counters */ - for( k = 0; k < 1000; k++ ) { - QueryPerformanceCounter(&lpPerformanceCount1); - QueryPerformanceCounter(&lpPerformanceCount2); - lpPerformanceCount2.QuadPart -= lpPerformanceCount1.QuadPart; - if( (int)lpPerformanceCount2.LowPart < del ) - del = lpPerformanceCount2.LowPart; - } - QueryPerformanceFrequency(&lpFrequency); - /* print results to file */ - sum_avg = 0.0f; - for( k = 0; k < silk_Timer_nTimers; k++ ) { - if (silk_Timer_depth[k] == 0) { - sum_avg += (1e6 * silk_Timer_sum[k] / silk_Timer_cnt[k] - del) / lpFrequency.QuadPart * silk_Timer_cnt[k]; - } - } - fp = fopen(file_name, "w"); - fprintf(fp, " min avg %% max count\n"); - for( k = 0; k < silk_Timer_nTimers; k++ ) { - if (silk_Timer_depth[k] == 0) { - fprintf(fp, "%-28s", silk_Timer_tags[k]); - } else if (silk_Timer_depth[k] == 1) { - fprintf(fp, " %-27s", silk_Timer_tags[k]); - } else if (silk_Timer_depth[k] == 2) { - fprintf(fp, " %-26s", silk_Timer_tags[k]); - } else if (silk_Timer_depth[k] == 3) { - fprintf(fp, " %-25s", silk_Timer_tags[k]); - } else { - fprintf(fp, " %-24s", silk_Timer_tags[k]); - } - avg = (1e6 * silk_Timer_sum[k] / silk_Timer_cnt[k] - del) / lpFrequency.QuadPart; - fprintf(fp, "%8.2f", (1e6 * (silk_max_64(silk_Timer_min[k] - del, 0))) / lpFrequency.QuadPart); - fprintf(fp, "%12.2f %6.2f", avg, 100.0 * avg / sum_avg * silk_Timer_cnt[k]); - fprintf(fp, "%12.2f", (1e6 * (silk_max_64(silk_Timer_max[k] - del, 0))) / lpFrequency.QuadPart); - fprintf(fp, "%10d\n", silk_Timer_cnt[k]); - } - fprintf(fp, " microseconds\n"); - fclose(fp); - } -} -#else -void silk_TimerSave(char *file_name) -{ - if( silk_Timer_nTimers > 0 ) - { - int k; - FILE *fp; - /* print results to file */ - fp = fopen(file_name, "w"); - fprintf(fp, " min avg max count\n"); - for( k = 0; k < silk_Timer_nTimers; k++ ) - { - if (silk_Timer_depth[k] == 0) { - fprintf(fp, "%-28s", silk_Timer_tags[k]); - } else if (silk_Timer_depth[k] == 1) { - fprintf(fp, " %-27s", silk_Timer_tags[k]); - } else if (silk_Timer_depth[k] == 2) { - fprintf(fp, " %-26s", silk_Timer_tags[k]); - } else if (silk_Timer_depth[k] == 3) { - fprintf(fp, " %-25s", silk_Timer_tags[k]); - } else { - fprintf(fp, " %-24s", silk_Timer_tags[k]); - } - fprintf(fp, "%d ", silk_Timer_min[k]); - fprintf(fp, "%f ", (double)silk_Timer_sum[k] / (double)silk_Timer_cnt[k]); - fprintf(fp, "%d ", silk_Timer_max[k]); - fprintf(fp, "%10d\n", silk_Timer_cnt[k]); - } - fprintf(fp, " microseconds\n"); - fclose(fp); - } -} -#endif - -#endif /* SILK_TIC_TOC */ - -#if SILK_DEBUG -FILE *silk_debug_store_fp[ silk_NUM_STORES_MAX ]; -int silk_debug_store_count = 0; -#endif /* SILK_DEBUG */ - diff --git a/drivers/opus/silk/debug.h b/drivers/opus/silk/debug.h deleted file mode 100644 index d2eccfa1e4..0000000000 --- a/drivers/opus/silk/debug.h +++ /dev/null @@ -1,279 +0,0 @@ -/*********************************************************************** -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 - -#include "opus/silk/typedef.h" -#include <stdio.h> /* file writing */ -#include <string.h> /* strcpy, strcmp */ - -#ifdef __cplusplus -extern "C" -{ -#endif - -unsigned long GetHighResolutionTime(void); /* O time in usec*/ - -/* make SILK_DEBUG dependent on compiler's _DEBUG */ -#if defined _WIN32 - #ifdef _DEBUG - #define SILK_DEBUG 1 - #else - #define SILK_DEBUG 0 - #endif - - /* overrule the above */ - #if 0 - /* #define NO_ASSERTS*/ - #undef SILK_DEBUG - #define SILK_DEBUG 1 - #endif -#else - #define SILK_DEBUG 0 -#endif - -/* Flag for using timers */ -#define SILK_TIC_TOC 0 - - -#if SILK_TIC_TOC - -#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 */ - -#ifdef __cplusplus -} -#endif - -#endif /* SILK_DEBUG_H */ diff --git a/drivers/opus/silk/dec_API.c b/drivers/opus/silk/dec_API.c deleted file mode 100644 index 2fd681c0d2..0000000000 --- a/drivers/opus/silk/dec_API.c +++ /dev/null @@ -1,416 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" -#include "opus/silk/API.h" -#include "opus/silk/main.h" -#include "opus/celt/stack_alloc.h" -#include "opus/celt/os_support.h" - -/************************/ -/* 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; -} silk_decoder; - -/*********************/ -/* Decoder functions */ -/*********************/ - -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_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; - - 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_int16 *samplesOut, /* O Decoded output speech vector */ - opus_int32 *nSamplesOut, /* O Number of samples decoded */ - 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, samplesOut1_tmp_storage2 ); - 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; - int delay_stack_alloc; - SAVE_STACK; - - silk_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 { - silk_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 ) { - silk_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. */ - delay_stack_alloc = decControl->internalSampleRate*decControl->nChannelsInternal - < decControl->API_sampleRate*decControl->nChannelsAPI; - ALLOC( samplesOut1_tmp_storage1, delay_stack_alloc ? ALLOC_NONE - : decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2 ), - opus_int16 ); - if ( delay_stack_alloc ) - { - samplesOut1_tmp[ 0 ] = samplesOut; - samplesOut1_tmp[ 1 ] = samplesOut + channel_state[ 0 ].frame_length + 2; - } else { - 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 ); - } - /* 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; - } - ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag, condCoding, 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, - decControl->nChannelsAPI == 2 ? *nSamplesOut : ALLOC_NONE, opus_int16 ); - if( decControl->nChannelsAPI == 2 ) { - resample_out_ptr = samplesOut2_tmp; - } else { - resample_out_ptr = samplesOut; - } - - ALLOC( samplesOut1_tmp_storage2, delay_stack_alloc - ? decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2 ) - : ALLOC_NONE, - opus_int16 ); - if ( delay_stack_alloc ) { - OPUS_COPY(samplesOut1_tmp_storage2, samplesOut, decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2)); - samplesOut1_tmp[ 0 ] = samplesOut1_tmp_storage2; - samplesOut1_tmp[ 1 ] = samplesOut1_tmp_storage2 + channel_state[ 0 ].frame_length + 2; - } - for( n = 0; n < silk_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) { - - /* Resample decoded signal to API_sampleRate */ - ret += silk_resampler( &channel_state[ n ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec ); - - /* Interleave if stereo output and stereo stream */ - if( decControl->nChannelsAPI == 2 ) { - for( i = 0; i < *nSamplesOut; i++ ) { - samplesOut[ n + 2 * i ] = resample_out_ptr[ i ]; - } - } - } - - /* 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 ] = 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/drivers/opus/silk/decode_core.c b/drivers/opus/silk/decode_core.c deleted file mode 100644 index 8ca1adffdd..0000000000 --- a/drivers/opus/silk/decode_core.c +++ /dev/null @@ -1,236 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/celt/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 ); - ALLOC( sLPC_Q14, psDec->subfr_length + MAX_LPC_ORDER, opus_int32 ); - - 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 coeficients 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; - silk_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 */ - silk_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_LSHIFT32( pres_Q14[ i ], 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 ) ); - } - - /* DEBUG_STORE_DATA( dec.pcm, pxq, psDec->subfr_length * sizeof( opus_int16 ) ) */ - - /* 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/drivers/opus/silk/decode_frame.c b/drivers/opus/silk/decode_frame.c deleted file mode 100644 index 18e2bc9b1a..0000000000 --- a/drivers/opus/silk/decode_frame.c +++ /dev/null @@ -1,126 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/celt/stack_alloc.h" -#include "opus/silk/PLC.h" - -/****************/ -/* 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 */ - 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 */ - silk_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 ); - 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 PLC state */ - /********************************************************/ - silk_PLC( psDec, psDecCtrl, pOut, 0, arch ); - - psDec->lossCnt = 0; - psDec->prevSignalType = psDec->indices.signalType; - silk_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, arch ); - } - - /*************************/ - /* Update output buffer. */ - /*************************/ - silk_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/drivers/opus/silk/decode_indices.c b/drivers/opus/silk/decode_indices.c deleted file mode 100644 index fa8066e5f7..0000000000 --- a/drivers/opus/silk/decode_indices.c +++ /dev/null @@ -1,148 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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 ] ); - silk_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 countour 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/drivers/opus/silk/decode_parameters.c b/drivers/opus/silk/decode_parameters.c deleted file mode 100644 index d17cb8a3df..0000000000 --- a/drivers/opus/silk/decode_parameters.c +++ /dev/null @@ -1,112 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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 ); - - /* 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 ); - } 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/drivers/opus/silk/decode_pitch.c b/drivers/opus/silk/decode_pitch.c deleted file mode 100644 index 1d98ee7f33..0000000000 --- a/drivers/opus/silk/decode_pitch.c +++ /dev/null @@ -1,74 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -/*********************************************************** -* Pitch analyser function -********************************************************** */ -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/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 { - silk_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 { - silk_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/drivers/opus/silk/decode_pulses.c b/drivers/opus/silk/decode_pulses.c deleted file mode 100644 index c687d3bfa8..0000000000 --- a/drivers/opus/silk/decode_pulses.c +++ /dev/null @@ -1,112 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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 ) { - silk_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/drivers/opus/silk/decoder_set_fs.c b/drivers/opus/silk/decoder_set_fs.c deleted file mode 100644 index 0079a506ee..0000000000 --- a/drivers/opus/silk/decoder_set_fs.c +++ /dev/null @@ -1,105 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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; - - silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 ); - silk_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 */ - silk_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 */ - silk_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH ); - - return ret; -} - diff --git a/drivers/opus/silk/define.h b/drivers/opus/silk/define.h deleted file mode 100644 index c6165e3cff..0000000000 --- a/drivers/opus/silk/define.h +++ /dev/null @@ -1,235 +0,0 @@ -/*********************************************************************** -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 "opus/silk/errors.h" -#include "opus/silk/typedef.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* 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 -#define TARGET_RATE_TAB_SZ 8 - -/* 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 */ - -/* Maximum sampling frequency */ -#define MAX_FS_KHZ 16 -#define MAX_API_FS_KHZ 48 - -/* 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 16 - -#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 32 -#define DECISION_DELAY_MASK ( DECISION_DELAY - 1 ) - -/* 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 */ - -#if( MAX_LPC_ORDER > DECISION_DELAY ) -# define NSQ_LPC_BUF_LENGTH MAX_LPC_ORDER -#else -# define NSQ_LPC_BUF_LENGTH DECISION_DELAY -#endif - -/***************************/ -/* 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_VQ_MAX_SURVIVORS 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_NLSF_SMTH_Q16 16348 /* 0.25 */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/opus/silk/enc_API.c b/drivers/opus/silk/enc_API.c deleted file mode 100644 index beb46214d8..0000000000 --- a/drivers/opus/silk/enc_API.c +++ /dev/null @@ -1,560 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" -#include "opus/silk/define.h" -#include "opus/silk/API.h" -#include "opus/silk/control.h" -#include "opus/silk/typedef.h" -#include "opus/celt/stack_alloc.h" -#include "opus/silk/structs.h" -#include "opus/silk/tuning_parameters.h" -#ifdef OPUS_FIXED_POINT -#include "opus/silk/fixed/main_FIX.h" -#else -#include "opus/silk/float/main_FLP.h" -#endif - -/***************************************/ -/* Read control structure from encoder */ -/***************************************/ -static opus_int silk_QueryEncoder( /* O Returns error code */ - const void *encState, /* I State */ - silk_EncControlStruct *encStatus /* O Encoder Status */ -); - -/****************************************/ -/* Encoder functions */ -/****************************************/ - -opus_int silk_Get_Encoder_Size( /* O Returns error code */ - opus_int *encSizeBytes /* O Number of bytes in SILK encoder state */ -) -{ - opus_int ret = SILK_NO_ERROR; - - *encSizeBytes = sizeof( silk_encoder ); - - return ret; -} - -/*************************/ -/* Init or Reset encoder */ -/*************************/ -opus_int silk_InitEncoder( /* O Returns error code */ - void *encState, /* I/O State */ - int arch, /* I Run-time architecture */ - silk_EncControlStruct *encStatus /* O Encoder Status */ -) -{ - silk_encoder *psEnc; - opus_int n, ret = SILK_NO_ERROR; - - psEnc = (silk_encoder *)encState; - - /* Reset encoder */ - silk_memset( psEnc, 0, sizeof( silk_encoder ) ); - for( n = 0; n < ENCODER_NUM_CHANNELS; n++ ) { - if( ret += silk_init_encoder( &psEnc->state_Fxx[ n ], arch ) ) { - silk_assert( 0 ); - } - } - - psEnc->nChannelsAPI = 1; - psEnc->nChannelsInternal = 1; - - /* Read control structure */ - if( ret += silk_QueryEncoder( encState, encStatus ) ) { - silk_assert( 0 ); - } - - return ret; -} - -/***************************************/ -/* Read control structure from encoder */ -/***************************************/ -static opus_int silk_QueryEncoder( /* O Returns error code */ - const void *encState, /* I State */ - silk_EncControlStruct *encStatus /* O Encoder Status */ -) -{ - opus_int ret = SILK_NO_ERROR; - silk_encoder_state_Fxx *state_Fxx; - silk_encoder *psEnc = (silk_encoder *)encState; - - state_Fxx = psEnc->state_Fxx; - - encStatus->nChannelsAPI = psEnc->nChannelsAPI; - encStatus->nChannelsInternal = psEnc->nChannelsInternal; - encStatus->API_sampleRate = state_Fxx[ 0 ].sCmn.API_fs_Hz; - encStatus->maxInternalSampleRate = state_Fxx[ 0 ].sCmn.maxInternal_fs_Hz; - encStatus->minInternalSampleRate = state_Fxx[ 0 ].sCmn.minInternal_fs_Hz; - encStatus->desiredInternalSampleRate = state_Fxx[ 0 ].sCmn.desiredInternal_fs_Hz; - encStatus->payloadSize_ms = state_Fxx[ 0 ].sCmn.PacketSize_ms; - encStatus->bitRate = state_Fxx[ 0 ].sCmn.TargetRate_bps; - encStatus->packetLossPercentage = state_Fxx[ 0 ].sCmn.PacketLoss_perc; - encStatus->complexity = state_Fxx[ 0 ].sCmn.Complexity; - encStatus->useInBandFEC = state_Fxx[ 0 ].sCmn.useInBandFEC; - encStatus->useDTX = state_Fxx[ 0 ].sCmn.useDTX; - encStatus->useCBR = state_Fxx[ 0 ].sCmn.useCBR; - encStatus->internalSampleRate = silk_SMULBB( state_Fxx[ 0 ].sCmn.fs_kHz, 1000 ); - encStatus->allowBandwidthSwitch = state_Fxx[ 0 ].sCmn.allow_bandwidth_switch; - encStatus->inWBmodeWithoutVariableLP = state_Fxx[ 0 ].sCmn.fs_kHz == 16 && state_Fxx[ 0 ].sCmn.sLP.mode == 0; - - return ret; -} - - -/**************************/ -/* 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_int16 *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 */ -) -{ - opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0; - opus_int nSamplesToBuffer, nSamplesToBufferMax, nBlocksOf10ms; - opus_int nSamplesFromInput = 0, nSamplesFromInputMax; - opus_int speech_act_thr_for_switch_Q8; - opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol, sum; - silk_encoder *psEnc = ( silk_encoder * )encState; - VARDECL( opus_int16, buf ); - opus_int transition, curr_block, tot_blocks; - SAVE_STACK; - - if (encControl->reducedDependency) - { - psEnc->state_Fxx[0].sCmn.first_frame_after_reset = 1; - psEnc->state_Fxx[1].sCmn.first_frame_after_reset = 1; - } - psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded = psEnc->state_Fxx[ 1 ].sCmn.nFramesEncoded = 0; - - /* Check values in encoder control structure */ - if( ( ret = check_control_input( encControl ) ) != 0 ) { - silk_assert( 0 ); - RESTORE_STACK; - return ret; - } - - encControl->switchReady = 0; - - if( encControl->nChannelsInternal > psEnc->nChannelsInternal ) { - /* Mono -> Stereo transition: init state of second channel and stereo state */ - ret += silk_init_encoder( &psEnc->state_Fxx[ 1 ], psEnc->state_Fxx[ 0 ].sCmn.arch ); - silk_memset( psEnc->sStereo.pred_prev_Q13, 0, sizeof( psEnc->sStereo.pred_prev_Q13 ) ); - silk_memset( psEnc->sStereo.sSide, 0, sizeof( psEnc->sStereo.sSide ) ); - psEnc->sStereo.mid_side_amp_Q0[ 0 ] = 0; - psEnc->sStereo.mid_side_amp_Q0[ 1 ] = 1; - psEnc->sStereo.mid_side_amp_Q0[ 2 ] = 0; - psEnc->sStereo.mid_side_amp_Q0[ 3 ] = 1; - psEnc->sStereo.width_prev_Q14 = 0; - psEnc->sStereo.smth_width_Q14 = SILK_FIX_CONST( 1, 14 ); - if( psEnc->nChannelsAPI == 2 ) { - silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof( silk_resampler_state_struct ) ); - silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.In_HP_State, &psEnc->state_Fxx[ 0 ].sCmn.In_HP_State, sizeof( psEnc->state_Fxx[ 1 ].sCmn.In_HP_State ) ); - } - } - - transition = (encControl->payloadSize_ms != psEnc->state_Fxx[ 0 ].sCmn.PacketSize_ms) || (psEnc->nChannelsInternal != encControl->nChannelsInternal); - - psEnc->nChannelsAPI = encControl->nChannelsAPI; - psEnc->nChannelsInternal = encControl->nChannelsInternal; - - nBlocksOf10ms = silk_DIV32( 100 * nSamplesIn, encControl->API_sampleRate ); - tot_blocks = ( nBlocksOf10ms > 1 ) ? nBlocksOf10ms >> 1 : 1; - curr_block = 0; - if( prefillFlag ) { - /* Only accept input length of 10 ms */ - if( nBlocksOf10ms != 1 ) { - silk_assert( 0 ); - RESTORE_STACK; - return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; - } - /* Reset Encoder */ - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - ret = silk_init_encoder( &psEnc->state_Fxx[ n ], psEnc->state_Fxx[ n ].sCmn.arch ); - silk_assert( !ret ); - } - tmp_payloadSize_ms = encControl->payloadSize_ms; - encControl->payloadSize_ms = 10; - tmp_complexity = encControl->complexity; - encControl->complexity = 0; - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; - psEnc->state_Fxx[ n ].sCmn.prefillFlag = 1; - } - } else { - /* Only accept input lengths that are a multiple of 10 ms */ - if( nBlocksOf10ms * encControl->API_sampleRate != 100 * nSamplesIn || nSamplesIn < 0 ) { - silk_assert( 0 ); - RESTORE_STACK; - return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; - } - /* Make sure no more than one packet can be produced */ - if( 1000 * (opus_int32)nSamplesIn > encControl->payloadSize_ms * encControl->API_sampleRate ) { - silk_assert( 0 ); - RESTORE_STACK; - return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; - } - } - - TargetRate_bps = silk_RSHIFT32( encControl->bitRate, encControl->nChannelsInternal - 1 ); - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - /* Force the side channel to the same rate as the mid */ - opus_int force_fs_kHz = (n==1) ? psEnc->state_Fxx[0].sCmn.fs_kHz : 0; - if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) { - silk_assert( 0 ); - RESTORE_STACK; - return ret; - } - if( psEnc->state_Fxx[n].sCmn.first_frame_after_reset || transition ) { - for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) { - psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] = 0; - } - } - psEnc->state_Fxx[ n ].sCmn.inDTX = psEnc->state_Fxx[ n ].sCmn.useDTX; - } - silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); - - /* Input buffering/resampling and encoding */ - nSamplesToBufferMax = - 10 * nBlocksOf10ms * psEnc->state_Fxx[ 0 ].sCmn.fs_kHz; - nSamplesFromInputMax = - silk_DIV32_16( nSamplesToBufferMax * - psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz, - psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 ); - ALLOC( buf, nSamplesFromInputMax, opus_int16 ); - while( 1 ) { - nSamplesToBuffer = psEnc->state_Fxx[ 0 ].sCmn.frame_length - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx; - nSamplesToBuffer = silk_min( nSamplesToBuffer, nSamplesToBufferMax ); - nSamplesFromInput = silk_DIV32_16( nSamplesToBuffer * psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz, psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 ); - /* Resample and write to buffer */ - if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) { - opus_int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded; - for( n = 0; n < nSamplesFromInput; n++ ) { - buf[ n ] = samplesIn[ 2 * n ]; - } - /* Making sure to start both resamplers from the same state when switching from mono to stereo */ - if( psEnc->nPrevChannelsInternal == 1 && id==0 ) { - silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof(psEnc->state_Fxx[ 1 ].sCmn.resampler_state)); - } - - ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, - &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; - - nSamplesToBuffer = psEnc->state_Fxx[ 1 ].sCmn.frame_length - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx; - nSamplesToBuffer = silk_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); - for( n = 0; n < nSamplesFromInput; n++ ) { - buf[ n ] = samplesIn[ 2 * n + 1 ]; - } - ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, - &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); - - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx += nSamplesToBuffer; - } else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) { - /* Combine left and right channels before resampling */ - for( n = 0; n < nSamplesFromInput; n++ ) { - sum = samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ]; - buf[ n ] = (opus_int16)silk_RSHIFT_ROUND( sum, 1 ); - } - ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, - &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); - /* On the first mono frame, average the results for the two resampler states */ - if( psEnc->nPrevChannelsInternal == 2 && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 ) { - ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, - &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); - for( n = 0; n < psEnc->state_Fxx[ 0 ].sCmn.frame_length; n++ ) { - psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx+n+2 ] = - silk_RSHIFT(psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx+n+2 ] - + psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx+n+2 ], 1); - } - } - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; - } else { - silk_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 ); - silk_memcpy(buf, samplesIn, nSamplesFromInput*sizeof(opus_int16)); - ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, - &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; - } - - samplesIn += nSamplesFromInput * encControl->nChannelsAPI; - nSamplesIn -= nSamplesFromInput; - - /* Default */ - psEnc->allowBandwidthSwitch = 0; - - /* Silk encoder */ - if( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx >= psEnc->state_Fxx[ 0 ].sCmn.frame_length ) { - /* Enough data in input buffer, so encode */ - silk_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length ); - silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length ); - - /* Deal with LBRR data */ - if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 && !prefillFlag ) { - /* Create space at start of payload for VAD and FEC flags */ - opus_uint8 iCDF[ 2 ] = { 0, 0 }; - iCDF[ 0 ] = 256 - silk_RSHIFT( 256, ( psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket + 1 ) * encControl->nChannelsInternal ); - ec_enc_icdf( psRangeEnc, 0, iCDF, 8 ); - - /* Encode any LBRR data from previous packet */ - /* Encode LBRR flags */ - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - LBRR_symbol = 0; - for( i = 0; i < psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket; i++ ) { - LBRR_symbol |= silk_LSHIFT( psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ], i ); - } - psEnc->state_Fxx[ n ].sCmn.LBRR_flag = LBRR_symbol > 0 ? 1 : 0; - if( LBRR_symbol && psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket > 1 ) { - ec_enc_icdf( psRangeEnc, LBRR_symbol - 1, silk_LBRR_flags_iCDF_ptr[ psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket - 2 ], 8 ); - } - } - - /* Code LBRR indices and excitation signals */ - for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) { - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - if( psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] ) { - opus_int condCoding; - - if( encControl->nChannelsInternal == 2 && n == 0 ) { - silk_stereo_encode_pred( psRangeEnc, psEnc->sStereo.predIx[ i ] ); - /* For LBRR data there's no need to code the mid-only flag if the side-channel LBRR flag is set */ - if( psEnc->state_Fxx[ 1 ].sCmn.LBRR_flags[ i ] == 0 ) { - silk_stereo_encode_mid_only( psRangeEnc, psEnc->sStereo.mid_only_flags[ i ] ); - } - } - /* Use conditional coding if previous frame available */ - if( i > 0 && psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i - 1 ] ) { - condCoding = CODE_CONDITIONALLY; - } else { - condCoding = CODE_INDEPENDENTLY; - } - silk_encode_indices( &psEnc->state_Fxx[ n ].sCmn, psRangeEnc, i, 1, condCoding ); - silk_encode_pulses( psRangeEnc, psEnc->state_Fxx[ n ].sCmn.indices_LBRR[i].signalType, psEnc->state_Fxx[ n ].sCmn.indices_LBRR[i].quantOffsetType, - psEnc->state_Fxx[ n ].sCmn.pulses_LBRR[ i ], psEnc->state_Fxx[ n ].sCmn.frame_length ); - } - } - } - - /* Reset LBRR flags */ - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - silk_memset( psEnc->state_Fxx[ n ].sCmn.LBRR_flags, 0, sizeof( psEnc->state_Fxx[ n ].sCmn.LBRR_flags ) ); - } - - psEnc->nBitsUsedLBRR = ec_tell( psRangeEnc ); - } - - silk_HP_variable_cutoff( psEnc->state_Fxx ); - - /* Total target bits for packet */ - nBits = silk_DIV32_16( silk_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 ); - /* Subtract bits used for LBRR */ - if( !prefillFlag ) { - nBits -= psEnc->nBitsUsedLBRR; - } - /* Divide by number of uncoded frames left in packet */ - nBits = silk_DIV32_16( nBits, psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket ); - /* Convert to bits/second */ - if( encControl->payloadSize_ms == 10 ) { - TargetRate_bps = silk_SMULBB( nBits, 100 ); - } else { - TargetRate_bps = silk_SMULBB( nBits, 50 ); - } - /* Subtract fraction of bits in excess of target in previous frames and packets */ - TargetRate_bps -= silk_DIV32_16( silk_MUL( psEnc->nBitsExceeded, 1000 ), BITRESERVOIR_DECAY_TIME_MS ); - if( !prefillFlag && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded > 0 ) { - /* Compare actual vs target bits so far in this packet */ - opus_int32 bitsBalance = ec_tell( psRangeEnc ) - psEnc->nBitsUsedLBRR - nBits * psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded; - TargetRate_bps -= silk_DIV32_16( silk_MUL( bitsBalance, 1000 ), BITRESERVOIR_DECAY_TIME_MS ); - } - /* Never exceed input bitrate */ - TargetRate_bps = silk_LIMIT( TargetRate_bps, encControl->bitRate, 5000 ); - - /* Convert Left/Right to Mid/Side */ - if( encControl->nChannelsInternal == 2 ) { - silk_stereo_LR_to_MS( &psEnc->sStereo, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ 2 ], &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ 2 ], - psEnc->sStereo.predIx[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ], &psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ], - MStargetRates_bps, TargetRate_bps, psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8, encControl->toMono, - psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, psEnc->state_Fxx[ 0 ].sCmn.frame_length ); - if( psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] == 0 ) { - /* Reset side channel encoder memory for first frame with side coding */ - if( psEnc->prev_decode_only_middle == 1 ) { - silk_memset( &psEnc->state_Fxx[ 1 ].sShape, 0, sizeof( psEnc->state_Fxx[ 1 ].sShape ) ); - silk_memset( &psEnc->state_Fxx[ 1 ].sPrefilt, 0, sizeof( psEnc->state_Fxx[ 1 ].sPrefilt ) ); - silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sNSQ, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sNSQ ) ); - silk_memset( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15 ) ); - silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State ) ); - psEnc->state_Fxx[ 1 ].sCmn.prevLag = 100; - psEnc->state_Fxx[ 1 ].sCmn.sNSQ.lagPrev = 100; - psEnc->state_Fxx[ 1 ].sShape.LastGainIndex = 10; - psEnc->state_Fxx[ 1 ].sCmn.prevSignalType = TYPE_NO_VOICE_ACTIVITY; - psEnc->state_Fxx[ 1 ].sCmn.sNSQ.prev_gain_Q16 = 65536; - psEnc->state_Fxx[ 1 ].sCmn.first_frame_after_reset = 1; - } - silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 1 ] ); - } else { - psEnc->state_Fxx[ 1 ].sCmn.VAD_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] = 0; - } - if( !prefillFlag ) { - silk_stereo_encode_pred( psRangeEnc, psEnc->sStereo.predIx[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] ); - if( psEnc->state_Fxx[ 1 ].sCmn.VAD_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] == 0 ) { - silk_stereo_encode_mid_only( psRangeEnc, psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] ); - } - } - } else { - /* Buffering */ - silk_memcpy( psEnc->state_Fxx[ 0 ].sCmn.inputBuf, psEnc->sStereo.sMid, 2 * sizeof( opus_int16 ) ); - silk_memcpy( psEnc->sStereo.sMid, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.frame_length ], 2 * sizeof( opus_int16 ) ); - } - silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 0 ] ); - - /* Encode */ - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - opus_int maxBits, useCBR; - - /* Handling rate constraints */ - maxBits = encControl->maxBits; - if( tot_blocks == 2 && curr_block == 0 ) { - maxBits = maxBits * 3 / 5; - } else if( tot_blocks == 3 ) { - if( curr_block == 0 ) { - maxBits = maxBits * 2 / 5; - } else if( curr_block == 1 ) { - maxBits = maxBits * 3 / 4; - } - } - useCBR = encControl->useCBR && curr_block == tot_blocks - 1; - - if( encControl->nChannelsInternal == 1 ) { - channelRate_bps = TargetRate_bps; - } else { - channelRate_bps = MStargetRates_bps[ n ]; - if( n == 0 && MStargetRates_bps[ 1 ] > 0 ) { - useCBR = 0; - /* Give mid up to 1/2 of the max bits for that frame */ - maxBits -= encControl->maxBits / ( tot_blocks * 2 ); - } - } - - if( channelRate_bps > 0 ) { - opus_int condCoding; - - silk_control_SNR( &psEnc->state_Fxx[ n ].sCmn, channelRate_bps ); - - /* Use independent coding if no previous frame available */ - if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded - n <= 0 ) { - condCoding = CODE_INDEPENDENTLY; - } else if( n > 0 && psEnc->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; - } - if( ( ret = silk_encode_frame_Fxx( &psEnc->state_Fxx[ n ], nBytesOut, psRangeEnc, condCoding, maxBits, useCBR ) ) != 0 ) { - silk_assert( 0 ); - } - } - psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; - psEnc->state_Fxx[ n ].sCmn.inputBufIx = 0; - psEnc->state_Fxx[ n ].sCmn.nFramesEncoded++; - } - psEnc->prev_decode_only_middle = psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded - 1 ]; - - /* Insert VAD and FEC flags at beginning of bitstream */ - if( *nBytesOut > 0 && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket) { - flags = 0; - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - for( i = 0; i < psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket; i++ ) { - flags = silk_LSHIFT( flags, 1 ); - flags |= psEnc->state_Fxx[ n ].sCmn.VAD_flags[ i ]; - } - flags = silk_LSHIFT( flags, 1 ); - flags |= psEnc->state_Fxx[ n ].sCmn.LBRR_flag; - } - if( !prefillFlag ) { - ec_enc_patch_initial_bits( psRangeEnc, flags, ( psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket + 1 ) * encControl->nChannelsInternal ); - } - - /* Return zero bytes if all channels DTXed */ - if( psEnc->state_Fxx[ 0 ].sCmn.inDTX && ( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inDTX ) ) { - *nBytesOut = 0; - } - - psEnc->nBitsExceeded += *nBytesOut * 8; - psEnc->nBitsExceeded -= silk_DIV32_16( silk_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 ); - psEnc->nBitsExceeded = silk_LIMIT( psEnc->nBitsExceeded, 0, 10000 ); - - /* Update flag indicating if bandwidth switching is allowed */ - speech_act_thr_for_switch_Q8 = silk_SMLAWB( SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ), - SILK_FIX_CONST( ( 1 - SPEECH_ACTIVITY_DTX_THRES ) / MAX_BANDWIDTH_SWITCH_DELAY_MS, 16 + 8 ), psEnc->timeSinceSwitchAllowed_ms ); - if( psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8 < speech_act_thr_for_switch_Q8 ) { - psEnc->allowBandwidthSwitch = 1; - psEnc->timeSinceSwitchAllowed_ms = 0; - } else { - psEnc->allowBandwidthSwitch = 0; - psEnc->timeSinceSwitchAllowed_ms += encControl->payloadSize_ms; - } - } - - if( nSamplesIn == 0 ) { - break; - } - } else { - break; - } - curr_block++; - } - - psEnc->nPrevChannelsInternal = encControl->nChannelsInternal; - - encControl->allowBandwidthSwitch = psEnc->allowBandwidthSwitch; - encControl->inWBmodeWithoutVariableLP = psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == 16 && psEnc->state_Fxx[ 0 ].sCmn.sLP.mode == 0; - encControl->internalSampleRate = silk_SMULBB( psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, 1000 ); - encControl->stereoWidth_Q14 = encControl->toMono ? 0 : psEnc->sStereo.smth_width_Q14; - if( prefillFlag ) { - encControl->payloadSize_ms = tmp_payloadSize_ms; - encControl->complexity = tmp_complexity; - for( n = 0; n < encControl->nChannelsInternal; n++ ) { - psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; - psEnc->state_Fxx[ n ].sCmn.prefillFlag = 0; - } - } - - RESTORE_STACK; - return ret; -} - diff --git a/drivers/opus/silk/encode_indices.c b/drivers/opus/silk/encode_indices.c deleted file mode 100644 index 72fc6a80e8..0000000000 --- a/drivers/opus/silk/encode_indices.c +++ /dev/null @@ -1,178 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" - -/* Encode side-information parameters to payload */ -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 */ -) -{ - opus_int i, k, typeOffset; - opus_int encode_absolute_lagIndex, delta_lagIndex; - opus_int16 ec_ix[ MAX_LPC_ORDER ]; - opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; - const SideInfoIndices *psIndices; - - if( encode_LBRR ) { - psIndices = &psEncC->indices_LBRR[ FrameIndex ]; - } else { - psIndices = &psEncC->indices; - } - - /*******************************************/ - /* Encode signal type and quantizer offset */ - /*******************************************/ - typeOffset = 2 * psIndices->signalType + psIndices->quantOffsetType; - silk_assert( typeOffset >= 0 && typeOffset < 6 ); - silk_assert( encode_LBRR == 0 || typeOffset >= 2 ); - if( encode_LBRR || typeOffset >= 2 ) { - ec_enc_icdf( psRangeEnc, typeOffset - 2, silk_type_offset_VAD_iCDF, 8 ); - } else { - ec_enc_icdf( psRangeEnc, typeOffset, silk_type_offset_no_VAD_iCDF, 8 ); - } - - /****************/ - /* Encode gains */ - /****************/ - /* first subframe */ - if( condCoding == CODE_CONDITIONALLY ) { - /* conditional coding */ - silk_assert( psIndices->GainsIndices[ 0 ] >= 0 && psIndices->GainsIndices[ 0 ] < MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ); - ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ 0 ], silk_delta_gain_iCDF, 8 ); - } else { - /* independent coding, in two stages: MSB bits followed by 3 LSBs */ - silk_assert( psIndices->GainsIndices[ 0 ] >= 0 && psIndices->GainsIndices[ 0 ] < N_LEVELS_QGAIN ); - ec_enc_icdf( psRangeEnc, silk_RSHIFT( psIndices->GainsIndices[ 0 ], 3 ), silk_gain_iCDF[ psIndices->signalType ], 8 ); - ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ 0 ] & 7, silk_uniform8_iCDF, 8 ); - } - - /* remaining subframes */ - for( i = 1; i < psEncC->nb_subfr; i++ ) { - silk_assert( psIndices->GainsIndices[ i ] >= 0 && psIndices->GainsIndices[ i ] < MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ); - ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ i ], silk_delta_gain_iCDF, 8 ); - } - - /****************/ - /* Encode NLSFs */ - /****************/ - ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ 0 ], &psEncC->psNLSF_CB->CB1_iCDF[ ( psIndices->signalType >> 1 ) * psEncC->psNLSF_CB->nVectors ], 8 ); - silk_NLSF_unpack( ec_ix, pred_Q8, psEncC->psNLSF_CB, psIndices->NLSFIndices[ 0 ] ); - silk_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder ); - for( i = 0; i < psEncC->psNLSF_CB->order; i++ ) { - if( psIndices->NLSFIndices[ i+1 ] >= NLSF_QUANT_MAX_AMPLITUDE ) { - ec_enc_icdf( psRangeEnc, 2 * NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); - ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ i+1 ] - NLSF_QUANT_MAX_AMPLITUDE, silk_NLSF_EXT_iCDF, 8 ); - } else if( psIndices->NLSFIndices[ i+1 ] <= -NLSF_QUANT_MAX_AMPLITUDE ) { - ec_enc_icdf( psRangeEnc, 0, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); - ec_enc_icdf( psRangeEnc, -psIndices->NLSFIndices[ i+1 ] - NLSF_QUANT_MAX_AMPLITUDE, silk_NLSF_EXT_iCDF, 8 ); - } else { - ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ i+1 ] + NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); - } - } - - /* Encode NLSF interpolation factor */ - if( psEncC->nb_subfr == MAX_NB_SUBFR ) { - silk_assert( psIndices->NLSFInterpCoef_Q2 >= 0 && psIndices->NLSFInterpCoef_Q2 < 5 ); - ec_enc_icdf( psRangeEnc, psIndices->NLSFInterpCoef_Q2, silk_NLSF_interpolation_factor_iCDF, 8 ); - } - - if( psIndices->signalType == TYPE_VOICED ) - { - /*********************/ - /* Encode pitch lags */ - /*********************/ - /* lag index */ - encode_absolute_lagIndex = 1; - if( condCoding == CODE_CONDITIONALLY && psEncC->ec_prevSignalType == TYPE_VOICED ) { - /* Delta Encoding */ - delta_lagIndex = psIndices->lagIndex - psEncC->ec_prevLagIndex; - if( delta_lagIndex < -8 || delta_lagIndex > 11 ) { - delta_lagIndex = 0; - } else { - delta_lagIndex = delta_lagIndex + 9; - encode_absolute_lagIndex = 0; /* Only use delta */ - } - silk_assert( delta_lagIndex >= 0 && delta_lagIndex < 21 ); - ec_enc_icdf( psRangeEnc, delta_lagIndex, silk_pitch_delta_iCDF, 8 ); - } - if( encode_absolute_lagIndex ) { - /* Absolute encoding */ - opus_int32 pitch_high_bits, pitch_low_bits; - pitch_high_bits = silk_DIV32_16( psIndices->lagIndex, silk_RSHIFT( psEncC->fs_kHz, 1 ) ); - pitch_low_bits = psIndices->lagIndex - silk_SMULBB( pitch_high_bits, silk_RSHIFT( psEncC->fs_kHz, 1 ) ); - silk_assert( pitch_low_bits < psEncC->fs_kHz / 2 ); - silk_assert( pitch_high_bits < 32 ); - ec_enc_icdf( psRangeEnc, pitch_high_bits, silk_pitch_lag_iCDF, 8 ); - ec_enc_icdf( psRangeEnc, pitch_low_bits, psEncC->pitch_lag_low_bits_iCDF, 8 ); - } - psEncC->ec_prevLagIndex = psIndices->lagIndex; - - /* Countour index */ - silk_assert( psIndices->contourIndex >= 0 ); - silk_assert( ( psIndices->contourIndex < 34 && psEncC->fs_kHz > 8 && psEncC->nb_subfr == 4 ) || - ( psIndices->contourIndex < 11 && psEncC->fs_kHz == 8 && psEncC->nb_subfr == 4 ) || - ( psIndices->contourIndex < 12 && psEncC->fs_kHz > 8 && psEncC->nb_subfr == 2 ) || - ( psIndices->contourIndex < 3 && psEncC->fs_kHz == 8 && psEncC->nb_subfr == 2 ) ); - ec_enc_icdf( psRangeEnc, psIndices->contourIndex, psEncC->pitch_contour_iCDF, 8 ); - - /********************/ - /* Encode LTP gains */ - /********************/ - /* PERIndex value */ - silk_assert( psIndices->PERIndex >= 0 && psIndices->PERIndex < 3 ); - ec_enc_icdf( psRangeEnc, psIndices->PERIndex, silk_LTP_per_index_iCDF, 8 ); - - /* Codebook Indices */ - for( k = 0; k < psEncC->nb_subfr; k++ ) { - silk_assert( psIndices->LTPIndex[ k ] >= 0 && psIndices->LTPIndex[ k ] < ( 8 << psIndices->PERIndex ) ); - ec_enc_icdf( psRangeEnc, psIndices->LTPIndex[ k ], silk_LTP_gain_iCDF_ptrs[ psIndices->PERIndex ], 8 ); - } - - /**********************/ - /* Encode LTP scaling */ - /**********************/ - if( condCoding == CODE_INDEPENDENTLY ) { - silk_assert( psIndices->LTP_scaleIndex >= 0 && psIndices->LTP_scaleIndex < 3 ); - ec_enc_icdf( psRangeEnc, psIndices->LTP_scaleIndex, silk_LTPscale_iCDF, 8 ); - } - silk_assert( !condCoding || psIndices->LTP_scaleIndex == 0 ); - } - - psEncC->ec_prevSignalType = psIndices->signalType; - - /***************/ - /* Encode seed */ - /***************/ - silk_assert( psIndices->Seed >= 0 && psIndices->Seed < 4 ); - ec_enc_icdf( psRangeEnc, psIndices->Seed, silk_uniform4_iCDF, 8 ); -} diff --git a/drivers/opus/silk/encode_pulses.c b/drivers/opus/silk/encode_pulses.c deleted file mode 100644 index 238eec1e42..0000000000 --- a/drivers/opus/silk/encode_pulses.c +++ /dev/null @@ -1,203 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/celt/stack_alloc.h" - -/*********************************************/ -/* Encode quantization indices of excitation */ -/*********************************************/ - -static OPUS_INLINE opus_int combine_and_check( /* return ok */ - opus_int *pulses_comb, /* O */ - const opus_int *pulses_in, /* I */ - opus_int max_pulses, /* I max value for sum of pulses */ - opus_int len /* I number of output values */ -) -{ - opus_int k, sum; - - for( k = 0; k < len; k++ ) { - sum = pulses_in[ 2 * k ] + pulses_in[ 2 * k + 1 ]; - if( sum > max_pulses ) { - return 1; - } - pulses_comb[ k ] = sum; - } - - return 0; -} - -/* 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 */ -) -{ - opus_int i, k, j, iter, bit, nLS, scale_down, RateLevelIndex = 0; - opus_int32 abs_q, minSumBits_Q5, sumBits_Q5; - VARDECL( opus_int, abs_pulses ); - VARDECL( opus_int, sum_pulses ); - VARDECL( opus_int, nRshifts ); - opus_int pulses_comb[ 8 ]; - opus_int *abs_pulses_ptr; - const opus_int8 *pulses_ptr; - const opus_uint8 *cdf_ptr; - const opus_uint8 *nBits_ptr; - SAVE_STACK; - - silk_memset( pulses_comb, 0, 8 * sizeof( opus_int ) ); /* Fixing Valgrind reported problem*/ - - /****************************/ - /* Prepare for shell coding */ - /****************************/ - /* 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 ) { - silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */ - iter++; - silk_memset( &pulses[ frame_length ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof(opus_int8)); - } - - /* Take the absolute value of the pulses */ - ALLOC( abs_pulses, iter * SHELL_CODEC_FRAME_LENGTH, opus_int ); - silk_assert( !( SHELL_CODEC_FRAME_LENGTH & 3 ) ); - for( i = 0; i < iter * SHELL_CODEC_FRAME_LENGTH; i+=4 ) { - abs_pulses[i+0] = ( opus_int )silk_abs( pulses[ i + 0 ] ); - abs_pulses[i+1] = ( opus_int )silk_abs( pulses[ i + 1 ] ); - abs_pulses[i+2] = ( opus_int )silk_abs( pulses[ i + 2 ] ); - abs_pulses[i+3] = ( opus_int )silk_abs( pulses[ i + 3 ] ); - } - - /* Calc sum pulses per shell code frame */ - ALLOC( sum_pulses, iter, opus_int ); - ALLOC( nRshifts, iter, opus_int ); - abs_pulses_ptr = abs_pulses; - for( i = 0; i < iter; i++ ) { - nRshifts[ i ] = 0; - - while( 1 ) { - /* 1+1 -> 2 */ - scale_down = combine_and_check( pulses_comb, abs_pulses_ptr, silk_max_pulses_table[ 0 ], 8 ); - /* 2+2 -> 4 */ - scale_down += combine_and_check( pulses_comb, pulses_comb, silk_max_pulses_table[ 1 ], 4 ); - /* 4+4 -> 8 */ - scale_down += combine_and_check( pulses_comb, pulses_comb, silk_max_pulses_table[ 2 ], 2 ); - /* 8+8 -> 16 */ - scale_down += combine_and_check( &sum_pulses[ i ], pulses_comb, silk_max_pulses_table[ 3 ], 1 ); - - if( scale_down ) { - /* We need to downscale the quantization signal */ - nRshifts[ i ]++; - for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { - abs_pulses_ptr[ k ] = silk_RSHIFT( abs_pulses_ptr[ k ], 1 ); - } - } else { - /* Jump out of while(1) loop and go to next shell coding frame */ - break; - } - } - abs_pulses_ptr += SHELL_CODEC_FRAME_LENGTH; - } - - /**************/ - /* Rate level */ - /**************/ - /* find rate level that leads to fewest bits for coding of pulses per block info */ - minSumBits_Q5 = silk_int32_MAX; - for( k = 0; k < N_RATE_LEVELS - 1; k++ ) { - nBits_ptr = silk_pulses_per_block_BITS_Q5[ k ]; - sumBits_Q5 = silk_rate_levels_BITS_Q5[ signalType >> 1 ][ k ]; - for( i = 0; i < iter; i++ ) { - if( nRshifts[ i ] > 0 ) { - sumBits_Q5 += nBits_ptr[ SILK_MAX_PULSES + 1 ]; - } else { - sumBits_Q5 += nBits_ptr[ sum_pulses[ i ] ]; - } - } - if( sumBits_Q5 < minSumBits_Q5 ) { - minSumBits_Q5 = sumBits_Q5; - RateLevelIndex = k; - } - } - ec_enc_icdf( psRangeEnc, RateLevelIndex, silk_rate_levels_iCDF[ signalType >> 1 ], 8 ); - - /***************************************************/ - /* Sum-Weighted-Pulses Encoding */ - /***************************************************/ - cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ]; - for( i = 0; i < iter; i++ ) { - if( nRshifts[ i ] == 0 ) { - ec_enc_icdf( psRangeEnc, sum_pulses[ i ], cdf_ptr, 8 ); - } else { - ec_enc_icdf( psRangeEnc, SILK_MAX_PULSES + 1, cdf_ptr, 8 ); - for( k = 0; k < nRshifts[ i ] - 1; k++ ) { - ec_enc_icdf( psRangeEnc, SILK_MAX_PULSES + 1, silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 ); - } - ec_enc_icdf( psRangeEnc, sum_pulses[ i ], silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 ); - } - } - - /******************/ - /* Shell Encoding */ - /******************/ - for( i = 0; i < iter; i++ ) { - if( sum_pulses[ i ] > 0 ) { - silk_shell_encoder( psRangeEnc, &abs_pulses[ i * SHELL_CODEC_FRAME_LENGTH ] ); - } - } - - /****************/ - /* LSB Encoding */ - /****************/ - for( i = 0; i < iter; i++ ) { - if( nRshifts[ i ] > 0 ) { - pulses_ptr = &pulses[ i * SHELL_CODEC_FRAME_LENGTH ]; - nLS = nRshifts[ i ] - 1; - for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { - abs_q = (opus_int8)silk_abs( pulses_ptr[ k ] ); - for( j = nLS; j > 0; j-- ) { - bit = silk_RSHIFT( abs_q, j ) & 1; - ec_enc_icdf( psRangeEnc, bit, silk_lsb_iCDF, 8 ); - } - bit = abs_q & 1; - ec_enc_icdf( psRangeEnc, bit, silk_lsb_iCDF, 8 ); - } - } - } - - /****************/ - /* Encode signs */ - /****************/ - silk_encode_signs( psRangeEnc, pulses, frame_length, signalType, quantOffsetType, sum_pulses ); - RESTORE_STACK; -} diff --git a/drivers/opus/silk/fixed/LTP_analysis_filter_FIX.c b/drivers/opus/silk/fixed/LTP_analysis_filter_FIX.c deleted file mode 100644 index 041e85f0b9..0000000000 --- a/drivers/opus/silk/fixed/LTP_analysis_filter_FIX.c +++ /dev/null @@ -1,87 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" - -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 */ -) -{ - const opus_int16 *x_ptr, *x_lag_ptr; - opus_int16 Btmp_Q14[ LTP_ORDER ]; - opus_int16 *LTP_res_ptr; - opus_int k, i; - opus_int32 LTP_est; - - x_ptr = x; - LTP_res_ptr = LTP_res; - for( k = 0; k < nb_subfr; k++ ) { - - x_lag_ptr = x_ptr - pitchL[ k ]; - - Btmp_Q14[ 0 ] = LTPCoef_Q14[ k * LTP_ORDER ]; - Btmp_Q14[ 1 ] = LTPCoef_Q14[ k * LTP_ORDER + 1 ]; - Btmp_Q14[ 2 ] = LTPCoef_Q14[ k * LTP_ORDER + 2 ]; - Btmp_Q14[ 3 ] = LTPCoef_Q14[ k * LTP_ORDER + 3 ]; - Btmp_Q14[ 4 ] = LTPCoef_Q14[ k * LTP_ORDER + 4 ]; - - /* LTP analysis FIR filter */ - for( i = 0; i < subfr_length + pre_length; i++ ) { - LTP_res_ptr[ i ] = x_ptr[ i ]; - - /* Long-term prediction */ - LTP_est = silk_SMULBB( x_lag_ptr[ LTP_ORDER / 2 ], Btmp_Q14[ 0 ] ); - LTP_est = silk_SMLABB_ovflw( LTP_est, x_lag_ptr[ 1 ], Btmp_Q14[ 1 ] ); - LTP_est = silk_SMLABB_ovflw( LTP_est, x_lag_ptr[ 0 ], Btmp_Q14[ 2 ] ); - LTP_est = silk_SMLABB_ovflw( LTP_est, x_lag_ptr[ -1 ], Btmp_Q14[ 3 ] ); - LTP_est = silk_SMLABB_ovflw( LTP_est, x_lag_ptr[ -2 ], Btmp_Q14[ 4 ] ); - - LTP_est = silk_RSHIFT_ROUND( LTP_est, 14 ); /* round and -> Q0*/ - - /* Subtract long-term prediction */ - LTP_res_ptr[ i ] = (opus_int16)silk_SAT16( (opus_int32)x_ptr[ i ] - LTP_est ); - - /* Scale residual */ - LTP_res_ptr[ i ] = silk_SMULWB( invGains_Q16[ k ], LTP_res_ptr[ i ] ); - - x_lag_ptr++; - } - - /* Update pointers */ - LTP_res_ptr += subfr_length + pre_length; - x_ptr += subfr_length; - } -} - diff --git a/drivers/opus/silk/fixed/LTP_scale_ctrl_FIX.c b/drivers/opus/silk/fixed/LTP_scale_ctrl_FIX.c deleted file mode 100644 index dac1fbc08a..0000000000 --- a/drivers/opus/silk/fixed/LTP_scale_ctrl_FIX.c +++ /dev/null @@ -1,50 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" - -/* 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 */ -) -{ - opus_int round_loss; - - if( condCoding == CODE_INDEPENDENTLY ) { - /* Only scale if first frame in packet */ - round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket; - psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( - silk_SMULWB( silk_SMULBB( round_loss, psEncCtrl->LTPredCodGain_Q7 ), SILK_FIX_CONST( 0.1, 9 ) ), 0, 2 ); - } else { - /* Default is minimum scaling */ - psEnc->sCmn.indices.LTP_scaleIndex = 0; - } - psEncCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ]; -} diff --git a/drivers/opus/silk/fixed/apply_sine_window_FIX.c b/drivers/opus/silk/fixed/apply_sine_window_FIX.c deleted file mode 100644 index 9d63e7bce2..0000000000 --- a/drivers/opus/silk/fixed/apply_sine_window_FIX.c +++ /dev/null @@ -1,98 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.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 */ -/* Every other sample is linearly interpolated, for speed. */ -/* Window length must be between 16 and 120 (incl) and a multiple of 4. */ - -/* Matlab code for table: - for k=16:9*4:16+2*9*4, fprintf(' %7.d,', -round(65536*pi ./ (k:4:k+8*4))); fprintf('\n'); end -*/ -static const opus_int16 freq_table_Q16[ 27 ] = { - 12111, 9804, 8235, 7100, 6239, 5565, 5022, 4575, 4202, - 3885, 3612, 3375, 3167, 2984, 2820, 2674, 2542, 2422, - 2313, 2214, 2123, 2038, 1961, 1889, 1822, 1760, 1702, -}; - -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 */ -) -{ - opus_int k, f_Q16, c_Q16; - opus_int32 S0_Q16, S1_Q16; - - silk_assert( win_type == 1 || win_type == 2 ); - - /* Length must be in a range from 16 to 120 and a multiple of 4 */ - silk_assert( length >= 16 && length <= 120 ); - silk_assert( ( length & 3 ) == 0 ); - - /* Frequency */ - k = ( length >> 2 ) - 4; - silk_assert( k >= 0 && k <= 26 ); - f_Q16 = (opus_int)freq_table_Q16[ k ]; - - /* Factor used for cosine approximation */ - c_Q16 = silk_SMULWB( (opus_int32)f_Q16, -f_Q16 ); - silk_assert( c_Q16 >= -32768 ); - - /* initialize state */ - if( win_type == 1 ) { - /* start from 0 */ - S0_Q16 = 0; - /* approximation of sin(f) */ - S1_Q16 = f_Q16 + silk_RSHIFT( length, 3 ); - } else { - /* start from 1 */ - S0_Q16 = ( (opus_int32)1 << 16 ); - /* approximation of cos(f) */ - S1_Q16 = ( (opus_int32)1 << 16 ) + silk_RSHIFT( c_Q16, 1 ) + silk_RSHIFT( length, 4 ); - } - - /* 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 ] = (opus_int16)silk_SMULWB( silk_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k ] ); - px_win[ k + 1 ] = (opus_int16)silk_SMULWB( S1_Q16, px[ k + 1] ); - S0_Q16 = silk_SMULWB( S1_Q16, c_Q16 ) + silk_LSHIFT( S1_Q16, 1 ) - S0_Q16 + 1; - S0_Q16 = silk_min( S0_Q16, ( (opus_int32)1 << 16 ) ); - - px_win[ k + 2 ] = (opus_int16)silk_SMULWB( silk_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k + 2] ); - px_win[ k + 3 ] = (opus_int16)silk_SMULWB( S0_Q16, px[ k + 3 ] ); - S1_Q16 = silk_SMULWB( S0_Q16, c_Q16 ) + silk_LSHIFT( S0_Q16, 1 ) - S1_Q16; - S1_Q16 = silk_min( S1_Q16, ( (opus_int32)1 << 16 ) ); - } -} diff --git a/drivers/opus/silk/fixed/autocorr_FIX.c b/drivers/opus/silk/fixed/autocorr_FIX.c deleted file mode 100644 index db39a0335b..0000000000 --- a/drivers/opus/silk/fixed/autocorr_FIX.c +++ /dev/null @@ -1,45 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" -#include "opus/celt/celt_lpc.h" - -/* 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 */ -) -{ - opus_int corrCount; - corrCount = silk_min_int( inputDataSize, correlationCount ); - *scale = _celt_autocorr(inputData, results, NULL, 0, corrCount-1, inputDataSize, arch); -} diff --git a/drivers/opus/silk/fixed/burg_modified_FIX.c b/drivers/opus/silk/fixed/burg_modified_FIX.c deleted file mode 100644 index 48d64eccc5..0000000000 --- a/drivers/opus/silk/fixed/burg_modified_FIX.c +++ /dev/null @@ -1,272 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/define.h" -#include "opus/silk/tuning_parameters.h" -#include "opus/celt/pitch.h" - -#define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */ - -#define QA 25 -#define N_BITS_HEAD_ROOM 2 -#define MIN_RSHIFTS -16 -#define MAX_RSHIFTS (32 - QA) - -/* 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 */ -) -{ - opus_int k, n, s, lz, rshifts, reached_max_gain; - opus_int32 C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2; - const opus_int16 *x_ptr; - opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ]; - opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ]; - opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ]; - opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ]; - opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ]; - opus_int32 xcorr[ SILK_MAX_ORDER_LPC ]; - opus_int64 C0_64; - - silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); - - /* Compute autocorrelations, added over subframes */ - C0_64 = silk_inner_prod16_aligned_64( x, x, subfr_length*nb_subfr, arch ); - lz = silk_CLZ64(C0_64); - rshifts = 32 + 1 + N_BITS_HEAD_ROOM - lz; - if (rshifts > MAX_RSHIFTS) rshifts = MAX_RSHIFTS; - if (rshifts < MIN_RSHIFTS) rshifts = MIN_RSHIFTS; - - if (rshifts > 0) { - C0 = (opus_int32)silk_RSHIFT64(C0_64, rshifts ); - } else { - C0 = silk_LSHIFT32((opus_int32)C0_64, -rshifts ); - } - - CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ - silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); - if( rshifts > 0 ) { - 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 ] += (opus_int32)silk_RSHIFT64( - silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n, arch ), rshifts ); - } - } - } else { - for( s = 0; s < nb_subfr; s++ ) { - int i; - opus_int32 d; - x_ptr = x + s * subfr_length; - celt_pitch_xcorr(x_ptr, x_ptr + 1, xcorr, subfr_length - D, D, arch ); - for( n = 1; n < D + 1; n++ ) { - for ( i = n + subfr_length - D, d = 0; i < subfr_length; i++ ) - d = MAC16_16( d, x_ptr[ i ], x_ptr[ i - n ] ); - xcorr[ n - 1 ] += d; - } - for( n = 1; n < D + 1; n++ ) { - C_first_row[ n - 1 ] += silk_LSHIFT32( xcorr[ n - 1 ], -rshifts ); - } - } - } - silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); - - /* Initialize */ - CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ - - invGain_Q30 = (opus_int32)1 << 30; - 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) */ - if( rshifts > -2 ) { - for( s = 0; s < nb_subfr; s++ ) { - x_ptr = x + s * subfr_length; - x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], 16 - rshifts ); /* Q(16-rshifts) */ - x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts ); /* Q(16-rshifts) */ - tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], QA - 16 ); /* Q(QA-16) */ - tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); /* Q(QA-16) */ - for( k = 0; k < n; k++ ) { - C_first_row[ k ] = silk_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ - C_last_row[ k ] = silk_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ - Atmp_QA = Af_QA[ k ]; - tmp1 = silk_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); /* Q(QA-16) */ - tmp2 = silk_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] ); /* Q(QA-16) */ - } - tmp1 = silk_LSHIFT32( -tmp1, 32 - QA - rshifts ); /* Q(16-rshifts) */ - tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts ); /* Q(16-rshifts) */ - for( k = 0; k <= n; k++ ) { - CAf[ k ] = silk_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); /* Q( -rshift ) */ - CAb[ k ] = silk_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); /* Q( -rshift ) */ - } - } - } else { - for( s = 0; s < nb_subfr; s++ ) { - x_ptr = x + s * subfr_length; - x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], -rshifts ); /* Q( -rshifts ) */ - x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); /* Q( -rshifts ) */ - tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); /* Q17 */ - tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); /* Q17 */ - for( k = 0; k < n; k++ ) { - C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ - C_last_row[ k ] = silk_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ - Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); /* Q17 */ - tmp1 = silk_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */ - tmp2 = silk_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17 */ - } - tmp1 = -tmp1; /* Q17 */ - tmp2 = -tmp2; /* Q17 */ - for( k = 0; k <= n; k++ ) { - CAf[ k ] = silk_SMLAWW( CAf[ k ], tmp1, - silk_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) ); /* Q( -rshift ) */ - CAb[ k ] = silk_SMLAWW( CAb[ k ], tmp2, - silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) ); /* Q( -rshift ) */ - } - } - } - - /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ - tmp1 = C_first_row[ n ]; /* Q( -rshifts ) */ - tmp2 = C_last_row[ n ]; /* Q( -rshifts ) */ - num = 0; /* Q( -rshifts ) */ - nrg = silk_ADD32( CAb[ 0 ], CAf[ 0 ] ); /* Q( 1-rshifts ) */ - for( k = 0; k < n; k++ ) { - Atmp_QA = Af_QA[ k ]; - lz = silk_CLZ32( silk_abs( Atmp_QA ) ) - 1; - lz = silk_min( 32 - QA, lz ); - Atmp1 = silk_LSHIFT32( Atmp_QA, lz ); /* Q( QA + lz ) */ - - tmp1 = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( C_last_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ - tmp2 = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ - num = silk_ADD_LSHIFT32( num, silk_SMMUL( CAb[ n - k ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ - nrg = silk_ADD_LSHIFT32( nrg, silk_SMMUL( silk_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ), - Atmp1 ), 32 - QA - lz ); /* Q( 1-rshifts ) */ - } - CAf[ n + 1 ] = tmp1; /* Q( -rshifts ) */ - CAb[ n + 1 ] = tmp2; /* Q( -rshifts ) */ - num = silk_ADD32( num, tmp2 ); /* Q( -rshifts ) */ - num = silk_LSHIFT32( -num, 1 ); /* Q( 1-rshifts ) */ - - /* Calculate the next order reflection (parcor) coefficient */ - if( silk_abs( num ) < nrg ) { - rc_Q31 = silk_DIV32_varQ( num, nrg, 31 ); - } else { - rc_Q31 = ( num > 0 ) ? silk_int32_MAX : silk_int32_MIN; - } - - /* Update inverse prediction gain */ - tmp1 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); - tmp1 = silk_LSHIFT( silk_SMMUL( invGain_Q30, tmp1 ), 2 ); - if( tmp1 <= minInvGain_Q30 ) { - /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */ - tmp2 = ( (opus_int32)1 << 30 ) - silk_DIV32_varQ( minInvGain_Q30, invGain_Q30, 30 ); /* Q30 */ - rc_Q31 = silk_SQRT_APPROX( tmp2 ); /* Q15 */ - /* Newton-Raphson iteration */ - rc_Q31 = silk_RSHIFT32( rc_Q31 + silk_DIV32( tmp2, rc_Q31 ), 1 ); /* Q15 */ - rc_Q31 = silk_LSHIFT32( rc_Q31, 16 ); /* Q31 */ - if( num < 0 ) { - /* Ensure adjusted reflection coefficients has the original sign */ - rc_Q31 = -rc_Q31; - } - invGain_Q30 = minInvGain_Q30; - reached_max_gain = 1; - } else { - invGain_Q30 = tmp1; - } - - /* Update the AR coefficients */ - for( k = 0; k < (n + 1) >> 1; k++ ) { - tmp1 = Af_QA[ k ]; /* QA */ - tmp2 = Af_QA[ n - k - 1 ]; /* QA */ - Af_QA[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* QA */ - Af_QA[ n - k - 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* QA */ - } - Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA ); /* QA */ - - if( reached_max_gain ) { - /* Reached max prediction gain; set remaining coefficients to zero and exit loop */ - for( k = n + 1; k < D; k++ ) { - Af_QA[ k ] = 0; - } - break; - } - - /* Update C * Af and C * Ab */ - for( k = 0; k <= n + 1; k++ ) { - tmp1 = CAf[ k ]; /* Q( -rshifts ) */ - tmp2 = CAb[ n - k + 1 ]; /* Q( -rshifts ) */ - CAf[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* Q( -rshifts ) */ - CAb[ n - k + 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* Q( -rshifts ) */ - } - } - - if( reached_max_gain ) { - for( k = 0; k < D; k++ ) { - /* Scale coefficients */ - A_Q16[ k ] = -silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); - } - /* Subtract energy of preceding samples from C0 */ - if( rshifts > 0 ) { - for( s = 0; s < nb_subfr; s++ ) { - x_ptr = x + s * subfr_length; - C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr, D, arch ), rshifts ); - } - } else { - for( s = 0; s < nb_subfr; s++ ) { - x_ptr = x + s * subfr_length; - C0 -= silk_LSHIFT32( silk_inner_prod_aligned( x_ptr, x_ptr, D, arch), -rshifts); - } - } - /* Approximate residual energy */ - *res_nrg = silk_LSHIFT( silk_SMMUL( invGain_Q30, C0 ), 2 ); - *res_nrg_Q = -rshifts; - } else { - /* Return residual energy */ - nrg = CAf[ 0 ]; /* Q( -rshifts ) */ - tmp1 = (opus_int32)1 << 16; /* Q16 */ - for( k = 0; k < D; k++ ) { - Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); /* Q16 */ - nrg = silk_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); /* Q( -rshifts ) */ - tmp1 = silk_SMLAWW( tmp1, Atmp1, Atmp1 ); /* Q16 */ - A_Q16[ k ] = -Atmp1; - } - *res_nrg = silk_SMLAWW( nrg, silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ), -tmp1 );/* Q( -rshifts ) */ - *res_nrg_Q = -rshifts; - } -} diff --git a/drivers/opus/silk/fixed/corrMatrix_FIX.c b/drivers/opus/silk/fixed/corrMatrix_FIX.c deleted file mode 100644 index ac5331fe57..0000000000 --- a/drivers/opus/silk/fixed/corrMatrix_FIX.c +++ /dev/null @@ -1,155 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -/********************************************************************** - * Correlation Matrix Computations for LS estimate. - **********************************************************************/ - -#include "opus/silk/fixed/main_FIX.h" - -/* 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 */ -) -{ - opus_int lag, i; - const opus_int16 *ptr1, *ptr2; - opus_int32 inner_prod; - - ptr1 = &x[ order - 1 ]; /* Points to first sample of column 0 of X: X[:,0] */ - ptr2 = t; - /* Calculate X'*t */ - if( rshifts > 0 ) { - /* Right shifting used */ - for( lag = 0; lag < order; lag++ ) { - inner_prod = 0; - for( i = 0; i < L; i++ ) { - inner_prod += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts ); - } - Xt[ lag ] = inner_prod; /* X[:,lag]'*t */ - ptr1--; /* Go to next column of X */ - } - } else { - silk_assert( rshifts == 0 ); - for( lag = 0; lag < order; lag++ ) { - Xt[ lag ] = silk_inner_prod_aligned( ptr1, ptr2, L, arch ); /* X[:,lag]'*t */ - ptr1--; /* Go to next column of X */ - } - } -} - -/* 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 */ - const opus_int head_room, /* I Desired headroom */ - opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */ - opus_int *rshifts, /* I/O Right shifts of correlations */ - int arch /* I Run-time architecture */ -) -{ - opus_int i, j, lag, rshifts_local, head_room_rshifts; - opus_int32 energy; - const opus_int16 *ptr1, *ptr2; - - /* Calculate energy to find shift used to fit in 32 bits */ - silk_sum_sqr_shift( &energy, &rshifts_local, x, L + order - 1 ); - /* Add shifts to get the desired head room */ - head_room_rshifts = silk_max( head_room - silk_CLZ32( energy ), 0 ); - - energy = silk_RSHIFT32( energy, head_room_rshifts ); - rshifts_local += head_room_rshifts; - - /* Calculate energy of first column (0) of X: X[:,0]'*X[:,0] */ - /* Remove contribution of first order - 1 samples */ - for( i = 0; i < order - 1; i++ ) { - energy -= silk_RSHIFT32( silk_SMULBB( x[ i ], x[ i ] ), rshifts_local ); - } - if( rshifts_local < *rshifts ) { - /* Adjust energy */ - energy = silk_RSHIFT32( energy, *rshifts - rshifts_local ); - rshifts_local = *rshifts; - } - - /* Calculate energy of remaining columns of X: X[:,j]'*X[:,j] */ - /* Fill out the diagonal of the correlation matrix */ - matrix_ptr( XX, 0, 0, order ) = energy; - ptr1 = &x[ order - 1 ]; /* First sample of column 0 of X */ - for( j = 1; j < order; j++ ) { - energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), rshifts_local ) ); - energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr1[ -j ] ), rshifts_local ) ); - matrix_ptr( XX, j, j, order ) = energy; - } - - ptr2 = &x[ order - 2 ]; /* First sample of column 1 of X */ - /* Calculate the remaining elements of the correlation matrix */ - if( rshifts_local > 0 ) { - /* Right shifting used */ - for( lag = 1; lag < order; lag++ ) { - /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */ - energy = 0; - for( i = 0; i < L; i++ ) { - energy += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts_local ); - } - /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */ - matrix_ptr( XX, lag, 0, order ) = energy; - matrix_ptr( XX, 0, lag, order ) = energy; - for( j = 1; j < ( order - lag ); j++ ) { - energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), rshifts_local ) ); - energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr2[ -j ] ), rshifts_local ) ); - matrix_ptr( XX, lag + j, j, order ) = energy; - matrix_ptr( XX, j, lag + j, order ) = energy; - } - ptr2--; /* Update pointer to first sample of next column (lag) in X */ - } - } else { - for( lag = 1; lag < order; lag++ ) { - /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */ - energy = silk_inner_prod_aligned( ptr1, ptr2, L, arch ); - matrix_ptr( XX, lag, 0, order ) = energy; - matrix_ptr( XX, 0, lag, order ) = energy; - /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */ - for( j = 1; j < ( order - lag ); j++ ) { - energy = silk_SUB32( energy, silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ) ); - energy = silk_SMLABB( energy, ptr1[ -j ], ptr2[ -j ] ); - matrix_ptr( XX, lag + j, j, order ) = energy; - matrix_ptr( XX, j, lag + j, order ) = energy; - } - ptr2--;/* Update pointer to first sample of next column (lag) in X */ - } - } - *rshifts = rshifts_local; -} - diff --git a/drivers/opus/silk/fixed/encode_frame_FIX.c b/drivers/opus/silk/fixed/encode_frame_FIX.c deleted file mode 100644 index e4ead0afef..0000000000 --- a/drivers/opus/silk/fixed/encode_frame_FIX.c +++ /dev/null @@ -1,384 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" -#include "opus/celt/stack_alloc.h" -#include "opus/silk/tuning_parameters.h" - -/* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate */ -static OPUS_INLINE void silk_LBRR_encode_FIX( - silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ - silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ - const opus_int32 xfw_Q3[], /* I Input signal */ - opus_int condCoding /* I The type of conditional coding used so far for this frame */ -); - -void silk_encode_do_VAD_FIX( - silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk FIX encoder state */ -) -{ - /****************************/ - /* Voice Activity Detection */ - /****************************/ - silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch ); - - /**************************************************/ - /* Convert speech activity into VAD and DTX flags */ - /**************************************************/ - if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) { - 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_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 */ -) -{ - silk_encoder_control_FIX sEncCtrl; - opus_int i, iter, maxIter, found_upper, found_lower, ret = 0; - opus_int16 *x_frame; - ec_enc sRangeEnc_copy, sRangeEnc_copy2; - silk_nsq_state sNSQ_copy, sNSQ_copy2; - 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; - SAVE_STACK; - - /* 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 */ - /*************************************************************/ - /* start of frame to encode */ - x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; - - /***************************************/ - /* 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_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length * sizeof( opus_int16 ) ); - - if( !psEnc->sCmn.prefillFlag ) { - VARDECL( opus_int32, xfw_Q3 ); - VARDECL( opus_int16, res_pitch ); - VARDECL( opus_uint8, ec_buf_copy ); - opus_int16 *res_pitch_frame; - - ALLOC( res_pitch, - psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length - + psEnc->sCmn.ltp_mem_length, opus_int16 ); - /* start of pitch LPC residual frame */ - res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length; - - /*****************************************/ - /* Find pitch lags, initial LPC analysis */ - /*****************************************/ - silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame, psEnc->sCmn.arch ); - - /************************/ - /* Noise shape analysis */ - /************************/ - silk_noise_shape_analysis_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, psEnc->sCmn.arch ); - - /***************************************************/ - /* Find linear prediction coefficients (LPC + LTP) */ - /***************************************************/ - silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch, x_frame, condCoding ); - - /****************************************/ - /* Process gains */ - /****************************************/ - silk_process_gains_FIX( psEnc, &sEncCtrl, condCoding ); - - /*****************************************/ - /* Prefiltering for noise shaper */ - /*****************************************/ - ALLOC( xfw_Q3, psEnc->sCmn.frame_length, opus_int32 ); - silk_prefilter_FIX( psEnc, &sEncCtrl, xfw_Q3, x_frame ); - - /****************************************/ - /* Low Bitrate Redundant Encoding */ - /****************************************/ - silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw_Q3, condCoding ); - - /* Loop over quantizer and entropy 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, &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, 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 */ - /*****************************************/ - if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { - silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses, - sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, - sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14, - psEnc->sCmn.arch ); - } else { - silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses, - sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, - sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14, - psEnc->sCmn.arch); - } - - /****************************************/ - /* 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( 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 ) ); - silk_assert( sRangeEnc_copy2.offs <= 1275 ); - silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs ); - silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, 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_Q10 = silk_ADD_RSHIFT32( sEncCtrl.Lambda_Q10, sEncCtrl.Lambda_Q10, 1 ); - found_upper = 0; - gainsID_upper = -1; - } else { - found_upper = 1; - nBits_upper = nBits; - gainMult_upper = gainMult_Q8; - gainsID_upper = gainsID; - } - } else if( nBits < maxBits - 5 ) { - 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 ) ); - silk_assert( psRangeEnc->offs <= 1275 ); - silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs ); - silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); - LastGainIndex_copy2 = psEnc->sShape.LastGainIndex; - } - } else { - /* Within 5 bits of budget: close enough */ - break; - } - - if( ( found_lower & found_upper ) == 0 ) { - /* Adjust gain according to high-rate rate/distortion curve */ - opus_int32 gain_factor_Q16; - gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) ); - gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) ); - if( nBits > maxBits ) { - gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) ); - } - gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 ); - } else { - /* Adjust gain by interpolating */ - gainMult_Q8 = gainMult_lower + silk_DIV32_16( silk_MUL( gainMult_upper - gainMult_lower, maxBits - nBits_lower ), nBits_upper - nBits_lower ); - /* New gain multplier 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++ ) { - sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 ); - } - - /* Quantize gains */ - psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev; - silk_gains_quant( psEnc->sCmn.indices.GainsIndices, sEncCtrl.Gains_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 ); - } - } - - /* 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( opus_int16 ) ); - - /* 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_FIX( - silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ - silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ - const opus_int32 xfw_Q3[], /* I Input signal */ - opus_int condCoding /* I The type of conditional coding used so far for this frame */ -) -{ - opus_int32 TempGains_Q16[ MAX_NB_SUBFR ]; - SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ]; - silk_nsq_state sNSQ_LBRR; - - /*******************************************/ - /* Control use of inband LBRR */ - /*******************************************/ - if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { - psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1; - - /* Copy noise shaping quantizer state and quantization indices from regular encoding */ - silk_memcpy( &sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); - silk_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) ); - - /* Save original gains */ - silk_memcpy( TempGains_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); - - 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 ] = 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 */ - /* Overwrite unquantized gains with quantized gains */ - silk_gains_dequant( psEncCtrl->Gains_Q16, psIndices_LBRR->GainsIndices, - &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); - - /*****************************************/ - /* Noise shaping quantization */ - /*****************************************/ - if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { - silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3, - psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, - psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, - psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch ); - } else { - silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3, - psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, - psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, - psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch ); - } - - /* Restore original gains */ - silk_memcpy( psEncCtrl->Gains_Q16, TempGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); - } -} diff --git a/drivers/opus/silk/fixed/find_LPC_FIX.c b/drivers/opus/silk/fixed/find_LPC_FIX.c deleted file mode 100644 index 5b56c41702..0000000000 --- a/drivers/opus/silk/fixed/find_LPC_FIX.c +++ /dev/null @@ -1,148 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" -#include "opus/celt/stack_alloc.h" -#include "opus/silk/tuning_parameters.h" - -/* Finds LPC vector from correlations, and converts to NLSF */ -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 */ -) -{ - opus_int k, subfr_length; - opus_int32 a_Q16[ MAX_LPC_ORDER ]; - opus_int isInterpLower, shift; - opus_int32 res_nrg0, res_nrg1; - opus_int rshift0, rshift1; - - /* Used only for LSF interpolation */ - opus_int32 a_tmp_Q16[ MAX_LPC_ORDER ], res_nrg_interp, res_nrg, res_tmp_nrg; - opus_int res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q; - opus_int16 a_tmp_Q12[ MAX_LPC_ORDER ]; - opus_int16 NLSF0_Q15[ MAX_LPC_ORDER ]; - SAVE_STACK; - - subfr_length = psEncC->subfr_length + psEncC->predictLPCOrder; - - /* Default: no interpolation */ - psEncC->indices.NLSFInterpCoef_Q2 = 4; - - /* Burg AR analysis for the full frame */ - silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, minInvGain_Q30, subfr_length, psEncC->nb_subfr, psEncC->predictLPCOrder, psEncC->arch ); - - if( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) { - VARDECL( opus_int16, LPC_res ); - - /* Optimal solution for last 10 ms */ - silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + 2 * subfr_length, minInvGain_Q30, subfr_length, 2, psEncC->predictLPCOrder, psEncC->arch ); - - /* 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 */ - shift = res_tmp_nrg_Q - res_nrg_Q; - if( shift >= 0 ) { - if( shift < 32 ) { - res_nrg = res_nrg - silk_RSHIFT( res_tmp_nrg, shift ); - } - } else { - silk_assert( shift > -32 ); - res_nrg = silk_RSHIFT( res_nrg, -shift ) - res_tmp_nrg; - res_nrg_Q = res_tmp_nrg_Q; - } - - /* Convert to NLSFs */ - silk_A2NLSF( NLSF_Q15, a_tmp_Q16, psEncC->predictLPCOrder ); - - ALLOC( LPC_res, 2 * subfr_length, opus_int16 ); - - /* Search over interpolation indices to find the one with lowest residual energy */ - 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( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder ); - - /* Calculate residual energy with NLSF interpolation */ - silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, psEncC->predictLPCOrder, psEncC->arch ); - - silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + psEncC->predictLPCOrder, subfr_length - psEncC->predictLPCOrder ); - silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder ); - - /* Add subframe energies from first half frame */ - shift = rshift0 - rshift1; - if( shift >= 0 ) { - res_nrg1 = silk_RSHIFT( res_nrg1, shift ); - res_nrg_interp_Q = -rshift0; - } else { - res_nrg0 = silk_RSHIFT( res_nrg0, -shift ); - res_nrg_interp_Q = -rshift1; - } - res_nrg_interp = silk_ADD32( res_nrg0, res_nrg1 ); - - /* Compare with first half energy without NLSF interpolation, or best interpolated value so far */ - shift = res_nrg_interp_Q - res_nrg_Q; - if( shift >= 0 ) { - if( silk_RSHIFT( res_nrg_interp, shift ) < res_nrg ) { - isInterpLower = silk_TRUE; - } else { - isInterpLower = silk_FALSE; - } - } else { - if( -shift < 32 ) { - if( res_nrg_interp < silk_RSHIFT( res_nrg, -shift ) ) { - isInterpLower = silk_TRUE; - } else { - isInterpLower = silk_FALSE; - } - } else { - isInterpLower = silk_FALSE; - } - } - - /* Determine whether current interpolated NLSFs are best so far */ - if( isInterpLower == silk_TRUE ) { - /* Interpolation has lower residual energy */ - res_nrg = res_nrg_interp; - res_nrg_Q = res_nrg_interp_Q; - psEncC->indices.NLSFInterpCoef_Q2 = (opus_int8)k; - } - } - } - - if( psEncC->indices.NLSFInterpCoef_Q2 == 4 ) { - /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */ - silk_A2NLSF( NLSF_Q15, a_Q16, psEncC->predictLPCOrder ); - } - - silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) ); - RESTORE_STACK; -} diff --git a/drivers/opus/silk/fixed/find_LTP_FIX.c b/drivers/opus/silk/fixed/find_LTP_FIX.c deleted file mode 100644 index a5a253516d..0000000000 --- a/drivers/opus/silk/fixed/find_LTP_FIX.c +++ /dev/null @@ -1,242 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" -#include "opus/silk/tuning_parameters.h" - -/* Head room for correlations */ -#define LTP_CORRS_HEAD_ROOM 2 - -void silk_fit_LTP( - opus_int32 LTP_coefs_Q16[ LTP_ORDER ], - opus_int16 LTP_coefs_Q14[ LTP_ORDER ] -); - -void silk_find_LTP_FIX( - opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ - opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ - opus_int *LTPredCodGain_Q7, /* O LTP coding gain */ - const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */ - const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ - const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */ - const opus_int subfr_length, /* I subframe length */ - const opus_int nb_subfr, /* I number of subframes */ - const opus_int mem_offset, /* I number of samples in LTP memory */ - opus_int corr_rshifts[ MAX_NB_SUBFR ], /* O right shifts applied to correlations */ - int arch /* I Run-time architecture */ -) -{ - opus_int i, k, lshift; - const opus_int16 *r_ptr, *lag_ptr; - opus_int16 *b_Q14_ptr; - - opus_int32 regu; - opus_int32 *WLTP_ptr; - opus_int32 b_Q16[ LTP_ORDER ], delta_b_Q14[ LTP_ORDER ], d_Q14[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], g_Q26; - opus_int32 w[ MAX_NB_SUBFR ], WLTP_max, max_abs_d_Q14, max_w_bits; - - opus_int32 temp32, denom32; - opus_int extra_shifts; - opus_int rr_shifts, maxRshifts, maxRshifts_wxtra, LZs; - opus_int32 LPC_res_nrg, LPC_LTP_res_nrg, div_Q16; - opus_int32 Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ]; - opus_int32 wd, m_Q12; - - b_Q14_ptr = b_Q14; - WLTP_ptr = WLTP; - r_ptr = &r_lpc[ mem_offset ]; - for( k = 0; k < nb_subfr; k++ ) { - lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 ); - - silk_sum_sqr_shift( &rr[ k ], &rr_shifts, r_ptr, subfr_length ); /* rr[ k ] in Q( -rr_shifts ) */ - - /* Assure headroom */ - LZs = silk_CLZ32( rr[k] ); - if( LZs < LTP_CORRS_HEAD_ROOM ) { - rr[ k ] = silk_RSHIFT_ROUND( rr[ k ], LTP_CORRS_HEAD_ROOM - LZs ); - rr_shifts += ( LTP_CORRS_HEAD_ROOM - LZs ); - } - corr_rshifts[ k ] = rr_shifts; - silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, LTP_CORRS_HEAD_ROOM, WLTP_ptr, &corr_rshifts[ k ], arch ); /* WLTP_fix_ptr in Q( -corr_rshifts[ k ] ) */ - - /* The correlation vector always has lower max abs value than rr and/or RR so head room is assured */ - silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr, corr_rshifts[ k ], arch ); /* Rr_fix_ptr in Q( -corr_rshifts[ k ] ) */ - if( corr_rshifts[ k ] > rr_shifts ) { - rr[ k ] = silk_RSHIFT( rr[ k ], corr_rshifts[ k ] - rr_shifts ); /* rr[ k ] in Q( -corr_rshifts[ k ] ) */ - } - silk_assert( rr[ k ] >= 0 ); - - regu = 1; - regu = silk_SMLAWB( regu, rr[ k ], SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); - regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); - regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); - silk_regularize_correlations_FIX( WLTP_ptr, &rr[k], regu, LTP_ORDER ); - - silk_solve_LDL_FIX( WLTP_ptr, LTP_ORDER, Rr, b_Q16 ); /* WLTP_fix_ptr and Rr_fix_ptr both in Q(-corr_rshifts[k]) */ - - /* Limit and store in Q14 */ - silk_fit_LTP( b_Q16, b_Q14_ptr ); - - /* Calculate residual energy */ - nrg[ k ] = silk_residual_energy16_covar_FIX( b_Q14_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER, 14 ); /* nrg_fix in Q( -corr_rshifts[ k ] ) */ - - /* temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); */ - extra_shifts = silk_min_int( corr_rshifts[ k ], LTP_CORRS_HEAD_ROOM ); - denom32 = silk_LSHIFT_SAT32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 + extra_shifts ) + /* Q( -corr_rshifts[ k ] + extra_shifts ) */ - silk_RSHIFT( silk_SMULWB( (opus_int32)subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts ); /* Q( -corr_rshifts[ k ] + extra_shifts ) */ - denom32 = silk_max( denom32, 1 ); - silk_assert( ((opus_int64)Wght_Q15[ k ] << 16 ) < silk_int32_MAX ); /* Wght always < 0.5 in Q0 */ - temp32 = silk_DIV32( silk_LSHIFT( (opus_int32)Wght_Q15[ k ], 16 ), denom32 ); /* Q( 15 + 16 + corr_rshifts[k] - extra_shifts ) */ - temp32 = silk_RSHIFT( temp32, 31 + corr_rshifts[ k ] - extra_shifts - 26 ); /* Q26 */ - - /* Limit temp such that the below scaling never wraps around */ - WLTP_max = 0; - for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) { - WLTP_max = silk_max( WLTP_ptr[ i ], WLTP_max ); - } - lshift = silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */ - silk_assert( 26 - 18 + lshift >= 0 ); - if( 26 - 18 + lshift < 31 ) { - temp32 = silk_min_32( temp32, silk_LSHIFT( (opus_int32)1, 26 - 18 + lshift ) ); - } - - silk_scale_vector32_Q26_lshift_18( WLTP_ptr, temp32, LTP_ORDER * LTP_ORDER ); /* WLTP_ptr in Q( 18 - corr_rshifts[ k ] ) */ - - w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER/2, LTP_ORDER/2, LTP_ORDER ); /* w in Q( 18 - corr_rshifts[ k ] ) */ - silk_assert( w[k] >= 0 ); - - r_ptr += subfr_length; - b_Q14_ptr += LTP_ORDER; - WLTP_ptr += LTP_ORDER * LTP_ORDER; - } - - maxRshifts = 0; - for( k = 0; k < nb_subfr; k++ ) { - maxRshifts = silk_max_int( corr_rshifts[ k ], maxRshifts ); - } - - /* Compute LTP coding gain */ - if( LTPredCodGain_Q7 != NULL ) { - LPC_LTP_res_nrg = 0; - LPC_res_nrg = 0; - silk_assert( LTP_CORRS_HEAD_ROOM >= 2 ); /* Check that no overflow will happen when adding */ - for( k = 0; k < nb_subfr; k++ ) { - LPC_res_nrg = silk_ADD32( LPC_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( rr[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */ - LPC_LTP_res_nrg = silk_ADD32( LPC_LTP_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */ - } - LPC_LTP_res_nrg = silk_max( LPC_LTP_res_nrg, 1 ); /* avoid division by zero */ - - div_Q16 = silk_DIV32_varQ( LPC_res_nrg, LPC_LTP_res_nrg, 16 ); - *LTPredCodGain_Q7 = ( opus_int )silk_SMULBB( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ); - - silk_assert( *LTPredCodGain_Q7 == ( opus_int )silk_SAT16( silk_MUL( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ) ) ); - } - - /* smoothing */ - /* d = sum( B, 1 ); */ - b_Q14_ptr = b_Q14; - for( k = 0; k < nb_subfr; k++ ) { - d_Q14[ k ] = 0; - for( i = 0; i < LTP_ORDER; i++ ) { - d_Q14[ k ] += b_Q14_ptr[ i ]; - } - b_Q14_ptr += LTP_ORDER; - } - - /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */ - - /* Find maximum absolute value of d_Q14 and the bits used by w in Q0 */ - max_abs_d_Q14 = 0; - max_w_bits = 0; - for( k = 0; k < nb_subfr; k++ ) { - max_abs_d_Q14 = silk_max_32( max_abs_d_Q14, silk_abs( d_Q14[ k ] ) ); - /* w[ k ] is in Q( 18 - corr_rshifts[ k ] ) */ - /* Find bits needed in Q( 18 - maxRshifts ) */ - max_w_bits = silk_max_32( max_w_bits, 32 - silk_CLZ32( w[ k ] ) + corr_rshifts[ k ] - maxRshifts ); - } - - /* max_abs_d_Q14 = (5 << 15); worst case, i.e. LTP_ORDER * -silk_int16_MIN */ - silk_assert( max_abs_d_Q14 <= ( 5 << 15 ) ); - - /* How many bits is needed for w*d' in Q( 18 - maxRshifts ) in the worst case, of all d_Q14's being equal to max_abs_d_Q14 */ - extra_shifts = max_w_bits + 32 - silk_CLZ32( max_abs_d_Q14 ) - 14; - - /* Subtract what we got available; bits in output var plus maxRshifts */ - extra_shifts -= ( 32 - 1 - 2 + maxRshifts ); /* Keep sign bit free as well as 2 bits for accumulation */ - extra_shifts = silk_max_int( extra_shifts, 0 ); - - maxRshifts_wxtra = maxRshifts + extra_shifts; - - temp32 = silk_RSHIFT( 262, maxRshifts + extra_shifts ) + 1; /* 1e-3f in Q( 18 - (maxRshifts + extra_shifts) ) */ - wd = 0; - for( k = 0; k < nb_subfr; k++ ) { - /* w has at least 2 bits of headroom so no overflow should happen */ - temp32 = silk_ADD32( temp32, silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ) ); /* Q( 18 - maxRshifts_wxtra ) */ - wd = silk_ADD32( wd, silk_LSHIFT( silk_SMULWW( silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ), d_Q14[ k ] ), 2 ) ); /* Q( 18 - maxRshifts_wxtra ) */ - } - m_Q12 = silk_DIV32_varQ( wd, temp32, 12 ); - - b_Q14_ptr = b_Q14; - for( k = 0; k < nb_subfr; k++ ) { - /* w_fix[ k ] from Q( 18 - corr_rshifts[ k ] ) to Q( 16 ) */ - if( 2 - corr_rshifts[k] > 0 ) { - temp32 = silk_RSHIFT( w[ k ], 2 - corr_rshifts[ k ] ); - } else { - temp32 = silk_LSHIFT_SAT32( w[ k ], corr_rshifts[ k ] - 2 ); - } - - g_Q26 = silk_MUL( - silk_DIV32( - SILK_FIX_CONST( LTP_SMOOTHING, 26 ), - silk_RSHIFT( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), 10 ) + temp32 ), /* Q10 */ - silk_LSHIFT_SAT32( silk_SUB_SAT32( (opus_int32)m_Q12, silk_RSHIFT( d_Q14[ k ], 2 ) ), 4 ) ); /* Q16 */ - - temp32 = 0; - for( i = 0; i < LTP_ORDER; i++ ) { - delta_b_Q14[ i ] = silk_max_16( b_Q14_ptr[ i ], 1638 ); /* 1638_Q14 = 0.1_Q0 */ - temp32 += delta_b_Q14[ i ]; /* Q14 */ - } - temp32 = silk_DIV32( g_Q26, temp32 ); /* Q14 -> Q12 */ - for( i = 0; i < LTP_ORDER; i++ ) { - b_Q14_ptr[ i ] = silk_LIMIT_32( (opus_int32)b_Q14_ptr[ i ] + silk_SMULWB( silk_LSHIFT_SAT32( temp32, 4 ), delta_b_Q14[ i ] ), -16000, 28000 ); - } - b_Q14_ptr += LTP_ORDER; - } -} - -void silk_fit_LTP( - opus_int32 LTP_coefs_Q16[ LTP_ORDER ], - opus_int16 LTP_coefs_Q14[ LTP_ORDER ] -) -{ - opus_int i; - - for( i = 0; i < LTP_ORDER; i++ ) { - LTP_coefs_Q14[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( LTP_coefs_Q16[ i ], 2 ) ); - } -} diff --git a/drivers/opus/silk/fixed/find_pitch_lags_FIX.c b/drivers/opus/silk/fixed/find_pitch_lags_FIX.c deleted file mode 100644 index bfd2c1b2d2..0000000000 --- a/drivers/opus/silk/fixed/find_pitch_lags_FIX.c +++ /dev/null @@ -1,142 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" -#include "opus/celt/stack_alloc.h" -#include "opus/silk/tuning_parameters.h" - -/* 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 */ -) -{ - opus_int buf_len, i, scale; - opus_int32 thrhld_Q13, res_nrg; - const opus_int16 *x_buf, *x_buf_ptr; - VARDECL( opus_int16, Wsig ); - opus_int16 *Wsig_ptr; - opus_int32 auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ]; - opus_int16 rc_Q15[ MAX_FIND_PITCH_LPC_ORDER ]; - opus_int32 A_Q24[ MAX_FIND_PITCH_LPC_ORDER ]; - opus_int16 A_Q12[ MAX_FIND_PITCH_LPC_ORDER ]; - SAVE_STACK; - - /******************************************/ - /* 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 */ - silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length ); - - x_buf = x - psEnc->sCmn.ltp_mem_length; - - /*************************************/ - /* Estimate LPC AR coefficients */ - /*************************************/ - - /* Calculate windowed signal */ - - ALLOC( Wsig, psEnc->sCmn.pitch_LPC_win_length, opus_int16 ); - - /* First LA_LTP samples */ - x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length; - Wsig_ptr = Wsig; - silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch ); - - /* Middle un - 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 - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) ); - - /* Last LA_LTP samples */ - Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ); - x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ); - silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch ); - - /* Calculate autocorrelation sequence */ - silk_autocorr( auto_corr, &scale, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1, arch ); - - /* Add white noise, as fraction of energy */ - auto_corr[ 0 ] = silk_SMLAWB( auto_corr[ 0 ], auto_corr[ 0 ], SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ) + 1; - - /* Calculate the reflection coefficients using schur */ - res_nrg = silk_schur( rc_Q15, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder ); - - /* Prediction gain */ - psEncCtrl->predGain_Q16 = silk_DIV32_varQ( auto_corr[ 0 ], silk_max_int( res_nrg, 1 ), 16 ); - - /* Convert reflection coefficients to prediction coefficients */ - silk_k2a( A_Q24, rc_Q15, psEnc->sCmn.pitchEstimationLPCOrder ); - - /* Convert From 32 bit Q24 to 16 bit Q12 coefs */ - for( i = 0; i < psEnc->sCmn.pitchEstimationLPCOrder; i++ ) { - A_Q12[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT( A_Q24[ i ], 12 ) ); - } - - /* Do BWE */ - silk_bwexpander( A_Q12, psEnc->sCmn.pitchEstimationLPCOrder, SILK_FIX_CONST( FIND_PITCH_BANDWIDTH_EXPANSION, 16 ) ); - - /*****************************************/ - /* LPC analysis filtering */ - /*****************************************/ - silk_LPC_analysis_filter( res, x_buf, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder, psEnc->sCmn.arch ); - - if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) { - /* Threshold for pitch estimator */ - thrhld_Q13 = SILK_FIX_CONST( 0.6, 13 ); - thrhld_Q13 = silk_SMLABB( thrhld_Q13, SILK_FIX_CONST( -0.004, 13 ), psEnc->sCmn.pitchEstimationLPCOrder ); - thrhld_Q13 = silk_SMLAWB( thrhld_Q13, SILK_FIX_CONST( -0.1, 21 ), psEnc->sCmn.speech_activity_Q8 ); - thrhld_Q13 = silk_SMLABB( thrhld_Q13, SILK_FIX_CONST( -0.15, 13 ), silk_RSHIFT( psEnc->sCmn.prevSignalType, 1 ) ); - thrhld_Q13 = silk_SMLAWB( thrhld_Q13, SILK_FIX_CONST( -0.1, 14 ), psEnc->sCmn.input_tilt_Q15 ); - thrhld_Q13 = silk_SAT16( thrhld_Q13 ); - - /*****************************************/ - /* Call pitch estimator */ - /*****************************************/ - if( silk_pitch_analysis_core( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex, &psEnc->sCmn.indices.contourIndex, - &psEnc->LTPCorr_Q15, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16, - (opus_int)thrhld_Q13, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr, - psEnc->sCmn.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_Q15 = 0; - } - RESTORE_STACK; -} diff --git a/drivers/opus/silk/fixed/find_pred_coefs_FIX.c b/drivers/opus/silk/fixed/find_pred_coefs_FIX.c deleted file mode 100644 index d0280963bd..0000000000 --- a/drivers/opus/silk/fixed/find_pred_coefs_FIX.c +++ /dev/null @@ -1,145 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" -#include "opus/celt/stack_alloc.h" - -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 */ -) -{ - opus_int i; - opus_int32 invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ], Wght_Q15[ MAX_NB_SUBFR ]; - opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; - const opus_int16 *x_ptr; - opus_int16 *x_pre_ptr; - VARDECL( opus_int16, LPC_in_pre ); - opus_int32 tmp, min_gain_Q16, minInvGain_Q30; - opus_int LTP_corrs_rshift[ MAX_NB_SUBFR ]; - SAVE_STACK; - - /* weighting for weighted least squares */ - min_gain_Q16 = silk_int32_MAX >> 6; - for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { - min_gain_Q16 = silk_min( min_gain_Q16, psEncCtrl->Gains_Q16[ i ] ); - } - for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { - /* Divide to Q16 */ - silk_assert( psEncCtrl->Gains_Q16[ i ] > 0 ); - /* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */ - invGains_Q16[ i ] = silk_DIV32_varQ( min_gain_Q16, psEncCtrl->Gains_Q16[ i ], 16 - 2 ); - - /* Ensure Wght_Q15 a minimum value 1 */ - invGains_Q16[ i ] = silk_max( invGains_Q16[ i ], 363 ); - - /* Square the inverted gains */ - silk_assert( invGains_Q16[ i ] == silk_SAT16( invGains_Q16[ i ] ) ); - tmp = silk_SMULWB( invGains_Q16[ i ], invGains_Q16[ i ] ); - Wght_Q15[ i ] = silk_RSHIFT( tmp, 1 ); - - /* Invert the inverted and normalized gains */ - local_gains[ i ] = silk_DIV32( ( (opus_int32)1 << 16 ), invGains_Q16[ i ] ); - } - - ALLOC( LPC_in_pre, - psEnc->sCmn.nb_subfr * psEnc->sCmn.predictLPCOrder - + psEnc->sCmn.frame_length, opus_int16 ); - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - VARDECL( opus_int32, WLTP ); - - /**********/ - /* VOICED */ - /**********/ - silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 ); - - ALLOC( WLTP, psEnc->sCmn.nb_subfr * LTP_ORDER * LTP_ORDER, opus_int32 ); - - /* LTP analysis */ - silk_find_LTP_FIX( psEncCtrl->LTPCoef_Q14, WLTP, &psEncCtrl->LTPredCodGain_Q7, - res_pitch, psEncCtrl->pitchL, Wght_Q15, psEnc->sCmn.subfr_length, - psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length, LTP_corrs_rshift, psEnc->sCmn.arch ); - - /* Quantize LTP gain parameters */ - silk_quant_LTP_gains( psEncCtrl->LTPCoef_Q14, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex, - &psEnc->sCmn.sum_log_gain_Q7, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr, - psEnc->sCmn.arch); - - /* Control LTP scaling */ - silk_LTP_scale_ctrl_FIX( psEnc, psEncCtrl, condCoding ); - - /* Create LTP residual */ - silk_LTP_analysis_filter_FIX( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef_Q14, - psEncCtrl->pitchL, invGains_Q16, 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_vector16( x_pre_ptr, x_ptr, invGains_Q16[ 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_Q14, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( opus_int16 ) ); - psEncCtrl->LTPredCodGain_Q7 = 0; - psEnc->sCmn.sum_log_gain_Q7 = 0; - } - - /* Limit on total predictive coding gain */ - if( psEnc->sCmn.first_frame_after_reset ) { - minInvGain_Q30 = SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN_AFTER_RESET, 30 ); - } else { - minInvGain_Q30 = silk_log2lin( silk_SMLAWB( 16 << 7, (opus_int32)psEncCtrl->LTPredCodGain_Q7, SILK_FIX_CONST( 1.0 / 3, 16 ) ) ); /* Q16 */ - minInvGain_Q30 = silk_DIV32_varQ( minInvGain_Q30, - silk_SMULWW( SILK_FIX_CONST( MAX_PREDICTION_POWER_GAIN, 0 ), - silk_SMLAWB( SILK_FIX_CONST( 0.25, 18 ), SILK_FIX_CONST( 0.75, 18 ), psEncCtrl->coding_quality_Q14 ) ), 14 ); - } - - /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */ - silk_find_LPC_FIX( &psEnc->sCmn, NLSF_Q15, LPC_in_pre, minInvGain_Q30 ); - - /* Quantize LSFs */ - silk_process_NLSFs( &psEnc->sCmn, psEncCtrl->PredCoef_Q12, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 ); - - /* Calculate residual energy using quantized LPC coefficients */ - silk_residual_energy_FIX( psEncCtrl->ResNrg, psEncCtrl->ResNrgQ, LPC_in_pre, psEncCtrl->PredCoef_Q12, local_gains, - psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder, psEnc->sCmn.arch ); - - /* 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 ) ); - RESTORE_STACK; -} diff --git a/drivers/opus/silk/fixed/k2a_FIX.c b/drivers/opus/silk/fixed/k2a_FIX.c deleted file mode 100644 index 64771f370c..0000000000 --- a/drivers/opus/silk/fixed/k2a_FIX.c +++ /dev/null @@ -1,50 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" - -/* 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 */ -) -{ - opus_int k, n; - opus_int32 Atmp[ SILK_MAX_ORDER_LPC ]; - - for( k = 0; k < order; k++ ) { - for( n = 0; n < k; n++ ) { - Atmp[ n ] = A_Q24[ n ]; - } - for( n = 0; n < k; n++ ) { - A_Q24[ n ] = silk_SMLAWB( A_Q24[ n ], silk_LSHIFT( Atmp[ k - n - 1 ], 1 ), rc_Q15[ k ] ); - } - A_Q24[ k ] = -silk_LSHIFT( (opus_int32)rc_Q15[ k ], 9 ); - } -} diff --git a/drivers/opus/silk/fixed/k2a_Q16_FIX.c b/drivers/opus/silk/fixed/k2a_Q16_FIX.c deleted file mode 100644 index 49d90a862e..0000000000 --- a/drivers/opus/silk/fixed/k2a_Q16_FIX.c +++ /dev/null @@ -1,50 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" - -/* 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 */ -) -{ - opus_int k, n; - opus_int32 Atmp[ SILK_MAX_ORDER_LPC ]; - - for( k = 0; k < order; k++ ) { - for( n = 0; n < k; n++ ) { - Atmp[ n ] = A_Q24[ n ]; - } - for( n = 0; n < k; n++ ) { - A_Q24[ n ] = silk_SMLAWW( A_Q24[ n ], Atmp[ k - n - 1 ], rc_Q16[ k ] ); - } - A_Q24[ k ] = -silk_LSHIFT( rc_Q16[ k ], 8 ); - } -} diff --git a/drivers/opus/silk/fixed/main_FIX.h b/drivers/opus/silk/fixed/main_FIX.h deleted file mode 100644 index f824c47653..0000000000 --- a/drivers/opus/silk/fixed/main_FIX.h +++ /dev/null @@ -1,272 +0,0 @@ -/*********************************************************************** -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 "opus/silk/SigProc_FIX.h" -#include "opus/silk/fixed/structs_FIX.h" -#include "opus/silk/control.h" -#include "opus/silk/main.h" -#include "opus/silk/PLC.h" -#include "opus/silk/debug.h" -#include "opus/celt/entenc.h" - -#ifndef FORCE_CPP_BUILD -#ifdef __cplusplus -extern "C" -{ -#endif -#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 - -/*********************/ -/* 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 */ -); - -/* 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_int32 TargetRate_bps, /* I Target max bitrate (bps) */ - 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 -); - -/****************/ -/* Prefiltering */ -/****************/ -void silk_prefilter_FIX( - silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ - const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */ - opus_int32 xw_Q10[], /* O Weighted signal */ - const opus_int16 x[] /* I Speech signal */ -); - -void silk_warped_LPC_analysis_filter_FIX_c( - opus_int32 state[], /* I/O State [order + 1] */ - opus_int32 res_Q2[], /* O Residual signal [length] */ - const opus_int16 coef_Q13[], /* I Coefficients [order] */ - const opus_int16 input[], /* I Input signal [length] */ - const opus_int16 lambda_Q16, /* I Warping factor */ - const opus_int length, /* I Length of input signal */ - const opus_int order /* I Filter order (even) */ -); - - -/**************************/ -/* 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( - 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) */ -); - -/* 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_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ - opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ - opus_int *LTPredCodGain_Q7, /* O LTP coding gain */ - const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */ - const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ - const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */ - const opus_int subfr_length, /* I subframe length */ - const opus_int nb_subfr, /* I number of subframes */ - const opus_int mem_offset, /* I number of samples in LTP memory */ - opus_int corr_rshifts[ MAX_NB_SUBFR ], /* O right shifts applied to correlations */ - 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 */ - const opus_int head_room, /* I Desired headroom */ - opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */ - opus_int *rshifts, /* I/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 */ -); - -/* Add noise to matrix diagonal */ -void silk_regularize_correlations_FIX( - opus_int32 *XX, /* I/O Correlation matrices */ - opus_int32 *xx, /* I/O Correlation values */ - opus_int32 noise, /* I Noise to add */ - opus_int D /* I Dimension of XX */ -); - -/* Solves Ax = b, assuming A is symmetric */ -void silk_solve_LDL_FIX( - opus_int32 *A, /* I Pointer to symetric square matrix A */ - opus_int M, /* I Size of matrix */ - const opus_int32 *b, /* I Pointer to b vector */ - opus_int32 *x_Q16 /* O Pointer to x solution vector */ -); - -#ifndef FORCE_CPP_BUILD -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* FORCE_CPP_BUILD */ -#endif /* SILK_MAIN_FIX_H */ diff --git a/drivers/opus/silk/fixed/mips/prefilter_FIX_mipsr1.h b/drivers/opus/silk/fixed/mips/prefilter_FIX_mipsr1.h deleted file mode 100644 index c7f04279a0..0000000000 --- a/drivers/opus/silk/fixed/mips/prefilter_FIX_mipsr1.h +++ /dev/null @@ -1,181 +0,0 @@ -/*********************************************************************** -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 __PREFILTER_FIX_MIPSR1_H__ -#define __PREFILTER_FIX_MIPSR1_H__ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" -#include "opus/celt/stack_alloc.h" -#include "opus/silk/tuning_parameters.h" - -#define OVERRIDE_silk_warped_LPC_analysis_filter_FIX -void silk_warped_LPC_analysis_filter_FIX( - opus_int32 state[], /* I/O State [order + 1] */ - opus_int32 res_Q2[], /* O Residual signal [length] */ - const opus_int16 coef_Q13[], /* I Coefficients [order] */ - const opus_int16 input[], /* I Input signal [length] */ - const opus_int16 lambda_Q16, /* I Warping factor */ - const opus_int length, /* I Length of input signal */ - const opus_int order, /* I Filter order (even) */ - int arch -) -{ - opus_int n, i; - opus_int32 acc_Q11, acc_Q22, tmp1, tmp2, tmp3, tmp4; - opus_int32 state_cur, state_next; - - (void)arch; - - /* Order must be even */ - /* Length must be even */ - - silk_assert( ( order & 1 ) == 0 ); - silk_assert( ( length & 1 ) == 0 ); - - for( n = 0; n < length; n+=2 ) { - /* Output of lowpass section */ - tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 ); - state_cur = silk_LSHIFT( input[ n ], 14 ); - /* Output of allpass section */ - tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 ); - state_next = tmp2; - acc_Q11 = silk_RSHIFT( order, 1 ); - acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] ); - - - /* Output of lowpass section */ - tmp4 = silk_SMLAWB( state_cur, state_next, lambda_Q16 ); - state[ 0 ] = silk_LSHIFT( input[ n+1 ], 14 ); - /* Output of allpass section */ - tmp3 = silk_SMLAWB( state_next, tmp1 - tmp4, lambda_Q16 ); - state[ 1 ] = tmp4; - acc_Q22 = silk_RSHIFT( order, 1 ); - acc_Q22 = silk_SMLAWB( acc_Q22, tmp4, coef_Q13[ 0 ] ); - - /* Loop over allpass sections */ - for( i = 2; i < order; i += 2 ) { - /* Output of allpass section */ - tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 ); - state_cur = tmp1; - acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] ); - /* Output of allpass section */ - tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 ); - state_next = tmp2; - acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] ); - - - /* Output of allpass section */ - tmp4 = silk_SMLAWB( state_cur, state_next - tmp3, lambda_Q16 ); - state[ i ] = tmp3; - acc_Q22 = silk_SMLAWB( acc_Q22, tmp3, coef_Q13[ i - 1 ] ); - /* Output of allpass section */ - tmp3 = silk_SMLAWB( state_next, tmp1 - tmp4, lambda_Q16 ); - state[ i + 1 ] = tmp4; - acc_Q22 = silk_SMLAWB( acc_Q22, tmp4, coef_Q13[ i ] ); - } - acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); - res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 ); - - state[ order ] = tmp3; - acc_Q22 = silk_SMLAWB( acc_Q22, tmp3, coef_Q13[ order - 1 ] ); - res_Q2[ n+1 ] = silk_LSHIFT( (opus_int32)input[ n+1 ], 2 ) - silk_RSHIFT_ROUND( acc_Q22, 9 ); - } -} - - - -/* Prefilter for finding Quantizer input signal */ -#define OVERRIDE_silk_prefilt_FIX -static inline void silk_prefilt_FIX( - silk_prefilter_state_FIX *P, /* I/O state */ - opus_int32 st_res_Q12[], /* I short term residual signal */ - opus_int32 xw_Q3[], /* O prefiltered signal */ - opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ - opus_int Tilt_Q14, /* I Tilt shaping coeficient */ - opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */ - opus_int lag, /* I Lag for harmonic shaping */ - opus_int length /* I Length of signals */ -) -{ - opus_int i, idx, LTP_shp_buf_idx; - opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10; - opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12; - opus_int16 *LTP_shp_buf; - - /* To speed up use temp variables instead of using the struct */ - LTP_shp_buf = P->sLTP_shp; - LTP_shp_buf_idx = P->sLTP_shp_buf_idx; - sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12; - sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12; - - if( lag > 0 ) { - for( i = 0; i < length; i++ ) { - /* unrolled loop */ - silk_assert( HARM_SHAPE_FIR_TAPS == 3 ); - idx = lag + LTP_shp_buf_idx; - n_LTP_Q12 = silk_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); - n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); - n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); - - n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 ); - n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 ); - - sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) ); - sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) ); - - LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; - LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); - - xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 ); - } - } - else - { - for( i = 0; i < length; i++ ) { - - n_LTP_Q12 = 0; - - n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 ); - n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 ); - - sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) ); - sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) ); - - LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; - LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); - - xw_Q3[i] = silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 9 ); - } - } - - /* Copy temp variable back to state */ - P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12; - P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12; - P->sLTP_shp_buf_idx = LTP_shp_buf_idx; -} - -#endif /* __PREFILTER_FIX_MIPSR1_H__ */ diff --git a/drivers/opus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h b/drivers/opus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h deleted file mode 100644 index eba7711db7..0000000000 --- a/drivers/opus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h +++ /dev/null @@ -1,162 +0,0 @@ -/*********************************************************************** -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__ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" - -#undef QC -#define QC 10 - -#undef QS -#define QS 14 - -/* Autocorrelations for a warped frequency axis */ -#define OVERRIDE_silk_warped_autocorrelation_FIX -void silk_warped_autocorrelation_FIX( - 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 ] = __builtin_mips_madd( corr_QC[ i ], tmp1_QS, start_1); - - tmp4_QS = silk_SMLAWB( tmp1_QS, tmp2_QS - tmp3_QS, warping_Q16 ); - corr_QC[ i ] = __builtin_mips_madd( corr_QC[ i ], tmp3_QS, start_2); - - tmp6_QS = silk_SMLAWB( tmp3_QS, tmp4_QS - tmp5_QS, warping_Q16 ); - corr_QC[ i ] = __builtin_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 ] = __builtin_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 ] = __builtin_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 ] = __builtin_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 ] = __builtin_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 ] = __builtin_mips_madd( corr_QC[ i+1 ], tmp8_QS, state_QS[ 0 ]); - - } - state_QS[ order ] = tmp7_QS; - - corr_QC[ order ] = __builtin_mips_madd( corr_QC[ order ], tmp1_QS, start_1); - corr_QC[ order ] = __builtin_mips_madd( corr_QC[ order ], tmp3_QS, start_2); - corr_QC[ order ] = __builtin_mips_madd( corr_QC[ order ], tmp5_QS, start_3); - corr_QC[ order ] = __builtin_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 ] = __builtin_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 ] = __builtin_mips_madd( corr_QC[ i+1 ], tmp2_QS, state_QS[ 0 ]); - } - state_QS[ order ] = tmp1_QS; - corr_QC[ order ] = __builtin_mips_madd( corr_QC[ order ], tmp1_QS, state_QS[ 0 ]); - } - - temp64 = corr_QC[ 0 ]; - temp64 = __builtin_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 = __builtin_mips_shilo(temp64, val); - temp64 = (val >= 0) ? (temp64 >> val) : (temp64 << -val); - corr[ i ] = (opus_int32)silk_CHECK_FIT32( __builtin_mips_shilo( temp64, -lsh ) ); - } - } else { - for( i = 0; i < order + 1; i++ ) { - temp64 = corr_QC[ i ]; - //temp64 = __builtin_mips_shilo(temp64, val); - temp64 = (val >= 0) ? (temp64 >> val) : (temp64 << -val); - corr[ i ] = (opus_int32)silk_CHECK_FIT32( __builtin_mips_shilo( temp64, -lsh ) ); - } - } - - corr_QC[ 0 ] = __builtin_mips_shilo(corr_QC[ 0 ], val); - - silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/ -} -#endif /* __WARPED_AUTOCORRELATION_FIX_MIPSR1_H__ */ diff --git a/drivers/opus/silk/fixed/noise_shape_analysis_FIX.c b/drivers/opus/silk/fixed/noise_shape_analysis_FIX.c deleted file mode 100644 index 6f1dc3ddd5..0000000000 --- a/drivers/opus/silk/fixed/noise_shape_analysis_FIX.c +++ /dev/null @@ -1,448 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" -#include "opus/celt/stack_alloc.h" -#include "opus/silk/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 opus_int32 warped_gain( /* gain in Q16*/ - const opus_int32 *coefs_Q24, - opus_int lambda_Q16, - opus_int order -) { - opus_int i; - opus_int32 gain_Q24; - - lambda_Q16 = -lambda_Q16; - gain_Q24 = coefs_Q24[ order - 1 ]; - for( i = order - 2; i >= 0; i-- ) { - gain_Q24 = silk_SMLAWB( coefs_Q24[ i ], gain_Q24, lambda_Q16 ); - } - gain_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), gain_Q24, -lambda_Q16 ); - return silk_INVERSE32_varQ( gain_Q24, 40 ); -} - -/* 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 limit_warped_coefs( - opus_int32 *coefs_syn_Q24, - opus_int32 *coefs_ana_Q24, - opus_int lambda_Q16, - opus_int32 limit_Q24, - opus_int order -) { - opus_int i, iter, ind = 0; - opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_syn_Q16, gain_ana_Q16; - opus_int32 nom_Q16, den_Q24; - - /* Convert to monic coefficients */ - lambda_Q16 = -lambda_Q16; - for( i = order - 1; i > 0; i-- ) { - coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); - coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); - } - lambda_Q16 = -lambda_Q16; - nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 ); - den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); - gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); - den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); - gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); - for( i = 0; i < order; i++ ) { - coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); - coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); - } - - for( iter = 0; iter < 10; iter++ ) { - /* Find maximum absolute value */ - maxabs_Q24 = -1; - for( i = 0; i < order; i++ ) { - tmp = silk_max( silk_abs_int32( coefs_syn_Q24[ i ] ), silk_abs_int32( coefs_ana_Q24[ i ] ) ); - if( tmp > maxabs_Q24 ) { - maxabs_Q24 = tmp; - ind = i; - } - } - if( maxabs_Q24 <= limit_Q24 ) { - /* Coefficients are within range - done */ - return; - } - - /* Convert back to true warped coefficients */ - for( i = 1; i < order; i++ ) { - coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); - coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); - } - gain_syn_Q16 = silk_INVERSE32_varQ( gain_syn_Q16, 32 ); - gain_ana_Q16 = silk_INVERSE32_varQ( gain_ana_Q16, 32 ); - for( i = 0; i < order; i++ ) { - coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); - coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); - } - - /* Apply bandwidth expansion */ - chirp_Q16 = SILK_FIX_CONST( 0.99, 16 ) - silk_DIV32_varQ( - silk_SMULWB( maxabs_Q24 - limit_Q24, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ), - silk_MUL( maxabs_Q24, ind + 1 ), 22 ); - silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 ); - silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 ); - - /* Convert to monic warped coefficients */ - lambda_Q16 = -lambda_Q16; - for( i = order - 1; i > 0; i-- ) { - coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); - coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); - } - lambda_Q16 = -lambda_Q16; - nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 ); - den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); - gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); - den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); - gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); - for( i = 0; i < order; i++ ) { - coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); - coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); - } - } - silk_assert( 0 ); -} - -#if defined(MIPSr1_ASM) -#include "opus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h" -#endif - -/**************************************************************/ -/* Compute noise shaping coefficients and initial gain values */ -/**************************************************************/ -#ifndef OVERRIDE_silk_noise_shape_analysis_FIX -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 */ -) -{ - silk_shape_state_FIX *psShapeSt = &psEnc->sShape; - opus_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0; - opus_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32; - opus_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7; - opus_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8; - opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; - opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ]; - opus_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ]; - opus_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ]; - VARDECL( opus_int16, x_windowed ); - const opus_int16 *x_ptr, *pitch_res_ptr; - SAVE_STACK; - - /* Point to start of first LPC analysis block */ - x_ptr = x - psEnc->sCmn.la_shape; - - /****************/ - /* GAIN CONTROL */ - /****************/ - SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7; - - /* Input quality is the average of the quality in the lowest two VAD bands */ - psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( (opus_int32)psEnc->sCmn.input_quality_bands_Q15[ 0 ] - + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 ); - - /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ - psEncCtrl->coding_quality_Q14 = silk_RSHIFT( silk_sigm_Q15( silk_RSHIFT_ROUND( SNR_adj_dB_Q7 - - SILK_FIX_CONST( 20.0, 7 ), 4 ) ), 1 ); - - /* Reduce coding SNR during low speech activity */ - if( psEnc->sCmn.useCBR == 0 ) { - b_Q8 = SILK_FIX_CONST( 1.0, 8 ) - psEnc->sCmn.speech_activity_Q8; - b_Q8 = silk_SMULWB( silk_LSHIFT( b_Q8, 8 ), b_Q8 ); - SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, - silk_SMULBB( SILK_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), /* Q11*/ - silk_SMULWB( SILK_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); /* Q12*/ - } - - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /* Reduce gains for periodic signals */ - SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( HARM_SNR_INCR_dB, 8 ), psEnc->LTPCorr_Q15 ); - } else { - /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */ - SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, - silk_SMLAWB( SILK_FIX_CONST( 6.0, 9 ), -SILK_FIX_CONST( 0.4, 18 ), psEnc->sCmn.SNR_dB_Q7 ), - SILK_FIX_CONST( 1.0, 14 ) - psEncCtrl->input_quality_Q14 ); - } - - /*************************/ - /* 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; - psEncCtrl->sparseness_Q8 = 0; - } else { - /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */ - nSamples = silk_LSHIFT( psEnc->sCmn.fs_kHz, 1 ); - energy_variation_Q7 = 0; - log_energy_prev_Q7 = 0; - pitch_res_ptr = pitch_res; - for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) { - silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples ); - nrg += silk_RSHIFT( nSamples, scale ); /* Q(-scale)*/ - - log_energy_Q7 = silk_lin2log( nrg ); - if( k > 0 ) { - energy_variation_Q7 += silk_abs( log_energy_Q7 - log_energy_prev_Q7 ); - } - log_energy_prev_Q7 = log_energy_Q7; - pitch_res_ptr += nSamples; - } - - psEncCtrl->sparseness_Q8 = silk_RSHIFT( silk_sigm_Q15( silk_SMULWB( energy_variation_Q7 - - SILK_FIX_CONST( 5.0, 7 ), SILK_FIX_CONST( 0.1, 16 ) ) ), 7 ); - - /* Set quantization offset depending on sparseness measure */ - if( psEncCtrl->sparseness_Q8 > SILK_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) { - psEnc->sCmn.indices.quantOffsetType = 0; - } else { - psEnc->sCmn.indices.quantOffsetType = 1; - } - - /* Increase coding SNR for sparse signals */ - SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( SPARSE_SNR_INCR_dB, 15 ), psEncCtrl->sparseness_Q8 - SILK_FIX_CONST( 0.5, 8 ) ); - } - - /*******************************/ - /* Control bandwidth expansion */ - /*******************************/ - /* More BWE for signals with high prediction gain */ - strength_Q16 = silk_SMULWB( psEncCtrl->predGain_Q16, SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ); - BWExp1_Q16 = BWExp2_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ), - silk_SMLAWW( SILK_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 ); - delta_Q16 = silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - silk_SMULBB( 3, psEncCtrl->coding_quality_Q14 ), - SILK_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) ); - BWExp1_Q16 = silk_SUB32( BWExp1_Q16, delta_Q16 ); - BWExp2_Q16 = silk_ADD32( BWExp2_Q16, delta_Q16 ); - /* BWExp1 will be applied after BWExp2, so make it relative */ - BWExp1_Q16 = silk_DIV32_16( silk_LSHIFT( BWExp1_Q16, 14 ), silk_RSHIFT( BWExp2_Q16, 2 ) ); - - if( psEnc->sCmn.warping_Q16 > 0 ) { - /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */ - warping_Q16 = silk_SMLAWB( psEnc->sCmn.warping_Q16, (opus_int32)psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( 0.01, 18 ) ); - } else { - warping_Q16 = 0; - } - - /********************************************/ - /* Compute noise shaping AR coefs and gains */ - /********************************************/ - ALLOC( x_windowed, psEnc->sCmn.shapeWinLength, opus_int16 ); - 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 = silk_RSHIFT( psEnc->sCmn.shapeWinLength - flat_part, 1 ); - - silk_apply_sine_window( x_windowed, x_ptr, 1, slope_part ); - shift = slope_part; - silk_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(opus_int16) ); - shift += flat_part; - silk_apply_sine_window( 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_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder ); - } else { - /* Calculate regular auto correlation */ - silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch ); - } - - /* Add white noise, as a fraction of energy */ - auto_corr[0] = silk_ADD32( auto_corr[0], silk_max_32( silk_SMULWB( silk_RSHIFT( auto_corr[ 0 ], 4 ), - SILK_FIX_CONST( SHAPE_WHITE_NOISE_FRACTION, 20 ) ), 1 ) ); - - /* Calculate the reflection coefficients using schur */ - nrg = silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder ); - silk_assert( nrg >= 0 ); - - /* Convert reflection coefficients to prediction coefficients */ - silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder ); - - Qnrg = -scale; /* range: -12...30*/ - silk_assert( Qnrg >= -12 ); - silk_assert( Qnrg <= 30 ); - - /* Make sure that Qnrg is an even number */ - if( Qnrg & 1 ) { - Qnrg -= 1; - nrg >>= 1; - } - - tmp32 = silk_SQRT_APPROX( nrg ); - Qnrg >>= 1; /* range: -6...15*/ - - psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( tmp32, 16 - Qnrg ); - - if( psEnc->sCmn.warping_Q16 > 0 ) { - /* Adjust gain for warping */ - gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder ); - silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); - if ( silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 ) >= ( silk_int32_MAX >> 1 ) ) { - psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX; - } else { - psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); - } - } - - /* Bandwidth expansion for synthesis filter shaping */ - silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 ); - - /* Compute noise shaping filter coefficients */ - silk_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( opus_int32 ) ); - - /* Bandwidth expansion for analysis filter shaping */ - silk_assert( BWExp1_Q16 <= SILK_FIX_CONST( 1.0, 16 ) ); - silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 ); - - /* Ratio of prediction gains, in energy domain */ - pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder ); - nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder ); - - /*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/ - pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 ); - psEncCtrl->GainsPre_Q14[ k ] = ( opus_int ) SILK_FIX_CONST( 0.3, 14 ) + silk_DIV32_varQ( pre_nrg_Q30, nrg, 14 ); - - /* Convert to monic warped prediction coefficients and limit absolute values */ - limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder ); - - /* Convert from Q24 to Q13 and store in int16 */ - for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) { - psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) ); - psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) ); - } - } - - /*****************/ - /* Gain tweaking */ - /*****************/ - /* Increase gains during low speech activity and put lower limit on gains */ - gain_mult_Q16 = silk_log2lin( -silk_SMLAWB( -SILK_FIX_CONST( 16.0, 7 ), SNR_adj_dB_Q7, SILK_FIX_CONST( 0.16, 16 ) ) ); - gain_add_Q16 = silk_log2lin( silk_SMLAWB( SILK_FIX_CONST( 16.0, 7 ), SILK_FIX_CONST( MIN_QGAIN_DB, 7 ), SILK_FIX_CONST( 0.16, 16 ) ) ); - silk_assert( gain_mult_Q16 > 0 ); - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); - silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); - psEncCtrl->Gains_Q16[ k ] = silk_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 ); - } - - gain_mult_Q16 = SILK_FIX_CONST( 1.0, 16 ) + silk_RSHIFT_ROUND( silk_MLA( SILK_FIX_CONST( INPUT_TILT, 26 ), - psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ), 10 ); - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->GainsPre_Q14[ k ] = silk_SMULWB( gain_mult_Q16, psEncCtrl->GainsPre_Q14[ k ] ); - } - - /************************************************/ - /* Control low-frequency shaping and noise tilt */ - /************************************************/ - /* Less low frequency shaping for noisy inputs */ - strength_Q16 = silk_MUL( SILK_FIX_CONST( LOW_FREQ_SHAPING, 4 ), silk_SMLAWB( SILK_FIX_CONST( 1.0, 12 ), - SILK_FIX_CONST( LOW_QUALITY_LOW_FREQ_SHAPING_DECR, 13 ), psEnc->sCmn.input_quality_bands_Q15[ 0 ] - SILK_FIX_CONST( 1.0, 15 ) ) ); - strength_Q16 = silk_RSHIFT( silk_MUL( strength_Q16, psEnc->sCmn.speech_activity_Q8 ), 8 ); - 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])*/ - opus_int fs_kHz_inv = silk_DIV32_16( SILK_FIX_CONST( 0.2, 14 ), psEnc->sCmn.fs_kHz ); - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - b_Q14 = fs_kHz_inv + silk_DIV32_16( SILK_FIX_CONST( 3.0, 14 ), psEncCtrl->pitchL[ k ] ); - /* Pack two coefficients in one int32 */ - psEncCtrl->LF_shp_Q14[ k ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - silk_SMULWB( strength_Q16, b_Q14 ), 16 ); - psEncCtrl->LF_shp_Q14[ k ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); - } - silk_assert( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ) < SILK_FIX_CONST( 0.5, 24 ) ); /* Guarantees that second argument to SMULWB() is within range of an opus_int16*/ - Tilt_Q16 = - SILK_FIX_CONST( HP_NOISE_COEF, 16 ) - - silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - SILK_FIX_CONST( HP_NOISE_COEF, 16 ), - silk_SMULWB( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ), psEnc->sCmn.speech_activity_Q8 ) ); - } else { - b_Q14 = silk_DIV32_16( 21299, psEnc->sCmn.fs_kHz ); /* 1.3_Q0 = 21299_Q14*/ - /* Pack two coefficients in one int32 */ - psEncCtrl->LF_shp_Q14[ 0 ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - - silk_SMULWB( strength_Q16, silk_SMULWB( SILK_FIX_CONST( 0.6, 16 ), b_Q14 ) ), 16 ); - psEncCtrl->LF_shp_Q14[ 0 ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); - for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->LF_shp_Q14[ k ] = psEncCtrl->LF_shp_Q14[ 0 ]; - } - Tilt_Q16 = -SILK_FIX_CONST( HP_NOISE_COEF, 16 ); - } - - /****************************/ - /* HARMONIC SHAPING CONTROL */ - /****************************/ - /* Control boosting of harmonic frequencies */ - HarmBoost_Q16 = silk_SMULWB( silk_SMULWB( SILK_FIX_CONST( 1.0, 17 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 3 ), - psEnc->LTPCorr_Q15 ), SILK_FIX_CONST( LOW_RATE_HARMONIC_BOOST, 16 ) ); - - /* More harmonic boost for noisy input signals */ - HarmBoost_Q16 = silk_SMLAWB( HarmBoost_Q16, - SILK_FIX_CONST( 1.0, 16 ) - silk_LSHIFT( psEncCtrl->input_quality_Q14, 2 ), SILK_FIX_CONST( LOW_INPUT_QUALITY_HARMONIC_BOOST, 16 ) ); - - if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /* More harmonic noise shaping for high bitrates or noisy input */ - HarmShapeGain_Q16 = silk_SMLAWB( SILK_FIX_CONST( HARMONIC_SHAPING, 16 ), - SILK_FIX_CONST( 1.0, 16 ) - silk_SMULWB( SILK_FIX_CONST( 1.0, 18 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 4 ), - psEncCtrl->input_quality_Q14 ), SILK_FIX_CONST( HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING, 16 ) ); - - /* Less harmonic noise shaping for less periodic signals */ - HarmShapeGain_Q16 = silk_SMULWB( silk_LSHIFT( HarmShapeGain_Q16, 1 ), - silk_SQRT_APPROX( silk_LSHIFT( psEnc->LTPCorr_Q15, 15 ) ) ); - } else { - HarmShapeGain_Q16 = 0; - } - - /*************************/ - /* Smooth over subframes */ - /*************************/ - for( k = 0; k < MAX_NB_SUBFR; k++ ) { - psShapeSt->HarmBoost_smth_Q16 = - silk_SMLAWB( psShapeSt->HarmBoost_smth_Q16, HarmBoost_Q16 - psShapeSt->HarmBoost_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); - psShapeSt->HarmShapeGain_smth_Q16 = - silk_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); - psShapeSt->Tilt_smth_Q16 = - silk_SMLAWB( psShapeSt->Tilt_smth_Q16, Tilt_Q16 - psShapeSt->Tilt_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); - - psEncCtrl->HarmBoost_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmBoost_smth_Q16, 2 ); - psEncCtrl->HarmShapeGain_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 ); - psEncCtrl->Tilt_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16, 2 ); - } - RESTORE_STACK; -} -#endif /* OVERRIDE_silk_noise_shape_analysis_FIX */ diff --git a/drivers/opus/silk/fixed/pitch_analysis_core_FIX.c b/drivers/opus/silk/fixed/pitch_analysis_core_FIX.c deleted file mode 100644 index cf421c9612..0000000000 --- a/drivers/opus/silk/fixed/pitch_analysis_core_FIX.c +++ /dev/null @@ -1,743 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -/*********************************************************** -* Pitch analyser function -********************************************************** */ -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/pitch_est_defines.h" -#include "opus/celt/stack_alloc.h" -#include "opus/silk/debug.h" -#include "opus/celt/pitch.h" - -#define SCRATCH_SIZE 22 -#define SF_LENGTH_4KHZ ( PE_SUBFR_LENGTH_MS * 4 ) -#define SF_LENGTH_8KHZ ( PE_SUBFR_LENGTH_MS * 8 ) -#define MIN_LAG_4KHZ ( PE_MIN_LAG_MS * 4 ) -#define MIN_LAG_8KHZ ( PE_MIN_LAG_MS * 8 ) -#define MAX_LAG_4KHZ ( PE_MAX_LAG_MS * 4 ) -#define MAX_LAG_8KHZ ( PE_MAX_LAG_MS * 8 - 1 ) -#define CSTRIDE_4KHZ ( MAX_LAG_4KHZ + 1 - MIN_LAG_4KHZ ) -#define CSTRIDE_8KHZ ( MAX_LAG_8KHZ + 3 - ( MIN_LAG_8KHZ - 2 ) ) -#define D_COMP_MIN ( MIN_LAG_8KHZ - 3 ) -#define D_COMP_MAX ( MAX_LAG_8KHZ + 4 ) -#define D_COMP_STRIDE ( D_COMP_MAX - D_COMP_MIN ) - -typedef opus_int32 silk_pe_stage3_vals[ PE_NB_STAGE3_LAGS ]; - -/************************************************************/ -/* Internally used functions */ -/************************************************************/ -static void silk_P_Ana_calc_corr_st3( - silk_pe_stage3_vals cross_corr_st3[], /* O 3 DIM correlation array */ - const opus_int16 frame[], /* I vector to correlate */ - opus_int start_lag, /* I lag offset to search around */ - opus_int sf_length, /* I length of a 5 ms subframe */ - 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_pe_stage3_vals energies_st3[], /* O 3 DIM energy array */ - const opus_int16 frame[], /* I vector to calc energy in */ - opus_int start_lag, /* I lag offset to search around */ - opus_int sf_length, /* I length of one 5 ms subframe */ - opus_int nb_subfr, /* I number of subframes */ - opus_int complexity, /* I Complexity setting */ - int arch /* I Run-time architecture */ -); - -/*************************************************************/ -/* FIXED POINT CORE PITCH ANALYSIS FUNCTION */ -/*************************************************************/ -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 */ -) -{ - VARDECL( opus_int16, frame_8kHz ); - VARDECL( opus_int16, frame_4kHz ); - opus_int32 filt_state[ 6 ]; - const opus_int16 *input_frame_ptr; - opus_int i, k, d, j; - VARDECL( opus_int16, C ); - VARDECL( opus_int32, xcorr32 ); - const opus_int16 *target_ptr, *basis_ptr; - opus_int32 cross_corr, normalizer, energy, shift, energy_basis, energy_target; - opus_int d_srch[ PE_D_SRCH_LENGTH ], Cmax, length_d_srch, length_d_comp; - VARDECL( opus_int16, d_comp ); - opus_int32 sum, threshold, lag_counter; - opus_int CBimax, CBimax_new, CBimax_old, lag, start_lag, end_lag, lag_new; - opus_int32 CC[ PE_NB_CBKS_STAGE2_EXT ], CCmax, CCmax_b, CCmax_new_b, CCmax_new; - VARDECL( silk_pe_stage3_vals, energies_st3 ); - VARDECL( silk_pe_stage3_vals, cross_corr_st3 ); - opus_int frame_length, frame_length_8kHz, frame_length_4kHz; - opus_int sf_length; - opus_int min_lag; - opus_int max_lag; - opus_int32 contour_bias_Q15, diff; - opus_int nb_cbk_search, cbk_size; - opus_int32 delta_lag_log2_sqr_Q7, lag_log2_Q7, prevLag_log2_Q7, prev_lag_bias_Q13; - const opus_int8 *Lag_CB_ptr; - SAVE_STACK; - /* Check for valid sampling frequency */ - silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 ); - - /* Check for valid complexity setting */ - silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); - silk_assert( complexity <= SILK_PE_MAX_COMPLEX ); - - silk_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) ); - silk_assert( search_thres2_Q13 >= 0 && search_thres2_Q13 <= (1<<13) ); - - /* 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; - min_lag = PE_MIN_LAG_MS * Fs_kHz; - max_lag = PE_MAX_LAG_MS * Fs_kHz - 1; - - /* Resample from input sampled at Fs_kHz to 8 kHz */ - ALLOC( frame_8kHz, frame_length_8kHz, opus_int16 ); - if( Fs_kHz == 16 ) { - silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) ); - silk_resampler_down2( filt_state, frame_8kHz, frame, frame_length ); - } else if( Fs_kHz == 12 ) { - silk_memset( filt_state, 0, 6 * sizeof( opus_int32 ) ); - silk_resampler_down2_3( filt_state, frame_8kHz, frame, frame_length ); - } else { - silk_assert( Fs_kHz == 8 ); - silk_memcpy( frame_8kHz, frame, frame_length_8kHz * sizeof(opus_int16) ); - } - - /* Decimate again to 4 kHz */ - silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );/* Set state to zero */ - ALLOC( frame_4kHz, frame_length_4kHz, opus_int16 ); - silk_resampler_down2( filt_state, frame_4kHz, frame_8kHz, frame_length_8kHz ); - - /* 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 ] ); - } - - /******************************************************************************* - ** Scale 4 kHz signal down to prevent correlations measures from overflowing - ** find scaling as max scaling for each 8kHz(?) subframe - *******************************************************************************/ - - /* Inner product is calculated with different lengths, so scale for the worst case */ - silk_sum_sqr_shift( &energy, &shift, frame_4kHz, frame_length_4kHz ); - if( shift > 0 ) { - shift = silk_RSHIFT( shift, 1 ); - for( i = 0; i < frame_length_4kHz; i++ ) { - frame_4kHz[ i ] = silk_RSHIFT( frame_4kHz[ i ], shift ); - } - } - - /****************************************************************************** - * FIRST STAGE, operating in 4 khz - ******************************************************************************/ - ALLOC( C, nb_subfr * CSTRIDE_8KHZ, opus_int16 ); - ALLOC( xcorr32, MAX_LAG_4KHZ-MIN_LAG_4KHZ+1, opus_int32 ); - silk_memset( C, 0, (nb_subfr >> 1) * CSTRIDE_4KHZ * sizeof( opus_int16 ) ); - 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 */ - silk_assert( target_ptr >= frame_4kHz ); - silk_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 */ - silk_assert( basis_ptr >= frame_4kHz ); - silk_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz ); - - celt_pitch_xcorr( target_ptr, target_ptr - MAX_LAG_4KHZ, xcorr32, SF_LENGTH_8KHZ, MAX_LAG_4KHZ - MIN_LAG_4KHZ + 1, arch ); - - /* Calculate first vector products before loop */ - cross_corr = xcorr32[ MAX_LAG_4KHZ - MIN_LAG_4KHZ ]; - normalizer = silk_inner_prod_aligned( target_ptr, target_ptr, SF_LENGTH_8KHZ, arch ); - normalizer = silk_ADD32( normalizer, silk_inner_prod_aligned( basis_ptr, basis_ptr, SF_LENGTH_8KHZ, arch ) ); - normalizer = silk_ADD32( normalizer, silk_SMULBB( SF_LENGTH_8KHZ, 4000 ) ); - - matrix_ptr( C, k, 0, CSTRIDE_4KHZ ) = - (opus_int16)silk_DIV32_varQ( cross_corr, normalizer, 13 + 1 ); /* Q13 */ - - /* 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 = xcorr32[ MAX_LAG_4KHZ - d ]; - - /* Add contribution of new sample and remove contribution from oldest sample */ - normalizer = silk_ADD32( normalizer, - silk_SMULBB( basis_ptr[ 0 ], basis_ptr[ 0 ] ) - - silk_SMULBB( basis_ptr[ SF_LENGTH_8KHZ ], basis_ptr[ SF_LENGTH_8KHZ ] ) ); - - matrix_ptr( C, k, d - MIN_LAG_4KHZ, CSTRIDE_4KHZ) = - (opus_int16)silk_DIV32_varQ( cross_corr, normalizer, 13 + 1 ); /* Q13 */ - } - /* Update target pointer */ - target_ptr += SF_LENGTH_8KHZ; - } - - /* Combine two subframes into single correlation measure and apply short-lag bias */ - if( nb_subfr == PE_MAX_NB_SUBFR ) { - for( i = MAX_LAG_4KHZ; i >= MIN_LAG_4KHZ; i-- ) { - sum = (opus_int32)matrix_ptr( C, 0, i - MIN_LAG_4KHZ, CSTRIDE_4KHZ ) - + (opus_int32)matrix_ptr( C, 1, i - MIN_LAG_4KHZ, CSTRIDE_4KHZ ); /* Q14 */ - sum = silk_SMLAWB( sum, sum, silk_LSHIFT( -i, 4 ) ); /* Q14 */ - C[ i - MIN_LAG_4KHZ ] = (opus_int16)sum; /* Q14 */ - } - } else { - /* Only short-lag bias */ - for( i = MAX_LAG_4KHZ; i >= MIN_LAG_4KHZ; i-- ) { - sum = silk_LSHIFT( (opus_int32)C[ i - MIN_LAG_4KHZ ], 1 ); /* Q14 */ - sum = silk_SMLAWB( sum, sum, silk_LSHIFT( -i, 4 ) ); /* Q14 */ - C[ i - MIN_LAG_4KHZ ] = (opus_int16)sum; /* Q14 */ - } - } - - /* Sort */ - length_d_srch = silk_ADD_LSHIFT32( 4, complexity, 1 ); - silk_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH ); - silk_insertion_sort_decreasing_int16( C, d_srch, CSTRIDE_4KHZ, - length_d_srch ); - - /* Escape if correlation is very low already here */ - Cmax = (opus_int)C[ 0 ]; /* Q14 */ - if( Cmax < SILK_FIX_CONST( 0.2, 14 ) ) { - silk_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) ); - *LTPCorr_Q15 = 0; - *lagIndex = 0; - *contourIndex = 0; - RESTORE_STACK; - return 1; - } - - threshold = silk_SMULWB( search_thres1_Q16, Cmax ); - for( i = 0; i < length_d_srch; i++ ) { - /* Convert to 8 kHz indices for the sorted correlation that exceeds the threshold */ - if( C[ i ] > threshold ) { - d_srch[ i ] = silk_LSHIFT( d_srch[ i ] + MIN_LAG_4KHZ, 1 ); - } else { - length_d_srch = i; - break; - } - } - silk_assert( length_d_srch > 0 ); - - ALLOC( d_comp, D_COMP_STRIDE, opus_int16 ); - for( i = D_COMP_MIN; i < D_COMP_MAX; i++ ) { - d_comp[ i - D_COMP_MIN ] = 0; - } - for( i = 0; i < length_d_srch; i++ ) { - d_comp[ d_srch[ i ] - D_COMP_MIN ] = 1; - } - - /* Convolution */ - for( i = D_COMP_MAX - 1; i >= MIN_LAG_8KHZ; i-- ) { - d_comp[ i - D_COMP_MIN ] += - d_comp[ i - 1 - D_COMP_MIN ] + d_comp[ i - 2 - D_COMP_MIN ]; - } - - length_d_srch = 0; - for( i = MIN_LAG_8KHZ; i < MAX_LAG_8KHZ + 1; i++ ) { - if( d_comp[ i + 1 - D_COMP_MIN ] > 0 ) { - d_srch[ length_d_srch ] = i; - length_d_srch++; - } - } - - /* Convolution */ - for( i = D_COMP_MAX - 1; i >= MIN_LAG_8KHZ; i-- ) { - d_comp[ i - D_COMP_MIN ] += d_comp[ i - 1 - D_COMP_MIN ] - + d_comp[ i - 2 - D_COMP_MIN ] + d_comp[ i - 3 - D_COMP_MIN ]; - } - - length_d_comp = 0; - for( i = MIN_LAG_8KHZ; i < D_COMP_MAX; i++ ) { - if( d_comp[ i - D_COMP_MIN ] > 0 ) { - d_comp[ length_d_comp ] = i - 2; - length_d_comp++; - } - } - - /********************************************************************************** - ** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation - *************************************************************************************/ - - /****************************************************************************** - ** Scale signal down to avoid correlations measures from overflowing - *******************************************************************************/ - /* find scaling as max scaling for each subframe */ - silk_sum_sqr_shift( &energy, &shift, frame_8kHz, frame_length_8kHz ); - if( shift > 0 ) { - shift = silk_RSHIFT( shift, 1 ); - for( i = 0; i < frame_length_8kHz; i++ ) { - frame_8kHz[ i ] = silk_RSHIFT( frame_8kHz[ i ], shift ); - } - } - - /********************************************************************************* - * Find energy of each subframe projected onto its history, for a range of delays - *********************************************************************************/ - silk_memset( C, 0, nb_subfr * CSTRIDE_8KHZ * sizeof( opus_int16 ) ); - - target_ptr = &frame_8kHz[ PE_LTP_MEM_LENGTH_MS * 8 ]; - for( k = 0; k < nb_subfr; k++ ) { - - /* Check that we are within range of the array */ - silk_assert( target_ptr >= frame_8kHz ); - silk_assert( target_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz ); - - energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, SF_LENGTH_8KHZ, arch ), 1 ); - for( j = 0; j < length_d_comp; j++ ) { - d = d_comp[ j ]; - basis_ptr = target_ptr - d; - - /* Check that we are within range of the array */ - silk_assert( basis_ptr >= frame_8kHz ); - silk_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz ); - - cross_corr = silk_inner_prod_aligned( target_ptr, basis_ptr, SF_LENGTH_8KHZ, arch ); - if( cross_corr > 0 ) { - energy_basis = silk_inner_prod_aligned( basis_ptr, basis_ptr, SF_LENGTH_8KHZ, arch ); - matrix_ptr( C, k, d - ( MIN_LAG_8KHZ - 2 ), CSTRIDE_8KHZ ) = - (opus_int16)silk_DIV32_varQ( cross_corr, - silk_ADD32( energy_target, - energy_basis ), - 13 + 1 ); /* Q13 */ - } else { - matrix_ptr( C, k, d - ( MIN_LAG_8KHZ - 2 ), CSTRIDE_8KHZ ) = 0; - } - } - target_ptr += SF_LENGTH_8KHZ; - } - - /* search over lag range and lags codebook */ - /* scale factor for lag codebook, as a function of center lag */ - - CCmax = silk_int32_MIN; - CCmax_b = silk_int32_MIN; - - 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_DIV32_16( silk_LSHIFT( prevLag, 1 ), 3 ); - } else if( Fs_kHz == 16 ) { - prevLag = silk_RSHIFT( prevLag, 1 ); - } - prevLag_log2_Q7 = silk_lin2log( (opus_int32)prevLag ); - } else { - prevLag_log2_Q7 = 0; - } - silk_assert( search_thres2_Q13 == silk_SAT16( search_thres2_Q13 ) ); - /* 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; - for( i = 0; i < nb_subfr; i++ ) { - opus_int d_subfr; - /* Try all codebooks */ - d_subfr = d + matrix_ptr( Lag_CB_ptr, i, j, cbk_size ); - CC[ j ] = CC[ j ] - + (opus_int32)matrix_ptr( C, i, - d_subfr - ( MIN_LAG_8KHZ - 2 ), - CSTRIDE_8KHZ ); - } - } - /* Find best codebook */ - CCmax_new = silk_int32_MIN; - 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_Q7 = silk_lin2log( d ); /* Q7 */ - silk_assert( lag_log2_Q7 == silk_SAT16( lag_log2_Q7 ) ); - silk_assert( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 13 ) == silk_SAT16( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 13 ) ) ); - CCmax_new_b = CCmax_new - silk_RSHIFT( silk_SMULBB( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 13 ), lag_log2_Q7 ), 7 ); /* Q13 */ - - /* Bias towards previous lag */ - silk_assert( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 13 ) == silk_SAT16( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 13 ) ) ); - if( prevLag > 0 ) { - delta_lag_log2_sqr_Q7 = lag_log2_Q7 - prevLag_log2_Q7; - silk_assert( delta_lag_log2_sqr_Q7 == silk_SAT16( delta_lag_log2_sqr_Q7 ) ); - delta_lag_log2_sqr_Q7 = silk_RSHIFT( silk_SMULBB( delta_lag_log2_sqr_Q7, delta_lag_log2_sqr_Q7 ), 7 ); - prev_lag_bias_Q13 = silk_RSHIFT( silk_SMULBB( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 13 ), *LTPCorr_Q15 ), 15 ); /* Q13 */ - prev_lag_bias_Q13 = silk_DIV32( silk_MUL( prev_lag_bias_Q13, delta_lag_log2_sqr_Q7 ), delta_lag_log2_sqr_Q7 + SILK_FIX_CONST( 0.5, 7 ) ); - CCmax_new_b -= prev_lag_bias_Q13; /* Q13 */ - } - - if( CCmax_new_b > CCmax_b && /* Find maximum biased correlation */ - CCmax_new > silk_SMULBB( nb_subfr, search_thres2_Q13 ) && /* Correlation needs to be high enough to be voiced */ - silk_CB_lags_stage2[ 0 ][ CBimax_new ] <= MIN_LAG_8KHZ /* Lag must be in range */ - ) { - 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, nb_subfr * sizeof( opus_int ) ); - *LTPCorr_Q15 = 0; - *lagIndex = 0; - *contourIndex = 0; - RESTORE_STACK; - return 1; - } - - /* Output normalized correlation */ - *LTPCorr_Q15 = (opus_int)silk_LSHIFT( silk_DIV32_16( CCmax, nb_subfr ), 2 ); - silk_assert( *LTPCorr_Q15 >= 0 ); - - if( Fs_kHz > 8 ) { - VARDECL( opus_int16, scratch_mem ); - /***************************************************************************/ - /* Scale input signal down to avoid correlations measures from overflowing */ - /***************************************************************************/ - /* find scaling as max scaling for each subframe */ - silk_sum_sqr_shift( &energy, &shift, frame, frame_length ); - ALLOC( scratch_mem, shift > 0 ? frame_length : ALLOC_NONE, opus_int16 ); - if( shift > 0 ) { - /* Move signal to scratch mem because the input signal should be unchanged */ - shift = silk_RSHIFT( shift, 1 ); - for( i = 0; i < frame_length; i++ ) { - scratch_mem[ i ] = silk_RSHIFT( frame[ i ], shift ); - } - input_frame_ptr = scratch_mem; - } else { - input_frame_ptr = frame; - } - - /* Search in original signal */ - - CBimax_old = CBimax; - /* Compensate for decimation */ - silk_assert( lag == silk_SAT16( lag ) ); - if( Fs_kHz == 12 ) { - lag = silk_RSHIFT( silk_SMULBB( lag, 3 ), 1 ); - } else if( Fs_kHz == 16 ) { - lag = silk_LSHIFT( lag, 1 ); - } else { - lag = silk_SMULBB( lag, 3 ); - } - - 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 = silk_int32_MIN; - /* pitch lags according to second stage */ - for( k = 0; k < nb_subfr; k++ ) { - pitch_out[ k ] = lag + 2 * silk_CB_lags_stage2[ k ][ CBimax_old ]; - } - - /* Set up codebook 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 ]; - } - - /* Calculate the correlations and energies needed in stage 3 */ - ALLOC( energies_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals ); - ALLOC( cross_corr_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals ); - silk_P_Ana_calc_corr_st3( cross_corr_st3, input_frame_ptr, start_lag, sf_length, nb_subfr, complexity, arch ); - silk_P_Ana_calc_energy_st3( energies_st3, input_frame_ptr, start_lag, sf_length, nb_subfr, complexity, arch ); - - lag_counter = 0; - silk_assert( lag == silk_SAT16( lag ) ); - contour_bias_Q15 = silk_DIV32_16( SILK_FIX_CONST( PE_FLATCONTOUR_BIAS, 15 ), lag ); - - target_ptr = &input_frame_ptr[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ]; - energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, nb_subfr * sf_length, arch ), 1 ); - for( d = start_lag; d <= end_lag; d++ ) { - for( j = 0; j < nb_cbk_search; j++ ) { - cross_corr = 0; - energy = energy_target; - for( k = 0; k < nb_subfr; k++ ) { - cross_corr = silk_ADD32( cross_corr, - matrix_ptr( cross_corr_st3, k, j, - nb_cbk_search )[ lag_counter ] ); - energy = silk_ADD32( energy, - matrix_ptr( energies_st3, k, j, - nb_cbk_search )[ lag_counter ] ); - silk_assert( energy >= 0 ); - } - if( cross_corr > 0 ) { - CCmax_new = silk_DIV32_varQ( cross_corr, energy, 13 + 1 ); /* Q13 */ - /* Reduce depending on flatness of contour */ - diff = silk_int16_MAX - silk_MUL( contour_bias_Q15, j ); /* Q15 */ - silk_assert( diff == silk_SAT16( diff ) ); - CCmax_new = silk_SMULWB( CCmax_new, diff ); /* Q14 */ - } else { - CCmax_new = 0; - } - - if( CCmax_new > CCmax && ( d + 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; - } - silk_assert( *lagIndex >= 0 ); - /* return as voiced */ - RESTORE_STACK; - 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_pe_stage3_vals cross_corr_st3[], /* O 3 DIM correlation array */ - const opus_int16 frame[], /* I vector to correlate */ - opus_int start_lag, /* I lag offset to search around */ - opus_int sf_length, /* I length of a 5 ms subframe */ - opus_int nb_subfr, /* I number of subframes */ - opus_int complexity, /* I Complexity setting */ - int arch /* I Run-time architecture */ -) -{ - const opus_int16 *target_ptr; - opus_int i, j, k, lag_counter, lag_low, lag_high; - opus_int nb_cbk_search, delta, idx, cbk_size; - VARDECL( opus_int32, scratch_mem ); - VARDECL( opus_int32, xcorr32 ); - const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; - SAVE_STACK; - - silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); - silk_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 { - silk_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; - } - ALLOC( scratch_mem, SCRATCH_SIZE, opus_int32 ); - ALLOC( xcorr32, SCRATCH_SIZE, opus_int32 ); - - 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, xcorr32, 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 ] = xcorr32[ 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 ); - matrix_ptr( cross_corr_st3, k, i, nb_cbk_search )[ j ] = - scratch_mem[ idx + j ]; - } - } - target_ptr += sf_length; - } - RESTORE_STACK; -} - -/********************************************************************/ -/* Calculate the energies for first two subframes. The energies are */ -/* calculated recursively. */ -/********************************************************************/ -static void silk_P_Ana_calc_energy_st3( - silk_pe_stage3_vals energies_st3[], /* O 3 DIM energy array */ - const opus_int16 frame[], /* I vector to calc energy in */ - opus_int start_lag, /* I lag offset to search around */ - opus_int sf_length, /* I length of one 5 ms subframe */ - opus_int nb_subfr, /* I number of subframes */ - opus_int complexity, /* I Complexity setting */ - int arch /* I Run-time architecture */ -) -{ - const opus_int16 *target_ptr, *basis_ptr; - opus_int32 energy; - opus_int k, i, j, lag_counter; - opus_int nb_cbk_search, delta, idx, cbk_size, lag_diff; - VARDECL( opus_int32, scratch_mem ); - const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; - SAVE_STACK; - - silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); - silk_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 { - silk_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; - } - ALLOC( scratch_mem, SCRATCH_SIZE, opus_int32 ); - - 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_inner_prod_aligned( basis_ptr, basis_ptr, sf_length, arch ); - silk_assert( energy >= 0 ); - scratch_mem[ lag_counter ] = 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 -= silk_SMULBB( basis_ptr[ sf_length - i ], basis_ptr[ sf_length - i ] ); - silk_assert( energy >= 0 ); - - /* add part that comes into window */ - energy = silk_ADD_SAT32( energy, silk_SMULBB( basis_ptr[ -i ], basis_ptr[ -i ] ) ); - silk_assert( energy >= 0 ); - silk_assert( lag_counter < SCRATCH_SIZE ); - scratch_mem[ lag_counter ] = 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 ); - matrix_ptr( energies_st3, k, i, nb_cbk_search )[ j ] = - scratch_mem[ idx + j ]; - silk_assert( - matrix_ptr( energies_st3, k, i, nb_cbk_search )[ j ] >= 0 ); - } - } - target_ptr += sf_length; - } - RESTORE_STACK; -} diff --git a/drivers/opus/silk/fixed/prefilter_FIX.c b/drivers/opus/silk/fixed/prefilter_FIX.c deleted file mode 100644 index 344be2badd..0000000000 --- a/drivers/opus/silk/fixed/prefilter_FIX.c +++ /dev/null @@ -1,218 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" -#include "opus/celt/stack_alloc.h" -#include "opus/silk/tuning_parameters.h" - -#if defined(MIPSr1_ASM) -#include "opus/silk/fixed/mips/prefilter_FIX_mipsr1.h" -#endif - - -#if !defined(OVERRIDE_silk_warped_LPC_analysis_filter_FIX) -#define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \ - ((void)(arch),silk_warped_LPC_analysis_filter_FIX_c(state, res_Q2, coef_Q13, input, lambda_Q16, length, order)) -#endif - -/* Prefilter for finding Quantizer input signal */ -static OPUS_INLINE void silk_prefilt_FIX( - silk_prefilter_state_FIX *P, /* I/O state */ - opus_int32 st_res_Q12[], /* I short term residual signal */ - opus_int32 xw_Q3[], /* O prefiltered signal */ - opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ - opus_int Tilt_Q14, /* I Tilt shaping coeficient */ - opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */ - opus_int lag, /* I Lag for harmonic shaping */ - opus_int length /* I Length of signals */ -); - -void silk_warped_LPC_analysis_filter_FIX_c( - opus_int32 state[], /* I/O State [order + 1] */ - opus_int32 res_Q2[], /* O Residual signal [length] */ - const opus_int16 coef_Q13[], /* I Coefficients [order] */ - const opus_int16 input[], /* I Input signal [length] */ - const opus_int16 lambda_Q16, /* I Warping factor */ - const opus_int length, /* I Length of input signal */ - const opus_int order /* I Filter order (even) */ -) -{ - opus_int n, i; - opus_int32 acc_Q11, tmp1, tmp2; - - /* Order must be even */ - silk_assert( ( order & 1 ) == 0 ); - - for( n = 0; n < length; n++ ) { - /* Output of lowpass section */ - tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 ); - state[ 0 ] = silk_LSHIFT( input[ n ], 14 ); - /* Output of allpass section */ - tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 ); - state[ 1 ] = tmp2; - acc_Q11 = silk_RSHIFT( order, 1 ); - acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] ); - /* Loop over allpass sections */ - for( i = 2; i < order; i += 2 ) { - /* Output of allpass section */ - tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 ); - state[ i ] = tmp1; - acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] ); - /* Output of allpass section */ - tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 ); - state[ i + 1 ] = tmp2; - acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] ); - } - state[ order ] = tmp1; - acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); - res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 ); - } -} - -void silk_prefilter_FIX( - silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ - const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */ - opus_int32 xw_Q3[], /* O Weighted signal */ - const opus_int16 x[] /* I Speech signal */ -) -{ - silk_prefilter_state_FIX *P = &psEnc->sPrefilt; - opus_int j, k, lag; - opus_int32 tmp_32; - const opus_int16 *AR1_shp_Q13; - const opus_int16 *px; - opus_int32 *pxw_Q3; - opus_int HarmShapeGain_Q12, Tilt_Q14; - opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14; - VARDECL( opus_int32, x_filt_Q12 ); - VARDECL( opus_int32, st_res_Q2 ); - opus_int16 B_Q10[ 2 ]; - SAVE_STACK; - - /* Set up pointers */ - px = x; - pxw_Q3 = xw_Q3; - lag = P->lagPrev; - ALLOC( x_filt_Q12, psEnc->sCmn.subfr_length, opus_int32 ); - ALLOC( st_res_Q2, psEnc->sCmn.subfr_length, opus_int32 ); - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - /* Update Variables that change per sub frame */ - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - lag = psEncCtrl->pitchL[ k ]; - } - - /* Noise shape parameters */ - HarmShapeGain_Q12 = silk_SMULWB( (opus_int32)psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] ); - silk_assert( HarmShapeGain_Q12 >= 0 ); - HarmShapeFIRPacked_Q12 = silk_RSHIFT( HarmShapeGain_Q12, 2 ); - HarmShapeFIRPacked_Q12 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q12, 1 ), 16 ); - Tilt_Q14 = psEncCtrl->Tilt_Q14[ k ]; - LF_shp_Q14 = psEncCtrl->LF_shp_Q14[ k ]; - AR1_shp_Q13 = &psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER ]; - - /* Short term FIR filtering*/ - silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res_Q2, AR1_shp_Q13, px, - psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder, psEnc->sCmn.arch ); - - /* Reduce (mainly) low frequencies during harmonic emphasis */ - B_Q10[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 4 ); - tmp_32 = silk_SMLABB( SILK_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */ - tmp_32 = silk_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */ - tmp_32 = silk_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */ - tmp_32 = silk_RSHIFT_ROUND( tmp_32, 14 ); /* Q10 */ - B_Q10[ 1 ]= silk_SAT16( tmp_32 ); - x_filt_Q12[ 0 ] = silk_MLA( silk_MUL( st_res_Q2[ 0 ], B_Q10[ 0 ] ), P->sHarmHP_Q2, B_Q10[ 1 ] ); - for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { - x_filt_Q12[ j ] = silk_MLA( silk_MUL( st_res_Q2[ j ], B_Q10[ 0 ] ), st_res_Q2[ j - 1 ], B_Q10[ 1 ] ); - } - P->sHarmHP_Q2 = st_res_Q2[ psEnc->sCmn.subfr_length - 1 ]; - - silk_prefilt_FIX( P, x_filt_Q12, pxw_Q3, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length ); - - px += psEnc->sCmn.subfr_length; - pxw_Q3 += psEnc->sCmn.subfr_length; - } - - P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ]; - RESTORE_STACK; -} - -#ifndef OVERRIDE_silk_prefilt_FIX -/* Prefilter for finding Quantizer input signal */ -static OPUS_INLINE void silk_prefilt_FIX( - silk_prefilter_state_FIX *P, /* I/O state */ - opus_int32 st_res_Q12[], /* I short term residual signal */ - opus_int32 xw_Q3[], /* O prefiltered signal */ - opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ - opus_int Tilt_Q14, /* I Tilt shaping coeficient */ - opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */ - opus_int lag, /* I Lag for harmonic shaping */ - opus_int length /* I Length of signals */ -) -{ - opus_int i, idx, LTP_shp_buf_idx; - opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10; - opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12; - opus_int16 *LTP_shp_buf; - - /* To speed up use temp variables instead of using the struct */ - LTP_shp_buf = P->sLTP_shp; - LTP_shp_buf_idx = P->sLTP_shp_buf_idx; - sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12; - sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12; - - for( i = 0; i < length; i++ ) { - if( lag > 0 ) { - /* unrolled loop */ - silk_assert( HARM_SHAPE_FIR_TAPS == 3 ); - idx = lag + LTP_shp_buf_idx; - n_LTP_Q12 = silk_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); - n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); - n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); - } else { - n_LTP_Q12 = 0; - } - - n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 ); - n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 ); - - sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) ); - sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) ); - - LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; - LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); - - xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 ); - } - - /* Copy temp variable back to state */ - P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12; - P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12; - P->sLTP_shp_buf_idx = LTP_shp_buf_idx; -} -#endif /* OVERRIDE_silk_prefilt_FIX */ diff --git a/drivers/opus/silk/fixed/process_gains_FIX.c b/drivers/opus/silk/fixed/process_gains_FIX.c deleted file mode 100644 index c0d591210b..0000000000 --- a/drivers/opus/silk/fixed/process_gains_FIX.c +++ /dev/null @@ -1,114 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" -#include "opus/silk/tuning_parameters.h" - -/* 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 */ -) -{ - silk_shape_state_FIX *psShapeSt = &psEnc->sShape; - opus_int k; - opus_int32 s_Q16, InvMaxSqrVal_Q16, gain, gain_squared, ResNrg, ResNrgPart, quant_offset_Q10; - - /* Gain reduction when LTP coding gain is high */ - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /*s = -0.5f * silk_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) ); */ - s_Q16 = -silk_sigm_Q15( silk_RSHIFT_ROUND( psEncCtrl->LTPredCodGain_Q7 - SILK_FIX_CONST( 12.0, 7 ), 4 ) ); - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->Gains_Q16[ k ] = silk_SMLAWB( psEncCtrl->Gains_Q16[ k ], psEncCtrl->Gains_Q16[ k ], s_Q16 ); - } - } - - /* Limit the quantized signal */ - /* InvMaxSqrVal = pow( 2.0f, 0.33f * ( 21.0f - SNR_dB ) ) / subfr_length; */ - InvMaxSqrVal_Q16 = silk_DIV32_16( silk_log2lin( - silk_SMULWB( SILK_FIX_CONST( 21 + 16 / 0.33, 7 ) - psEnc->sCmn.SNR_dB_Q7, SILK_FIX_CONST( 0.33, 16 ) ) ), psEnc->sCmn.subfr_length ); - - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - /* Soft limit on ratio residual energy and squared gains */ - ResNrg = psEncCtrl->ResNrg[ k ]; - ResNrgPart = silk_SMULWW( ResNrg, InvMaxSqrVal_Q16 ); - if( psEncCtrl->ResNrgQ[ k ] > 0 ) { - ResNrgPart = silk_RSHIFT_ROUND( ResNrgPart, psEncCtrl->ResNrgQ[ k ] ); - } else { - if( ResNrgPart >= silk_RSHIFT( silk_int32_MAX, -psEncCtrl->ResNrgQ[ k ] ) ) { - ResNrgPart = silk_int32_MAX; - } else { - ResNrgPart = silk_LSHIFT( ResNrgPart, -psEncCtrl->ResNrgQ[ k ] ); - } - } - gain = psEncCtrl->Gains_Q16[ k ]; - gain_squared = silk_ADD_SAT32( ResNrgPart, silk_SMMUL( gain, gain ) ); - if( gain_squared < silk_int16_MAX ) { - /* recalculate with higher precision */ - gain_squared = silk_SMLAWW( silk_LSHIFT( ResNrgPart, 16 ), gain, gain ); - silk_assert( gain_squared > 0 ); - gain = silk_SQRT_APPROX( gain_squared ); /* Q8 */ - gain = silk_min( gain, silk_int32_MAX >> 8 ); - psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( gain, 8 ); /* Q16 */ - } else { - gain = silk_SQRT_APPROX( gain_squared ); /* Q0 */ - gain = silk_min( gain, silk_int32_MAX >> 16 ); - psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( gain, 16 ); /* Q16 */ - } - } - - /* Save unquantized gains and gain Index */ - silk_memcpy( psEncCtrl->GainsUnq_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); - psEncCtrl->lastGainIndexPrev = psShapeSt->LastGainIndex; - - /* Quantize gains */ - silk_gains_quant( psEnc->sCmn.indices.GainsIndices, psEncCtrl->Gains_Q16, - &psShapeSt->LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); - - /* 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_Q7 + silk_RSHIFT( psEnc->sCmn.input_tilt_Q15, 8 ) > SILK_FIX_CONST( 1.0, 7 ) ) { - psEnc->sCmn.indices.quantOffsetType = 0; - } else { - psEnc->sCmn.indices.quantOffsetType = 1; - } - } - - /* Quantizer boundary adjustment */ - quant_offset_Q10 = silk_Quantization_Offsets_Q10[ psEnc->sCmn.indices.signalType >> 1 ][ psEnc->sCmn.indices.quantOffsetType ]; - psEncCtrl->Lambda_Q10 = SILK_FIX_CONST( LAMBDA_OFFSET, 10 ) - + silk_SMULBB( SILK_FIX_CONST( LAMBDA_DELAYED_DECISIONS, 10 ), psEnc->sCmn.nStatesDelayedDecision ) - + silk_SMULWB( SILK_FIX_CONST( LAMBDA_SPEECH_ACT, 18 ), psEnc->sCmn.speech_activity_Q8 ) - + silk_SMULWB( SILK_FIX_CONST( LAMBDA_INPUT_QUALITY, 12 ), psEncCtrl->input_quality_Q14 ) - + silk_SMULWB( SILK_FIX_CONST( LAMBDA_CODING_QUALITY, 12 ), psEncCtrl->coding_quality_Q14 ) - + silk_SMULWB( SILK_FIX_CONST( LAMBDA_QUANT_OFFSET, 16 ), quant_offset_Q10 ); - - silk_assert( psEncCtrl->Lambda_Q10 > 0 ); - silk_assert( psEncCtrl->Lambda_Q10 < SILK_FIX_CONST( 2, 10 ) ); -} diff --git a/drivers/opus/silk/fixed/regularize_correlations_FIX.c b/drivers/opus/silk/fixed/regularize_correlations_FIX.c deleted file mode 100644 index c38a5589b6..0000000000 --- a/drivers/opus/silk/fixed/regularize_correlations_FIX.c +++ /dev/null @@ -1,44 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" - -/* Add noise to matrix diagonal */ -void silk_regularize_correlations_FIX( - opus_int32 *XX, /* I/O Correlation matrices */ - opus_int32 *xx, /* I/O Correlation values */ - opus_int32 noise, /* I Noise to add */ - opus_int D /* I Dimension of XX */ -) -{ - opus_int i; - for( i = 0; i < D; i++ ) { - matrix_ptr( &XX[ 0 ], i, i, D ) = silk_ADD32( matrix_ptr( &XX[ 0 ], i, i, D ), noise ); - } - xx[ 0 ] += noise; -} diff --git a/drivers/opus/silk/fixed/residual_energy16_FIX.c b/drivers/opus/silk/fixed/residual_energy16_FIX.c deleted file mode 100644 index 39bc96fd90..0000000000 --- a/drivers/opus/silk/fixed/residual_energy16_FIX.c +++ /dev/null @@ -1,100 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" - -/* 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 */ -) -{ - opus_int i, j, lshifts, Qxtra; - opus_int32 c_max, w_max, tmp, tmp2, nrg; - opus_int cn[ MAX_MATRIX_SIZE ]; - const opus_int32 *pRow; - - /* Safety checks */ - silk_assert( D >= 0 ); - silk_assert( D <= 16 ); - silk_assert( cQ > 0 ); - silk_assert( cQ < 16 ); - - lshifts = 16 - cQ; - Qxtra = lshifts; - - c_max = 0; - for( i = 0; i < D; i++ ) { - c_max = silk_max_32( c_max, silk_abs( (opus_int32)c[ i ] ) ); - } - Qxtra = silk_min_int( Qxtra, silk_CLZ32( c_max ) - 17 ); - - w_max = silk_max_32( wXX[ 0 ], wXX[ D * D - 1 ] ); - Qxtra = silk_min_int( Qxtra, silk_CLZ32( silk_MUL( D, silk_RSHIFT( silk_SMULWB( w_max, c_max ), 4 ) ) ) - 5 ); - Qxtra = silk_max_int( Qxtra, 0 ); - for( i = 0; i < D; i++ ) { - cn[ i ] = silk_LSHIFT( ( opus_int )c[ i ], Qxtra ); - silk_assert( silk_abs(cn[i]) <= ( silk_int16_MAX + 1 ) ); /* Check that silk_SMLAWB can be used */ - } - lshifts -= Qxtra; - - /* Compute wxx - 2 * wXx * c */ - tmp = 0; - for( i = 0; i < D; i++ ) { - tmp = silk_SMLAWB( tmp, wXx[ i ], cn[ i ] ); - } - nrg = silk_RSHIFT( wxx, 1 + lshifts ) - tmp; /* Q: -lshifts - 1 */ - - /* Add c' * wXX * c, assuming wXX is symmetric */ - tmp2 = 0; - for( i = 0; i < D; i++ ) { - tmp = 0; - pRow = &wXX[ i * D ]; - for( j = i + 1; j < D; j++ ) { - tmp = silk_SMLAWB( tmp, pRow[ j ], cn[ j ] ); - } - tmp = silk_SMLAWB( tmp, silk_RSHIFT( pRow[ i ], 1 ), cn[ i ] ); - tmp2 = silk_SMLAWB( tmp2, tmp, cn[ i ] ); - } - nrg = silk_ADD_LSHIFT32( nrg, tmp2, lshifts ); /* Q: -lshifts - 1 */ - - /* Keep one bit free always, because we add them for LSF interpolation */ - if( nrg < 1 ) { - nrg = 1; - } else if( nrg > silk_RSHIFT( silk_int32_MAX, lshifts + 2 ) ) { - nrg = silk_int32_MAX >> 1; - } else { - nrg = silk_LSHIFT( nrg, lshifts + 1 ); /* Q0 */ - } - return nrg; - -} diff --git a/drivers/opus/silk/fixed/residual_energy_FIX.c b/drivers/opus/silk/fixed/residual_energy_FIX.c deleted file mode 100644 index 0e51f4baa1..0000000000 --- a/drivers/opus/silk/fixed/residual_energy_FIX.c +++ /dev/null @@ -1,95 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" -#include "opus/celt/stack_alloc.h" - -/* 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 */ -) -{ - opus_int offset, i, j, rshift, lz1, lz2; - opus_int16 *LPC_res_ptr; - VARDECL( opus_int16, LPC_res ); - const opus_int16 *x_ptr; - opus_int32 tmp32; - SAVE_STACK; - - x_ptr = x; - offset = LPC_order + subfr_length; - - /* Filter input to create the LPC residual for each frame half, and measure subframe energies */ - ALLOC( LPC_res, ( MAX_NB_SUBFR >> 1 ) * offset, opus_int16 ); - silk_assert( ( nb_subfr >> 1 ) * ( MAX_NB_SUBFR >> 1 ) == nb_subfr ); - for( i = 0; i < nb_subfr >> 1; i++ ) { - /* Calculate half frame LPC residual signal including preceding samples */ - silk_LPC_analysis_filter( LPC_res, x_ptr, a_Q12[ i ], ( MAX_NB_SUBFR >> 1 ) * offset, LPC_order, arch ); - - /* Point to first subframe of the just calculated LPC residual signal */ - LPC_res_ptr = LPC_res + LPC_order; - for( j = 0; j < ( MAX_NB_SUBFR >> 1 ); j++ ) { - /* Measure subframe energy */ - silk_sum_sqr_shift( &nrgs[ i * ( MAX_NB_SUBFR >> 1 ) + j ], &rshift, LPC_res_ptr, subfr_length ); - - /* Set Q values for the measured energy */ - nrgsQ[ i * ( MAX_NB_SUBFR >> 1 ) + j ] = -rshift; - - /* Move to next subframe */ - LPC_res_ptr += offset; - } - /* Move to next frame half */ - x_ptr += ( MAX_NB_SUBFR >> 1 ) * offset; - } - - /* Apply the squared subframe gains */ - for( i = 0; i < nb_subfr; i++ ) { - /* Fully upscale gains and energies */ - lz1 = silk_CLZ32( nrgs[ i ] ) - 1; - lz2 = silk_CLZ32( gains[ i ] ) - 1; - - tmp32 = silk_LSHIFT32( gains[ i ], lz2 ); - - /* Find squared gains */ - tmp32 = silk_SMMUL( tmp32, tmp32 ); /* Q( 2 * lz2 - 32 )*/ - - /* Scale energies */ - nrgs[ i ] = silk_SMMUL( tmp32, silk_LSHIFT32( nrgs[ i ], lz1 ) ); /* Q( nrgsQ[ i ] + lz1 + 2 * lz2 - 32 - 32 )*/ - nrgsQ[ i ] += lz1 + 2 * lz2 - 32 - 32; - } - RESTORE_STACK; -} diff --git a/drivers/opus/silk/fixed/schur64_FIX.c b/drivers/opus/silk/fixed/schur64_FIX.c deleted file mode 100644 index 69ef76e028..0000000000 --- a/drivers/opus/silk/fixed/schur64_FIX.c +++ /dev/null @@ -1,89 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" - -/* 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 */ -) -{ - opus_int k, n; - opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; - opus_int32 Ctmp1_Q30, Ctmp2_Q30, rc_tmp_Q31; - - silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 ); - - /* Check for invalid input */ - if( c[ 0 ] <= 0 ) { - silk_memset( rc_Q16, 0, order * sizeof( opus_int32 ) ); - return 0; - } - - for( k = 0; k < order + 1; k++ ) { - C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; - } - - for( k = 0; k < order; k++ ) { - /* Check that we won't be getting an unstable rc, otherwise stop here. */ - if (silk_abs_int32(C[ k + 1 ][ 0 ]) >= C[ 0 ][ 1 ]) { - if ( C[ k + 1 ][ 0 ] > 0 ) { - rc_Q16[ k ] = -SILK_FIX_CONST( .99f, 16 ); - } else { - rc_Q16[ k ] = SILK_FIX_CONST( .99f, 16 ); - } - k++; - break; - } - - /* Get reflection coefficient: divide two Q30 values and get result in Q31 */ - rc_tmp_Q31 = silk_DIV32_varQ( -C[ k + 1 ][ 0 ], C[ 0 ][ 1 ], 31 ); - - /* Save the output */ - rc_Q16[ k ] = silk_RSHIFT_ROUND( rc_tmp_Q31, 15 ); - - /* Update correlations */ - for( n = 0; n < order - k; n++ ) { - Ctmp1_Q30 = C[ n + k + 1 ][ 0 ]; - Ctmp2_Q30 = C[ n ][ 1 ]; - - /* Multiply and add the highest int32 */ - C[ n + k + 1 ][ 0 ] = Ctmp1_Q30 + silk_SMMUL( silk_LSHIFT( Ctmp2_Q30, 1 ), rc_tmp_Q31 ); - C[ n ][ 1 ] = Ctmp2_Q30 + silk_SMMUL( silk_LSHIFT( Ctmp1_Q30, 1 ), rc_tmp_Q31 ); - } - } - - for(; k < order; k++ ) { - rc_Q16[ k ] = 0; - } - - return silk_max_32( 1, C[ 0 ][ 1 ] ); -} diff --git a/drivers/opus/silk/fixed/schur_FIX.c b/drivers/opus/silk/fixed/schur_FIX.c deleted file mode 100644 index 9effa59daf..0000000000 --- a/drivers/opus/silk/fixed/schur_FIX.c +++ /dev/null @@ -1,103 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" - -/* 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 */ -) -{ - opus_int k, n, lz; - opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; - opus_int32 Ctmp1, Ctmp2, rc_tmp_Q15; - - silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 ); - - /* Get number of leading zeros */ - lz = silk_CLZ32( c[ 0 ] ); - - /* Copy correlations and adjust level to Q30 */ - if( lz < 2 ) { - /* lz must be 1, so shift one to the right */ - for( k = 0; k < order + 1; k++ ) { - C[ k ][ 0 ] = C[ k ][ 1 ] = silk_RSHIFT( c[ k ], 1 ); - } - } else if( lz > 2 ) { - /* Shift to the left */ - lz -= 2; - for( k = 0; k < order + 1; k++ ) { - C[ k ][ 0 ] = C[ k ][ 1 ] = silk_LSHIFT( c[ k ], lz ); - } - } else { - /* No need to shift */ - for( k = 0; k < order + 1; k++ ) { - C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; - } - } - - for( k = 0; k < order; k++ ) { - /* Check that we won't be getting an unstable rc, otherwise stop here. */ - if (silk_abs_int32(C[ k + 1 ][ 0 ]) >= C[ 0 ][ 1 ]) { - if ( C[ k + 1 ][ 0 ] > 0 ) { - rc_Q15[ k ] = -SILK_FIX_CONST( .99f, 15 ); - } else { - rc_Q15[ k ] = SILK_FIX_CONST( .99f, 15 ); - } - k++; - break; - } - - /* Get reflection coefficient */ - rc_tmp_Q15 = -silk_DIV32_16( C[ k + 1 ][ 0 ], silk_max_32( silk_RSHIFT( C[ 0 ][ 1 ], 15 ), 1 ) ); - - /* Clip (shouldn't happen for properly conditioned inputs) */ - rc_tmp_Q15 = silk_SAT16( rc_tmp_Q15 ); - - /* Store */ - rc_Q15[ k ] = (opus_int16)rc_tmp_Q15; - - /* Update correlations */ - for( n = 0; n < order - k; n++ ) { - Ctmp1 = C[ n + k + 1 ][ 0 ]; - Ctmp2 = C[ n ][ 1 ]; - C[ n + k + 1 ][ 0 ] = silk_SMLAWB( Ctmp1, silk_LSHIFT( Ctmp2, 1 ), rc_tmp_Q15 ); - C[ n ][ 1 ] = silk_SMLAWB( Ctmp2, silk_LSHIFT( Ctmp1, 1 ), rc_tmp_Q15 ); - } - } - - for(; k < order; k++ ) { - rc_Q15[ k ] = 0; - } - - /* return residual energy */ - return silk_max_32( 1, C[ 0 ][ 1 ] ); -} diff --git a/drivers/opus/silk/fixed/solve_LS_FIX.c b/drivers/opus/silk/fixed/solve_LS_FIX.c deleted file mode 100644 index 4ff97497be..0000000000 --- a/drivers/opus/silk/fixed/solve_LS_FIX.c +++ /dev/null @@ -1,246 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" -#include "opus/celt/stack_alloc.h" -#include "opus/silk/tuning_parameters.h" - -/*****************************/ -/* Internal function headers */ -/*****************************/ - -typedef struct { - opus_int32 Q36_part; - opus_int32 Q48_part; -} inv_D_t; - -/* Factorize square matrix A into LDL form */ -static OPUS_INLINE void silk_LDL_factorize_FIX( - opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */ - opus_int M, /* I Size of Matrix */ - opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */ - inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */ -); - -/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */ -static OPUS_INLINE void silk_LS_SolveFirst_FIX( - const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ - opus_int M, /* I Dim of Matrix equation */ - const opus_int32 *b, /* I b Vector */ - opus_int32 *x_Q16 /* O x Vector */ -); - -/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */ -static OPUS_INLINE void silk_LS_SolveLast_FIX( - const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ - const opus_int M, /* I Dim of Matrix equation */ - const opus_int32 *b, /* I b Vector */ - opus_int32 *x_Q16 /* O x Vector */ -); - -static OPUS_INLINE void silk_LS_divide_Q16_FIX( - opus_int32 T[], /* I/O Numenator vector */ - inv_D_t *inv_D, /* I 1 / D vector */ - opus_int M /* I dimension */ -); - -/* Solves Ax = b, assuming A is symmetric */ -void silk_solve_LDL_FIX( - opus_int32 *A, /* I Pointer to symetric square matrix A */ - opus_int M, /* I Size of matrix */ - const opus_int32 *b, /* I Pointer to b vector */ - opus_int32 *x_Q16 /* O Pointer to x solution vector */ -) -{ - VARDECL( opus_int32, L_Q16 ); - opus_int32 Y[ MAX_MATRIX_SIZE ]; - inv_D_t inv_D[ MAX_MATRIX_SIZE ]; - SAVE_STACK; - - silk_assert( M <= MAX_MATRIX_SIZE ); - ALLOC( L_Q16, M * M, opus_int32 ); - - /*************************************************** - Factorize A by LDL such that A = L*D*L', - where L is lower triangular with ones on diagonal - ****************************************************/ - silk_LDL_factorize_FIX( A, M, L_Q16, inv_D ); - - /**************************************************** - * substitute D*L'*x = Y. ie: - L*D*L'*x = b => L*Y = b <=> Y = inv(L)*b - ******************************************************/ - silk_LS_SolveFirst_FIX( L_Q16, M, b, Y ); - - /**************************************************** - D*L'*x = Y <=> L'*x = inv(D)*Y, because D is - diagonal just multiply with 1/d_i - ****************************************************/ - silk_LS_divide_Q16_FIX( Y, inv_D, M ); - - /**************************************************** - x = inv(L') * inv(D) * Y - *****************************************************/ - silk_LS_SolveLast_FIX( L_Q16, M, Y, x_Q16 ); - RESTORE_STACK; -} - -static OPUS_INLINE void silk_LDL_factorize_FIX( - opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */ - opus_int M, /* I Size of Matrix */ - opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */ - inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */ -) -{ - opus_int i, j, k, status, loop_count; - const opus_int32 *ptr1, *ptr2; - opus_int32 diag_min_value, tmp_32, err; - opus_int32 v_Q0[ MAX_MATRIX_SIZE ], D_Q0[ MAX_MATRIX_SIZE ]; - opus_int32 one_div_diag_Q36, one_div_diag_Q40, one_div_diag_Q48; - - silk_assert( M <= MAX_MATRIX_SIZE ); - - status = 1; - diag_min_value = silk_max_32( silk_SMMUL( silk_ADD_SAT32( A[ 0 ], A[ silk_SMULBB( M, M ) - 1 ] ), SILK_FIX_CONST( FIND_LTP_COND_FAC, 31 ) ), 1 << 9 ); - for( loop_count = 0; loop_count < M && status == 1; loop_count++ ) { - status = 0; - for( j = 0; j < M; j++ ) { - ptr1 = matrix_adr( L_Q16, j, 0, M ); - tmp_32 = 0; - for( i = 0; i < j; i++ ) { - v_Q0[ i ] = silk_SMULWW( D_Q0[ i ], ptr1[ i ] ); /* Q0 */ - tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ i ], ptr1[ i ] ); /* Q0 */ - } - tmp_32 = silk_SUB32( matrix_ptr( A, j, j, M ), tmp_32 ); - - if( tmp_32 < diag_min_value ) { - tmp_32 = silk_SUB32( silk_SMULBB( loop_count + 1, diag_min_value ), tmp_32 ); - /* Matrix not positive semi-definite, or ill conditioned */ - for( i = 0; i < M; i++ ) { - matrix_ptr( A, i, i, M ) = silk_ADD32( matrix_ptr( A, i, i, M ), tmp_32 ); - } - status = 1; - break; - } - D_Q0[ j ] = tmp_32; /* always < max(Correlation) */ - - /* two-step division */ - one_div_diag_Q36 = silk_INVERSE32_varQ( tmp_32, 36 ); /* Q36 */ - one_div_diag_Q40 = silk_LSHIFT( one_div_diag_Q36, 4 ); /* Q40 */ - err = silk_SUB32( (opus_int32)1 << 24, silk_SMULWW( tmp_32, one_div_diag_Q40 ) ); /* Q24 */ - one_div_diag_Q48 = silk_SMULWW( err, one_div_diag_Q40 ); /* Q48 */ - - /* Save 1/Ds */ - inv_D[ j ].Q36_part = one_div_diag_Q36; - inv_D[ j ].Q48_part = one_div_diag_Q48; - - matrix_ptr( L_Q16, j, j, M ) = 65536; /* 1.0 in Q16 */ - ptr1 = matrix_adr( A, j, 0, M ); - ptr2 = matrix_adr( L_Q16, j + 1, 0, M ); - for( i = j + 1; i < M; i++ ) { - tmp_32 = 0; - for( k = 0; k < j; k++ ) { - tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ k ], ptr2[ k ] ); /* Q0 */ - } - tmp_32 = silk_SUB32( ptr1[ i ], tmp_32 ); /* always < max(Correlation) */ - - /* tmp_32 / D_Q0[j] : Divide to Q16 */ - matrix_ptr( L_Q16, i, j, M ) = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ), - silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) ); - - /* go to next column */ - ptr2 += M; - } - } - } - - silk_assert( status == 0 ); -} - -static OPUS_INLINE void silk_LS_divide_Q16_FIX( - opus_int32 T[], /* I/O Numenator vector */ - inv_D_t *inv_D, /* I 1 / D vector */ - opus_int M /* I dimension */ -) -{ - opus_int i; - opus_int32 tmp_32; - opus_int32 one_div_diag_Q36, one_div_diag_Q48; - - for( i = 0; i < M; i++ ) { - one_div_diag_Q36 = inv_D[ i ].Q36_part; - one_div_diag_Q48 = inv_D[ i ].Q48_part; - - tmp_32 = T[ i ]; - T[ i ] = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ), silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) ); - } -} - -/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */ -static OPUS_INLINE void silk_LS_SolveFirst_FIX( - const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ - opus_int M, /* I Dim of Matrix equation */ - const opus_int32 *b, /* I b Vector */ - opus_int32 *x_Q16 /* O x Vector */ -) -{ - opus_int i, j; - const opus_int32 *ptr32; - opus_int32 tmp_32; - - for( i = 0; i < M; i++ ) { - ptr32 = matrix_adr( L_Q16, i, 0, M ); - tmp_32 = 0; - for( j = 0; j < i; j++ ) { - tmp_32 = silk_SMLAWW( tmp_32, ptr32[ j ], x_Q16[ j ] ); - } - x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 ); - } -} - -/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */ -static OPUS_INLINE void silk_LS_SolveLast_FIX( - const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ - const opus_int M, /* I Dim of Matrix equation */ - const opus_int32 *b, /* I b Vector */ - opus_int32 *x_Q16 /* O x Vector */ -) -{ - opus_int i, j; - const opus_int32 *ptr32; - opus_int32 tmp_32; - - for( i = M - 1; i >= 0; i-- ) { - ptr32 = matrix_adr( L_Q16, 0, i, M ); - tmp_32 = 0; - for( j = M - 1; j > i; j-- ) { - tmp_32 = silk_SMLAWW( tmp_32, ptr32[ silk_SMULBB( j, M ) ], x_Q16[ j ] ); - } - x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 ); - } -} diff --git a/drivers/opus/silk/fixed/structs_FIX.h b/drivers/opus/silk/fixed/structs_FIX.h deleted file mode 100644 index 36ddff0a9e..0000000000 --- a/drivers/opus/silk/fixed/structs_FIX.h +++ /dev/null @@ -1,134 +0,0 @@ -/*********************************************************************** -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 "opus/silk/typedef.h" -#include "opus/silk/main.h" -#include "opus/silk/structs.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************/ -/* 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; - -/********************************/ -/* Prefilter state */ -/********************************/ -typedef struct { - opus_int16 sLTP_shp[ LTP_BUF_LENGTH ]; - opus_int32 sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ]; - opus_int sLTP_shp_buf_idx; - opus_int32 sLF_AR_shp_Q12; - opus_int32 sLF_MA_shp_Q12; - opus_int32 sHarmHP_Q2; - opus_int32 rand_seed; - opus_int lagPrev; -} silk_prefilter_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 */ - silk_prefilter_state_FIX sPrefilt; /* Prefilter 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 */ -} 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 AR1_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; - silk_DWORD_ALIGN opus_int16 AR2_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 GainsPre_Q14[ MAX_NB_SUBFR ]; - opus_int HarmBoost_Q14[ MAX_NB_SUBFR ]; - 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_int sparseness_Q8; - 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 { - silk_encoder_state_FIX state_Fxx[ ENCODER_NUM_CHANNELS ]; - 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; -} silk_encoder; - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/opus/silk/fixed/vector_ops_FIX.c b/drivers/opus/silk/fixed/vector_ops_FIX.c deleted file mode 100644 index 1e8fdec0cb..0000000000 --- a/drivers/opus/silk/fixed/vector_ops_FIX.c +++ /dev/null @@ -1,99 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" -#include "opus/celt/pitch.h" - -/* 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 */ -) -{ - opus_int i; - opus_int32 tmp32; - - for( i = 0; i < dataSize; i++ ) { - tmp32 = silk_SMULWB( gain_Q16, data_in[ i ] ); - data_out[ i ] = (opus_int16)silk_CHECK_FIT16( tmp32 ); - } -} - -/* Multiply a vector by a constant */ -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 */ -) -{ - opus_int i; - - for( i = 0; i < dataSize; i++ ) { - data1[ i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( silk_SMULL( data1[ i ], gain_Q26 ), 8 ) ); /* OUTPUT: Q18 */ - } -} - -/* sum = for(i=0;i<len;i++)inVec1[i]*inVec2[i]; --- inner product */ -/* Note for ARM asm: */ -/* * inVec1 and inVec2 should be at least 2 byte aligned. */ -/* * len should be positive 16bit integer. */ -/* * only when len>6, memory access can be reduced by half. */ -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 */ -) -{ -#ifdef OPUS_FIXED_POINT - return celt_inner_prod(inVec1, inVec2, len, arch); -#else - opus_int i; - opus_int32 sum = 0; - for( i = 0; i < len; i++ ) { - sum = silk_SMLABB( sum, inVec1[ i ], inVec2[ i ] ); - } - return sum; -#endif -} - -opus_int64 silk_inner_prod16_aligned_64_c( - const opus_int16 *inVec1, /* I input vector 1 */ - const opus_int16 *inVec2, /* I input vector 2 */ - const opus_int len /* I vector lengths */ -) -{ - opus_int i; - opus_int64 sum = 0; - for( i = 0; i < len; i++ ) { - sum = silk_SMLALBB( sum, inVec1[ i ], inVec2[ i ] ); - } - return sum; -} diff --git a/drivers/opus/silk/fixed/warped_autocorrelation_FIX.c b/drivers/opus/silk/fixed/warped_autocorrelation_FIX.c deleted file mode 100644 index 3b8d52d5c6..0000000000 --- a/drivers/opus/silk/fixed/warped_autocorrelation_FIX.c +++ /dev/null @@ -1,92 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/fixed/main_FIX.h" - -#define QC 10 -#define QS 14 - -#if defined(MIPSr1_ASM) -#include "opus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h" -#endif - - -#ifndef OVERRIDE_silk_warped_autocorrelation_FIX -/* Autocorrelations for a warped frequency axis */ -void silk_warped_autocorrelation_FIX( - 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, tmp2_QS; - opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; - opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; - - /* Order must be even */ - silk_assert( ( order & 1 ) == 0 ); - silk_assert( 2 * QS - QC >= 0 ); - - /* Loop over samples */ - for( n = 0; 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 ] += silk_RSHIFT64( silk_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); - /* 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 ] += silk_RSHIFT64( silk_SMULL( tmp2_QS, state_QS[ 0 ] ), 2 * QS - QC ); - } - state_QS[ order ] = tmp1_QS; - corr_QC[ order ] += silk_RSHIFT64( silk_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); - } - - lsh = silk_CLZ64( corr_QC[ 0 ] ) - 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++ ) { - corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_LSHIFT64( corr_QC[ i ], lsh ) ); - } - } else { - for( i = 0; i < order + 1; i++ ) { - corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QC[ i ], -lsh ) ); - } - } - silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/ -} -#endif /* OVERRIDE_silk_warped_autocorrelation_FIX */ diff --git a/drivers/opus/silk/fixed/x86/burg_modified_FIX_sse.c b/drivers/opus/silk/fixed/x86/burg_modified_FIX_sse.c deleted file mode 100644 index f7d46487df..0000000000 --- a/drivers/opus/silk/fixed/x86/burg_modified_FIX_sse.c +++ /dev/null @@ -1,372 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include <xmmintrin.h> -#include <emmintrin.h> -#include <smmintrin.h> - -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/define.h" -#include "opus/silk/tuning_parameters.h" -#include "opus/celt/pitch.h" -#include "opus/celt/x86/x86cpu.h" - -#define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */ - -#define QA 25 -#define N_BITS_HEAD_ROOM 2 -#define MIN_RSHIFTS -16 -#define MAX_RSHIFTS (32 - QA) - -/* Compute reflection coefficients from input signal */ -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 */ -) -{ - opus_int k, n, s, lz, rshifts, rshifts_extra, reached_max_gain; - opus_int32 C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2; - const opus_int16 *x_ptr; - opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ]; - opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ]; - opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ]; - opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ]; - opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ]; - opus_int32 xcorr[ SILK_MAX_ORDER_LPC ]; - - __m128i FIRST_3210, LAST_3210, ATMP_3210, TMP1_3210, TMP2_3210, T1_3210, T2_3210, PTR_3210, SUBFR_3210, X1_3210, X2_3210; - __m128i CONST1 = _mm_set1_epi32(1); - - silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); - - /* Compute autocorrelations, added over subframes */ - silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length ); - if( rshifts > MAX_RSHIFTS ) { - C0 = silk_LSHIFT32( C0, rshifts - MAX_RSHIFTS ); - silk_assert( C0 > 0 ); - rshifts = MAX_RSHIFTS; - } else { - lz = silk_CLZ32( C0 ) - 1; - rshifts_extra = N_BITS_HEAD_ROOM - lz; - if( rshifts_extra > 0 ) { - rshifts_extra = silk_min( rshifts_extra, MAX_RSHIFTS - rshifts ); - C0 = silk_RSHIFT32( C0, rshifts_extra ); - } else { - rshifts_extra = silk_max( rshifts_extra, MIN_RSHIFTS - rshifts ); - C0 = silk_LSHIFT32( C0, -rshifts_extra ); - } - rshifts += rshifts_extra; - } - CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ - silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); - if( rshifts > 0 ) { - 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 ] += (opus_int32)silk_RSHIFT64( - silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n, arch ), rshifts ); - } - } - } else { - for( s = 0; s < nb_subfr; s++ ) { - int i; - opus_int32 d; - x_ptr = x + s * subfr_length; - celt_pitch_xcorr(x_ptr, x_ptr + 1, xcorr, subfr_length - D, D, arch ); - for( n = 1; n < D + 1; n++ ) { - for ( i = n + subfr_length - D, d = 0; i < subfr_length; i++ ) - d = MAC16_16( d, x_ptr[ i ], x_ptr[ i - n ] ); - xcorr[ n - 1 ] += d; - } - for( n = 1; n < D + 1; n++ ) { - C_first_row[ n - 1 ] += silk_LSHIFT32( xcorr[ n - 1 ], -rshifts ); - } - } - } - silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); - - /* Initialize */ - CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ - - invGain_Q30 = (opus_int32)1 << 30; - 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) */ - if( rshifts > -2 ) { - for( s = 0; s < nb_subfr; s++ ) { - x_ptr = x + s * subfr_length; - x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], 16 - rshifts ); /* Q(16-rshifts) */ - x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts ); /* Q(16-rshifts) */ - tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], QA - 16 ); /* Q(QA-16) */ - tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); /* Q(QA-16) */ - for( k = 0; k < n; k++ ) { - C_first_row[ k ] = silk_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ - C_last_row[ k ] = silk_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ - Atmp_QA = Af_QA[ k ]; - tmp1 = silk_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); /* Q(QA-16) */ - tmp2 = silk_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] ); /* Q(QA-16) */ - } - tmp1 = silk_LSHIFT32( -tmp1, 32 - QA - rshifts ); /* Q(16-rshifts) */ - tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts ); /* Q(16-rshifts) */ - for( k = 0; k <= n; k++ ) { - CAf[ k ] = silk_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); /* Q( -rshift ) */ - CAb[ k ] = silk_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); /* Q( -rshift ) */ - } - } - } else { - for( s = 0; s < nb_subfr; s++ ) { - x_ptr = x + s * subfr_length; - x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], -rshifts ); /* Q( -rshifts ) */ - x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); /* Q( -rshifts ) */ - tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); /* Q17 */ - tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); /* Q17 */ - - X1_3210 = _mm_set1_epi32( x1 ); - X2_3210 = _mm_set1_epi32( x2 ); - TMP1_3210 = _mm_setzero_si128(); - TMP2_3210 = _mm_setzero_si128(); - for( k = 0; k < n - 3; k += 4 ) { - PTR_3210 = OP_CVTEPI16_EPI32_M64( &x_ptr[ n - k - 1 - 3 ] ); - SUBFR_3210 = OP_CVTEPI16_EPI32_M64( &x_ptr[ subfr_length - n + k ] ); - FIRST_3210 = _mm_loadu_si128( (__m128i *)&C_first_row[ k ] ); - PTR_3210 = _mm_shuffle_epi32( PTR_3210, _MM_SHUFFLE( 0, 1, 2, 3 ) ); - LAST_3210 = _mm_loadu_si128( (__m128i *)&C_last_row[ k ] ); - ATMP_3210 = _mm_loadu_si128( (__m128i *)&Af_QA[ k ] ); - - T1_3210 = _mm_mullo_epi32( PTR_3210, X1_3210 ); - T2_3210 = _mm_mullo_epi32( SUBFR_3210, X2_3210 ); - - ATMP_3210 = _mm_srai_epi32( ATMP_3210, 7 ); - ATMP_3210 = _mm_add_epi32( ATMP_3210, CONST1 ); - ATMP_3210 = _mm_srai_epi32( ATMP_3210, 1 ); - - FIRST_3210 = _mm_add_epi32( FIRST_3210, T1_3210 ); - LAST_3210 = _mm_add_epi32( LAST_3210, T2_3210 ); - - PTR_3210 = _mm_mullo_epi32( ATMP_3210, PTR_3210 ); - SUBFR_3210 = _mm_mullo_epi32( ATMP_3210, SUBFR_3210 ); - - _mm_storeu_si128( (__m128i *)&C_first_row[ k ], FIRST_3210 ); - _mm_storeu_si128( (__m128i *)&C_last_row[ k ], LAST_3210 ); - - TMP1_3210 = _mm_add_epi32( TMP1_3210, PTR_3210 ); - TMP2_3210 = _mm_add_epi32( TMP2_3210, SUBFR_3210 ); - } - - TMP1_3210 = _mm_add_epi32( TMP1_3210, _mm_unpackhi_epi64(TMP1_3210, TMP1_3210 ) ); - TMP2_3210 = _mm_add_epi32( TMP2_3210, _mm_unpackhi_epi64(TMP2_3210, TMP2_3210 ) ); - TMP1_3210 = _mm_add_epi32( TMP1_3210, _mm_shufflelo_epi16(TMP1_3210, 0x0E ) ); - TMP2_3210 = _mm_add_epi32( TMP2_3210, _mm_shufflelo_epi16(TMP2_3210, 0x0E ) ); - - tmp1 += _mm_cvtsi128_si32( TMP1_3210 ); - tmp2 += _mm_cvtsi128_si32( TMP2_3210 ); - - for( ; k < n; k++ ) { - C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ - C_last_row[ k ] = silk_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ - Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); /* Q17 */ - tmp1 = silk_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */ - tmp2 = silk_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17 */ - } - - tmp1 = -tmp1; /* Q17 */ - tmp2 = -tmp2; /* Q17 */ - - { - __m128i xmm_tmp1, xmm_tmp2; - __m128i xmm_x_ptr_n_k_x2x0, xmm_x_ptr_n_k_x3x1; - __m128i xmm_x_ptr_sub_x2x0, xmm_x_ptr_sub_x3x1; - - xmm_tmp1 = _mm_set1_epi32( tmp1 ); - xmm_tmp2 = _mm_set1_epi32( tmp2 ); - - for( k = 0; k <= n - 3; k += 4 ) { - xmm_x_ptr_n_k_x2x0 = OP_CVTEPI16_EPI32_M64( &x_ptr[ n - k - 3 ] ); - xmm_x_ptr_sub_x2x0 = OP_CVTEPI16_EPI32_M64( &x_ptr[ subfr_length - n + k - 1 ] ); - - xmm_x_ptr_n_k_x2x0 = _mm_shuffle_epi32( xmm_x_ptr_n_k_x2x0, _MM_SHUFFLE( 0, 1, 2, 3 ) ); - - xmm_x_ptr_n_k_x2x0 = _mm_slli_epi32( xmm_x_ptr_n_k_x2x0, -rshifts - 1 ); - xmm_x_ptr_sub_x2x0 = _mm_slli_epi32( xmm_x_ptr_sub_x2x0, -rshifts - 1 ); - - /* equal shift right 4 bytes, xmm_x_ptr_n_k_x3x1 = _mm_srli_si128(xmm_x_ptr_n_k_x2x0, 4)*/ - xmm_x_ptr_n_k_x3x1 = _mm_shuffle_epi32( xmm_x_ptr_n_k_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) ); - xmm_x_ptr_sub_x3x1 = _mm_shuffle_epi32( xmm_x_ptr_sub_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) ); - - xmm_x_ptr_n_k_x2x0 = _mm_mul_epi32( xmm_x_ptr_n_k_x2x0, xmm_tmp1 ); - xmm_x_ptr_n_k_x3x1 = _mm_mul_epi32( xmm_x_ptr_n_k_x3x1, xmm_tmp1 ); - xmm_x_ptr_sub_x2x0 = _mm_mul_epi32( xmm_x_ptr_sub_x2x0, xmm_tmp2 ); - xmm_x_ptr_sub_x3x1 = _mm_mul_epi32( xmm_x_ptr_sub_x3x1, xmm_tmp2 ); - - xmm_x_ptr_n_k_x2x0 = _mm_srli_epi64( xmm_x_ptr_n_k_x2x0, 16 ); - xmm_x_ptr_n_k_x3x1 = _mm_slli_epi64( xmm_x_ptr_n_k_x3x1, 16 ); - xmm_x_ptr_sub_x2x0 = _mm_srli_epi64( xmm_x_ptr_sub_x2x0, 16 ); - xmm_x_ptr_sub_x3x1 = _mm_slli_epi64( xmm_x_ptr_sub_x3x1, 16 ); - - xmm_x_ptr_n_k_x2x0 = _mm_blend_epi16( xmm_x_ptr_n_k_x2x0, xmm_x_ptr_n_k_x3x1, 0xCC ); - xmm_x_ptr_sub_x2x0 = _mm_blend_epi16( xmm_x_ptr_sub_x2x0, xmm_x_ptr_sub_x3x1, 0xCC ); - - X1_3210 = _mm_loadu_si128( (__m128i *)&CAf[ k ] ); - PTR_3210 = _mm_loadu_si128( (__m128i *)&CAb[ k ] ); - - X1_3210 = _mm_add_epi32( X1_3210, xmm_x_ptr_n_k_x2x0 ); - PTR_3210 = _mm_add_epi32( PTR_3210, xmm_x_ptr_sub_x2x0 ); - - _mm_storeu_si128( (__m128i *)&CAf[ k ], X1_3210 ); - _mm_storeu_si128( (__m128i *)&CAb[ k ], PTR_3210 ); - } - - for( ; k <= n; k++ ) { - CAf[ k ] = silk_SMLAWW( CAf[ k ], tmp1, - silk_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) ); /* Q( -rshift ) */ - CAb[ k ] = silk_SMLAWW( CAb[ k ], tmp2, - silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) ); /* Q( -rshift ) */ - } - } - } - } - - /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ - tmp1 = C_first_row[ n ]; /* Q( -rshifts ) */ - tmp2 = C_last_row[ n ]; /* Q( -rshifts ) */ - num = 0; /* Q( -rshifts ) */ - nrg = silk_ADD32( CAb[ 0 ], CAf[ 0 ] ); /* Q( 1-rshifts ) */ - for( k = 0; k < n; k++ ) { - Atmp_QA = Af_QA[ k ]; - lz = silk_CLZ32( silk_abs( Atmp_QA ) ) - 1; - lz = silk_min( 32 - QA, lz ); - Atmp1 = silk_LSHIFT32( Atmp_QA, lz ); /* Q( QA + lz ) */ - - tmp1 = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( C_last_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ - tmp2 = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ - num = silk_ADD_LSHIFT32( num, silk_SMMUL( CAb[ n - k ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ - nrg = silk_ADD_LSHIFT32( nrg, silk_SMMUL( silk_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ), - Atmp1 ), 32 - QA - lz ); /* Q( 1-rshifts ) */ - } - CAf[ n + 1 ] = tmp1; /* Q( -rshifts ) */ - CAb[ n + 1 ] = tmp2; /* Q( -rshifts ) */ - num = silk_ADD32( num, tmp2 ); /* Q( -rshifts ) */ - num = silk_LSHIFT32( -num, 1 ); /* Q( 1-rshifts ) */ - - /* Calculate the next order reflection (parcor) coefficient */ - if( silk_abs( num ) < nrg ) { - rc_Q31 = silk_DIV32_varQ( num, nrg, 31 ); - } else { - rc_Q31 = ( num > 0 ) ? silk_int32_MAX : silk_int32_MIN; - } - - /* Update inverse prediction gain */ - tmp1 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); - tmp1 = silk_LSHIFT( silk_SMMUL( invGain_Q30, tmp1 ), 2 ); - if( tmp1 <= minInvGain_Q30 ) { - /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */ - tmp2 = ( (opus_int32)1 << 30 ) - silk_DIV32_varQ( minInvGain_Q30, invGain_Q30, 30 ); /* Q30 */ - rc_Q31 = silk_SQRT_APPROX( tmp2 ); /* Q15 */ - /* Newton-Raphson iteration */ - rc_Q31 = silk_RSHIFT32( rc_Q31 + silk_DIV32( tmp2, rc_Q31 ), 1 ); /* Q15 */ - rc_Q31 = silk_LSHIFT32( rc_Q31, 16 ); /* Q31 */ - if( num < 0 ) { - /* Ensure adjusted reflection coefficients has the original sign */ - rc_Q31 = -rc_Q31; - } - invGain_Q30 = minInvGain_Q30; - reached_max_gain = 1; - } else { - invGain_Q30 = tmp1; - } - - /* Update the AR coefficients */ - for( k = 0; k < (n + 1) >> 1; k++ ) { - tmp1 = Af_QA[ k ]; /* QA */ - tmp2 = Af_QA[ n - k - 1 ]; /* QA */ - Af_QA[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* QA */ - Af_QA[ n - k - 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* QA */ - } - Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA ); /* QA */ - - if( reached_max_gain ) { - /* Reached max prediction gain; set remaining coefficients to zero and exit loop */ - for( k = n + 1; k < D; k++ ) { - Af_QA[ k ] = 0; - } - break; - } - - /* Update C * Af and C * Ab */ - for( k = 0; k <= n + 1; k++ ) { - tmp1 = CAf[ k ]; /* Q( -rshifts ) */ - tmp2 = CAb[ n - k + 1 ]; /* Q( -rshifts ) */ - CAf[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* Q( -rshifts ) */ - CAb[ n - k + 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* Q( -rshifts ) */ - } - } - - if( reached_max_gain ) { - for( k = 0; k < D; k++ ) { - /* Scale coefficients */ - A_Q16[ k ] = -silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); - } - /* Subtract energy of preceding samples from C0 */ - if( rshifts > 0 ) { - for( s = 0; s < nb_subfr; s++ ) { - x_ptr = x + s * subfr_length; - C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr, D, arch ), rshifts ); - } - } else { - for( s = 0; s < nb_subfr; s++ ) { - x_ptr = x + s * subfr_length; - C0 -= silk_LSHIFT32( silk_inner_prod_aligned( x_ptr, x_ptr, D, arch ), -rshifts ); - } - } - /* Approximate residual energy */ - *res_nrg = silk_LSHIFT( silk_SMMUL( invGain_Q30, C0 ), 2 ); - *res_nrg_Q = -rshifts; - } else { - /* Return residual energy */ - nrg = CAf[ 0 ]; /* Q( -rshifts ) */ - tmp1 = (opus_int32)1 << 16; /* Q16 */ - for( k = 0; k < D; k++ ) { - Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); /* Q16 */ - nrg = silk_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); /* Q( -rshifts ) */ - tmp1 = silk_SMLAWW( tmp1, Atmp1, Atmp1 ); /* Q16 */ - A_Q16[ k ] = -Atmp1; - } - *res_nrg = silk_SMLAWW( nrg, silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ), -tmp1 );/* Q( -rshifts ) */ - *res_nrg_Q = -rshifts; - } -} diff --git a/drivers/opus/silk/fixed/x86/prefilter_FIX_sse.c b/drivers/opus/silk/fixed/x86/prefilter_FIX_sse.c deleted file mode 100644 index febb105645..0000000000 --- a/drivers/opus/silk/fixed/x86/prefilter_FIX_sse.c +++ /dev/null @@ -1,157 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include <xmmintrin.h> -#include <emmintrin.h> -#include <smmintrin.h> -#include "opus/silk/main.h" -#include "opus/celt/x86/x86cpu.h" - -void silk_warped_LPC_analysis_filter_FIX_sse4_1( - opus_int32 state[], /* I/O State [order + 1] */ - opus_int32 res_Q2[], /* O Residual signal [length] */ - const opus_int16 coef_Q13[], /* I Coefficients [order] */ - const opus_int16 input[], /* I Input signal [length] */ - const opus_int16 lambda_Q16, /* I Warping factor */ - const opus_int length, /* I Length of input signal */ - const opus_int order /* I Filter order (even) */ -) -{ - opus_int n, i; - opus_int32 acc_Q11, tmp1, tmp2; - - /* Order must be even */ - silk_assert( ( order & 1 ) == 0 ); - - if (order == 10) - { - if (0 == lambda_Q16) - { - __m128i coef_Q13_3210, coef_Q13_7654; - __m128i coef_Q13_0123, coef_Q13_4567; - __m128i state_0123, state_4567; - __m128i xmm_product1, xmm_product2; - __m128i xmm_tempa, xmm_tempb; - - register opus_int32 sum; - register opus_int32 state_8, state_9, state_a; - register opus_int64 coef_Q13_8, coef_Q13_9; - - silk_assert( length > 0 ); - - coef_Q13_3210 = OP_CVTEPI16_EPI32_M64( &coef_Q13[ 0 ] ); - coef_Q13_7654 = OP_CVTEPI16_EPI32_M64( &coef_Q13[ 4 ] ); - - coef_Q13_0123 = _mm_shuffle_epi32( coef_Q13_3210, _MM_SHUFFLE( 0, 1, 2, 3 ) ); - coef_Q13_4567 = _mm_shuffle_epi32( coef_Q13_7654, _MM_SHUFFLE( 0, 1, 2, 3 ) ); - - coef_Q13_8 = (opus_int64) coef_Q13[ 8 ]; - coef_Q13_9 = (opus_int64) coef_Q13[ 9 ]; - - state_0123 = _mm_loadu_si128( (__m128i *)(&state[ 0 ] ) ); - state_4567 = _mm_loadu_si128( (__m128i *)(&state[ 4 ] ) ); - - state_0123 = _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) ); - state_4567 = _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) ); - - state_8 = state[ 8 ]; - state_9 = state[ 9 ]; - state_a = 0; - - for( n = 0; n < length; n++ ) - { - xmm_product1 = _mm_mul_epi32( coef_Q13_0123, state_0123 ); /* 64-bit multiply, only 2 pairs */ - xmm_product2 = _mm_mul_epi32( coef_Q13_4567, state_4567 ); - - xmm_tempa = _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) ); - xmm_tempb = _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) ); - - xmm_product1 = _mm_srli_epi64( xmm_product1, 16 ); /* >> 16, zero extending works */ - xmm_product2 = _mm_srli_epi64( xmm_product2, 16 ); - - xmm_tempa = _mm_mul_epi32( coef_Q13_3210, xmm_tempa ); - xmm_tempb = _mm_mul_epi32( coef_Q13_7654, xmm_tempb ); - - xmm_tempa = _mm_srli_epi64( xmm_tempa, 16 ); - xmm_tempb = _mm_srli_epi64( xmm_tempb, 16 ); - - xmm_tempa = _mm_add_epi32( xmm_tempa, xmm_product1 ); - xmm_tempb = _mm_add_epi32( xmm_tempb, xmm_product2 ); - xmm_tempa = _mm_add_epi32( xmm_tempa, xmm_tempb ); - - sum = (coef_Q13_8 * state_8) >> 16; - sum += (coef_Q13_9 * state_9) >> 16; - - xmm_tempa = _mm_add_epi32( xmm_tempa, _mm_shuffle_epi32( xmm_tempa, _MM_SHUFFLE( 0, 0, 0, 2 ) ) ); - sum += _mm_cvtsi128_si32( xmm_tempa); - res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( ( 5 + sum ), 9); - - /* move right */ - state_a = state_9; - state_9 = state_8; - state_8 = _mm_cvtsi128_si32( state_4567 ); - state_4567 = _mm_alignr_epi8( state_0123, state_4567, 4 ); - - state_0123 = _mm_alignr_epi8( _mm_cvtsi32_si128( silk_LSHIFT( input[ n ], 14 ) ), state_0123, 4 ); - } - - _mm_storeu_si128( (__m128i *)( &state[ 0 ] ), _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) ) ); - _mm_storeu_si128( (__m128i *)( &state[ 4 ] ), _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) ) ); - state[ 8 ] = state_8; - state[ 9 ] = state_9; - state[ 10 ] = state_a; - - return; - } - } - - for( n = 0; n < length; n++ ) { - /* Output of lowpass section */ - tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 ); - state[ 0 ] = silk_LSHIFT( input[ n ], 14 ); - /* Output of allpass section */ - tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 ); - state[ 1 ] = tmp2; - acc_Q11 = silk_RSHIFT( order, 1 ); - acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] ); - /* Loop over allpass sections */ - for( i = 2; i < order; i += 2 ) { - /* Output of allpass section */ - tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 ); - state[ i ] = tmp1; - acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] ); - /* Output of allpass section */ - tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 ); - state[ i + 1 ] = tmp2; - acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] ); - } - state[ order ] = tmp1; - acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); - res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 ); - } -} diff --git a/drivers/opus/silk/fixed/x86/vector_ops_FIX_sse.c b/drivers/opus/silk/fixed/x86/vector_ops_FIX_sse.c deleted file mode 100644 index 920d58cebc..0000000000 --- a/drivers/opus/silk/fixed/x86/vector_ops_FIX_sse.c +++ /dev/null @@ -1,85 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include <xmmintrin.h> -#include <emmintrin.h> -#include <smmintrin.h> -#include "opus/silk/main.h" - -#include "opus/silk/SigProc_FIX.h" -#include "opus/celt/pitch.h" - -opus_int64 silk_inner_prod16_aligned_64_sse4_1( - const opus_int16 *inVec1, /* I input vector 1 */ - const opus_int16 *inVec2, /* I input vector 2 */ - const opus_int len /* I vector lengths */ -) -{ - opus_int i, dataSize8; - opus_int64 sum; - - __m128i xmm_tempa; - __m128i inVec1_76543210, acc1; - __m128i inVec2_76543210, acc2; - - sum = 0; - dataSize8 = len & ~7; - - acc1 = _mm_setzero_si128(); - acc2 = _mm_setzero_si128(); - - for( i = 0; i < dataSize8; i += 8 ) { - inVec1_76543210 = _mm_loadu_si128( (__m128i *)(&inVec1[i + 0] ) ); - inVec2_76543210 = _mm_loadu_si128( (__m128i *)(&inVec2[i + 0] ) ); - - /* only when all 4 operands are -32768 (0x8000), this results in wrap around */ - inVec1_76543210 = _mm_madd_epi16( inVec1_76543210, inVec2_76543210 ); - - xmm_tempa = _mm_cvtepi32_epi64( inVec1_76543210 ); - /* equal shift right 8 bytes */ - inVec1_76543210 = _mm_shuffle_epi32( inVec1_76543210, _MM_SHUFFLE( 0, 0, 3, 2 ) ); - inVec1_76543210 = _mm_cvtepi32_epi64( inVec1_76543210 ); - - acc1 = _mm_add_epi64( acc1, xmm_tempa ); - acc2 = _mm_add_epi64( acc2, inVec1_76543210 ); - } - - acc1 = _mm_add_epi64( acc1, acc2 ); - - /* equal shift right 8 bytes */ - acc2 = _mm_shuffle_epi32( acc1, _MM_SHUFFLE( 0, 0, 3, 2 ) ); - acc1 = _mm_add_epi64( acc1, acc2 ); - - _mm_storel_epi64( (__m128i *)&sum, acc1 ); - - for( ; i < len; i++ ) { - sum = silk_SMLABB( sum, inVec1[ i ], inVec2[ i ] ); - } - - return sum; -} diff --git a/drivers/opus/silk/float/LPC_analysis_filter_FLP.c b/drivers/opus/silk/float/LPC_analysis_filter_FLP.c deleted file mode 100644 index 344e52ade2..0000000000 --- a/drivers/opus/silk/float/LPC_analysis_filter_FLP.c +++ /dev/null @@ -1,246 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include <stdlib.h> -#include "opus/silk/float/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 */ -) -{ - silk_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: - silk_assert( 0 ); - break; - } - - /* Set first Order output samples to zero */ - silk_memset( r_LPC, 0, Order * sizeof( silk_float ) ); -} - diff --git a/drivers/opus/silk/float/LPC_inv_pred_gain_FLP.c b/drivers/opus/silk/float/LPC_inv_pred_gain_FLP.c deleted file mode 100644 index f99a427623..0000000000 --- a/drivers/opus/silk/float/LPC_inv_pred_gain_FLP.c +++ /dev/null @@ -1,73 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/float/SigProc_FLP.h" - -#define RC_THRESHOLD 0.9999f - -/* 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; - silk_float Atmp[ 2 ][ SILK_MAX_ORDER_LPC ]; - silk_float *Aold, *Anew; - - Anew = Atmp[ order & 1 ]; - silk_memcpy( Anew, A, order * sizeof(silk_float) ); - - invGain = 1.0; - for( k = order - 1; k > 0; k-- ) { - rc = -Anew[ k ]; - if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) { - return 0.0f; - } - rc_mult1 = 1.0f - rc * rc; - rc_mult2 = 1.0f / rc_mult1; - invGain *= rc_mult1; - /* swap pointers */ - Aold = Anew; - Anew = Atmp[ k & 1 ]; - for( n = 0; n < k; n++ ) { - Anew[ n ] = (silk_float)( ( Aold[ n ] - Aold[ k - n - 1 ] * rc ) * rc_mult2 ); - } - } - rc = -Anew[ 0 ]; - if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) { - return 0.0f; - } - rc_mult1 = 1.0f - rc * rc; - invGain *= rc_mult1; - return (silk_float)invGain; -} diff --git a/drivers/opus/silk/float/LTP_analysis_filter_FLP.c b/drivers/opus/silk/float/LTP_analysis_filter_FLP.c deleted file mode 100644 index 853040d160..0000000000 --- a/drivers/opus/silk/float/LTP_analysis_filter_FLP.c +++ /dev/null @@ -1,72 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/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/drivers/opus/silk/float/LTP_scale_ctrl_FLP.c b/drivers/opus/silk/float/LTP_scale_ctrl_FLP.c deleted file mode 100644 index 4219c14c5b..0000000000 --- a/drivers/opus/silk/float/LTP_scale_ctrl_FLP.c +++ /dev/null @@ -1,49 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/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; - psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( round_loss * psEncCtrl->LTPredCodGain * 0.1f, 0.0f, 2.0f ); - } 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/drivers/opus/silk/float/SigProc_FLP.h b/drivers/opus/silk/float/SigProc_FLP.h deleted file mode 100644 index 9b14f24f21..0000000000 --- a/drivers/opus/silk/float/SigProc_FLP.h +++ /dev/null @@ -1,204 +0,0 @@ -/*********************************************************************** -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 "opus/silk/SigProc_FIX.h" -#include "opus/celt/float_cast.h" -#include <math.h> - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************************************************/ -/* 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 */ -); - -/* Solve the normal equations using the Levinson-Durbin recursion */ -silk_float silk_levinsondurbin_FLP( /* O prediction error energy */ - silk_float A[], /* O prediction coefficients [order] */ - const silk_float corr[], /* I input auto-correlations [order + 1] */ - const opus_int 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 */ -); - -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 */ -); - -/* 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( - const silk_float *data1, - const silk_float *data2, - opus_int dataSize -); - -/* 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 ) ); -} - -#ifdef __cplusplus -} -#endif - -#endif /* SILK_SIGPROC_FLP_H */ diff --git a/drivers/opus/silk/float/apply_sine_window_FLP.c b/drivers/opus/silk/float/apply_sine_window_FLP.c deleted file mode 100644 index 0d9c894cd8..0000000000 --- a/drivers/opus/silk/float/apply_sine_window_FLP.c +++ /dev/null @@ -1,78 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/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; - - silk_assert( win_type == 1 || win_type == 2 ); - - /* Length must be multiple of 4 */ - silk_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/drivers/opus/silk/float/autocorrelation_FLP.c b/drivers/opus/silk/float/autocorrelation_FLP.c deleted file mode 100644 index 0b78b0230d..0000000000 --- a/drivers/opus/silk/float/autocorrelation_FLP.c +++ /dev/null @@ -1,49 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/typedef.h" -#include "opus/silk/float/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 */ -) -{ - 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 ); - } -} diff --git a/drivers/opus/silk/float/burg_modified_FLP.c b/drivers/opus/silk/float/burg_modified_FLP.c deleted file mode 100644 index 567990b850..0000000000 --- a/drivers/opus/silk/float/burg_modified_FLP.c +++ /dev/null @@ -1,183 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/SigProc_FLP.h" -#include "opus/silk/tuning_parameters.h" -#include "opus/silk/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 */ -) -{ - 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 ]; - - silk_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 ); - } - } - 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/drivers/opus/silk/float/bwexpander_FLP.c b/drivers/opus/silk/float/bwexpander_FLP.c deleted file mode 100644 index c47bfa9433..0000000000 --- a/drivers/opus/silk/float/bwexpander_FLP.c +++ /dev/null @@ -1,46 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/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/drivers/opus/silk/float/corrMatrix_FLP.c b/drivers/opus/silk/float/corrMatrix_FLP.c deleted file mode 100644 index e34b42b541..0000000000 --- a/drivers/opus/silk/float/corrMatrix_FLP.c +++ /dev/null @@ -1,90 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -/********************************************************************** - * Correlation matrix computations for LS estimate. - **********************************************************************/ - -#include "opus/silk/float/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] */ -) -{ - 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 ); - 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] */ -) -{ - 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 ); - 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/drivers/opus/silk/float/encode_frame_FLP.c b/drivers/opus/silk/float/encode_frame_FLP.c deleted file mode 100644 index 4e46a52ee8..0000000000 --- a/drivers/opus/silk/float/encode_frame_FLP.c +++ /dev/null @@ -1,369 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/main_FLP.h" -#include "opus/silk/tuning_parameters.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 */ -) -{ - /****************************/ - /* Voice Activity Detection */ - /****************************/ - silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch ); - - /**************************************************/ - /* Convert speech activity into VAD and DTX flags */ - /**************************************************/ - if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) { - 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 xfw[ MAX_FRAME_LENGTH ]; - silk_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ]; - ec_enc sRangeEnc_copy, sRangeEnc_copy2; - silk_nsq_state sNSQ_copy, sNSQ_copy2; - 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_uint8 ec_buf_copy[ 1275 ]; - - /* 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 ) { - /*****************************************/ - /* 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, x_frame, condCoding ); - - /****************************************/ - /* Process gains */ - /****************************************/ - silk_process_gains_FLP( psEnc, &sEncCtrl, condCoding ); - - /*****************************************/ - /* Prefiltering for noise shaper */ - /*****************************************/ - silk_prefilter_FLP( psEnc, &sEncCtrl, xfw, x_frame ); - - /****************************************/ - /* Low Bitrate Redundant Encoding */ - /****************************************/ - silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, 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, &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; - 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, 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, xfw ); - - /****************************************/ - /* 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( 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 ) ); - silk_assert( sRangeEnc_copy2.offs <= 1275 ); - silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs ); - silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, 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 *= 1.5f; - found_upper = 0; - gainsID_upper = -1; - } else { - found_upper = 1; - nBits_upper = nBits; - gainMult_upper = gainMult_Q8; - gainsID_upper = gainsID; - } - } else if( nBits < maxBits - 5 ) { - 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 ) ); - silk_assert( psRangeEnc->offs <= 1275 ); - silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs ); - silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); - LastGainIndex_copy2 = psEnc->sShape.LastGainIndex; - } - } else { - /* Within 5 bits of budget: close enough */ - break; - } - - if( ( found_lower & found_upper ) == 0 ) { - /* Adjust gain according to high-rate rate/distortion curve */ - opus_int32 gain_factor_Q16; - gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) ); - gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) ); - if( nBits > maxBits ) { - gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) ); - } - gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 ); - } else { - /* Adjust gain by interpolating */ - gainMult_Q8 = gainMult_lower + ( ( gainMult_upper - gainMult_lower ) * ( maxBits - nBits_lower ) ) / ( nBits_upper - nBits_lower ); - /* New gain multplier 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++ ) { - pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 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; - 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 ); - - 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 ]; - silk_nsq_state sNSQ_LBRR; - - /*******************************************/ - /* Control use of inband LBRR */ - /*******************************************/ - if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { - psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1; - - /* Copy noise shaping quantizer state and quantization indices from regular encoding */ - silk_memcpy( &sNSQ_LBRR, &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, - psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], xfw ); - - /* Restore original gains */ - silk_memcpy( psEncCtrl->Gains, TempGains, psEnc->sCmn.nb_subfr * sizeof( silk_float ) ); - } -} diff --git a/drivers/opus/silk/float/energy_FLP.c b/drivers/opus/silk/float/energy_FLP.c deleted file mode 100644 index 443f52bb16..0000000000 --- a/drivers/opus/silk/float/energy_FLP.c +++ /dev/null @@ -1,57 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/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, dataSize4; - double result; - - /* 4x unrolled loop */ - result = 0.0; - dataSize4 = dataSize & 0xFFFC; - for( i = 0; i < dataSize4; 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/drivers/opus/silk/float/find_LPC_FLP.c b/drivers/opus/silk/float/find_LPC_FLP.c deleted file mode 100644 index 162a490d1d..0000000000 --- a/drivers/opus/silk/float/find_LPC_FLP.c +++ /dev/null @@ -1,101 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/define.h" -#include "opus/silk/float/main_FLP.h" -#include "opus/silk/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 */ -) -{ - 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 ); - - 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 ); - - /* 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 ); - - /* 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 ); - } - - silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || - ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) ); -} diff --git a/drivers/opus/silk/float/find_LTP_FLP.c b/drivers/opus/silk/float/find_LTP_FLP.c deleted file mode 100644 index 9c03eeb6a7..0000000000 --- a/drivers/opus/silk/float/find_LTP_FLP.c +++ /dev/null @@ -1,129 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/main_FLP.h" -#include "opus/silk/tuning_parameters.h" - -void silk_find_LTP_FLP( - silk_float b[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ - silk_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ - silk_float *LTPredCodGain, /* O LTP coding gain */ - const silk_float r_lpc[], /* I LPC residual */ - const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ - const silk_float Wght[ MAX_NB_SUBFR ], /* I Weights */ - const opus_int subfr_length, /* I Subframe length */ - const opus_int nb_subfr, /* I number of subframes */ - const opus_int mem_offset /* I Number of samples in LTP memory */ -) -{ - opus_int i, k; - silk_float *b_ptr, temp, *WLTP_ptr; - silk_float LPC_res_nrg, LPC_LTP_res_nrg; - silk_float d[ MAX_NB_SUBFR ], m, g, delta_b[ LTP_ORDER ]; - silk_float w[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], regu; - silk_float Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ]; - const silk_float *r_ptr, *lag_ptr; - - b_ptr = b; - WLTP_ptr = WLTP; - r_ptr = &r_lpc[ mem_offset ]; - 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, WLTP_ptr ); - silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr ); - - rr[ k ] = ( silk_float )silk_energy_FLP( r_ptr, subfr_length ); - regu = 1.0f + rr[ k ] + - matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ) + - matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ); - regu *= LTP_DAMPING / 3; - silk_regularize_correlations_FLP( WLTP_ptr, &rr[ k ], regu, LTP_ORDER ); - silk_solve_LDL_FLP( WLTP_ptr, LTP_ORDER, Rr, b_ptr ); - - /* Calculate residual energy */ - nrg[ k ] = silk_residual_energy_covar_FLP( b_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER ); - - temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); - silk_scale_vector_FLP( WLTP_ptr, temp, LTP_ORDER * LTP_ORDER ); - w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER / 2, LTP_ORDER / 2, LTP_ORDER ); - - r_ptr += subfr_length; - b_ptr += LTP_ORDER; - WLTP_ptr += LTP_ORDER * LTP_ORDER; - } - - /* Compute LTP coding gain */ - if( LTPredCodGain != NULL ) { - LPC_LTP_res_nrg = 1e-6f; - LPC_res_nrg = 0.0f; - for( k = 0; k < nb_subfr; k++ ) { - LPC_res_nrg += rr[ k ] * Wght[ k ]; - LPC_LTP_res_nrg += nrg[ k ] * Wght[ k ]; - } - - silk_assert( LPC_LTP_res_nrg > 0 ); - *LTPredCodGain = 3.0f * silk_log2( LPC_res_nrg / LPC_LTP_res_nrg ); - } - - /* Smoothing */ - /* d = sum( B, 1 ); */ - b_ptr = b; - for( k = 0; k < nb_subfr; k++ ) { - d[ k ] = 0; - for( i = 0; i < LTP_ORDER; i++ ) { - d[ k ] += b_ptr[ i ]; - } - b_ptr += LTP_ORDER; - } - /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */ - temp = 1e-3f; - for( k = 0; k < nb_subfr; k++ ) { - temp += w[ k ]; - } - m = 0; - for( k = 0; k < nb_subfr; k++ ) { - m += d[ k ] * w[ k ]; - } - m = m / temp; - - b_ptr = b; - for( k = 0; k < nb_subfr; k++ ) { - g = LTP_SMOOTHING / ( LTP_SMOOTHING + w[ k ] ) * ( m - d[ k ] ); - temp = 0; - for( i = 0; i < LTP_ORDER; i++ ) { - delta_b[ i ] = silk_max_float( b_ptr[ i ], 0.1f ); - temp += delta_b[ i ]; - } - temp = g / temp; - for( i = 0; i < LTP_ORDER; i++ ) { - b_ptr[ i ] = b_ptr[ i ] + delta_b[ i ] * temp; - } - b_ptr += LTP_ORDER; - } -} diff --git a/drivers/opus/silk/float/find_pitch_lags_FLP.c b/drivers/opus/silk/float/find_pitch_lags_FLP.c deleted file mode 100644 index bb7ef8ec2e..0000000000 --- a/drivers/opus/silk/float/find_pitch_lags_FLP.c +++ /dev/null @@ -1,129 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include <stdlib.h> -#include "opus/silk/float/main_FLP.h" -#include "opus/silk/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 */ - silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length ); - - x_buf = x - psEnc->sCmn.ltp_mem_length; - - /******************************************/ - /* Estimate LPC AR coeficients */ - /******************************************/ - - /* 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 ); - - /* 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/drivers/opus/silk/float/find_pred_coefs_FLP.c b/drivers/opus/silk/float/find_pred_coefs_FLP.c deleted file mode 100644 index c0496ff1b5..0000000000 --- a/drivers/opus/silk/float/find_pred_coefs_FLP.c +++ /dev/null @@ -1,115 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/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 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ]; - silk_float invGains[ MAX_NB_SUBFR ], Wght[ MAX_NB_SUBFR ]; - opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; - 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 ]; - Wght[ i ] = invGains[ i ] * invGains[ i ]; - } - - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - /**********/ - /* VOICED */ - /**********/ - silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 ); - - /* LTP analysis */ - silk_find_LTP_FLP( psEncCtrl->LTPCoef, WLTP, &psEncCtrl->LTPredCodGain, res_pitch, - psEncCtrl->pitchL, Wght, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length ); - - /* 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, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, 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 ); - - /* 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/drivers/opus/silk/float/inner_product_FLP.c b/drivers/opus/silk/float/inner_product_FLP.c deleted file mode 100644 index 0586c4d7fb..0000000000 --- a/drivers/opus/silk/float/inner_product_FLP.c +++ /dev/null @@ -1,57 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/SigProc_FLP.h" - -/* inner product of two silk_float arrays, with result as double */ -double silk_inner_product_FLP( - const silk_float *data1, - const silk_float *data2, - opus_int dataSize -) -{ - opus_int i, dataSize4; - double result; - - /* 4x unrolled loop */ - result = 0.0; - dataSize4 = dataSize & 0xFFFC; - for( i = 0; i < dataSize4; 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/drivers/opus/silk/float/k2a_FLP.c b/drivers/opus/silk/float/k2a_FLP.c deleted file mode 100644 index 26ba94e610..0000000000 --- a/drivers/opus/silk/float/k2a_FLP.c +++ /dev/null @@ -1,50 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/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 Atmp[ SILK_MAX_ORDER_LPC ]; - - for( k = 0; k < order; k++ ) { - for( n = 0; n < k; n++ ) { - Atmp[ n ] = A[ n ]; - } - for( n = 0; n < k; n++ ) { - A[ n ] += Atmp[ k - n - 1 ] * rc[ k ]; - } - A[ k ] = -rc[ k ]; - } -} diff --git a/drivers/opus/silk/float/levinsondurbin_FLP.c b/drivers/opus/silk/float/levinsondurbin_FLP.c deleted file mode 100644 index 7e3c9d6531..0000000000 --- a/drivers/opus/silk/float/levinsondurbin_FLP.c +++ /dev/null @@ -1,78 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/SigProc_FLP.h" - -/* Solve the normal equations using the Levinson-Durbin recursion */ -silk_float silk_levinsondurbin_FLP( /* O prediction error energy */ - silk_float A[], /* O prediction coefficients [order] */ - const silk_float corr[], /* I input auto-correlations [order + 1] */ - const opus_int order /* I prediction order */ -) -{ - opus_int i, mHalf, m; - silk_float min_nrg, nrg, t, km, Atmp1, Atmp2; - - min_nrg = 1e-12f * corr[ 0 ] + 1e-9f; - nrg = corr[ 0 ]; - nrg = silk_max_float(min_nrg, nrg); - A[ 0 ] = corr[ 1 ] / nrg; - nrg -= A[ 0 ] * corr[ 1 ]; - nrg = silk_max_float(min_nrg, nrg); - - for( m = 1; m < order; m++ ) - { - t = corr[ m + 1 ]; - for( i = 0; i < m; i++ ) { - t -= A[ i ] * corr[ m - i ]; - } - - /* reflection coefficient */ - km = t / nrg; - - /* residual energy */ - nrg -= km * t; - nrg = silk_max_float(min_nrg, nrg); - - mHalf = m >> 1; - for( i = 0; i < mHalf; i++ ) { - Atmp1 = A[ i ]; - Atmp2 = A[ m - i - 1 ]; - A[ m - i - 1 ] -= km * Atmp1; - A[ i ] -= km * Atmp2; - } - if( m & 1 ) { - A[ mHalf ] -= km * A[ mHalf ]; - } - A[ m ] = km; - } - - /* return the residual energy */ - return nrg; -} - diff --git a/drivers/opus/silk/float/main_FLP.h b/drivers/opus/silk/float/main_FLP.h deleted file mode 100644 index 8f35177549..0000000000 --- a/drivers/opus/silk/float/main_FLP.h +++ /dev/null @@ -1,313 +0,0 @@ -/*********************************************************************** -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 "opus/silk/float/SigProc_FLP.h" -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/float/structs_FLP.h" -#include "opus/silk/main.h" -#include "opus/silk/define.h" -#include "opus/silk/debug.h" -#include "opus/celt/entenc.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -#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 */ -); - -/* 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_int32 TargetRate_bps, /* I Target max bitrate (bps) */ - 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 -); - -/****************/ -/* Prefiltering */ -/****************/ -void silk_prefilter_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - const silk_encoder_control_FLP *psEncCtrl, /* I Encoder control FLP */ - silk_float xw[], /* O Weighted signal */ - const silk_float x[] /* I Speech signal */ -); - -/**************************/ -/* 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) */ -); - -/* LTP analysis */ -void silk_find_LTP_FLP( - silk_float b[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ - silk_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ - silk_float *LTPredCodGain, /* O LTP coding gain */ - const silk_float r_lpc[], /* I LPC residual */ - const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ - const silk_float Wght[ MAX_NB_SUBFR ], /* I Weights */ - const opus_int subfr_length, /* I Subframe length */ - const opus_int nb_subfr, /* I number of subframes */ - const opus_int mem_offset /* I Number of samples in LTP memory */ -); - -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 ], /* I/O (Un-)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 */ - const silk_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */ - const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */ - const opus_int lowComplexity, /* I Flag for low complexity */ - 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] */ -); - -/* 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] */ -); - -/* 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 */ -); - -/* Function to solve linear equation Ax = b, where A is an MxM symmetric matrix */ -void silk_solve_LDL_FLP( - silk_float *A, /* I/O Symmetric square matrix, out: reg. */ - const opus_int M, /* I Size of matrix */ - const silk_float *b, /* I Pointer to b vector */ - silk_float *x /* O Pointer to x solution vector */ -); - -/* 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 */ -); - -/* 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 */ -); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/opus/silk/float/noise_shape_analysis_FLP.c b/drivers/opus/silk/float/noise_shape_analysis_FLP.c deleted file mode 100644 index cbb8ba4470..0000000000 --- a/drivers/opus/silk/float/noise_shape_analysis_FLP.c +++ /dev/null @@ -1,362 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/main_FLP.h" -#include "opus/silk/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_syn, - silk_float *coefs_ana, - silk_float lambda, - silk_float limit, - opus_int order -) { - opus_int i, iter, ind = 0; - silk_float tmp, maxabs, chirp, gain_syn, gain_ana; - - /* Convert to monic coefficients */ - for( i = order - 1; i > 0; i-- ) { - coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ]; - coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ]; - } - gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] ); - gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] ); - for( i = 0; i < order; i++ ) { - coefs_syn[ i ] *= gain_syn; - coefs_ana[ i ] *= gain_ana; - } - - /* Limit */ - for( iter = 0; iter < 10; iter++ ) { - /* Find maximum absolute value */ - maxabs = -1.0f; - for( i = 0; i < order; i++ ) { - tmp = silk_max( silk_abs_float( coefs_syn[ i ] ), silk_abs_float( coefs_ana[ 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_syn[ i - 1 ] += lambda * coefs_syn[ i ]; - coefs_ana[ i - 1 ] += lambda * coefs_ana[ i ]; - } - gain_syn = 1.0f / gain_syn; - gain_ana = 1.0f / gain_ana; - for( i = 0; i < order; i++ ) { - coefs_syn[ i ] *= gain_syn; - coefs_ana[ i ] *= gain_ana; - } - - /* Apply bandwidth expansion */ - chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) ); - silk_bwexpander_FLP( coefs_syn, order, chirp ); - silk_bwexpander_FLP( coefs_ana, order, chirp ); - - /* Convert to monic warped coefficients */ - for( i = order - 1; i > 0; i-- ) { - coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ]; - coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ]; - } - gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] ); - gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] ); - for( i = 0; i < order; i++ ) { - coefs_syn[ i ] *= gain_syn; - coefs_ana[ i ] *= gain_ana; - } - } - 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; - silk_float SNR_adj_dB, HarmBoost, HarmShapeGain, Tilt; - silk_float nrg, pre_nrg, log_energy, log_energy_prev, energy_variation; - silk_float delta, BWExp1, BWExp2, gain_mult, gain_add, strength, b, warping; - silk_float x_windowed[ SHAPE_LPC_WIN_MAX ]; - silk_float auto_corr[ 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; - psEncCtrl->sparseness = 0.0f; - } 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; - for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; 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; - } - psEncCtrl->sparseness = silk_sigmoid( 0.4f * ( energy_variation - 5.0f ) ); - - /* Set quantization offset depending on sparseness measure */ - if( psEncCtrl->sparseness > SPARSENESS_THRESHOLD_QNT_OFFSET ) { - psEnc->sCmn.indices.quantOffsetType = 0; - } else { - psEnc->sCmn.indices.quantOffsetType = 1; - } - - /* Increase coding SNR for sparse signals */ - SNR_adj_dB += SPARSE_SNR_INCR_dB * ( psEncCtrl->sparseness - 0.5f ); - } - - /*******************************/ - /* 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 */ - BWExp1 = BWExp2 = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength ); - delta = LOW_RATE_BANDWIDTH_EXPANSION_DELTA * ( 1.0f - 0.75f * psEncCtrl->coding_quality ); - BWExp1 -= delta; - BWExp2 += delta; - /* BWExp1 will be applied after BWExp2, so make it relative */ - BWExp1 /= BWExp2; - - if( psEnc->sCmn.warping_Q16 > 0 ) { - /* 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; - } else { - warping = 0.0f; - } - - /********************************************/ - /* 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 ); - } - - /* Add white noise, as a fraction of energy */ - auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION; - - /* Convert correlations to prediction coefficients, and compute residual energy */ - nrg = silk_levinsondurbin_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], auto_corr, 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->AR2[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder ); - } - - /* Bandwidth expansion for synthesis filter shaping */ - silk_bwexpander_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp2 ); - - /* Compute noise shaping filter coefficients */ - silk_memcpy( - &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], - &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], - psEnc->sCmn.shapingLPCOrder * sizeof( silk_float ) ); - - /* Bandwidth expansion for analysis filter shaping */ - silk_bwexpander_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp1 ); - - /* Ratio of prediction gains, in energy domain */ - pre_nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder ); - nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder ); - psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ); - - /* Convert to monic warped prediction coefficients and limit absolute values */ - warped_true2monic_coefs( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], - warping, 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; - } - - gain_mult = 1.0f + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT; - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - psEncCtrl->GainsPre[ k ] *= gain_mult; - } - - /************************************************/ - /* 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 */ - /****************************/ - /* Control boosting of harmonic frequencies */ - HarmBoost = LOW_RATE_HARMONIC_BOOST * ( 1.0f - psEncCtrl->coding_quality ) * psEnc->LTPCorr; - - /* More harmonic boost for noisy input signals */ - HarmBoost += LOW_INPUT_QUALITY_HARMONIC_BOOST * ( 1.0f - psEncCtrl->input_quality ); - - 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->HarmBoost_smth += SUBFR_SMTH_COEF * ( HarmBoost - psShapeSt->HarmBoost_smth ); - psEncCtrl->HarmBoost[ k ] = psShapeSt->HarmBoost_smth; - 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/drivers/opus/silk/float/pitch_analysis_core_FLP.c b/drivers/opus/silk/float/pitch_analysis_core_FLP.c deleted file mode 100644 index 6a48ae498c..0000000000 --- a/drivers/opus/silk/float/pitch_analysis_core_FLP.c +++ /dev/null @@ -1,627 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -/***************************************************************************** -* Pitch analyser function -******************************************************************************/ -#include "opus/silk/float/SigProc_FLP.h" -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/pitch_est_defines.h" -#include "opus/celt/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 */ - silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 ); - - /* Check for valid complexity setting */ - silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); - silk_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 { - silk_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 ] += 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 */ - silk_assert( target_ptr >= frame_4kHz ); - silk_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 */ - silk_assert( basis_ptr >= frame_4kHz ); - silk_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; - silk_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; - } - } - silk_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 ); - 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; - } - silk_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; - - silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); - silk_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 { - silk_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; - - silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); - silk_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 { - silk_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/drivers/opus/silk/float/prefilter_FLP.c b/drivers/opus/silk/float/prefilter_FLP.c deleted file mode 100644 index 0857888b91..0000000000 --- a/drivers/opus/silk/float/prefilter_FLP.c +++ /dev/null @@ -1,203 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/main_FLP.h" -#include "opus/silk/tuning_parameters.h" - -/* -* Prefilter for finding Quantizer input signal -*/ -static OPUS_INLINE void silk_prefilt_FLP( - silk_prefilter_state_FLP *P, /* I/O state */ - silk_float st_res[], /* I */ - silk_float xw[], /* O */ - silk_float *HarmShapeFIR, /* I */ - silk_float Tilt, /* I */ - silk_float LF_MA_shp, /* I */ - silk_float LF_AR_shp, /* I */ - opus_int lag, /* I */ - opus_int length /* I */ -); - -static void silk_warped_LPC_analysis_filter_FLP( - silk_float state[], /* I/O State [order + 1] */ - silk_float res[], /* O Residual signal [length] */ - const silk_float coef[], /* I Coefficients [order] */ - const silk_float input[], /* I Input signal [length] */ - const silk_float lambda, /* I Warping factor */ - const opus_int length, /* I Length of input signal */ - const opus_int order /* I Filter order (even) */ -) -{ - opus_int n, i; - silk_float acc, tmp1, tmp2; - - /* Order must be even */ - silk_assert( ( order & 1 ) == 0 ); - - for( n = 0; n < length; n++ ) { - /* Output of lowpass section */ - tmp2 = state[ 0 ] + lambda * state[ 1 ]; - state[ 0 ] = input[ n ]; - /* Output of allpass section */ - tmp1 = state[ 1 ] + lambda * ( state[ 2 ] - tmp2 ); - state[ 1 ] = tmp2; - acc = coef[ 0 ] * tmp2; - /* Loop over allpass sections */ - for( i = 2; i < order; i += 2 ) { - /* Output of allpass section */ - tmp2 = state[ i ] + lambda * ( state[ i + 1 ] - tmp1 ); - state[ i ] = tmp1; - acc += coef[ i - 1 ] * tmp1; - /* Output of allpass section */ - tmp1 = state[ i + 1 ] + lambda * ( state[ i + 2 ] - tmp2 ); - state[ i + 1 ] = tmp2; - acc += coef[ i ] * tmp2; - } - state[ order ] = tmp1; - acc += coef[ order - 1 ] * tmp1; - res[ n ] = input[ n ] - acc; - } -} - -/* -* silk_prefilter. Main prefilter function -*/ -void silk_prefilter_FLP( - silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ - const silk_encoder_control_FLP *psEncCtrl, /* I Encoder control FLP */ - silk_float xw[], /* O Weighted signal */ - const silk_float x[] /* I Speech signal */ -) -{ - silk_prefilter_state_FLP *P = &psEnc->sPrefilt; - opus_int j, k, lag; - silk_float HarmShapeGain, Tilt, LF_MA_shp, LF_AR_shp; - silk_float B[ 2 ]; - const silk_float *AR1_shp; - const silk_float *px; - silk_float *pxw; - silk_float HarmShapeFIR[ 3 ]; - silk_float st_res[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ]; - - /* Set up pointers */ - px = x; - pxw = xw; - lag = P->lagPrev; - for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { - /* Update Variables that change per sub frame */ - if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { - lag = psEncCtrl->pitchL[ k ]; - } - - /* Noise shape parameters */ - HarmShapeGain = psEncCtrl->HarmShapeGain[ k ] * ( 1.0f - psEncCtrl->HarmBoost[ k ] ); - HarmShapeFIR[ 0 ] = 0.25f * HarmShapeGain; - HarmShapeFIR[ 1 ] = 32767.0f / 65536.0f * HarmShapeGain; - HarmShapeFIR[ 2 ] = 0.25f * HarmShapeGain; - Tilt = psEncCtrl->Tilt[ k ]; - LF_MA_shp = psEncCtrl->LF_MA_shp[ k ]; - LF_AR_shp = psEncCtrl->LF_AR_shp[ k ]; - AR1_shp = &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ]; - - /* Short term FIR filtering */ - silk_warped_LPC_analysis_filter_FLP( P->sAR_shp, st_res, AR1_shp, px, - (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder ); - - /* Reduce (mainly) low frequencies during harmonic emphasis */ - B[ 0 ] = psEncCtrl->GainsPre[ k ]; - B[ 1 ] = -psEncCtrl->GainsPre[ k ] * - ( psEncCtrl->HarmBoost[ k ] * HarmShapeGain + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT ); - pxw[ 0 ] = B[ 0 ] * st_res[ 0 ] + B[ 1 ] * P->sHarmHP; - for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { - pxw[ j ] = B[ 0 ] * st_res[ j ] + B[ 1 ] * st_res[ j - 1 ]; - } - P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ]; - - silk_prefilt_FLP( P, pxw, pxw, HarmShapeFIR, Tilt, LF_MA_shp, LF_AR_shp, lag, psEnc->sCmn.subfr_length ); - - px += psEnc->sCmn.subfr_length; - pxw += psEnc->sCmn.subfr_length; - } - P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ]; -} - -/* -* Prefilter for finding Quantizer input signal -*/ -static OPUS_INLINE void silk_prefilt_FLP( - silk_prefilter_state_FLP *P, /* I/O state */ - silk_float st_res[], /* I */ - silk_float xw[], /* O */ - silk_float *HarmShapeFIR, /* I */ - silk_float Tilt, /* I */ - silk_float LF_MA_shp, /* I */ - silk_float LF_AR_shp, /* I */ - opus_int lag, /* I */ - opus_int length /* I */ -) -{ - opus_int i; - opus_int idx, LTP_shp_buf_idx; - silk_float n_Tilt, n_LF, n_LTP; - silk_float sLF_AR_shp, sLF_MA_shp; - silk_float *LTP_shp_buf; - - /* To speed up use temp variables instead of using the struct */ - LTP_shp_buf = P->sLTP_shp; - LTP_shp_buf_idx = P->sLTP_shp_buf_idx; - sLF_AR_shp = P->sLF_AR_shp; - sLF_MA_shp = P->sLF_MA_shp; - - for( i = 0; i < length; i++ ) { - if( lag > 0 ) { - silk_assert( HARM_SHAPE_FIR_TAPS == 3 ); - idx = lag + LTP_shp_buf_idx; - n_LTP = LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ] * HarmShapeFIR[ 0 ]; - n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ] * HarmShapeFIR[ 1 ]; - n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ] * HarmShapeFIR[ 2 ]; - } else { - n_LTP = 0; - } - - n_Tilt = sLF_AR_shp * Tilt; - n_LF = sLF_AR_shp * LF_AR_shp + sLF_MA_shp * LF_MA_shp; - - sLF_AR_shp = st_res[ i ] - n_Tilt; - sLF_MA_shp = sLF_AR_shp - n_LF; - - LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; - LTP_shp_buf[ LTP_shp_buf_idx ] = sLF_MA_shp; - - xw[ i ] = sLF_MA_shp - n_LTP; - } - /* Copy temp variable back to state */ - P->sLF_AR_shp = sLF_AR_shp; - P->sLF_MA_shp = sLF_MA_shp; - P->sLTP_shp_buf_idx = LTP_shp_buf_idx; -} diff --git a/drivers/opus/silk/float/process_gains_FLP.c b/drivers/opus/silk/float/process_gains_FLP.c deleted file mode 100644 index 3a1e46f096..0000000000 --- a/drivers/opus/silk/float/process_gains_FLP.c +++ /dev/null @@ -1,100 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/main_FLP.h" -#include "opus/silk/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/drivers/opus/silk/float/regularize_correlations_FLP.c b/drivers/opus/silk/float/regularize_correlations_FLP.c deleted file mode 100644 index 20e9074a0b..0000000000 --- a/drivers/opus/silk/float/regularize_correlations_FLP.c +++ /dev/null @@ -1,45 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/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/drivers/opus/silk/float/residual_energy_FLP.c b/drivers/opus/silk/float/residual_energy_FLP.c deleted file mode 100644 index cc462a9e54..0000000000 --- a/drivers/opus/silk/float/residual_energy_FLP.c +++ /dev/null @@ -1,114 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/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 */ - silk_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/drivers/opus/silk/float/scale_copy_vector_FLP.c b/drivers/opus/silk/float/scale_copy_vector_FLP.c deleted file mode 100644 index 2656963e88..0000000000 --- a/drivers/opus/silk/float/scale_copy_vector_FLP.c +++ /dev/null @@ -1,54 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/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/drivers/opus/silk/float/scale_vector_FLP.c b/drivers/opus/silk/float/scale_vector_FLP.c deleted file mode 100644 index ea2aa0e330..0000000000 --- a/drivers/opus/silk/float/scale_vector_FLP.c +++ /dev/null @@ -1,53 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/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/drivers/opus/silk/float/schur_FLP.c b/drivers/opus/silk/float/schur_FLP.c deleted file mode 100644 index f2071db214..0000000000 --- a/drivers/opus/silk/float/schur_FLP.c +++ /dev/null @@ -1,67 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/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; - silk_float C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; - silk_float Ctmp1, Ctmp2, rc_tmp; - - silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 ); - - /* Copy correlations */ - for( k = 0; k < order+1; k++ ) { - C[ k ][ 0 ] = C[ k ][ 1 ] = auto_corr[ k ]; - } - - 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 ] = 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 C[ 0 ][ 1 ]; -} - diff --git a/drivers/opus/silk/float/solve_LS_FLP.c b/drivers/opus/silk/float/solve_LS_FLP.c deleted file mode 100644 index 9d625c695d..0000000000 --- a/drivers/opus/silk/float/solve_LS_FLP.c +++ /dev/null @@ -1,204 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/main_FLP.h" -#include "opus/silk/tuning_parameters.h" - -/********************************************************************** - * LDL Factorisation. Finds the upper triangular matrix L and the diagonal - * Matrix D (only the diagonal elements returned in a vector)such that - * the symmetric matric A is given by A = L*D*L'. - **********************************************************************/ -static OPUS_INLINE void silk_LDL_FLP( - silk_float *A, /* I/O Pointer to Symetric Square Matrix */ - opus_int M, /* I Size of Matrix */ - silk_float *L, /* I/O Pointer to Square Upper triangular Matrix */ - silk_float *Dinv /* I/O Pointer to vector holding the inverse diagonal elements of D */ -); - -/********************************************************************** - * Function to solve linear equation Ax = b, when A is a MxM lower - * triangular matrix, with ones on the diagonal. - **********************************************************************/ -static OPUS_INLINE void silk_SolveWithLowerTriangularWdiagOnes_FLP( - const silk_float *L, /* I Pointer to Lower Triangular Matrix */ - opus_int M, /* I Dim of Matrix equation */ - const silk_float *b, /* I b Vector */ - silk_float *x /* O x Vector */ -); - -/********************************************************************** - * Function to solve linear equation (A^T)x = b, when A is a MxM lower - * triangular, with ones on the diagonal. (ie then A^T is upper triangular) - **********************************************************************/ -static OPUS_INLINE void silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( - const silk_float *L, /* I Pointer to Lower Triangular Matrix */ - opus_int M, /* I Dim of Matrix equation */ - const silk_float *b, /* I b Vector */ - silk_float *x /* O x Vector */ -); - -/********************************************************************** - * Function to solve linear equation Ax = b, when A is a MxM - * symmetric square matrix - using LDL factorisation - **********************************************************************/ -void silk_solve_LDL_FLP( - silk_float *A, /* I/O Symmetric square matrix, out: reg. */ - const opus_int M, /* I Size of matrix */ - const silk_float *b, /* I Pointer to b vector */ - silk_float *x /* O Pointer to x solution vector */ -) -{ - opus_int i; - silk_float L[ MAX_MATRIX_SIZE ][ MAX_MATRIX_SIZE ]; - silk_float T[ MAX_MATRIX_SIZE ]; - silk_float Dinv[ MAX_MATRIX_SIZE ]; /* inverse diagonal elements of D*/ - - silk_assert( M <= MAX_MATRIX_SIZE ); - - /*************************************************** - Factorize A by LDL such that A = L*D*(L^T), - where L is lower triangular with ones on diagonal - ****************************************************/ - silk_LDL_FLP( A, M, &L[ 0 ][ 0 ], Dinv ); - - /**************************************************** - * substitute D*(L^T) = T. ie: - L*D*(L^T)*x = b => L*T = b <=> T = inv(L)*b - ******************************************************/ - silk_SolveWithLowerTriangularWdiagOnes_FLP( &L[ 0 ][ 0 ], M, b, T ); - - /**************************************************** - D*(L^T)*x = T <=> (L^T)*x = inv(D)*T, because D is - diagonal just multiply with 1/d_i - ****************************************************/ - for( i = 0; i < M; i++ ) { - T[ i ] = T[ i ] * Dinv[ i ]; - } - /**************************************************** - x = inv(L') * inv(D) * T - *****************************************************/ - silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( &L[ 0 ][ 0 ], M, T, x ); -} - -static OPUS_INLINE void silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( - const silk_float *L, /* I Pointer to Lower Triangular Matrix */ - opus_int M, /* I Dim of Matrix equation */ - const silk_float *b, /* I b Vector */ - silk_float *x /* O x Vector */ -) -{ - opus_int i, j; - silk_float temp; - const silk_float *ptr1; - - for( i = M - 1; i >= 0; i-- ) { - ptr1 = matrix_adr( L, 0, i, M ); - temp = 0; - for( j = M - 1; j > i ; j-- ) { - temp += ptr1[ j * M ] * x[ j ]; - } - temp = b[ i ] - temp; - x[ i ] = temp; - } -} - -static OPUS_INLINE void silk_SolveWithLowerTriangularWdiagOnes_FLP( - const silk_float *L, /* I Pointer to Lower Triangular Matrix */ - opus_int M, /* I Dim of Matrix equation */ - const silk_float *b, /* I b Vector */ - silk_float *x /* O x Vector */ -) -{ - opus_int i, j; - silk_float temp; - const silk_float *ptr1; - - for( i = 0; i < M; i++ ) { - ptr1 = matrix_adr( L, i, 0, M ); - temp = 0; - for( j = 0; j < i; j++ ) { - temp += ptr1[ j ] * x[ j ]; - } - temp = b[ i ] - temp; - x[ i ] = temp; - } -} - -static OPUS_INLINE void silk_LDL_FLP( - silk_float *A, /* I/O Pointer to Symetric Square Matrix */ - opus_int M, /* I Size of Matrix */ - silk_float *L, /* I/O Pointer to Square Upper triangular Matrix */ - silk_float *Dinv /* I/O Pointer to vector holding the inverse diagonal elements of D */ -) -{ - opus_int i, j, k, loop_count, err = 1; - silk_float *ptr1, *ptr2; - double temp, diag_min_value; - silk_float v[ MAX_MATRIX_SIZE ], D[ MAX_MATRIX_SIZE ]; /* temp arrays*/ - - silk_assert( M <= MAX_MATRIX_SIZE ); - - diag_min_value = FIND_LTP_COND_FAC * 0.5f * ( A[ 0 ] + A[ M * M - 1 ] ); - for( loop_count = 0; loop_count < M && err == 1; loop_count++ ) { - err = 0; - for( j = 0; j < M; j++ ) { - ptr1 = matrix_adr( L, j, 0, M ); - temp = matrix_ptr( A, j, j, M ); /* element in row j column j*/ - for( i = 0; i < j; i++ ) { - v[ i ] = ptr1[ i ] * D[ i ]; - temp -= ptr1[ i ] * v[ i ]; - } - if( temp < diag_min_value ) { - /* Badly conditioned matrix: add white noise and run again */ - temp = ( loop_count + 1 ) * diag_min_value - temp; - for( i = 0; i < M; i++ ) { - matrix_ptr( A, i, i, M ) += ( silk_float )temp; - } - err = 1; - break; - } - D[ j ] = ( silk_float )temp; - Dinv[ j ] = ( silk_float )( 1.0f / temp ); - matrix_ptr( L, j, j, M ) = 1.0f; - - ptr1 = matrix_adr( A, j, 0, M ); - ptr2 = matrix_adr( L, j + 1, 0, M); - for( i = j + 1; i < M; i++ ) { - temp = 0.0; - for( k = 0; k < j; k++ ) { - temp += ptr2[ k ] * v[ k ]; - } - matrix_ptr( L, i, j, M ) = ( silk_float )( ( ptr1[ i ] - temp ) * Dinv[ j ] ); - ptr2 += M; /* go to next column*/ - } - } - } - silk_assert( err == 0 ); -} - diff --git a/drivers/opus/silk/float/sort_FLP.c b/drivers/opus/silk/float/sort_FLP.c deleted file mode 100644 index ed212c63c9..0000000000 --- a/drivers/opus/silk/float/sort_FLP.c +++ /dev/null @@ -1,80 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -/* 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 "opus/silk/typedef.h" -#include "opus/silk/float/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 */ - silk_assert( K > 0 ); - silk_assert( L > 0 ); - silk_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/drivers/opus/silk/float/structs_FLP.h b/drivers/opus/silk/float/structs_FLP.h deleted file mode 100644 index 9eb5eb05eb..0000000000 --- a/drivers/opus/silk/float/structs_FLP.h +++ /dev/null @@ -1,132 +0,0 @@ -/*********************************************************************** -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 "opus/silk/typedef.h" -#include "opus/silk/main.h" -#include "opus/silk/structs.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************/ -/* Noise shaping analysis state */ -/********************************/ -typedef struct { - opus_int8 LastGainIndex; - silk_float HarmBoost_smth; - silk_float HarmShapeGain_smth; - silk_float Tilt_smth; -} silk_shape_state_FLP; - -/********************************/ -/* Prefilter state */ -/********************************/ -typedef struct { - silk_float sLTP_shp[ LTP_BUF_LENGTH ]; - silk_float sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ]; - opus_int sLTP_shp_buf_idx; - silk_float sLF_AR_shp; - silk_float sLF_MA_shp; - silk_float sHarmHP; - opus_int32 rand_seed; - opus_int lagPrev; -} silk_prefilter_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 */ - silk_prefilter_state_FLP sPrefilt; /* Prefilter 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 AR1[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; - silk_float AR2[ 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 GainsPre[ MAX_NB_SUBFR ]; - silk_float HarmBoost[ 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 sparseness; - 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 { - silk_encoder_state_FLP state_Fxx[ ENCODER_NUM_CHANNELS ]; - 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; -} silk_encoder; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/opus/silk/float/warped_autocorrelation_FLP.c b/drivers/opus/silk/float/warped_autocorrelation_FLP.c deleted file mode 100644 index b814661b92..0000000000 --- a/drivers/opus/silk/float/warped_autocorrelation_FLP.c +++ /dev/null @@ -1,70 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; - double C[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; - - /* Order must be even */ - silk_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 */ - tmp2 = state[ i ] + warping * ( state[ i + 1 ] - tmp1 ); - state[ i ] = tmp1; - C[ i ] += state[ 0 ] * tmp1; - /* Output of allpass section */ - tmp1 = state[ i + 1 ] + warping * ( state[ i + 2 ] - 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/drivers/opus/silk/float/wrappers_FLP.c b/drivers/opus/silk/float/wrappers_FLP.c deleted file mode 100644 index c80c618a92..0000000000 --- a/drivers/opus/silk/float/wrappers_FLP.c +++ /dev/null @@ -1,199 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/float/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 */ -) -{ - opus_int i; - opus_int16 a_fix_Q12[ MAX_LPC_ORDER ]; - - silk_NLSF2A( a_fix_Q12, NLSF_Q15, LPC_order ); - - 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_int32 x_Q3[ 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 AR2_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++ ) { - AR2_Q13[ i * MAX_SHAPE_LPC_ORDER + j ] = silk_float2int( psEncCtrl->AR2[ 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++ ) { - x_Q3[ i ] = silk_float2int( 8.0f * x[ i ] ); - } - - /* Call NSQ */ - if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { - silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x_Q3, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14, - AR2_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, x_Q3, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14, - AR2_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 ], /* I/O (Un-)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 */ - const silk_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */ - const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */ - const opus_int lowComplexity, /* I Flag for low complexity */ - const opus_int nb_subfr, /* I number of subframes */ - int arch /* I Run-time architecture */ -) -{ - opus_int i; - opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ]; - opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ]; - - for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) { - B_Q14[ i ] = (opus_int16)silk_float2int( B[ i ] * 16384.0f ); - } - for( i = 0; i < nb_subfr * LTP_ORDER * LTP_ORDER; i++ ) { - W_Q18[ i ] = (opus_int32)silk_float2int( W[ i ] * 262144.0f ); - } - - silk_quant_LTP_gains( B_Q14, cbk_index, periodicity_index, sum_log_gain_Q7, W_Q18, mu_Q10, lowComplexity, nb_subfr, arch ); - - for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) { - B[ i ] = (silk_float)B_Q14[ i ] * ( 1.0f / 16384.0f ); - } -} diff --git a/drivers/opus/silk/gain_quant.c b/drivers/opus/silk/gain_quant.c deleted file mode 100644 index 7b7a65d674..0000000000 --- a/drivers/opus/silk/gain_quant.c +++ /dev/null @@ -1,138 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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; - } 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/drivers/opus/silk/init_decoder.c b/drivers/opus/silk/init_decoder.c deleted file mode 100644 index c8f694c9d7..0000000000 --- a/drivers/opus/silk/init_decoder.c +++ /dev/null @@ -1,53 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" - -/************************/ -/* 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 ) ); - - /* Used to deactivate LSF interpolation */ - psDec->first_frame_after_reset = 1; - psDec->prev_gain_Q16 = 65536; - - /* Reset CNG state */ - silk_CNG_Reset( psDec ); - - /* Reset PLC state */ - silk_PLC_Reset( psDec ); - - return(0); -} - diff --git a/drivers/opus/silk/init_encoder.c b/drivers/opus/silk/init_encoder.c deleted file mode 100644 index 1c63edb4b8..0000000000 --- a/drivers/opus/silk/init_encoder.c +++ /dev/null @@ -1,61 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" -#ifdef OPUS_FIXED_POINT -#include "opus/silk/fixed/main_FIX.h" -#else -#include "opus/silk/float/main_FLP.h" -#endif -#include "opus/silk/tuning_parameters.h" -#include "opus/celt/cpu_support.h" - -/*********************************/ -/* Initialize 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 */ -) -{ - opus_int ret = 0; - - /* Clear the entire encoder state */ - silk_memset( psEnc, 0, sizeof( silk_encoder_state_Fxx ) ); - - psEnc->sCmn.arch = arch; - - psEnc->sCmn.variable_HP_smth1_Q15 = silk_LSHIFT( silk_lin2log( SILK_FIX_CONST( VARIABLE_HP_MIN_CUTOFF_HZ, 16 ) ) - ( 16 << 7 ), 8 ); - psEnc->sCmn.variable_HP_smth2_Q15 = psEnc->sCmn.variable_HP_smth1_Q15; - - /* Used to deactivate LSF interpolation, pitch prediction */ - psEnc->sCmn.first_frame_after_reset = 1; - - /* Initialize Silk VAD */ - ret += silk_VAD_Init( &psEnc->sCmn.sVAD ); - - return ret; -} diff --git a/drivers/opus/silk/inner_prod_aligned.c b/drivers/opus/silk/inner_prod_aligned.c deleted file mode 100644 index 7bd7297c7d..0000000000 --- a/drivers/opus/silk/inner_prod_aligned.c +++ /dev/null @@ -1,44 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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/drivers/opus/silk/interpolate.c b/drivers/opus/silk/interpolate.c deleted file mode 100644 index 25091b4fa6..0000000000 --- a/drivers/opus/silk/interpolate.c +++ /dev/null @@ -1,48 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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; - - silk_assert( ifact_Q2 >= 0 ); - silk_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/drivers/opus/silk/lin2log.c b/drivers/opus/silk/lin2log.c deleted file mode 100644 index 694eb1e876..0000000000 --- a/drivers/opus/silk/lin2log.c +++ /dev/null @@ -1,43 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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_LSHIFT( 31 - lz, 7 ) + silk_SMLAWB( frac_Q7, silk_MUL( frac_Q7, 128 - frac_Q7 ), 179 ); -} - diff --git a/drivers/opus/silk/log2lin.c b/drivers/opus/silk/log2lin.c deleted file mode 100644 index 8d14150a41..0000000000 --- a/drivers/opus/silk/log2lin.c +++ /dev/null @@ -1,55 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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/drivers/opus/silk/macros.h b/drivers/opus/silk/macros.h deleted file mode 100644 index 29efd11ace..0000000000 --- a/drivers/opus/silk/macros.h +++ /dev/null @@ -1,150 +0,0 @@ -/*********************************************************************** -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 -#include "opus/opus_config.h" - -#include "opus/opus_types.h" -#include "opus/opus_defines.h" - -#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 - -/* Set this if opus_int64 is a native type of the CPU. */ -#define OPUS_FAST_INT64 (defined(__x86_64__) || defined(__LP64__) || defined(_WIN64)) - -/* 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) (((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) ((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 */ -#define silk_SMULWT(a32, b32) (((a32) >> 16) * ((b32) >> 16) + ((((a32) & 0x0000FFFF) * ((b32) >> 16)) >> 16)) - -/* a32 + (b32 * (c32 >> 16)) >> 16 */ -#if OPUS_FAST_INT64 -#define silk_SMLAWT(a32, b32, c32) ((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_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) ((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(MIPSr1_ASM) -#include "opus/silk/mips/macros_mipsr1.h" -#endif - -#include "opus/celt/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 "opus/silk/arm/macros_armv4.h" -#endif - -#ifdef OPUS_ARM_INLINE_EDSP -#include "opus/silk/arm/macros_armv5e.h" -#endif - -#endif /* SILK_MACROS_H */ - diff --git a/drivers/opus/silk/main.h b/drivers/opus/silk/main.h deleted file mode 100644 index a6ec2d7e4c..0000000000 --- a/drivers/opus/silk/main.h +++ /dev/null @@ -1,471 +0,0 @@ -/*********************************************************************** -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 "opus/silk/SigProc_FIX.h" -#include "opus/silk/define.h" -#include "opus/silk/structs.h" -#include "opus/silk/tables.h" -#include "opus/silk/PLC.h" -#include "opus/silk/control.h" -#include "opus/silk/debug.h" -#include "opus/celt/entenc.h" -#include "opus/celt/entdec.h" - -#if defined(OPUS_X86_MAY_HAVE_SSE4_1) -#include "opus/silk/x86/main_sse.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 redidual 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 ], /* I/O (un)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 */ - const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */ - opus_int mu_Q9, /* I Mu value (R/D tradeoff) */ - opus_int lowComplexity, /* I Flag for low complexity */ - 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 *rate_dist_Q14, /* O best weighted quant error + mu * rate */ - opus_int *gain_Q7, /* O sum of absolute LTP coefficients */ - const opus_int16 *in_Q14, /* I input vector to be quantized */ - const opus_int32 *W_Q18, /* I weighting matrix */ - 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 mu_Q9, /* I tradeoff betw. weighted error and rate */ - const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ - opus_int L /* I number of vectors in codebook */ -); - -#if !defined(OVERRIDE_silk_VQ_WMat_EC) -#define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \ - mu_Q9, max_gain_Q7, L, arch) \ - ((void)(arch),silk_VQ_WMat_EC_c(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \ - mu_Q9, max_gain_Q7, L)) -#endif - -/************************************/ -/* Noise shaping quantization (NSQ) */ -/************************************/ - -void silk_NSQ_c( - const silk_encoder_state *psEncC, /* I/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int32 x_Q3[], /* I Prefiltered input signal */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ - const opus_int16 AR2_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, 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_c(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 - -/* Noise shaping using delayed decision */ -void silk_NSQ_del_dec_c( - const silk_encoder_state *psEncC, /* I/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int32 x_Q3[], /* I Prefiltered input signal */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ - const opus_int16 AR2_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, 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_del_dec_c(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 - -/************/ -/* 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_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_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 */ - 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/drivers/opus/silk/mips/NSQ_del_dec_mipsr1.h b/drivers/opus/silk/mips/NSQ_del_dec_mipsr1.h deleted file mode 100644 index 5cecca28b7..0000000000 --- a/drivers/opus/silk/mips/NSQ_del_dec_mipsr1.h +++ /dev/null @@ -1,402 +0,0 @@ -/*********************************************************************** -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_DEL_DEC_MIPSR1_H__ -#define __NSQ_DEL_DEC_MIPSR1_H__ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/celt/stack_alloc.h" - -#define OVERRIDE_silk_noise_shape_quantizer_del_dec -static inline void silk_noise_shape_quantizer_del_dec( - silk_nsq_state *NSQ, /* I/O NSQ state */ - NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ - opus_int signalType, /* I Signal type */ - const opus_int32 x_Q10[], /* I */ - opus_int8 pulses[], /* O */ - opus_int16 xq[], /* O */ - opus_int32 sLTP_Q15[], /* I/O LTP filter state */ - opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */ - 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 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 subfr, /* I Subframe number */ - opus_int shapingLPCOrder, /* I Shaping LPC filter order */ - opus_int predictLPCOrder, /* I Prediction filter order */ - opus_int warping_Q16, /* I */ - opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ - opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ - opus_int decisionDelay /* I */ -) -{ - opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx; - opus_int32 Winner_rand_state; - opus_int32 LTP_pred_Q14, LPC_pred_Q14, n_AR_Q14, n_LTP_Q14; - opus_int32 n_LF_Q14, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10; - opus_int32 q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10; - opus_int32 tmp1, tmp2, sLF_AR_shp_Q14; - opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14; - NSQ_sample_struct psSampleState[ MAX_DEL_DEC_STATES ][ 2 ]; - NSQ_del_dec_struct *psDD; - NSQ_sample_struct *psSS; - opus_int16 b_Q14_0, b_Q14_1, b_Q14_2, b_Q14_3, b_Q14_4; - opus_int16 a_Q12_0, a_Q12_1, a_Q12_2, a_Q12_3, a_Q12_4, a_Q12_5, a_Q12_6; - opus_int16 a_Q12_7, a_Q12_8, a_Q12_9, a_Q12_10, a_Q12_11, a_Q12_12, a_Q12_13; - opus_int16 a_Q12_14, a_Q12_15; - - opus_int32 cur, prev, next; - - //Intialize b_Q14 variables - b_Q14_0 = b_Q14[ 0 ]; - b_Q14_1 = b_Q14[ 1 ]; - b_Q14_2 = b_Q14[ 2 ]; - b_Q14_3 = b_Q14[ 3 ]; - b_Q14_4 = b_Q14[ 4 ]; - - //Intialize a_Q12 variables - a_Q12_0 = a_Q12[0]; - a_Q12_1 = a_Q12[1]; - a_Q12_2 = a_Q12[2]; - a_Q12_3 = a_Q12[3]; - a_Q12_4 = a_Q12[4]; - a_Q12_5 = a_Q12[5]; - a_Q12_6 = a_Q12[6]; - a_Q12_7 = a_Q12[7]; - a_Q12_8 = a_Q12[8]; - a_Q12_9 = a_Q12[9]; - a_Q12_10 = a_Q12[10]; - a_Q12_11 = a_Q12[11]; - a_Q12_12 = a_Q12[12]; - a_Q12_13 = a_Q12[13]; - a_Q12_14 = a_Q12[14]; - a_Q12_15 = a_Q12[15]; - - long long temp64; - - silk_assert( nStatesDelayedDecision > 0 ); - - shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; - pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; - Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 ); - - for( i = 0; i < length; i++ ) { - /* Perform common calculations used in all states */ - - /* Long-term prediction */ - if( signalType == TYPE_VOICED ) { - /* Unrolled loop */ - /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ - temp64 = __builtin_mips_mult(pred_lag_ptr[ 0 ], b_Q14_0 ); - temp64 = __builtin_mips_madd( temp64, pred_lag_ptr[ -1 ], b_Q14_1 ); - temp64 = __builtin_mips_madd( temp64, pred_lag_ptr[ -2 ], b_Q14_2 ); - temp64 = __builtin_mips_madd( temp64, pred_lag_ptr[ -3 ], b_Q14_3 ); - temp64 = __builtin_mips_madd( temp64, pred_lag_ptr[ -4 ], b_Q14_4 ); - temp64 += 32768; - LTP_pred_Q14 = __builtin_mips_extr_w(temp64, 16); - LTP_pred_Q14 = silk_LSHIFT( LTP_pred_Q14, 1 ); /* Q13 -> Q14 */ - pred_lag_ptr++; - } else { - LTP_pred_Q14 = 0; - } - - /* Long-term shaping */ - if( lag > 0 ) { - /* Symmetric, packed FIR coefficients */ - n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); - n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); - n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */ - shp_lag_ptr++; - } else { - n_LTP_Q14 = 0; - } - - for( k = 0; k < nStatesDelayedDecision; k++ ) { - /* Delayed decision state */ - psDD = &psDelDec[ k ]; - - /* Sample state */ - psSS = psSampleState[ k ]; - - /* Generate dither */ - psDD->Seed = silk_RAND( psDD->Seed ); - - /* Pointer used in short term prediction and shaping */ - psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ]; - /* Short-term prediction */ - silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 ); - temp64 = __builtin_mips_mult(psLPC_Q14[ 0 ], a_Q12_0 ); - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -1 ], a_Q12_1 ); - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -2 ], a_Q12_2 ); - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -3 ], a_Q12_3 ); - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -4 ], a_Q12_4 ); - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -5 ], a_Q12_5 ); - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -6 ], a_Q12_6 ); - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -7 ], a_Q12_7 ); - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -8 ], a_Q12_8 ); - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -9 ], a_Q12_9 ); - if( predictLPCOrder == 16 ) { - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -10 ], a_Q12_10 ); - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -11 ], a_Q12_11 ); - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -12 ], a_Q12_12 ); - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -13 ], a_Q12_13 ); - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -14 ], a_Q12_14 ); - temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -15 ], a_Q12_15 ); - } - temp64 += 32768; - LPC_pred_Q14 = __builtin_mips_extr_w(temp64, 16); - - LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */ - - /* Noise shape feedback */ - silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ - /* Output of lowpass section */ - tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 ); - /* Output of allpass section */ - tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 ); - psDD->sAR2_Q14[ 0 ] = tmp2; - - temp64 = __builtin_mips_mult(tmp2, AR_shp_Q13[ 0 ] ); - - prev = psDD->sAR2_Q14[ 1 ]; - - /* Loop over allpass sections */ - for( j = 2; j < shapingLPCOrder; j += 2 ) { - cur = psDD->sAR2_Q14[ j ]; - next = psDD->sAR2_Q14[ j+1 ]; - /* Output of allpass section */ - tmp2 = silk_SMLAWB( prev, cur - tmp1, warping_Q16 ); - psDD->sAR2_Q14[ j - 1 ] = tmp1; - temp64 = __builtin_mips_madd( temp64, tmp1, AR_shp_Q13[ j - 1 ] ); - temp64 = __builtin_mips_madd( temp64, tmp2, AR_shp_Q13[ j ] ); - /* Output of allpass section */ - tmp1 = silk_SMLAWB( cur, next - tmp2, warping_Q16 ); - psDD->sAR2_Q14[ j + 0 ] = tmp2; - prev = next; - } - psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1; - temp64 = __builtin_mips_madd( temp64, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] ); - temp64 += 32768; - n_AR_Q14 = __builtin_mips_extr_w(temp64, 16); - n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 1 ); /* Q11 -> Q12 */ - n_AR_Q14 = silk_SMLAWB( n_AR_Q14, psDD->LF_AR_Q14, Tilt_Q14 ); /* Q12 */ - n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 2 ); /* Q12 -> Q14 */ - - n_LF_Q14 = silk_SMULWB( psDD->Shape_Q14[ *smpl_buf_idx ], LF_shp_Q14 ); /* Q12 */ - n_LF_Q14 = silk_SMLAWT( n_LF_Q14, psDD->LF_AR_Q14, LF_shp_Q14 ); /* Q12 */ - n_LF_Q14 = silk_LSHIFT( n_LF_Q14, 2 ); /* Q12 -> Q14 */ - - /* Input minus prediction plus noise feedback */ - /* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */ - tmp1 = silk_ADD32( n_AR_Q14, n_LF_Q14 ); /* Q14 */ - tmp2 = silk_ADD32( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */ - tmp1 = silk_SUB32( tmp2, tmp1 ); /* Q13 */ - tmp1 = silk_RSHIFT_ROUND( tmp1, 4 ); /* Q10 */ - - r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */ - - /* Flip sign depending on dither */ - if ( psDD->Seed < 0 ) { - r_Q10 = -r_Q10; - } - r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 ); - - /* Find two quantization level candidates and measure their rate-distortion */ - q1_Q10 = silk_SUB32( r_Q10, offset_Q10 ); - q1_Q0 = silk_RSHIFT( q1_Q10, 10 ); - if( q1_Q0 > 0 ) { - q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); - q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); - q2_Q10 = silk_ADD32( q1_Q10, 1024 ); - rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 ); - rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); - } else if( q1_Q0 == 0 ) { - q1_Q10 = offset_Q10; - q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); - rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 ); - rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); - } else if( q1_Q0 == -1 ) { - q2_Q10 = offset_Q10; - q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); - rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); - rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); - } else { /* q1_Q0 < -1 */ - q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); - q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); - q2_Q10 = silk_ADD32( q1_Q10, 1024 ); - rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); - rd2_Q10 = silk_SMULBB( -q2_Q10, Lambda_Q10 ); - } - rr_Q10 = silk_SUB32( r_Q10, q1_Q10 ); - rd1_Q10 = silk_RSHIFT( silk_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 ); - rr_Q10 = silk_SUB32( r_Q10, q2_Q10 ); - rd2_Q10 = silk_RSHIFT( silk_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 ); - - if( rd1_Q10 < rd2_Q10 ) { - psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 ); - psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 ); - psSS[ 0 ].Q_Q10 = q1_Q10; - psSS[ 1 ].Q_Q10 = q2_Q10; - } else { - psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 ); - psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 ); - psSS[ 0 ].Q_Q10 = q2_Q10; - psSS[ 1 ].Q_Q10 = q1_Q10; - } - - /* Update states for best quantization */ - - /* Quantized excitation */ - exc_Q14 = silk_LSHIFT32( psSS[ 0 ].Q_Q10, 4 ); - if ( psDD->Seed < 0 ) { - exc_Q14 = -exc_Q14; - } - - /* Add predictions */ - LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 ); - xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 ); - - /* Update states */ - sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 ); - psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 ); - psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14; - psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14; - psSS[ 0 ].xq_Q14 = xq_Q14; - - /* Update states for second best quantization */ - - /* Quantized excitation */ - exc_Q14 = silk_LSHIFT32( psSS[ 1 ].Q_Q10, 4 ); - if ( psDD->Seed < 0 ) { - exc_Q14 = -exc_Q14; - } - - - /* Add predictions */ - LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 ); - xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 ); - - /* Update states */ - sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 ); - psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 ); - psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14; - psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14; - psSS[ 1 ].xq_Q14 = xq_Q14; - } - - *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */ - last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */ - - /* Find winner */ - RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; - Winner_ind = 0; - for( k = 1; k < nStatesDelayedDecision; k++ ) { - if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) { - RDmin_Q10 = psSampleState[ k ][ 0 ].RD_Q10; - Winner_ind = k; - } - } - - /* Increase RD values of expired states */ - Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ]; - for( k = 0; k < nStatesDelayedDecision; k++ ) { - if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) { - psSampleState[ k ][ 0 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 0 ].RD_Q10, silk_int32_MAX >> 4 ); - psSampleState[ k ][ 1 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 1 ].RD_Q10, silk_int32_MAX >> 4 ); - silk_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 ); - } - } - - /* Find worst in first set and best in second set */ - RDmax_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; - RDmin_Q10 = psSampleState[ 0 ][ 1 ].RD_Q10; - RDmax_ind = 0; - RDmin_ind = 0; - for( k = 1; k < nStatesDelayedDecision; k++ ) { - /* find worst in first set */ - if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) { - RDmax_Q10 = psSampleState[ k ][ 0 ].RD_Q10; - RDmax_ind = k; - } - /* find best in second set */ - if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) { - RDmin_Q10 = psSampleState[ k ][ 1 ].RD_Q10; - RDmin_ind = k; - } - } - - /* Replace a state if best from second set outperforms worst in first set */ - if( RDmin_Q10 < RDmax_Q10 ) { - silk_memcpy( ( (opus_int32 *)&psDelDec[ RDmax_ind ] ) + i, - ( (opus_int32 *)&psDelDec[ RDmin_ind ] ) + i, sizeof( NSQ_del_dec_struct ) - i * sizeof( opus_int32) ); - silk_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) ); - } - - /* Write samples from winner to output and long-term filter states */ - psDD = &psDelDec[ Winner_ind ]; - if( subfr > 0 || i >= decisionDelay ) { - pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); - xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( - silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], delayedGain_Q10[ last_smple_idx ] ), 8 ) ); - NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q14[ last_smple_idx ]; - sLTP_Q15[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q15[ last_smple_idx ]; - } - NSQ->sLTP_shp_buf_idx++; - NSQ->sLTP_buf_idx++; - - /* Update states */ - for( k = 0; k < nStatesDelayedDecision; k++ ) { - psDD = &psDelDec[ k ]; - psSS = &psSampleState[ k ][ 0 ]; - psDD->LF_AR_Q14 = psSS->LF_AR_Q14; - psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14; - psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14; - psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10; - psDD->Pred_Q15[ *smpl_buf_idx ] = silk_LSHIFT32( psSS->LPC_exc_Q14, 1 ); - psDD->Shape_Q14[ *smpl_buf_idx ] = psSS->sLTP_shp_Q14; - psDD->Seed = silk_ADD32_ovflw( psDD->Seed, silk_RSHIFT_ROUND( psSS->Q_Q10, 10 ) ); - psDD->RandState[ *smpl_buf_idx ] = psDD->Seed; - psDD->RD_Q10 = psSS->RD_Q10; - } - delayedGain_Q10[ *smpl_buf_idx ] = Gain_Q10; - } - /* Update LPC states */ - for( k = 0; k < nStatesDelayedDecision; k++ ) { - psDD = &psDelDec[ k ]; - silk_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); - } -} - -#endif /* __NSQ_DEL_DEC_MIPSR1_H__ */ diff --git a/drivers/opus/silk/pitch_est_defines.h b/drivers/opus/silk/pitch_est_defines.h deleted file mode 100644 index e2d9e517c4..0000000000 --- a/drivers/opus/silk/pitch_est_defines.h +++ /dev/null @@ -1,88 +0,0 @@ -/*********************************************************************** -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 "opus/silk/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/drivers/opus/silk/pitch_est_tables.c b/drivers/opus/silk/pitch_est_tables.c deleted file mode 100644 index eb17bf0b26..0000000000 --- a/drivers/opus/silk/pitch_est_tables.c +++ /dev/null @@ -1,96 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/typedef.h" -#include "opus/silk/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/drivers/opus/silk/process_NLSFs.c b/drivers/opus/silk/process_NLSFs.c deleted file mode 100644 index 9d8f96d7b7..0000000000 --- a/drivers/opus/silk/process_NLSFs.c +++ /dev/null @@ -1,102 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" - -/* 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_int i, doInterpolate; - opus_int NLSF_mu_Q20; - opus_int32 i_sqr_Q15; - opus_int16 pNLSF0_temp_Q15[ MAX_LPC_ORDER ]; - opus_int16 pNLSFW_QW[ MAX_LPC_ORDER ]; - opus_int16 pNLSFW0_temp_QW[ MAX_LPC_ORDER ]; - - silk_assert( psEncC->speech_activity_Q8 >= 0 ); - silk_assert( psEncC->speech_activity_Q8 <= SILK_FIX_CONST( 1.0, 8 ) ); - silk_assert( psEncC->useInterpolatedNLSFs == 1 || psEncC->indices.NLSFInterpCoef_Q2 == ( 1 << 2 ) ); - - /***********************/ - /* Calculate mu values */ - /***********************/ - /* NLSF_mu = 0.003 - 0.0015 * psEnc->speech_activity; */ - NLSF_mu_Q20 = silk_SMLAWB( SILK_FIX_CONST( 0.003, 20 ), SILK_FIX_CONST( -0.001, 28 ), psEncC->speech_activity_Q8 ); - if( psEncC->nb_subfr == 2 ) { - /* Multiply by 1.5 for 10 ms packets */ - NLSF_mu_Q20 = silk_ADD_RSHIFT( NLSF_mu_Q20, NLSF_mu_Q20, 1 ); - } - - silk_assert( NLSF_mu_Q20 > 0 ); - silk_assert( NLSF_mu_Q20 <= SILK_FIX_CONST( 0.005, 20 ) ); - - /* Calculate NLSF weights */ - silk_NLSF_VQ_weights_laroia( pNLSFW_QW, pNLSF_Q15, psEncC->predictLPCOrder ); - - /* Update NLSF weights for interpolated NLSFs */ - doInterpolate = ( psEncC->useInterpolatedNLSFs == 1 ) && ( psEncC->indices.NLSFInterpCoef_Q2 < 4 ); - if( doInterpolate ) { - /* Calculate the interpolated NLSF vector for the first half */ - silk_interpolate( pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15, - psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder ); - - /* Calculate first half NLSF weights for the interpolated NLSFs */ - silk_NLSF_VQ_weights_laroia( pNLSFW0_temp_QW, pNLSF0_temp_Q15, psEncC->predictLPCOrder ); - - /* Update NLSF weights with contribution from first half */ - i_sqr_Q15 = silk_LSHIFT( silk_SMULBB( psEncC->indices.NLSFInterpCoef_Q2, psEncC->indices.NLSFInterpCoef_Q2 ), 11 ); - for( i = 0; i < psEncC->predictLPCOrder; i++ ) { - pNLSFW_QW[ i ] = silk_SMLAWB( silk_RSHIFT( pNLSFW_QW[ i ], 1 ), (opus_int32)pNLSFW0_temp_QW[ i ], i_sqr_Q15 ); - silk_assert( pNLSFW_QW[ i ] >= 1 ); - } - } - - silk_NLSF_encode( psEncC->indices.NLSFIndices, pNLSF_Q15, psEncC->psNLSF_CB, pNLSFW_QW, - NLSF_mu_Q20, psEncC->NLSF_MSVQ_Survivors, psEncC->indices.signalType ); - - /* Convert quantized NLSFs back to LPC coefficients */ - silk_NLSF2A( PredCoef_Q12[ 1 ], pNLSF_Q15, psEncC->predictLPCOrder ); - - if( doInterpolate ) { - /* Calculate the interpolated, quantized LSF vector for the first half */ - silk_interpolate( pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15, - psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder ); - - /* Convert back to LPC coefficients */ - silk_NLSF2A( PredCoef_Q12[ 0 ], pNLSF0_temp_Q15, psEncC->predictLPCOrder ); - - } else { - /* Copy LPC coefficients for first half from second half */ - silk_memcpy( PredCoef_Q12[ 0 ], PredCoef_Q12[ 1 ], psEncC->predictLPCOrder * sizeof( opus_int16 ) ); - } -} diff --git a/drivers/opus/silk/quant_LTP_gains.c b/drivers/opus/silk/quant_LTP_gains.c deleted file mode 100644 index ffc3cb24ab..0000000000 --- a/drivers/opus/silk/quant_LTP_gains.c +++ /dev/null @@ -1,126 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/silk/tuning_parameters.h" - -void silk_quant_LTP_gains( - opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (un)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 */ - const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */ - opus_int mu_Q9, /* I Mu value (R/D tradeoff) */ - opus_int lowComplexity, /* I Flag for low complexity */ - const opus_int nb_subfr, /* I number of subframes */ - int arch /* I Run-time architecture */ -) -{ - opus_int j, k, cbk_size; - opus_int8 temp_idx[ MAX_NB_SUBFR ]; - const opus_uint8 *cl_ptr_Q5; - const opus_int8 *cbk_ptr_Q7; - const opus_uint8 *cbk_gain_ptr_Q7; - const opus_int16 *b_Q14_ptr; - const opus_int32 *W_Q18_ptr; - opus_int32 rate_dist_Q14_subfr, rate_dist_Q14, min_rate_dist_Q14; - opus_int32 sum_log_gain_tmp_Q7, best_sum_log_gain_Q7, max_gain_Q7, gain_Q7; - - /***************************************************/ - /* iterate over different codebooks with different */ - /* rates/distortions, and choose best */ - /***************************************************/ - min_rate_dist_Q14 = silk_int32_MAX; - best_sum_log_gain_Q7 = 0; - for( k = 0; k < 3; k++ ) { - /* Safety margin for pitch gain control, to take into account factors - such as state rescaling/rewhitening. */ - opus_int32 gain_safety = SILK_FIX_CONST( 0.4, 7 ); - - cl_ptr_Q5 = silk_LTP_gain_BITS_Q5_ptrs[ k ]; - cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ k ]; - cbk_gain_ptr_Q7 = silk_LTP_vq_gain_ptrs_Q7[ k ]; - cbk_size = silk_LTP_vq_sizes[ k ]; - - /* Set up pointer to first subframe */ - W_Q18_ptr = W_Q18; - b_Q14_ptr = B_Q14; - - rate_dist_Q14 = 0; - sum_log_gain_tmp_Q7 = *sum_log_gain_Q7; - for( j = 0; j < nb_subfr; j++ ) { - max_gain_Q7 = silk_log2lin( ( SILK_FIX_CONST( MAX_SUM_LOG_GAIN_DB / 6.0, 7 ) - sum_log_gain_tmp_Q7 ) - + SILK_FIX_CONST( 7, 7 ) ) - gain_safety; - - silk_VQ_WMat_EC( - &temp_idx[ j ], /* O index of best codebook vector */ - &rate_dist_Q14_subfr, /* O best weighted quantization error + mu * rate */ - &gain_Q7, /* O sum of absolute LTP coefficients */ - b_Q14_ptr, /* I input vector to be quantized */ - W_Q18_ptr, /* I weighting matrix */ - cbk_ptr_Q7, /* I codebook */ - cbk_gain_ptr_Q7, /* I codebook effective gains */ - cl_ptr_Q5, /* I code length for each codebook vector */ - mu_Q9, /* I tradeoff between weighted error and rate */ - max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ - cbk_size, /* I number of vectors in codebook */ - arch /* I Run-time architecture */ - ); - - rate_dist_Q14 = silk_ADD_POS_SAT32( rate_dist_Q14, rate_dist_Q14_subfr ); - sum_log_gain_tmp_Q7 = silk_max(0, sum_log_gain_tmp_Q7 - + silk_lin2log( gain_safety + gain_Q7 ) - SILK_FIX_CONST( 7, 7 )); - - b_Q14_ptr += LTP_ORDER; - W_Q18_ptr += LTP_ORDER * LTP_ORDER; - } - - /* Avoid never finding a codebook */ - rate_dist_Q14 = silk_min( silk_int32_MAX - 1, rate_dist_Q14 ); - - if( rate_dist_Q14 < min_rate_dist_Q14 ) { - min_rate_dist_Q14 = rate_dist_Q14; - *periodicity_index = (opus_int8)k; - silk_memcpy( cbk_index, temp_idx, nb_subfr * sizeof( opus_int8 ) ); - best_sum_log_gain_Q7 = sum_log_gain_tmp_Q7; - } - - /* Break early in low-complexity mode if rate distortion is below threshold */ - if( lowComplexity && ( rate_dist_Q14 < silk_LTP_gain_middle_avg_RD_Q14 ) ) { - break; - } - } - - cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ *periodicity_index ]; - for( j = 0; j < nb_subfr; j++ ) { - for( k = 0; k < LTP_ORDER; k++ ) { - B_Q14[ j * LTP_ORDER + k ] = silk_LSHIFT( cbk_ptr_Q7[ cbk_index[ j ] * LTP_ORDER + k ], 7 ); - } - } - *sum_log_gain_Q7 = best_sum_log_gain_Q7; -} diff --git a/drivers/opus/silk/resampler.c b/drivers/opus/silk/resampler.c deleted file mode 100644 index 12b2f92060..0000000000 --- a/drivers/opus/silk/resampler.c +++ /dev/null @@ -1,212 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -/* - * 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 "opus/silk/resampler_private.h" - -/* Tables with delay compensation values to equalize total delay for different modes */ -static const opus_int8 delay_matrix_enc[ 5 ][ 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 } -}; - -static const opus_int8 delay_matrix_dec[ 3 ][ 5 ] = { -/* in \ out 8 12 16 24 48 */ -/* 8 */ { 4, 0, 2, 0, 0 }, -/* 12 */ { 0, 9, 4, 7, 4 }, -/* 16 */ { 0, 3, 12, 7, 7 } -}; - -/* Simple way to make [8000, 12000, 16000, 24000, 48000] to [0, 1, 2, 3, 4] */ -#define rateID(R) ( ( ( ((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 ) || - ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 ) ) { - silk_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 ) ) { - silk_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 */ - silk_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 */ - silk_assert( inLen >= S->Fs_in_kHz ); - /* Delay can't exceed the 1 ms of buffering */ - silk_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/drivers/opus/silk/resampler_down2.c b/drivers/opus/silk/resampler_down2.c deleted file mode 100644 index 20a42c98a6..0000000000 --- a/drivers/opus/silk/resampler_down2.c +++ /dev/null @@ -1,71 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/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; - - silk_assert( silk_resampler_down2_0 > 0 ); - silk_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/drivers/opus/silk/resampler_down2_3.c b/drivers/opus/silk/resampler_down2_3.c deleted file mode 100644 index e01dd2bc72..0000000000 --- a/drivers/opus/silk/resampler_down2_3.c +++ /dev/null @@ -1,100 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/resampler_private.h" -#include "opus/celt/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/drivers/opus/silk/resampler_private.h b/drivers/opus/silk/resampler_private.h deleted file mode 100644 index 5c0ee110fc..0000000000 --- a/drivers/opus/silk/resampler_private.h +++ /dev/null @@ -1,88 +0,0 @@ -/*********************************************************************** -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 - -#ifdef __cplusplus -extern "C" { -#endif - -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/resampler_structs.h" -#include "opus/silk/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 */ -); - -#ifdef __cplusplus -} -#endif -#endif /* SILK_RESAMPLER_PRIVATE_H */ diff --git a/drivers/opus/silk/resampler_private_AR2.c b/drivers/opus/silk/resampler_private_AR2.c deleted file mode 100644 index cc753ea704..0000000000 --- a/drivers/opus/silk/resampler_private_AR2.c +++ /dev/null @@ -1,52 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/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/drivers/opus/silk/resampler_private_IIR_FIR.c b/drivers/opus/silk/resampler_private_IIR_FIR.c deleted file mode 100644 index 9a8733fbbb..0000000000 --- a/drivers/opus/silk/resampler_private_IIR_FIR.c +++ /dev/null @@ -1,104 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/resampler_private.h" -#include "opus/celt/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/drivers/opus/silk/resampler_private_down_FIR.c b/drivers/opus/silk/resampler_private_down_FIR.c deleted file mode 100644 index fb9acc60a7..0000000000 --- a/drivers/opus/silk/resampler_private_down_FIR.c +++ /dev/null @@ -1,191 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/resampler_private.h" -#include "opus/celt/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: - silk_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/drivers/opus/silk/resampler_private_up2_HQ.c b/drivers/opus/silk/resampler_private_up2_HQ.c deleted file mode 100644 index 0b23c16dab..0000000000 --- a/drivers/opus/silk/resampler_private_up2_HQ.c +++ /dev/null @@ -1,110 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/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/drivers/opus/silk/resampler_rom.c b/drivers/opus/silk/resampler_rom.c deleted file mode 100644 index 7079efe1dc..0000000000 --- a/drivers/opus/silk/resampler_rom.c +++ /dev/null @@ -1,93 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -/* Filter coefficients for IIR/FIR polyphase resampling * - * Total size: 179 Words (358 Bytes) */ - -#include "opus/silk/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/drivers/opus/silk/resampler_rom.h b/drivers/opus/silk/resampler_rom.h deleted file mode 100644 index 2fa586ebf2..0000000000 --- a/drivers/opus/silk/resampler_rom.h +++ /dev/null @@ -1,68 +0,0 @@ -/*********************************************************************** -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 - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "opus/silk/typedef.h" -#include "opus/silk/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 ]; - -#ifdef __cplusplus -} -#endif - -#endif /* SILK_FIX_RESAMPLER_ROM_H */ diff --git a/drivers/opus/silk/shell_coder.c b/drivers/opus/silk/shell_coder.c deleted file mode 100644 index 67a5446927..0000000000 --- a/drivers/opus/silk/shell_coder.c +++ /dev/null @@ -1,148 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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/drivers/opus/silk/sigm_Q15.c b/drivers/opus/silk/sigm_Q15.c deleted file mode 100644 index 3171d15f4a..0000000000 --- a/drivers/opus/silk/sigm_Q15.c +++ /dev/null @@ -1,73 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -/* Approximate sigmoid function */ - -#include "opus/silk/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/drivers/opus/silk/sort.c b/drivers/opus/silk/sort.c deleted file mode 100644 index dd2988e5b8..0000000000 --- a/drivers/opus/silk/sort.c +++ /dev/null @@ -1,151 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -/* 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: http://en.wikipedia.org/wiki/Shell_sort */ - -#include "opus/silk/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 */ - silk_assert( K > 0 ); - silk_assert( L > 0 ); - silk_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 OPUS_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 */ - silk_assert( K > 0 ); - silk_assert( L > 0 ); - silk_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 */ - silk_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/drivers/opus/silk/stereo_LR_to_MS.c b/drivers/opus/silk/stereo_LR_to_MS.c deleted file mode 100644 index cf8affa90b..0000000000 --- a/drivers/opus/silk/stereo_LR_to_MS.c +++ /dev/null @@ -1,226 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" -#include "opus/celt/stack_alloc.h" - -/* 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 */ -) -{ - opus_int n, is10msFrame, denom_Q16, delta0_Q13, delta1_Q13; - opus_int32 sum, diff, smooth_coef_Q16, pred_Q13[ 2 ], pred0_Q13, pred1_Q13; - opus_int32 LP_ratio_Q14, HP_ratio_Q14, frac_Q16, frac_3_Q16, min_mid_rate_bps, width_Q14, w_Q24, deltaw_Q24; - VARDECL( opus_int16, side ); - VARDECL( opus_int16, LP_mid ); - VARDECL( opus_int16, HP_mid ); - VARDECL( opus_int16, LP_side ); - VARDECL( opus_int16, HP_side ); - opus_int16 *mid = &x1[ -2 ]; - SAVE_STACK; - - ALLOC( side, frame_length + 2, opus_int16 ); - /* Convert to basic mid/side signals */ - for( n = 0; n < frame_length + 2; n++ ) { - sum = x1[ n - 2 ] + (opus_int32)x2[ n - 2 ]; - diff = x1[ n - 2 ] - (opus_int32)x2[ n - 2 ]; - mid[ n ] = (opus_int16)silk_RSHIFT_ROUND( sum, 1 ); - side[ n ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( diff, 1 ) ); - } - - /* Buffering */ - silk_memcpy( mid, state->sMid, 2 * sizeof( opus_int16 ) ); - silk_memcpy( side, state->sSide, 2 * sizeof( opus_int16 ) ); - silk_memcpy( state->sMid, &mid[ frame_length ], 2 * sizeof( opus_int16 ) ); - silk_memcpy( state->sSide, &side[ frame_length ], 2 * sizeof( opus_int16 ) ); - - /* LP and HP filter mid signal */ - ALLOC( LP_mid, frame_length, opus_int16 ); - ALLOC( HP_mid, frame_length, opus_int16 ); - for( n = 0; n < frame_length; n++ ) { - sum = silk_RSHIFT_ROUND( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 2 ); - LP_mid[ n ] = sum; - HP_mid[ n ] = mid[ n + 1 ] - sum; - } - - /* LP and HP filter side signal */ - ALLOC( LP_side, frame_length, opus_int16 ); - ALLOC( HP_side, frame_length, opus_int16 ); - for( n = 0; n < frame_length; n++ ) { - sum = silk_RSHIFT_ROUND( silk_ADD_LSHIFT( side[ n ] + side[ n + 2 ], side[ n + 1 ], 1 ), 2 ); - LP_side[ n ] = sum; - HP_side[ n ] = side[ n + 1 ] - sum; - } - - /* Find energies and predictors */ - is10msFrame = frame_length == 10 * fs_kHz; - smooth_coef_Q16 = is10msFrame ? - SILK_FIX_CONST( STEREO_RATIO_SMOOTH_COEF / 2, 16 ) : - SILK_FIX_CONST( STEREO_RATIO_SMOOTH_COEF, 16 ); - smooth_coef_Q16 = silk_SMULWB( silk_SMULBB( prev_speech_act_Q8, prev_speech_act_Q8 ), smooth_coef_Q16 ); - - pred_Q13[ 0 ] = silk_stereo_find_predictor( &LP_ratio_Q14, LP_mid, LP_side, &state->mid_side_amp_Q0[ 0 ], frame_length, smooth_coef_Q16 ); - pred_Q13[ 1 ] = silk_stereo_find_predictor( &HP_ratio_Q14, HP_mid, HP_side, &state->mid_side_amp_Q0[ 2 ], frame_length, smooth_coef_Q16 ); - /* Ratio of the norms of residual and mid signals */ - frac_Q16 = silk_SMLABB( HP_ratio_Q14, LP_ratio_Q14, 3 ); - frac_Q16 = silk_min( frac_Q16, SILK_FIX_CONST( 1, 16 ) ); - - /* Determine bitrate distribution between mid and side, and possibly reduce stereo width */ - total_rate_bps -= is10msFrame ? 1200 : 600; /* Subtract approximate bitrate for coding stereo parameters */ - if( total_rate_bps < 1 ) { - total_rate_bps = 1; - } - min_mid_rate_bps = silk_SMLABB( 2000, fs_kHz, 900 ); - silk_assert( min_mid_rate_bps < 32767 ); - /* Default bitrate distribution: 8 parts for Mid and (5+3*frac) parts for Side. so: mid_rate = ( 8 / ( 13 + 3 * frac ) ) * total_ rate */ - frac_3_Q16 = silk_MUL( 3, frac_Q16 ); - mid_side_rates_bps[ 0 ] = silk_DIV32_varQ( total_rate_bps, SILK_FIX_CONST( 8 + 5, 16 ) + frac_3_Q16, 16+3 ); - /* If Mid bitrate below minimum, reduce stereo width */ - if( mid_side_rates_bps[ 0 ] < min_mid_rate_bps ) { - mid_side_rates_bps[ 0 ] = min_mid_rate_bps; - mid_side_rates_bps[ 1 ] = total_rate_bps - mid_side_rates_bps[ 0 ]; - /* width = 4 * ( 2 * side_rate - min_rate ) / ( ( 1 + 3 * frac ) * min_rate ) */ - width_Q14 = silk_DIV32_varQ( silk_LSHIFT( mid_side_rates_bps[ 1 ], 1 ) - min_mid_rate_bps, - silk_SMULWB( SILK_FIX_CONST( 1, 16 ) + frac_3_Q16, min_mid_rate_bps ), 14+2 ); - width_Q14 = silk_LIMIT( width_Q14, 0, SILK_FIX_CONST( 1, 14 ) ); - } else { - mid_side_rates_bps[ 1 ] = total_rate_bps - mid_side_rates_bps[ 0 ]; - width_Q14 = SILK_FIX_CONST( 1, 14 ); - } - - /* Smoother */ - state->smth_width_Q14 = (opus_int16)silk_SMLAWB( state->smth_width_Q14, width_Q14 - state->smth_width_Q14, smooth_coef_Q16 ); - - /* At very low bitrates or for inputs that are nearly amplitude panned, switch to panned-mono coding */ - *mid_only_flag = 0; - if( toMono ) { - /* Last frame before stereo->mono transition; collapse stereo width */ - width_Q14 = 0; - pred_Q13[ 0 ] = 0; - pred_Q13[ 1 ] = 0; - silk_stereo_quant_pred( pred_Q13, ix ); - } else if( state->width_prev_Q14 == 0 && - ( 8 * total_rate_bps < 13 * min_mid_rate_bps || silk_SMULWB( frac_Q16, state->smth_width_Q14 ) < SILK_FIX_CONST( 0.05, 14 ) ) ) - { - /* Code as panned-mono; previous frame already had zero width */ - /* Scale down and quantize predictors */ - pred_Q13[ 0 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 0 ] ), 14 ); - pred_Q13[ 1 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); - silk_stereo_quant_pred( pred_Q13, ix ); - /* Collapse stereo width */ - width_Q14 = 0; - pred_Q13[ 0 ] = 0; - pred_Q13[ 1 ] = 0; - mid_side_rates_bps[ 0 ] = total_rate_bps; - mid_side_rates_bps[ 1 ] = 0; - *mid_only_flag = 1; - } else if( state->width_prev_Q14 != 0 && - ( 8 * total_rate_bps < 11 * min_mid_rate_bps || silk_SMULWB( frac_Q16, state->smth_width_Q14 ) < SILK_FIX_CONST( 0.02, 14 ) ) ) - { - /* Transition to zero-width stereo */ - /* Scale down and quantize predictors */ - pred_Q13[ 0 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 0 ] ), 14 ); - pred_Q13[ 1 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); - silk_stereo_quant_pred( pred_Q13, ix ); - /* Collapse stereo width */ - width_Q14 = 0; - pred_Q13[ 0 ] = 0; - pred_Q13[ 1 ] = 0; - } else if( state->smth_width_Q14 > SILK_FIX_CONST( 0.95, 14 ) ) { - /* Full-width stereo coding */ - silk_stereo_quant_pred( pred_Q13, ix ); - width_Q14 = SILK_FIX_CONST( 1, 14 ); - } else { - /* Reduced-width stereo coding; scale down and quantize predictors */ - pred_Q13[ 0 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 0 ] ), 14 ); - pred_Q13[ 1 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); - silk_stereo_quant_pred( pred_Q13, ix ); - width_Q14 = state->smth_width_Q14; - } - - /* Make sure to keep on encoding until the tapered output has been transmitted */ - if( *mid_only_flag == 1 ) { - state->silent_side_len += frame_length - STEREO_INTERP_LEN_MS * fs_kHz; - if( state->silent_side_len < LA_SHAPE_MS * fs_kHz ) { - *mid_only_flag = 0; - } else { - /* Limit to avoid wrapping around */ - state->silent_side_len = 10000; - } - } else { - state->silent_side_len = 0; - } - - if( *mid_only_flag == 0 && mid_side_rates_bps[ 1 ] < 1 ) { - mid_side_rates_bps[ 1 ] = 1; - mid_side_rates_bps[ 0 ] = silk_max_int( 1, total_rate_bps - mid_side_rates_bps[ 1 ]); - } - - /* Interpolate predictors and subtract prediction from side channel */ - pred0_Q13 = -state->pred_prev_Q13[ 0 ]; - pred1_Q13 = -state->pred_prev_Q13[ 1 ]; - w_Q24 = silk_LSHIFT( state->width_prev_Q14, 10 ); - 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 ); - deltaw_Q24 = silk_LSHIFT( silk_SMULWB( width_Q14 - state->width_prev_Q14, denom_Q16 ), 10 ); - for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) { - pred0_Q13 += delta0_Q13; - pred1_Q13 += delta1_Q13; - w_Q24 += deltaw_Q24; - sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ - sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ - sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)mid[ 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 ]; - w_Q24 = silk_LSHIFT( width_Q14, 10 ); - for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { - sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ - sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ - sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)mid[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ - x2[ n - 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) ); - } - state->pred_prev_Q13[ 0 ] = (opus_int16)pred_Q13[ 0 ]; - state->pred_prev_Q13[ 1 ] = (opus_int16)pred_Q13[ 1 ]; - state->width_prev_Q14 = (opus_int16)width_Q14; - RESTORE_STACK; -} diff --git a/drivers/opus/silk/stereo_MS_to_LR.c b/drivers/opus/silk/stereo_MS_to_LR.c deleted file mode 100644 index 4f553eb694..0000000000 --- a/drivers/opus/silk/stereo_MS_to_LR.c +++ /dev/null @@ -1,82 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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_LSHIFT( x1[ n ] + 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_LSHIFT( x1[ n ] + 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/drivers/opus/silk/stereo_decode_pred.c b/drivers/opus/silk/stereo_decode_pred.c deleted file mode 100644 index 9e8abf39d0..0000000000 --- a/drivers/opus/silk/stereo_decode_pred.c +++ /dev/null @@ -1,70 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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/drivers/opus/silk/stereo_encode_pred.c b/drivers/opus/silk/stereo_encode_pred.c deleted file mode 100644 index a864d404f6..0000000000 --- a/drivers/opus/silk/stereo_encode_pred.c +++ /dev/null @@ -1,59 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" - -/* 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 */ -) -{ - opus_int n; - - /* Entropy coding */ - n = 5 * ix[ 0 ][ 2 ] + ix[ 1 ][ 2 ]; - silk_assert( n < 25 ); - ec_enc_icdf( psRangeEnc, n, silk_stereo_pred_joint_iCDF, 8 ); - for( n = 0; n < 2; n++ ) { - silk_assert( ix[ n ][ 0 ] < 3 ); - silk_assert( ix[ n ][ 1 ] < STEREO_QUANT_SUB_STEPS ); - ec_enc_icdf( psRangeEnc, ix[ n ][ 0 ], silk_uniform3_iCDF, 8 ); - ec_enc_icdf( psRangeEnc, ix[ n ][ 1 ], silk_uniform5_iCDF, 8 ); - } -} - -/* 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 -) -{ - /* Encode flag that only mid channel is coded */ - ec_enc_icdf( psRangeEnc, mid_only_flag, silk_stereo_only_code_mid_iCDF, 8 ); -} diff --git a/drivers/opus/silk/stereo_find_predictor.c b/drivers/opus/silk/stereo_find_predictor.c deleted file mode 100644 index c7fa3ac555..0000000000 --- a/drivers/opus/silk/stereo_find_predictor.c +++ /dev/null @@ -1,76 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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/drivers/opus/silk/stereo_quant_pred.c b/drivers/opus/silk/stereo_quant_pred.c deleted file mode 100644 index ff2971e7c1..0000000000 --- a/drivers/opus/silk/stereo_quant_pred.c +++ /dev/null @@ -1,70 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/main.h" - -/* 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 */ -) -{ - opus_int i, j, n; - opus_int32 low_Q13, step_Q13, lvl_Q13, err_min_Q13, err_Q13, quant_pred_Q13 = 0; - - /* Quantize */ - for( n = 0; n < 2; n++ ) { - /* Brute-force search over quantization levels */ - err_min_Q13 = silk_int32_MAX; - for( i = 0; i < STEREO_QUANT_TAB_SIZE - 1; i++ ) { - low_Q13 = silk_stereo_pred_quant_Q13[ i ]; - step_Q13 = silk_SMULWB( silk_stereo_pred_quant_Q13[ i + 1 ] - low_Q13, - SILK_FIX_CONST( 0.5 / STEREO_QUANT_SUB_STEPS, 16 ) ); - for( j = 0; j < STEREO_QUANT_SUB_STEPS; j++ ) { - lvl_Q13 = silk_SMLABB( low_Q13, step_Q13, 2 * j + 1 ); - err_Q13 = silk_abs( pred_Q13[ n ] - lvl_Q13 ); - if( err_Q13 < err_min_Q13 ) { - err_min_Q13 = err_Q13; - quant_pred_Q13 = lvl_Q13; - ix[ n ][ 0 ] = i; - ix[ n ][ 1 ] = j; - } else { - /* Error increasing, so we're past the optimum */ - goto done; - } - } - } - done: - ix[ n ][ 2 ] = silk_DIV32_16( ix[ n ][ 0 ], 3 ); - ix[ n ][ 0 ] -= ix[ n ][ 2 ] * 3; - pred_Q13[ n ] = quant_pred_Q13; - } - - /* Subtract second from first predictor (helps when actually applying these) */ - pred_Q13[ 0 ] -= pred_Q13[ 1 ]; -} diff --git a/drivers/opus/silk/structs.h b/drivers/opus/silk/structs.h deleted file mode 100644 index a2876b62a2..0000000000 --- a/drivers/opus/silk/structs.h +++ /dev/null @@ -1,327 +0,0 @@ -/*********************************************************************** -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 "opus/silk/typedef.h" -#include "opus/silk/SigProc_FIX.h" -#include "opus/silk/define.h" -#include "opus/celt/entenc.h" -#include "opus/celt/entdec.h" - -#ifdef __cplusplus -extern "C" -{ -#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_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 */ -} 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_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_int LTPQuantLowComplexity; /* Flag for low complexity LTP quantization */ - opus_int mu_LTP_Q9; /* Rate-distortion tradeoff in LTP quantization */ - 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; - - -/* 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 coeficients 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; -} 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 { - 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; - - 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; - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/opus/silk/sum_sqr_shift.c b/drivers/opus/silk/sum_sqr_shift.c deleted file mode 100644 index 1d1da449f4..0000000000 --- a/drivers/opus/silk/sum_sqr_shift.c +++ /dev/null @@ -1,83 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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_int32 nrg_tmp, nrg; - - nrg = 0; - shft = 0; - len--; - for( i = 0; i < len; i += 2 ) { - nrg = silk_SMLABB_ovflw( nrg, x[ i ], x[ i ] ); - nrg = silk_SMLABB_ovflw( nrg, x[ i + 1 ], x[ i + 1 ] ); - if( nrg < 0 ) { - /* Scale down */ - nrg = (opus_int32)silk_RSHIFT_uint( (opus_uint32)nrg, 2 ); - shft = 2; - i+=2; - break; - } - } - for( ; i < len; 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, (opus_uint32)nrg_tmp, shft ); - if( nrg < 0 ) { - /* Scale down */ - nrg = (opus_int32)silk_RSHIFT_uint( (opus_uint32)nrg, 2 ); - shft += 2; - } - } - 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 ); - } - - /* Make sure to have at least one extra leading zero (two leading zeros in total) */ - if( nrg & 0xC0000000 ) { - nrg = silk_RSHIFT_uint( (opus_uint32)nrg, 2 ); - shft += 2; - } - - /* Output arguments */ - *shift = shft; - *energy = nrg; -} - diff --git a/drivers/opus/silk/table_LSF_cos.c b/drivers/opus/silk/table_LSF_cos.c deleted file mode 100644 index d350df9add..0000000000 --- a/drivers/opus/silk/table_LSF_cos.c +++ /dev/null @@ -1,67 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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/drivers/opus/silk/tables.h b/drivers/opus/silk/tables.h deleted file mode 100644 index 2ad69eec80..0000000000 --- a/drivers/opus/silk/tables.h +++ /dev/null @@ -1,122 +0,0 @@ -/*********************************************************************** -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 "opus/silk/define.h" -#include "opus/silk/structs.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* 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_int16 silk_LTP_gain_middle_avg_RD_Q14; -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 */ - -/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */ -extern const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ]; /* 32 */ -extern const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ]; /* 32 */ -extern const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ]; /* 32 */ -extern const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ]; /* 32 */ - -/* 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 */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/opus/silk/tables_LTP.c b/drivers/opus/silk/tables_LTP.c deleted file mode 100644 index 9f500b25f2..0000000000 --- a/drivers/opus/silk/tables_LTP.c +++ /dev/null @@ -1,293 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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 -}; - -const opus_int16 silk_LTP_gain_middle_avg_RD_Q14 = 12304; - -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/drivers/opus/silk/tables_NLSF_CB_NB_MB.c b/drivers/opus/silk/tables_NLSF_CB_NB_MB.c deleted file mode 100644 index d1cf99356d..0000000000 --- a/drivers/opus/silk/tables_NLSF_CB_NB_MB.c +++ /dev/null @@ -1,156 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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_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_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/drivers/opus/silk/tables_NLSF_CB_WB.c b/drivers/opus/silk/tables_NLSF_CB_WB.c deleted file mode 100644 index 5ee6e880c4..0000000000 --- a/drivers/opus/silk/tables_NLSF_CB_WB.c +++ /dev/null @@ -1,195 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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_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_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/drivers/opus/silk/tables_gain.c b/drivers/opus/silk/tables_gain.c deleted file mode 100644 index e1e4319d7d..0000000000 --- a/drivers/opus/silk/tables_gain.c +++ /dev/null @@ -1,60 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/tables.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -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 -}; - -#ifdef __cplusplus -} -#endif diff --git a/drivers/opus/silk/tables_other.c b/drivers/opus/silk/tables_other.c deleted file mode 100644 index 3713ff8227..0000000000 --- a/drivers/opus/silk/tables_other.c +++ /dev/null @@ -1,135 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/structs.h" -#include "opus/silk/define.h" -#include "opus/silk/tables.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */ -const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ] = { - 0, 8000, 9400, 11500, 13500, 17500, 25000, MAX_TARGET_RATE_BPS -}; -const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ] = { - 0, 9000, 12000, 14500, 18500, 24500, 35500, MAX_TARGET_RATE_BPS -}; -const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ] = { - 0, 10500, 14000, 17000, 21500, 28500, 42000, MAX_TARGET_RATE_BPS -}; -const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ] = { - 18, 29, 38, 40, 46, 52, 62, 84 -}; - -/* 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 } -}; - -#ifdef __cplusplus -} -#endif - diff --git a/drivers/opus/silk/tables_pitch_lag.c b/drivers/opus/silk/tables_pitch_lag.c deleted file mode 100644 index f435b7e016..0000000000 --- a/drivers/opus/silk/tables_pitch_lag.c +++ /dev/null @@ -1,66 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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/drivers/opus/silk/tables_pulses_per_block.c b/drivers/opus/silk/tables_pulses_per_block.c deleted file mode 100644 index 21f430791a..0000000000 --- a/drivers/opus/silk/tables_pulses_per_block.c +++ /dev/null @@ -1,261 +0,0 @@ -/*********************************************************************** -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. -***********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/silk/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/drivers/opus/silk/typedef.h b/drivers/opus/silk/typedef.h deleted file mode 100644 index 3e193b4a45..0000000000 --- a/drivers/opus/silk/typedef.h +++ /dev/null @@ -1,78 +0,0 @@ -/*********************************************************************** -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/opus_types.h" -#include "opus/opus_defines.h" - -#ifndef OPUS_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); - abort(); -} -# define silk_assert(COND) {if (!(COND)) {silk_fatal("assertion failed: " #COND);}} -# else -# define silk_assert(COND) -# endif -#endif - -#endif /* SILK_TYPEDEF_H */ diff --git a/drivers/opus/silk/x86/NSQ_del_dec_sse.c b/drivers/opus/silk/x86/NSQ_del_dec_sse.c deleted file mode 100644 index e9afbba01b..0000000000 --- a/drivers/opus/silk/x86/NSQ_del_dec_sse.c +++ /dev/null @@ -1,854 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include <xmmintrin.h> -#include <emmintrin.h> -#include <smmintrin.h> -#include "opus/silk/main.h" -#include "opus/celt/x86/x86cpu.h" - -#include "opus/celt/stack_alloc.h" - -typedef struct { - opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ]; - opus_int32 RandState[ DECISION_DELAY ]; - opus_int32 Q_Q10[ DECISION_DELAY ]; - opus_int32 Xq_Q14[ DECISION_DELAY ]; - opus_int32 Pred_Q15[ DECISION_DELAY ]; - opus_int32 Shape_Q14[ DECISION_DELAY ]; - opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ]; - opus_int32 LF_AR_Q14; - opus_int32 Seed; - opus_int32 SeedInit; - opus_int32 RD_Q10; -} NSQ_del_dec_struct; - -typedef struct { - opus_int32 Q_Q10; - opus_int32 RD_Q10; - opus_int32 xq_Q14; - opus_int32 LF_AR_Q14; - opus_int32 sLTP_shp_Q14; - opus_int32 LPC_exc_Q14; -} NSQ_sample_struct; - -typedef NSQ_sample_struct NSQ_sample_pair[ 2 ]; - -static OPUS_INLINE void silk_nsq_del_dec_scale_states_sse4_1( - const silk_encoder_state *psEncC, /* I Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ - const opus_int32 x_Q3[], /* I Input in Q3 */ - opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */ - const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ - opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ - opus_int subfr, /* I Subframe number */ - opus_int nStatesDelayedDecision, /* I Number of del dec states */ - const opus_int LTP_scale_Q14, /* I LTP state scaling */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ - const opus_int signal_type, /* I Signal type */ - const opus_int decisionDelay /* I Decision delay */ -); - -/******************************************/ -/* Noise shape quantizer for one subframe */ -/******************************************/ -static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1( - silk_nsq_state *NSQ, /* I/O NSQ state */ - NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ - opus_int signalType, /* I Signal type */ - const opus_int32 x_Q10[], /* I */ - opus_int8 pulses[], /* O */ - opus_int16 xq[], /* O */ - opus_int32 sLTP_Q15[], /* I/O LTP filter state */ - opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */ - 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 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 subfr, /* I Subframe number */ - opus_int shapingLPCOrder, /* I Shaping LPC filter order */ - opus_int predictLPCOrder, /* I Prediction filter order */ - opus_int warping_Q16, /* I */ - opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ - opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ - opus_int decisionDelay /* I */ -); - -void silk_NSQ_del_dec_sse4_1( - const silk_encoder_state *psEncC, /* I/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int32 x_Q3[], /* I Prefiltered input signal */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ - const opus_int16 AR2_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 */ -) -{ - opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr; - opus_int last_smple_idx, smpl_buf_idx, decisionDelay; - const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; - opus_int16 *pxq; - VARDECL( opus_int32, sLTP_Q15 ); - VARDECL( opus_int16, sLTP ); - opus_int32 HarmShapeFIRPacked_Q14; - opus_int offset_Q10; - opus_int32 RDmin_Q10, Gain_Q10; - VARDECL( opus_int32, x_sc_Q10 ); - VARDECL( opus_int32, delayedGain_Q10 ); - VARDECL( NSQ_del_dec_struct, psDelDec ); - NSQ_del_dec_struct *psDD; - SAVE_STACK; - - /* Set unvoiced lag to the previous one, overwrite later for voiced */ - lag = NSQ->lagPrev; - - silk_assert( NSQ->prev_gain_Q16 != 0 ); - - /* Initialize delayed decision states */ - ALLOC( psDelDec, psEncC->nStatesDelayedDecision, NSQ_del_dec_struct ); - silk_memset( psDelDec, 0, psEncC->nStatesDelayedDecision * sizeof( NSQ_del_dec_struct ) ); - for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) { - psDD = &psDelDec[ k ]; - psDD->Seed = ( k + psIndices->Seed ) & 3; - psDD->SeedInit = psDD->Seed; - psDD->RD_Q10 = 0; - psDD->LF_AR_Q14 = NSQ->sLF_AR_shp_Q14; - psDD->Shape_Q14[ 0 ] = NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ]; - silk_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); - silk_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) ); - } - - offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; - smpl_buf_idx = 0; /* index of oldest samples */ - - decisionDelay = silk_min_int( DECISION_DELAY, psEncC->subfr_length ); - - /* For voiced frames limit the decision delay to lower than the pitch lag */ - if( psIndices->signalType == TYPE_VOICED ) { - for( k = 0; k < psEncC->nb_subfr; k++ ) { - decisionDelay = silk_min_int( decisionDelay, pitchL[ k ] - LTP_ORDER / 2 - 1 ); - } - } else { - if( lag > 0 ) { - decisionDelay = silk_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 ); - } - } - - if( psIndices->NLSFInterpCoef_Q2 == 4 ) { - LSF_interpolation_flag = 0; - } else { - LSF_interpolation_flag = 1; - } - - ALLOC( sLTP_Q15, - psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 ); - ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 ); - ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 ); - ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 ); - /* Set up pointers to start of sub frame */ - pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; - NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; - NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; - subfr = 0; - for( k = 0; k < psEncC->nb_subfr; k++ ) { - A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ]; - B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; - AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; - - /* Noise shape parameters */ - silk_assert( HarmShapeGain_Q14[ k ] >= 0 ); - HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); - HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); - - NSQ->rewhite_flag = 0; - if( psIndices->signalType == TYPE_VOICED ) { - /* Voiced */ - lag = pitchL[ k ]; - - /* Re-whitening */ - if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { - if( k == 2 ) { - /* RESET DELAYED DECISIONS */ - /* Find winner */ - RDmin_Q10 = psDelDec[ 0 ].RD_Q10; - Winner_ind = 0; - for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) { - if( psDelDec[ i ].RD_Q10 < RDmin_Q10 ) { - RDmin_Q10 = psDelDec[ i ].RD_Q10; - Winner_ind = i; - } - } - for( i = 0; i < psEncC->nStatesDelayedDecision; i++ ) { - if( i != Winner_ind ) { - psDelDec[ i ].RD_Q10 += ( silk_int32_MAX >> 4 ); - silk_assert( psDelDec[ i ].RD_Q10 >= 0 ); - } - } - - /* Copy final part of signals from winner state to output and long-term filter states */ - psDD = &psDelDec[ Winner_ind ]; - last_smple_idx = smpl_buf_idx + decisionDelay; - for( i = 0; i < decisionDelay; i++ ) { - last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; - pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); - pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( - silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) ); - NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ]; - } - - subfr = 0; - } - - /* Rewhiten with new A coefs */ - start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; - silk_assert( start_idx > 0 ); - - silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], - A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch ); - - NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; - NSQ->rewhite_flag = 1; - } - } - - silk_nsq_del_dec_scale_states_sse4_1( psEncC, NSQ, psDelDec, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, - psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay ); - - silk_noise_shape_quantizer_del_dec_sse4_1( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, - delayedGain_Q10, A_Q12, B_Q14, AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], - Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder, - psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay ); - - x_Q3 += psEncC->subfr_length; - pulses += psEncC->subfr_length; - pxq += psEncC->subfr_length; - } - - /* Find winner */ - RDmin_Q10 = psDelDec[ 0 ].RD_Q10; - Winner_ind = 0; - for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) { - if( psDelDec[ k ].RD_Q10 < RDmin_Q10 ) { - RDmin_Q10 = psDelDec[ k ].RD_Q10; - Winner_ind = k; - } - } - - /* Copy final part of signals from winner state to output and long-term filter states */ - psDD = &psDelDec[ Winner_ind ]; - psIndices->Seed = psDD->SeedInit; - last_smple_idx = smpl_buf_idx + decisionDelay; - Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 ); - for( i = 0; i < decisionDelay; i++ ) { - last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; - pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); - pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( - silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) ); - NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ]; - } - silk_memcpy( NSQ->sLPC_Q14, &psDD->sLPC_Q14[ psEncC->subfr_length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); - silk_memcpy( NSQ->sAR2_Q14, psDD->sAR2_Q14, sizeof( psDD->sAR2_Q14 ) ); - - /* Update states */ - NSQ->sLF_AR_shp_Q14 = psDD->LF_AR_Q14; - NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; - - /* Save quantized speech signal */ - /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */ - silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); - silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); - RESTORE_STACK; -} - -/******************************************/ -/* Noise shape quantizer for one subframe */ -/******************************************/ -static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1( - silk_nsq_state *NSQ, /* I/O NSQ state */ - NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ - opus_int signalType, /* I Signal type */ - const opus_int32 x_Q10[], /* I */ - opus_int8 pulses[], /* O */ - opus_int16 xq[], /* O */ - opus_int32 sLTP_Q15[], /* I/O LTP filter state */ - opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */ - 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 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 subfr, /* I Subframe number */ - opus_int shapingLPCOrder, /* I Shaping LPC filter order */ - opus_int predictLPCOrder, /* I Prediction filter order */ - opus_int warping_Q16, /* I */ - opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ - opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ - opus_int decisionDelay /* I */ -) -{ - opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx; - opus_int32 Winner_rand_state; - opus_int32 LTP_pred_Q14, LPC_pred_Q14, n_AR_Q14, n_LTP_Q14; - opus_int32 n_LF_Q14, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10; - opus_int32 q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10; - opus_int32 tmp1, tmp2, sLF_AR_shp_Q14; - opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14; - VARDECL( NSQ_sample_pair, psSampleState ); - NSQ_del_dec_struct *psDD; - NSQ_sample_struct *psSS; - - __m128i a_Q12_0123, a_Q12_4567, a_Q12_89AB, a_Q12_CDEF; - __m128i b_Q12_0123, b_sr_Q12_0123; - SAVE_STACK; - - silk_assert( nStatesDelayedDecision > 0 ); - ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair ); - - shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; - pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; - Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 ); - - a_Q12_0123 = OP_CVTEPI16_EPI32_M64( a_Q12 ); - a_Q12_4567 = OP_CVTEPI16_EPI32_M64( a_Q12 + 4 ); - - if( opus_likely( predictLPCOrder == 16 ) ) { - a_Q12_89AB = OP_CVTEPI16_EPI32_M64( a_Q12 + 8 ); - a_Q12_CDEF = OP_CVTEPI16_EPI32_M64( a_Q12 + 12 ); - } - - if( signalType == TYPE_VOICED ){ - b_Q12_0123 = OP_CVTEPI16_EPI32_M64( b_Q14 ); - b_sr_Q12_0123 = _mm_shuffle_epi32( b_Q12_0123, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ - } - for( i = 0; i < length; i++ ) { - /* Perform common calculations used in all states */ - - /* Long-term prediction */ - if( signalType == TYPE_VOICED ) { - /* Unrolled loop */ - /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ - LTP_pred_Q14 = 2; - { - __m128i tmpa, tmpb, pred_lag_ptr_tmp; - pred_lag_ptr_tmp = _mm_loadu_si128( (__m128i *)(&pred_lag_ptr[ -3 ] ) ); - pred_lag_ptr_tmp = _mm_shuffle_epi32( pred_lag_ptr_tmp, 0x1B ); - tmpa = _mm_mul_epi32( pred_lag_ptr_tmp, b_Q12_0123 ); - tmpa = _mm_srli_si128( tmpa, 2 ); - - pred_lag_ptr_tmp = _mm_shuffle_epi32( pred_lag_ptr_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) );/* equal shift right 4 bytes */ - pred_lag_ptr_tmp = _mm_mul_epi32( pred_lag_ptr_tmp, b_sr_Q12_0123 ); - pred_lag_ptr_tmp = _mm_srli_si128( pred_lag_ptr_tmp, 2 ); - pred_lag_ptr_tmp = _mm_add_epi32( pred_lag_ptr_tmp, tmpa ); - - tmpb = _mm_shuffle_epi32( pred_lag_ptr_tmp, _MM_SHUFFLE( 0, 0, 3, 2 ) );/* equal shift right 8 bytes */ - pred_lag_ptr_tmp = _mm_add_epi32( pred_lag_ptr_tmp, tmpb ); - LTP_pred_Q14 += _mm_cvtsi128_si32( pred_lag_ptr_tmp ); - - LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); - LTP_pred_Q14 = silk_LSHIFT( LTP_pred_Q14, 1 ); /* Q13 -> Q14 */ - pred_lag_ptr++; - } - } else { - LTP_pred_Q14 = 0; - } - - /* Long-term shaping */ - if( lag > 0 ) { - /* Symmetric, packed FIR coefficients */ - n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); - n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); - n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */ - shp_lag_ptr++; - } else { - n_LTP_Q14 = 0; - } - { - __m128i tmpa, tmpb, psLPC_Q14_tmp, a_Q12_tmp; - - for( k = 0; k < nStatesDelayedDecision; k++ ) { - /* Delayed decision state */ - psDD = &psDelDec[ k ]; - - /* Sample state */ - psSS = psSampleState[ k ]; - - /* Generate dither */ - psDD->Seed = silk_RAND( psDD->Seed ); - - /* Pointer used in short term prediction and shaping */ - psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ]; - /* Short-term prediction */ - silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 ); - /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ - LPC_pred_Q14 = silk_RSHIFT( predictLPCOrder, 1 ); - - tmpb = _mm_setzero_si128(); - - /* step 1 */ - psLPC_Q14_tmp = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -3 ] ) ); /* -3, -2 , -1, 0 */ - psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, 0x1B ); /* 0, -1, -2, -3 */ - tmpa = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_0123 ); /* 0, -1, -2, -3 * 0123 -> 0*0, 2*-2 */ - - tmpa = _mm_srli_epi64( tmpa, 16 ); - tmpb = _mm_add_epi32( tmpb, tmpa ); - - psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ - a_Q12_tmp = _mm_shuffle_epi32( a_Q12_0123, _MM_SHUFFLE(0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ - psLPC_Q14_tmp = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_tmp ); /* 1*-1, 3*-3 */ - psLPC_Q14_tmp = _mm_srli_epi64( psLPC_Q14_tmp, 16 ); - tmpb = _mm_add_epi32( tmpb, psLPC_Q14_tmp ); - - /* step 2 */ - psLPC_Q14_tmp = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -7 ] ) ); - psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, 0x1B ); - tmpa = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_4567 ); - tmpa = _mm_srli_epi64( tmpa, 16 ); - tmpb = _mm_add_epi32( tmpb, tmpa ); - - psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ - a_Q12_tmp = _mm_shuffle_epi32( a_Q12_4567, _MM_SHUFFLE(0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ - psLPC_Q14_tmp = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_tmp ); - psLPC_Q14_tmp = _mm_srli_epi64( psLPC_Q14_tmp, 16 ); - tmpb = _mm_add_epi32( tmpb, psLPC_Q14_tmp ); - - if ( opus_likely( predictLPCOrder == 16 ) ) - { - /* step 3 */ - psLPC_Q14_tmp = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -11 ] ) ); - psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, 0x1B ); - tmpa = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_89AB ); - tmpa = _mm_srli_epi64( tmpa, 16 ); - tmpb = _mm_add_epi32( tmpb, tmpa ); - - psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ - a_Q12_tmp = _mm_shuffle_epi32( a_Q12_89AB, _MM_SHUFFLE(0, 3, 2, 1 ) );/* equal shift right 4 bytes */ - psLPC_Q14_tmp = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_tmp ); - psLPC_Q14_tmp = _mm_srli_epi64( psLPC_Q14_tmp, 16 ); - tmpb = _mm_add_epi32( tmpb, psLPC_Q14_tmp ); - - /* setp 4 */ - psLPC_Q14_tmp = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -15 ] ) ); - psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, 0x1B ); - tmpa = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_CDEF ); - tmpa = _mm_srli_epi64( tmpa, 16 ); - tmpb = _mm_add_epi32( tmpb, tmpa ); - - psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ - a_Q12_tmp = _mm_shuffle_epi32( a_Q12_CDEF, _MM_SHUFFLE(0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ - psLPC_Q14_tmp = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_tmp ); - psLPC_Q14_tmp = _mm_srli_epi64( psLPC_Q14_tmp, 16 ); - tmpb = _mm_add_epi32( tmpb, psLPC_Q14_tmp ); - - /* add at last */ - /* equal shift right 8 bytes*/ - tmpa = _mm_shuffle_epi32( tmpb, _MM_SHUFFLE( 0, 0, 3, 2 ) ); - tmpb = _mm_add_epi32( tmpb, tmpa ); - LPC_pred_Q14 += _mm_cvtsi128_si32( tmpb ); - } - else - { - /* add at last */ - tmpa = _mm_shuffle_epi32( tmpb, _MM_SHUFFLE( 0, 0, 3, 2 ) ); /* equal shift right 8 bytes*/ - tmpb = _mm_add_epi32( tmpb, tmpa ); - LPC_pred_Q14 += _mm_cvtsi128_si32( tmpb ); - - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -8 ], a_Q12[ 8 ] ); - LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); - } - - LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */ - - /* Noise shape feedback */ - silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ - /* Output of lowpass section */ - tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 ); - /* Output of allpass section */ - tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 ); - psDD->sAR2_Q14[ 0 ] = tmp2; - n_AR_Q14 = silk_RSHIFT( shapingLPCOrder, 1 ); - n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ 0 ] ); - /* Loop over allpass sections */ - for( j = 2; j < shapingLPCOrder; j += 2 ) { - /* Output of allpass section */ - tmp2 = silk_SMLAWB( psDD->sAR2_Q14[ j - 1 ], psDD->sAR2_Q14[ j + 0 ] - tmp1, warping_Q16 ); - psDD->sAR2_Q14[ j - 1 ] = tmp1; - n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ j - 1 ] ); - /* Output of allpass section */ - tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ j + 0 ], psDD->sAR2_Q14[ j + 1 ] - tmp2, warping_Q16 ); - psDD->sAR2_Q14[ j + 0 ] = tmp2; - n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ j ] ); - } - psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1; - n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] ); - - n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 1 ); /* Q11 -> Q12 */ - n_AR_Q14 = silk_SMLAWB( n_AR_Q14, psDD->LF_AR_Q14, Tilt_Q14 ); /* Q12 */ - n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 2 ); /* Q12 -> Q14 */ - - n_LF_Q14 = silk_SMULWB( psDD->Shape_Q14[ *smpl_buf_idx ], LF_shp_Q14 ); /* Q12 */ - n_LF_Q14 = silk_SMLAWT( n_LF_Q14, psDD->LF_AR_Q14, LF_shp_Q14 ); /* Q12 */ - n_LF_Q14 = silk_LSHIFT( n_LF_Q14, 2 ); /* Q12 -> Q14 */ - - /* Input minus prediction plus noise feedback */ - /* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */ - tmp1 = silk_ADD32( n_AR_Q14, n_LF_Q14 ); /* Q14 */ - tmp2 = silk_ADD32( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */ - tmp1 = silk_SUB32( tmp2, tmp1 ); /* Q13 */ - tmp1 = silk_RSHIFT_ROUND( tmp1, 4 ); /* Q10 */ - - r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */ - - /* Flip sign depending on dither */ - if ( psDD->Seed < 0 ) { - r_Q10 = -r_Q10; - } - r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 ); - - /* Find two quantization level candidates and measure their rate-distortion */ - q1_Q10 = silk_SUB32( r_Q10, offset_Q10 ); - q1_Q0 = silk_RSHIFT( q1_Q10, 10 ); - if( q1_Q0 > 0 ) { - q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); - q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); - q2_Q10 = silk_ADD32( q1_Q10, 1024 ); - rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 ); - rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); - } else if( q1_Q0 == 0 ) { - q1_Q10 = offset_Q10; - q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); - rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 ); - rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); - } else if( q1_Q0 == -1 ) { - q2_Q10 = offset_Q10; - q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); - rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); - rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); - } else { /* q1_Q0 < -1 */ - q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); - q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); - q2_Q10 = silk_ADD32( q1_Q10, 1024 ); - rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); - rd2_Q10 = silk_SMULBB( -q2_Q10, Lambda_Q10 ); - } - rr_Q10 = silk_SUB32( r_Q10, q1_Q10 ); - rd1_Q10 = silk_RSHIFT( silk_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 ); - rr_Q10 = silk_SUB32( r_Q10, q2_Q10 ); - rd2_Q10 = silk_RSHIFT( silk_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 ); - - if( rd1_Q10 < rd2_Q10 ) { - psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 ); - psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 ); - psSS[ 0 ].Q_Q10 = q1_Q10; - psSS[ 1 ].Q_Q10 = q2_Q10; - } else { - psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 ); - psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 ); - psSS[ 0 ].Q_Q10 = q2_Q10; - psSS[ 1 ].Q_Q10 = q1_Q10; - } - - /* Update states for best quantization */ - - /* Quantized excitation */ - exc_Q14 = silk_LSHIFT32( psSS[ 0 ].Q_Q10, 4 ); - if ( psDD->Seed < 0 ) { - exc_Q14 = -exc_Q14; - } - - /* Add predictions */ - LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 ); - xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 ); - - /* Update states */ - sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 ); - psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 ); - psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14; - psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14; - psSS[ 0 ].xq_Q14 = xq_Q14; - - /* Update states for second best quantization */ - - /* Quantized excitation */ - exc_Q14 = silk_LSHIFT32( psSS[ 1 ].Q_Q10, 4 ); - if ( psDD->Seed < 0 ) { - exc_Q14 = -exc_Q14; - } - - - /* Add predictions */ - LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 ); - xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 ); - - /* Update states */ - sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 ); - psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 ); - psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14; - psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14; - psSS[ 1 ].xq_Q14 = xq_Q14; - } - } - *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */ - last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */ - - /* Find winner */ - RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; - Winner_ind = 0; - for( k = 1; k < nStatesDelayedDecision; k++ ) { - if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) { - RDmin_Q10 = psSampleState[ k ][ 0 ].RD_Q10; - Winner_ind = k; - } - } - - /* Increase RD values of expired states */ - Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ]; - for( k = 0; k < nStatesDelayedDecision; k++ ) { - if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) { - psSampleState[ k ][ 0 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 0 ].RD_Q10, silk_int32_MAX >> 4 ); - psSampleState[ k ][ 1 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 1 ].RD_Q10, silk_int32_MAX >> 4 ); - silk_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 ); - } - } - - /* Find worst in first set and best in second set */ - RDmax_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; - RDmin_Q10 = psSampleState[ 0 ][ 1 ].RD_Q10; - RDmax_ind = 0; - RDmin_ind = 0; - for( k = 1; k < nStatesDelayedDecision; k++ ) { - /* find worst in first set */ - if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) { - RDmax_Q10 = psSampleState[ k ][ 0 ].RD_Q10; - RDmax_ind = k; - } - /* find best in second set */ - if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) { - RDmin_Q10 = psSampleState[ k ][ 1 ].RD_Q10; - RDmin_ind = k; - } - } - - /* Replace a state if best from second set outperforms worst in first set */ - if( RDmin_Q10 < RDmax_Q10 ) { - silk_memcpy( ( (opus_int32 *)&psDelDec[ RDmax_ind ] ) + i, - ( (opus_int32 *)&psDelDec[ RDmin_ind ] ) + i, sizeof( NSQ_del_dec_struct ) - i * sizeof( opus_int32) ); - silk_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) ); - } - - /* Write samples from winner to output and long-term filter states */ - psDD = &psDelDec[ Winner_ind ]; - if( subfr > 0 || i >= decisionDelay ) { - pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); - xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( - silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], delayedGain_Q10[ last_smple_idx ] ), 8 ) ); - NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q14[ last_smple_idx ]; - sLTP_Q15[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q15[ last_smple_idx ]; - } - NSQ->sLTP_shp_buf_idx++; - NSQ->sLTP_buf_idx++; - - /* Update states */ - for( k = 0; k < nStatesDelayedDecision; k++ ) { - psDD = &psDelDec[ k ]; - psSS = &psSampleState[ k ][ 0 ]; - psDD->LF_AR_Q14 = psSS->LF_AR_Q14; - psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14; - psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14; - psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10; - psDD->Pred_Q15[ *smpl_buf_idx ] = silk_LSHIFT32( psSS->LPC_exc_Q14, 1 ); - psDD->Shape_Q14[ *smpl_buf_idx ] = psSS->sLTP_shp_Q14; - psDD->Seed = silk_ADD32_ovflw( psDD->Seed, silk_RSHIFT_ROUND( psSS->Q_Q10, 10 ) ); - psDD->RandState[ *smpl_buf_idx ] = psDD->Seed; - psDD->RD_Q10 = psSS->RD_Q10; - } - delayedGain_Q10[ *smpl_buf_idx ] = Gain_Q10; - } - /* Update LPC states */ - for( k = 0; k < nStatesDelayedDecision; k++ ) { - psDD = &psDelDec[ k ]; - silk_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); - } - RESTORE_STACK; -} - -static OPUS_INLINE void silk_nsq_del_dec_scale_states_sse4_1( - const silk_encoder_state *psEncC, /* I Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ - const opus_int32 x_Q3[], /* I Input in Q3 */ - opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */ - const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ - opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ - opus_int subfr, /* I Subframe number */ - opus_int nStatesDelayedDecision, /* I Number of del dec states */ - const opus_int LTP_scale_Q14, /* I LTP state scaling */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ - const opus_int signal_type, /* I Signal type */ - const opus_int decisionDelay /* I Decision delay */ -) -{ - opus_int i, k, lag; - opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23; - NSQ_del_dec_struct *psDD; - __m128i xmm_inv_gain_Q23, xmm_x_Q3_x2x0, xmm_x_Q3_x3x1; - - lag = pitchL[ subfr ]; - inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 ); - - silk_assert( inv_gain_Q31 != 0 ); - - /* Calculate gain adjustment factor */ - if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) { - gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 ); - } else { - gain_adj_Q16 = (opus_int32)1 << 16; - } - - /* Scale input */ - inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 ); - - /* prepare inv_gain_Q23 in packed 4 32-bits */ - xmm_inv_gain_Q23 = _mm_set1_epi32(inv_gain_Q23); - - for( i = 0; i < psEncC->subfr_length - 3; i += 4 ) { - xmm_x_Q3_x2x0 = _mm_loadu_si128( (__m128i *)(&(x_Q3[ i ] ) ) ); - /* equal shift right 4 bytes*/ - xmm_x_Q3_x3x1 = _mm_shuffle_epi32( xmm_x_Q3_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) ); - - xmm_x_Q3_x2x0 = _mm_mul_epi32( xmm_x_Q3_x2x0, xmm_inv_gain_Q23 ); - xmm_x_Q3_x3x1 = _mm_mul_epi32( xmm_x_Q3_x3x1, xmm_inv_gain_Q23 ); - - xmm_x_Q3_x2x0 = _mm_srli_epi64( xmm_x_Q3_x2x0, 16 ); - xmm_x_Q3_x3x1 = _mm_slli_epi64( xmm_x_Q3_x3x1, 16 ); - - xmm_x_Q3_x2x0 = _mm_blend_epi16( xmm_x_Q3_x2x0, xmm_x_Q3_x3x1, 0xCC ); - - _mm_storeu_si128( (__m128i *)(&(x_sc_Q10[ i ])), xmm_x_Q3_x2x0 ); - } - - for( ; i < psEncC->subfr_length; i++ ) { - x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 ); - } - - /* Save inverse gain */ - NSQ->prev_gain_Q16 = Gains_Q16[ subfr ]; - - /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ - if( NSQ->rewhite_flag ) { - if( subfr == 0 ) { - /* Do LTP downscaling */ - inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 ); - } - for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { - silk_assert( i < MAX_FRAME_LENGTH ); - sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] ); - } - } - - /* Adjust for changing gain */ - if( gain_adj_Q16 != (opus_int32)1 << 16 ) { - /* Scale long-term shaping state */ - { - __m128i xmm_gain_adj_Q16, xmm_sLTP_shp_Q14_x2x0, xmm_sLTP_shp_Q14_x3x1; - - /* prepare gain_adj_Q16 in packed 4 32-bits */ - xmm_gain_adj_Q16 = _mm_set1_epi32( gain_adj_Q16 ); - - for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx - 3; i += 4 ) - { - xmm_sLTP_shp_Q14_x2x0 = _mm_loadu_si128( (__m128i *)(&(NSQ->sLTP_shp_Q14[ i ] ) ) ); - /* equal shift right 4 bytes*/ - xmm_sLTP_shp_Q14_x3x1 = _mm_shuffle_epi32( xmm_sLTP_shp_Q14_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) ); - - xmm_sLTP_shp_Q14_x2x0 = _mm_mul_epi32( xmm_sLTP_shp_Q14_x2x0, xmm_gain_adj_Q16 ); - xmm_sLTP_shp_Q14_x3x1 = _mm_mul_epi32( xmm_sLTP_shp_Q14_x3x1, xmm_gain_adj_Q16 ); - - xmm_sLTP_shp_Q14_x2x0 = _mm_srli_epi64( xmm_sLTP_shp_Q14_x2x0, 16 ); - xmm_sLTP_shp_Q14_x3x1 = _mm_slli_epi64( xmm_sLTP_shp_Q14_x3x1, 16 ); - - xmm_sLTP_shp_Q14_x2x0 = _mm_blend_epi16( xmm_sLTP_shp_Q14_x2x0, xmm_sLTP_shp_Q14_x3x1, 0xCC ); - - _mm_storeu_si128( (__m128i *)(&(NSQ->sLTP_shp_Q14[ i ] ) ), xmm_sLTP_shp_Q14_x2x0 ); - } - - for( ; i < NSQ->sLTP_shp_buf_idx; i++ ) { - NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] ); - } - - /* Scale long-term prediction state */ - if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) { - for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) { - sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] ); - } - } - - for( k = 0; k < nStatesDelayedDecision; k++ ) { - psDD = &psDelDec[ k ]; - - /* Scale scalar states */ - psDD->LF_AR_Q14 = silk_SMULWW( gain_adj_Q16, psDD->LF_AR_Q14 ); - - /* Scale short-term prediction and shaping states */ - for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { - psDD->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sLPC_Q14[ i ] ); - } - for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { - psDD->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sAR2_Q14[ i ] ); - } - for( i = 0; i < DECISION_DELAY; i++ ) { - psDD->Pred_Q15[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Pred_Q15[ i ] ); - psDD->Shape_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Shape_Q14[ i ] ); - } - } - } - } -} diff --git a/drivers/opus/silk/x86/NSQ_sse.c b/drivers/opus/silk/x86/NSQ_sse.c deleted file mode 100644 index ac0fa1ab04..0000000000 --- a/drivers/opus/silk/x86/NSQ_sse.c +++ /dev/null @@ -1,717 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include <xmmintrin.h> -#include <emmintrin.h> -#include <smmintrin.h> -#include "opus/silk/main.h" -#include "opus/celt/x86/x86cpu.h" -#include "opus/celt/stack_alloc.h" - -static OPUS_INLINE void silk_nsq_scale_states_sse4_1( - const silk_encoder_state *psEncC, /* I Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - const opus_int32 x_Q3[], /* I input in Q3 */ - opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */ - const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */ - opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ - opus_int subfr, /* I subframe number */ - const opus_int LTP_scale_Q14, /* I */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ - const opus_int signal_type /* I Signal type */ -); - -static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1( - 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 offset_Q10, /* I */ - opus_int length, /* I Input length */ - opus_int32 table[][4] /* I */ -); - -void silk_NSQ_sse4_1( - const silk_encoder_state *psEncC, /* I/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int32 x_Q3[], /* I Prefiltered input signal */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ - const opus_int16 AR2_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 */ -) -{ - opus_int k, lag, start_idx, LSF_interpolation_flag; - const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; - opus_int16 *pxq; - VARDECL( opus_int32, sLTP_Q15 ); - VARDECL( opus_int16, sLTP ); - opus_int32 HarmShapeFIRPacked_Q14; - opus_int offset_Q10; - VARDECL( opus_int32, x_sc_Q10 ); - - opus_int32 table[ 64 ][ 4 ]; - opus_int32 tmp1; - opus_int32 q1_Q10, q2_Q10, rd1_Q20, rd2_Q20; - - SAVE_STACK; - - NSQ->rand_seed = psIndices->Seed; - - /* Set unvoiced lag to the previous one, overwrite later for voiced */ - lag = NSQ->lagPrev; - - silk_assert( NSQ->prev_gain_Q16 != 0 ); - - offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; - - /* 0 */ - q1_Q10 = offset_Q10; - q2_Q10 = offset_Q10 + ( 1024 - QUANT_LEVEL_ADJUST_Q10 ); - rd1_Q20 = q1_Q10 * Lambda_Q10; - rd2_Q20 = q2_Q10 * Lambda_Q10; - - table[ 32 ][ 0 ] = q1_Q10; - table[ 32 ][ 1 ] = q2_Q10; - table[ 32 ][ 2 ] = 2 * (q1_Q10 - q2_Q10); - table[ 32 ][ 3 ] = (rd1_Q20 - rd2_Q20) + (q1_Q10 * q1_Q10 - q2_Q10 * q2_Q10); - - /* -1 */ - q1_Q10 = offset_Q10 - ( 1024 - QUANT_LEVEL_ADJUST_Q10 ); - q2_Q10 = offset_Q10; - rd1_Q20 = - q1_Q10 * Lambda_Q10; - rd2_Q20 = q2_Q10 * Lambda_Q10; - - table[ 31 ][ 0 ] = q1_Q10; - table[ 31 ][ 1 ] = q2_Q10; - table[ 31 ][ 2 ] = 2 * (q1_Q10 - q2_Q10); - table[ 31 ][ 3 ] = (rd1_Q20 - rd2_Q20) + (q1_Q10 * q1_Q10 - q2_Q10 * q2_Q10); - - /* > 0 */ - for (k = 1; k <= 31; k++) - { - tmp1 = offset_Q10 + silk_LSHIFT( k, 10 ); - - q1_Q10 = tmp1 - QUANT_LEVEL_ADJUST_Q10; - q2_Q10 = tmp1 - QUANT_LEVEL_ADJUST_Q10 + 1024; - rd1_Q20 = q1_Q10 * Lambda_Q10; - rd2_Q20 = q2_Q10 * Lambda_Q10; - - table[ 32 + k ][ 0 ] = q1_Q10; - table[ 32 + k ][ 1 ] = q2_Q10; - table[ 32 + k ][ 2 ] = 2 * (q1_Q10 - q2_Q10); - table[ 32 + k ][ 3 ] = (rd1_Q20 - rd2_Q20) + (q1_Q10 * q1_Q10 - q2_Q10 * q2_Q10); - } - - /* < -1 */ - for (k = -32; k <= -2; k++) - { - tmp1 = offset_Q10 + silk_LSHIFT( k, 10 ); - - q1_Q10 = tmp1 + QUANT_LEVEL_ADJUST_Q10; - q2_Q10 = tmp1 + QUANT_LEVEL_ADJUST_Q10 + 1024; - rd1_Q20 = - q1_Q10 * Lambda_Q10; - rd2_Q20 = - q2_Q10 * Lambda_Q10; - - table[ 32 + k ][ 0 ] = q1_Q10; - table[ 32 + k ][ 1 ] = q2_Q10; - table[ 32 + k ][ 2 ] = 2 * (q1_Q10 - q2_Q10); - table[ 32 + k ][ 3 ] = (rd1_Q20 - rd2_Q20) + (q1_Q10 * q1_Q10 - q2_Q10 * q2_Q10); - } - - if( psIndices->NLSFInterpCoef_Q2 == 4 ) { - LSF_interpolation_flag = 0; - } else { - LSF_interpolation_flag = 1; - } - - ALLOC( sLTP_Q15, - psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 ); - ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 ); - ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 ); - /* Set up pointers to start of sub frame */ - NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; - NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; - pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; - for( k = 0; k < psEncC->nb_subfr; k++ ) { - A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ]; - B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; - AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; - - /* Noise shape parameters */ - silk_assert( HarmShapeGain_Q14[ k ] >= 0 ); - HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); - HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); - - NSQ->rewhite_flag = 0; - if( psIndices->signalType == TYPE_VOICED ) { - /* Voiced */ - lag = pitchL[ k ]; - - /* Re-whitening */ - if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { - /* Rewhiten with new A coefs */ - start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; - silk_assert( start_idx > 0 ); - - silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], - A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch ); - - NSQ->rewhite_flag = 1; - NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; - } - } - - silk_nsq_scale_states_sse4_1( psEncC, NSQ, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType ); - - if ( opus_likely( ( 10 == psEncC->shapingLPCOrder ) && ( 16 == psEncC->predictLPCOrder) ) ) - { - silk_noise_shape_quantizer_10_16_sse4_1( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14, - AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], - offset_Q10, psEncC->subfr_length, &(table[32]) ); - } - else - { - silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14, - AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10, - offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder ); - } - - x_Q3 += psEncC->subfr_length; - pulses += psEncC->subfr_length; - pxq += psEncC->subfr_length; - } - - /* Update lagPrev for next frame */ - NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; - - /* Save quantized speech and noise shaping signals */ - /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */ - silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); - silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); - RESTORE_STACK; -} - -/***********************************/ -/* silk_noise_shape_quantizer_10_16 */ -/***********************************/ -static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1( - 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 offset_Q10, /* I */ - opus_int length, /* I Input length */ - opus_int32 table[][4] /* I */ -) -{ - opus_int i; - opus_int32 LTP_pred_Q13, LPC_pred_Q10, n_AR_Q12, n_LTP_Q13; - opus_int32 n_LF_Q12, r_Q10, q1_Q0, q1_Q10, q2_Q10; - opus_int32 exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10; - opus_int32 tmp1, tmp2, sLF_AR_shp_Q14; - opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr; - - __m128i xmm_tempa, xmm_tempb; - - __m128i xmm_one; - - __m128i psLPC_Q14_hi_01234567, psLPC_Q14_hi_89ABCDEF; - __m128i psLPC_Q14_lo_01234567, psLPC_Q14_lo_89ABCDEF; - __m128i a_Q12_01234567, a_Q12_89ABCDEF; - - __m128i sAR2_Q14_hi_76543210, sAR2_Q14_lo_76543210; - __m128i AR_shp_Q13_76543210; - - shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; - pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; - Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 ); - - /* Set up short term AR state */ - psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ]; - - sLF_AR_shp_Q14 = NSQ->sLF_AR_shp_Q14; - xq_Q14 = psLPC_Q14[ 0 ]; - LTP_pred_Q13 = 0; - - /* load a_Q12 */ - xmm_one = _mm_set_epi8( 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 ); - - /* load a_Q12[0] - a_Q12[7] */ - a_Q12_01234567 = _mm_loadu_si128( (__m128i *)(&a_Q12[ 0 ] ) ); - /* load a_Q12[ 8 ] - a_Q12[ 15 ] */ - a_Q12_89ABCDEF = _mm_loadu_si128( (__m128i *)(&a_Q12[ 8 ] ) ); - - a_Q12_01234567 = _mm_shuffle_epi8( a_Q12_01234567, xmm_one ); - a_Q12_89ABCDEF = _mm_shuffle_epi8( a_Q12_89ABCDEF, xmm_one ); - - /* load AR_shp_Q13 */ - AR_shp_Q13_76543210 = _mm_loadu_si128( (__m128i *)(&AR_shp_Q13[0] ) ); - - /* load psLPC_Q14 */ - xmm_one = _mm_set_epi8(15, 14, 11, 10, 7, 6, 3, 2, 13, 12, 9, 8, 5, 4, 1, 0 ); - - xmm_tempa = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[-16]) ); - xmm_tempb = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[-12]) ); - - xmm_tempa = _mm_shuffle_epi8( xmm_tempa, xmm_one ); - xmm_tempb = _mm_shuffle_epi8( xmm_tempb, xmm_one ); - - psLPC_Q14_hi_89ABCDEF = _mm_unpackhi_epi64( xmm_tempa, xmm_tempb ); - psLPC_Q14_lo_89ABCDEF = _mm_unpacklo_epi64( xmm_tempa, xmm_tempb ); - - xmm_tempa = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -8 ]) ); - xmm_tempb = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -4 ]) ); - - xmm_tempa = _mm_shuffle_epi8( xmm_tempa, xmm_one ); - xmm_tempb = _mm_shuffle_epi8( xmm_tempb, xmm_one ); - - psLPC_Q14_hi_01234567 = _mm_unpackhi_epi64( xmm_tempa, xmm_tempb ); - psLPC_Q14_lo_01234567 = _mm_unpacklo_epi64( xmm_tempa, xmm_tempb ); - - /* load sAR2_Q14 */ - xmm_tempa = _mm_loadu_si128( (__m128i *)(&(NSQ->sAR2_Q14[ 0 ]) ) ); - xmm_tempb = _mm_loadu_si128( (__m128i *)(&(NSQ->sAR2_Q14[ 4 ]) ) ); - - xmm_tempa = _mm_shuffle_epi8( xmm_tempa, xmm_one ); - xmm_tempb = _mm_shuffle_epi8( xmm_tempb, xmm_one ); - - sAR2_Q14_hi_76543210 = _mm_unpackhi_epi64( xmm_tempa, xmm_tempb ); - sAR2_Q14_lo_76543210 = _mm_unpacklo_epi64( xmm_tempa, xmm_tempb ); - - /* prepare 1 in 8 * 16bit */ - xmm_one = _mm_set1_epi16(1); - - for( i = 0; i < length; i++ ) - { - /* Short-term prediction */ - __m128i xmm_hi_07, xmm_hi_8F, xmm_lo_07, xmm_lo_8F; - - /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ - LPC_pred_Q10 = 8; /* silk_RSHIFT( predictLPCOrder, 1 ); */ - - /* shift psLPC_Q14 */ - psLPC_Q14_hi_89ABCDEF = _mm_alignr_epi8( psLPC_Q14_hi_01234567, psLPC_Q14_hi_89ABCDEF, 2 ); - psLPC_Q14_lo_89ABCDEF = _mm_alignr_epi8( psLPC_Q14_lo_01234567, psLPC_Q14_lo_89ABCDEF, 2 ); - - psLPC_Q14_hi_01234567 = _mm_srli_si128( psLPC_Q14_hi_01234567, 2 ); - psLPC_Q14_lo_01234567 = _mm_srli_si128( psLPC_Q14_lo_01234567, 2 ); - - psLPC_Q14_hi_01234567 = _mm_insert_epi16( psLPC_Q14_hi_01234567, (xq_Q14 >> 16), 7 ); - psLPC_Q14_lo_01234567 = _mm_insert_epi16( psLPC_Q14_lo_01234567, (xq_Q14), 7 ); - - /* high part, use pmaddwd, results in 4 32-bit */ - xmm_hi_07 = _mm_madd_epi16( psLPC_Q14_hi_01234567, a_Q12_01234567 ); - xmm_hi_8F = _mm_madd_epi16( psLPC_Q14_hi_89ABCDEF, a_Q12_89ABCDEF ); - - /* low part, use pmulhw, results in 8 16-bit, note we need simulate unsigned * signed, _mm_srai_epi16(psLPC_Q14_lo_01234567, 15) */ - xmm_tempa = _mm_cmpgt_epi16( _mm_setzero_si128(), psLPC_Q14_lo_01234567 ); - xmm_tempb = _mm_cmpgt_epi16( _mm_setzero_si128(), psLPC_Q14_lo_89ABCDEF ); - - xmm_tempa = _mm_and_si128( xmm_tempa, a_Q12_01234567 ); - xmm_tempb = _mm_and_si128( xmm_tempb, a_Q12_89ABCDEF ); - - xmm_lo_07 = _mm_mulhi_epi16( psLPC_Q14_lo_01234567, a_Q12_01234567 ); - xmm_lo_8F = _mm_mulhi_epi16( psLPC_Q14_lo_89ABCDEF, a_Q12_89ABCDEF ); - - xmm_lo_07 = _mm_add_epi16( xmm_lo_07, xmm_tempa ); - xmm_lo_8F = _mm_add_epi16( xmm_lo_8F, xmm_tempb ); - - xmm_lo_07 = _mm_madd_epi16( xmm_lo_07, xmm_one ); - xmm_lo_8F = _mm_madd_epi16( xmm_lo_8F, xmm_one ); - - /* accumulate */ - xmm_hi_07 = _mm_add_epi32( xmm_hi_07, xmm_hi_8F ); - xmm_lo_07 = _mm_add_epi32( xmm_lo_07, xmm_lo_8F ); - - xmm_hi_07 = _mm_add_epi32( xmm_hi_07, xmm_lo_07 ); - - xmm_hi_07 = _mm_add_epi32( xmm_hi_07, _mm_unpackhi_epi64(xmm_hi_07, xmm_hi_07 ) ); - xmm_hi_07 = _mm_add_epi32( xmm_hi_07, _mm_shufflelo_epi16(xmm_hi_07, 0x0E ) ); - - LPC_pred_Q10 += _mm_cvtsi128_si32( xmm_hi_07 ); - - /* Long-term prediction */ - if ( opus_likely( signalType == TYPE_VOICED ) ) { - /* Unrolled loop */ - /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ - LTP_pred_Q13 = 2; - { - __m128i b_Q14_3210, b_Q14_0123, pred_lag_ptr_0123; - - b_Q14_3210 = OP_CVTEPI16_EPI32_M64( b_Q14 ); - b_Q14_0123 = _mm_shuffle_epi32( b_Q14_3210, 0x1B ); - - /* loaded: [0] [-1] [-2] [-3] */ - pred_lag_ptr_0123 = _mm_loadu_si128( (__m128i *)(&pred_lag_ptr[ -3 ] ) ); - /* shuffle to [-3] [-2] [-1] [0] and to new xmm */ - xmm_tempa = _mm_shuffle_epi32( pred_lag_ptr_0123, 0x1B ); - /*64-bit multiply, a[2] * b[-2], a[0] * b[0] */ - xmm_tempa = _mm_mul_epi32( xmm_tempa, b_Q14_3210 ); - /* right shift 2 bytes (16 bits), zero extended */ - xmm_tempa = _mm_srli_si128( xmm_tempa, 2 ); - - /* a[1] * b[-1], a[3] * b[-3] */ - pred_lag_ptr_0123 = _mm_mul_epi32( pred_lag_ptr_0123, b_Q14_0123 ); - pred_lag_ptr_0123 = _mm_srli_si128( pred_lag_ptr_0123, 2 ); - - pred_lag_ptr_0123 = _mm_add_epi32( pred_lag_ptr_0123, xmm_tempa ); - /* equal shift right 8 bytes*/ - xmm_tempa = _mm_shuffle_epi32( pred_lag_ptr_0123, _MM_SHUFFLE( 0, 0, 3, 2 ) ); - xmm_tempa = _mm_add_epi32( xmm_tempa, pred_lag_ptr_0123 ); - - LTP_pred_Q13 += _mm_cvtsi128_si32( xmm_tempa ); - - LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); - pred_lag_ptr++; - } - } - - /* Noise shape feedback */ - NSQ->sAR2_Q14[ 9 ] = NSQ->sAR2_Q14[ 8 ]; - NSQ->sAR2_Q14[ 8 ] = _mm_cvtsi128_si32( _mm_srli_si128(_mm_unpackhi_epi16( sAR2_Q14_lo_76543210, sAR2_Q14_hi_76543210 ), 12 ) ); - - sAR2_Q14_hi_76543210 = _mm_slli_si128( sAR2_Q14_hi_76543210, 2 ); - sAR2_Q14_lo_76543210 = _mm_slli_si128( sAR2_Q14_lo_76543210, 2 ); - - sAR2_Q14_hi_76543210 = _mm_insert_epi16( sAR2_Q14_hi_76543210, (xq_Q14 >> 16), 0 ); - sAR2_Q14_lo_76543210 = _mm_insert_epi16( sAR2_Q14_lo_76543210, (xq_Q14), 0 ); - - /* high part, use pmaddwd, results in 4 32-bit */ - xmm_hi_07 = _mm_madd_epi16( sAR2_Q14_hi_76543210, AR_shp_Q13_76543210 ); - - /* low part, use pmulhw, results in 8 16-bit, note we need simulate unsigned * signed,_mm_srai_epi16(sAR2_Q14_lo_76543210, 15) */ - xmm_tempa = _mm_cmpgt_epi16( _mm_setzero_si128(), sAR2_Q14_lo_76543210 ); - xmm_tempa = _mm_and_si128( xmm_tempa, AR_shp_Q13_76543210 ); - - xmm_lo_07 = _mm_mulhi_epi16( sAR2_Q14_lo_76543210, AR_shp_Q13_76543210 ); - xmm_lo_07 = _mm_add_epi16( xmm_lo_07, xmm_tempa ); - - xmm_lo_07 = _mm_madd_epi16( xmm_lo_07, xmm_one ); - - /* accumulate */ - xmm_hi_07 = _mm_add_epi32( xmm_hi_07, xmm_lo_07 ); - - xmm_hi_07 = _mm_add_epi32( xmm_hi_07, _mm_unpackhi_epi64(xmm_hi_07, xmm_hi_07 ) ); - xmm_hi_07 = _mm_add_epi32( xmm_hi_07, _mm_shufflelo_epi16(xmm_hi_07, 0x0E ) ); - - n_AR_Q12 = 5 + _mm_cvtsi128_si32( xmm_hi_07 ); - - n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sAR2_Q14[ 8 ], AR_shp_Q13[ 8 ] ); - n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sAR2_Q14[ 9 ], AR_shp_Q13[ 9 ] ); - - n_AR_Q12 = silk_LSHIFT32( n_AR_Q12, 1 ); /* Q11 -> Q12 */ - n_AR_Q12 = silk_SMLAWB( n_AR_Q12, sLF_AR_shp_Q14, Tilt_Q14 ); - - n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 ); - n_LF_Q12 = silk_SMLAWT( n_LF_Q12, sLF_AR_shp_Q14, LF_shp_Q14 ); - - silk_assert( lag > 0 || signalType != TYPE_VOICED ); - - /* Combine prediction and noise shaping signals */ - tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */ - tmp1 = silk_SUB32( tmp1, n_LF_Q12 ); /* Q12 */ - if( lag > 0 ) { - /* Symmetric, packed FIR coefficients */ - n_LTP_Q13 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); - n_LTP_Q13 = silk_SMLAWT( n_LTP_Q13, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); - n_LTP_Q13 = silk_LSHIFT( n_LTP_Q13, 1 ); - shp_lag_ptr++; - - tmp2 = silk_SUB32( LTP_pred_Q13, n_LTP_Q13 ); /* Q13 */ - tmp1 = silk_ADD_LSHIFT32( tmp2, tmp1, 1 ); /* Q13 */ - tmp1 = silk_RSHIFT_ROUND( tmp1, 3 ); /* Q10 */ - } else { - tmp1 = silk_RSHIFT_ROUND( tmp1, 2 ); /* Q10 */ - } - - r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */ - - /* Generate dither */ - NSQ->rand_seed = silk_RAND( NSQ->rand_seed ); - - /* Flip sign depending on dither */ - tmp2 = -r_Q10; - if ( NSQ->rand_seed < 0 ) r_Q10 = tmp2; - - r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 ); - - /* Find two quantization level candidates and measure their rate-distortion */ - q1_Q10 = silk_SUB32( r_Q10, offset_Q10 ); - q1_Q0 = silk_RSHIFT( q1_Q10, 10 ); - - q1_Q10 = table[q1_Q0][0]; - q2_Q10 = table[q1_Q0][1]; - - if (r_Q10 * table[q1_Q0][2] - table[q1_Q0][3] < 0) - { - q1_Q10 = q2_Q10; - } - - pulses[ i ] = (opus_int8)silk_RSHIFT_ROUND( q1_Q10, 10 ); - - /* Excitation */ - exc_Q14 = silk_LSHIFT( q1_Q10, 4 ); - - tmp2 = -exc_Q14; - if ( NSQ->rand_seed < 0 ) exc_Q14 = tmp2; - - /* Add predictions */ - LPC_exc_Q14 = silk_ADD_LSHIFT32( exc_Q14, LTP_pred_Q13, 1 ); - xq_Q14 = silk_ADD_LSHIFT32( LPC_exc_Q14, LPC_pred_Q10, 4 ); - - /* Update states */ - psLPC_Q14++; - *psLPC_Q14 = xq_Q14; - sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, n_AR_Q12, 2 ); - - NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 ); - sLTP_Q15[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q14, 1 ); - NSQ->sLTP_shp_buf_idx++; - NSQ->sLTP_buf_idx++; - - /* Make dither dependent on quantized signal */ - NSQ->rand_seed = silk_ADD32_ovflw( NSQ->rand_seed, pulses[ i ] ); - } - - NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14; - - /* Scale XQ back to normal level before saving */ - psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH ]; - - /* write back sAR2_Q14 */ - xmm_tempa = _mm_unpackhi_epi16( sAR2_Q14_lo_76543210, sAR2_Q14_hi_76543210 ); - xmm_tempb = _mm_unpacklo_epi16( sAR2_Q14_lo_76543210, sAR2_Q14_hi_76543210 ); - _mm_storeu_si128( (__m128i *)(&NSQ->sAR2_Q14[ 4 ]), xmm_tempa ); - _mm_storeu_si128( (__m128i *)(&NSQ->sAR2_Q14[ 0 ]), xmm_tempb ); - - /* xq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( psLPC_Q14[ i ], Gain_Q10 ), 8 ) ); */ - { - __m128i xmm_Gain_Q10; - __m128i xmm_xq_Q14_3210, xmm_xq_Q14_x3x1, xmm_xq_Q14_7654, xmm_xq_Q14_x7x5; - - /* prepare (1 << 7) in packed 4 32-bits */ - xmm_tempa = _mm_set1_epi32( (1 << 7) ); - - /* prepare Gain_Q10 in packed 4 32-bits */ - xmm_Gain_Q10 = _mm_set1_epi32( Gain_Q10 ); - - /* process xq */ - for (i = 0; i < length - 7; i += 8) - { - xmm_xq_Q14_3210 = _mm_loadu_si128( (__m128i *)(&(psLPC_Q14[ i + 0 ] ) ) ); - xmm_xq_Q14_7654 = _mm_loadu_si128( (__m128i *)(&(psLPC_Q14[ i + 4 ] ) ) ); - - /* equal shift right 4 bytes*/ - xmm_xq_Q14_x3x1 = _mm_shuffle_epi32( xmm_xq_Q14_3210, _MM_SHUFFLE( 0, 3, 2, 1 ) ); - /* equal shift right 4 bytes*/ - xmm_xq_Q14_x7x5 = _mm_shuffle_epi32( xmm_xq_Q14_7654, _MM_SHUFFLE( 0, 3, 2, 1 ) ); - - xmm_xq_Q14_3210 = _mm_mul_epi32( xmm_xq_Q14_3210, xmm_Gain_Q10 ); - xmm_xq_Q14_x3x1 = _mm_mul_epi32( xmm_xq_Q14_x3x1, xmm_Gain_Q10 ); - xmm_xq_Q14_7654 = _mm_mul_epi32( xmm_xq_Q14_7654, xmm_Gain_Q10 ); - xmm_xq_Q14_x7x5 = _mm_mul_epi32( xmm_xq_Q14_x7x5, xmm_Gain_Q10 ); - - xmm_xq_Q14_3210 = _mm_srli_epi64( xmm_xq_Q14_3210, 16 ); - xmm_xq_Q14_x3x1 = _mm_slli_epi64( xmm_xq_Q14_x3x1, 16 ); - xmm_xq_Q14_7654 = _mm_srli_epi64( xmm_xq_Q14_7654, 16 ); - xmm_xq_Q14_x7x5 = _mm_slli_epi64( xmm_xq_Q14_x7x5, 16 ); - - xmm_xq_Q14_3210 = _mm_blend_epi16( xmm_xq_Q14_3210, xmm_xq_Q14_x3x1, 0xCC ); - xmm_xq_Q14_7654 = _mm_blend_epi16( xmm_xq_Q14_7654, xmm_xq_Q14_x7x5, 0xCC ); - - /* silk_RSHIFT_ROUND(xq, 8) */ - xmm_xq_Q14_3210 = _mm_add_epi32( xmm_xq_Q14_3210, xmm_tempa ); - xmm_xq_Q14_7654 = _mm_add_epi32( xmm_xq_Q14_7654, xmm_tempa ); - - xmm_xq_Q14_3210 = _mm_srai_epi32( xmm_xq_Q14_3210, 8 ); - xmm_xq_Q14_7654 = _mm_srai_epi32( xmm_xq_Q14_7654, 8 ); - - /* silk_SAT16 */ - xmm_xq_Q14_3210 = _mm_packs_epi32( xmm_xq_Q14_3210, xmm_xq_Q14_7654 ); - - /* save to xq */ - _mm_storeu_si128( (__m128i *)(&xq[ i ] ), xmm_xq_Q14_3210 ); - } - } - for ( ; i < length; i++) - { - xq[i] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( psLPC_Q14[ i ], Gain_Q10 ), 8 ) ); - } - - /* Update LPC synth buffer */ - silk_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); -} - -static OPUS_INLINE void silk_nsq_scale_states_sse4_1( - const silk_encoder_state *psEncC, /* I Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - const opus_int32 x_Q3[], /* I input in Q3 */ - opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */ - const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */ - opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ - opus_int subfr, /* I subframe number */ - const opus_int LTP_scale_Q14, /* I */ - const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ - const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ - const opus_int signal_type /* I Signal type */ -) -{ - opus_int i, lag; - opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23; - __m128i xmm_inv_gain_Q23, xmm_x_Q3_x2x0, xmm_x_Q3_x3x1; - - lag = pitchL[ subfr ]; - inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 ); - silk_assert( inv_gain_Q31 != 0 ); - - /* Calculate gain adjustment factor */ - if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) { - gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 ); - } else { - gain_adj_Q16 = (opus_int32)1 << 16; - } - - /* Scale input */ - inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 ); - - /* prepare inv_gain_Q23 in packed 4 32-bits */ - xmm_inv_gain_Q23 = _mm_set1_epi32(inv_gain_Q23); - - for( i = 0; i < psEncC->subfr_length - 3; i += 4 ) { - xmm_x_Q3_x2x0 = _mm_loadu_si128( (__m128i *)(&(x_Q3[ i ] ) ) ); - - /* equal shift right 4 bytes*/ - xmm_x_Q3_x3x1 = _mm_shuffle_epi32( xmm_x_Q3_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) ); - - xmm_x_Q3_x2x0 = _mm_mul_epi32( xmm_x_Q3_x2x0, xmm_inv_gain_Q23 ); - xmm_x_Q3_x3x1 = _mm_mul_epi32( xmm_x_Q3_x3x1, xmm_inv_gain_Q23 ); - - xmm_x_Q3_x2x0 = _mm_srli_epi64( xmm_x_Q3_x2x0, 16 ); - xmm_x_Q3_x3x1 = _mm_slli_epi64( xmm_x_Q3_x3x1, 16 ); - - xmm_x_Q3_x2x0 = _mm_blend_epi16( xmm_x_Q3_x2x0, xmm_x_Q3_x3x1, 0xCC ); - - _mm_storeu_si128( (__m128i *)(&(x_sc_Q10[ i ] ) ), xmm_x_Q3_x2x0 ); - } - - for( ; i < psEncC->subfr_length; i++ ) { - x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 ); - } - - /* Save inverse gain */ - NSQ->prev_gain_Q16 = Gains_Q16[ subfr ]; - - /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ - if( NSQ->rewhite_flag ) { - if( subfr == 0 ) { - /* Do LTP downscaling */ - inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 ); - } - for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { - silk_assert( i < MAX_FRAME_LENGTH ); - sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] ); - } - } - - /* Adjust for changing gain */ - if( gain_adj_Q16 != (opus_int32)1 << 16 ) { - /* Scale long-term shaping state */ - __m128i xmm_gain_adj_Q16, xmm_sLTP_shp_Q14_x2x0, xmm_sLTP_shp_Q14_x3x1; - - /* prepare gain_adj_Q16 in packed 4 32-bits */ - xmm_gain_adj_Q16 = _mm_set1_epi32(gain_adj_Q16); - - for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx - 3; i += 4 ) - { - xmm_sLTP_shp_Q14_x2x0 = _mm_loadu_si128( (__m128i *)(&(NSQ->sLTP_shp_Q14[ i ] ) ) ); - /* equal shift right 4 bytes*/ - xmm_sLTP_shp_Q14_x3x1 = _mm_shuffle_epi32( xmm_sLTP_shp_Q14_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) ); - - xmm_sLTP_shp_Q14_x2x0 = _mm_mul_epi32( xmm_sLTP_shp_Q14_x2x0, xmm_gain_adj_Q16 ); - xmm_sLTP_shp_Q14_x3x1 = _mm_mul_epi32( xmm_sLTP_shp_Q14_x3x1, xmm_gain_adj_Q16 ); - - xmm_sLTP_shp_Q14_x2x0 = _mm_srli_epi64( xmm_sLTP_shp_Q14_x2x0, 16 ); - xmm_sLTP_shp_Q14_x3x1 = _mm_slli_epi64( xmm_sLTP_shp_Q14_x3x1, 16 ); - - xmm_sLTP_shp_Q14_x2x0 = _mm_blend_epi16( xmm_sLTP_shp_Q14_x2x0, xmm_sLTP_shp_Q14_x3x1, 0xCC ); - - _mm_storeu_si128( (__m128i *)(&(NSQ->sLTP_shp_Q14[ i ] ) ), xmm_sLTP_shp_Q14_x2x0 ); - } - - for( ; i < NSQ->sLTP_shp_buf_idx; i++ ) { - NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] ); - } - - /* Scale long-term prediction state */ - if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) { - for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { - sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] ); - } - } - - NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 ); - - /* Scale short-term prediction and shaping states */ - for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { - NSQ->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] ); - } - for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { - NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] ); - } - } -} diff --git a/drivers/opus/silk/x86/SigProc_FIX_sse.h b/drivers/opus/silk/x86/SigProc_FIX_sse.h deleted file mode 100644 index 67ab30fd78..0000000000 --- a/drivers/opus/silk/x86/SigProc_FIX_sse.h +++ /dev/null @@ -1,91 +0,0 @@ -/* 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 -#include "opus/opus_config.h" - -#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 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)) - -#else - -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 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_aligned_64_sse4_1( - const opus_int16 *inVec1, - const opus_int16 *inVec2, - const opus_int len -); - - -#if defined(OPUS_X86_PRESUME_SSE4_1) - -#define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \ - ((void)(arch),silk_inner_prod16_aligned_64_sse4_1(inVec1, inVec2, len)) - -#else - -extern opus_int64 (*const SILK_INNER_PROD16_ALIGNED_64_IMPL[OPUS_ARCHMASK + 1])( - const opus_int16 *inVec1, - const opus_int16 *inVec2, - const opus_int len); - -# define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \ - ((*SILK_INNER_PROD16_ALIGNED_64_IMPL[(arch) & OPUS_ARCHMASK])(inVec1, inVec2, len)) - -#endif -#endif -#endif diff --git a/drivers/opus/silk/x86/VAD_sse.c b/drivers/opus/silk/x86/VAD_sse.c deleted file mode 100644 index 5db2c86aa9..0000000000 --- a/drivers/opus/silk/x86/VAD_sse.c +++ /dev/null @@ -1,274 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include <xmmintrin.h> -#include <emmintrin.h> -#include <smmintrin.h> - -#include "opus/silk/main.h" -#include "opus/celt/stack_alloc.h" - -/* Weighting factors for tilt measure */ -static const opus_int32 tiltWeights[ VAD_N_BANDS ] = { 30000, 6000, -12000, -12000 }; - -/***************************************/ -/* Get the speech activity level in Q8 */ -/***************************************/ -opus_int silk_VAD_GetSA_Q8_sse4_1( /* O Return value, 0 if success */ - silk_encoder_state *psEncC, /* I/O Encoder state */ - const opus_int16 pIn[] /* I PCM input */ -) -{ - opus_int SA_Q15, pSNR_dB_Q7, input_tilt; - opus_int decimated_framelength1, decimated_framelength2; - opus_int decimated_framelength; - opus_int dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s; - opus_int32 sumSquared, smooth_coef_Q16; - opus_int16 HPstateTmp; - VARDECL( opus_int16, X ); - opus_int32 Xnrg[ VAD_N_BANDS ]; - opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ]; - opus_int32 speech_nrg, x_tmp; - opus_int X_offset[ VAD_N_BANDS ]; - opus_int ret = 0; - silk_VAD_state *psSilk_VAD = &psEncC->sVAD; - - SAVE_STACK; - - /* Safety checks */ - silk_assert( VAD_N_BANDS == 4 ); - silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length ); - silk_assert( psEncC->frame_length <= 512 ); - silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) ); - - /***********************/ - /* Filter and Decimate */ - /***********************/ - decimated_framelength1 = silk_RSHIFT( psEncC->frame_length, 1 ); - decimated_framelength2 = silk_RSHIFT( psEncC->frame_length, 2 ); - decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 ); - /* Decimate into 4 bands: - 0 L 3L L 3L 5L - - -- - -- -- - 8 8 2 4 4 - - [0-1 kHz| temp. |1-2 kHz| 2-4 kHz | 4-8 kHz | - - They're arranged to allow the minimal ( frame_length / 4 ) extra - scratch space during the downsampling process */ - X_offset[ 0 ] = 0; - X_offset[ 1 ] = decimated_framelength + decimated_framelength2; - X_offset[ 2 ] = X_offset[ 1 ] + decimated_framelength; - X_offset[ 3 ] = X_offset[ 2 ] + decimated_framelength2; - ALLOC( X, X_offset[ 3 ] + decimated_framelength1, opus_int16 ); - - /* 0-8 kHz to 0-4 kHz and 4-8 kHz */ - silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ], - X, &X[ X_offset[ 3 ] ], psEncC->frame_length ); - - /* 0-4 kHz to 0-2 kHz and 2-4 kHz */ - silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState1[ 0 ], - X, &X[ X_offset[ 2 ] ], decimated_framelength1 ); - - /* 0-2 kHz to 0-1 kHz and 1-2 kHz */ - silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState2[ 0 ], - X, &X[ X_offset[ 1 ] ], decimated_framelength2 ); - - /*********************************************/ - /* HP filter on lowest band (differentiator) */ - /*********************************************/ - X[ decimated_framelength - 1 ] = silk_RSHIFT( X[ decimated_framelength - 1 ], 1 ); - HPstateTmp = X[ decimated_framelength - 1 ]; - for( i = decimated_framelength - 1; i > 0; i-- ) { - X[ i - 1 ] = silk_RSHIFT( X[ i - 1 ], 1 ); - X[ i ] -= X[ i - 1 ]; - } - X[ 0 ] -= psSilk_VAD->HPstate; - psSilk_VAD->HPstate = HPstateTmp; - - /*************************************/ - /* Calculate the energy in each band */ - /*************************************/ - for( b = 0; b < VAD_N_BANDS; b++ ) { - /* Find the decimated framelength in the non-uniformly divided bands */ - decimated_framelength = silk_RSHIFT( psEncC->frame_length, silk_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) ); - - /* Split length into subframe lengths */ - dec_subframe_length = silk_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 ); - dec_subframe_offset = 0; - - /* Compute energy per sub-frame */ - /* initialize with summed energy of last subframe */ - Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ]; - for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) { - __m128i xmm_X, xmm_acc; - sumSquared = 0; - - xmm_acc = _mm_setzero_si128(); - - for( i = 0; i < dec_subframe_length - 7; i += 8 ) - { - xmm_X = _mm_loadu_si128( (__m128i *)&(X[ X_offset[ b ] + i + dec_subframe_offset ] ) ); - xmm_X = _mm_srai_epi16( xmm_X, 3 ); - xmm_X = _mm_madd_epi16( xmm_X, xmm_X ); - xmm_acc = _mm_add_epi32( xmm_acc, xmm_X ); - } - - xmm_acc = _mm_add_epi32( xmm_acc, _mm_unpackhi_epi64( xmm_acc, xmm_acc ) ); - xmm_acc = _mm_add_epi32( xmm_acc, _mm_shufflelo_epi16( xmm_acc, 0x0E ) ); - - sumSquared += _mm_cvtsi128_si32( xmm_acc ); - - for( ; i < dec_subframe_length; i++ ) { - /* The energy will be less than dec_subframe_length * ( silk_int16_MIN / 8 ) ^ 2. */ - /* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */ - x_tmp = silk_RSHIFT( - X[ X_offset[ b ] + i + dec_subframe_offset ], 3 ); - sumSquared = silk_SMLABB( sumSquared, x_tmp, x_tmp ); - - /* Safety check */ - silk_assert( sumSquared >= 0 ); - } - - /* Add/saturate summed energy of current subframe */ - if( s < VAD_INTERNAL_SUBFRAMES - 1 ) { - Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], sumSquared ); - } else { - /* Look-ahead subframe */ - Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], silk_RSHIFT( sumSquared, 1 ) ); - } - - dec_subframe_offset += dec_subframe_length; - } - psSilk_VAD->XnrgSubfr[ b ] = sumSquared; - } - - /********************/ - /* Noise estimation */ - /********************/ - silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD ); - - /***********************************************/ - /* Signal-plus-noise to noise ratio estimation */ - /***********************************************/ - sumSquared = 0; - input_tilt = 0; - for( b = 0; b < VAD_N_BANDS; b++ ) { - speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ]; - if( speech_nrg > 0 ) { - /* Divide, with sufficient resolution */ - if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) { - NrgToNoiseRatio_Q8[ b ] = silk_DIV32( silk_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 ); - } else { - NrgToNoiseRatio_Q8[ b ] = silk_DIV32( Xnrg[ b ], silk_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 ); - } - - /* Convert to log domain */ - SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128; - - /* Sum-of-squares */ - sumSquared = silk_SMLABB( sumSquared, SNR_Q7, SNR_Q7 ); /* Q14 */ - - /* Tilt measure */ - if( speech_nrg < ( (opus_int32)1 << 20 ) ) { - /* Scale down SNR value for small subband speech energies */ - SNR_Q7 = silk_SMULWB( silk_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 ); - } - input_tilt = silk_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 ); - } else { - NrgToNoiseRatio_Q8[ b ] = 256; - } - } - - /* Mean-of-squares */ - sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */ - - /* Root-mean-square approximation, scale to dBs, and write to output pointer */ - pSNR_dB_Q7 = (opus_int16)( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */ - - /*********************************/ - /* Speech Probability Estimation */ - /*********************************/ - SA_Q15 = silk_sigm_Q15( silk_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 ); - - /**************************/ - /* Frequency Tilt Measure */ - /**************************/ - psEncC->input_tilt_Q15 = silk_LSHIFT( silk_sigm_Q15( input_tilt ) - 16384, 1 ); - - /**************************************************/ - /* Scale the sigmoid output based on power levels */ - /**************************************************/ - speech_nrg = 0; - for( b = 0; b < VAD_N_BANDS; b++ ) { - /* Accumulate signal-without-noise energies, higher frequency bands have more weight */ - speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 ); - } - - /* Power scaling */ - if( speech_nrg <= 0 ) { - SA_Q15 = silk_RSHIFT( SA_Q15, 1 ); - } else if( speech_nrg < 32768 ) { - if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { - speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 16 ); - } else { - speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 15 ); - } - - /* square-root */ - speech_nrg = silk_SQRT_APPROX( speech_nrg ); - SA_Q15 = silk_SMULWB( 32768 + speech_nrg, SA_Q15 ); - } - - /* Copy the resulting speech activity in Q8 */ - psEncC->speech_activity_Q8 = silk_min_int( silk_RSHIFT( SA_Q15, 7 ), silk_uint8_MAX ); - - /***********************************/ - /* Energy Level and SNR estimation */ - /***********************************/ - /* Smoothing coefficient */ - smooth_coef_Q16 = silk_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, silk_SMULWB( (opus_int32)SA_Q15, SA_Q15 ) ); - - if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { - smooth_coef_Q16 >>= 1; - } - - for( b = 0; b < VAD_N_BANDS; b++ ) { - /* compute smoothed energy-to-noise ratio per band */ - psSilk_VAD->NrgRatioSmth_Q8[ b ] = silk_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ], - NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 ); - - /* signal to noise ratio in dB per band */ - SNR_Q7 = 3 * ( silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 ); - /* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */ - psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( silk_RSHIFT( SNR_Q7 - 16 * 128, 4 ) ); - } - - RESTORE_STACK; - return( ret ); -} diff --git a/drivers/opus/silk/x86/VQ_WMat_EC_sse.c b/drivers/opus/silk/x86/VQ_WMat_EC_sse.c deleted file mode 100644 index 3afa42a6e5..0000000000 --- a/drivers/opus/silk/x86/VQ_WMat_EC_sse.c +++ /dev/null @@ -1,139 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include <xmmintrin.h> -#include <emmintrin.h> -#include <smmintrin.h> -#include "opus/silk/main.h" -#include "opus/celt/x86/x86cpu.h" - -/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */ -void silk_VQ_WMat_EC_sse4_1( - opus_int8 *ind, /* O index of best codebook vector */ - opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */ - opus_int *gain_Q7, /* O sum of absolute LTP coefficients */ - const opus_int16 *in_Q14, /* I input vector to be quantized */ - const opus_int32 *W_Q18, /* I weighting matrix */ - 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 mu_Q9, /* I tradeoff betw. weighted error and rate */ - const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ - opus_int L /* I number of vectors in codebook */ -) -{ - opus_int k, gain_tmp_Q7; - const opus_int8 *cb_row_Q7; - opus_int16 diff_Q14[ 5 ]; - opus_int32 sum1_Q14, sum2_Q16; - - __m128i C_tmp1, C_tmp2, C_tmp3, C_tmp4, C_tmp5; - /* Loop over codebook */ - *rate_dist_Q14 = silk_int32_MAX; - cb_row_Q7 = cb_Q7; - for( k = 0; k < L; k++ ) { - gain_tmp_Q7 = cb_gain_Q7[k]; - - diff_Q14[ 0 ] = in_Q14[ 0 ] - silk_LSHIFT( cb_row_Q7[ 0 ], 7 ); - - C_tmp1 = OP_CVTEPI16_EPI32_M64( &in_Q14[ 1 ] ); - C_tmp2 = OP_CVTEPI8_EPI32_M32( &cb_row_Q7[ 1 ] ); - C_tmp2 = _mm_slli_epi32( C_tmp2, 7 ); - C_tmp1 = _mm_sub_epi32( C_tmp1, C_tmp2 ); - - diff_Q14[ 1 ] = _mm_extract_epi16( C_tmp1, 0 ); - diff_Q14[ 2 ] = _mm_extract_epi16( C_tmp1, 2 ); - diff_Q14[ 3 ] = _mm_extract_epi16( C_tmp1, 4 ); - diff_Q14[ 4 ] = _mm_extract_epi16( C_tmp1, 6 ); - - /* Weighted rate */ - sum1_Q14 = silk_SMULBB( mu_Q9, cl_Q5[ k ] ); - - /* Penalty for too large gain */ - sum1_Q14 = silk_ADD_LSHIFT32( sum1_Q14, silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 10 ); - - silk_assert( sum1_Q14 >= 0 ); - - /* first row of W_Q18 */ - C_tmp3 = _mm_loadu_si128( (__m128i *)(&W_Q18[ 1 ] ) ); - C_tmp4 = _mm_mul_epi32( C_tmp3, C_tmp1 ); - C_tmp4 = _mm_srli_si128( C_tmp4, 2 ); - - C_tmp1 = _mm_shuffle_epi32( C_tmp1, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* shift right 4 bytes */ - C_tmp3 = _mm_shuffle_epi32( C_tmp3, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* shift right 4 bytes */ - - C_tmp5 = _mm_mul_epi32( C_tmp3, C_tmp1 ); - C_tmp5 = _mm_srli_si128( C_tmp5, 2 ); - - C_tmp5 = _mm_add_epi32( C_tmp4, C_tmp5 ); - C_tmp5 = _mm_slli_epi32( C_tmp5, 1 ); - - C_tmp5 = _mm_add_epi32( C_tmp5, _mm_shuffle_epi32( C_tmp5, _MM_SHUFFLE( 0, 0, 0, 2 ) ) ); - sum2_Q16 = _mm_cvtsi128_si32( C_tmp5 ); - - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] ); - sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] ); - - /* second row of W_Q18 */ - sum2_Q16 = silk_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] ); - sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] ); - sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] ); - - /* third row of W_Q18 */ - sum2_Q16 = silk_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] ); - sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] ); - sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] ); - - /* fourth row of W_Q18 */ - sum2_Q16 = silk_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] ); - sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); - sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] ); - sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] ); - - /* last row of W_Q18 */ - sum2_Q16 = silk_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] ); - sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] ); - - silk_assert( sum1_Q14 >= 0 ); - - /* find best */ - if( sum1_Q14 < *rate_dist_Q14 ) { - *rate_dist_Q14 = sum1_Q14; - *ind = (opus_int8)k; - *gain_Q7 = gain_tmp_Q7; - } - - /* Go to next cbk vector */ - cb_row_Q7 += LTP_ORDER; - } -} diff --git a/drivers/opus/silk/x86/main_sse.h b/drivers/opus/silk/x86/main_sse.h deleted file mode 100644 index 6fef1b358b..0000000000 --- a/drivers/opus/silk/x86/main_sse.h +++ /dev/null @@ -1,273 +0,0 @@ -/* 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 -#include "opus/opus_config.h" - -# if defined(OPUS_X86_MAY_HAVE_SSE4_1) - -# define OVERRIDE_silk_VQ_WMat_EC - -void silk_VQ_WMat_EC_sse4_1( - opus_int8 *ind, /* O index of best codebook vector */ - opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */ - opus_int *gain_Q7, /* O sum of absolute LTP coefficients */ - const opus_int16 *in_Q14, /* I input vector to be quantized */ - const opus_int32 *W_Q18, /* I weighting matrix */ - 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 mu_Q9, /* I tradeoff betw. weighted error and rate */ - const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ - opus_int L /* I number of vectors in codebook */ -); - -#if defined OPUS_X86_PRESUME_SSE4_1 - -#define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \ - mu_Q9, max_gain_Q7, L, arch) \ - ((void)(arch),silk_VQ_WMat_EC_sse4_1(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \ - mu_Q9, max_gain_Q7, L)) - -#else - -extern void (*const SILK_VQ_WMAT_EC_IMPL[OPUS_ARCHMASK + 1])( - opus_int8 *ind, /* O index of best codebook vector */ - opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */ - opus_int *gain_Q7, /* O sum of absolute LTP coefficients */ - const opus_int16 *in_Q14, /* I input vector to be quantized */ - const opus_int32 *W_Q18, /* I weighting matrix */ - 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 mu_Q9, /* I tradeoff betw. weighted error and rate */ - const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ - opus_int L /* I number of vectors in codebook */ -); - -# define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \ - mu_Q9, max_gain_Q7, L, arch) \ - ((*SILK_VQ_WMAT_EC_IMPL[(arch) & OPUS_ARCHMASK])(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \ - mu_Q9, max_gain_Q7, L)) - -#endif - -# define OVERRIDE_silk_NSQ - -void silk_NSQ_sse4_1( - const silk_encoder_state *psEncC, /* I/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int32 x_Q3[], /* I Prefiltered input signal */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ - const opus_int16 AR2_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 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)) - -#else - -extern void (*const SILK_NSQ_IMPL[OPUS_ARCHMASK + 1])( - const silk_encoder_state *psEncC, /* I/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int32 x_Q3[], /* I Prefiltered input signal */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ - const opus_int16 AR2_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 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 - -# define OVERRIDE_silk_NSQ_del_dec - -void silk_NSQ_del_dec_sse4_1( - const silk_encoder_state *psEncC, /* I/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int32 x_Q3[], /* I Prefiltered input signal */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ - const opus_int16 AR2_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 silk_NSQ_del_dec(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_del_dec_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)) - -#else - -extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])( - const silk_encoder_state *psEncC, /* I/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int32 x_Q3[], /* I Prefiltered input signal */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ - const opus_int16 AR2_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 silk_NSQ_del_dec(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_DEL_DEC_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_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 */ -); - -/**************************/ -/* 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 */ -); - -# define OVERRIDE_silk_VAD_GetSA_Q8 - -opus_int silk_VAD_GetSA_Q8_sse4_1( - silk_encoder_state *psEnC, - const opus_int16 pIn[] -); - -#if defined(OPUS_X86_PRESUME_SSE4_1) -#define silk_VAD_GetSA_Q8(psEnC, pIn, arch) ((void)(arch),silk_VAD_GetSA_Q8_sse4_1(psEnC, pIn)) - -#else - -# define silk_VAD_GetSA_Q8(psEnC, pIn, arch) \ - ((*SILK_VAD_GETSA_Q8_IMPL[(arch) & OPUS_ARCHMASK])(psEnC, pIn)) - -extern opus_int (*const SILK_VAD_GETSA_Q8_IMPL[OPUS_ARCHMASK + 1])( - silk_encoder_state *psEnC, - const opus_int16 pIn[]); - -# define OVERRIDE_silk_warped_LPC_analysis_filter_FIX - -#endif - -void silk_warped_LPC_analysis_filter_FIX_sse4_1( - opus_int32 state[], /* I/O State [order + 1] */ - opus_int32 res_Q2[], /* O Residual signal [length] */ - const opus_int16 coef_Q13[], /* I Coefficients [order] */ - const opus_int16 input[], /* I Input signal [length] */ - const opus_int16 lambda_Q16, /* I Warping factor */ - const opus_int length, /* I Length of input signal */ - const opus_int order /* I Filter order (even) */ -); - -#if defined(OPUS_X86_PRESUME_SSE4_1) -#define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \ - ((void)(arch),silk_warped_LPC_analysis_filter_FIX_c(state, res_Q2, coef_Q13, input, lambda_Q16, length, order)) - -#else - -extern void (*const SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[OPUS_ARCHMASK + 1])( - opus_int32 state[], /* I/O State [order + 1] */ - opus_int32 res_Q2[], /* O Residual signal [length] */ - const opus_int16 coef_Q13[], /* I Coefficients [order] */ - const opus_int16 input[], /* I Input signal [length] */ - const opus_int16 lambda_Q16, /* I Warping factor */ - const opus_int length, /* I Length of input signal */ - const opus_int order /* I Filter order (even) */ -); - -# define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \ - ((*SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[(arch) & OPUS_ARCHMASK])(state, res_Q2, coef_Q13, input, lambda_Q16, length, order)) - -#endif - -# endif -#endif diff --git a/drivers/opus/silk/x86/x86_silk_map.c b/drivers/opus/silk/x86/x86_silk_map.c deleted file mode 100644 index c3502114d1..0000000000 --- a/drivers/opus/silk/x86/x86_silk_map.c +++ /dev/null @@ -1,171 +0,0 @@ -/* 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. -*/ -#include "opus/opus_config.h" - -#include "opus/celt/x86/x86cpu.h" -#include "opus/silk/structs.h" -#include "opus/silk/SigProc_FIX.h" -#include "opus/celt/pitch.h" -#include "opus/silk/main.h" - -#if !defined(OPUS_X86_PRESUME_SSE4_1) - -#if defined(FIXED_POINT) - -#include "opus/silk/fixed/main_FIX.h" - -opus_int64 (*const SILK_INNER_PROD16_ALIGNED_64_IMPL[ OPUS_ARCHMASK + 1 ] )( - const opus_int16 *inVec1, - const opus_int16 *inVec2, - const opus_int len -) = { - silk_inner_prod16_aligned_64_c, /* non-sse */ - silk_inner_prod16_aligned_64_c, - silk_inner_prod16_aligned_64_c, - MAY_HAVE_SSE4_1( silk_inner_prod16_aligned_64 ), /* sse4.1 */ - MAY_HAVE_SSE4_1( silk_inner_prod16_aligned_64 ) /* 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/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int32 x_Q3[], /* I Prefiltered input signal */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ - const opus_int16 AR2_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 *rate_dist_Q14, /* O best weighted quant error + mu * rate */ - opus_int *gain_Q7, /* O sum of absolute LTP coefficients */ - const opus_int16 *in_Q14, /* I input vector to be quantized */ - const opus_int32 *W_Q18, /* I weighting matrix */ - 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 mu_Q9, /* I tradeoff betw. weighted error and rate */ - const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ - 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/O Encoder State */ - silk_nsq_state *NSQ, /* I/O NSQ state */ - SideInfoIndices *psIndices, /* I/O Quantization Indices */ - const opus_int32 x_Q3[], /* I Prefiltered input signal */ - opus_int8 pulses[], /* O Quantized pulse signal */ - const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ - const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ - const opus_int16 AR2_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_SSE4_1( silk_NSQ_del_dec ) /* avx */ -}; - -#if defined(FIXED_POINT) - -void (*const SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[ OPUS_ARCHMASK + 1 ] )( - opus_int32 state[], /* I/O State [order + 1] */ - opus_int32 res_Q2[], /* O Residual signal [length] */ - const opus_int16 coef_Q13[], /* I Coefficients [order] */ - const opus_int16 input[], /* I Input signal [length] */ - const opus_int16 lambda_Q16, /* I Warping factor */ - const opus_int length, /* I Length of input signal */ - const opus_int order /* I Filter order (even) */ -) = { - silk_warped_LPC_analysis_filter_FIX_c, /* non-sse */ - silk_warped_LPC_analysis_filter_FIX_c, - silk_warped_LPC_analysis_filter_FIX_c, - MAY_HAVE_SSE4_1( silk_warped_LPC_analysis_filter_FIX ), /* sse4.1 */ - MAY_HAVE_SSE4_1( silk_warped_LPC_analysis_filter_FIX ) /* avx */ -}; - -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 -#endif diff --git a/drivers/opus/stream.c b/drivers/opus/stream.c deleted file mode 100644 index 2ac12642dd..0000000000 --- a/drivers/opus/stream.c +++ /dev/null @@ -1,364 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ******************************************************************** - - function: stdio-based convenience library for opening/seeking/decoding - last mod: $Id: vorbisfile.c 17573 2010-10-27 14:53:59Z xiphmont $ - - ********************************************************************/ -#include "opus/opus_config.h" - -#include "opus/internal.h" -#include <sys/types.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#if defined(_WIN32) -# include <io.h> -#endif - -typedef struct OpusMemStream OpusMemStream; - -#define OP_MEM_SIZE_MAX (~(size_t)0>>1) -#define OP_MEM_DIFF_MAX ((ptrdiff_t)OP_MEM_SIZE_MAX) - -/*The context information needed to read from a block of memory as if it were a - file.*/ -struct OpusMemStream{ - /*The block of memory to read from.*/ - const unsigned char *data; - /*The total size of the block. - This must be at most OP_MEM_SIZE_MAX to prevent signed overflow while - seeking.*/ - ptrdiff_t size; - /*The current file position. - This is allowed to be set arbitrarily greater than size (i.e., past the end - of the block, though we will not read data past the end of the block), but - is not allowed to be negative (i.e., before the beginning of the block).*/ - ptrdiff_t pos; -}; - -static int op_fread(void *_stream,unsigned char *_ptr,int _buf_size){ - FILE *stream; - size_t ret; - /*Check for empty read.*/ - if(_buf_size<=0)return 0; - stream=(FILE *)_stream; - ret=fread(_ptr,1,_buf_size,stream); - OP_ASSERT(ret<=(size_t)_buf_size); - /*If ret==0 and !feof(stream), there was a read error.*/ - return ret>0||feof(stream)?(int)ret:OP_EREAD; -} - -static int op_fseek(void *_stream,opus_int64 _offset,int _whence){ -#if defined(_WIN32) - /*_fseeki64() is not exposed until MSCVCRT80. - This is the default starting with MSVC 2005 (_MSC_VER>=1400), but we want - to allow linking against older MSVCRT versions for compatibility back to - XP without installing extra runtime libraries. - i686-pc-mingw32 does not have fseeko() and requires - __MSVCRT_VERSION__>=0x800 for _fseeki64(), which screws up linking with - other libraries (that don't use MSVCRT80 from MSVC 2005 by default). - i686-w64-mingw32 does have fseeko() and respects _FILE_OFFSET_BITS, but I - don't know how to detect that at compile time. - We could just use fseeko64() (which is available in both), but its - implemented using fgetpos()/fsetpos() just like this code, except without - the overflow checking, so we prefer our version.*/ - opus_int64 pos; - /*We don't use fpos_t directly because it might be a struct if __STDC__ is - non-zero or _INTEGRAL_MAX_BITS < 64. - I'm not certain when the latter is true, but someone could in theory set - the former. - Either way, it should be binary compatible with a normal 64-bit int (this - assumption is not portable, but I believe it is true for MSVCRT).*/ - OP_ASSERT(sizeof(pos)==sizeof(fpos_t)); - /*Translate the seek to an absolute one.*/ - if(_whence==SEEK_CUR){ - int ret; - ret=fgetpos((FILE *)_stream,(fpos_t *)&pos); - if(ret)return ret; - } - else if(_whence==SEEK_END)pos=_filelengthi64(_fileno((FILE *)_stream)); - else if(_whence==SEEK_SET)pos=0; - else return -1; - /*Check for errors or overflow.*/ - if(pos<0||_offset<-pos||_offset>OP_INT64_MAX-pos)return -1; - pos+=_offset; - return fsetpos((FILE *)_stream,(fpos_t *)&pos); -#else - /*This function actually conforms to the SUSv2 and POSIX.1-2001, so we prefer - it except on Windows.*/ - return fseeko((FILE *)_stream,(off_t)_offset,_whence); -#endif -} - -static opus_int64 op_ftell(void *_stream){ -#if defined(_WIN32) - /*_ftelli64() is not exposed until MSCVCRT80, and ftello()/ftello64() have - the same problems as fseeko()/fseeko64() in MingW. - See above for a more detailed explanation.*/ - opus_int64 pos; - OP_ASSERT(sizeof(pos)==sizeof(fpos_t)); - return fgetpos((FILE *)_stream,(fpos_t *)&pos)?-1:pos; -#else - /*This function actually conforms to the SUSv2 and POSIX.1-2001, so we prefer - it except on Windows.*/ - return ftello((FILE *)_stream); -#endif -} - -static const OpusFileCallbacks OP_FILE_CALLBACKS={ - op_fread, - op_fseek, - op_ftell, - (op_close_func)fclose -}; - -#if defined(_WIN32) -# include <stddef.h> -# include <errno.h> - -/*Windows doesn't accept UTF-8 by default, and we don't have a wchar_t API, - so if we just pass the path to fopen(), then there'd be no way for a user - of our API to open a Unicode filename. - Instead, we translate from UTF-8 to UTF-16 and use Windows' wchar_t API. - This makes this API more consistent with platforms where the character set - used by fopen is the same as used on disk, which is generally UTF-8, and - with our metadata API, which always uses UTF-8.*/ -static wchar_t *op_utf8_to_utf16(const char *_src){ - wchar_t *dst; - size_t len; - len=strlen(_src); - /*Worst-case output is 1 wide character per 1 input character.*/ - dst=(wchar_t *)_ogg_malloc(sizeof(*dst)*(len+1)); - if(dst!=NULL){ - size_t si; - size_t di; - for(di=si=0;si<len;si++){ - int c0; - c0=(unsigned char)_src[si]; - if(!(c0&0x80)){ - /*Start byte says this is a 1-byte sequence.*/ - dst[di++]=(wchar_t)c0; - continue; - } - else{ - int c1; - /*This is safe, because c0 was not 0 and _src is NUL-terminated.*/ - c1=(unsigned char)_src[si+1]; - if((c1&0xC0)==0x80){ - /*Found at least one continuation byte.*/ - if((c0&0xE0)==0xC0){ - wchar_t w; - /*Start byte says this is a 2-byte sequence.*/ - w=(c0&0x1F)<<6|c1&0x3F; - if(w>=0x80U){ - /*This is a 2-byte sequence that is not overlong.*/ - dst[di++]=w; - si++; - continue; - } - } - else{ - int c2; - /*This is safe, because c1 was not 0 and _src is NUL-terminated.*/ - c2=(unsigned char)_src[si+2]; - if((c2&0xC0)==0x80){ - /*Found at least two continuation bytes.*/ - if((c0&0xF0)==0xE0){ - wchar_t w; - /*Start byte says this is a 3-byte sequence.*/ - w=(c0&0xF)<<12|(c1&0x3F)<<6|c2&0x3F; - if(w>=0x800U&&(w<0xD800||w>=0xE000)&&w<0xFFFE){ - /*This is a 3-byte sequence that is not overlong, not a - UTF-16 surrogate pair value, and not a 'not a character' - value.*/ - dst[di++]=w; - si+=2; - continue; - } - } - else{ - int c3; - /*This is safe, because c2 was not 0 and _src is - NUL-terminated.*/ - c3=(unsigned char)_src[si+3]; - if((c3&0xC0)==0x80){ - /*Found at least three continuation bytes.*/ - if((c0&0xF8)==0xF0){ - opus_uint32 w; - /*Start byte says this is a 4-byte sequence.*/ - w=(c0&7)<<18|(c1&0x3F)<<12|(c2&0x3F)<<6&(c3&0x3F); - if(w>=0x10000U&&w<0x110000U){ - /*This is a 4-byte sequence that is not overlong and not - greater than the largest valid Unicode code point. - Convert it to a surrogate pair.*/ - w-=0x10000; - dst[di++]=(wchar_t)(0xD800+(w>>10)); - dst[di++]=(wchar_t)(0xDC00+(w&0x3FF)); - si+=3; - continue; - } - } - } - } - } - } - } - } - /*If we got here, we encountered an illegal UTF-8 sequence.*/ - _ogg_free(dst); - return NULL; - } - OP_ASSERT(di<=len); - dst[di]='\0'; - } - return dst; -} - -#endif - -void *op_fopen(OpusFileCallbacks *_cb,const char *_path,const char *_mode){ - FILE *fp; -#if !defined(_WIN32) - fp=fopen(_path,_mode); -#else - fp=NULL; - if(_path==NULL||_mode==NULL)errno=EINVAL; - else{ - wchar_t *wpath; - wchar_t *wmode; - wpath=op_utf8_to_utf16(_path); - wmode=op_utf8_to_utf16(_mode); - if(wmode==NULL)errno=EINVAL; - else if(wpath==NULL)errno=ENOENT; - else fp=_wfopen(wpath,wmode); - _ogg_free(wmode); - _ogg_free(wpath); - } -#endif - if(fp!=NULL)*_cb=*&OP_FILE_CALLBACKS; - return fp; -} - -void *op_fdopen(OpusFileCallbacks *_cb,int _fd,const char *_mode){ - FILE *fp; - fp=fdopen(_fd,_mode); - if(fp!=NULL)*_cb=*&OP_FILE_CALLBACKS; - return fp; -} - -void *op_freopen(OpusFileCallbacks *_cb,const char *_path,const char *_mode, - void *_stream){ - FILE *fp; -#if !defined(_WIN32) - fp=freopen(_path,_mode,(FILE *)_stream); -#else - fp=NULL; - if(_path==NULL||_mode==NULL)errno=EINVAL; - else{ - wchar_t *wpath; - wchar_t *wmode; - wpath=op_utf8_to_utf16(_path); - wmode=op_utf8_to_utf16(_mode); - if(wmode==NULL)errno=EINVAL; - else if(wpath==NULL)errno=ENOENT; - else fp=_wfreopen(wpath,wmode,(FILE *)_stream); - _ogg_free(wmode); - _ogg_free(wpath); - } -#endif - if(fp!=NULL)*_cb=*&OP_FILE_CALLBACKS; - return fp; -} - -static int op_mem_read(void *_stream,unsigned char *_ptr,int _buf_size){ - OpusMemStream *stream; - ptrdiff_t size; - ptrdiff_t pos; - stream=(OpusMemStream *)_stream; - /*Check for empty read.*/ - if(_buf_size<=0)return 0; - size=stream->size; - pos=stream->pos; - /*Check for EOF.*/ - if(pos>=size)return 0; - /*Check for a short read.*/ - _buf_size=(int)OP_MIN(size-pos,_buf_size); - memcpy(_ptr,stream->data+pos,_buf_size); - pos+=_buf_size; - stream->pos=pos; - return _buf_size; -} - -static int op_mem_seek(void *_stream,opus_int64 _offset,int _whence){ - OpusMemStream *stream; - ptrdiff_t pos; - stream=(OpusMemStream *)_stream; - pos=stream->pos; - OP_ASSERT(pos>=0); - switch(_whence){ - case SEEK_SET:{ - /*Check for overflow:*/ - if(_offset<0||_offset>OP_MEM_DIFF_MAX)return -1; - pos=(ptrdiff_t)_offset; - }break; - case SEEK_CUR:{ - /*Check for overflow:*/ - if(_offset<-pos||_offset>OP_MEM_DIFF_MAX-pos)return -1; - pos=(ptrdiff_t)(pos+_offset); - }break; - case SEEK_END:{ - ptrdiff_t size; - size=stream->size; - OP_ASSERT(size>=0); - /*Check for overflow:*/ - if(_offset>size||_offset<size-OP_MEM_DIFF_MAX)return -1; - pos=(ptrdiff_t)(size-_offset); - }break; - default:return -1; - } - stream->pos=pos; - return 0; -} - -static opus_int64 op_mem_tell(void *_stream){ - OpusMemStream *stream; - stream=(OpusMemStream *)_stream; - return (ogg_int64_t)stream->pos; -} - -static int op_mem_close(void *_stream){ - _ogg_free(_stream); - return 0; -} - -static const OpusFileCallbacks OP_MEM_CALLBACKS={ - op_mem_read, - op_mem_seek, - op_mem_tell, - op_mem_close -}; - -void *op_mem_stream_create(OpusFileCallbacks *_cb, - const unsigned char *_data,size_t _size){ - OpusMemStream *stream; - if(_size>OP_MEM_SIZE_MAX)return NULL; - stream=(OpusMemStream *)_ogg_malloc(sizeof(*stream)); - if(stream!=NULL){ - *_cb=*&OP_MEM_CALLBACKS; - stream->data=_data; - stream->size=_size; - stream->pos=0; - } - return stream; -} diff --git a/drivers/opus/wincerts.c b/drivers/opus/wincerts.c deleted file mode 100644 index 1a5b634063..0000000000 --- a/drivers/opus/wincerts.c +++ /dev/null @@ -1,168 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2013 * - * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * - * * - ********************************************************************/ - -/*This should really be part of OpenSSL, but there's been a patch [1] sitting - in their bugtracker for over two years that implements this, without any - action, so I'm giving up and re-implementing it locally. - - [1] <http://rt.openssl.org/Ticket/Display.html?id=2158>*/ -#include "opus/opus_config.h" - -#include "opus/internal.h" -#if defined(OP_ENABLE_HTTP)&&defined(_WIN32) -/*You must include windows.h before wincrypt.h and x509.h.*/ -# define WIN32_LEAN_AND_MEAN -# define WIN32_EXTRA_LEAN -# include <windows.h> -/*You must include wincrypt.h before x509.h, too, or X509_NAME doesn't get - defined properly.*/ -# include <wincrypt.h> -# include <openssl/ssl.h> -# include <openssl/err.h> -# include <openssl/x509.h> - -static int op_capi_new(X509_LOOKUP *_lu){ - HCERTSTORE h_store; - h_store=CertOpenStore(CERT_STORE_PROV_SYSTEM_A,0,0, - CERT_STORE_OPEN_EXISTING_FLAG|CERT_STORE_READONLY_FLAG| - CERT_SYSTEM_STORE_CURRENT_USER|CERT_STORE_SHARE_CONTEXT_FLAG,"ROOT"); - if(h_store!=NULL){ - _lu->method_data=(char *)h_store; - return 1; - } - return 0; -} - -static void op_capi_free(X509_LOOKUP *_lu){ - HCERTSTORE h_store; - h_store=(HCERTSTORE)_lu->method_data; -# if defined(OP_ENABLE_ASSERTIONS) - OP_ALWAYS_TRUE(CertCloseStore(h_store,CERT_CLOSE_STORE_CHECK_FLAG)); -# else - CertCloseStore(h_store,0); -# endif -} - -static int op_capi_retrieve_by_subject(X509_LOOKUP *_lu,int _type, - X509_NAME *_name,X509_OBJECT *_ret){ - X509_OBJECT *obj; - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); - obj=X509_OBJECT_retrieve_by_subject(_lu->store_ctx->objs,_type,_name); - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - if(obj!=NULL){ - _ret->type=obj->type; - memcpy(&_ret->data,&obj->data,sizeof(_ret->data)); - return 1; - } - return 0; -} - -static int op_capi_get_by_subject(X509_LOOKUP *_lu,int _type,X509_NAME *_name, - X509_OBJECT *_ret){ - HCERTSTORE h_store; - if(_name==NULL)return 0; - if(_name->bytes==NULL||_name->bytes->length<=0||_name->modified){ - if(i2d_X509_NAME(_name,NULL)<0)return 0; - OP_ASSERT(_name->bytes->length>0); - } - h_store=(HCERTSTORE)_lu->method_data; - switch(_type){ - case X509_LU_X509:{ - CERT_NAME_BLOB find_para; - PCCERT_CONTEXT cert; - X509 *x; - int ret; - /*Although X509_NAME contains a canon_enc field, that "canonical" [1] - encoding was just made up by OpenSSL. - It doesn't correspond to any actual standard, and since it drops the - initial sequence header, won't be recognized by the Crypto API. - The assumption here is that CertFindCertificateInStore() will allow any - appropriate variations in the encoding when it does its comparison. - This is, however, emphatically not true under Wine, which just compares - the encodings with memcmp(). - Most of the time things work anyway, though, and there isn't really - anything we can do to make the situation better. - - [1] A "canonical form" is defined as the one where, if you locked 10 - mathematicians in a room and asked them to come up with a - representation for something, it's the answer that 9 of them would - give you back. - I don't think OpenSSL's encoding qualifies.*/ - find_para.cbData=_name->bytes->length; - find_para.pbData=(unsigned char *)_name->bytes->data; - cert=CertFindCertificateInStore(h_store,X509_ASN_ENCODING,0, - CERT_FIND_SUBJECT_NAME,&find_para,NULL); - if(cert==NULL)return 0; - x=d2i_X509(NULL,(const unsigned char **)&cert->pbCertEncoded, - cert->cbCertEncoded); - CertFreeCertificateContext(cert); - if(x==NULL)return 0; - ret=X509_STORE_add_cert(_lu->store_ctx,x); - X509_free(x); - if(ret)return op_capi_retrieve_by_subject(_lu,_type,_name,_ret); - }break; - case X509_LU_CRL:{ - CERT_INFO cert_info; - CERT_CONTEXT find_para; - PCCRL_CONTEXT crl; - X509_CRL *x; - int ret; - ret=op_capi_retrieve_by_subject(_lu,_type,_name,_ret); - if(ret>0)return ret; - memset(&cert_info,0,sizeof(cert_info)); - cert_info.Issuer.cbData=_name->bytes->length; - cert_info.Issuer.pbData=(unsigned char *)_name->bytes->data; - memset(&find_para,0,sizeof(find_para)); - find_para.pCertInfo=&cert_info; - crl=CertFindCRLInStore(h_store,0,0,CRL_FIND_ISSUED_BY,&find_para,NULL); - if(crl==NULL)return 0; - x=d2i_X509_CRL(NULL,(const unsigned char **)&crl->pbCrlEncoded, - crl->cbCrlEncoded); - CertFreeCRLContext(crl); - if(x==NULL)return 0; - ret=X509_STORE_add_crl(_lu->store_ctx,x); - X509_CRL_free(x); - if(ret)return op_capi_retrieve_by_subject(_lu,_type,_name,_ret); - }break; - } - return 0; -} - -/*This is not const because OpenSSL doesn't allow it, even though it won't - write to it.*/ -static X509_LOOKUP_METHOD X509_LOOKUP_CAPI={ - "Load Crypto API store into cache", - op_capi_new, - op_capi_free, - NULL, - NULL, - NULL, - op_capi_get_by_subject, - NULL, - NULL, - NULL -}; - -int SSL_CTX_set_default_verify_paths_win32(SSL_CTX *_ssl_ctx){ - X509_STORE *store; - X509_LOOKUP *lu; - /*We intentionally do not add the normal default paths, as they are usually - wrong, and are just asking to be used as an exploit vector.*/ - store=SSL_CTX_get_cert_store(_ssl_ctx); - OP_ASSERT(store!=NULL); - lu=X509_STORE_add_lookup(store,&X509_LOOKUP_CAPI); - if(lu==NULL)return 0; - ERR_clear_error(); - return 1; -} - -#endif diff --git a/drivers/png/SCsub b/drivers/png/SCsub index 96ef9fa5f8..04cb70e1c1 100644 --- a/drivers/png/SCsub +++ b/drivers/png/SCsub @@ -1,42 +1,50 @@ +#!/usr/bin/env python + Import('env') -Import('env_drivers') +env_png = env.Clone() -png_sources = [ - "png/png.c", - "png/pngerror.c", - "png/pngget.c", - "png/pngmem.c", - "png/pngpread.c", - "png/pngread.c", - "png/pngrio.c", - "png/pngrtran.c", - "png/pngrutil.c", - "png/pngset.c", - "png/pngtrans.c", - "png/pngwio.c", - "png/pngwrite.c", - "png/pngwtran.c", - "png/pngwutil.c", - "png/resource_saver_png.cpp", - "png/image_loader_png.cpp" -] +# Thirdparty source files +if (env["libpng"] == "builtin"): + thirdparty_dir = "#thirdparty/libpng/" + thirdparty_sources = [ + "png.c", + "pngerror.c", + "pngget.c", + "pngmem.c", + "pngpread.c", + "pngread.c", + "pngrio.c", + "pngrtran.c", + "pngrutil.c", + "pngset.c", + "pngtrans.c", + "pngwio.c", + "pngwrite.c", + "pngwtran.c", + "pngwutil.c", + ] + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] -# Currently .ASM filter_neon.S does not compile on NT. -import os -if ("neon_enabled" in env and env["neon_enabled"]) and os.name!="nt": - env_drivers.Append(CPPFLAGS=["-DPNG_ARM_NEON_OPT=2"]) - env_neon = env_drivers.Clone(); - if "S_compiler" in env: - env_neon['CC'] = env['S_compiler'] - #env_neon.Append(CPPFLAGS=["-DPNG_ARM_NEON"]) - png_sources.append(env_neon.Object("#drivers/png/arm/arm_init.c")) - png_sources.append(env_neon.Object("#drivers/png/arm/filter_neon.S")) -else: - env_drivers.Append(CPPFLAGS=["-DPNG_ARM_NEON_OPT=0"]) + env_png.add_source_files(env.drivers_sources, thirdparty_sources) + env_png.Append(CPPPATH = [thirdparty_dir]) -env.drivers_sources+=png_sources + # Currently .ASM filter_neon.S does not compile on NT. + import os + if ("neon_enabled" in env and env["neon_enabled"]) and os.name!="nt": + env_png.Append(CPPFLAGS = ["-DPNG_ARM_NEON_OPT=2"]) + env_neon = env_png.Clone(); + if "S_compiler" in env: + env_neon['CC'] = env['S_compiler'] + neon_sources = [] + neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/arm_init.c")) + neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/filter_neon_intrinsics.c")) + neon_sources.append(env_neon.Object(thirdparty_dir + "/arm/filter_neon.S")) + env.drivers_sources += neon_sources + else: + env_png.Append(CPPFLAGS = ["-DPNG_ARM_NEON_OPT=0"]) -#env.add_source_files(env.drivers_sources, png_sources) +# Godot source files +env_png.add_source_files(env.drivers_sources, "*.cpp") Export('env') diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp index e10ac7493f..ab3f3e78fc 100644 --- a/drivers/png/image_loader_png.cpp +++ b/drivers/png/image_loader_png.cpp @@ -30,6 +30,7 @@ #include "print_string.h" #include "os/os.h" + #include <string.h> @@ -270,7 +271,7 @@ static void user_read_data(png_structp png_ptr,png_bytep data, png_size_t p_leng PNGReadStatus *rstatus; rstatus=(PNGReadStatus*)png_get_io_ptr(png_ptr); - int to_read=p_length; + png_size_t to_read=p_length; if (rstatus->size>=0) { to_read = MIN( p_length, rstatus->size - rstatus->offset); } diff --git a/drivers/png/image_loader_png.h b/drivers/png/image_loader_png.h index d87d67d898..c146e3f5a1 100644 --- a/drivers/png/image_loader_png.h +++ b/drivers/png/image_loader_png.h @@ -30,7 +30,8 @@ #define IMAGE_LOADER_PNG_H #include "io/image_loader.h" -#include "drivers/png/png.h" + +#include <png.h> /** @author Juan Linietsky <reduzio@gmail.com> diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp index 2578fe9eb6..e7987f27bf 100644 --- a/drivers/png/resource_saver_png.cpp +++ b/drivers/png/resource_saver_png.cpp @@ -27,11 +27,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "resource_saver_png.h" -#include "scene/resources/texture.h" -#include "drivers/png/png.h" -#include "os/file_access.h" -#include "globals.h" + #include "core/image.h" +#include "globals.h" +#include "os/file_access.h" +#include "scene/resources/texture.h" + +#include <png.h> static void _write_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length) { diff --git a/drivers/pnm/SCsub b/drivers/pnm/SCsub deleted file mode 100644 index 28b35773a4..0000000000 --- a/drivers/pnm/SCsub +++ /dev/null @@ -1,10 +0,0 @@ -Import('env') - - -pnm_sources = [ - "pnm/bitmap_loader_pnm.cpp" - ] - -env.drivers_sources+=pnm_sources - -#env.add_source_files(env.drivers_sources, pnm_sources) diff --git a/drivers/pnm/bitmap_loader_pnm.cpp b/drivers/pnm/bitmap_loader_pnm.cpp deleted file mode 100644 index e06d4c80f0..0000000000 --- a/drivers/pnm/bitmap_loader_pnm.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/*************************************************************************/ -/* bitmap_loader_pnm.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "bitmap_loader_pnm.h" -#include "os/file_access.h" -#include "scene/resources/bit_mask.h" - - -static bool _get_token(FileAccessRef& f,uint8_t &saved,DVector<uint8_t>& r_token,bool p_binary=false,bool p_single_chunk=false) { - - - int token_max = r_token.size(); - DVector<uint8_t>::Write w; - if (token_max) - w=r_token.write(); - int ofs=0; - bool lf=false; - - - while(true) { - - uint8_t b; - if (saved) { - b=saved; - saved=0; - } else { - b = f->get_8(); - } - if (f->eof_reached()) { - if (ofs) { - w=DVector<uint8_t>::Write(); - r_token.resize(ofs); - return true; - } else { - return false; - } - } - - if (!ofs && !p_binary && b=='#') { - //skip comment - while(b!='\n') { - if (f->eof_reached()) { - return false; - } - - b = f->get_8(); - } - - lf=true; - - } else if (b<=32 && !(p_binary && (ofs || lf))) { - - if (b=='\n') { - lf=true; - } - - - if (ofs && !p_single_chunk) { - w=DVector<uint8_t>::Write(); - r_token.resize(ofs); - saved=b; - - return true; - } - } else { - - bool resized=false; - while (ofs>=token_max) { - if (token_max) - token_max<<=1; - else - token_max=1; - resized=true; - } - if (resized) { - w=DVector<uint8_t>::Write(); - r_token.resize(token_max); - w=r_token.write(); - } - w[ofs++]=b; - } - } - - return false; -} - -static int _get_number_from_token(DVector<uint8_t>& r_token) { - - int len = r_token.size(); - DVector<uint8_t>::Read r = r_token.read(); - return String::to_int((const char*)r.ptr(),len); - -} - - -RES ResourceFormatPBM::load(const String &p_path,const String& p_original_path,Error *r_error) { - -#define _RETURN(m_err)\ -{\ - if (r_error)\ - *r_error=m_err;\ - ERR_FAIL_V(RES());\ -} - - - FileAccessRef f=FileAccess::open(p_path,FileAccess::READ); - uint8_t saved=0; - if (!f) - _RETURN(ERR_CANT_OPEN); - - DVector<uint8_t> token; - - if (!_get_token(f,saved,token)) { - _RETURN(ERR_PARSE_ERROR); - } - - if (token.size()!=2) { - _RETURN(ERR_FILE_CORRUPT); - } - if (token[0]!='P') { - _RETURN(ERR_FILE_CORRUPT); - } - if (token[1]!='1' && token[1]!='4') { - _RETURN(ERR_FILE_CORRUPT); - } - - bool bits = token[1]=='4'; - - if (!_get_token(f,saved,token)) { - _RETURN(ERR_PARSE_ERROR); - } - - int width = _get_number_from_token(token); - if (width<=0) { - _RETURN(ERR_FILE_CORRUPT); - } - - - if (!_get_token(f,saved,token)) { - _RETURN(ERR_PARSE_ERROR); - } - - int height = _get_number_from_token(token); - if (height<=0) { - _RETURN(ERR_FILE_CORRUPT); - } - - - Ref<BitMap> bm; - bm.instance(); - bm->create(Size2i(width,height)); - - if (!bits) { - - int required_bytes = width*height; - if (!_get_token(f,saved,token,false,true)) { - _RETURN(ERR_PARSE_ERROR); - } - - if (token.size()<required_bytes) { - _RETURN(ERR_FILE_CORRUPT); - } - - DVector<uint8_t>::Read r=token.read(); - - for(int i=0;i<height;i++) { - for(int j=0;j<width;j++) { - - - char num = r[i*width+j]; - bm->set_bit(Point2i(j,i),num=='0'); - } - - } - - - - } else { - //a single, entire token of bits! - if (!_get_token(f,saved,token,true)) { - _RETURN(ERR_PARSE_ERROR); - } - int required_bytes = Math::ceil((width*height)/8.0); - if (token.size()<required_bytes) { - _RETURN(ERR_FILE_CORRUPT); - } - - DVector<uint8_t>::Read r=token.read(); - int bitwidth = width; - if (bitwidth % 8) - bitwidth+=8-(bitwidth%8); - - for(int i=0;i<height;i++) { - for(int j=0;j<width;j++) { - - int ofs = bitwidth*i+j; - - uint8_t byte = r[ofs/8]; - bool bit = (byte>>(7-(ofs%8)))&1; - - bm->set_bit(Point2i(j,i),!bit); - - } - - } - - } - - return bm; - - -} - -void ResourceFormatPBM::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("pbm"); -} -bool ResourceFormatPBM::handles_type(const String& p_type) const { - return p_type=="BitMap"; -} -String ResourceFormatPBM::get_resource_type(const String &p_path) const { - - if (p_path.extension().to_lower()=="pbm") - return "BitMap"; - return ""; -} - - diff --git a/drivers/pnm/bitmap_loader_pnm.h b/drivers/pnm/bitmap_loader_pnm.h deleted file mode 100644 index 965cf7a451..0000000000 --- a/drivers/pnm/bitmap_loader_pnm.h +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************/ -/* bitmap_loader_pnm.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef BITMAP_LOADER_PNM_H -#define BITMAP_LOADER_PNM_H - -#include "io/resource_loader.h" - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ -class ResourceFormatPBM : public ResourceFormatLoader { - - -public: - - virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); - virtual void get_recognized_extensions(List<String> *p_extensions) const; - virtual bool handles_type(const String& p_type) const; - virtual String get_resource_type(const String &p_path) const; -}; - - - -#endif diff --git a/drivers/pulseaudio/SCsub b/drivers/pulseaudio/SCsub index 9fbb467baa..ee39fd2631 100644 --- a/drivers/pulseaudio/SCsub +++ b/drivers/pulseaudio/SCsub @@ -1,5 +1,7 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.drivers_sources,"*.cpp") +env.add_source_files(env.drivers_sources, "*.cpp") Export('env') diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index 4804bc5630..954d2c20f2 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -175,8 +175,8 @@ void AudioDriverPulseAudio::finish() { exit_thread = true; Thread::wait_to_finish(thread); - if (pulse) - pa_simple_free(pulse); + if (pulse) + pa_simple_free(pulse); if (samples_in) { memdelete_arr(samples_in); diff --git a/drivers/pvr/SCsub b/drivers/pvr/SCsub deleted file mode 100644 index 44b8c3d6bb..0000000000 --- a/drivers/pvr/SCsub +++ /dev/null @@ -1,15 +0,0 @@ -Import('env') - - -pvr_sources = [ - "pvr/BitScale.cpp", - "pvr/MortonTable.cpp", - "pvr/PvrTcDecoder.cpp", - "pvr/PvrTcEncoder.cpp", - "pvr/PvrTcPacket.cpp", - "pvr/texture_loader_pvr.cpp" - ] - -env.drivers_sources+=pvr_sources - -#env.add_source_files(env.drivers_sources, pvr_sources) diff --git a/drivers/register_driver_types.cpp b/drivers/register_driver_types.cpp index 8354de8c6f..7486d4f217 100644 --- a/drivers/register_driver_types.cpp +++ b/drivers/register_driver_types.cpp @@ -28,21 +28,9 @@ /*************************************************************************/ #include "register_driver_types.h" +#include "core/math/geometry.h" #include "png/image_loader_png.h" -#include "webp/image_loader_webp.h" #include "png/resource_saver_png.h" -#include "jpegd/image_loader_jpegd.h" -#include "dds/texture_loader_dds.h" -#include "etc1/texture_loader_pkm.h" -#include "pvr/texture_loader_pvr.h" -#include "etc1/image_etc.h" -#include "chibi/event_stream_chibi.h" -#include "pnm/bitmap_loader_pnm.h" - - -#ifdef TOOLS_ENABLED -#include "squish/image_compress_squish.h" -#endif #ifdef TOOLS_ENABLED #include "convex_decomp/b2d_decompose.h" @@ -52,276 +40,38 @@ #include "platform/windows/export/export.h" #endif -#ifdef TREMOR_ENABLED -#include "teora/audio_stream_ogg.h" -#endif - -#ifdef VORBIS_ENABLED -#include "vorbis/audio_stream_ogg_vorbis.h" -#endif - -#ifdef OPUS_ENABLED -#include "opus/audio_stream_opus.h" -#endif - -#ifdef SPEEX_ENABLED -#include "speex/audio_stream_speex.h" -#endif - -#ifdef THEORA_ENABLED -#include "theora/video_stream_theora.h" -#endif - - #include "drivers/nrex/regex.h" -#ifdef MUSEPACK_ENABLED -#include "mpc/audio_stream_mpc.h" -#endif - -#ifdef PNG_ENABLED static ImageLoaderPNG *image_loader_png=NULL; static ResourceSaverPNG *resource_saver_png=NULL; -#endif - -#ifdef WEBP_ENABLED -static ImageLoaderWEBP *image_loader_webp=NULL; -//static ResourceSaverPNG *resource_saver_png=NULL; -#endif - -#ifdef JPG_ENABLED -static ImageLoaderJPG *image_loader_jpg=NULL; -#endif - -#ifdef DDS_ENABLED -static ResourceFormatDDS *resource_loader_dds=NULL; -#endif - -#ifdef ETC1_ENABLED -static ResourceFormatPKM *resource_loader_pkm=NULL; -#endif - - -#ifdef PVR_ENABLED -static ResourceFormatPVR *resource_loader_pvr=NULL; -#endif - -#ifdef TREMOR_ENABLED -static ResourceFormatLoaderAudioStreamOGG *vorbis_stream_loader=NULL; -#endif - -#ifdef VORBIS_ENABLED -static ResourceFormatLoaderAudioStreamOGGVorbis *vorbis_stream_loader=NULL; -#endif - -#ifdef OPUS_ENABLED -static ResourceFormatLoaderAudioStreamOpus *opus_stream_loader=NULL; -#endif - -#ifdef SPEEX_ENABLED -static ResourceFormatLoaderAudioStreamSpeex *speex_stream_loader=NULL; -#endif - -#ifdef THEORA_ENABLED -static ResourceFormatLoaderVideoStreamTheora* theora_stream_loader = NULL; -#endif - -#ifdef MUSEPACK_ENABLED -static ResourceFormatLoaderAudioStreamMPC * mpc_stream_loader=NULL; -#endif - -#ifdef OPENSSL_ENABLED -#include "openssl/register_openssl.h" -#endif - - -static ResourceFormatPBM * pbm_loader=NULL; void register_core_driver_types() { -#ifdef PNG_ENABLED image_loader_png = memnew( ImageLoaderPNG ); ImageLoader::add_image_format_loader( image_loader_png ); resource_saver_png = memnew( ResourceSaverPNG ); ResourceSaver::add_resource_format_saver(resource_saver_png); -#endif - -#ifdef WEBP_ENABLED - image_loader_webp = memnew( ImageLoaderWEBP ); - ImageLoader::add_image_format_loader( image_loader_webp ); - -// resource_saver_png = memnew( ResourceSaverPNG ); -// ResourceSaver::add_resource_format_saver(resource_saver_png); - -#endif - -#ifdef JPG_ENABLED - - image_loader_jpg = memnew( ImageLoaderJPG ); - ImageLoader::add_image_format_loader( image_loader_jpg ); -#endif - - - pbm_loader = memnew( ResourceFormatPBM ); - ResourceLoader::add_resource_format_loader(pbm_loader); - ObjectTypeDB::register_type<RegEx>(); } void unregister_core_driver_types() { -#ifdef PNG_ENABLED if (image_loader_png) memdelete( image_loader_png ); if (resource_saver_png) memdelete( resource_saver_png ); -#endif - -#ifdef WEBP_ENABLED - if (image_loader_webp) - memdelete( image_loader_webp ); -// if (resource_saver_png) -// memdelete( resource_saver_png ); -#endif - -#ifdef JPG_ENABLED - if (image_loader_jpg) - memdelete( image_loader_jpg ); -#endif - - memdelete( pbm_loader ); } void register_driver_types() { -#ifdef TREMOR_ENABLED - vorbis_stream_loader=memnew( ResourceFormatLoaderAudioStreamOGG ); - ResourceLoader::add_resource_format_loader(vorbis_stream_loader ); - ObjectTypeDB::register_type<AudioStreamOGG>(); -#endif - -#ifdef VORBIS_ENABLED - vorbis_stream_loader=memnew( ResourceFormatLoaderAudioStreamOGGVorbis ); - ResourceLoader::add_resource_format_loader(vorbis_stream_loader ); - ObjectTypeDB::register_type<AudioStreamOGGVorbis>(); -#endif - -#ifdef OPUS_ENABLED - opus_stream_loader=memnew( ResourceFormatLoaderAudioStreamOpus ); - ResourceLoader::add_resource_format_loader( opus_stream_loader ); - ObjectTypeDB::register_type<AudioStreamOpus>(); -#endif - -#ifdef DDS_ENABLED - resource_loader_dds = memnew( ResourceFormatDDS ); - ResourceLoader::add_resource_format_loader(resource_loader_dds ); -#endif - -#ifdef ETC1_ENABLED - resource_loader_pkm = memnew( ResourceFormatPKM ); - ResourceLoader::add_resource_format_loader(resource_loader_pkm); -#endif - -#ifdef PVR_ENABLED - resource_loader_pvr = memnew( ResourceFormatPVR ); - ResourceLoader::add_resource_format_loader(resource_loader_pvr ); -#endif - #ifdef TOOLS_ENABLED - Geometry::_decompose_func=b2d_decompose; #endif - -#ifdef SPEEX_ENABLED - speex_stream_loader=memnew( ResourceFormatLoaderAudioStreamSpeex ); - ResourceLoader::add_resource_format_loader(speex_stream_loader); - ObjectTypeDB::register_type<AudioStreamSpeex>(); -#endif - -#ifdef MUSEPACK_ENABLED - - mpc_stream_loader=memnew( ResourceFormatLoaderAudioStreamMPC ); - ResourceLoader::add_resource_format_loader(mpc_stream_loader); - ObjectTypeDB::register_type<AudioStreamMPC>(); - -#endif - -#ifdef OPENSSL_ENABLED - - register_openssl(); -#endif - -#ifdef THEORA_ENABLED - theora_stream_loader = memnew( ResourceFormatLoaderVideoStreamTheora ); - ResourceLoader::add_resource_format_loader(theora_stream_loader); - ObjectTypeDB::register_type<VideoStreamTheora>(); -#endif - - -#ifdef TOOLS_ENABLED -#ifdef SQUISH_ENABLED - - Image::set_compress_bc_func(image_compress_squish); - -#endif -#endif - -#ifdef ETC1_ENABLED - _register_etc1_compress_func(); -#endif - - initialize_chibi(); } void unregister_driver_types() { - - -#ifdef TREMOR_ENABLED - memdelete( vorbis_stream_loader ); -#endif - -#ifdef VORBIS_ENABLED - memdelete( vorbis_stream_loader ); -#endif - -#ifdef OPUS_ENABLED - memdelete( opus_stream_loader ); -#endif - -#ifdef SPEEX_ENABLED - memdelete( speex_stream_loader ); -#endif - -#ifdef THEORA_ENABLED - memdelete (theora_stream_loader); -#endif - - -#ifdef MUSEPACK_ENABLED - - memdelete (mpc_stream_loader); -#endif - -#ifdef DDS_ENABLED - memdelete(resource_loader_dds); -#endif - -#ifdef ETC1_ENABLED - memdelete(resource_loader_pkm); -#endif - -#ifdef PVR_ENABLED - memdelete(resource_loader_pvr); -#endif - -#ifdef OPENSSL_ENABLED - - unregister_openssl(); -#endif - - finalize_chibi(); } diff --git a/drivers/rtaudio/SCsub b/drivers/rtaudio/SCsub index 6699efef75..f0273dd421 100644 --- a/drivers/rtaudio/SCsub +++ b/drivers/rtaudio/SCsub @@ -1,4 +1,20 @@ +#!/usr/bin/env python + Import('env') -Export('env'); -env.add_source_files(env.drivers_sources,"*.cpp") +# Not cloning the env, the includes need to be accessible for platform/ + +# Thirdparty source files +thirdparty_dir = "#thirdparty/rtaudio/" +thirdparty_sources = [ + "RtAudio.cpp", +] +thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + +env.add_source_files(env.drivers_sources, thirdparty_sources) +env.Append(CPPPATH = [thirdparty_dir]) + +# Driver source files +env.add_source_files(env.drivers_sources, "*.cpp") + +Export('env') diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp index 1bea828680..fbe7ac68d4 100644 --- a/drivers/rtaudio/audio_driver_rtaudio.cpp +++ b/drivers/rtaudio/audio_driver_rtaudio.cpp @@ -27,8 +27,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "audio_driver_rtaudio.h" + #include "globals.h" #include "os/os.h" + #ifdef RTAUDIO_ENABLED const char* AudioDriverRtAudio::get_name() const { diff --git a/drivers/rtaudio/audio_driver_rtaudio.h b/drivers/rtaudio/audio_driver_rtaudio.h index ccb3d005c1..82055f6d17 100644 --- a/drivers/rtaudio/audio_driver_rtaudio.h +++ b/drivers/rtaudio/audio_driver_rtaudio.h @@ -32,7 +32,8 @@ #ifdef RTAUDIO_ENABLED #include "servers/audio/audio_server_sw.h" -#include "drivers/rtaudio/RtAudio.h" + +#include <RtAudio.h> class AudioDriverRtAudio : public AudioDriverSW { diff --git a/drivers/speex/SCsub b/drivers/speex/SCsub deleted file mode 100644 index 5094b259a2..0000000000 --- a/drivers/speex/SCsub +++ /dev/null @@ -1,55 +0,0 @@ -Import('env') - - - - -speex_sources = [\ -"speex/bits.c",\ -"speex/buffer.c",\ -"speex/cb_search.c",\ -"speex/exc_10_16_table.c",\ -"speex/exc_10_32_table.c",\ -"speex/exc_20_32_table.c",\ -"speex/exc_5_256_table.c",\ -"speex/exc_5_64_table.c",\ -"speex/exc_8_128_table.c",\ -"speex/fftwrap.c",\ -"speex/filterbank.c",\ -"speex/filters.c",\ -"speex/gain_table.c",\ -"speex/gain_table_lbr.c",\ -"speex/hexc_10_32_table.c",\ -"speex/hexc_table.c",\ -"speex/high_lsp_tables.c",\ -"speex/jitter.c",\ -"speex/kiss_fft.c",\ -"speex/kiss_fftr.c",\ -"speex/lpc.c",\ -"speex/lsp.c",\ -"speex/lsp_tables_nb.c",\ -"speex/ltp.c",\ -"speex/mdf.c",\ -"speex/modes.c",\ -"speex/modes_wb.c",\ -"speex/nb_celp.c",\ -"speex/preprocess.c",\ -"speex/quant_lsp.c",\ -"speex/resample.c",\ -"speex/sb_celp.c",\ -"speex/scal.c",\ -"speex/smallft.c",\ -"speex/speex.c",\ -"speex/speex_callbacks.c",\ -"speex/speex_header.c",\ -"speex/stereo.c",\ -"speex/vbr.c",\ -"speex/vq.c",\ -"speex/window.c",\ -"speex/audio_stream_speex.cpp", -] - -env.drivers_sources+=speex_sources - -#env.add_source_files(env.drivers_sources, speex_sources) - -Export('env') diff --git a/drivers/speex/_kiss_fft_guts.h b/drivers/speex/_kiss_fft_guts.h deleted file mode 100644 index 6571e79c0c..0000000000 --- a/drivers/speex/_kiss_fft_guts.h +++ /dev/null @@ -1,160 +0,0 @@ -/* -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. - * Neither the author nor the names of any 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. -*/ - -#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" -#include "math_approx.h" - -#define MAXFACTORS 32 -/* e.g. an fft of length 128 has 4 factors - as far as kissfft is concerned - 4*4*4*2 - */ - -struct kiss_fft_state{ - int nfft; - int inverse; - int factors[2*MAXFACTORS]; - kiss_fft_cpx twiddles[1]; -}; - -/* - 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 FRACBITS 15 -# define SAMPPROD spx_int32_t -#define SAMP_MAX 32767 - -#define SAMP_MIN -SAMP_MAX - -#if defined(CHECK_OVERFLOW) -# define CHECK_OVERFLOW_OP(a,op,b) \ - if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \ - fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); } -#endif - - -# define smul(a,b) ( (SAMPPROD)(a)*(b) ) -# define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS ) - -# define S_MUL(a,b) sround( smul(a,b) ) - -# define C_MUL(m,a,b) \ - do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ - (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) - -# define C_MUL4(m,a,b) \ - do{ (m).r = PSHR32( smul((a).r,(b).r) - smul((a).i,(b).i),17 ); \ - (m).i = PSHR32( smul((a).r,(b).i) + smul((a).i,(b).r),17 ); }while(0) - -# define DIVSCALAR(x,k) \ - (x) = sround( smul( x, SAMP_MAX/k ) ) - -# define C_FIXDIV(c,div) \ - do { DIVSCALAR( (c).r , div); \ - DIVSCALAR( (c).i , div); }while (0) - -# define C_MULBYSCALAR( c, s ) \ - do{ (c).r = sround( smul( (c).r , s ) ) ;\ - (c).i = sround( smul( (c).i , s ) ) ; }while(0) - -#else /* not FIXED_POINT*/ - -# define S_MUL(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_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 - -#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) - - -#ifdef FIXED_POINT -# define KISS_FFT_COS(phase) floor(MIN(32767,MAX(-32767,.5+32768 * cos (phase)))) -# define KISS_FFT_SIN(phase) floor(MIN(32767,MAX(-32767,.5+32768 * 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(.5)) -#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)*.5) -#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 = spx_cos_norm((phase));\ - (x)->i = spx_cos_norm((phase)-32768);\ -}while(0) - - -/* a debugging function */ -#define pcpx(c)\ - fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) diff --git a/drivers/speex/arch.h b/drivers/speex/arch.h deleted file mode 100644 index e2513dae48..0000000000 --- a/drivers/speex/arch.h +++ /dev/null @@ -1,249 +0,0 @@ -/* Copyright (C) 2003 Jean-Marc Valin */ -/** - @file arch.h - @brief Various architecture definitions Speex -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 ARCH_H -#define ARCH_H - -#ifndef SPEEX_VERSION -#define SPEEX_MAJOR_VERSION 1 /**< Major Speex version. */ -#define SPEEX_MINOR_VERSION 1 /**< Minor Speex version. */ -#define SPEEX_MICRO_VERSION 15 /**< Micro Speex version. */ -#define SPEEX_EXTRA_VERSION "" /**< Extra Speex version. */ -#define SPEEX_VERSION "speex-1.2beta3" /**< Speex version string. */ -#endif - -#include "os_support.h" -/* A couple test to catch stupid option combinations */ - -//custom engine code -#ifndef FIXED_POINT -#define FLOATING_POINT -#endif -#define USE_SMALLFT -#define EXPORT -//end of custom engine code - -#ifdef FIXED_POINT - -#ifdef FLOATING_POINT -#error You cannot compile as floating point and fixed point at the same time -#endif -#ifdef _USE_SSE -#error SSE is only for floating-point -#endif -#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM)) -#error Make up your mind. What CPU do you have? -#endif -#ifdef VORBIS_PSYCHO -#error Vorbis-psy model currently not implemented in fixed-point -#endif - -#else - -#ifndef FLOATING_POINT -#error You now need to define either FIXED_POINT or FLOATING_POINT -#endif -#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM) -#error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions? -#endif -#ifdef FIXED_POINT_DEBUG -#error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?" -#endif - - -#endif - -#ifndef OUTSIDE_SPEEX -#include "speex/speex_types.h" -#endif - -#define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */ -#define ABS16(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 16-bit value. */ -#define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 16-bit value. */ -#define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */ -#define ABS32(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 32-bit value. */ -#define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 32-bit value. */ -#define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */ - -#ifdef FIXED_POINT - -typedef spx_int16_t spx_word16_t; -typedef spx_int32_t spx_word32_t; -typedef spx_word32_t spx_mem_t; -typedef spx_word16_t spx_coef_t; -typedef spx_word16_t spx_lsp_t; -typedef spx_word32_t spx_sig_t; - -#define Q15ONE 32767 - -#define LPC_SCALING 8192 -#define SIG_SCALING 16384 -#define LSP_SCALING 8192. -#define GAMMA_SCALING 32768. -#define GAIN_SCALING 64 -#define GAIN_SCALING_1 0.015625 - -#define LPC_SHIFT 13 -#define LSP_SHIFT 13 -#define SIG_SHIFT 14 -#define GAIN_SHIFT 6 - -#define VERY_SMALL 0 -#define VERY_LARGE32 ((spx_word32_t)2147483647) -#define VERY_LARGE16 ((spx_word16_t)32767) -#define Q15_ONE ((spx_word16_t)32767) - - -#ifdef FIXED_DEBUG -#include "fixed_debug.h" -#else - -#include "fixed_generic.h" - -#ifdef ARM5E_ASM -#include "fixed_arm5e.h" -#elif defined (ARM4_ASM) -#include "fixed_arm4.h" -#elif defined (BFIN_ASM) -#include "fixed_bfin.h" -#endif - -#endif - - -#else - -typedef float spx_mem_t; -typedef float spx_coef_t; -typedef float spx_lsp_t; -typedef float spx_sig_t; -typedef float spx_word16_t; -typedef float spx_word32_t; - -#define Q15ONE 1.0f -#define LPC_SCALING 1.f -#define SIG_SCALING 1.f -#define LSP_SCALING 1.f -#define GAMMA_SCALING 1.f -#define GAIN_SCALING 1.f -#define GAIN_SCALING_1 1.f - - -#define VERY_SMALL 1e-15f -#define VERY_LARGE32 1e15f -#define VERY_LARGE16 1e15f -#define Q15_ONE ((spx_word16_t)1.f) - -#define QCONST16(x,bits) (x) -#define QCONST32(x,bits) (x) - -#define NEG16(x) (-(x)) -#define NEG32(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 PSHR16(a,shift) (a) -#define PSHR32(a,shift) (a) -#define VSHR32(a,shift) (a) -#define SATURATE16(x,a) (x) -#define SATURATE32(x,a) (x) - -#define PSHR(a,shift) (a) -#define SHR(a,shift) (a) -#define SHL(a,shift) (a) -#define SATURATE(x,a) (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 MULT16_16_16(a,b) ((a)*(b)) -#define MULT16_16(a,b) ((spx_word32_t)(a)*(spx_word32_t)(b)) -#define MAC16_16(c,a,b) ((c)+(spx_word32_t)(a)*(spx_word32_t)(b)) - -#define MULT16_32_Q11(a,b) ((a)*(b)) -#define MULT16_32_Q13(a,b) ((a)*(b)) -#define MULT16_32_Q14(a,b) ((a)*(b)) -#define MULT16_32_Q15(a,b) ((a)*(b)) -#define MULT16_32_P15(a,b) ((a)*(b)) - -#define MAC16_32_Q11(c,a,b) ((c)+(a)*(b)) -#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b)) - -#define MAC16_16_Q11(c,a,b) ((c)+(a)*(b)) -#define MAC16_16_Q13(c,a,b) ((c)+(a)*(b)) -#define MAC16_16_P13(c,a,b) ((c)+(a)*(b)) -#define MULT16_16_Q11_32(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 DIV32_16(a,b) (((spx_word32_t)(a))/(spx_word16_t)(b)) -#define PDIV32_16(a,b) (((spx_word32_t)(a))/(spx_word16_t)(b)) -#define DIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b)) -#define PDIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b)) - - -#endif - - -#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) - -/* 2 on TI C5x DSP */ -#define BYTES_PER_CHAR 2 -#define BITS_PER_CHAR 16 -#define LOG2_BITS_PER_CHAR 4 - -#else - -#define BYTES_PER_CHAR 1 -#define BITS_PER_CHAR 8 -#define LOG2_BITS_PER_CHAR 3 - -#endif - - - -#ifdef FIXED_DEBUG -extern long long spx_mips; -#endif - - -#endif diff --git a/drivers/speex/audio_stream_speex.cpp b/drivers/speex/audio_stream_speex.cpp deleted file mode 100644 index 3aa80fd0b9..0000000000 --- a/drivers/speex/audio_stream_speex.cpp +++ /dev/null @@ -1,581 +0,0 @@ -/*************************************************************************/ -/* audio_stream_speex.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "audio_stream_speex.h" - -#include "os_support.h" -#include "os/os.h" -#define READ_CHUNK 1024 - -static _FORCE_INLINE_ uint16_t le_short(uint16_t s) -{ - uint16_t ret=s; -#if 0 //def BIG_ENDIAN_ENABLED - ret = s>>8; - ret += s<<8; -#endif - return ret; -} - - -int AudioStreamPlaybackSpeex::mix(int16_t* p_buffer,int p_frames) { - - - - //printf("update, loops %i, read ofs %i\n", (int)loops, read_ofs); - //printf("playing %i, paused %i\n", (int)playing, (int)paused); - - if (!active || !playing || !data.size()) - return 0; - - /* - if (read_ofs >= data.size()) { - if (loops) { - reload(); - ++loop_count; - } else { - return; - }; - }; - */ - - int todo = p_frames; - if (todo < page_size) { - return 0; - }; - - int eos = 0; - - while (todo > page_size) { - - int ret=0; - while ((todo>page_size && packets_available && !eos) || (ret = ogg_sync_pageout(&oy, &og))==1) { - - if (!packets_available) { - /*Add page to the bitstream*/ - ogg_stream_pagein(&os, &og); - page_granule = ogg_page_granulepos(&og); - page_nb_packets = ogg_page_packets(&og); - packet_no=0; - if (page_granule>0 && frame_size) - { - skip_samples = page_nb_packets*frame_size*nframes - (page_granule-last_granule); - if (ogg_page_eos(&og)) - skip_samples = -skip_samples; - /*else if (!ogg_page_bos(&og)) - skip_samples = 0;*/ - } else - { - skip_samples = 0; - } - - - last_granule = page_granule; - packets_available=true; - } - /*Extract all available packets*/ - while (todo > page_size && !eos) { - - if (ogg_stream_packetout(&os, &op)!=1) { - packets_available=false; - break; - } - - packet_no++; - - - /*End of stream condition*/ - if (op.e_o_s) - eos=1; - - /*Copy Ogg packet to Speex bitstream*/ - speex_bits_read_from(&bits, (char*)op.packet, op.bytes); - - - for (int j=0;j!=nframes;j++) - { - - int16_t* out = p_buffer; - - int ret; - /*Decode frame*/ - ret = speex_decode_int(st, &bits, out); - - /*for (i=0;i<frame_size*channels;i++) - printf ("%d\n", (int)output[i]);*/ - - if (ret==-1) { - printf("decode returned -1\n"); - break; - }; - if (ret==-2) - { - OS::get_singleton()->printerr( "Decoding error: corrupted stream?\n"); - break; - } - if (speex_bits_remaining(&bits)<0) - { - OS::get_singleton()->printerr( "Decoding overflow: corrupted stream?\n"); - break; - } - //if (channels==2) - // speex_decode_stereo_int(output, frame_size, &stereo); - - - /*Convert to short and save to output file*/ - for (int i=0;i<frame_size*stream_channels;i++) { - out[i]=le_short(out[i]); - } - - - { - - int new_frame_size = frame_size; - - /*printf ("packet %d %d\n", packet_no, skip_samples);*/ - if (packet_no == 1 && j==0 && skip_samples > 0) - { - /*printf ("chopping first packet\n");*/ - new_frame_size -= skip_samples; - } - if (packet_no == page_nb_packets && skip_samples < 0) - { - int packet_length = nframes*frame_size+skip_samples; - new_frame_size = packet_length - j*frame_size; - if (new_frame_size<0) - new_frame_size = 0; - if (new_frame_size>frame_size) - new_frame_size = frame_size; - /*printf ("chopping end: %d %d %d\n", new_frame_size, packet_length, packet_no);*/ - } - - - p_buffer+=new_frame_size*stream_channels; - todo-=new_frame_size; - } - } - - }; - }; - //todo = get_todo(); - - //todo is still greater than page size, can write more - if (todo > page_size || eos) { - if (read_ofs < data.size()) { - - //char *buf; - int nb_read = MIN(data.size() - read_ofs, READ_CHUNK); - - /*Get the ogg buffer for writing*/ - char* ogg_dst = ogg_sync_buffer(&oy, nb_read); - /*Read bitstream from input file*/ - copymem(ogg_dst, &data[read_ofs], nb_read); - read_ofs += nb_read; - ogg_sync_wrote(&oy, nb_read); - } else { - if (loops) { - reload(); - ++loop_count; - //break; - } else { - playing=false; - unload(); - break; - }; - } - }; - }; - - return p_frames-todo; -}; - - -void AudioStreamPlaybackSpeex::unload() { - - - - if (!active) return; - - speex_bits_destroy(&bits); - if (st) - speex_decoder_destroy(st); - - ogg_sync_clear(&oy); - active = false; - //data.resize(0); - st = NULL; - - frame_size = 0; - page_size = 0; - loop_count = 0; -} - -void *AudioStreamPlaybackSpeex::process_header(ogg_packet *op, int *frame_size, int *rate, int *nframes, int *channels, int *extra_headers) { - - SpeexHeader *header; - int modeID; - - header = speex_packet_to_header((char*)op->packet, op->bytes); - if (!header) - { - OS::get_singleton()->printerr( "Cannot read header\n"); - return NULL; - } - if (header->mode >= SPEEX_NB_MODES) - { - OS::get_singleton()->printerr( "Mode number %d does not (yet/any longer) exist in this version\n", - header->mode); - return NULL; - } - - modeID = header->mode; - - const SpeexMode *mode = speex_lib_get_mode (modeID); - - if (header->speex_version_id > 1) - { - OS::get_singleton()->printerr( "This file was encoded with Speex bit-stream version %d, which I don't know how to decode\n", header->speex_version_id); - return NULL; - } - - if (mode->bitstream_version < header->mode_bitstream_version) - { - OS::get_singleton()->printerr( "The file was encoded with a newer version of Speex. You need to upgrade in order to play it.\n"); - return NULL; - } - if (mode->bitstream_version > header->mode_bitstream_version) - { - OS::get_singleton()->printerr( "The file was encoded with an older version of Speex. You would need to downgrade the version in order to play it.\n"); - return NULL; - } - - void* state = speex_decoder_init(mode); - if (!state) - { - OS::get_singleton()->printerr( "Decoder initialization failed.\n"); - return NULL; - } - //speex_decoder_ctl(state, SPEEX_SET_ENH, &enh_enabled); - speex_decoder_ctl(state, SPEEX_GET_FRAME_SIZE, frame_size); - - if (!*rate) - *rate = header->rate; - - speex_decoder_ctl(state, SPEEX_SET_SAMPLING_RATE, rate); - - *nframes = header->frames_per_packet; - - *channels = header->nb_channels; - - if (*channels!=1) { - OS::get_singleton()->printerr("Only MONO speex streams supported\n"); - return NULL; - } - - *extra_headers = header->extra_headers; - - speex_free(header); - return state; -} - - - -void AudioStreamPlaybackSpeex::reload() { - - - - if (active) - unload(); - - if (!data.size()) - return; - - ogg_sync_init(&oy); - speex_bits_init(&bits); - - read_ofs = 0; -// char *buf; - - int packet_count = 0; - int extra_headers = 0; - int stream_init = 0; - - page_granule=0; - last_granule=0; - skip_samples=0; - page_nb_packets=0; - packets_available=false; - packet_no=0; - - int eos = 0; - - do { - - /*Get the ogg buffer for writing*/ - int nb_read = MIN(data.size() - read_ofs, READ_CHUNK); - char* ogg_dst = ogg_sync_buffer(&oy, nb_read); - /*Read bitstream from input file*/ - copymem(ogg_dst, &data[read_ofs], nb_read); - read_ofs += nb_read; - ogg_sync_wrote(&oy, nb_read); - - /*Loop for all complete pages we got (most likely only one)*/ - while (ogg_sync_pageout(&oy, &og)==1) { - - if (stream_init == 0) { - ogg_stream_init(&os, ogg_page_serialno(&og)); - stream_init = 1; - } - /*Add page to the bitstream*/ - ogg_stream_pagein(&os, &og); - page_granule = ogg_page_granulepos(&og); - page_nb_packets = ogg_page_packets(&og); - if (page_granule>0 && frame_size) - { - skip_samples = page_nb_packets*frame_size*nframes - (page_granule-last_granule); - if (ogg_page_eos(&og)) - skip_samples = -skip_samples; - /*else if (!ogg_page_bos(&og)) - skip_samples = 0;*/ - } else - { - skip_samples = 0; - } - - - last_granule = page_granule; - /*Extract all available packets*/ - while (!eos && ogg_stream_packetout(&os, &op)==1) - { - /*If first packet, process as Speex header*/ - if (packet_count==0) - { - int rate = 0; - int channels; - st = process_header(&op, &frame_size, &rate, &nframes, &channels, &extra_headers); - if (!nframes) - nframes=1; - if (!st) { - unload(); - return; - }; - - page_size = nframes * frame_size; - stream_srate=rate; - stream_channels=channels; - stream_minbuff_size=page_size; - - - } else if (packet_count==1) - { - } else if (packet_count<=1+extra_headers) - { - /* Ignore extra headers */ - }; - }; - ++packet_count; - }; - - } while (packet_count <= extra_headers); - - active=true; - -} - -void AudioStreamPlaybackSpeex::_bind_methods() { - - //ObjectTypeDB::bind_method(_MD("set_file","file"),&AudioStreamPlaybackSpeex::set_file); -// ObjectTypeDB::bind_method(_MD("get_file"),&AudioStreamPlaybackSpeex::get_file); - - ObjectTypeDB::bind_method(_MD("_set_bundled"),&AudioStreamPlaybackSpeex::_set_bundled); - ObjectTypeDB::bind_method(_MD("_get_bundled"),&AudioStreamPlaybackSpeex::_get_bundled); - - ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_bundled",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_BUNDLE),_SCS("_set_bundled"),_SCS("_get_bundled")); - //ADD_PROPERTY( PropertyInfo(Variant::STRING,"file",PROPERTY_HINT_FILE,"*.spx"),_SCS("set_file"),_SCS("get_file")); -}; - -void AudioStreamPlaybackSpeex::_set_bundled(const Dictionary& dict) { - - ERR_FAIL_COND( !dict.has("filename")); - ERR_FAIL_COND( !dict.has("data")); - - filename = dict["filename"]; - data = dict["data"]; -}; - -Dictionary AudioStreamPlaybackSpeex::_get_bundled() const { - - Dictionary d; - d["filename"] = filename; - d["data"] = data; - return d; -}; - - - -void AudioStreamPlaybackSpeex::set_data(const Vector<uint8_t>& p_data) { - - data=p_data; - reload(); -} - - -void AudioStreamPlaybackSpeex::play(float p_from_pos) { - - - - reload(); - if (!active) - return; - playing = true; - -} -void AudioStreamPlaybackSpeex::stop(){ - - - unload(); - playing = false; - -} -bool AudioStreamPlaybackSpeex::is_playing() const{ - - return playing; -} - - -void AudioStreamPlaybackSpeex::set_loop(bool p_enable){ - - loops = p_enable; -} -bool AudioStreamPlaybackSpeex::has_loop() const{ - - return loops; -} - -float AudioStreamPlaybackSpeex::get_length() const{ - - return 0; -} - -String AudioStreamPlaybackSpeex::get_stream_name() const{ - - return ""; -} - -int AudioStreamPlaybackSpeex::get_loop_count() const{ - - return 0; -} - -float AudioStreamPlaybackSpeex::get_pos() const{ - - return 0; -} -void AudioStreamPlaybackSpeex::seek_pos(float p_time){ - - -}; - - - -AudioStreamPlaybackSpeex::AudioStreamPlaybackSpeex() { - - active=false; - st = NULL; - stream_channels=1; - stream_srate=1; - stream_minbuff_size=1; - playing=false; - - -} - -AudioStreamPlaybackSpeex::~AudioStreamPlaybackSpeex() { - - unload(); -} - - - - - -//////////////////////////////////////// - - - -void AudioStreamSpeex::set_file(const String& p_file) { - - if (this->file == p_file) - return; - - this->file=p_file; - - if (p_file == "") { - data.resize(0); - return; - }; - - Error err; - FileAccess* file = FileAccess::open(p_file, FileAccess::READ,&err); - if (err != OK) { - data.resize(0); - }; - ERR_FAIL_COND(err != OK); - - this->file = p_file; - data.resize(file->get_len()); - int read = file->get_buffer(&data[0], data.size()); - memdelete(file); - -} - -RES ResourceFormatLoaderAudioStreamSpeex::load(const String &p_path, const String& p_original_path, Error *r_error) { - - if (r_error) - *r_error=OK; - - AudioStreamSpeex *stream = memnew(AudioStreamSpeex); - stream->set_file(p_path); - return Ref<AudioStreamSpeex>(stream); -} - -void ResourceFormatLoaderAudioStreamSpeex::get_recognized_extensions(List<String> *p_extensions) const { - - p_extensions->push_back("spx"); -} -bool ResourceFormatLoaderAudioStreamSpeex::handles_type(const String& p_type) const { - - return (p_type=="AudioStream" || p_type=="AudioStreamSpeex"); -} - -String ResourceFormatLoaderAudioStreamSpeex::get_resource_type(const String &p_path) const { - - if (p_path.extension().to_lower()=="spx") - return "AudioStreamSpeex"; - return ""; -} diff --git a/drivers/speex/audio_stream_speex.h b/drivers/speex/audio_stream_speex.h deleted file mode 100644 index 491c593e47..0000000000 --- a/drivers/speex/audio_stream_speex.h +++ /dev/null @@ -1,153 +0,0 @@ -/*************************************************************************/ -/* audio_stream_speex.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef AUDIO_STREAM_SPEEX_H -#define AUDIO_STREAM_SPEEX_H - -#include "scene/resources/audio_stream.h" -#include "speex/speex.h" -#include "os/file_access.h" -#include "io/resource_loader.h" -#include "os/thread_safe.h" - -#include <speex/speex.h> -#include <speex/speex_header.h> -#include <speex/speex_stereo.h> -#include <speex/speex_callbacks.h> - -#include <ogg/ogg.h> - -class AudioStreamPlaybackSpeex : public AudioStreamPlayback { - - OBJ_TYPE(AudioStreamPlaybackSpeex, AudioStreamPlayback); - - - void *st; - SpeexBits bits; - Vector<uint8_t> data; - int read_ofs; - bool active; - String filename; - int loop_count; - bool loops; - int page_size; - bool playing; - bool packets_available; - - void unload(); - void reload(); - - ogg_sync_state oy; - ogg_page og; - ogg_packet op; - ogg_stream_state os; - int nframes; - int frame_size; - int packet_no; - - ogg_int64_t page_granule, last_granule; - int skip_samples, page_nb_packets; - int stream_channels; - int stream_srate; - int stream_minbuff_size; - - void* process_header(ogg_packet *op, int *frame_size, int *rate, int *nframes, int *channels, int *extra_headers); - - static void _bind_methods(); - -protected: - - //virtual bool _can_mix() const; - - Dictionary _get_bundled() const; - void _set_bundled(const Dictionary& dict); - -public: - - - void set_data(const Vector<uint8_t>& p_data); - - virtual void play(float p_from_pos=0); - virtual void stop(); - virtual bool is_playing() const; - - virtual void set_loop(bool p_enable); - virtual bool has_loop() const; - - virtual float get_length() const; - - virtual String get_stream_name() const; - - virtual int get_loop_count() const; - - virtual float get_pos() const; - virtual void seek_pos(float p_time); - - virtual int get_channels() const { return stream_channels; } - virtual int get_mix_rate() const { return stream_srate; } - - virtual int get_minimum_buffer_size() const { return stream_minbuff_size; } - virtual int mix(int16_t* p_bufer,int p_frames); - - virtual void set_loop_restart_time(float p_time) { } //no loop restart, ignore - - AudioStreamPlaybackSpeex(); - ~AudioStreamPlaybackSpeex(); -}; - - - -class AudioStreamSpeex : public AudioStream { - - OBJ_TYPE(AudioStreamSpeex,AudioStream); - - Vector<uint8_t> data; - String file; -public: - - Ref<AudioStreamPlayback> instance_playback() { - Ref<AudioStreamPlaybackSpeex> pb = memnew( AudioStreamPlaybackSpeex ); - pb->set_data(data); - return pb; - } - - void set_file(const String& p_file); - -}; - - -class ResourceFormatLoaderAudioStreamSpeex : public ResourceFormatLoader { -public: - virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); - virtual void get_recognized_extensions(List<String> *p_extensions) const; - virtual bool handles_type(const String& p_type) const; - virtual String get_resource_type(const String &p_path) const; - -}; - -#endif // AUDIO_STREAM_SPEEX_H diff --git a/drivers/speex/bits.c b/drivers/speex/bits.c deleted file mode 100644 index 66c6886066..0000000000 --- a/drivers/speex/bits.c +++ /dev/null @@ -1,372 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: speex_bits.c - - Handles bit packing/unpacking - - 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 the Xiph.org Foundation nor the names of its - 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 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. - -*/ - - -#include "config.h" - - -#include <speex/speex_bits.h> -#include "arch.h" -#include "os_support.h" - -/* Maximum size of the bit-stream (for fixed-size allocation) */ -#ifndef MAX_CHARS_PER_FRAME -#define MAX_CHARS_PER_FRAME (2000/BYTES_PER_CHAR) -#endif - -EXPORT void speex_bits_init(SpeexBits *bits) -{ - bits->chars = (char*)speex_alloc(MAX_CHARS_PER_FRAME); - if (!bits->chars) - return; - - bits->buf_size = MAX_CHARS_PER_FRAME; - - bits->owner=1; - - speex_bits_reset(bits); -} - -EXPORT void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size) -{ - bits->chars = (char*)buff; - bits->buf_size = buf_size; - - bits->owner=0; - - speex_bits_reset(bits); -} - -EXPORT void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size) -{ - bits->chars = (char*)buff; - bits->buf_size = buf_size; - - bits->owner=0; - - bits->nbBits=buf_size<<LOG2_BITS_PER_CHAR; - bits->charPtr=0; - bits->bitPtr=0; - bits->overflow=0; - -} - -EXPORT void speex_bits_destroy(SpeexBits *bits) -{ - if (bits->owner) - speex_free(bits->chars); - /* Will do something once the allocation is dynamic */ -} - -EXPORT void speex_bits_reset(SpeexBits *bits) -{ - /* We only need to clear the first byte now */ - bits->chars[0]=0; - bits->nbBits=0; - bits->charPtr=0; - bits->bitPtr=0; - bits->overflow=0; -} - -EXPORT void speex_bits_rewind(SpeexBits *bits) -{ - bits->charPtr=0; - bits->bitPtr=0; - bits->overflow=0; -} - -EXPORT void speex_bits_read_from(SpeexBits *bits, char *chars, int len) -{ - int i; - int nchars = len / BYTES_PER_CHAR; - if (nchars > bits->buf_size) - { - speex_notify("Packet is larger than allocated buffer"); - if (bits->owner) - { - char *tmp = (char*)speex_realloc(bits->chars, nchars); - if (tmp) - { - bits->buf_size=nchars; - bits->chars=tmp; - } else { - nchars=bits->buf_size; - speex_warning("Could not resize input buffer: truncating input"); - } - } else { - speex_warning("Do not own input buffer: truncating oversize input"); - nchars=bits->buf_size; - } - } -#if (BYTES_PER_CHAR==2) -/* Swap bytes to proper endian order (could be done externally) */ -#define HTOLS(A) ((((A) >> 8)&0xff)|(((A) & 0xff)<<8)) -#else -#define HTOLS(A) (A) -#endif - for (i=0;i<nchars;i++) - bits->chars[i]=HTOLS(chars[i]); - - bits->nbBits=nchars<<LOG2_BITS_PER_CHAR; - bits->charPtr=0; - bits->bitPtr=0; - bits->overflow=0; -} - -static void speex_bits_flush(SpeexBits *bits) -{ - int nchars = ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR); - if (bits->charPtr>0) - SPEEX_MOVE(bits->chars, &bits->chars[bits->charPtr], nchars-bits->charPtr); - bits->nbBits -= bits->charPtr<<LOG2_BITS_PER_CHAR; - bits->charPtr=0; -} - -EXPORT void speex_bits_read_whole_bytes(SpeexBits *bits, char *chars, int nbytes) -{ - int i,pos; - int nchars = nbytes/BYTES_PER_CHAR; - - if (((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR)+nchars > bits->buf_size) - { - /* Packet is larger than allocated buffer */ - if (bits->owner) - { - char *tmp = (char*)speex_realloc(bits->chars, (bits->nbBits>>LOG2_BITS_PER_CHAR)+nchars+1); - if (tmp) - { - bits->buf_size=(bits->nbBits>>LOG2_BITS_PER_CHAR)+nchars+1; - bits->chars=tmp; - } else { - nchars=bits->buf_size-(bits->nbBits>>LOG2_BITS_PER_CHAR)-1; - speex_warning("Could not resize input buffer: truncating oversize input"); - } - } else { - speex_warning("Do not own input buffer: truncating oversize input"); - nchars=bits->buf_size; - } - } - - speex_bits_flush(bits); - pos=bits->nbBits>>LOG2_BITS_PER_CHAR; - for (i=0;i<nchars;i++) - bits->chars[pos+i]=HTOLS(chars[i]); - bits->nbBits+=nchars<<LOG2_BITS_PER_CHAR; -} - -EXPORT int speex_bits_write(SpeexBits *bits, char *chars, int max_nbytes) -{ - int i; - int max_nchars = max_nbytes/BYTES_PER_CHAR; - int charPtr, bitPtr, nbBits; - - /* Insert terminator, but save the data so we can put it back after */ - bitPtr=bits->bitPtr; - charPtr=bits->charPtr; - nbBits=bits->nbBits; - speex_bits_insert_terminator(bits); - bits->bitPtr=bitPtr; - bits->charPtr=charPtr; - bits->nbBits=nbBits; - - if (max_nchars > ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR)) - max_nchars = ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR); - - for (i=0;i<max_nchars;i++) - chars[i]=HTOLS(bits->chars[i]); - return max_nchars*BYTES_PER_CHAR; -} - -EXPORT int speex_bits_write_whole_bytes(SpeexBits *bits, char *chars, int max_nbytes) -{ - int max_nchars = max_nbytes/BYTES_PER_CHAR; - int i; - if (max_nchars > ((bits->nbBits)>>LOG2_BITS_PER_CHAR)) - max_nchars = ((bits->nbBits)>>LOG2_BITS_PER_CHAR); - for (i=0;i<max_nchars;i++) - chars[i]=HTOLS(bits->chars[i]); - - if (bits->bitPtr>0) - bits->chars[0]=bits->chars[max_nchars]; - else - bits->chars[0]=0; - bits->charPtr=0; - bits->nbBits &= (BITS_PER_CHAR-1); - return max_nchars*BYTES_PER_CHAR; -} - -EXPORT void speex_bits_pack(SpeexBits *bits, int data, int nbBits) -{ - unsigned int d=data; - - if (bits->charPtr+((nbBits+bits->bitPtr)>>LOG2_BITS_PER_CHAR) >= bits->buf_size) - { - speex_notify("Buffer too small to pack bits"); - if (bits->owner) - { - int new_nchars = ((bits->buf_size+5)*3)>>1; - char *tmp = (char*)speex_realloc(bits->chars, new_nchars); - if (tmp) - { - bits->buf_size=new_nchars; - bits->chars=tmp; - } else { - speex_warning("Could not resize input buffer: not packing"); - return; - } - } else { - speex_warning("Do not own input buffer: not packing"); - return; - } - } - - while(nbBits) - { - int bit; - bit = (d>>(nbBits-1))&1; - bits->chars[bits->charPtr] |= bit<<(BITS_PER_CHAR-1-bits->bitPtr); - bits->bitPtr++; - - if (bits->bitPtr==BITS_PER_CHAR) - { - bits->bitPtr=0; - bits->charPtr++; - bits->chars[bits->charPtr] = 0; - } - bits->nbBits++; - nbBits--; - } -} - -EXPORT int speex_bits_unpack_signed(SpeexBits *bits, int nbBits) -{ - unsigned int d=speex_bits_unpack_unsigned(bits,nbBits); - /* If number is negative */ - if (d>>(nbBits-1)) - { - d |= (-1)<<nbBits; - } - return d; -} - -EXPORT unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits) -{ - unsigned int d=0; - if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits) - bits->overflow=1; - if (bits->overflow) - return 0; - while(nbBits) - { - d<<=1; - d |= (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1; - bits->bitPtr++; - if (bits->bitPtr==BITS_PER_CHAR) - { - bits->bitPtr=0; - bits->charPtr++; - } - nbBits--; - } - return d; -} - -EXPORT unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits) -{ - unsigned int d=0; - int bitPtr, charPtr; - char *chars; - - if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits) - bits->overflow=1; - if (bits->overflow) - return 0; - - bitPtr=bits->bitPtr; - charPtr=bits->charPtr; - chars = bits->chars; - while(nbBits) - { - d<<=1; - d |= (chars[charPtr]>>(BITS_PER_CHAR-1 - bitPtr))&1; - bitPtr++; - if (bitPtr==BITS_PER_CHAR) - { - bitPtr=0; - charPtr++; - } - nbBits--; - } - return d; -} - -EXPORT int speex_bits_peek(SpeexBits *bits) -{ - if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+1>bits->nbBits) - bits->overflow=1; - if (bits->overflow) - return 0; - return (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1; -} - -EXPORT void speex_bits_advance(SpeexBits *bits, int n) -{ - if (((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+n>bits->nbBits) || bits->overflow){ - bits->overflow=1; - return; - } - bits->charPtr += (bits->bitPtr+n) >> LOG2_BITS_PER_CHAR; /* divide by BITS_PER_CHAR */ - bits->bitPtr = (bits->bitPtr+n) & (BITS_PER_CHAR-1); /* modulo by BITS_PER_CHAR */ -} - -EXPORT int speex_bits_remaining(SpeexBits *bits) -{ - if (bits->overflow) - return -1; - else - return bits->nbBits-((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr); -} - -EXPORT int speex_bits_nbytes(SpeexBits *bits) -{ - return ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR); -} - -EXPORT void speex_bits_insert_terminator(SpeexBits *bits) -{ - if (bits->bitPtr) - speex_bits_pack(bits, 0, 1); - while (bits->bitPtr) - speex_bits_pack(bits, 1, 1); -} diff --git a/drivers/speex/buffer.c b/drivers/speex/buffer.c deleted file mode 100644 index 848840e8aa..0000000000 --- a/drivers/speex/buffer.c +++ /dev/null @@ -1,176 +0,0 @@ -/* Copyright (C) 2007 Jean-Marc Valin - - File: buffer.c - This is a very simple ring buffer implementation. It is not thread-safe - so you need to do your own locking. - - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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. -*/ - - -#include "config.h" - - - -#include "os_support.h" -#include "arch.h" -#include <speex/speex_buffer.h> - -struct SpeexBuffer_ { - char *data; - int size; - int read_ptr; - int write_ptr; - int available; -}; - -EXPORT SpeexBuffer *speex_buffer_init(int size) -{ - SpeexBuffer *st = speex_alloc(sizeof(SpeexBuffer)); - st->data = speex_alloc(size); - st->size = size; - st->read_ptr = 0; - st->write_ptr = 0; - st->available = 0; - return st; -} - -EXPORT void speex_buffer_destroy(SpeexBuffer *st) -{ - speex_free(st->data); - speex_free(st); -} - -EXPORT int speex_buffer_write(SpeexBuffer *st, void *_data, int len) -{ - int end; - int end1; - char *data = _data; - if (len > st->size) - { - data += len-st->size; - len = st->size; - } - end = st->write_ptr + len; - end1 = end; - if (end1 > st->size) - end1 = st->size; - SPEEX_COPY(st->data + st->write_ptr, data, end1 - st->write_ptr); - if (end > st->size) - { - end -= st->size; - SPEEX_COPY(st->data, data+end1 - st->write_ptr, end); - } - st->available += len; - if (st->available > st->size) - { - st->available = st->size; - st->read_ptr = st->write_ptr; - } - st->write_ptr += len; - if (st->write_ptr > st->size) - st->write_ptr -= st->size; - return len; -} - -EXPORT int speex_buffer_writezeros(SpeexBuffer *st, int len) -{ - /* This is almost the same as for speex_buffer_write() but using - SPEEX_MEMSET() instead of SPEEX_COPY(). Update accordingly. */ - int end; - int end1; - if (len > st->size) - { - len = st->size; - } - end = st->write_ptr + len; - end1 = end; - if (end1 > st->size) - end1 = st->size; - SPEEX_MEMSET(st->data + st->write_ptr, 0, end1 - st->write_ptr); - if (end > st->size) - { - end -= st->size; - SPEEX_MEMSET(st->data, 0, end); - } - st->available += len; - if (st->available > st->size) - { - st->available = st->size; - st->read_ptr = st->write_ptr; - } - st->write_ptr += len; - if (st->write_ptr > st->size) - st->write_ptr -= st->size; - return len; -} - -EXPORT int speex_buffer_read(SpeexBuffer *st, void *_data, int len) -{ - int end, end1; - char *data = _data; - if (len > st->available) - { - SPEEX_MEMSET(data+st->available, 0, st->size-st->available); - len = st->available; - } - end = st->read_ptr + len; - end1 = end; - if (end1 > st->size) - end1 = st->size; - SPEEX_COPY(data, st->data + st->read_ptr, end1 - st->read_ptr); - - if (end > st->size) - { - end -= st->size; - SPEEX_COPY(data+end1 - st->read_ptr, st->data, end); - } - st->available -= len; - st->read_ptr += len; - if (st->read_ptr > st->size) - st->read_ptr -= st->size; - return len; -} - -EXPORT int speex_buffer_get_available(SpeexBuffer *st) -{ - return st->available; -} - -EXPORT int speex_buffer_resize(SpeexBuffer *st, int len) -{ - int old_len = st->size; - if (len > old_len) - { - st->data = speex_realloc(st->data, len); - /* FIXME: move data/pointers properly for growing the buffer */ - } else { - /* FIXME: move data/pointers properly for shrinking the buffer */ - st->data = speex_realloc(st->data, len); - } - return len; -} diff --git a/drivers/speex/cb_search.c b/drivers/speex/cb_search.c deleted file mode 100644 index 7fbfe1a2f1..0000000000 --- a/drivers/speex/cb_search.c +++ /dev/null @@ -1,612 +0,0 @@ -/* Copyright (C) 2002-2006 Jean-Marc Valin - File: cb_search.c - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -#include "config.h" - - -#include "cb_search.h" -#include "filters.h" -#include "stack_alloc.h" -#include "vq.h" -#include "arch.h" -#include "math_approx.h" -#include "os_support.h" - -#ifdef _USE_SSE -#include "cb_search_sse.h" -#elif defined(ARM4_ASM) || defined(ARM5E_ASM) -#include "cb_search_arm4.h" -#elif defined(BFIN_ASM) -#include "cb_search_bfin.h" -#endif - -#ifndef OVERRIDE_COMPUTE_WEIGHTED_CODEBOOK -static void compute_weighted_codebook(const signed char *shape_cb, const spx_word16_t *r, spx_word16_t *resp, spx_word16_t *resp2, spx_word32_t *E, int shape_cb_size, int subvect_size, char *stack) -{ - int i, j, k; - VARDECL(spx_word16_t *shape); - ALLOC(shape, subvect_size, spx_word16_t); - for (i=0;i<shape_cb_size;i++) - { - spx_word16_t *res; - - res = resp+i*subvect_size; - for (k=0;k<subvect_size;k++) - shape[k] = (spx_word16_t)shape_cb[i*subvect_size+k]; - E[i]=0; - - /* Compute codeword response using convolution with impulse response */ - for(j=0;j<subvect_size;j++) - { - spx_word32_t resj=0; - spx_word16_t res16; - for (k=0;k<=j;k++) - resj = MAC16_16(resj,shape[k],r[j-k]); -#ifdef FIXED_POINT - res16 = EXTRACT16(SHR32(resj, 13)); -#else - res16 = 0.03125f*resj; -#endif - /* Compute codeword energy */ - E[i]=MAC16_16(E[i],res16,res16); - res[j] = res16; - /*printf ("%d\n", (int)res[j]);*/ - } - } - -} -#endif - -#ifndef OVERRIDE_TARGET_UPDATE -static SPEEX_INLINE void target_update(spx_word16_t *t, spx_word16_t g, spx_word16_t *r, int len) -{ - int n; - for (n=0;n<len;n++) - t[n] = SUB16(t[n],PSHR32(MULT16_16(g,r[n]),13)); -} -#endif - - - -static void split_cb_search_shape_sign_N1( -spx_word16_t target[], /* target vector */ -spx_coef_t ak[], /* LPCs for this subframe */ -spx_coef_t awk1[], /* Weighted LPCs for this subframe */ -spx_coef_t awk2[], /* Weighted LPCs for this subframe */ -const void *par, /* Codebook/search parameters*/ -int p, /* number of LPC coeffs */ -int nsf, /* number of samples in subframe */ -spx_sig_t *exc, -spx_word16_t *r, -SpeexBits *bits, -char *stack, -int update_target -) -{ - int i,j,m,q; - VARDECL(spx_word16_t *resp); -#ifdef _USE_SSE - VARDECL(__m128 *resp2); - VARDECL(__m128 *E); -#else - spx_word16_t *resp2; - VARDECL(spx_word32_t *E); -#endif - VARDECL(spx_word16_t *t); - VARDECL(spx_sig_t *e); - const signed char *shape_cb; - int shape_cb_size, subvect_size, nb_subvect; - const split_cb_params *params; - int best_index; - spx_word32_t best_dist; - int have_sign; - - params = (const split_cb_params *) par; - subvect_size = params->subvect_size; - nb_subvect = params->nb_subvect; - shape_cb_size = 1<<params->shape_bits; - shape_cb = params->shape_cb; - have_sign = params->have_sign; - ALLOC(resp, shape_cb_size*subvect_size, spx_word16_t); -#ifdef _USE_SSE - ALLOC(resp2, (shape_cb_size*subvect_size)>>2, __m128); - ALLOC(E, shape_cb_size>>2, __m128); -#else - resp2 = resp; - ALLOC(E, shape_cb_size, spx_word32_t); -#endif - ALLOC(t, nsf, spx_word16_t); - ALLOC(e, nsf, spx_sig_t); - - /* FIXME: Do we still need to copy the target? */ - SPEEX_COPY(t, target, nsf); - - compute_weighted_codebook(shape_cb, r, resp, resp2, E, shape_cb_size, subvect_size, stack); - - for (i=0;i<nb_subvect;i++) - { - spx_word16_t *x=t+subvect_size*i; - /*Find new n-best based on previous n-best j*/ - if (have_sign) - vq_nbest_sign(x, resp2, subvect_size, shape_cb_size, E, 1, &best_index, &best_dist, stack); - else - vq_nbest(x, resp2, subvect_size, shape_cb_size, E, 1, &best_index, &best_dist, stack); - - speex_bits_pack(bits,best_index,params->shape_bits+have_sign); - - { - int rind; - spx_word16_t *res; - spx_word16_t sign=1; - rind = best_index; - if (rind>=shape_cb_size) - { - sign=-1; - rind-=shape_cb_size; - } - res = resp+rind*subvect_size; - if (sign>0) - for (m=0;m<subvect_size;m++) - t[subvect_size*i+m] = SUB16(t[subvect_size*i+m], res[m]); - else - for (m=0;m<subvect_size;m++) - t[subvect_size*i+m] = ADD16(t[subvect_size*i+m], res[m]); - -#ifdef FIXED_POINT - if (sign==1) - { - for (j=0;j<subvect_size;j++) - e[subvect_size*i+j]=SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5); - } else { - for (j=0;j<subvect_size;j++) - e[subvect_size*i+j]=NEG32(SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5)); - } -#else - for (j=0;j<subvect_size;j++) - e[subvect_size*i+j]=sign*0.03125*shape_cb[rind*subvect_size+j]; -#endif - - } - - for (m=0;m<subvect_size;m++) - { - spx_word16_t g; - int rind; - spx_word16_t sign=1; - rind = best_index; - if (rind>=shape_cb_size) - { - sign=-1; - rind-=shape_cb_size; - } - - q=subvect_size-m; -#ifdef FIXED_POINT - g=sign*shape_cb[rind*subvect_size+m]; -#else - g=sign*0.03125*shape_cb[rind*subvect_size+m]; -#endif - target_update(t+subvect_size*(i+1), g, r+q, nsf-subvect_size*(i+1)); - } - } - - /* Update excitation */ - /* FIXME: We could update the excitation directly above */ - for (j=0;j<nsf;j++) - exc[j]=ADD32(exc[j],e[j]); - - /* Update target: only update target if necessary */ - if (update_target) - { - VARDECL(spx_word16_t *r2); - ALLOC(r2, nsf, spx_word16_t); - for (j=0;j<nsf;j++) - r2[j] = EXTRACT16(PSHR32(e[j] ,6)); - syn_percep_zero16(r2, ak, awk1, awk2, r2, nsf,p, stack); - for (j=0;j<nsf;j++) - target[j]=SUB16(target[j],PSHR16(r2[j],2)); - } -} - - - -void split_cb_search_shape_sign( -spx_word16_t target[], /* target vector */ -spx_coef_t ak[], /* LPCs for this subframe */ -spx_coef_t awk1[], /* Weighted LPCs for this subframe */ -spx_coef_t awk2[], /* Weighted LPCs for this subframe */ -const void *par, /* Codebook/search parameters*/ -int p, /* number of LPC coeffs */ -int nsf, /* number of samples in subframe */ -spx_sig_t *exc, -spx_word16_t *r, -SpeexBits *bits, -char *stack, -int complexity, -int update_target -) -{ - int i,j,k,m,n,q; - VARDECL(spx_word16_t *resp); -#ifdef _USE_SSE - VARDECL(__m128 *resp2); - VARDECL(__m128 *E); -#else - spx_word16_t *resp2; - VARDECL(spx_word32_t *E); -#endif - VARDECL(spx_word16_t *t); - VARDECL(spx_sig_t *e); - VARDECL(spx_word16_t *tmp); - VARDECL(spx_word32_t *ndist); - VARDECL(spx_word32_t *odist); - VARDECL(int *itmp); - VARDECL(spx_word16_t **ot2); - VARDECL(spx_word16_t **nt2); - spx_word16_t **ot, **nt; - VARDECL(int **nind); - VARDECL(int **oind); - VARDECL(int *ind); - const signed char *shape_cb; - int shape_cb_size, subvect_size, nb_subvect; - const split_cb_params *params; - int N=2; - VARDECL(int *best_index); - VARDECL(spx_word32_t *best_dist); - VARDECL(int *best_nind); - VARDECL(int *best_ntarget); - int have_sign; - N=complexity; - if (N>10) - N=10; - /* Complexity isn't as important for the codebooks as it is for the pitch */ - N=(2*N)/3; - if (N<1) - N=1; - if (N==1) - { - split_cb_search_shape_sign_N1(target,ak,awk1,awk2,par,p,nsf,exc,r,bits,stack,update_target); - return; - } - ALLOC(ot2, N, spx_word16_t*); - ALLOC(nt2, N, spx_word16_t*); - ALLOC(oind, N, int*); - ALLOC(nind, N, int*); - - params = (const split_cb_params *) par; - subvect_size = params->subvect_size; - nb_subvect = params->nb_subvect; - shape_cb_size = 1<<params->shape_bits; - shape_cb = params->shape_cb; - have_sign = params->have_sign; - ALLOC(resp, shape_cb_size*subvect_size, spx_word16_t); -#ifdef _USE_SSE - ALLOC(resp2, (shape_cb_size*subvect_size)>>2, __m128); - ALLOC(E, shape_cb_size>>2, __m128); -#else - resp2 = resp; - ALLOC(E, shape_cb_size, spx_word32_t); -#endif - ALLOC(t, nsf, spx_word16_t); - ALLOC(e, nsf, spx_sig_t); - ALLOC(ind, nb_subvect, int); - - ALLOC(tmp, 2*N*nsf, spx_word16_t); - for (i=0;i<N;i++) - { - ot2[i]=tmp+2*i*nsf; - nt2[i]=tmp+(2*i+1)*nsf; - } - ot=ot2; - nt=nt2; - ALLOC(best_index, N, int); - ALLOC(best_dist, N, spx_word32_t); - ALLOC(best_nind, N, int); - ALLOC(best_ntarget, N, int); - ALLOC(ndist, N, spx_word32_t); - ALLOC(odist, N, spx_word32_t); - - ALLOC(itmp, 2*N*nb_subvect, int); - for (i=0;i<N;i++) - { - nind[i]=itmp+2*i*nb_subvect; - oind[i]=itmp+(2*i+1)*nb_subvect; - } - - SPEEX_COPY(t, target, nsf); - - for (j=0;j<N;j++) - SPEEX_COPY(&ot[j][0], t, nsf); - - /* Pre-compute codewords response and energy */ - compute_weighted_codebook(shape_cb, r, resp, resp2, E, shape_cb_size, subvect_size, stack); - - for (j=0;j<N;j++) - odist[j]=0; - - /*For all subvectors*/ - for (i=0;i<nb_subvect;i++) - { - /*"erase" nbest list*/ - for (j=0;j<N;j++) - ndist[j]=VERY_LARGE32; - /* This is not strictly necessary, but it provides an additonal safety - to prevent crashes in case something goes wrong in the previous - steps (e.g. NaNs) */ - for (j=0;j<N;j++) - best_nind[j] = best_ntarget[j] = 0; - /*For all n-bests of previous subvector*/ - for (j=0;j<N;j++) - { - spx_word16_t *x=ot[j]+subvect_size*i; - spx_word32_t tener = 0; - for (m=0;m<subvect_size;m++) - tener = MAC16_16(tener, x[m],x[m]); -#ifdef FIXED_POINT - tener = SHR32(tener,1); -#else - tener *= .5; -#endif - /*Find new n-best based on previous n-best j*/ - if (have_sign) - vq_nbest_sign(x, resp2, subvect_size, shape_cb_size, E, N, best_index, best_dist, stack); - else - vq_nbest(x, resp2, subvect_size, shape_cb_size, E, N, best_index, best_dist, stack); - - /*For all new n-bests*/ - for (k=0;k<N;k++) - { - /* Compute total distance (including previous sub-vectors */ - spx_word32_t err = ADD32(ADD32(odist[j],best_dist[k]),tener); - - /*update n-best list*/ - if (err<ndist[N-1]) - { - for (m=0;m<N;m++) - { - if (err < ndist[m]) - { - for (n=N-1;n>m;n--) - { - ndist[n] = ndist[n-1]; - best_nind[n] = best_nind[n-1]; - best_ntarget[n] = best_ntarget[n-1]; - } - /* n is equal to m here, so they're interchangeable */ - ndist[m] = err; - best_nind[n] = best_index[k]; - best_ntarget[n] = j; - break; - } - } - } - } - if (i==0) - break; - } - for (j=0;j<N;j++) - { - /*previous target (we don't care what happened before*/ - for (m=(i+1)*subvect_size;m<nsf;m++) - nt[j][m]=ot[best_ntarget[j]][m]; - - /* New code: update the rest of the target only if it's worth it */ - for (m=0;m<subvect_size;m++) - { - spx_word16_t g; - int rind; - spx_word16_t sign=1; - rind = best_nind[j]; - if (rind>=shape_cb_size) - { - sign=-1; - rind-=shape_cb_size; - } - - q=subvect_size-m; -#ifdef FIXED_POINT - g=sign*shape_cb[rind*subvect_size+m]; -#else - g=sign*0.03125*shape_cb[rind*subvect_size+m]; -#endif - target_update(nt[j]+subvect_size*(i+1), g, r+q, nsf-subvect_size*(i+1)); - } - - for (q=0;q<nb_subvect;q++) - nind[j][q]=oind[best_ntarget[j]][q]; - nind[j][i]=best_nind[j]; - } - - /*update old-new data*/ - /* just swap pointers instead of a long copy */ - { - spx_word16_t **tmp2; - tmp2=ot; - ot=nt; - nt=tmp2; - } - for (j=0;j<N;j++) - for (m=0;m<nb_subvect;m++) - oind[j][m]=nind[j][m]; - for (j=0;j<N;j++) - odist[j]=ndist[j]; - } - - /*save indices*/ - for (i=0;i<nb_subvect;i++) - { - ind[i]=nind[0][i]; - speex_bits_pack(bits,ind[i],params->shape_bits+have_sign); - } - - /* Put everything back together */ - for (i=0;i<nb_subvect;i++) - { - int rind; - spx_word16_t sign=1; - rind = ind[i]; - if (rind>=shape_cb_size) - { - sign=-1; - rind-=shape_cb_size; - } -#ifdef FIXED_POINT - if (sign==1) - { - for (j=0;j<subvect_size;j++) - e[subvect_size*i+j]=SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5); - } else { - for (j=0;j<subvect_size;j++) - e[subvect_size*i+j]=NEG32(SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5)); - } -#else - for (j=0;j<subvect_size;j++) - e[subvect_size*i+j]=sign*0.03125*shape_cb[rind*subvect_size+j]; -#endif - } - /* Update excitation */ - for (j=0;j<nsf;j++) - exc[j]=ADD32(exc[j],e[j]); - - /* Update target: only update target if necessary */ - if (update_target) - { - VARDECL(spx_word16_t *r2); - ALLOC(r2, nsf, spx_word16_t); - for (j=0;j<nsf;j++) - r2[j] = EXTRACT16(PSHR32(e[j] ,6)); - syn_percep_zero16(r2, ak, awk1, awk2, r2, nsf,p, stack); - for (j=0;j<nsf;j++) - target[j]=SUB16(target[j],PSHR16(r2[j],2)); - } -} - - -void split_cb_shape_sign_unquant( -spx_sig_t *exc, -const void *par, /* non-overlapping codebook */ -int nsf, /* number of samples in subframe */ -SpeexBits *bits, -char *stack, -spx_int32_t *seed -) -{ - int i,j; - VARDECL(int *ind); - VARDECL(int *signs); - const signed char *shape_cb; - int shape_cb_size, subvect_size, nb_subvect; - const split_cb_params *params; - int have_sign; - - params = (const split_cb_params *) par; - subvect_size = params->subvect_size; - nb_subvect = params->nb_subvect; - shape_cb_size = 1<<params->shape_bits; - shape_cb = params->shape_cb; - have_sign = params->have_sign; - - ALLOC(ind, nb_subvect, int); - ALLOC(signs, nb_subvect, int); - - /* Decode codewords and gains */ - for (i=0;i<nb_subvect;i++) - { - if (have_sign) - signs[i] = speex_bits_unpack_unsigned(bits, 1); - else - signs[i] = 0; - ind[i] = speex_bits_unpack_unsigned(bits, params->shape_bits); - } - /* Compute decoded excitation */ - for (i=0;i<nb_subvect;i++) - { - spx_word16_t s=1; - if (signs[i]) - s=-1; -#ifdef FIXED_POINT - if (s==1) - { - for (j=0;j<subvect_size;j++) - exc[subvect_size*i+j]=SHL32(EXTEND32(shape_cb[ind[i]*subvect_size+j]),SIG_SHIFT-5); - } else { - for (j=0;j<subvect_size;j++) - exc[subvect_size*i+j]=NEG32(SHL32(EXTEND32(shape_cb[ind[i]*subvect_size+j]),SIG_SHIFT-5)); - } -#else - for (j=0;j<subvect_size;j++) - exc[subvect_size*i+j]+=s*0.03125*shape_cb[ind[i]*subvect_size+j]; -#endif - } -} - -void noise_codebook_quant( -spx_word16_t target[], /* target vector */ -spx_coef_t ak[], /* LPCs for this subframe */ -spx_coef_t awk1[], /* Weighted LPCs for this subframe */ -spx_coef_t awk2[], /* Weighted LPCs for this subframe */ -const void *par, /* Codebook/search parameters*/ -int p, /* number of LPC coeffs */ -int nsf, /* number of samples in subframe */ -spx_sig_t *exc, -spx_word16_t *r, -SpeexBits *bits, -char *stack, -int complexity, -int update_target -) -{ - int i; - VARDECL(spx_word16_t *tmp); - ALLOC(tmp, nsf, spx_word16_t); - residue_percep_zero16(target, ak, awk1, awk2, tmp, nsf, p, stack); - - for (i=0;i<nsf;i++) - exc[i]+=SHL32(EXTEND32(tmp[i]),8); - SPEEX_MEMSET(target, 0, nsf); -} - - -void noise_codebook_unquant( -spx_sig_t *exc, -const void *par, /* non-overlapping codebook */ -int nsf, /* number of samples in subframe */ -SpeexBits *bits, -char *stack, -spx_int32_t *seed -) -{ - int i; - /* FIXME: This is bad, but I don't think the function ever gets called anyway */ - for (i=0;i<nsf;i++) - exc[i]=SHL32(EXTEND32(speex_rand(1, seed)),SIG_SHIFT); -} diff --git a/drivers/speex/cb_search.h b/drivers/speex/cb_search.h deleted file mode 100644 index 7687b453fd..0000000000 --- a/drivers/speex/cb_search.h +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin & David Rowe */ -/** - @file cb_search.h - @brief Overlapped codebook search -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 CB_SEARCH_H -#define CB_SEARCH_H - -#include <speex/speex_bits.h> -#include "arch.h" - -/** Split codebook parameters. */ -typedef struct split_cb_params { - int subvect_size; - int nb_subvect; - const signed char *shape_cb; - int shape_bits; - int have_sign; -} split_cb_params; - - -void split_cb_search_shape_sign( -spx_word16_t target[], /* target vector */ -spx_coef_t ak[], /* LPCs for this subframe */ -spx_coef_t awk1[], /* Weighted LPCs for this subframe */ -spx_coef_t awk2[], /* Weighted LPCs for this subframe */ -const void *par, /* Codebook/search parameters */ -int p, /* number of LPC coeffs */ -int nsf, /* number of samples in subframe */ -spx_sig_t *exc, -spx_word16_t *r, -SpeexBits *bits, -char *stack, -int complexity, -int update_target -); - -void split_cb_shape_sign_unquant( -spx_sig_t *exc, -const void *par, /* non-overlapping codebook */ -int nsf, /* number of samples in subframe */ -SpeexBits *bits, -char *stack, -spx_int32_t *seed -); - - -void noise_codebook_quant( -spx_word16_t target[], /* target vector */ -spx_coef_t ak[], /* LPCs for this subframe */ -spx_coef_t awk1[], /* Weighted LPCs for this subframe */ -spx_coef_t awk2[], /* Weighted LPCs for this subframe */ -const void *par, /* Codebook/search parameters */ -int p, /* number of LPC coeffs */ -int nsf, /* number of samples in subframe */ -spx_sig_t *exc, -spx_word16_t *r, -SpeexBits *bits, -char *stack, -int complexity, -int update_target -); - - -void noise_codebook_unquant( -spx_sig_t *exc, -const void *par, /* non-overlapping codebook */ -int nsf, /* number of samples in subframe */ -SpeexBits *bits, -char *stack, -spx_int32_t *seed -); - -#endif diff --git a/drivers/speex/cb_search_arm4.h b/drivers/speex/cb_search_arm4.h deleted file mode 100644 index 19b752a4bc..0000000000 --- a/drivers/speex/cb_search_arm4.h +++ /dev/null @@ -1,137 +0,0 @@ -/* Copyright (C) 2004 Jean-Marc Valin */ -/** - @file cb_search_arm4.h - @brief Fixed codebook functions (ARM4 version) -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -/* This optimization is temporaly disabled until it is fixed to account for the fact - that "r" is now a 16-bit array */ -#if 0 -#define OVERRIDE_COMPUTE_WEIGHTED_CODEBOOK -static void compute_weighted_codebook(const signed char *shape_cb, const spx_word16_t *r, spx_word16_t *resp, spx_word16_t *resp2, spx_word32_t *E, int shape_cb_size, int subvect_size, char *stack) -{ - int i, j, k; - //const signed char *shape; - for (i=0;i<shape_cb_size;i+=4) - { - - //shape = shape_cb; - E[0]=0; - E[1]=0; - E[2]=0; - E[3]=0; - - /* Compute codeword response using convolution with impulse response */ - for(j=0;j<subvect_size;j++) - { -#if 1 - spx_word16_t *res; - res = resp+j; - spx_word32_t resj0,resj1,resj2,resj3; - spx_word32_t dead1, dead2, dead3, dead4, dead5, dead6, dead7, dead8; - __asm__ __volatile__ ( - "mov %0, #0 \n\t" - "mov %1, #0 \n\t" - "mov %2, #0 \n\t" - "mov %3, #0 \n\t" - ".weighted%=: \n\t" - "ldrsb %8, [%6] \n\t" - "ldr %10, [%5], #-4 \n\t" - "mov %9, %6 \n\t" - "ldrsb %11, [%9, %7]! \n\t" - "mla %0, %10, %8, %0 \n\t" - "ldrsb %8, [%9, %7]! \n\t" - "mla %1, %10, %11, %1 \n\t" - "ldrsb %11, [%9, %7]! \n\t" - "mla %2, %10, %8, %2 \n\t" - "subs %4, %4, #1 \n\t" - "mla %3, %10, %11, %3 \n\t" - "add %6, %6, #1 \n\t" - "bne .weighted%= \n\t" - : "=r" (resj0), "=r" (resj1), "=r" (resj2), "=r" (resj3), - "=r" (dead1), "=r" (dead2), "=r" (dead3), "=r" (dead4), - "=r" (dead5), "=r" (dead6), "=r" (dead7), "=r" (dead8) - : "4" (j+1), "5" (r+j), "6" (shape_cb), "7" (subvect_size) - : "cc", "memory"); -#else - spx_word16_t *res; - res = resp+j; - spx_word32_t resj0=0; - spx_word32_t resj1=0; - spx_word32_t resj2=0; - spx_word32_t resj3=0; - for (k=0;k<=j;k++) - { - const signed char *shape=shape_cb+k; - resj0 = MAC16_16(resj0,*shape,r[j-k]); - shape += subvect_size; - resj1 = MAC16_16(resj1,*shape,r[j-k]); - shape += subvect_size; - resj2 = MAC16_16(resj2,*shape,r[j-k]); - shape += subvect_size; - resj3 = MAC16_16(resj3,*shape,r[j-k]); - shape += subvect_size; - } -#endif - -#ifdef FIXED_POINT - resj0 = SHR(resj0, 11); - resj1 = SHR(resj1, 11); - resj2 = SHR(resj2, 11); - resj3 = SHR(resj3, 11); -#else - resj0 *= 0.03125; - resj1 *= 0.03125; - resj2 *= 0.03125; - resj3 *= 0.03125; -#endif - - /* Compute codeword energy */ - E[0]=ADD32(E[0],MULT16_16(resj0,resj0)); - E[1]=ADD32(E[1],MULT16_16(resj1,resj1)); - E[2]=ADD32(E[2],MULT16_16(resj2,resj2)); - E[3]=ADD32(E[3],MULT16_16(resj3,resj3)); - *res = resj0; - res += subvect_size; - *res = resj1; - res += subvect_size; - *res = resj2; - res += subvect_size; - *res = resj3; - res += subvect_size; - } - resp += subvect_size<<2; - shape_cb += subvect_size<<2; - E+=4; - } - -} -#endif diff --git a/drivers/speex/cb_search_bfin.h b/drivers/speex/cb_search_bfin.h deleted file mode 100644 index ae9cf8343d..0000000000 --- a/drivers/speex/cb_search_bfin.h +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright (C) 2005 Analog Devices */ -/** - @author Jean-Marc Valin - @file cb_search_bfin.h - @brief Fixed codebook functions (Blackfin version) -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#define OVERRIDE_COMPUTE_WEIGHTED_CODEBOOK -void compute_weighted_codebook(const signed char *shape_cb, const spx_word16_t *r, spx_word16_t *resp, spx_word16_t *resp2, spx_word32_t *E, int shape_cb_size, int subvect_size, char *stack) -{ - int i; - for (i=0;i<shape_cb_size;i++) - { - __asm__ __volatile__ ( - "P0 = %0;\n\t" - "LC0 = P0;\n\t" - "P1 = %1;\n\t" - "P2 = %2;\n\t" - "P3 = %3;\n\t" - "P0 = 1;\n\t" - "L0 = 0;\n\t" - "L1 = 0;\n\t" - "R2 = 0;\n\t" - "A1 = 0;\n\t" - "LOOP outter%= LC0;\n\t" - "LOOP_BEGIN outter%=;\n\t" - "A0 = 0;\n\t" - "P4 = P1;\n\t" - "I1 = P2;\n\t" - "R0 = B[P4++] (X) || R1.L = W[I1--];\n\t" - "LOOP inner%= LC1 = P0;\n\t" - "LOOP_BEGIN inner%=;\n\t" - "A0 += R0.L*R1.L (IS) || R0 = B[P4++] (X) || R1.L = W[I1--];\n\t" - "LOOP_END inner%=;\n\t" - "R0 = A0;\n\t" - "R0 >>>= 13;\n\t" - "A1 += R0.L*R0.L (IS);\n\t" - "W[P3++] = R0;\n\t" - "P0 += 1;\n\t" - "P2 += 2;\n\t" - "LOOP_END outter%=;\n\t" - "P4 = %4;\n\t" - "R1 = A1;\n\t" - "[P4] = R1;\n\t" - : - : "m" (subvect_size), "m" (shape_cb), "m" (r), "m" (resp), "m" (E) - : "A0", "P0", "P1", "P2", "P3", "P4", "R0", "R1", "R2", "I0", "I1", "L0", - "L1", "A0", "A1", "memory" -#if !(__GNUC__ == 3) - , "LC0", "LC1" /* gcc 3.4 doesn't know about LC registers */ -#endif - ); - shape_cb += subvect_size; - resp += subvect_size; - E++; - } -} - -#define OVERRIDE_TARGET_UPDATE -static inline void target_update(spx_word16_t *t, spx_word16_t g, spx_word16_t *r, int len) -{ - if (!len) - return; - __asm__ __volatile__ - ( - "I0 = %0;\n\t" - "I1 = %1;\n\t" - "L0 = 0;\n\t" - "L1 = 0;\n\t" - "R2 = 4096;\n\t" - "LOOP tupdate%= LC0 = %3;\n\t" - "LOOP_BEGIN tupdate%=;\n\t" - "R0.L = W[I0] || R1.L = W[I1++];\n\t" - "R1 = (A1 = R1.L*%2.L) (IS);\n\t" - "R1 = R1 + R2;\n\t" - "R1 >>>= 13;\n\t" - "R0.L = R0.L - R1.L;\n\t" - "W[I0++] = R0.L;\n\t" - "LOOP_END tupdate%=;\n\t" - : - : "a" (t), "a" (r), "d" (g), "a" (len) - : "R0", "R1", "R2", "A1", "I0", "I1", "L0", "L1" - ); -} diff --git a/drivers/speex/cb_search_sse.h b/drivers/speex/cb_search_sse.h deleted file mode 100644 index 8b039686fb..0000000000 --- a/drivers/speex/cb_search_sse.h +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 2004 Jean-Marc Valin */ -/** - @file cb_search_sse.h - @brief Fixed codebook functions (SSE version) -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#include <xmmintrin.h> - -static inline void _spx_mm_getr_ps (__m128 U, float *__Z, float *__Y, float *__X, float *__W) -{ - union { - float __a[4]; - __m128 __v; - } __u; - - __u.__v = U; - - *__Z = __u.__a[0]; - *__Y = __u.__a[1]; - *__X = __u.__a[2]; - *__W = __u.__a[3]; - -} - -#define OVERRIDE_COMPUTE_WEIGHTED_CODEBOOK -static void compute_weighted_codebook(const signed char *shape_cb, const spx_sig_t *_r, float *resp, __m128 *resp2, __m128 *E, int shape_cb_size, int subvect_size, char *stack) -{ - int i, j, k; - __m128 resj, EE; - VARDECL(__m128 *r); - VARDECL(__m128 *shape); - ALLOC(r, subvect_size, __m128); - ALLOC(shape, subvect_size, __m128); - for(j=0;j<subvect_size;j++) - r[j] = _mm_load_ps1(_r+j); - for (i=0;i<shape_cb_size;i+=4) - { - float *_res = resp+i*subvect_size; - const signed char *_shape = shape_cb+i*subvect_size; - EE = _mm_setzero_ps(); - for(j=0;j<subvect_size;j++) - { - shape[j] = _mm_setr_ps(0.03125*_shape[j], 0.03125*_shape[subvect_size+j], 0.03125*_shape[2*subvect_size+j], 0.03125*_shape[3*subvect_size+j]); - } - for(j=0;j<subvect_size;j++) - { - resj = _mm_setzero_ps(); - for (k=0;k<=j;k++) - resj = _mm_add_ps(resj, _mm_mul_ps(shape[k],r[j-k])); - _spx_mm_getr_ps(resj, _res+j, _res+subvect_size+j, _res+2*subvect_size+j, _res+3*subvect_size+j); - *resp2++ = resj; - EE = _mm_add_ps(EE, _mm_mul_ps(resj, resj)); - } - E[i>>2] = EE; - } -} diff --git a/drivers/speex/config.h b/drivers/speex/config.h deleted file mode 100644 index 8c48e3b99d..0000000000 --- a/drivers/speex/config.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - Copyright (C) 2003 Commonwealth Scientific and Industrial Research - Organisation (CSIRO) Australia - - 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 CSIRO Australia nor the names of its - 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 ORGANISATION OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 CONFIG_H -#define CONFIG_H - -/* An inline macro is required for use of the inline keyword as not all C compilers support */ -/* inline. It is officially C99 and C++ only */ - - -/* Use only fixed point arithmetic */ - -//#ifdef _MSC_VER -//#define inline _inline -//#endif - -#define FIXED_POINT 1 - -#ifdef _MSC_VER -#define inline __inline -#endif - -#endif /* ! CONFIG_H */ diff --git a/drivers/speex/echo_diagnostic.m b/drivers/speex/echo_diagnostic.m deleted file mode 100644 index aebf390672..0000000000 --- a/drivers/speex/echo_diagnostic.m +++ /dev/null @@ -1,72 +0,0 @@ -% Attempts to diagnose AEC problems from recorded samples -% -% out = echo_diagnostic(rec_file, play_file, out_file, tail_length) -% -% Computes the full matrix inversion to cancel echo from the -% recording 'rec_file' using the far end signal 'play_file' using -% a filter length of 'tail_length'. The output is saved to 'out_file'. -function out = echo_diagnostic(rec_file, play_file, out_file, tail_length) - -F=fopen(rec_file,'rb'); -rec=fread(F,Inf,'short'); -fclose (F); -F=fopen(play_file,'rb'); -play=fread(F,Inf,'short'); -fclose (F); - -rec = [rec; zeros(1024,1)]; -play = [play; zeros(1024,1)]; - -N = length(rec); -corr = real(ifft(fft(rec).*conj(fft(play)))); -acorr = real(ifft(fft(play).*conj(fft(play)))); - -[a,b] = max(corr); - -if b > N/2 - b = b-N; -end -printf ("Far end to near end delay is %d samples\n", b); -if (b > .3*tail_length) - printf ('This is too much delay, try delaying the far-end signal a bit\n'); -else if (b < 0) - printf ('You have a negative delay, the echo canceller has no chance to cancel anything!\n'); - else - printf ('Delay looks OK.\n'); - end - end -end -N2 = round(N/2); -corr1 = real(ifft(fft(rec(1:N2)).*conj(fft(play(1:N2))))); -corr2 = real(ifft(fft(rec(N2+1:end)).*conj(fft(play(N2+1:end))))); - -[a,b1] = max(corr1); -if b1 > N2/2 - b1 = b1-N2; -end -[a,b2] = max(corr2); -if b2 > N2/2 - b2 = b2-N2; -end -drift = (b1-b2)/N2; -printf ('Drift estimate is %f%% (%d samples)\n', 100*drift, b1-b2); -if abs(b1-b2) < 10 - printf ('A drift of a few (+-10) samples is normal.\n'); -else - if abs(b1-b2) < 30 - printf ('There may be (not sure) excessive clock drift. Is the capture and playback done on the same soundcard?\n'); - else - printf ('Your clock is drifting! No way the AEC will be able to do anything with that. Most likely, you''re doing capture and playback from two different cards.\n'); - end - end -end -acorr(1) = .001+1.00001*acorr(1); -AtA = toeplitz(acorr(1:tail_length)); -bb = corr(1:tail_length); -h = AtA\bb; - -out = (rec - filter(h, 1, play)); - -F=fopen(out_file,'w'); -fwrite(F,out,'short'); -fclose (F); diff --git a/drivers/speex/exc_10_16_table.c b/drivers/speex/exc_10_16_table.c deleted file mode 100644 index 98ae357d8c..0000000000 --- a/drivers/speex/exc_10_16_table.c +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: exc_10_16_table.c - Codebook for excitation in narrowband CELP mode (3200 bps) - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -const signed char exc_10_16_table[160] = { -22,39,14,44,11,35,-2,23,-4,6, -46,-28,13,-27,-23,12,4,20,-5,9, -37,-18,-23,23,0,9,-6,-20,4,-1, --17,-5,-4,17,0,1,9,-2,1,2, -2,-12,8,-25,39,15,9,16,-55,-11, -9,11,5,10,-2,-60,8,13,-6,11, --16,27,-47,-12,11,1,16,-7,9,-3, --29,9,-14,25,-19,34,36,12,40,-10, --3,-24,-14,-37,-21,-35,-2,-36,3,-6, -67,28,6,-17,-3,-12,-16,-15,-17,-7, --59,-36,-13,1,7,1,2,10,2,11, -13,10,8,-2,7,3,5,4,2,2, --3,-8,4,-5,6,7,-42,15,35,-2, --46,38,28,-20,-9,1,7,-3,0,-2, -0,0,0,0,0,0,0,0,0,0, --15,-28,52,32,5,-5,-17,-20,-10,-1}; diff --git a/drivers/speex/exc_10_32_table.c b/drivers/speex/exc_10_32_table.c deleted file mode 100644 index 1ee56a2595..0000000000 --- a/drivers/speex/exc_10_32_table.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: exc_10_32_table.c - Codebook for excitation in narrowband CELP mode (4000 bps) - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -const signed char exc_10_32_table[320] = { -7,17,17,27,25,22,12,4,-3,0, -28,-36,39,-24,-15,3,-9,15,-5,10, -31,-28,11,31,-21,9,-11,-11,-2,-7, --25,14,-22,31,4,-14,19,-12,14,-5, -4,-7,4,-5,9,0,-2,42,-47,-16, -1,8,0,9,23,-57,0,28,-11,6, --31,55,-45,3,-5,4,2,-2,4,-7, --3,6,-2,7,-3,12,5,8,54,-10, -8,-7,-8,-24,-25,-27,-14,-5,8,5, -44,23,5,-9,-11,-11,-13,-9,-12,-8, --29,-8,-22,6,-15,3,-12,-1,-5,-3, -34,-1,29,-16,17,-4,12,2,1,4, --2,-4,2,-1,11,-3,-52,28,30,-9, --32,25,44,-20,-24,4,6,-1,0,0, -0,0,0,0,0,0,0,0,0,0, --25,-10,22,29,13,-13,-22,-13,-4,0, --4,-16,10,15,-36,-24,28,25,-1,-3, -66,-33,-11,-15,6,0,3,4,-2,5, -24,-20,-47,29,19,-2,-4,-1,0,-1, --2,3,1,8,-11,5,5,-57,28,28, -0,-16,4,-4,12,-6,-1,2,-20,61, --9,24,-22,-42,29,6,17,8,4,2, --65,15,8,10,5,6,5,3,2,-2, --3,5,-9,4,-5,23,13,23,-3,-63, -3,-5,-4,-6,0,-3,23,-36,-46,9, -5,5,8,4,9,-5,1,-3,10,1, --6,10,-11,24,-47,31,22,-12,14,-10, -6,11,-7,-7,7,-31,51,-12,-6,7, -6,-17,9,-11,-20,52,-19,3,-6,-6, --8,-5,23,-41,37,1,-21,10,-14,8, -7,5,-15,-15,23,39,-26,-33,7,2, --32,-30,-21,-8,4,12,17,15,14,11}; diff --git a/drivers/speex/exc_20_32_table.c b/drivers/speex/exc_20_32_table.c deleted file mode 100644 index e4098b8d1c..0000000000 --- a/drivers/speex/exc_20_32_table.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: exc_20_32_table.c - Codebook for excitation in narrowband CELP mode (2000 bps) - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -const signed char exc_20_32_table[640] = { -12,32,25,46,36,33,9,14,-3,6,1,-8,0,-10,-5,-7,-7,-7,-5,-5, -31,-27,24,-32,-4,10,-11,21,-3,19,23,-9,22,24,-10,-1,-10,-13,-7,-11, -42,-33,31,19,-8,0,-10,-16,1,-21,-17,10,-8,14,8,4,11,-2,5,-2, --33,11,-16,33,11,-4,9,-4,11,2,6,-5,8,-5,11,-4,-6,26,-36,-16, -0,4,-2,-8,12,6,-1,34,-46,-22,9,9,21,9,5,-66,-5,26,2,10, -13,2,19,9,12,-81,3,13,13,0,-14,22,-35,6,-7,-4,6,-6,10,-6, --31,38,-33,0,-10,-11,5,-12,12,-17,5,0,-6,13,-9,10,8,25,33,2, --12,8,-6,10,-2,21,7,17,43,5,11,-7,-9,-20,-36,-20,-23,-4,-4,-3, -27,-9,-9,-49,-39,-38,-11,-9,6,5,23,25,5,3,3,4,1,2,-3,-1, -87,39,17,-21,-9,-19,-9,-15,-13,-14,-17,-11,-10,-11,-8,-6,-1,-3,-3,-1, --54,-34,-27,-8,-11,-4,-5,0,0,4,8,6,9,7,9,7,6,5,5,5, -48,10,19,-10,12,-1,9,-3,2,5,-3,2,-2,-2,0,-2,-26,6,9,-7, --16,-9,2,7,7,-5,-43,11,22,-11,-9,34,37,-15,-13,-6,1,-1,1,1, --64,56,52,-11,-27,5,4,3,1,2,1,3,-1,-4,-4,-10,-7,-4,-4,2, --1,-7,-7,-12,-10,-15,-9,-5,-5,-11,-16,-13,6,16,4,-13,-16,-10,-4,2, --47,-13,25,47,19,-14,-20,-8,-17,0,-3,-13,1,6,-17,-14,15,1,10,6, --24,0,-10,19,-69,-8,14,49,17,-5,33,-29,3,-4,0,2,-8,5,-6,2, -120,-56,-12,-47,23,-9,6,-5,1,2,-5,1,-10,4,-1,-1,4,-1,0,-3, -30,-52,-67,30,22,11,-1,-4,3,0,7,2,0,1,-10,-4,-8,-13,5,1, -1,-1,5,13,-9,-3,-10,-62,22,48,-4,-6,2,3,5,1,1,4,1,13, -3,-20,10,-9,13,-2,-4,9,-20,44,-1,20,-32,-67,19,0,28,11,8,2, --11,15,-19,-53,31,2,34,10,6,-4,-58,8,10,13,14,1,12,2,0,0, --128,37,-8,44,-9,26,-3,18,2,6,11,-1,9,1,5,3,0,1,1,2, -12,3,-2,-3,7,25,9,18,-6,-37,3,-8,-16,3,-10,-7,17,-34,-44,11, -17,-15,-3,-16,-1,-13,11,-46,-65,-2,8,13,2,4,4,5,15,5,9,6, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, --9,19,-12,12,-28,38,29,-1,12,2,5,23,-10,3,4,-15,21,-4,3,3, -6,17,-9,-4,-8,-20,26,5,-10,6,1,-19,18,-15,-12,47,-6,-2,-7,-9, --1,-17,-2,-2,-14,30,-14,2,-7,-4,-1,-12,11,-25,16,-3,-12,11,-7,7, --17,1,19,-28,31,-7,-10,7,-10,3,12,5,-16,6,24,41,-29,-54,0,1, -7,-1,5,-6,13,10,-4,-8,8,-9,-27,-53,-38,-1,10,19,17,16,12,12, -0,3,-7,-4,13,12,-31,-14,6,-5,3,5,17,43,50,25,10,1,-6,-2}; diff --git a/drivers/speex/exc_5_256_table.c b/drivers/speex/exc_5_256_table.c deleted file mode 100644 index 4137996d4f..0000000000 --- a/drivers/speex/exc_5_256_table.c +++ /dev/null @@ -1,290 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: exc_5_256_table.c - Codebook for excitation in narrowband CELP mode (12800 bps) - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -const signed char exc_5_256_table[1280] = { --8,-37,5,-43,5, -73,61,39,12,-3, --61,-32,2,42,30, --3,17,-27,9,34, -20,-1,-5,2,23, --7,-46,26,53,-47, -20,-2,-33,-89,-51, --64,27,11,15,-34, --5,-56,25,-9,-1, --29,1,40,67,-23, --16,16,33,19,7, -14,85,22,-10,-10, --12,-7,-1,52,89, -29,11,-20,-37,-46, --15,17,-24,-28,24, -2,1,0,23,-101, -23,14,-1,-23,-18, -9,5,-13,38,1, --28,-28,4,27,51, --26,34,-40,35,47, -54,38,-54,-26,-6, -42,-25,13,-30,-36, -18,41,-4,-33,23, --32,-7,-4,51,-3, -17,-52,56,-47,36, --2,-21,36,10,8, --33,31,19,9,-5, --40,10,-9,-21,19, -18,-78,-18,-5,0, --26,-36,-47,-51,-44, -18,40,27,-2,29, -49,-26,2,32,-54, -30,-73,54,3,-5, -36,22,53,10,-1, --84,-53,-29,-5,3, --44,53,-51,4,22, -71,-35,-1,33,-5, --27,-7,36,17,-23, --39,16,-9,-55,-15, --20,39,-35,6,-39, --14,18,48,-64,-17, --15,9,39,81,37, --68,37,47,-21,-6, --104,13,6,9,-2, -35,8,-23,18,42, -45,21,33,-5,-49, -9,-6,-43,-56,39, -2,-16,-25,87,1, --3,-9,17,-25,-11, --9,-1,10,2,-14, --14,4,-1,-10,28, --23,40,-32,26,-9, -26,4,-27,-23,3, -42,-60,1,49,-3, -27,10,-52,-40,-2, -18,45,-23,17,-44, -3,-3,17,-46,52, --40,-47,25,75,31, --49,53,30,-30,-32, --36,38,-6,-15,-16, -54,-27,-48,3,38, --29,-32,-22,-14,-4, --23,-13,32,-39,9, -8,-45,-13,34,-16, -49,40,32,31,28, -23,23,32,47,59, --68,8,62,44,25, --14,-24,-65,-16,36, -67,-25,-38,-21,4, --33,-2,42,5,-63, -40,11,26,-42,-23, --61,79,-31,23,-20, -10,-32,53,-25,-36, -10,-26,-5,3,0, --71,5,-10,-37,1, --24,21,-54,-17,1, --29,-25,-15,-27,32, -68,45,-16,-37,-18, --5,1,0,-77,71, --6,3,-20,71,-67, -29,-35,10,-30,19, -4,16,17,5,0, --14,19,2,28,26, -59,3,2,24,39, -55,-50,-45,-18,-17, -33,-35,14,-1,1, -8,87,-35,-29,0, --27,13,-7,23,-13, -37,-40,50,-35,14, -19,-7,-14,49,54, --5,22,-2,-29,-8, --27,38,13,27,48, -12,-41,-21,-15,28, -7,-16,-24,-19,-20, -11,-20,9,2,13, -23,-20,11,27,-27, -71,-69,8,2,-6, -22,12,16,16,9, --16,-8,-17,1,25, -1,40,-37,-33,66, -94,53,4,-22,-25, --41,-42,25,35,-16, --15,57,31,-29,-32, -21,16,-60,45,15, --1,7,57,-26,-47, --29,11,8,15,19, --105,-8,54,27,10, --17,6,-12,-1,-10, -4,0,23,-10,31, -13,11,10,12,-64, -23,-3,-8,-19,16, -52,24,-40,16,10, -40,5,9,0,-13, --7,-21,-8,-6,-7, --21,59,16,-53,18, --60,11,-47,14,-18, -25,-13,-24,4,-39, -16,-28,54,26,-67, -30,27,-20,-52,20, --12,55,12,18,-16, -39,-14,-6,-26,56, --88,-55,12,25,26, --37,6,75,0,-34, --81,54,-30,1,-7, -49,-23,-14,21,10, --62,-58,-57,-47,-34, -15,-4,34,-78,31, -25,-11,7,50,-10, -42,-63,14,-36,-4, -57,55,57,53,42, --42,-1,15,40,37, -15,25,-11,6,1, -31,-2,-6,-1,-7, --64,34,28,30,-1, -3,21,0,-88,-12, --56,25,-28,40,8, --28,-14,9,12,2, --6,-17,22,49,-6, --26,14,28,-20,4, --12,50,35,40,13, --38,-58,-29,17,30, -22,60,26,-54,-39, --12,58,-28,-63,10, --21,-8,-12,26,-62, -6,-10,-11,-22,-6, --7,4,1,18,2, --70,11,14,4,13, -19,-24,-34,24,67, -17,51,-21,13,23, -54,-30,48,1,-13, -80,26,-16,-2,13, --4,6,-30,29,-24, -73,-58,30,-27,20, --2,-21,41,45,30, --27,-3,-5,-18,-20, --49,-3,-35,10,42, --19,-67,-53,-11,9, -13,-15,-33,-51,-30, -15,7,25,-30,4, -28,-22,-34,54,-29, -39,-46,20,16,34, --4,47,75,1,-44, --55,-24,7,-1,9, --42,50,-8,-36,41, -68,0,-4,-10,-23, --15,-50,64,36,-9, --27,12,25,-38,-47, --37,32,-49,51,-36, -2,-4,69,-26,19, -7,45,67,46,13, --63,46,15,-47,4, --41,13,-6,5,-21, -37,26,-55,-7,33, --1,-28,10,-17,-64, --14,0,-36,-17,93, --3,-9,-66,44,-21, -3,-12,38,-6,-13, --12,19,13,43,-43, --10,-12,6,-5,9, --49,32,-5,2,4, -5,15,-16,10,-21, -8,-62,-8,64,8, -79,-1,-66,-49,-18, -5,40,-5,-30,-45, -1,-6,21,-32,93, --18,-30,-21,32,21, --18,22,8,5,-41, --54,80,22,-10,-7, --8,-23,-64,66,56, --14,-30,-41,-46,-14, --29,-37,27,-14,42, --2,-9,-29,34,14, -33,-14,22,4,10, -26,26,28,32,23, --72,-32,3,0,-14, -35,-42,-78,-32,6, -29,-18,-45,-5,7, --33,-45,-3,-22,-34, -8,-8,4,-51,-25, --9,59,-78,21,-5, --25,-48,66,-15,-17, --24,-49,-13,25,-23, --64,-6,40,-24,-19, --11,57,-33,-8,1, -10,-52,-54,28,39, -49,34,-11,-61,-41, --43,10,15,-15,51, -30,15,-51,32,-34, --2,-34,14,18,16, -1,1,-3,-3,1, -1,-18,6,16,48, -12,-5,-42,7,36, -48,7,-20,-10,7, -12,2,54,39,-38, -37,54,4,-11,-8, --46,-10,5,-10,-34, -46,-12,29,-37,39, -36,-11,24,56,17, -14,20,25,0,-25, --28,55,-7,-5,27, -3,9,-26,-8,6, --24,-10,-30,-31,-34, -18,4,22,21,40, --1,-29,-37,-8,-21, -92,-29,11,-3,11, -73,23,22,7,4, --44,-9,-11,21,-13, -11,9,-78,-1,47, -114,-12,-37,-19,-5, --11,-22,19,12,-30, -7,38,45,-21,-8, --9,55,-45,56,-21, -7,17,46,-57,-87, --6,27,31,31,7, --56,-12,46,21,-5, --12,36,3,3,-21, -43,19,12,-7,9, --14,0,-9,-33,-91, -7,26,3,-11,64, -83,-31,-46,25,2, -9,5,2,2,-1, -20,-17,10,-5,-27, --8,20,8,-19,16, --21,-13,-31,5,5, -42,24,9,34,-20, -28,-61,22,11,-39, -64,-20,-1,-30,-9, --20,24,-25,-24,-29, -22,-60,6,-5,41, --9,-87,14,34,15, --57,52,69,15,-3, --102,58,16,3,6, -60,-75,-32,26,7, --57,-27,-32,-24,-21, --29,-16,62,-46,31, -30,-27,-15,7,15}; diff --git a/drivers/speex/exc_5_64_table.c b/drivers/speex/exc_5_64_table.c deleted file mode 100644 index 2c66d5189e..0000000000 --- a/drivers/speex/exc_5_64_table.c +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: exc_5_64_table.c - Codebook for excitation in narrowband CELP mode (9600 bps) - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -const signed char exc_5_64_table[320]={ -1,5,-15,49,-66, --48,-4,50,-44,7, -37,16,-18,25,-26, --26,-15,19,19,-27, --47,28,57,5,-17, --32,-41,68,21,-2, -64,56,8,-16,-13, --26,-9,-16,11,6, --39,25,-19,22,-31, -20,-45,55,-43,10, --16,47,-40,40,-20, --51,3,-17,-14,-15, --24,53,-20,-46,46, -27,-68,32,3,-18, --5,9,-31,16,-9, --10,-1,-23,48,95, -47,25,-41,-32,-3, -15,-25,-55,36,41, --27,20,5,13,14, --22,5,2,-23,18, -46,-15,17,-18,-34, --5,-8,27,-55,73, -16,2,-1,-17,40, --78,33,0,2,19, -4,53,-16,-15,-16, --28,-3,-13,49,8, --7,-29,27,-13,32, -20,32,-61,16,14, -41,44,40,24,20, -7,4,48,-60,-77, -17,-6,-48,65,-15, -32,-30,-71,-10,-3, --6,10,-2,-7,-29, --56,67,-30,7,-5, -86,-6,-10,0,5, --31,60,34,-38,-3, -24,10,-2,30,23, -24,-41,12,70,-43, -15,-17,6,13,16, --13,8,30,-15,-8, -5,23,-34,-98,-4, --13,13,-48,-31,70, -12,31,25,24,-24, -26,-7,33,-16,8, -5,-11,-14,-8,-65, -13,10,-2,-9,0, --3,-68,5,35,7, -0,-31,-1,-17,-9, --9,16,-37,-18,-1, -69,-48,-28,22,-21, --11,5,49,55,23, --86,-36,16,2,13, -63,-51,30,-11,13, -24,-18,-6,14,-19, -1,41,9,-5,27, --36,-44,-34,-37,-21, --26,31,-39,15,43, -5,-8,29,20,-8, --20,-52,-28,-1,13, -26,-34,-10,-9,27, --8,8,27,-66,4, -12,-22,49,10,-77, -32,-18,3,-38,12, --3,-1,2,2,0}; diff --git a/drivers/speex/exc_8_128_table.c b/drivers/speex/exc_8_128_table.c deleted file mode 100644 index 17ee64b926..0000000000 --- a/drivers/speex/exc_8_128_table.c +++ /dev/null @@ -1,162 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: exc_8_128_table.c - Codebook for excitation in narrowband CELP mode (7000 bps) - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -const signed char exc_8_128_table[1024] = { --14,9,13,-32,2,-10,31,-10, --8,-8,6,-4,-1,10,-64,23, -6,20,13,6,8,-22,16,34, -7,42,-49,-28,5,26,4,-15, -41,34,41,32,33,24,23,14, -8,40,34,4,-24,-41,-19,-15, -13,-13,33,-54,24,27,-44,33, -27,-15,-15,24,-19,14,-36,14, --9,24,-12,-4,37,-5,16,-34, -5,10,33,-15,-54,-16,12,25, -12,1,2,0,3,-1,-4,-4, -11,2,-56,54,27,-20,13,-6, --46,-41,-33,-11,-5,7,12,14, --14,-5,8,20,6,3,4,-8, --5,-42,11,8,-14,25,-2,2, -13,11,-22,39,-9,9,5,-45, --9,7,-9,12,-7,34,-17,-102, -7,2,-42,18,35,-9,-34,11, --5,-2,3,22,46,-52,-25,-9, --94,8,11,-5,-5,-5,4,-7, --35,-7,54,5,-32,3,24,-9, --22,8,65,37,-1,-12,-23,-6, --9,-28,55,-33,14,-3,2,18, --60,41,-17,8,-16,17,-11,0, --11,29,-28,37,9,-53,33,-14, --9,7,-25,-7,-11,26,-32,-8, -24,-21,22,-19,19,-10,29,-14, -0,0,0,0,0,0,0,0, --5,-52,10,41,6,-30,-4,16, -32,22,-27,-22,32,-3,-28,-3, -3,-35,6,17,23,21,8,2, -4,-45,-17,14,23,-4,-31,-11, --3,14,1,19,-11,2,61,-8, -9,-12,7,-10,12,-3,-24,99, --48,23,50,-37,-5,-23,0,8, --14,35,-64,-5,46,-25,13,-1, --49,-19,-15,9,34,50,25,11, --6,-9,-16,-20,-32,-33,-32,-27, -10,-8,12,-15,56,-14,-32,33, -3,-9,1,65,-9,-9,-10,-2, --6,-23,9,17,3,-28,13,-32, -4,-2,-10,4,-16,76,12,-52, -6,13,33,-6,4,-14,-9,-3, -1,-15,-16,28,1,-15,11,16, -9,4,-21,-37,-40,-6,22,12, --15,-23,-14,-17,-16,-9,-10,-9, -13,-39,41,5,-9,16,-38,25, -46,-47,4,49,-14,17,-2,6, -18,5,-6,-33,-22,44,50,-2, -1,3,-6,7,7,-3,-21,38, --18,34,-14,-41,60,-13,6,16, --24,35,19,-13,-36,24,3,-17, --14,-10,36,44,-44,-29,-3,3, --54,-8,12,55,26,4,-2,-5, -2,-11,22,-23,2,22,1,-25, --39,66,-49,21,-8,-2,10,-14, --60,25,6,10,27,-25,16,5, --2,-9,26,-13,-20,58,-2,7, -52,-9,2,5,-4,-15,23,-1, --38,23,8,27,-6,0,-27,-7, -39,-10,-14,26,11,-45,-12,9, --5,34,4,-35,10,43,-22,-11, -56,-7,20,1,10,1,-26,9, -94,11,-27,-14,-13,1,-11,0, -14,-5,-6,-10,-4,-15,-8,-41, -21,-5,1,-28,-8,22,-9,33, --23,-4,-4,-12,39,4,-7,3, --60,80,8,-17,2,-6,12,-5, -1,9,15,27,31,30,27,23, -61,47,26,10,-5,-8,-12,-13, -5,-18,25,-15,-4,-15,-11,12, --2,-2,-16,-2,-6,24,12,11, --4,9,1,-9,14,-45,57,12, -20,-35,26,11,-64,32,-10,-10, -42,-4,-9,-16,32,24,7,10, -52,-11,-57,29,0,8,0,-6, -17,-17,-56,-40,7,20,18,12, --6,16,5,7,-1,9,1,10, -29,12,16,13,-2,23,7,9, --3,-4,-5,18,-64,13,55,-25, -9,-9,24,14,-25,15,-11,-40, --30,37,1,-19,22,-5,-31,13, --2,0,7,-4,16,-67,12,66, --36,24,-8,18,-15,-23,19,0, --45,-7,4,3,-13,13,35,5, -13,33,10,27,23,0,-7,-11, -43,-74,36,-12,2,5,-8,6, --33,11,-16,-14,-5,-7,-3,17, --34,27,-16,11,-9,15,33,-31, -8,-16,7,-6,-7,63,-55,-17, -11,-1,20,-46,34,-30,6,9, -19,28,-9,5,-24,-8,-23,-2, -31,-19,-16,-5,-15,-18,0,26, -18,37,-5,-15,-2,17,5,-27, -21,-33,44,12,-27,-9,17,11, -25,-21,-31,-7,13,33,-8,-25, --7,7,-10,4,-6,-9,48,-82, --23,-8,6,11,-23,3,-3,49, --29,25,31,4,14,16,9,-4, --18,10,-26,3,5,-44,-9,9, --47,-55,15,9,28,1,4,-3, -46,6,-6,-38,-29,-31,-15,-6, -3,0,14,-6,8,-54,-50,33, --5,1,-14,33,-48,26,-4,-5, --3,-5,-3,-5,-28,-22,77,55, --1,2,10,10,-9,-14,-66,-49, -11,-36,-6,-20,10,-10,16,12, -4,-1,-16,45,-44,-50,31,-2, -25,42,23,-32,-22,0,11,20, --40,-35,-40,-36,-32,-26,-21,-13, -52,-22,6,-24,-20,17,-5,-8, -36,-25,-11,21,-26,6,34,-8, -7,20,-3,5,-25,-8,18,-5, --9,-4,1,-9,20,20,39,48, --24,9,5,-65,22,29,4,3, --43,-11,32,-6,9,19,-27,-10, --47,-14,24,10,-7,-36,-7,-1, --4,-5,-5,16,53,25,-26,-29, --4,-12,45,-58,-34,33,-5,2, --1,27,-48,31,-15,22,-5,4, -7,7,-25,-3,11,-22,16,-12, -8,-3,7,-11,45,14,-73,-19, -56,-46,24,-20,28,-12,-2,-1, --36,-3,-33,19,-6,7,2,-15, -5,-31,-45,8,35,13,20,0, --9,48,-13,-43,-3,-13,2,-5, -72,-68,-27,2,1,-2,-7,5, -36,33,-40,-12,-4,-5,23,19}; diff --git a/drivers/speex/fftwrap.c b/drivers/speex/fftwrap.c deleted file mode 100644 index ac71bbfcb7..0000000000 --- a/drivers/speex/fftwrap.c +++ /dev/null @@ -1,397 +0,0 @@ -/* Copyright (C) 2005-2006 Jean-Marc Valin - File: fftwrap.c - - Wrapper for various FFTs - - 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 the Xiph.org Foundation nor the names of its - 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 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. - -*/ - - -#include "config.h" - - -#include "arch.h" -#include "os_support.h" - -#define MAX_FFT_SIZE 2048 - -#ifdef FIXED_POINT -static int maximize_range(spx_word16_t *in, spx_word16_t *out, spx_word16_t bound, int len) -{ - int i, shift; - spx_word16_t max_val = 0; - for (i=0;i<len;i++) - { - if (in[i]>max_val) - max_val = in[i]; - if (-in[i]>max_val) - max_val = -in[i]; - } - shift=0; - while (max_val <= (bound>>1) && max_val != 0) - { - max_val <<= 1; - shift++; - } - for (i=0;i<len;i++) - { - out[i] = SHL16(in[i], shift); - } - return shift; -} - -static void renorm_range(spx_word16_t *in, spx_word16_t *out, int shift, int len) -{ - int i; - for (i=0;i<len;i++) - { - out[i] = PSHR16(in[i], shift); - } -} -#endif - -#ifdef USE_SMALLFT - -#include "smallft.h" -#include <math.h> - -void *spx_fft_init(int size) -{ - struct drft_lookup *table; - table = speex_alloc(sizeof(struct drft_lookup)); - spx_drft_init((struct drft_lookup *)table, size); - return (void*)table; -} - -void spx_fft_destroy(void *table) -{ - spx_drft_clear(table); - speex_free(table); -} - -void spx_fft(void *table, float *in, float *out) -{ - if (in==out) - { - int i; - float scale = 1./((struct drft_lookup *)table)->n; - speex_warning("FFT should not be done in-place"); - for (i=0;i<((struct drft_lookup *)table)->n;i++) - out[i] = scale*in[i]; - } else { - int i; - float scale = 1./((struct drft_lookup *)table)->n; - for (i=0;i<((struct drft_lookup *)table)->n;i++) - out[i] = scale*in[i]; - } - spx_drft_forward((struct drft_lookup *)table, out); -} - -void spx_ifft(void *table, float *in, float *out) -{ - if (in==out) - { - speex_warning("FFT should not be done in-place"); - } else { - int i; - for (i=0;i<((struct drft_lookup *)table)->n;i++) - out[i] = in[i]; - } - spx_drft_backward((struct drft_lookup *)table, out); -} - -#elif defined(USE_INTEL_MKL) -#include <mkl.h> - -struct mkl_config { - DFTI_DESCRIPTOR_HANDLE desc; - int N; -}; - -void *spx_fft_init(int size) -{ - struct mkl_config *table = (struct mkl_config *) speex_alloc(sizeof(struct mkl_config)); - table->N = size; - DftiCreateDescriptor(&table->desc, DFTI_SINGLE, DFTI_REAL, 1, size); - DftiSetValue(table->desc, DFTI_PACKED_FORMAT, DFTI_PACK_FORMAT); - DftiSetValue(table->desc, DFTI_PLACEMENT, DFTI_NOT_INPLACE); - DftiSetValue(table->desc, DFTI_FORWARD_SCALE, 1.0f / size); - DftiCommitDescriptor(table->desc); - return table; -} - -void spx_fft_destroy(void *table) -{ - struct mkl_config *t = (struct mkl_config *) table; - DftiFreeDescriptor(t->desc); - speex_free(table); -} - -void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) -{ - struct mkl_config *t = (struct mkl_config *) table; - DftiComputeForward(t->desc, in, out); -} - -void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out) -{ - struct mkl_config *t = (struct mkl_config *) table; - DftiComputeBackward(t->desc, in, out); -} - -#elif defined(USE_GPL_FFTW3) - -#include <fftw3.h> - -struct fftw_config { - float *in; - float *out; - fftwf_plan fft; - fftwf_plan ifft; - int N; -}; - -void *spx_fft_init(int size) -{ - struct fftw_config *table = (struct fftw_config *) speex_alloc(sizeof(struct fftw_config)); - table->in = fftwf_malloc(sizeof(float) * (size+2)); - table->out = fftwf_malloc(sizeof(float) * (size+2)); - - table->fft = fftwf_plan_dft_r2c_1d(size, table->in, (fftwf_complex *) table->out, FFTW_PATIENT); - table->ifft = fftwf_plan_dft_c2r_1d(size, (fftwf_complex *) table->in, table->out, FFTW_PATIENT); - - table->N = size; - return table; -} - -void spx_fft_destroy(void *table) -{ - struct fftw_config *t = (struct fftw_config *) table; - fftwf_destroy_plan(t->fft); - fftwf_destroy_plan(t->ifft); - fftwf_free(t->in); - fftwf_free(t->out); - speex_free(table); -} - - -void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) -{ - int i; - struct fftw_config *t = (struct fftw_config *) table; - const int N = t->N; - float *iptr = t->in; - float *optr = t->out; - const float m = 1.0 / N; - for(i=0;i<N;++i) - iptr[i]=in[i] * m; - - fftwf_execute(t->fft); - - out[0] = optr[0]; - for(i=1;i<N;++i) - out[i] = optr[i+1]; -} - -void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out) -{ - int i; - struct fftw_config *t = (struct fftw_config *) table; - const int N = t->N; - float *iptr = t->in; - float *optr = t->out; - - iptr[0] = in[0]; - iptr[1] = 0.0f; - for(i=1;i<N;++i) - iptr[i+1] = in[i]; - iptr[N+1] = 0.0f; - - fftwf_execute(t->ifft); - - for(i=0;i<N;++i) - out[i] = optr[i]; -} - -#elif defined(USE_KISS_FFT) - -#include "kiss_fftr.h" -#include "kiss_fft.h" - -struct kiss_config { - kiss_fftr_cfg forward; - kiss_fftr_cfg backward; - int N; -}; - -void *spx_fft_init(int size) -{ - struct kiss_config *table; - table = (struct kiss_config*)speex_alloc(sizeof(struct kiss_config)); - table->forward = kiss_fftr_alloc(size,0,NULL,NULL); - table->backward = kiss_fftr_alloc(size,1,NULL,NULL); - table->N = size; - return table; -} - -void spx_fft_destroy(void *table) -{ - struct kiss_config *t = (struct kiss_config *)table; - kiss_fftr_free(t->forward); - kiss_fftr_free(t->backward); - speex_free(table); -} - -#ifdef FIXED_POINT - -void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) -{ - int shift; - struct kiss_config *t = (struct kiss_config *)table; - shift = maximize_range(in, in, 32000, t->N); - kiss_fftr2(t->forward, in, out); - renorm_range(in, in, shift, t->N); - renorm_range(out, out, shift, t->N); -} - -#else - -void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) -{ - int i; - float scale; - struct kiss_config *t = (struct kiss_config *)table; - scale = 1./t->N; - kiss_fftr2(t->forward, in, out); - for (i=0;i<t->N;i++) - out[i] *= scale; -} -#endif - -void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out) -{ - struct kiss_config *t = (struct kiss_config *)table; - kiss_fftri2(t->backward, in, out); -} - - -#else - -#error No other FFT implemented - -#endif - - -#ifdef FIXED_POINT -/*#include "smallft.h"*/ - - -void spx_fft_float(void *table, float *in, float *out) -{ - int i; -#ifdef USE_SMALLFT - int N = ((struct drft_lookup *)table)->n; -#elif defined(USE_KISS_FFT) - int N = ((struct kiss_config *)table)->N; -#else -#endif -#ifdef VAR_ARRAYS - spx_word16_t _in[N]; - spx_word16_t _out[N]; -#else - spx_word16_t _in[MAX_FFT_SIZE]; - spx_word16_t _out[MAX_FFT_SIZE]; -#endif - for (i=0;i<N;i++) - _in[i] = (int)floor(.5+in[i]); - spx_fft(table, _in, _out); - for (i=0;i<N;i++) - out[i] = _out[i]; -#if 0 - if (!fixed_point) - { - float scale; - struct drft_lookup t; - spx_drft_init(&t, ((struct kiss_config *)table)->N); - scale = 1./((struct kiss_config *)table)->N; - for (i=0;i<((struct kiss_config *)table)->N;i++) - out[i] = scale*in[i]; - spx_drft_forward(&t, out); - spx_drft_clear(&t); - } -#endif -} - -void spx_ifft_float(void *table, float *in, float *out) -{ - int i; -#ifdef USE_SMALLFT - int N = ((struct drft_lookup *)table)->n; -#elif defined(USE_KISS_FFT) - int N = ((struct kiss_config *)table)->N; -#else -#endif -#ifdef VAR_ARRAYS - spx_word16_t _in[N]; - spx_word16_t _out[N]; -#else - spx_word16_t _in[MAX_FFT_SIZE]; - spx_word16_t _out[MAX_FFT_SIZE]; -#endif - for (i=0;i<N;i++) - _in[i] = (int)floor(.5+in[i]); - spx_ifft(table, _in, _out); - for (i=0;i<N;i++) - out[i] = _out[i]; -#if 0 - if (!fixed_point) - { - int i; - struct drft_lookup t; - spx_drft_init(&t, ((struct kiss_config *)table)->N); - for (i=0;i<((struct kiss_config *)table)->N;i++) - out[i] = in[i]; - spx_drft_backward(&t, out); - spx_drft_clear(&t); - } -#endif -} - -#else - -void spx_fft_float(void *table, float *in, float *out) -{ - spx_fft(table, in, out); -} -void spx_ifft_float(void *table, float *in, float *out) -{ - spx_ifft(table, in, out); -} - -#endif diff --git a/drivers/speex/fftwrap.h b/drivers/speex/fftwrap.h deleted file mode 100644 index dfaf489441..0000000000 --- a/drivers/speex/fftwrap.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (C) 2005 Jean-Marc Valin - File: fftwrap.h - - Wrapper for various FFTs - - 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 the Xiph.org Foundation nor the names of its - 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 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 FFTWRAP_H -#define FFTWRAP_H - -#include "arch.h" - -/** Compute tables for an FFT */ -void *spx_fft_init(int size); - -/** Destroy tables for an FFT */ -void spx_fft_destroy(void *table); - -/** Forward (real to half-complex) transform */ -void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out); - -/** Backward (half-complex to real) transform */ -void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out); - -/** Forward (real to half-complex) transform of float data */ -void spx_fft_float(void *table, float *in, float *out); - -/** Backward (half-complex to real) transform of float data */ -void spx_ifft_float(void *table, float *in, float *out); - -#endif diff --git a/drivers/speex/filterbank.c b/drivers/speex/filterbank.c deleted file mode 100644 index 8874ed482b..0000000000 --- a/drivers/speex/filterbank.c +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright (C) 2006 Jean-Marc Valin */ -/** - @file filterbank.c - @brief Converting between psd and filterbank - */ -/* - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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. -*/ - - -#include "config.h" - - -#include "filterbank.h" -#include "arch.h" -#include <math.h> -#include "math_approx.h" -#include "os_support.h" - -#ifdef FIXED_POINT - -#define toBARK(n) (MULT16_16(26829,spx_atan(SHR32(MULT16_16(97,n),2))) + MULT16_16(4588,spx_atan(MULT16_32_Q15(20,MULT16_16(n,n)))) + MULT16_16(3355,n)) - -#else -#define toBARK(n) (13.1f*atan(.00074f*(n))+2.24f*atan((n)*(n)*1.85e-8f)+1e-4f*(n)) -#endif - -#define toMEL(n) (2595.f*log10(1.f+(n)/700.f)) - -FilterBank *filterbank_new(int banks, spx_word32_t sampling, int len, int type) -{ - FilterBank *bank; - spx_word32_t df; - spx_word32_t max_mel, mel_interval; - int i; - int id1; - int id2; - df = DIV32(SHL32(sampling,15),MULT16_16(2,len)); - max_mel = toBARK(EXTRACT16(sampling/2)); - mel_interval = PDIV32(max_mel,banks-1); - - bank = (FilterBank*)speex_alloc(sizeof(FilterBank)); - bank->nb_banks = banks; - bank->len = len; - bank->bank_left = (int*)speex_alloc(len*sizeof(int)); - bank->bank_right = (int*)speex_alloc(len*sizeof(int)); - bank->filter_left = (spx_word16_t*)speex_alloc(len*sizeof(spx_word16_t)); - bank->filter_right = (spx_word16_t*)speex_alloc(len*sizeof(spx_word16_t)); - /* Think I can safely disable normalisation that for fixed-point (and probably float as well) */ -#ifndef FIXED_POINT - bank->scaling = (float*)speex_alloc(banks*sizeof(float)); -#endif - for (i=0;i<len;i++) - { - spx_word16_t curr_freq; - spx_word32_t mel; - spx_word16_t val; - curr_freq = EXTRACT16(MULT16_32_P15(i,df)); - mel = toBARK(curr_freq); - if (mel > max_mel) - break; -#ifdef FIXED_POINT - id1 = DIV32(mel,mel_interval); -#else - id1 = (int)(floor(mel/mel_interval)); -#endif - if (id1>banks-2) - { - id1 = banks-2; - val = Q15_ONE; - } else { - val = DIV32_16(mel - id1*mel_interval,EXTRACT16(PSHR32(mel_interval,15))); - } - id2 = id1+1; - bank->bank_left[i] = id1; - bank->filter_left[i] = SUB16(Q15_ONE,val); - bank->bank_right[i] = id2; - bank->filter_right[i] = val; - } - - /* Think I can safely disable normalisation for fixed-point (and probably float as well) */ -#ifndef FIXED_POINT - for (i=0;i<bank->nb_banks;i++) - bank->scaling[i] = 0; - for (i=0;i<bank->len;i++) - { - int id = bank->bank_left[i]; - bank->scaling[id] += bank->filter_left[i]; - id = bank->bank_right[i]; - bank->scaling[id] += bank->filter_right[i]; - } - for (i=0;i<bank->nb_banks;i++) - bank->scaling[i] = Q15_ONE/(bank->scaling[i]); -#endif - return bank; -} - -void filterbank_destroy(FilterBank *bank) -{ - speex_free(bank->bank_left); - speex_free(bank->bank_right); - speex_free(bank->filter_left); - speex_free(bank->filter_right); -#ifndef FIXED_POINT - speex_free(bank->scaling); -#endif - speex_free(bank); -} - -void filterbank_compute_bank32(FilterBank *bank, spx_word32_t *ps, spx_word32_t *mel) -{ - int i; - for (i=0;i<bank->nb_banks;i++) - mel[i] = 0; - - for (i=0;i<bank->len;i++) - { - int id; - id = bank->bank_left[i]; - mel[id] += MULT16_32_P15(bank->filter_left[i],ps[i]); - id = bank->bank_right[i]; - mel[id] += MULT16_32_P15(bank->filter_right[i],ps[i]); - } - /* Think I can safely disable normalisation that for fixed-point (and probably float as well) */ -#ifndef FIXED_POINT - /*for (i=0;i<bank->nb_banks;i++) - mel[i] = MULT16_32_P15(Q15(bank->scaling[i]),mel[i]); - */ -#endif -} - -void filterbank_compute_psd16(FilterBank *bank, spx_word16_t *mel, spx_word16_t *ps) -{ - int i; - for (i=0;i<bank->len;i++) - { - spx_word32_t tmp; - int id1, id2; - id1 = bank->bank_left[i]; - id2 = bank->bank_right[i]; - tmp = MULT16_16(mel[id1],bank->filter_left[i]); - tmp += MULT16_16(mel[id2],bank->filter_right[i]); - ps[i] = EXTRACT16(PSHR32(tmp,15)); - } -} - - -#ifndef FIXED_POINT -void filterbank_compute_bank(FilterBank *bank, float *ps, float *mel) -{ - int i; - for (i=0;i<bank->nb_banks;i++) - mel[i] = 0; - - for (i=0;i<bank->len;i++) - { - int id = bank->bank_left[i]; - mel[id] += bank->filter_left[i]*ps[i]; - id = bank->bank_right[i]; - mel[id] += bank->filter_right[i]*ps[i]; - } - for (i=0;i<bank->nb_banks;i++) - mel[i] *= bank->scaling[i]; -} - -void filterbank_compute_psd(FilterBank *bank, float *mel, float *ps) -{ - int i; - for (i=0;i<bank->len;i++) - { - int id = bank->bank_left[i]; - ps[i] = mel[id]*bank->filter_left[i]; - id = bank->bank_right[i]; - ps[i] += mel[id]*bank->filter_right[i]; - } -} - -void filterbank_psy_smooth(FilterBank *bank, float *ps, float *mask) -{ - /* Low freq slope: 14 dB/Bark*/ - /* High freq slope: 9 dB/Bark*/ - /* Noise vs tone: 5 dB difference */ - /* FIXME: Temporary kludge */ - float bark[100]; - int i; - /* Assumes 1/3 Bark resolution */ - float decay_low = 0.34145f; - float decay_high = 0.50119f; - filterbank_compute_bank(bank, ps, bark); - for (i=1;i<bank->nb_banks;i++) - { - /*float decay_high = 13-1.6*log10(bark[i-1]); - decay_high = pow(10,(-decay_high/30.f));*/ - bark[i] = bark[i] + decay_high*bark[i-1]; - } - for (i=bank->nb_banks-2;i>=0;i--) - { - bark[i] = bark[i] + decay_low*bark[i+1]; - } - filterbank_compute_psd(bank, bark, mask); -} - -#endif diff --git a/drivers/speex/filterbank.h b/drivers/speex/filterbank.h deleted file mode 100644 index 3e889a22f7..0000000000 --- a/drivers/speex/filterbank.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (C) 2006 Jean-Marc Valin */ -/** - @file filterbank.h - @brief Converting between psd and filterbank - */ -/* - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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 FILTERBANK_H -#define FILTERBANK_H - -#include "arch.h" - -typedef struct { - int *bank_left; - int *bank_right; - spx_word16_t *filter_left; - spx_word16_t *filter_right; -#ifndef FIXED_POINT - float *scaling; -#endif - int nb_banks; - int len; -} FilterBank; - - -FilterBank *filterbank_new(int banks, spx_word32_t sampling, int len, int type); - -void filterbank_destroy(FilterBank *bank); - -void filterbank_compute_bank32(FilterBank *bank, spx_word32_t *ps, spx_word32_t *mel); - -void filterbank_compute_psd16(FilterBank *bank, spx_word16_t *mel, spx_word16_t *psd); - -#ifndef FIXED_POINT -void filterbank_compute_bank(FilterBank *bank, float *psd, float *mel); -void filterbank_compute_psd(FilterBank *bank, float *mel, float *psd); -#endif - - -#endif diff --git a/drivers/speex/filters.c b/drivers/speex/filters.c deleted file mode 100644 index 2cfac6d672..0000000000 --- a/drivers/speex/filters.c +++ /dev/null @@ -1,821 +0,0 @@ -/* Copyright (C) 2002-2006 Jean-Marc Valin - File: filters.c - Various analysis/synthesis filters - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -#include "config.h" - - -#include "filters.h" -#include "stack_alloc.h" -#include "arch.h" -#include "math_approx.h" -#include "ltp.h" -#include <math.h> - -#ifdef _USE_SSE -#include "filters_sse.h" -#elif defined (ARM4_ASM) || defined(ARM5E_ASM) -#include "filters_arm4.h" -#elif defined (BFIN_ASM) -#include "filters_bfin.h" -#endif - - - -void bw_lpc(spx_word16_t gamma, const spx_coef_t *lpc_in, spx_coef_t *lpc_out, int order) -{ - int i; - spx_word16_t tmp=gamma; - for (i=0;i<order;i++) - { - lpc_out[i] = MULT16_16_P15(tmp,lpc_in[i]); - tmp = MULT16_16_P15(tmp, gamma); - } -} - -void sanitize_values32(spx_word32_t *vec, spx_word32_t min_val, spx_word32_t max_val, int len) -{ - int i; - for (i=0;i<len;i++) - { - /* It's important we do the test that way so we can catch NaNs, which are neither greater nor smaller */ - if (!(vec[i]>=min_val && vec[i] <= max_val)) - { - if (vec[i] < min_val) - vec[i] = min_val; - else if (vec[i] > max_val) - vec[i] = max_val; - else /* Has to be NaN */ - vec[i] = 0; - } - } -} - -void highpass(const spx_word16_t *x, spx_word16_t *y, int len, int filtID, spx_mem_t *mem) -{ - int i; -#ifdef FIXED_POINT - const spx_word16_t Pcoef[5][3] = {{16384, -31313, 14991}, {16384, -31569, 15249}, {16384, -31677, 15328}, {16384, -32313, 15947}, {16384, -22446, 6537}}; - const spx_word16_t Zcoef[5][3] = {{15672, -31344, 15672}, {15802, -31601, 15802}, {15847, -31694, 15847}, {16162, -32322, 16162}, {14418, -28836, 14418}}; -#else - const spx_word16_t Pcoef[5][3] = {{1.00000f, -1.91120f, 0.91498f}, {1.00000f, -1.92683f, 0.93071f}, {1.00000f, -1.93338f, 0.93553f}, {1.00000f, -1.97226f, 0.97332f}, {1.00000f, -1.37000f, 0.39900f}}; - const spx_word16_t Zcoef[5][3] = {{0.95654f, -1.91309f, 0.95654f}, {0.96446f, -1.92879f, 0.96446f}, {0.96723f, -1.93445f, 0.96723f}, {0.98645f, -1.97277f, 0.98645f}, {0.88000f, -1.76000f, 0.88000f}}; -#endif - const spx_word16_t *den, *num; - if (filtID>4) - filtID=4; - - den = Pcoef[filtID]; num = Zcoef[filtID]; - /*return;*/ - for (i=0;i<len;i++) - { - spx_word16_t yi; - spx_word32_t vout = ADD32(MULT16_16(num[0], x[i]),mem[0]); - yi = EXTRACT16(SATURATE(PSHR32(vout,14),32767)); - mem[0] = ADD32(MAC16_16(mem[1], num[1],x[i]), SHL32(MULT16_32_Q15(-den[1],vout),1)); - mem[1] = ADD32(MULT16_16(num[2],x[i]), SHL32(MULT16_32_Q15(-den[2],vout),1)); - y[i] = yi; - } -} - -#ifdef FIXED_POINT - -/* FIXME: These functions are ugly and probably introduce too much error */ -void signal_mul(const spx_sig_t *x, spx_sig_t *y, spx_word32_t scale, int len) -{ - int i; - for (i=0;i<len;i++) - { - y[i] = SHL32(MULT16_32_Q14(EXTRACT16(SHR32(x[i],7)),scale),7); - } -} - -void signal_div(const spx_word16_t *x, spx_word16_t *y, spx_word32_t scale, int len) -{ - int i; - if (scale > SHL32(EXTEND32(SIG_SCALING), 8)) - { - spx_word16_t scale_1; - scale = PSHR32(scale, SIG_SHIFT); - scale_1 = EXTRACT16(PDIV32_16(SHL32(EXTEND32(SIG_SCALING),7),scale)); - for (i=0;i<len;i++) - { - y[i] = MULT16_16_P15(scale_1, x[i]); - } - } else if (scale > SHR32(EXTEND32(SIG_SCALING), 2)) { - spx_word16_t scale_1; - scale = PSHR32(scale, SIG_SHIFT-5); - scale_1 = DIV32_16(SHL32(EXTEND32(SIG_SCALING),3),scale); - for (i=0;i<len;i++) - { - y[i] = PSHR32(MULT16_16(scale_1, SHL16(x[i],2)),8); - } - } else { - spx_word16_t scale_1; - scale = PSHR32(scale, SIG_SHIFT-7); - if (scale < 5) - scale = 5; - scale_1 = DIV32_16(SHL32(EXTEND32(SIG_SCALING),3),scale); - for (i=0;i<len;i++) - { - y[i] = PSHR32(MULT16_16(scale_1, SHL16(x[i],2)),6); - } - } -} - -#else - -void signal_mul(const spx_sig_t *x, spx_sig_t *y, spx_word32_t scale, int len) -{ - int i; - for (i=0;i<len;i++) - y[i] = scale*x[i]; -} - -void signal_div(const spx_sig_t *x, spx_sig_t *y, spx_word32_t scale, int len) -{ - int i; - float scale_1 = 1/scale; - for (i=0;i<len;i++) - y[i] = scale_1*x[i]; -} -#endif - - - -#ifdef FIXED_POINT - - - -spx_word16_t compute_rms(const spx_sig_t *x, int len) -{ - int i; - spx_word32_t sum=0; - spx_sig_t max_val=1; - int sig_shift; - - for (i=0;i<len;i++) - { - spx_sig_t tmp = x[i]; - if (tmp<0) - tmp = -tmp; - if (tmp > max_val) - max_val = tmp; - } - - sig_shift=0; - while (max_val>16383) - { - sig_shift++; - max_val >>= 1; - } - - for (i=0;i<len;i+=4) - { - spx_word32_t sum2=0; - spx_word16_t tmp; - tmp = EXTRACT16(SHR32(x[i],sig_shift)); - sum2 = MAC16_16(sum2,tmp,tmp); - tmp = EXTRACT16(SHR32(x[i+1],sig_shift)); - sum2 = MAC16_16(sum2,tmp,tmp); - tmp = EXTRACT16(SHR32(x[i+2],sig_shift)); - sum2 = MAC16_16(sum2,tmp,tmp); - tmp = EXTRACT16(SHR32(x[i+3],sig_shift)); - sum2 = MAC16_16(sum2,tmp,tmp); - sum = ADD32(sum,SHR32(sum2,6)); - } - - return EXTRACT16(PSHR32(SHL32(EXTEND32(spx_sqrt(DIV32(sum,len))),(sig_shift+3)),SIG_SHIFT)); -} - -spx_word16_t compute_rms16(const spx_word16_t *x, int len) -{ - int i; - spx_word16_t max_val=10; - - for (i=0;i<len;i++) - { - spx_sig_t tmp = x[i]; - if (tmp<0) - tmp = -tmp; - if (tmp > max_val) - max_val = tmp; - } - if (max_val>16383) - { - spx_word32_t sum=0; - for (i=0;i<len;i+=4) - { - spx_word32_t sum2=0; - sum2 = MAC16_16(sum2,SHR16(x[i],1),SHR16(x[i],1)); - sum2 = MAC16_16(sum2,SHR16(x[i+1],1),SHR16(x[i+1],1)); - sum2 = MAC16_16(sum2,SHR16(x[i+2],1),SHR16(x[i+2],1)); - sum2 = MAC16_16(sum2,SHR16(x[i+3],1),SHR16(x[i+3],1)); - sum = ADD32(sum,SHR32(sum2,6)); - } - return SHL16(spx_sqrt(DIV32(sum,len)),4); - } else { - spx_word32_t sum=0; - int sig_shift=0; - if (max_val < 8192) - sig_shift=1; - if (max_val < 4096) - sig_shift=2; - if (max_val < 2048) - sig_shift=3; - for (i=0;i<len;i+=4) - { - spx_word32_t sum2=0; - sum2 = MAC16_16(sum2,SHL16(x[i],sig_shift),SHL16(x[i],sig_shift)); - sum2 = MAC16_16(sum2,SHL16(x[i+1],sig_shift),SHL16(x[i+1],sig_shift)); - sum2 = MAC16_16(sum2,SHL16(x[i+2],sig_shift),SHL16(x[i+2],sig_shift)); - sum2 = MAC16_16(sum2,SHL16(x[i+3],sig_shift),SHL16(x[i+3],sig_shift)); - sum = ADD32(sum,SHR32(sum2,6)); - } - return SHL16(spx_sqrt(DIV32(sum,len)),3-sig_shift); - } -} - -#ifndef OVERRIDE_NORMALIZE16 -int normalize16(const spx_sig_t *x, spx_word16_t *y, spx_sig_t max_scale, int len) -{ - int i; - spx_sig_t max_val=1; - int sig_shift; - - for (i=0;i<len;i++) - { - spx_sig_t tmp = x[i]; - if (tmp<0) - tmp = NEG32(tmp); - if (tmp >= max_val) - max_val = tmp; - } - - sig_shift=0; - while (max_val>max_scale) - { - sig_shift++; - max_val >>= 1; - } - - for (i=0;i<len;i++) - y[i] = EXTRACT16(SHR32(x[i], sig_shift)); - - return sig_shift; -} -#endif - -#else - -spx_word16_t compute_rms(const spx_sig_t *x, int len) -{ - int i; - float sum=0; - for (i=0;i<len;i++) - { - sum += x[i]*x[i]; - } - return sqrt(.1+sum/len); -} -spx_word16_t compute_rms16(const spx_word16_t *x, int len) -{ - return compute_rms(x, len); -} -#endif - - - -#ifndef OVERRIDE_FILTER_MEM16 -void filter_mem16(const spx_word16_t *x, const spx_coef_t *num, const spx_coef_t *den, spx_word16_t *y, int N, int ord, spx_mem_t *mem, char *stack) -{ - int i,j; - spx_word16_t xi,yi,nyi; - for (i=0;i<N;i++) - { - xi= x[i]; - yi = EXTRACT16(SATURATE(ADD32(EXTEND32(x[i]),PSHR32(mem[0],LPC_SHIFT)),32767)); - nyi = NEG16(yi); - for (j=0;j<ord-1;j++) - { - mem[j] = MAC16_16(MAC16_16(mem[j+1], num[j],xi), den[j],nyi); - } - mem[ord-1] = ADD32(MULT16_16(num[ord-1],xi), MULT16_16(den[ord-1],nyi)); - y[i] = yi; - } -} -#endif - -#ifndef OVERRIDE_IIR_MEM16 -void iir_mem16(const spx_word16_t *x, const spx_coef_t *den, spx_word16_t *y, int N, int ord, spx_mem_t *mem, char *stack) -{ - int i,j; - spx_word16_t yi,nyi; - - for (i=0;i<N;i++) - { - yi = EXTRACT16(SATURATE(ADD32(EXTEND32(x[i]),PSHR32(mem[0],LPC_SHIFT)),32767)); - nyi = NEG16(yi); - for (j=0;j<ord-1;j++) - { - mem[j] = MAC16_16(mem[j+1],den[j],nyi); - } - mem[ord-1] = MULT16_16(den[ord-1],nyi); - y[i] = yi; - } -} -#endif - -#ifndef OVERRIDE_FIR_MEM16 -void fir_mem16(const spx_word16_t *x, const spx_coef_t *num, spx_word16_t *y, int N, int ord, spx_mem_t *mem, char *stack) -{ - int i,j; - spx_word16_t xi,yi; - - for (i=0;i<N;i++) - { - xi=x[i]; - yi = EXTRACT16(SATURATE(ADD32(EXTEND32(x[i]),PSHR32(mem[0],LPC_SHIFT)),32767)); - for (j=0;j<ord-1;j++) - { - mem[j] = MAC16_16(mem[j+1], num[j],xi); - } - mem[ord-1] = MULT16_16(num[ord-1],xi); - y[i] = yi; - } -} -#endif - - -void syn_percep_zero16(const spx_word16_t *xx, const spx_coef_t *ak, const spx_coef_t *awk1, const spx_coef_t *awk2, spx_word16_t *y, int N, int ord, char *stack) -{ - int i; - VARDECL(spx_mem_t *mem); - ALLOC(mem, ord, spx_mem_t); - for (i=0;i<ord;i++) - mem[i]=0; - iir_mem16(xx, ak, y, N, ord, mem, stack); - for (i=0;i<ord;i++) - mem[i]=0; - filter_mem16(y, awk1, awk2, y, N, ord, mem, stack); -} -void residue_percep_zero16(const spx_word16_t *xx, const spx_coef_t *ak, const spx_coef_t *awk1, const spx_coef_t *awk2, spx_word16_t *y, int N, int ord, char *stack) -{ - int i; - VARDECL(spx_mem_t *mem); - ALLOC(mem, ord, spx_mem_t); - for (i=0;i<ord;i++) - mem[i]=0; - filter_mem16(xx, ak, awk1, y, N, ord, mem, stack); - for (i=0;i<ord;i++) - mem[i]=0; - fir_mem16(y, awk2, y, N, ord, mem, stack); -} - - -#ifndef OVERRIDE_COMPUTE_IMPULSE_RESPONSE -void compute_impulse_response(const spx_coef_t *ak, const spx_coef_t *awk1, const spx_coef_t *awk2, spx_word16_t *y, int N, int ord, char *stack) -{ - int i,j; - spx_word16_t y1, ny1i, ny2i; - VARDECL(spx_mem_t *mem1); - VARDECL(spx_mem_t *mem2); - ALLOC(mem1, ord, spx_mem_t); - ALLOC(mem2, ord, spx_mem_t); - - y[0] = LPC_SCALING; - for (i=0;i<ord;i++) - y[i+1] = awk1[i]; - i++; - for (;i<N;i++) - y[i] = VERY_SMALL; - for (i=0;i<ord;i++) - mem1[i] = mem2[i] = 0; - for (i=0;i<N;i++) - { - y1 = ADD16(y[i], EXTRACT16(PSHR32(mem1[0],LPC_SHIFT))); - ny1i = NEG16(y1); - y[i] = PSHR32(ADD32(SHL32(EXTEND32(y1),LPC_SHIFT+1),mem2[0]),LPC_SHIFT); - ny2i = NEG16(y[i]); - for (j=0;j<ord-1;j++) - { - mem1[j] = MAC16_16(mem1[j+1], awk2[j],ny1i); - mem2[j] = MAC16_16(mem2[j+1], ak[j],ny2i); - } - mem1[ord-1] = MULT16_16(awk2[ord-1],ny1i); - mem2[ord-1] = MULT16_16(ak[ord-1],ny2i); - } -} -#endif - -/* Decomposes a signal into low-band and high-band using a QMF */ -void qmf_decomp(const spx_word16_t *xx, const spx_word16_t *aa, spx_word16_t *y1, spx_word16_t *y2, int N, int M, spx_word16_t *mem, char *stack) -{ - int i,j,k,M2; - VARDECL(spx_word16_t *a); - VARDECL(spx_word16_t *x); - spx_word16_t *x2; - - ALLOC(a, M, spx_word16_t); - ALLOC(x, N+M-1, spx_word16_t); - x2=x+M-1; - M2=M>>1; - for (i=0;i<M;i++) - a[M-i-1]= aa[i]; - for (i=0;i<M-1;i++) - x[i]=mem[M-i-2]; - for (i=0;i<N;i++) - x[i+M-1]=SHR16(xx[i],1); - for (i=0;i<M-1;i++) - mem[i]=SHR16(xx[N-i-1],1); - for (i=0,k=0;i<N;i+=2,k++) - { - spx_word32_t y1k=0, y2k=0; - for (j=0;j<M2;j++) - { - y1k=ADD32(y1k,MULT16_16(a[j],ADD16(x[i+j],x2[i-j]))); - y2k=SUB32(y2k,MULT16_16(a[j],SUB16(x[i+j],x2[i-j]))); - j++; - y1k=ADD32(y1k,MULT16_16(a[j],ADD16(x[i+j],x2[i-j]))); - y2k=ADD32(y2k,MULT16_16(a[j],SUB16(x[i+j],x2[i-j]))); - } - y1[k] = EXTRACT16(SATURATE(PSHR32(y1k,15),32767)); - y2[k] = EXTRACT16(SATURATE(PSHR32(y2k,15),32767)); - } -} - -/* Re-synthesised a signal from the QMF low-band and high-band signals */ -void qmf_synth(const spx_word16_t *x1, const spx_word16_t *x2, const spx_word16_t *a, spx_word16_t *y, int N, int M, spx_word16_t *mem1, spx_word16_t *mem2, char *stack) - /* assumptions: - all odd x[i] are zero -- well, actually they are left out of the array now - N and M are multiples of 4 */ -{ - int i, j; - int M2, N2; - VARDECL(spx_word16_t *xx1); - VARDECL(spx_word16_t *xx2); - - M2 = M>>1; - N2 = N>>1; - ALLOC(xx1, M2+N2, spx_word16_t); - ALLOC(xx2, M2+N2, spx_word16_t); - - for (i = 0; i < N2; i++) - xx1[i] = x1[N2-1-i]; - for (i = 0; i < M2; i++) - xx1[N2+i] = mem1[2*i+1]; - for (i = 0; i < N2; i++) - xx2[i] = x2[N2-1-i]; - for (i = 0; i < M2; i++) - xx2[N2+i] = mem2[2*i+1]; - - for (i = 0; i < N2; i += 2) { - spx_sig_t y0, y1, y2, y3; - spx_word16_t x10, x20; - - y0 = y1 = y2 = y3 = 0; - x10 = xx1[N2-2-i]; - x20 = xx2[N2-2-i]; - - for (j = 0; j < M2; j += 2) { - spx_word16_t x11, x21; - spx_word16_t a0, a1; - - a0 = a[2*j]; - a1 = a[2*j+1]; - x11 = xx1[N2-1+j-i]; - x21 = xx2[N2-1+j-i]; - -#ifdef FIXED_POINT - /* We multiply twice by the same coef to avoid overflows */ - y0 = MAC16_16(MAC16_16(y0, a0, x11), NEG16(a0), x21); - y1 = MAC16_16(MAC16_16(y1, a1, x11), a1, x21); - y2 = MAC16_16(MAC16_16(y2, a0, x10), NEG16(a0), x20); - y3 = MAC16_16(MAC16_16(y3, a1, x10), a1, x20); -#else - y0 = ADD32(y0,MULT16_16(a0, x11-x21)); - y1 = ADD32(y1,MULT16_16(a1, x11+x21)); - y2 = ADD32(y2,MULT16_16(a0, x10-x20)); - y3 = ADD32(y3,MULT16_16(a1, x10+x20)); -#endif - a0 = a[2*j+2]; - a1 = a[2*j+3]; - x10 = xx1[N2+j-i]; - x20 = xx2[N2+j-i]; - -#ifdef FIXED_POINT - /* We multiply twice by the same coef to avoid overflows */ - y0 = MAC16_16(MAC16_16(y0, a0, x10), NEG16(a0), x20); - y1 = MAC16_16(MAC16_16(y1, a1, x10), a1, x20); - y2 = MAC16_16(MAC16_16(y2, a0, x11), NEG16(a0), x21); - y3 = MAC16_16(MAC16_16(y3, a1, x11), a1, x21); -#else - y0 = ADD32(y0,MULT16_16(a0, x10-x20)); - y1 = ADD32(y1,MULT16_16(a1, x10+x20)); - y2 = ADD32(y2,MULT16_16(a0, x11-x21)); - y3 = ADD32(y3,MULT16_16(a1, x11+x21)); -#endif - } -#ifdef FIXED_POINT - y[2*i] = EXTRACT16(SATURATE32(PSHR32(y0,15),32767)); - y[2*i+1] = EXTRACT16(SATURATE32(PSHR32(y1,15),32767)); - y[2*i+2] = EXTRACT16(SATURATE32(PSHR32(y2,15),32767)); - y[2*i+3] = EXTRACT16(SATURATE32(PSHR32(y3,15),32767)); -#else - /* Normalize up explicitly if we're in float */ - y[2*i] = 2.f*y0; - y[2*i+1] = 2.f*y1; - y[2*i+2] = 2.f*y2; - y[2*i+3] = 2.f*y3; -#endif - } - - for (i = 0; i < M2; i++) - mem1[2*i+1] = xx1[i]; - for (i = 0; i < M2; i++) - mem2[2*i+1] = xx2[i]; -} - -#ifdef FIXED_POINT -#if 0 -const spx_word16_t shift_filt[3][7] = {{-33, 1043, -4551, 19959, 19959, -4551, 1043}, - {-98, 1133, -4425, 29179, 8895, -2328, 444}, - {444, -2328, 8895, 29179, -4425, 1133, -98}}; -#else -const spx_word16_t shift_filt[3][7] = {{-390, 1540, -4993, 20123, 20123, -4993, 1540}, - {-1064, 2817, -6694, 31589, 6837, -990, -209}, - {-209, -990, 6837, 31589, -6694, 2817, -1064}}; -#endif -#else -#if 0 -const float shift_filt[3][7] = {{-9.9369e-04, 3.1831e-02, -1.3889e-01, 6.0910e-01, 6.0910e-01, -1.3889e-01, 3.1831e-02}, - {-0.0029937, 0.0345613, -0.1350474, 0.8904793, 0.2714479, -0.0710304, 0.0135403}, - {0.0135403, -0.0710304, 0.2714479, 0.8904793, -0.1350474, 0.0345613, -0.0029937}}; -#else -const float shift_filt[3][7] = {{-0.011915f, 0.046995f, -0.152373f, 0.614108f, 0.614108f, -0.152373f, 0.046995f}, - {-0.0324855f, 0.0859768f, -0.2042986f, 0.9640297f, 0.2086420f, -0.0302054f, -0.0063646f}, - {-0.0063646f, -0.0302054f, 0.2086420f, 0.9640297f, -0.2042986f, 0.0859768f, -0.0324855f}}; -#endif -#endif - -int interp_pitch( -spx_word16_t *exc, /*decoded excitation*/ -spx_word16_t *interp, /*decoded excitation*/ -int pitch, /*pitch period*/ -int len -) -{ - int i,j,k; - spx_word32_t corr[4][7]; - spx_word32_t maxcorr; - int maxi, maxj; - for (i=0;i<7;i++) - { - corr[0][i] = inner_prod(exc, exc-pitch-3+i, len); - } - for (i=0;i<3;i++) - { - for (j=0;j<7;j++) - { - int i1, i2; - spx_word32_t tmp=0; - i1 = 3-j; - if (i1<0) - i1 = 0; - i2 = 10-j; - if (i2>7) - i2 = 7; - for (k=i1;k<i2;k++) - tmp += MULT16_32_Q15(shift_filt[i][k],corr[0][j+k-3]); - corr[i+1][j] = tmp; - } - } - maxi=maxj=0; - maxcorr = corr[0][0]; - for (i=0;i<4;i++) - { - for (j=0;j<7;j++) - { - if (corr[i][j] > maxcorr) - { - maxcorr = corr[i][j]; - maxi=i; - maxj=j; - } - } - } - for (i=0;i<len;i++) - { - spx_word32_t tmp = 0; - if (maxi>0) - { - for (k=0;k<7;k++) - { - tmp += MULT16_16(exc[i-(pitch-maxj+3)+k-3],shift_filt[maxi-1][k]); - } - } else { - tmp = SHL32(exc[i-(pitch-maxj+3)],15); - } - interp[i] = PSHR32(tmp,15); - } - return pitch-maxj+3; -} - -void multicomb( -spx_word16_t *exc, /*decoded excitation*/ -spx_word16_t *new_exc, /*enhanced excitation*/ -spx_coef_t *ak, /*LPC filter coefs*/ -int p, /*LPC order*/ -int nsf, /*sub-frame size*/ -int pitch, /*pitch period*/ -int max_pitch, -spx_word16_t comb_gain, /*gain of comb filter*/ -char *stack -) -{ - int i; - VARDECL(spx_word16_t *iexc); - spx_word16_t old_ener, new_ener; - int corr_pitch; - - spx_word16_t iexc0_mag, iexc1_mag, exc_mag; - spx_word32_t corr0, corr1; - spx_word16_t gain0, gain1; - spx_word16_t pgain1, pgain2; - spx_word16_t c1, c2; - spx_word16_t g1, g2; - spx_word16_t ngain; - spx_word16_t gg1, gg2; -#ifdef FIXED_POINT - int scaledown=0; -#endif -#if 0 /* Set to 1 to enable full pitch search */ - int nol_pitch[6]; - spx_word16_t nol_pitch_coef[6]; - spx_word16_t ol_pitch_coef; - open_loop_nbest_pitch(exc, 20, 120, nsf, - nol_pitch, nol_pitch_coef, 6, stack); - corr_pitch=nol_pitch[0]; - ol_pitch_coef = nol_pitch_coef[0]; - /*Try to remove pitch multiples*/ - for (i=1;i<6;i++) - { -#ifdef FIXED_POINT - if ((nol_pitch_coef[i]>MULT16_16_Q15(nol_pitch_coef[0],19661)) && -#else - if ((nol_pitch_coef[i]>.6*nol_pitch_coef[0]) && -#endif - (ABS(2*nol_pitch[i]-corr_pitch)<=2 || ABS(3*nol_pitch[i]-corr_pitch)<=3 || - ABS(4*nol_pitch[i]-corr_pitch)<=4 || ABS(5*nol_pitch[i]-corr_pitch)<=5)) - { - corr_pitch = nol_pitch[i]; - } - } -#else - corr_pitch = pitch; -#endif - - ALLOC(iexc, 2*nsf, spx_word16_t); - - interp_pitch(exc, iexc, corr_pitch, 80); - if (corr_pitch>max_pitch) - interp_pitch(exc, iexc+nsf, 2*corr_pitch, 80); - else - interp_pitch(exc, iexc+nsf, -corr_pitch, 80); - -#ifdef FIXED_POINT - for (i=0;i<nsf;i++) - { - if (ABS16(exc[i])>16383) - { - scaledown = 1; - break; - } - } - if (scaledown) - { - for (i=0;i<nsf;i++) - exc[i] = SHR16(exc[i],1); - for (i=0;i<2*nsf;i++) - iexc[i] = SHR16(iexc[i],1); - } -#endif - /*interp_pitch(exc, iexc+2*nsf, 2*corr_pitch, 80);*/ - - /*printf ("%d %d %f\n", pitch, corr_pitch, max_corr*ener_1);*/ - iexc0_mag = spx_sqrt(1000+inner_prod(iexc,iexc,nsf)); - iexc1_mag = spx_sqrt(1000+inner_prod(iexc+nsf,iexc+nsf,nsf)); - exc_mag = spx_sqrt(1+inner_prod(exc,exc,nsf)); - corr0 = inner_prod(iexc,exc,nsf); - if (corr0<0) - corr0=0; - corr1 = inner_prod(iexc+nsf,exc,nsf); - if (corr1<0) - corr1=0; -#ifdef FIXED_POINT - /* Doesn't cost much to limit the ratio and it makes the rest easier */ - if (SHL32(EXTEND32(iexc0_mag),6) < EXTEND32(exc_mag)) - iexc0_mag = ADD16(1,PSHR16(exc_mag,6)); - if (SHL32(EXTEND32(iexc1_mag),6) < EXTEND32(exc_mag)) - iexc1_mag = ADD16(1,PSHR16(exc_mag,6)); -#endif - if (corr0 > MULT16_16(iexc0_mag,exc_mag)) - pgain1 = QCONST16(1., 14); - else - pgain1 = PDIV32_16(SHL32(PDIV32(corr0, exc_mag),14),iexc0_mag); - if (corr1 > MULT16_16(iexc1_mag,exc_mag)) - pgain2 = QCONST16(1., 14); - else - pgain2 = PDIV32_16(SHL32(PDIV32(corr1, exc_mag),14),iexc1_mag); - gg1 = PDIV32_16(SHL32(EXTEND32(exc_mag),8), iexc0_mag); - gg2 = PDIV32_16(SHL32(EXTEND32(exc_mag),8), iexc1_mag); - if (comb_gain>0) - { -#ifdef FIXED_POINT - c1 = (MULT16_16_Q15(QCONST16(.4,15),comb_gain)+QCONST16(.07,15)); - c2 = QCONST16(.5,15)+MULT16_16_Q14(QCONST16(1.72,14),(c1-QCONST16(.07,15))); -#else - c1 = .4*comb_gain+.07; - c2 = .5+1.72*(c1-.07); -#endif - } else - { - c1=c2=0; - } -#ifdef FIXED_POINT - g1 = 32767 - MULT16_16_Q13(MULT16_16_Q15(c2, pgain1),pgain1); - g2 = 32767 - MULT16_16_Q13(MULT16_16_Q15(c2, pgain2),pgain2); -#else - g1 = 1-c2*pgain1*pgain1; - g2 = 1-c2*pgain2*pgain2; -#endif - if (g1<c1) - g1 = c1; - if (g2<c1) - g2 = c1; - g1 = (spx_word16_t)PDIV32_16(SHL32(EXTEND32(c1),14),(spx_word16_t)g1); - g2 = (spx_word16_t)PDIV32_16(SHL32(EXTEND32(c1),14),(spx_word16_t)g2); - if (corr_pitch>max_pitch) - { - gain0 = MULT16_16_Q15(QCONST16(.7,15),MULT16_16_Q14(g1,gg1)); - gain1 = MULT16_16_Q15(QCONST16(.3,15),MULT16_16_Q14(g2,gg2)); - } else { - gain0 = MULT16_16_Q15(QCONST16(.6,15),MULT16_16_Q14(g1,gg1)); - gain1 = MULT16_16_Q15(QCONST16(.6,15),MULT16_16_Q14(g2,gg2)); - } - for (i=0;i<nsf;i++) - new_exc[i] = ADD16(exc[i], EXTRACT16(PSHR32(ADD32(MULT16_16(gain0,iexc[i]), MULT16_16(gain1,iexc[i+nsf])),8))); - /* FIXME: compute_rms16 is currently not quite accurate enough (but close) */ - new_ener = compute_rms16(new_exc, nsf); - old_ener = compute_rms16(exc, nsf); - - if (old_ener < 1) - old_ener = 1; - if (new_ener < 1) - new_ener = 1; - if (old_ener > new_ener) - old_ener = new_ener; - ngain = PDIV32_16(SHL32(EXTEND32(old_ener),14),new_ener); - - for (i=0;i<nsf;i++) - new_exc[i] = MULT16_16_Q14(ngain, new_exc[i]); -#ifdef FIXED_POINT - if (scaledown) - { - for (i=0;i<nsf;i++) - exc[i] = SHL16(exc[i],1); - for (i=0;i<nsf;i++) - new_exc[i] = SHL16(SATURATE16(new_exc[i],16383),1); - } -#endif -} - diff --git a/drivers/speex/filters.h b/drivers/speex/filters.h deleted file mode 100644 index e3a5980e70..0000000000 --- a/drivers/speex/filters.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @file filters.h - @brief Various analysis/synthesis filters -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 FILTERS_H -#define FILTERS_H - -#include "arch.h" - -spx_word16_t compute_rms(const spx_sig_t *x, int len); -spx_word16_t compute_rms16(const spx_word16_t *x, int len); -void signal_mul(const spx_sig_t *x, spx_sig_t *y, spx_word32_t scale, int len); -void signal_div(const spx_word16_t *x, spx_word16_t *y, spx_word32_t scale, int len); - -#ifdef FIXED_POINT - -int normalize16(const spx_sig_t *x, spx_word16_t *y, spx_sig_t max_scale, int len); - -#endif - - -#define HIGHPASS_NARROWBAND 0 -#define HIGHPASS_WIDEBAND 2 -#define HIGHPASS_INPUT 0 -#define HIGHPASS_OUTPUT 1 -#define HIGHPASS_IRS 4 - -void highpass(const spx_word16_t *x, spx_word16_t *y, int len, int filtID, spx_mem_t *mem); - - -void qmf_decomp(const spx_word16_t *xx, const spx_word16_t *aa, spx_word16_t *, spx_word16_t *y2, int N, int M, spx_word16_t *mem, char *stack); -void qmf_synth(const spx_word16_t *x1, const spx_word16_t *x2, const spx_word16_t *a, spx_word16_t *y, int N, int M, spx_word16_t *mem1, spx_word16_t *mem2, char *stack); - -void filter_mem16(const spx_word16_t *x, const spx_coef_t *num, const spx_coef_t *den, spx_word16_t *y, int N, int ord, spx_mem_t *mem, char *stack); -void iir_mem16(const spx_word16_t *x, const spx_coef_t *den, spx_word16_t *y, int N, int ord, spx_mem_t *mem, char *stack); -void fir_mem16(const spx_word16_t *x, const spx_coef_t *num, spx_word16_t *y, int N, int ord, spx_mem_t *mem, char *stack); - -/* Apply bandwidth expansion on LPC coef */ -void bw_lpc(spx_word16_t , const spx_coef_t *lpc_in, spx_coef_t *lpc_out, int order); -void sanitize_values32(spx_word32_t *vec, spx_word32_t min_val, spx_word32_t max_val, int len); - - -void syn_percep_zero16(const spx_word16_t *xx, const spx_coef_t *ak, const spx_coef_t *awk1, const spx_coef_t *awk2, spx_word16_t *y, int N, int ord, char *stack); -void residue_percep_zero16(const spx_word16_t *xx, const spx_coef_t *ak, const spx_coef_t *awk1, const spx_coef_t *awk2, spx_word16_t *y, int N, int ord, char *stack); - -void compute_impulse_response(const spx_coef_t *ak, const spx_coef_t *awk1, const spx_coef_t *awk2, spx_word16_t *y, int N, int ord, char *stack); - -void multicomb( -spx_word16_t *exc, /*decoded excitation*/ -spx_word16_t *new_exc, /*enhanced excitation*/ -spx_coef_t *ak, /*LPC filter coefs*/ -int p, /*LPC order*/ -int nsf, /*sub-frame size*/ -int pitch, /*pitch period*/ -int max_pitch, /*pitch gain (3-tap)*/ -spx_word16_t comb_gain, /*gain of comb filter*/ -char *stack -); - -#endif diff --git a/drivers/speex/filters_arm4.h b/drivers/speex/filters_arm4.h deleted file mode 100644 index 7a74042467..0000000000 --- a/drivers/speex/filters_arm4.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (C) 2004 Jean-Marc Valin */ -/** - @file filters_arm4.h - @brief Various analysis/synthesis filters (ARM4 version) -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#define OVERRIDE_NORMALIZE16 -int normalize16(const spx_sig_t *x, spx_word16_t *y, spx_sig_t max_scale, int len) -{ - spx_sig_t max_val=1; - int sig_shift; - int dead1, dead2, dead3, dead4, dead5, dead6; - - __asm__ __volatile__ ( - "\tmov %1, #1 \n" - "\tmov %3, #0 \n" - - ".normalize16loop1%=: \n" - - "\tldr %4, [%0], #4 \n" - "\tcmps %4, %1 \n" - "\tmovgt %1, %4 \n" - "\tcmps %4, %3 \n" - "\tmovlt %3, %4 \n" - - "\tsubs %2, %2, #1 \n" - "\tbne .normalize16loop1%=\n" - - "\trsb %3, %3, #0 \n" - "\tcmp %1, %3 \n" - "\tmovlt %1, %3 \n" - : "=r" (dead1), "=r" (max_val), "=r" (dead3), "=r" (dead4), - "=r" (dead5), "=r" (dead6) - : "0" (x), "2" (len) - : "cc"); - - sig_shift=0; - while (max_val>max_scale) - { - sig_shift++; - max_val >>= 1; - } - - __asm__ __volatile__ ( - ".normalize16loop%=: \n" - - "\tldr %4, [%0], #4 \n" - "\tldr %5, [%0], #4 \n" - "\tmov %4, %4, asr %3 \n" - "\tstrh %4, [%1], #2 \n" - "\tldr %4, [%0], #4 \n" - "\tmov %5, %5, asr %3 \n" - "\tstrh %5, [%1], #2 \n" - "\tldr %5, [%0], #4 \n" - "\tmov %4, %4, asr %3 \n" - "\tstrh %4, [%1], #2 \n" - "\tsubs %2, %2, #1 \n" - "\tmov %5, %5, asr %3 \n" - "\tstrh %5, [%1], #2 \n" - - "\tbgt .normalize16loop%=\n" - : "=r" (dead1), "=r" (dead2), "=r" (dead3), "=r" (dead4), - "=r" (dead5), "=r" (dead6) - : "0" (x), "1" (y), "2" (len>>2), "3" (sig_shift) - : "cc", "memory"); - return sig_shift; -} - diff --git a/drivers/speex/filters_bfin.h b/drivers/speex/filters_bfin.h deleted file mode 100644 index 1e433ee167..0000000000 --- a/drivers/speex/filters_bfin.h +++ /dev/null @@ -1,515 +0,0 @@ -/* Copyright (C) 2005 Analog Devices */ -/** - @file filters_bfin.h - @brief Various analysis/synthesis filters (Blackfin version) -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#define OVERRIDE_NORMALIZE16 -int normalize16(const spx_sig_t *x, spx_word16_t *y, spx_sig_t max_scale, int len) -{ - spx_sig_t max_val=1; - int sig_shift; - __asm__ - ( - "%0 = 0;\n\t" - "I0 = %1;\n\t" - "L0 = 0;\n\t" - "R1 = [I0++];\n\t" - "LOOP norm_max%= LC0 = %2;\n\t" - "LOOP_BEGIN norm_max%=;\n\t" - "R2 = ABS R1 || R1 = [I0++];\n\t" - "%0 = MAX(%0, R2);\n\t" - "LOOP_END norm_max%=;\n\t" - : "=&d" (max_val) - : "a" (x), "a" (len) - : "R1", "R2" - ); - - sig_shift=0; - while (max_val>max_scale) - { - sig_shift++; - max_val >>= 1; - } - - __asm__ __volatile__ - ( - "I0 = %0;\n\t" - "L0 = 0;\n\t" - "P1 = %1;\n\t" - "R0 = [I0++];\n\t" - "LOOP norm_shift%= LC0 = %3;\n\t" - "LOOP_BEGIN norm_shift%=;\n\t" - "R1 = ASHIFT R0 by %2.L || R0 = [I0++];\n\t" - "W[P1++] = R1;\n\t" - "LOOP_END norm_shift%=;\n\t" - "R1 = ASHIFT R0 by %2.L;\n\t" - "W[P1++] = R1;\n\t" - : : "a" (x), "a" (y), "d" (-sig_shift), "a" (len-1) - : "I0", "L0", "P1", "R0", "R1", "memory" - ); - return sig_shift; -} - - - -#define OVERRIDE_FILTER_MEM16 -void filter_mem16(const spx_word16_t *_x, const spx_coef_t *num, const spx_coef_t *den, spx_word16_t *_y, int N, int ord, spx_mem_t *mem, char *stack) -{ - VARDECL(spx_word32_t *xy2); - VARDECL(spx_word32_t *numden_a); - spx_word32_t *xy; - spx_word16_t *numden; - int i; - - ALLOC(xy2, (N+1), spx_word32_t); - ALLOC(numden_a, (2*ord+2), spx_word32_t); - xy = xy2+1; - numden = (spx_word16_t*) numden_a; - - for (i=0;i<ord;i++) - { - numden[2*i] = num[i]; - numden[2*i+1] = den[i]; - } - __asm__ __volatile__ - ( - /* Register setup */ - "R0 = %5;\n\t" /*ord */ - - "P0 = %3;\n\t" - "I0 = P0;\n\t" - "B0 = P0;\n\t" /* numden */ - "L0 = 0;\n\t" - - "P2 = %0;\n\t" /* Fused xy */ - "I2 = P2;\n\t" - "L2 = 0;\n\t" - - "P4 = %6;\n\t" /* mem */ - "P0 = %1;\n\t" /* _x */ - "P1 = %2;\n\t" /* _y */ - - /* First sample */ - "R1 = [P4++];\n\t" - "R1 <<= 3;\n\t" /* shift mem */ - "R1.L = R1 (RND);\n\t" - "R2 = W[P0++];\n\t" /* load x[0] */ - "R1.L = R1.L + R2.L;\n\t" - "W[P1++] = R1;\n\t" /* store y[0] */ - "R2 = PACK(R1.L, R2.L);\n\t" /* pack x16 and y16 */ - "[P2] = R2;\n\t" - - /* Samples 1 to ord-1 (using memory) */ - "R0 += -1;\n\t" - "R3 = 0;\n\t" - "LC0 = R0;\n\t" - "LOOP filter_start%= LC0;\n\t" - "LOOP_BEGIN filter_start%=;\n\t" - "R3 += 1;\n\t" - "LC1 = R3;\n\t" - - "R1 = [P4++];\n\t" - "A1 = R1;\n\t" - "A0 = 0;\n\t" - "I0 = B0;\n\t" - "I2 = P2;\n\t" - "P2 += 4;\n\t" - "R4 = [I0++] || R5 = [I2--];\n\t" - "LOOP filter_start_inner%= LC1;\n\t" - "LOOP_BEGIN filter_start_inner%=;\n\t" - "A1 -= R4.H*R5.H, A0 += R4.L*R5.L (IS) || R4 = [I0++] || R5 = [I2--];\n\t" - "LOOP_END filter_start_inner%=;\n\t" - "A0 += A1;\n\t" - "R4 = A0;\n\t" - "R4 <<= 3;\n\t" /* shift mem */ - "R4.L = R4 (RND);\n\t" - "R2 = W[P0++];\n\t" /* load x */ - "R4.L = R4.L + R2.L;\n\t" - "W[P1++] = R4;\n\t" /* store y */ - //"R4 <<= 2;\n\t" - //"R2 <<= 2;\n\t" - "R2 = PACK(R4.L, R2.L);\n\t" /* pack x16 and y16 */ - "[P2] = R2;\n\t" - - "LOOP_END filter_start%=;\n\t" - - /* Samples ord to N*/ - "R0 = %5;\n\t" - "R0 <<= 1;\n\t" - "I0 = B0;\n\t" /* numden */ - "R0 <<= 1;\n\t" - "L0 = R0;\n\t" - - "R0 = %5;\n\t" /* org */ - "R2 = %4;\n\t" /* N */ - "R2 = R2 - R0;\n\t" - "R4 = [I0++];\n\t" /* numden */ - "LC0 = R2;\n\t" - "P3 = R0;\n\t" - "R0 <<= 2;\n\t" - "R0 += 8;\n\t" - "I2 = P2;\n\t" - "M0 = R0;\n\t" - "A1 = A0 = 0;\n\t" - "R5 = [I2--];\n\t" /* load xy */ - "LOOP filter_mid%= LC0;\n\t" - "LOOP_BEGIN filter_mid%=;\n\t" - "LOOP filter_mid_inner%= LC1=P3;\n\t" - "LOOP_BEGIN filter_mid_inner%=;\n\t" - "A1 -= R4.H*R5.H, A0 += R4.L*R5.L (IS) || R4 = [I0++] || R5 = [I2--];\n\t" - "LOOP_END filter_mid_inner%=;\n\t" - "R0 = (A0 += A1) || I2 += M0;\n\t" - "R0 = R0 << 3 || R5 = W[P0++];\n\t" /* load x */ - "R0.L = R0 (RND);\n\t" - "R0.L = R0.L + R5.L;\n\t" - "R5 = PACK(R0.L, R5.L) || W[P1++] = R0;\n\t" /* shift y | store y */ - "A1 = A0 = 0 || [I2--] = R5\n\t" - "LOOP_END filter_mid%=;\n\t" - "I2 += 4;\n\t" - "P2 = I2;\n\t" - /* Update memory */ - "P4 = %6;\n\t" - "R0 = %5;\n\t" - "LC0 = R0;\n\t" - "P0 = B0;\n\t" - "A1 = A0 = 0;\n\t" - "LOOP mem_update%= LC0;\n\t" - "LOOP_BEGIN mem_update%=;\n\t" - "I2 = P2;\n\t" - "I0 = P0;\n\t" - "P0 += 4;\n\t" - "R0 = LC0;\n\t" - "LC1 = R0;\n\t" - "R5 = [I2--] || R4 = [I0++];\n\t" - "LOOP mem_accum%= LC1;\n\t" - "LOOP_BEGIN mem_accum%=;\n\t" - "A1 -= R4.H*R5.H, A0 += R4.L*R5.L (IS) || R4 = [I0++] || R5 = [I2--];\n\t" - "LOOP_END mem_accum%=;\n\t" - "R0 = (A0 += A1);\n\t" - "A1 = A0 = 0 || [P4++] = R0;\n\t" - "LOOP_END mem_update%=;\n\t" - "L0 = 0;\n\t" - : : "m" (xy), "m" (_x), "m" (_y), "m" (numden), "m" (N), "m" (ord), "m" (mem) - : "A0", "A1", "R0", "R1", "R2", "R3", "R4", "R5", "P0", "P1", "P2", "P3", "P4", "B0", "I0", "I2", "L0", "L2", "M0", "memory" - ); - -} - - - -#define OVERRIDE_IIR_MEM16 -void iir_mem16(const spx_word16_t *_x, const spx_coef_t *den, spx_word16_t *_y, int N, int ord, spx_mem_t *mem, char *stack) -{ - VARDECL(spx_word16_t *y); - spx_word16_t *yy; - - ALLOC(y, (N+2), spx_word16_t); - yy = y+2; - - __asm__ __volatile__ - ( - /* Register setup */ - "R0 = %5;\n\t" /*ord */ - - "P1 = %3;\n\t" - "I1 = P1;\n\t" - "B1 = P1;\n\t" - "L1 = 0;\n\t" - - "P3 = %0;\n\t" - "I3 = P3;\n\t" - "L3 = 0;\n\t" - - "P4 = %6;\n\t" - "P0 = %1;\n\t" - "P1 = %2;\n\t" - - /* First sample */ - "R1 = [P4++];\n\t" - "R1 = R1 << 3 (S);\n\t" - "R1.L = R1 (RND);\n\t" - "R2 = W[P0++];\n\t" - "R1 = R1 + R2;\n\t" - "W[P1++] = R1;\n\t" - "W[P3] = R1;\n\t" - - /* Samples 1 to ord-1 (using memory) */ - "R0 += -1;\n\t" - "R3 = 0;\n\t" - "LC0 = R0;\n\t" - "LOOP filter_start%= LC0;\n\t" - "LOOP_BEGIN filter_start%=;\n\t" - "R3 += 1;\n\t" - "LC1 = R3;\n\t" - - "R1 = [P4++];\n\t" - "A1 = R1;\n\t" - "I1 = B1;\n\t" - "I3 = P3;\n\t" - "P3 += 2;\n\t" - "LOOP filter_start_inner%= LC1;\n\t" - "LOOP_BEGIN filter_start_inner%=;\n\t" - "R4.L = W[I1++];\n\t" - "R5.L = W[I3--];\n\t" - "A1 -= R4.L*R5.L (IS);\n\t" - "LOOP_END filter_start_inner%=;\n\t" - - "R1 = A1;\n\t" - "R1 <<= 3;\n\t" - "R1.L = R1 (RND);\n\t" - "R2 = W[P0++];\n\t" - "R1 = R1 + R2;\n\t" - "W[P1++] = R1;\n\t" - "W[P3] = R1;\n\t" - "LOOP_END filter_start%=;\n\t" - - /* Samples ord to N*/ - "R0 = %5;\n\t" - "R0 <<= 1;\n\t" - "I1 = B1;\n\t" - "L1 = R0;\n\t" - - "R0 = %5;\n\t" - "R2 = %4;\n\t" - "R2 = R2 - R0;\n\t" - "R4.L = W[I1++];\n\t" - "LC0 = R2;\n\t" - "LOOP filter_mid%= LC0;\n\t" - "LOOP_BEGIN filter_mid%=;\n\t" - "LC1 = R0;\n\t" - "A1 = 0;\n\t" - "I3 = P3;\n\t" - "P3 += 2;\n\t" - "R5.L = W[I3--];\n\t" - "LOOP filter_mid_inner%= LC1;\n\t" - "LOOP_BEGIN filter_mid_inner%=;\n\t" - "A1 -= R4.L*R5.L (IS) || R4.L = W[I1++] || R5.L = W[I3--];\n\t" - "LOOP_END filter_mid_inner%=;\n\t" - "R1 = A1;\n\t" - "R1 = R1 << 3 || R2 = W[P0++];\n\t" - "R1.L = R1 (RND);\n\t" - "R1 = R1 + R2;\n\t" - "W[P1++] = R1;\n\t" - "W[P3] = R1;\n\t" - "LOOP_END filter_mid%=;\n\t" - - /* Update memory */ - "P4 = %6;\n\t" - "R0 = %5;\n\t" - "LC0 = R0;\n\t" - "P1 = B1;\n\t" - "LOOP mem_update%= LC0;\n\t" - "LOOP_BEGIN mem_update%=;\n\t" - "A0 = 0;\n\t" - "I3 = P3;\n\t" - "I1 = P1;\n\t" - "P1 += 2;\n\t" - "R0 = LC0;\n\t" - "LC1=R0;\n\t" - "R5.L = W[I3--] || R4.L = W[I1++];\n\t" - "LOOP mem_accum%= LC1;\n\t" - "LOOP_BEGIN mem_accum%=;\n\t" - "A0 -= R4.L*R5.L (IS) || R4.L = W[I1++] || R5.L = W[I3--];\n\t" - "LOOP_END mem_accum%=;\n\t" - "R0 = A0;\n\t" - "[P4++] = R0;\n\t" - "LOOP_END mem_update%=;\n\t" - "L1 = 0;\n\t" - : : "m" (yy), "m" (_x), "m" (_y), "m" (den), "m" (N), "m" (ord), "m" (mem) - : "A0", "A1", "R0", "R1", "R2", "R3", "R4", "R5", "P0", "P1", "P2", "P3", "P4", "B1", "I1", "I3", "L1", "L3", "memory" - ); - -} - - -#define OVERRIDE_FIR_MEM16 -void fir_mem16(const spx_word16_t *x, const spx_coef_t *num, spx_word16_t *y, int N, int ord, spx_mem_t *mem, char *stack) -{ - int i; - spx_coef_t den2[12]; - spx_coef_t *den; - den = (spx_coef_t*)((((int)den2)+4)&0xfffffffc); - for (i=0;i<10;i++) - den[i] = 0; - filter_mem16(x, num, den, y, N, ord, mem, stack); -} - - -#define OVERRIDE_COMPUTE_IMPULSE_RESPONSE -void compute_impulse_response(const spx_coef_t *ak, const spx_coef_t *awk1, const spx_coef_t *awk2, spx_word16_t *y, int N, int ord, char *stack) -{ - int i; - VARDECL(spx_word16_t *ytmp); - ALLOC(ytmp, N, spx_word16_t); - spx_word16_t *ytmp2 = ytmp; - y[0] = LPC_SCALING; - for (i=0;i<ord;i++) - y[i+1] = awk1[i]; - i++; - for (;i<N;i++) - y[i] = 0; - - N-=1; - __asm__ __volatile__ - ( - "I0 = %0;\n\t" - "I1 = %1;\n\t" - "L0 = 0;\n\t" - "L1 = 0;\n\t" - "L2 = 0;\n\t" - "L3 = 0;\n\t" - "R0 = 1;\n\t" - "R0 <<= 13;\n\t" - "W[I0] = R0.L;\n\t" - "R0 <<= 1;\n\t" - "W[I1] = R0.L;\n\t" - "R0 = %5;\n\t" - "LC0 = R0;\n\t" - "R2 = 0;\n\t" - "LOOP samples%= LC0;\n\t" - "LOOP_BEGIN samples%=;\n\t" - "R2 += 1;\n\t" - "R2 = MIN(R2, %4);\n\t" - "I0 = %0;\n\t" - "I1 = %1;\n\t" - "I2 = %2;\n\t" - "I3 = %3;\n\t" - "%0 += 2;\n\t" - "%1 += 2;\n\t" - "A1 = A0 = 0;\n\t" - "R0.L = W[I0--] || R1.L = W[I2++];\n\t" - "LC1 = R2;\n\t" - "LOOP filter%= LC1;\n\t" - "LOOP_BEGIN filter%=;\n\t" - "A0 -= R0.L*R1.L (IS) || R0.L = W[I1--] || R1.L = W[I3++];\n\t" - "A1 -= R0.L*R1.L (IS) || R0.L = W[I0--] || R1.L = W[I2++];\n\t" - "LOOP_END filter%=;\n\t" - "R0 = A0, R1 = A1;\n\t" - "R3 = W[%1] (X);\n\t" - "R3 <<= 13;\n\t" - "R0 = R0 + R3;\n\t" - "R3 = R0 >>> 13;\n\t" - "W[%0] = R3.L;\n\t" - "R0 <<= 1;\n\t" - "R1 = R1 + R0;\n\t" - "R1 >>>= 13;\n\t" - "W[%1] = R1.L;\n\t" - "LOOP_END samples%=;\n\t" - : "=a" (ytmp2), "=a" (y) - : "a" (awk2), "a" (ak), "d" (ord), "m" (N), "0" (ytmp2), "1" (y) - : "A0", "A1", "R0", "R1", "R2", "R3", "I0", "I1", "I2", "I3", "L0", "L1", "L2", "L3", "A0", "A1" - ); -} - - - -#if 0 /* Equivalent C function for filter_mem2 and compute_impulse_response */ -#define min(a,b) ((a)<(b) ? (a):(b)) - -void compute_impulse_response(const spx_coef_t *ak, const spx_coef_t *awk1, const spx_coef_t *awk2, spx_word16_t *y, int N, int ord, char *stack) -{ - int i,j; - VARDECL(spx_word16_t *ytmp); - ALLOC(ytmp, N, spx_word16_t); - - y[0] = LPC_SCALING; - for (i=0;i<ord;i++) - y[i+1] = awk1[i]; - i++; - for (;i<N;i++) - y[i] = 0; - - for (i=0;i<N;i++) - { - spx_word32_t yi = SHL32(EXTEND32(y[i]),LPC_SHIFT); - spx_word32_t yi2 = 0; - for (j=0;j<min(i,ord);j++) - { - yi = MAC16_16(yi, awk2[j], -ytmp[i-j-1]); - yi2 = MAC16_16(yi2, ak[j], -y[i-j-1]); - } - ytmp[i] = EXTRACT16(SHR32(yi,LPC_SHIFT)); - yi2 = ADD32(yi2,SHL32(yi,1)); - y[i] = EXTRACT16(SHR32(yi2,LPC_SHIFT)); - } - -} - - -void filter_mem2(const spx_sig_t *_x, const spx_coef_t *num, const spx_coef_t *den, spx_sig_t *_y, int N, int ord, spx_mem_t *mem) -{ - int i,j; - spx_word16_t xi,yi,nyi; - spx_word16_t x[N],y[N]; - spx_word16_t *xx, *yy; - xx = x; - yy = y; - for (i=0;i<N;i++) - { - x[i] = EXTRACT16(SHR32(_x[i],SIG_SHIFT)); - } - - for (i=0;i<ord;i++) - { - spx_word32_t yi = mem[i]; - for (j=0;j<i;j++) - { - yi = MAC16_16(yi, num[j], x[i-j-1]); - yi = MAC16_16(yi, den[j], -y[i-j-1]); - } - _y[i] = ADD32(_x[i],SHL32(yi,1)); - y[i] = EXTRACT16(SHR32(_y[i],SIG_SHIFT)); - } - for (i=ord;i<N;i++) - { - spx_word32_t yi = 0; - for (j=0;j<ord;j++) - { - yi = MAC16_16(yi, num[j], x[i-j-1]); - yi = MAC16_16(yi, den[j], -y[i-j-1]); - } - _y[i] = ADD32(_x[i],SHL32(yi,1)); - y[i] = EXTRACT16(SHR32(_y[i],SIG_SHIFT)); - } - - for (i=0;i<ord;i++) - { - spx_mem_t m = 0; - for (j=0;j<ord-i;j++) - { - m = MAC16_16(m, x[N-1-j], num[j+i]); - m = MAC16_16(m, -y[N-1-j], den[j+i]); - } - mem[i] = m; - } -} -#endif diff --git a/drivers/speex/filters_sse.h b/drivers/speex/filters_sse.h deleted file mode 100644 index 4bb333daf3..0000000000 --- a/drivers/speex/filters_sse.h +++ /dev/null @@ -1,336 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @file filters_sse.h - @brief Various analysis/synthesis filters (SSE version) -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#include <xmmintrin.h> - -void filter_mem16_10(const float *x, const float *_num, const float *_den, float *y, int N, int ord, float *_mem) -{ - __m128 num[3], den[3], mem[3]; - - int i; - - /* Copy numerator, denominator and memory to aligned xmm */ - for (i=0;i<2;i++) - { - mem[i] = _mm_loadu_ps(_mem+4*i); - num[i] = _mm_loadu_ps(_num+4*i); - den[i] = _mm_loadu_ps(_den+4*i); - } - mem[2] = _mm_setr_ps(_mem[8], _mem[9], 0, 0); - num[2] = _mm_setr_ps(_num[8], _num[9], 0, 0); - den[2] = _mm_setr_ps(_den[8], _den[9], 0, 0); - - for (i=0;i<N;i++) - { - __m128 xx; - __m128 yy; - /* Compute next filter result */ - xx = _mm_load_ps1(x+i); - yy = _mm_add_ss(xx, mem[0]); - _mm_store_ss(y+i, yy); - yy = _mm_shuffle_ps(yy, yy, 0); - - /* Update memory */ - mem[0] = _mm_move_ss(mem[0], mem[1]); - mem[0] = _mm_shuffle_ps(mem[0], mem[0], 0x39); - - mem[0] = _mm_add_ps(mem[0], _mm_mul_ps(xx, num[0])); - mem[0] = _mm_sub_ps(mem[0], _mm_mul_ps(yy, den[0])); - - mem[1] = _mm_move_ss(mem[1], mem[2]); - mem[1] = _mm_shuffle_ps(mem[1], mem[1], 0x39); - - mem[1] = _mm_add_ps(mem[1], _mm_mul_ps(xx, num[1])); - mem[1] = _mm_sub_ps(mem[1], _mm_mul_ps(yy, den[1])); - - mem[2] = _mm_shuffle_ps(mem[2], mem[2], 0xfd); - - mem[2] = _mm_add_ps(mem[2], _mm_mul_ps(xx, num[2])); - mem[2] = _mm_sub_ps(mem[2], _mm_mul_ps(yy, den[2])); - } - /* Put memory back in its place */ - _mm_storeu_ps(_mem, mem[0]); - _mm_storeu_ps(_mem+4, mem[1]); - _mm_store_ss(_mem+8, mem[2]); - mem[2] = _mm_shuffle_ps(mem[2], mem[2], 0x55); - _mm_store_ss(_mem+9, mem[2]); -} - -void filter_mem16_8(const float *x, const float *_num, const float *_den, float *y, int N, int ord, float *_mem) -{ - __m128 num[2], den[2], mem[2]; - - int i; - - /* Copy numerator, denominator and memory to aligned xmm */ - for (i=0;i<2;i++) - { - mem[i] = _mm_loadu_ps(_mem+4*i); - num[i] = _mm_loadu_ps(_num+4*i); - den[i] = _mm_loadu_ps(_den+4*i); - } - - for (i=0;i<N;i++) - { - __m128 xx; - __m128 yy; - /* Compute next filter result */ - xx = _mm_load_ps1(x+i); - yy = _mm_add_ss(xx, mem[0]); - _mm_store_ss(y+i, yy); - yy = _mm_shuffle_ps(yy, yy, 0); - - /* Update memory */ - mem[0] = _mm_move_ss(mem[0], mem[1]); - mem[0] = _mm_shuffle_ps(mem[0], mem[0], 0x39); - - mem[0] = _mm_add_ps(mem[0], _mm_mul_ps(xx, num[0])); - mem[0] = _mm_sub_ps(mem[0], _mm_mul_ps(yy, den[0])); - - mem[1] = _mm_sub_ss(mem[1], mem[1]); - mem[1] = _mm_shuffle_ps(mem[1], mem[1], 0x39); - - mem[1] = _mm_add_ps(mem[1], _mm_mul_ps(xx, num[1])); - mem[1] = _mm_sub_ps(mem[1], _mm_mul_ps(yy, den[1])); - } - /* Put memory back in its place */ - _mm_storeu_ps(_mem, mem[0]); - _mm_storeu_ps(_mem+4, mem[1]); -} - - -#define OVERRIDE_FILTER_MEM16 -void filter_mem16(const float *x, const float *_num, const float *_den, float *y, int N, int ord, float *_mem, char *stack) -{ - if(ord==10) - filter_mem16_10(x, _num, _den, y, N, ord, _mem); - else if (ord==8) - filter_mem16_8(x, _num, _den, y, N, ord, _mem); -} - - - -void iir_mem16_10(const float *x, const float *_den, float *y, int N, int ord, float *_mem) -{ - __m128 den[3], mem[3]; - - int i; - - /* Copy numerator, denominator and memory to aligned xmm */ - for (i=0;i<2;i++) - { - mem[i] = _mm_loadu_ps(_mem+4*i); - den[i] = _mm_loadu_ps(_den+4*i); - } - mem[2] = _mm_setr_ps(_mem[8], _mem[9], 0, 0); - den[2] = _mm_setr_ps(_den[8], _den[9], 0, 0); - - for (i=0;i<N;i++) - { - __m128 xx; - __m128 yy; - /* Compute next filter result */ - xx = _mm_load_ps1(x+i); - yy = _mm_add_ss(xx, mem[0]); - _mm_store_ss(y+i, yy); - yy = _mm_shuffle_ps(yy, yy, 0); - - /* Update memory */ - mem[0] = _mm_move_ss(mem[0], mem[1]); - mem[0] = _mm_shuffle_ps(mem[0], mem[0], 0x39); - - mem[0] = _mm_sub_ps(mem[0], _mm_mul_ps(yy, den[0])); - - mem[1] = _mm_move_ss(mem[1], mem[2]); - mem[1] = _mm_shuffle_ps(mem[1], mem[1], 0x39); - - mem[1] = _mm_sub_ps(mem[1], _mm_mul_ps(yy, den[1])); - - mem[2] = _mm_shuffle_ps(mem[2], mem[2], 0xfd); - - mem[2] = _mm_sub_ps(mem[2], _mm_mul_ps(yy, den[2])); - } - /* Put memory back in its place */ - _mm_storeu_ps(_mem, mem[0]); - _mm_storeu_ps(_mem+4, mem[1]); - _mm_store_ss(_mem+8, mem[2]); - mem[2] = _mm_shuffle_ps(mem[2], mem[2], 0x55); - _mm_store_ss(_mem+9, mem[2]); -} - - -void iir_mem16_8(const float *x, const float *_den, float *y, int N, int ord, float *_mem) -{ - __m128 den[2], mem[2]; - - int i; - - /* Copy numerator, denominator and memory to aligned xmm */ - for (i=0;i<2;i++) - { - mem[i] = _mm_loadu_ps(_mem+4*i); - den[i] = _mm_loadu_ps(_den+4*i); - } - - for (i=0;i<N;i++) - { - __m128 xx; - __m128 yy; - /* Compute next filter result */ - xx = _mm_load_ps1(x+i); - yy = _mm_add_ss(xx, mem[0]); - _mm_store_ss(y+i, yy); - yy = _mm_shuffle_ps(yy, yy, 0); - - /* Update memory */ - mem[0] = _mm_move_ss(mem[0], mem[1]); - mem[0] = _mm_shuffle_ps(mem[0], mem[0], 0x39); - - mem[0] = _mm_sub_ps(mem[0], _mm_mul_ps(yy, den[0])); - - mem[1] = _mm_sub_ss(mem[1], mem[1]); - mem[1] = _mm_shuffle_ps(mem[1], mem[1], 0x39); - - mem[1] = _mm_sub_ps(mem[1], _mm_mul_ps(yy, den[1])); - } - /* Put memory back in its place */ - _mm_storeu_ps(_mem, mem[0]); - _mm_storeu_ps(_mem+4, mem[1]); -} - -#define OVERRIDE_IIR_MEM16 -void iir_mem16(const float *x, const float *_den, float *y, int N, int ord, float *_mem, char *stack) -{ - if(ord==10) - iir_mem16_10(x, _den, y, N, ord, _mem); - else if (ord==8) - iir_mem16_8(x, _den, y, N, ord, _mem); -} - - -void fir_mem16_10(const float *x, const float *_num, float *y, int N, int ord, float *_mem) -{ - __m128 num[3], mem[3]; - - int i; - - /* Copy numerator, denominator and memory to aligned xmm */ - for (i=0;i<2;i++) - { - mem[i] = _mm_loadu_ps(_mem+4*i); - num[i] = _mm_loadu_ps(_num+4*i); - } - mem[2] = _mm_setr_ps(_mem[8], _mem[9], 0, 0); - num[2] = _mm_setr_ps(_num[8], _num[9], 0, 0); - - for (i=0;i<N;i++) - { - __m128 xx; - __m128 yy; - /* Compute next filter result */ - xx = _mm_load_ps1(x+i); - yy = _mm_add_ss(xx, mem[0]); - _mm_store_ss(y+i, yy); - yy = _mm_shuffle_ps(yy, yy, 0); - - /* Update memory */ - mem[0] = _mm_move_ss(mem[0], mem[1]); - mem[0] = _mm_shuffle_ps(mem[0], mem[0], 0x39); - - mem[0] = _mm_add_ps(mem[0], _mm_mul_ps(xx, num[0])); - - mem[1] = _mm_move_ss(mem[1], mem[2]); - mem[1] = _mm_shuffle_ps(mem[1], mem[1], 0x39); - - mem[1] = _mm_add_ps(mem[1], _mm_mul_ps(xx, num[1])); - - mem[2] = _mm_shuffle_ps(mem[2], mem[2], 0xfd); - - mem[2] = _mm_add_ps(mem[2], _mm_mul_ps(xx, num[2])); - } - /* Put memory back in its place */ - _mm_storeu_ps(_mem, mem[0]); - _mm_storeu_ps(_mem+4, mem[1]); - _mm_store_ss(_mem+8, mem[2]); - mem[2] = _mm_shuffle_ps(mem[2], mem[2], 0x55); - _mm_store_ss(_mem+9, mem[2]); -} - -void fir_mem16_8(const float *x, const float *_num, float *y, int N, int ord, float *_mem) -{ - __m128 num[2], mem[2]; - - int i; - - /* Copy numerator, denominator and memory to aligned xmm */ - for (i=0;i<2;i++) - { - mem[i] = _mm_loadu_ps(_mem+4*i); - num[i] = _mm_loadu_ps(_num+4*i); - } - - for (i=0;i<N;i++) - { - __m128 xx; - __m128 yy; - /* Compute next filter result */ - xx = _mm_load_ps1(x+i); - yy = _mm_add_ss(xx, mem[0]); - _mm_store_ss(y+i, yy); - yy = _mm_shuffle_ps(yy, yy, 0); - - /* Update memory */ - mem[0] = _mm_move_ss(mem[0], mem[1]); - mem[0] = _mm_shuffle_ps(mem[0], mem[0], 0x39); - - mem[0] = _mm_add_ps(mem[0], _mm_mul_ps(xx, num[0])); - - mem[1] = _mm_sub_ss(mem[1], mem[1]); - mem[1] = _mm_shuffle_ps(mem[1], mem[1], 0x39); - - mem[1] = _mm_add_ps(mem[1], _mm_mul_ps(xx, num[1])); - } - /* Put memory back in its place */ - _mm_storeu_ps(_mem, mem[0]); - _mm_storeu_ps(_mem+4, mem[1]); -} - -#define OVERRIDE_FIR_MEM16 -void fir_mem16(const float *x, const float *_num, float *y, int N, int ord, float *_mem, char *stack) -{ - if(ord==10) - fir_mem16_10(x, _num, y, N, ord, _mem); - else if (ord==8) - fir_mem16_8(x, _num, y, N, ord, _mem); -} diff --git a/drivers/speex/fixed_arm4.h b/drivers/speex/fixed_arm4.h deleted file mode 100644 index b6981cae72..0000000000 --- a/drivers/speex/fixed_arm4.h +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright (C) 2004 Jean-Marc Valin */ -/** - @file fixed_arm4.h - @brief ARM4 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. - - - Neither the name of the Xiph.org Foundation nor the names of its - 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 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 FIXED_ARM4_H -#define FIXED_ARM4_H - -#undef MULT16_32_Q14 -static inline spx_word32_t MULT16_32_Q14(spx_word16_t x, spx_word32_t y) { - int res; - int dummy; - asm ( - "smull %0,%1,%2,%3 \n\t" - "mov %0, %0, lsr #14 \n\t" - "add %0, %0, %1, lsl #18 \n\t" - : "=&r"(res), "=&r" (dummy) - : "r"(y),"r"((int)x)); - return(res); -} - -#undef MULT16_32_Q15 -static inline spx_word32_t MULT16_32_Q15(spx_word16_t x, spx_word32_t y) { - int res; - int dummy; - asm ( - "smull %0,%1,%2,%3 \n\t" - "mov %0, %0, lsr #15 \n\t" - "add %0, %0, %1, lsl #17 \n\t" - : "=&r"(res), "=&r" (dummy) - : "r"(y),"r"((int)x)); - return(res); -} - -#undef DIV32_16 -static inline short DIV32_16(int a, int b) -{ - int res=0; - int dead1, dead2, dead3, dead4, dead5; - __asm__ __volatile__ ( - "\teor %5, %0, %1\n" - "\tmovs %4, %0\n" - "\trsbmi %0, %0, #0 \n" - "\tmovs %4, %1\n" - "\trsbmi %1, %1, #0 \n" - "\tmov %4, #1\n" - - "\tsubs %3, %0, %1, asl #14 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #14 \n" - - "\tsubs %3, %0, %1, asl #13 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #13 \n" - - "\tsubs %3, %0, %1, asl #12 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #12 \n" - - "\tsubs %3, %0, %1, asl #11 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #11 \n" - - "\tsubs %3, %0, %1, asl #10 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #10 \n" - - "\tsubs %3, %0, %1, asl #9 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #9 \n" - - "\tsubs %3, %0, %1, asl #8 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #8 \n" - - "\tsubs %3, %0, %1, asl #7 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #7 \n" - - "\tsubs %3, %0, %1, asl #6 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #6 \n" - - "\tsubs %3, %0, %1, asl #5 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #5 \n" - - "\tsubs %3, %0, %1, asl #4 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #4 \n" - - "\tsubs %3, %0, %1, asl #3 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #3 \n" - - "\tsubs %3, %0, %1, asl #2 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #2 \n" - - "\tsubs %3, %0, %1, asl #1 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #1 \n" - - "\tsubs %3, %0, %1 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4 \n" - - "\tmovs %5, %5, lsr #31 \n" - "\trsbne %2, %2, #0 \n" - : "=r" (dead1), "=r" (dead2), "=r" (res), - "=r" (dead3), "=r" (dead4), "=r" (dead5) - : "0" (a), "1" (b), "2" (res) - : "cc" - ); - return res; -} - - -#endif diff --git a/drivers/speex/fixed_arm5e.h b/drivers/speex/fixed_arm5e.h deleted file mode 100644 index 9b4861c9a7..0000000000 --- a/drivers/speex/fixed_arm5e.h +++ /dev/null @@ -1,178 +0,0 @@ -/* Copyright (C) 2003 Jean-Marc Valin */ -/** - @file fixed_arm5e.h - @brief ARM-tuned 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. - - - Neither the name of the Xiph.org Foundation nor the names of its - 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 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 FIXED_ARM5E_H -#define FIXED_ARM5E_H - -#undef MULT16_16 -static inline spx_word32_t MULT16_16(spx_word16_t x, spx_word16_t y) { - int res; - asm ("smulbb %0,%1,%2;\n" - : "=&r"(res) - : "%r"(x),"r"(y)); - return(res); -} - -#undef MAC16_16 -static inline spx_word32_t MAC16_16(spx_word32_t a, spx_word16_t x, spx_word32_t y) { - int res; - asm ("smlabb %0,%1,%2,%3;\n" - : "=&r"(res) - : "%r"(x),"r"(y),"r"(a)); - return(res); -} - -#undef MULT16_32_Q15 -static inline spx_word32_t MULT16_32_Q15(spx_word16_t x, spx_word32_t y) { - int res; - asm ("smulwb %0,%1,%2;\n" - : "=&r"(res) - : "%r"(y<<1),"r"(x)); - return(res); -} - -#undef MAC16_32_Q15 -static inline spx_word32_t MAC16_32_Q15(spx_word32_t a, spx_word16_t x, spx_word32_t y) { - int res; - asm ("smlawb %0,%1,%2,%3;\n" - : "=&r"(res) - : "%r"(y<<1),"r"(x),"r"(a)); - return(res); -} - -#undef MULT16_32_Q11 -static inline spx_word32_t MULT16_32_Q11(spx_word16_t x, spx_word32_t y) { - int res; - asm ("smulwb %0,%1,%2;\n" - : "=&r"(res) - : "%r"(y<<5),"r"(x)); - return(res); -} - -#undef MAC16_32_Q11 -static inline spx_word32_t MAC16_32_Q11(spx_word32_t a, spx_word16_t x, spx_word32_t y) { - int res; - asm ("smlawb %0,%1,%2,%3;\n" - : "=&r"(res) - : "%r"(y<<5),"r"(x),"r"(a)); - return(res); -} - -#undef DIV32_16 -static inline short DIV32_16(int a, int b) -{ - int res=0; - int dead1, dead2, dead3, dead4, dead5; - __asm__ __volatile__ ( - "\teor %5, %0, %1\n" - "\tmovs %4, %0\n" - "\trsbmi %0, %0, #0 \n" - "\tmovs %4, %1\n" - "\trsbmi %1, %1, #0 \n" - "\tmov %4, #1\n" - - "\tsubs %3, %0, %1, asl #14 \n" - "\torrpl %2, %2, %4, asl #14 \n" - "\tmovpl %0, %3 \n" - - "\tsubs %3, %0, %1, asl #13 \n" - "\torrpl %2, %2, %4, asl #13 \n" - "\tmovpl %0, %3 \n" - - "\tsubs %3, %0, %1, asl #12 \n" - "\torrpl %2, %2, %4, asl #12 \n" - "\tmovpl %0, %3 \n" - - "\tsubs %3, %0, %1, asl #11 \n" - "\torrpl %2, %2, %4, asl #11 \n" - "\tmovpl %0, %3 \n" - - "\tsubs %3, %0, %1, asl #10 \n" - "\torrpl %2, %2, %4, asl #10 \n" - "\tmovpl %0, %3 \n" - - "\tsubs %3, %0, %1, asl #9 \n" - "\torrpl %2, %2, %4, asl #9 \n" - "\tmovpl %0, %3 \n" - - "\tsubs %3, %0, %1, asl #8 \n" - "\torrpl %2, %2, %4, asl #8 \n" - "\tmovpl %0, %3 \n" - - "\tsubs %3, %0, %1, asl #7 \n" - "\torrpl %2, %2, %4, asl #7 \n" - "\tmovpl %0, %3 \n" - - "\tsubs %3, %0, %1, asl #6 \n" - "\torrpl %2, %2, %4, asl #6 \n" - "\tmovpl %0, %3 \n" - - "\tsubs %3, %0, %1, asl #5 \n" - "\torrpl %2, %2, %4, asl #5 \n" - "\tmovpl %0, %3 \n" - - "\tsubs %3, %0, %1, asl #4 \n" - "\torrpl %2, %2, %4, asl #4 \n" - "\tmovpl %0, %3 \n" - - "\tsubs %3, %0, %1, asl #3 \n" - "\torrpl %2, %2, %4, asl #3 \n" - "\tmovpl %0, %3 \n" - - "\tsubs %3, %0, %1, asl #2 \n" - "\torrpl %2, %2, %4, asl #2 \n" - "\tmovpl %0, %3 \n" - - "\tsubs %3, %0, %1, asl #1 \n" - "\torrpl %2, %2, %4, asl #1 \n" - "\tmovpl %0, %3 \n" - - "\tsubs %3, %0, %1 \n" - "\torrpl %2, %2, %4 \n" - "\tmovpl %0, %3 \n" - - "\tmovs %5, %5, lsr #31 \n" - "\trsbne %2, %2, #0 \n" - : "=r" (dead1), "=r" (dead2), "=r" (res), - "=r" (dead3), "=r" (dead4), "=r" (dead5) - : "0" (a), "1" (b), "2" (res) - : "memory", "cc" - ); - return res; -} - - - - -#endif diff --git a/drivers/speex/fixed_bfin.h b/drivers/speex/fixed_bfin.h deleted file mode 100644 index aa26f6a87d..0000000000 --- a/drivers/speex/fixed_bfin.h +++ /dev/null @@ -1,173 +0,0 @@ -/* Copyright (C) 2005 Analog Devices - Author: Jean-Marc Valin */ -/** - @file fixed_bfin.h - @brief Blackfin 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. - - - Neither the name of the Xiph.org Foundation nor the names of its - 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 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 FIXED_BFIN_H -#define FIXED_BFIN_H - -#undef PDIV32_16 -static inline spx_word16_t PDIV32_16(spx_word32_t a, spx_word16_t b) -{ - spx_word32_t res, bb; - bb = b; - a += b>>1; - __asm__ ( - "P0 = 15;\n\t" - "R0 = %1;\n\t" - "R1 = %2;\n\t" - //"R0 = R0 + R1;\n\t" - "R0 <<= 1;\n\t" - "DIVS (R0, R1);\n\t" - "LOOP divide%= LC0 = P0;\n\t" - "LOOP_BEGIN divide%=;\n\t" - "DIVQ (R0, R1);\n\t" - "LOOP_END divide%=;\n\t" - "R0 = R0.L;\n\t" - "%0 = R0;\n\t" - : "=m" (res) - : "m" (a), "m" (bb) - : "P0", "R0", "R1", "cc"); - return res; -} - -#undef DIV32_16 -static inline spx_word16_t DIV32_16(spx_word32_t a, spx_word16_t b) -{ - spx_word32_t res, bb; - bb = b; - /* Make the roundinf consistent with the C version - (do we need to do that?)*/ - if (a<0) - a += (b-1); - __asm__ ( - "P0 = 15;\n\t" - "R0 = %1;\n\t" - "R1 = %2;\n\t" - "R0 <<= 1;\n\t" - "DIVS (R0, R1);\n\t" - "LOOP divide%= LC0 = P0;\n\t" - "LOOP_BEGIN divide%=;\n\t" - "DIVQ (R0, R1);\n\t" - "LOOP_END divide%=;\n\t" - "R0 = R0.L;\n\t" - "%0 = R0;\n\t" - : "=m" (res) - : "m" (a), "m" (bb) - : "P0", "R0", "R1", "cc"); - return res; -} - -#undef MAX16 -static inline spx_word16_t MAX16(spx_word16_t a, spx_word16_t b) -{ - spx_word32_t res; - __asm__ ( - "%1 = %1.L (X);\n\t" - "%2 = %2.L (X);\n\t" - "%0 = MAX(%1,%2);" - : "=d" (res) - : "%d" (a), "d" (b) - ); - return res; -} - -#undef MULT16_32_Q15 -static inline spx_word32_t MULT16_32_Q15(spx_word16_t a, spx_word32_t b) -{ - spx_word32_t res; - __asm__ - ( - "A1 = %2.L*%1.L (M);\n\t" - "A1 = A1 >>> 15;\n\t" - "%0 = (A1 += %2.L*%1.H) ;\n\t" - : "=&W" (res), "=&d" (b) - : "d" (a), "1" (b) - : "A1" - ); - return res; -} - -#undef MAC16_32_Q15 -static inline spx_word32_t MAC16_32_Q15(spx_word32_t c, spx_word16_t a, spx_word32_t b) -{ - spx_word32_t res; - __asm__ - ( - "A1 = %2.L*%1.L (M);\n\t" - "A1 = A1 >>> 15;\n\t" - "%0 = (A1 += %2.L*%1.H);\n\t" - "%0 = %0 + %4;\n\t" - : "=&W" (res), "=&d" (b) - : "d" (a), "1" (b), "d" (c) - : "A1" - ); - return res; -} - -#undef MULT16_32_Q14 -static inline spx_word32_t MULT16_32_Q14(spx_word16_t a, spx_word32_t b) -{ - spx_word32_t res; - __asm__ - ( - "%2 <<= 1;\n\t" - "A1 = %1.L*%2.L (M);\n\t" - "A1 = A1 >>> 15;\n\t" - "%0 = (A1 += %1.L*%2.H);\n\t" - : "=W" (res), "=d" (a), "=d" (b) - : "1" (a), "2" (b) - : "A1" - ); - return res; -} - -#undef MAC16_32_Q14 -static inline spx_word32_t MAC16_32_Q14(spx_word32_t c, spx_word16_t a, spx_word32_t b) -{ - spx_word32_t res; - __asm__ - ( - "%1 <<= 1;\n\t" - "A1 = %2.L*%1.L (M);\n\t" - "A1 = A1 >>> 15;\n\t" - "%0 = (A1 += %2.L*%1.H);\n\t" - "%0 = %0 + %4;\n\t" - : "=&W" (res), "=&d" (b) - : "d" (a), "1" (b), "d" (c) - : "A1" - ); - return res; -} - -#endif diff --git a/drivers/speex/fixed_debug.h b/drivers/speex/fixed_debug.h deleted file mode 100644 index 54f3866e8f..0000000000 --- a/drivers/speex/fixed_debug.h +++ /dev/null @@ -1,487 +0,0 @@ -/* Copyright (C) 2003 Jean-Marc Valin */ -/** - @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. - - - Neither the name of the Xiph.org Foundation nor the names of its - 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 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 FIXED_DEBUG_H -#define FIXED_DEBUG_H - -#include <stdio.h> - -extern long long spx_mips; -#define MIPS_INC spx_mips++, - -#define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) -#define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) - - -#define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768) -#define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL) - -static inline short NEG16(int x) -{ - int res; - if (!VERIFY_SHORT(x)) - { - fprintf (stderr, "NEG16: input is not short: %d\n", (int)x); - } - res = -x; - if (!VERIFY_SHORT(res)) - fprintf (stderr, "NEG16: output is not short: %d\n", (int)res); - spx_mips++; - return res; -} -static inline int NEG32(long long x) -{ - long long res; - if (!VERIFY_INT(x)) - { - fprintf (stderr, "NEG16: input is not int: %d\n", (int)x); - } - res = -x; - if (!VERIFY_INT(res)) - fprintf (stderr, "NEG16: output is not int: %d\n", (int)res); - spx_mips++; - return res; -} - -#define EXTRACT16(x) _EXTRACT16(x, __FILE__, __LINE__) -static 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); - } - res = x; - spx_mips++; - return res; -} - -#define EXTEND32(x) _EXTEND32(x, __FILE__, __LINE__) -static 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); - } - res = x; - spx_mips++; - return res; -} - -#define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__) -static 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); - } - res = a>>shift; - if (!VERIFY_SHORT(res)) - fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line); - spx_mips++; - return res; -} -#define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__) -static inline short _SHL16(int a, int shift, char *file, int line) -{ - int 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); - } - res = a<<shift; - if (!VERIFY_SHORT(res)) - fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, file, line); - spx_mips++; - return res; -} - -static inline int SHR32(long long a, int shift) -{ - long long res; - if (!VERIFY_INT(a) || !VERIFY_SHORT(shift)) - { - fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift); - } - res = a>>shift; - if (!VERIFY_INT(res)) - { - fprintf (stderr, "SHR32: output is not int: %d\n", (int)res); - } - spx_mips++; - return res; -} -static inline int SHL32(long long a, int shift) -{ - long long res; - if (!VERIFY_INT(a) || !VERIFY_SHORT(shift)) - { - fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int)a, shift); - } - res = a<<shift; - if (!VERIFY_INT(res)) - { - fprintf (stderr, "SHL32: output is not int: %d\n", (int)res); - } - spx_mips++; - return res; -} - -#define PSHR16(a,shift) (SHR16(ADD16((a),((1<<((shift))>>1))),shift)) -#define PSHR32(a,shift) (SHR32(ADD32((a),((EXTEND32(1)<<((shift))>>1))),shift)) -#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) - -#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) -#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) - -//#define SHR(a,shift) ((a) >> (shift)) -//#define SHL(a,shift) ((a) << (shift)) - -#define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__) -static 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); - } - 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); - } - spx_mips++; - return res; -} - -#define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__) -static 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); - } - res = a-b; - if (!VERIFY_SHORT(res)) - fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line); - spx_mips++; - return res; -} - -#define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__) -static inline int _ADD32(long long a, long long b, char *file, int line) -{ - long long 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); - } - res = a+b; - if (!VERIFY_INT(res)) - { - fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line); - } - spx_mips++; - return res; -} - -static inline int SUB32(long long a, long long b) -{ - long long res; - if (!VERIFY_INT(a) || !VERIFY_INT(b)) - { - fprintf (stderr, "SUB32: inputs are not int: %d %d\n", (int)a, (int)b); - } - res = a-b; - if (!VERIFY_INT(res)) - fprintf (stderr, "SUB32: output is not int: %d\n", (int)res); - spx_mips++; - return res; -} - -#define ADD64(a,b) (MIPS_INC(a)+(b)) - -/* result fits in 16 bits */ -static 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); - } - res = a*b; - if (!VERIFY_SHORT(res)) - fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res); - spx_mips++; - return res; -} - -#define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__) -static inline int _MULT16_16(int a, int b, char *file, int line) -{ - long long 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); - } - res = ((long long)a)*b; - if (!VERIFY_INT(res)) - fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line); - spx_mips++; - return res; -} - -#define MAC16_16(c,a,b) (spx_mips--,ADD32((c),MULT16_16((a),(b)))) -#define MAC16_16_Q11(c,a,b) (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11))))) -#define MAC16_16_Q13(c,a,b) (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13))))) -#define MAC16_16_P13(c,a,b) (EXTRACT16(ADD32((c),SHR32(ADD32(4096,MULT16_16((a),(b))),13)))) - - -#define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__) -static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line) -{ - long long 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); - } - if (ABS32(b)>=(EXTEND32(1)<<(15+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); - res = (((long long)a)*(long long)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); - spx_mips+=5; - return res; -} - -static inline int MULT16_32_PX(int a, long long b, int Q) -{ - long long res; - if (!VERIFY_SHORT(a) || !VERIFY_INT(b)) - { - fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b); - } - if (ABS32(b)>=(EXTEND32(1)<<(15+Q))) - fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b); - res = ((((long long)a)*(long long)b) + ((EXTEND32(1)<<Q)>>1))>> Q; - if (!VERIFY_INT(res)) - fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res); - spx_mips+=5; - return res; -} - - -#define MULT16_32_Q11(a,b) MULT16_32_QX(a,b,11) -#define MAC16_32_Q11(c,a,b) ADD32((c),MULT16_32_Q11((a),(b))) -#define MULT16_32_Q12(a,b) MULT16_32_QX(a,b,12) -#define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13) -#define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14) -#define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15) -#define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15) -#define MAC16_32_Q15(c,a,b) ADD32((c),MULT16_32_Q15((a),(b))) - -static inline int SATURATE(int a, int b) -{ - if (a>b) - a=b; - if (a<-b) - a = -b; - return a; -} - -static inline int MULT16_16_Q11_32(int a, int b) -{ - long long res; - if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) - { - fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b); - } - res = ((long long)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); - spx_mips+=3; - return res; -} -static inline short MULT16_16_Q13(int a, int b) -{ - long long res; - if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) - { - fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b); - } - res = ((long long)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); - spx_mips+=3; - return res; -} -static inline short MULT16_16_Q14(int a, int b) -{ - long long res; - if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) - { - fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b); - } - res = ((long long)a)*b; - res >>= 14; - if (!VERIFY_SHORT(res)) - fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res); - spx_mips+=3; - return res; -} -static inline short MULT16_16_Q15(int a, int b) -{ - long long res; - if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) - { - fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d\n", a, b); - } - res = ((long long)a)*b; - res >>= 15; - if (!VERIFY_SHORT(res)) - { - fprintf (stderr, "MULT16_16_Q15: output is not short: %d\n", (int)res); - } - spx_mips+=3; - return res; -} - -static inline short MULT16_16_P13(int a, int b) -{ - long long res; - if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) - { - fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b); - } - res = ((long long)a)*b; - res += 4096; - if (!VERIFY_INT(res)) - fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res); - res >>= 13; - if (!VERIFY_SHORT(res)) - fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res); - spx_mips+=4; - return res; -} -static inline short MULT16_16_P14(int a, int b) -{ - long long res; - if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) - { - fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b); - } - res = ((long long)a)*b; - res += 8192; - if (!VERIFY_INT(res)) - fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res); - res >>= 14; - if (!VERIFY_SHORT(res)) - fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res); - spx_mips+=4; - return res; -} -static inline short MULT16_16_P15(int a, int b) -{ - long long res; - if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) - { - fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b); - } - res = ((long long)a)*b; - res += 16384; - if (!VERIFY_INT(res)) - fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res); - res >>= 15; - if (!VERIFY_SHORT(res)) - fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res); - spx_mips+=4; - return res; -} - -#define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__) - -static inline int _DIV32_16(long long a, long long b, char *file, int line) -{ - long long res; - if (b==0) - { - fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line); - 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); - } - 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; - } - spx_mips+=20; - return res; -} - -#define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__) -static inline int _DIV32(long long a, long long b, char *file, int line) -{ - long long res; - if (b==0) - { - fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line); - 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); - } - res = a/b; - if (!VERIFY_INT(res)) - fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line); - spx_mips+=36; - return res; -} -#define PDIV32(a,b) DIV32(ADD32((a),(b)>>1),b) -#define PDIV32_16(a,b) DIV32_16(ADD32((a),(b)>>1),b) - -#endif diff --git a/drivers/speex/fixed_generic.h b/drivers/speex/fixed_generic.h deleted file mode 100644 index 3fb096ed90..0000000000 --- a/drivers/speex/fixed_generic.h +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2003 Jean-Marc Valin */ -/** - @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. - - - Neither the name of the Xiph.org Foundation nor the names of its - 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 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 FIXED_GENERIC_H -#define FIXED_GENERIC_H - -#define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) -#define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) - -#define NEG16(x) (-(x)) -#define NEG32(x) (-(x)) -#define EXTRACT16(x) ((spx_word16_t)(x)) -#define EXTEND32(x) ((spx_word32_t)(x)) -#define SHR16(a,shift) ((a) >> (shift)) -#define SHL16(a,shift) ((a) << (shift)) -#define SHR32(a,shift) ((a) >> (shift)) -#define SHL32(a,shift) ((a) << (shift)) -#define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift)) -#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift)) -#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) -#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) -#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) - -#define SHR(a,shift) ((a) >> (shift)) -#define SHL(a,shift) ((spx_word32_t)(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 ADD16(a,b) ((spx_word16_t)((spx_word16_t)(a)+(spx_word16_t)(b))) -#define SUB16(a,b) ((spx_word16_t)(a)-(spx_word16_t)(b)) -#define ADD32(a,b) ((spx_word32_t)(a)+(spx_word32_t)(b)) -#define SUB32(a,b) ((spx_word32_t)(a)-(spx_word32_t)(b)) - - -/* result fits in 16 bits */ -#define MULT16_16_16(a,b) ((((spx_word16_t)(a))*((spx_word16_t)(b)))) - -/* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */ -#define MULT16_16(a,b) (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b))) - -#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b)))) -#define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12)) -#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13)) -#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14)) - -#define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11)) -#define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))) - -#define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15)) -#define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)) -#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))) - - -#define MAC16_16_Q11(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),11))) -#define MAC16_16_Q13(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),13))) -#define MAC16_16_P13(c,a,b) (ADD32((c),SHR(ADD32(4096,MULT16_16((a),(b))),13))) - -#define MULT16_16_Q11_32(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)) - -#define MUL_16_32_R15(a,bh,bl) ADD32(MULT16_16((a),(bh)), SHR(MULT16_16((a),(bl)),15)) - -#define DIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a))/((spx_word16_t)(b)))) -#define PDIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word16_t)(b)))) -#define DIV32(a,b) (((spx_word32_t)(a))/((spx_word32_t)(b))) -#define PDIV32(a,b) (((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word32_t)(b))) - -#endif diff --git a/drivers/speex/gain_table.c b/drivers/speex/gain_table.c deleted file mode 100644 index 00b8244259..0000000000 --- a/drivers/speex/gain_table.c +++ /dev/null @@ -1,160 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: gain_table.c - Codebook for 3-tap pitch prediction gain (128 entries) - - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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. -*/ - -const signed char gain_cdbk_nb[512] = { --32, -32, -32, 0, --28, -67, -5, 33, --42, -6, -32, 18, --57, -10, -54, 35, --16, 27, -41, 42, -19, -19, -40, 36, --45, 24, -21, 40, --8, -14, -18, 28, -1, 14, -58, 53, --18, -88, -39, 39, --38, 21, -18, 37, --19, 20, -43, 38, -10, 17, -48, 54, --52, -58, -13, 33, --44, -1, -11, 32, --12, -11, -34, 22, -14, 0, -46, 46, --37, -35, -34, 5, --25, 44, -30, 43, -6, -4, -63, 49, --31, 43, -41, 43, --23, 30, -43, 41, --43, 26, -14, 44, --33, 1, -13, 27, --13, 18, -37, 37, --46, -73, -45, 34, --36, 24, -25, 34, --36, -11, -20, 19, --25, 12, -18, 33, --36, -69, -59, 34, --45, 6, 8, 46, --22, -14, -24, 18, --1, 13, -44, 44, --39, -48, -26, 15, --32, 31, -37, 34, --33, 15, -46, 31, --24, 30, -36, 37, --41, 31, -23, 41, --50, 22, -4, 50, --22, 2, -21, 28, --17, 30, -34, 40, --7, -60, -28, 29, --38, 42, -28, 42, --44, -11, 21, 43, --16, 8, -44, 34, --39, -55, -43, 21, --11, -35, 26, 41, --9, 0, -34, 29, --8, 121, -81, 113, -7, -16, -22, 33, --37, 33, -31, 36, --27, -7, -36, 17, --34, 70, -57, 65, --37, -11, -48, 21, --40, 17, -1, 44, --33, 6, -6, 33, --9, 0, -20, 34, --21, 69, -33, 57, --29, 33, -31, 35, --55, 12, -1, 49, --33, 27, -22, 35, --50, -33, -47, 17, --50, 54, 51, 94, --1, -5, -44, 35, --4, 22, -40, 45, --39, -66, -25, 24, --33, 1, -26, 20, --24, -23, -25, 12, --11, 21, -45, 44, --25, -45, -19, 17, --43, 105, -16, 82, -5, -21, 1, 41, --16, 11, -33, 30, --13, -99, -4, 57, --37, 33, -15, 44, --25, 37, -63, 54, --36, 24, -31, 31, --53, -56, -38, 26, --41, -4, 4, 37, --33, 13, -30, 24, -49, 52, -94, 114, --5, -30, -15, 23, -1, 38, -40, 56, --23, 12, -36, 29, --17, 40, -47, 51, --37, -41, -39, 11, --49, 34, 0, 58, --18, -7, -4, 34, --16, 17, -27, 35, -30, 5, -62, 65, -4, 48, -68, 76, --43, 11, -11, 38, --18, 19, -15, 41, --23, -62, -39, 23, --42, 10, -2, 41, --21, -13, -13, 25, --9, 13, -47, 42, --23, -62, -24, 24, --44, 60, -21, 58, --18, -3, -52, 32, --22, 22, -36, 34, --75, 57, 16, 90, --19, 3, 10, 45, --29, 23, -38, 32, --5, -62, -51, 38, --51, 40, -18, 53, --42, 13, -24, 32, --34, 14, -20, 30, --56, -75, -26, 37, --26, 32, 15, 59, --26, 17, -29, 29, --7, 28, -52, 53, --12, -30, 5, 30, --5, -48, -5, 35, -2, 2, -43, 40, -21, 16, 16, 75, --25, -45, -32, 10, --43, 18, -10, 42, -9, 0, -1, 52, --1, 7, -30, 36, -19, -48, -4, 48, --28, 25, -29, 32, --22, 0, -31, 22, --32, 17, -10, 36, --64, -41, -62, 36, --52, 15, 16, 58, --30, -22, -32, 6, --7, 9, -38, 36}; diff --git a/drivers/speex/gain_table_lbr.c b/drivers/speex/gain_table_lbr.c deleted file mode 100644 index 3c1c3dba99..0000000000 --- a/drivers/speex/gain_table_lbr.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: gain_table_lbr.c - Codebook for 3-tap pitch prediction gain (32 entries) - - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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. -*/ - -const signed char gain_cdbk_lbr[128] = { --32, -32, -32, 0, --31, -58, -16, 22, --41, -24, -43, 14, --56, -22, -55, 29, --13, 33, -41, 47, --4, -39, -9, 29, --41, 15, -12, 38, --8, -15, -12, 31, -1, 2, -44, 40, --22, -66, -42, 27, --38, 28, -23, 38, --21, 14, -37, 31, -0, 21, -50, 52, --53, -71, -27, 33, --37, -1, -19, 25, --19, -5, -28, 22, -6, 65, -44, 74, --33, -48, -33, 9, --40, 57, -14, 58, --17, 4, -45, 32, --31, 38, -33, 36, --23, 28, -40, 39, --43, 29, -12, 46, --34, 13, -23, 28, --16, 15, -27, 34, --14, -82, -15, 43, --31, 25, -32, 29, --21, 5, -5, 38, --47, -63, -51, 33, --46, 12, 3, 47, --28, -17, -29, 11, --10, 14, -40, 38}; diff --git a/drivers/speex/hexc_10_32_table.c b/drivers/speex/hexc_10_32_table.c deleted file mode 100644 index 8dd408f2c3..0000000000 --- a/drivers/speex/hexc_10_32_table.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: hexc_10_32_table.c - Codebook for high-band excitation in SB-CELP mode (4000 bps) - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -const signed char hexc_10_32_table[320] = { --3, -2, -1, 0, -4, 5, 35, -40, -9, 13, --44, 5, -27, -1, -7, 6, -11, 7, -8, 7, -19, -14, 15, -4, 9, -10, 10, -8, 10, -9, --1, 1, 0, 0, 2, 5, -18, 22, -53, 50, -1, -23, 50, -36, 15, 3, -13, 14, -10, 6, -1, 5, -3, 4, -2, 5, -32, 25, 5, -2, --1, -4, 1, 11, -29, 26, -6, -15, 30, -18, -0, 15, -17, 40, -41, 3, 9, -2, -2, 3, --3, -1, -5, 2, 21, -6, -16, -21, 23, 2, -60, 15, 16, -16, -9, 14, 9, -1, 7, -9, -0, 1, 1, 0, -1, -6, 17, -28, 54, -45, --1, 1, -1, -6, -6, 2, 11, 26, -29, -2, -46, -21, 34, 12, -23, 32, -23, 16, -10, 3, -66, 19, -20, 24, 7, 11, -3, 0, -3, -1, --50, -46, 2, -18, -3, 4, -1, -2, 3, -3, --19, 41, -36, 9, 11, -24, 21, -16, 9, -3, --25, -3, 10, 18, -9, -2, -5, -1, -5, 6, --4, -3, 2, -26, 21, -19, 35, -15, 7, -13, -17, -19, 39, -43, 48, -31, 16, -9, 7, -2, --5, 3, -4, 9, -19, 27, -55, 63, -35, 10, -26, -44, -2, 9, 4, 1, -6, 8, -9, 5, --8, -1, -3, -16, 45, -42, 5, 15, -16, 10, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, --16, 24, -55, 47, -38, 27, -19, 7, -3, 1, -16, 27, 20, -19, 18, 5, -7, 1, -5, 2, --6, 8, -22, 0, -3, -3, 8, -1, 7, -8, -1, -3, 5, 0, 17, -48, 58, -52, 29, -7, --2, 3, -10, 6, -26, 58, -31, 1, -6, 3, -93, -29, 39, 3, 17, 5, 6, -1, -1, -1, -27, 13, 10, 19, -7, -34, 12, 10, -4, 9, --76, 9, 8, -28, -2, -11, 2, -1, 3, 1, --83, 38, -39, 4, -16, -6, -2, -5, 5, -2, -}; diff --git a/drivers/speex/hexc_table.c b/drivers/speex/hexc_table.c deleted file mode 100644 index 268408a8d4..0000000000 --- a/drivers/speex/hexc_table.c +++ /dev/null @@ -1,162 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: hexc_table.c - Codebook for high-band excitation in SB-CELP mode (8000 bps with sign) - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -const signed char hexc_table[1024] = { --24, 21, -20, 5, -5, -7, 14, -10, -2, -27, 16, -20, 0, -32, 26, 19, -8, -11, -41, 31, 28, -27, -32, 34, -42, 34, -17, 22, -10, 13, -29, 18, --12, -26, -24, 11, 22, 5, -5, -5, -54, -68, -43, 57, -25, 24, 4, 4, -26, -8, -12, -17, 54, 30, -45, 1, -10, -15, 18, -41, 11, 68, -67, 37, --16, -24, -16, 38, -22, 6, -29, 30, -66, -27, 5, 7, -16, 13, 2, -12, --7, -3, -20, 36, 4, -28, 9, 3, -32, 48, 26, 39, 3, 0, 7, -21, --13, 5, -82, -7, 73, -20, 34, -9, --5, 1, -1, 10, -5, -10, -1, 9, -1, -9, 10, 0, -14, 11, -1, -2, --1, 11, 20, 96, -81, -22, -12, -9, --58, 9, 24, -30, 26, -35, 27, -12, -13, -18, 56, -59, 15, -7, 23, -15, --1, 6, -25, 14, -22, -20, 47, -11, -16, 2, 38, -23, -19, -30, -9, 40, --11, 5, 4, -6, 8, 26, -21, -11, -127, 4, 1, 6, -9, 2, -7, -2, --3, 7, -5, 10, -19, 7, -106, 91, --3, 9, -4, 21, -8, 26, -80, 8, -1, -2, -10, -17, -17, -27, 32, 71, -6, -29, 11, -23, 54, -38, 29, -22, -39, 87, -31, -12, -20, 3, -2, -2, -2, 20, 0, -1, -35, 27, 9, -6, --12, 3, -12, -6, 13, 1, 14, -22, --59, -15, -17, -25, 13, -7, 7, 3, -0, 1, -7, 6, -3, 61, -37, -23, --23, -29, 38, -31, 27, 1, -8, 2, --27, 23, -26, 36, -34, 5, 24, -24, --6, 7, 3, -59, 78, -62, 44, -16, -1, 6, 0, 17, 8, 45, 0, -110, -6, 14, -2, 32, -77, -56, 62, -3, -3, -13, 4, -16, 102, -15, -36, -1, -9, -113, 6, 23, 0, 9, 9, 5, --8, -1, -14, 5, -12, 121, -53, -27, --8, -9, 22, -13, 3, 2, -3, 1, --2, -71, 95, 38, -19, 15, -16, -5, -71, 10, 2, -32, -13, -5, 15, -1, --2, -14, -85, 30, 29, 6, 3, 2, -0, 0, 0, 0, 0, 0, 0, 0, -2, -65, -56, -9, 18, 18, 23, -14, --2, 0, 12, -29, 26, -12, 1, 2, --12, -64, 90, -6, 4, 1, 5, -5, --110, -3, -31, 22, -29, 9, 0, 8, --40, -5, 21, -5, -5, 13, 10, -18, -40, 1, 35, -20, 30, -28, 11, -6, -19, 7, 14, 18, -64, 9, -6, 16, -51, 68, 8, 16, 12, -8, 0, -9, -20, -22, 25, 7, -4, -13, 41, -35, -93, -18, -54, 11, -1, 1, -9, 4, --66, 66, -31, 20, -22, 25, -23, 11, -10, 9, 19, 15, 11, -5, -31, -10, --23, -28, -6, -6, -3, -4, 5, 3, --28, 22, -11, -42, 25, -25, -16, 41, -34, 47, -6, 2, 42, -19, -22, 5, --39, 32, 6, -35, 22, 17, -30, 8, --26, -11, -11, 3, -12, 33, 33, -37, -21, -1, 6, -4, 3, 0, -5, 5, -12, -12, 57, 27, -61, -3, 20, -17, -2, 0, 4, 0, -2, -33, -58, 81, --23, 39, -10, -5, 2, 6, -7, 5, -4, -3, -2, -13, -23, -72, 107, 15, --5, 0, -7, -3, -6, 5, -4, 15, -47, 12, -31, 25, -16, 8, 22, -25, --62, -56, -18, 14, 28, 12, 2, -11, -74, -66, 41, -20, -7, 16, -20, 16, --8, 0, -16, 4, -19, 92, 12, -59, --14, -39, 49, -25, -16, 23, -27, 19, --3, -33, 19, 85, -29, 6, -7, -10, -16, -7, -12, 1, -6, 2, 4, -2, -64, 10, -25, 41, -2, -31, 15, 0, -110, 50, 69, 35, 28, 19, -10, 2, --43, -49, -56, -15, -16, 10, 3, 12, --1, -8, 1, 26, -12, -1, 7, -11, --27, 41, 25, 1, -11, -18, 22, -7, --1, -47, -8, 23, -3, -17, -7, 18, --125, 59, -5, 3, 18, 1, 2, 3, -27, -35, 65, -53, 50, -46, 37, -21, --28, 7, 14, -37, -5, -5, 12, 5, --8, 78, -19, 21, -6, -16, 8, -7, -5, 2, 7, 2, 10, -6, 12, -60, -44, 11, -36, -32, 31, 0, 2, -2, -2, 1, -3, 7, -10, 17, -21, 10, -6, -2, 19, -2, 59, -38, -86, 38, -8, -41, -30, -45, -33, 7, 15, 28, -29, -7, 24, -40, 7, 7, 5, -2, -9, 24, -23, -18, 6, -29, 30, 2, -28, 49, -11, -46, 10, 43, -13, -9, --1, -3, -7, -7, -17, -6, 97, -33, --21, 3, 5, 1, 12, -43, -8, 28, -7, -43, -7, 17, -20, 19, -1, 2, --13, 9, 54, 34, 9, -28, -11, -9, --17, 110, -59, 44, -26, 0, 3, -12, --47, 73, -34, -43, 38, -33, 16, -5, --46, -4, -6, -2, -25, 19, -29, 28, --13, 5, 14, 27, -40, -43, 4, 32, --13, -2, -35, -4, 112, -42, 9, -12, -37, -28, 17, 14, -19, 35, -39, 23, -3, -14, -1, -57, -5, 94, -9, 3, --39, 5, 30, -10, -32, 42, -13, -14, --97, -63, 30, -9, 1, -7, 12, 5, -20, 17, -9, -36, -30, 25, 47, -9, --15, 12, -22, 98, -8, -50, 15, -27, -21, -16, -11, 2, 12, -10, 10, -3, -33, 36, -96, 0, -17, 31, -9, 9, -3, -20, 13, -11, 8, -4, 10, -10, -9, 1, 112, -70, -27, 5, -21, 2, --57, -3, -29, 10, 19, -21, 21, -10, --66, -3, 91, -35, 30, -12, 0, -7, -59, -28, 26, 2, 14, -18, 1, 1, -11, 17, 20, -54, -59, 27, 4, 29, -32, 5, 19, 12, -4, 1, 7, -10, -5, -2, 10, 0, 23, -5, 28, -104, -46, 11, 16, 3, 29, 1, -8, -14, -1, 7, -50, 88, -62, 26, 8, -17, --14, 50, 0, 32, -12, -3, -27, 18, --8, -5, 8, 3, -20, -11, 37, -12, -9, 33, 46, -101, -1, -4, 1, 6, --1, 28, -42, -15, 16, 5, -1, -2, --55, 85, 38, -9, -4, 11, -2, -9, --6, 3, -20, -10, -77, 89, 24, -3, --104, -57, -26, -31, -20, -6, -9, 14, -20, -23, 46, -15, -31, 28, 1, -15, --2, 6, -2, 31, 45, -76, 23, -25, -}; diff --git a/drivers/speex/high_lsp_tables.c b/drivers/speex/high_lsp_tables.c deleted file mode 100644 index e82e87550d..0000000000 --- a/drivers/speex/high_lsp_tables.c +++ /dev/null @@ -1,163 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: high_lsp_tables.c - Codebooks for high-band LSPs in SB-CELP mode - - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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. -*/ - -const signed char high_lsp_cdbk[512]={ -39,12,-14,-20,-29,-61,-67,-76, --32,-71,-67,68,77,46,34,5, --13,-48,-46,-72,-81,-84,-60,-58, --40,-28,82,93,68,45,29,3, --19,-47,-28,-43,-35,-30,-8,-13, --39,-91,-91,-123,-96,10,10,-6, --18,-55,-60,-91,-56,-36,-27,-16, --48,-75,40,28,-10,-28,35,9, -37,19,1,-20,-31,-41,-18,-25, --35,-68,-80,45,27,-1,47,13, -0,-29,-35,-57,-50,-79,-73,-38, --19,5,35,14,-10,-23,16,-8, -5,-24,-40,-62,-23,-27,-22,-16, --18,-46,-72,-77,43,21,33,1, --80,-70,-70,-64,-56,-52,-39,-33, --31,-38,-19,-19,-15,32,33,-2, -7,-15,-15,-24,-23,-33,-41,-56, --24,-57,5,89,64,41,27,5, --9,-47,-60,-97,-97,-124,-20,-9, --44,-73,31,29,-4,64,48,7, --35,-57,0,-3,-26,-47,-3,-6, --40,-76,-79,-48,12,81,55,10, -9,-24,-43,-73,-57,-69,16,5, --28,-53,18,29,20,0,-4,-11, -6,-13,23,7,-17,-35,-37,-37, --30,-68,-63,6,24,-9,-14,3, -21,-13,-27,-57,-49,-80,-24,-41, --5,-16,-5,1,45,25,12,-7, -3,-15,-6,-16,-15,-8,6,-13, --42,-81,-80,-87,14,1,-10,-3, --43,-69,-46,-24,-28,-29,36,6, --43,-56,-12,12,54,79,43,9, -54,22,2,8,-12,-43,-46,-52, --38,-69,-89,-5,75,38,33,5, --13,-53,-62,-87,-89,-113,-99,-55, --34,-37,62,55,33,16,21,-2, --17,-46,-29,-38,-38,-48,-39,-42, --36,-75,-72,-88,-48,-30,21,2, --15,-57,-64,-98,-84,-76,25,1, --46,-80,-12,18,-7,3,34,6, -38,31,23,4,-1,20,14,-15, --43,-78,-91,-24,14,-3,54,16, -0,-27,-28,-44,-56,-83,-92,-89, --3,34,56,41,36,22,20,-8, --7,-35,-42,-62,-49,3,12,-10, --50,-87,-96,-66,92,70,38,9, --70,-71,-62,-42,-39,-43,-11,-7, --50,-79,-58,-50,-31,32,31,-6, --4,-25,7,-17,-38,-70,-58,-27, --43,-83,-28,59,36,20,31,2, --27,-71,-80,-109,-98,-75,-33,-32, --31,-2,33,15,-6,43,33,-5, -0,-22,-10,-27,-34,-49,-11,-20, --41,-91,-100,-121,-39,57,41,10, --19,-50,-38,-59,-60,-70,-18,-20, --8,-31,-8,-15,1,-14,-26,-25, -33,21,32,17,1,-19,-19,-26, --58,-81,-35,-22,45,30,11,-11, -3,-26,-48,-87,-67,-83,-58,3, --1,-26,-20,44,10,25,39,5, --9,-35,-27,-38,7,10,4,-9, --42,-85,-102,-127,52,44,28,10, --47,-61,-40,-39,-17,-1,-10,-33, --42,-74,-48,21,-4,70,52,10}; - - -const signed char high_lsp_cdbk2[512]={ --36,-62,6,-9,-10,-14,-56,23, -1,-26,23,-48,-17,12,8,-7, -23,29,-36,-28,-6,-29,-17,-5, -40,23,10,10,-46,-13,36,6, -4,-30,-29,62,32,-32,-1,22, --14,1,-4,-22,-45,2,54,4, --30,-57,-59,-12,27,-3,-31,8, --9,5,10,-14,32,66,19,9, -2,-25,-37,23,-15,18,-38,-31, -5,-9,-21,15,0,22,62,30, -15,-12,-14,-46,77,21,33,3, -34,29,-19,50,2,11,9,-38, --12,-37,62,1,-15,54,32,6, -2,-24,20,35,-21,2,19,24, --13,55,4,9,39,-19,30,-1, --21,73,54,33,8,18,3,15, -6,-19,-47,6,-3,-48,-50,1, -26,20,8,-23,-50,65,-14,-55, --17,-31,-37,-28,53,-1,-17,-53, -1,57,11,-8,-25,-30,-37,64, -5,-52,-45,15,23,31,15,14, --25,24,33,-2,-44,-56,-18,6, --21,-43,4,-12,17,-37,20,-10, -34,15,2,15,55,21,-11,-31, --6,46,25,16,-9,-25,-8,-62, -28,17,20,-32,-29,26,30,25, --19,2,-16,-17,26,-51,2,50, -42,19,-66,23,29,-2,3,19, --19,-37,32,15,6,30,-34,13, -11,-5,40,31,10,-42,4,-9, -26,-9,-70,17,-2,-23,20,-22, --55,51,-24,-31,22,-22,15,-13, -3,-10,-28,-16,56,4,-63,11, --18,-15,-18,-38,-35,16,-7,34, --1,-21,-49,-47,9,-37,7,8, -69,55,20,6,-33,-45,-10,-9, -6,-9,12,71,15,-3,-42,-7, --24,32,-35,-2,-42,-17,-5,0, --2,-33,-54,13,-12,-34,47,23, -19,55,7,-8,74,31,14,16, --23,-26,19,12,-18,-49,-28,-31, --20,2,-14,-20,-47,78,40,13, --23,-11,21,-6,18,1,47,5, -38,35,32,46,22,8,13,16, --14,18,51,19,40,39,11,-26, --1,-17,47,2,-53,-15,31,-22, -38,21,-15,-16,5,-33,53,15, --38,86,11,-3,-24,49,13,-4, --11,-18,28,20,-12,-27,-26,35, --25,-35,-3,-20,-61,30,10,-55, --12,-22,-52,-54,-14,19,-32,-12, -45,15,-8,-48,-9,11,-32,8, --16,-34,-13,51,18,38,-2,-32, --17,22,-2,-18,-28,-70,59,27, --28,-19,-10,-20,-9,-9,-8,-21, -21,-8,35,-2,45,-3,-9,12, -0,30,7,-39,43,27,-38,-91, -30,26,19,-55,-4,63,14,-17, -13,9,13,2,7,4,6,61, -72,-1,-17,29,-1,-22,-17,8, --28,-37,63,44,41,3,2,14, -9,-6,75,-8,-7,-12,-15,-12, -13,9,-4,30,-22,-65,15,0, --45,4,-4,1,5,22,11,23}; diff --git a/drivers/speex/jitter.c b/drivers/speex/jitter.c deleted file mode 100644 index 05a125e3d0..0000000000 --- a/drivers/speex/jitter.c +++ /dev/null @@ -1,843 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: speex_jitter.h - - Adaptive jitter buffer for Speex - - 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 the Xiph.org Foundation nor the names of its - 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 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. - -*/ - -/* -TODO: -- Add short-term estimate -- Defensive programming - + warn when last returned < last desired (begative buffering) - + warn if update_delay not called between get() and tick() or is called twice in a row -- Linked list structure for holding the packets instead of the current fixed-size array - + return memory to a pool - + allow pre-allocation of the pool - + optional max number of elements -- Statistics - + drift - + loss - + late - + jitter - + buffering delay -*/ - -#include "config.h" - - - -#include "arch.h" -#include <speex/speex.h> -#include <speex/speex_bits.h> -#include <speex/speex_jitter.h> -#include "os_support.h" - -#ifndef NULL -#define NULL 0 -#endif - -#define SPEEX_JITTER_MAX_BUFFER_SIZE 200 /**< Maximum number of packets in jitter buffer */ - -#define TSUB(a,b) ((spx_int32_t)((a)-(b))) - -#define GT32(a,b) (((spx_int32_t)((a)-(b)))>0) -#define GE32(a,b) (((spx_int32_t)((a)-(b)))>=0) -#define LT32(a,b) (((spx_int32_t)((a)-(b)))<0) -#define LE32(a,b) (((spx_int32_t)((a)-(b)))<=0) - -#define ROUND_DOWN(x, step) ((x)<0 ? ((x)-(step)+1)/(step)*(step) : (x)/(step)*(step)) - -#define MAX_TIMINGS 40 -#define MAX_BUFFERS 3 -#define TOP_DELAY 40 - -/** Buffer that keeps the time of arrival of the latest packets */ -struct TimingBuffer { - int filled; /**< Number of entries occupied in "timing" and "counts"*/ - int curr_count; /**< Number of packet timings we got (including those we discarded) */ - spx_int32_t timing[MAX_TIMINGS]; /**< Sorted list of all timings ("latest" packets first) */ - spx_int16_t counts[MAX_TIMINGS]; /**< Order the packets were put in (will be used for short-term estimate) */ -}; - -static void tb_init(struct TimingBuffer *tb) -{ - tb->filled = 0; - tb->curr_count = 0; -} - -/* Add the timing of a new packet to the TimingBuffer */ -static void tb_add(struct TimingBuffer *tb, spx_int16_t timing) -{ - int pos; - /* Discard packet that won't make it into the list because they're too early */ - if (tb->filled >= MAX_TIMINGS && timing >= tb->timing[tb->filled-1]) - { - tb->curr_count++; - return; - } - - /* Find where the timing info goes in the sorted list */ - pos = 0; - /* FIXME: Do bisection instead of linear search */ - while (pos<tb->filled && timing >= tb->timing[pos]) - { - pos++; - } - - speex_assert(pos <= tb->filled && pos < MAX_TIMINGS); - - /* Shift everything so we can perform the insertion */ - if (pos < tb->filled) - { - int move_size = tb->filled-pos; - if (tb->filled == MAX_TIMINGS) - move_size -= 1; - SPEEX_MOVE(&tb->timing[pos+1], &tb->timing[pos], move_size); - SPEEX_MOVE(&tb->counts[pos+1], &tb->counts[pos], move_size); - } - /* Insert */ - tb->timing[pos] = timing; - tb->counts[pos] = tb->curr_count; - - tb->curr_count++; - if (tb->filled<MAX_TIMINGS) - tb->filled++; -} - - - -/** Jitter buffer structure */ -struct JitterBuffer_ { - spx_uint32_t pointer_timestamp; /**< Timestamp of what we will *get* next */ - spx_uint32_t last_returned_timestamp; /**< Useful for getting the next packet with the same timestamp (for fragmented media) */ - spx_uint32_t next_stop; /**< Estimated time the next get() will be called */ - - spx_int32_t buffered; /**< Amount of data we think is still buffered by the application (timestamp units)*/ - - JitterBufferPacket packets[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packets stored in the buffer */ - spx_uint32_t arrival[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packet arrival time (0 means it was late, even though it's a valid timestamp) */ - - void (*destroy) (void *); /**< Callback for destroying a packet */ - - spx_int32_t delay_step; /**< Size of the steps when adjusting buffering (timestamp units) */ - spx_int32_t concealment_size; /**< Size of the packet loss concealment "units" */ - int reset_state; /**< True if state was just reset */ - int buffer_margin; /**< How many frames we want to keep in the buffer (lower bound) */ - int late_cutoff; /**< How late must a packet be for it not to be considered at all */ - int interp_requested; /**< An interpolation is requested by speex_jitter_update_delay() */ - int auto_adjust; /**< Whether to automatically adjust the delay at any time */ - - struct TimingBuffer _tb[MAX_BUFFERS]; /**< Don't use those directly */ - struct TimingBuffer *timeBuffers[MAX_BUFFERS]; /**< Storing arrival time of latest frames so we can compute some stats */ - int window_size; /**< Total window over which the late frames are counted */ - int subwindow_size; /**< Sub-window size for faster computation */ - int max_late_rate; /**< Absolute maximum amount of late packets tolerable (in percent) */ - int latency_tradeoff; /**< Latency equivalent of losing one percent of packets */ - int auto_tradeoff; /**< Latency equivalent of losing one percent of packets (automatic default) */ - - int lost_count; /**< Number of consecutive lost packets */ -}; - -/** Based on available data, this computes the optimal delay for the jitter buffer. - The optimised function is in timestamp units and is: - cost = delay + late_factor*[number of frames that would be late if we used that delay] - @param tb Array of buffers - @param late_factor Equivalent cost of a late frame (in timestamp units) - */ -static spx_int16_t compute_opt_delay(JitterBuffer *jitter) -{ - int i; - spx_int16_t opt=0; - spx_int32_t best_cost=0x7fffffff; - int late = 0; - int pos[MAX_BUFFERS]; - int tot_count; - float late_factor; - int penalty_taken = 0; - int best = 0; - int worst = 0; - spx_int32_t deltaT; - struct TimingBuffer *tb; - - tb = jitter->_tb; - - /* Number of packet timings we have received (including those we didn't keep) */ - tot_count = 0; - for (i=0;i<MAX_BUFFERS;i++) - tot_count += tb[i].curr_count; - if (tot_count==0) - return 0; - - /* Compute cost for one lost packet */ - if (jitter->latency_tradeoff != 0) - late_factor = jitter->latency_tradeoff * 100.0f / tot_count; - else - late_factor = jitter->auto_tradeoff * jitter->window_size/tot_count; - - /*fprintf(stderr, "late_factor = %f\n", late_factor);*/ - for (i=0;i<MAX_BUFFERS;i++) - pos[i] = 0; - - /* Pick the TOP_DELAY "latest" packets (doesn't need to actually be late - for the current settings) */ - for (i=0;i<TOP_DELAY;i++) - { - int j; - int next=-1; - int latest = 32767; - /* Pick latest amoung all sub-windows */ - for (j=0;j<MAX_BUFFERS;j++) - { - if (pos[j] < tb[j].filled && tb[j].timing[pos[j]] < latest) - { - next = j; - latest = tb[j].timing[pos[j]]; - } - } - if (next != -1) - { - spx_int32_t cost; - - if (i==0) - worst = latest; - best = latest; - latest = ROUND_DOWN(latest, jitter->delay_step); - pos[next]++; - - /* Actual cost function that tells us how bad using this delay would be */ - cost = -latest + late_factor*late; - /*fprintf(stderr, "cost %d = %d + %f * %d\n", cost, -latest, late_factor, late);*/ - if (cost < best_cost) - { - best_cost = cost; - opt = latest; - } - } else { - break; - } - - /* For the next timing we will consider, there will be one more late packet to count */ - late++; - /* Two-frame penalty if we're going to increase the amount of late frames (hysteresis) */ - if (latest >= 0 && !penalty_taken) - { - penalty_taken = 1; - late+=4; - } - } - - deltaT = best-worst; - /* This is a default "automatic latency tradeoff" when none is provided */ - jitter->auto_tradeoff = 1 + deltaT/TOP_DELAY; - /*fprintf(stderr, "auto_tradeoff = %d (%d %d %d)\n", jitter->auto_tradeoff, best, worst, i);*/ - - /* FIXME: Compute a short-term estimate too and combine with the long-term one */ - - /* Prevents reducing the buffer size when we haven't really had much data */ - if (tot_count < TOP_DELAY && opt > 0) - return 0; - return opt; -} - - -/** Initialise jitter buffer */ -EXPORT JitterBuffer *jitter_buffer_init(int step_size) -{ - JitterBuffer *jitter = (JitterBuffer*)speex_alloc(sizeof(JitterBuffer)); - if (jitter) - { - int i; - spx_int32_t tmp; - for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) - jitter->packets[i].data=NULL; - jitter->delay_step = step_size; - jitter->concealment_size = step_size; - /*FIXME: Should this be 0 or 1?*/ - jitter->buffer_margin = 0; - jitter->late_cutoff = 50; - jitter->destroy = NULL; - jitter->latency_tradeoff = 0; - jitter->auto_adjust = 1; - tmp = 4; - jitter_buffer_ctl(jitter, JITTER_BUFFER_SET_MAX_LATE_RATE, &tmp); - jitter_buffer_reset(jitter); - } - return jitter; -} - -/** Reset jitter buffer */ -EXPORT void jitter_buffer_reset(JitterBuffer *jitter) -{ - int i; - for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) - { - if (jitter->packets[i].data) - { - if (jitter->destroy) - jitter->destroy(jitter->packets[i].data); - else - speex_free(jitter->packets[i].data); - jitter->packets[i].data = NULL; - } - } - /* Timestamp is actually undefined at this point */ - jitter->pointer_timestamp = 0; - jitter->next_stop = 0; - jitter->reset_state = 1; - jitter->lost_count = 0; - jitter->buffered = 0; - jitter->auto_tradeoff = 32000; - - for (i=0;i<MAX_BUFFERS;i++) - { - tb_init(&jitter->_tb[i]); - jitter->timeBuffers[i] = &jitter->_tb[i]; - } - /*fprintf (stderr, "reset\n");*/ -} - -/** Destroy jitter buffer */ -EXPORT void jitter_buffer_destroy(JitterBuffer *jitter) -{ - jitter_buffer_reset(jitter); - speex_free(jitter); -} - -/** Take the following timing into consideration for future calculations */ -static void update_timings(JitterBuffer *jitter, spx_int32_t timing) -{ - if (timing < -32767) - timing = -32767; - if (timing > 32767) - timing = 32767; - /* If the current sub-window is full, perform a rotation and discard oldest sub-widow */ - if (jitter->timeBuffers[0]->curr_count >= jitter->subwindow_size) - { - int i; - /*fprintf(stderr, "Rotate buffer\n");*/ - struct TimingBuffer *tmp = jitter->timeBuffers[MAX_BUFFERS-1]; - for (i=MAX_BUFFERS-1;i>=1;i--) - jitter->timeBuffers[i] = jitter->timeBuffers[i-1]; - jitter->timeBuffers[0] = tmp; - tb_init(jitter->timeBuffers[0]); - } - tb_add(jitter->timeBuffers[0], timing); -} - -/** Compensate all timings when we do an adjustment of the buffering */ -static void shift_timings(JitterBuffer *jitter, spx_int16_t amount) -{ - int i, j; - for (i=0;i<MAX_BUFFERS;i++) - { - for (j=0;j<jitter->timeBuffers[i]->filled;j++) - jitter->timeBuffers[i]->timing[j] += amount; - } -} - - -/** Put one packet into the jitter buffer */ -EXPORT void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) -{ - int i,j; - int late; - /*fprintf (stderr, "put packet %d %d\n", timestamp, span);*/ - - /* Cleanup buffer (remove old packets that weren't played) */ - if (!jitter->reset_state) - { - for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) - { - /* Make sure we don't discard a "just-late" packet in case we want to play it next (if we interpolate). */ - if (jitter->packets[i].data && LE32(jitter->packets[i].timestamp + jitter->packets[i].span, jitter->pointer_timestamp)) - { - /*fprintf (stderr, "cleaned (not played)\n");*/ - if (jitter->destroy) - jitter->destroy(jitter->packets[i].data); - else - speex_free(jitter->packets[i].data); - jitter->packets[i].data = NULL; - } - } - } - - /*fprintf(stderr, "arrival: %d %d %d\n", packet->timestamp, jitter->next_stop, jitter->pointer_timestamp);*/ - /* Check if packet is late (could still be useful though) */ - if (!jitter->reset_state && LT32(packet->timestamp, jitter->next_stop)) - { - update_timings(jitter, ((spx_int32_t)packet->timestamp) - ((spx_int32_t)jitter->next_stop) - jitter->buffer_margin); - late = 1; - } else { - late = 0; - } - - /* For some reason, the consumer has failed the last 20 fetches. Make sure this packet is - * used to resync. */ - if (jitter->lost_count>20) - { - jitter_buffer_reset(jitter); - } - - /* Only insert the packet if it's not hopelessly late (i.e. totally useless) */ - if (jitter->reset_state || GE32(packet->timestamp+packet->span+jitter->delay_step, jitter->pointer_timestamp)) - { - - /*Find an empty slot in the buffer*/ - for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) - { - if (jitter->packets[i].data==NULL) - break; - } - - /*No place left in the buffer, need to make room for it by discarding the oldest packet */ - if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) - { - int earliest=jitter->packets[0].timestamp; - i=0; - for (j=1;j<SPEEX_JITTER_MAX_BUFFER_SIZE;j++) - { - if (!jitter->packets[i].data || LT32(jitter->packets[j].timestamp,earliest)) - { - earliest = jitter->packets[j].timestamp; - i=j; - } - } - if (jitter->destroy) - jitter->destroy(jitter->packets[i].data); - else - speex_free(jitter->packets[i].data); - jitter->packets[i].data=NULL; - /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/ - } - - /* Copy packet in buffer */ - if (jitter->destroy) - { - jitter->packets[i].data = packet->data; - } else { - jitter->packets[i].data=(char*)speex_alloc(packet->len); - for (j=0;j<packet->len;j++) - jitter->packets[i].data[j]=packet->data[j]; - } - jitter->packets[i].timestamp=packet->timestamp; - jitter->packets[i].span=packet->span; - jitter->packets[i].len=packet->len; - jitter->packets[i].sequence=packet->sequence; - jitter->packets[i].user_data=packet->user_data; - if (jitter->reset_state || late) - jitter->arrival[i] = 0; - else - jitter->arrival[i] = jitter->next_stop; - } - - -} - -/** Get one packet from the jitter buffer */ -EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset) -{ - int i; - unsigned int j; - int incomplete = 0; - spx_int16_t opt; - - if (start_offset != NULL) - *start_offset = 0; - - /* Syncing on the first call */ - if (jitter->reset_state) - { - int found = 0; - /* Find the oldest packet */ - spx_uint32_t oldest=0; - for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) - { - if (jitter->packets[i].data && (!found || LT32(jitter->packets[i].timestamp,oldest))) - { - oldest = jitter->packets[i].timestamp; - found = 1; - } - } - if (found) - { - jitter->reset_state=0; - jitter->pointer_timestamp = oldest; - jitter->next_stop = oldest; - } else { - packet->timestamp = 0; - packet->span = jitter->interp_requested; - return JITTER_BUFFER_MISSING; - } - } - - - jitter->last_returned_timestamp = jitter->pointer_timestamp; - - if (jitter->interp_requested != 0) - { - packet->timestamp = jitter->pointer_timestamp; - packet->span = jitter->interp_requested; - - /* Increment the pointer because it got decremented in the delay update */ - jitter->pointer_timestamp += jitter->interp_requested; - packet->len = 0; - /*fprintf (stderr, "Deferred interpolate\n");*/ - - jitter->interp_requested = 0; - - jitter->buffered = packet->span - desired_span; - - return JITTER_BUFFER_INSERTION; - } - - /* Searching for the packet that fits best */ - - /* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */ - for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) - { - if (jitter->packets[i].data && jitter->packets[i].timestamp==jitter->pointer_timestamp && GE32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp+desired_span)) - break; - } - - /* If no match, try for an "older" packet that still spans (fully) the current chunk */ - if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) - { - for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) - { - if (jitter->packets[i].data && LE32(jitter->packets[i].timestamp, jitter->pointer_timestamp) && GE32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp+desired_span)) - break; - } - } - - /* If still no match, try for an "older" packet that spans part of the current chunk */ - if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) - { - for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) - { - if (jitter->packets[i].data && LE32(jitter->packets[i].timestamp, jitter->pointer_timestamp) && GT32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp)) - break; - } - } - - /* If still no match, try for earliest packet possible */ - if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) - { - int found = 0; - spx_uint32_t best_time=0; - int best_span=0; - int besti=0; - for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) - { - /* check if packet starts within current chunk */ - if (jitter->packets[i].data && LT32(jitter->packets[i].timestamp,jitter->pointer_timestamp+desired_span) && GE32(jitter->packets[i].timestamp,jitter->pointer_timestamp)) - { - if (!found || LT32(jitter->packets[i].timestamp,best_time) || (jitter->packets[i].timestamp==best_time && GT32(jitter->packets[i].span,best_span))) - { - best_time = jitter->packets[i].timestamp; - best_span = jitter->packets[i].span; - besti = i; - found = 1; - } - } - } - if (found) - { - i=besti; - incomplete = 1; - /*fprintf (stderr, "incomplete: %d %d %d %d\n", jitter->packets[i].timestamp, jitter->pointer_timestamp, chunk_size, jitter->packets[i].span);*/ - } - } - - /* If we find something */ - if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE) - { - spx_int32_t offset; - - /* We (obviously) haven't lost this packet */ - jitter->lost_count = 0; - - /* In this case, 0 isn't as a valid timestamp */ - if (jitter->arrival[i] != 0) - { - update_timings(jitter, ((spx_int32_t)jitter->packets[i].timestamp) - ((spx_int32_t)jitter->arrival[i]) - jitter->buffer_margin); - } - - - /* Copy packet */ - if (jitter->destroy) - { - packet->data = jitter->packets[i].data; - packet->len = jitter->packets[i].len; - } else { - if (jitter->packets[i].len > packet->len) - { - speex_warning_int("jitter_buffer_get(): packet too large to fit. Size is", jitter->packets[i].len); - } else { - packet->len = jitter->packets[i].len; - } - for (j=0;j<packet->len;j++) - packet->data[j] = jitter->packets[i].data[j]; - /* Remove packet */ - speex_free(jitter->packets[i].data); - } - jitter->packets[i].data = NULL; - /* Set timestamp and span (if requested) */ - offset = (spx_int32_t)jitter->packets[i].timestamp-(spx_int32_t)jitter->pointer_timestamp; - if (start_offset != NULL) - *start_offset = offset; - else if (offset != 0) - speex_warning_int("jitter_buffer_get() discarding non-zero start_offset", offset); - - packet->timestamp = jitter->packets[i].timestamp; - jitter->last_returned_timestamp = packet->timestamp; - - packet->span = jitter->packets[i].span; - packet->sequence = jitter->packets[i].sequence; - packet->user_data = jitter->packets[i].user_data; - /* Point to the end of the current packet */ - jitter->pointer_timestamp = jitter->packets[i].timestamp+jitter->packets[i].span; - - jitter->buffered = packet->span - desired_span; - - if (start_offset != NULL) - jitter->buffered += *start_offset; - - return JITTER_BUFFER_OK; - } - - - /* If we haven't found anything worth returning */ - - /*fprintf (stderr, "not found\n");*/ - jitter->lost_count++; - /*fprintf (stderr, "m");*/ - /*fprintf (stderr, "lost_count = %d\n", jitter->lost_count);*/ - - opt = compute_opt_delay(jitter); - - /* Should we force an increase in the buffer or just do normal interpolation? */ - if (opt < 0) - { - /* Need to increase buffering */ - - /* Shift histogram to compensate */ - shift_timings(jitter, -opt); - - packet->timestamp = jitter->pointer_timestamp; - packet->span = -opt; - /* Don't move the pointer_timestamp forward */ - packet->len = 0; - - jitter->buffered = packet->span - desired_span; - return JITTER_BUFFER_INSERTION; - /*jitter->pointer_timestamp -= jitter->delay_step;*/ - /*fprintf (stderr, "Forced to interpolate\n");*/ - } else { - /* Normal packet loss */ - packet->timestamp = jitter->pointer_timestamp; - - desired_span = ROUND_DOWN(desired_span, jitter->concealment_size); - packet->span = desired_span; - jitter->pointer_timestamp += desired_span; - packet->len = 0; - - jitter->buffered = packet->span - desired_span; - return JITTER_BUFFER_MISSING; - /*fprintf (stderr, "Normal loss\n");*/ - } - - -} - -EXPORT int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet) -{ - int i, j; - for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) - { - if (jitter->packets[i].data && jitter->packets[i].timestamp==jitter->last_returned_timestamp) - break; - } - if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE) - { - /* Copy packet */ - packet->len = jitter->packets[i].len; - if (jitter->destroy) - { - packet->data = jitter->packets[i].data; - } else { - for (j=0;j<packet->len;j++) - packet->data[j] = jitter->packets[i].data[j]; - /* Remove packet */ - speex_free(jitter->packets[i].data); - } - jitter->packets[i].data = NULL; - packet->timestamp = jitter->packets[i].timestamp; - packet->span = jitter->packets[i].span; - packet->sequence = jitter->packets[i].sequence; - packet->user_data = jitter->packets[i].user_data; - return JITTER_BUFFER_OK; - } else { - packet->data = NULL; - packet->len = 0; - packet->span = 0; - return JITTER_BUFFER_MISSING; - } -} - -/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */ -static int _jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset) -{ - spx_int16_t opt = compute_opt_delay(jitter); - /*fprintf(stderr, "opt adjustment is %d ", opt);*/ - - if (opt < 0) - { - shift_timings(jitter, -opt); - - jitter->pointer_timestamp += opt; - jitter->interp_requested = -opt; - /*fprintf (stderr, "Decision to interpolate %d samples\n", -opt);*/ - } else if (opt > 0) - { - shift_timings(jitter, -opt); - jitter->pointer_timestamp += opt; - /*fprintf (stderr, "Decision to drop %d samples\n", opt);*/ - } - - return opt; -} - -/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */ -EXPORT int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset) -{ - /* If the programmer calls jitter_buffer_update_delay() directly, - automatically disable auto-adjustment */ - jitter->auto_adjust = 0; - - return _jitter_buffer_update_delay(jitter, packet, start_offset); -} - -/** Get pointer timestamp of jitter buffer */ -EXPORT int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter) -{ - return jitter->pointer_timestamp; -} - -EXPORT void jitter_buffer_tick(JitterBuffer *jitter) -{ - /* Automatically-adjust the buffering delay if requested */ - if (jitter->auto_adjust) - _jitter_buffer_update_delay(jitter, NULL, NULL); - - if (jitter->buffered >= 0) - { - jitter->next_stop = jitter->pointer_timestamp - jitter->buffered; - } else { - jitter->next_stop = jitter->pointer_timestamp; - speex_warning_int("jitter buffer sees negative buffering, your code might be broken. Value is ", jitter->buffered); - } - jitter->buffered = 0; -} - -EXPORT void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem) -{ - /* Automatically-adjust the buffering delay if requested */ - if (jitter->auto_adjust) - _jitter_buffer_update_delay(jitter, NULL, NULL); - - if (jitter->buffered < 0) - speex_warning_int("jitter buffer sees negative buffering, your code might be broken. Value is ", jitter->buffered); - jitter->next_stop = jitter->pointer_timestamp - rem; -} - - -/* Used like the ioctl function to control the jitter buffer parameters */ -EXPORT int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr) -{ - int count, i; - switch(request) - { - case JITTER_BUFFER_SET_MARGIN: - jitter->buffer_margin = *(spx_int32_t*)ptr; - break; - case JITTER_BUFFER_GET_MARGIN: - *(spx_int32_t*)ptr = jitter->buffer_margin; - break; - case JITTER_BUFFER_GET_AVALIABLE_COUNT: - count = 0; - for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) - { - if (jitter->packets[i].data && LE32(jitter->pointer_timestamp, jitter->packets[i].timestamp)) - { - count++; - } - } - *(spx_int32_t*)ptr = count; - break; - case JITTER_BUFFER_SET_DESTROY_CALLBACK: - jitter->destroy = (void (*) (void *))ptr; - break; - case JITTER_BUFFER_GET_DESTROY_CALLBACK: - *(void (**) (void *))ptr = jitter->destroy; - break; - case JITTER_BUFFER_SET_DELAY_STEP: - jitter->delay_step = *(spx_int32_t*)ptr; - break; - case JITTER_BUFFER_GET_DELAY_STEP: - *(spx_int32_t*)ptr = jitter->delay_step; - break; - case JITTER_BUFFER_SET_CONCEALMENT_SIZE: - jitter->concealment_size = *(spx_int32_t*)ptr; - break; - case JITTER_BUFFER_GET_CONCEALMENT_SIZE: - *(spx_int32_t*)ptr = jitter->concealment_size; - break; - case JITTER_BUFFER_SET_MAX_LATE_RATE: - jitter->max_late_rate = *(spx_int32_t*)ptr; - jitter->window_size = 100*TOP_DELAY/jitter->max_late_rate; - jitter->subwindow_size = jitter->window_size/MAX_BUFFERS; - break; - case JITTER_BUFFER_GET_MAX_LATE_RATE: - *(spx_int32_t*)ptr = jitter->max_late_rate; - break; - case JITTER_BUFFER_SET_LATE_COST: - jitter->latency_tradeoff = *(spx_int32_t*)ptr; - break; - case JITTER_BUFFER_GET_LATE_COST: - *(spx_int32_t*)ptr = jitter->latency_tradeoff; - break; - default: - speex_warning_int("Unknown jitter_buffer_ctl request: ", request); - return -1; - } - return 0; -} - diff --git a/drivers/speex/kiss_fft.c b/drivers/speex/kiss_fft.c deleted file mode 100644 index b85f018def..0000000000 --- a/drivers/speex/kiss_fft.c +++ /dev/null @@ -1,523 +0,0 @@ -/* -Copyright (c) 2003-2004, Mark Borgerding -Copyright (c) 2005-2007, Jean-Marc Valin - -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 author nor the names of any 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. -*/ - - - -#include "config.h" - - -#include "_kiss_fft_guts.h" -#include "arch.h" -#include "os_support.h" - -/* The guts header contains all the multiplication and addition macros that are defined for - fixed or floating point complex numbers. It also delares the kf_ internal functions. - */ - -static void kf_bfly2( - kiss_fft_cpx * Fout, - const size_t fstride, - const kiss_fft_cfg st, - int m, - int N, - int mm - ) -{ - kiss_fft_cpx * Fout2; - kiss_fft_cpx * tw1; - kiss_fft_cpx t; - if (!st->inverse) { - int i,j; - kiss_fft_cpx * Fout_beg = Fout; - for (i=0;i<N;i++) - { - Fout = Fout_beg + i*mm; - Fout2 = Fout + m; - tw1 = st->twiddles; - for(j=0;j<m;j++) - { - /* Almost the same as the code path below, except that we divide the input by two - (while keeping the best accuracy possible) */ - spx_word32_t tr, ti; - tr = SHR32(SUB32(MULT16_16(Fout2->r , tw1->r),MULT16_16(Fout2->i , tw1->i)), 1); - ti = SHR32(ADD32(MULT16_16(Fout2->i , tw1->r),MULT16_16(Fout2->r , tw1->i)), 1); - tw1 += fstride; - Fout2->r = PSHR32(SUB32(SHL32(EXTEND32(Fout->r), 14), tr), 15); - Fout2->i = PSHR32(SUB32(SHL32(EXTEND32(Fout->i), 14), ti), 15); - Fout->r = PSHR32(ADD32(SHL32(EXTEND32(Fout->r), 14), tr), 15); - Fout->i = PSHR32(ADD32(SHL32(EXTEND32(Fout->i), 14), ti), 15); - ++Fout2; - ++Fout; - } - } - } else { - int i,j; - kiss_fft_cpx * Fout_beg = Fout; - for (i=0;i<N;i++) - { - Fout = Fout_beg + i*mm; - Fout2 = Fout + m; - tw1 = st->twiddles; - for(j=0;j<m;j++) - { - C_MUL (t, *Fout2 , *tw1); - tw1 += fstride; - C_SUB( *Fout2 , *Fout , t ); - C_ADDTO( *Fout , t ); - ++Fout2; - ++Fout; - } - } - } -} - -static void kf_bfly4( - kiss_fft_cpx * Fout, - const size_t fstride, - const kiss_fft_cfg st, - int m, - int N, - int mm - ) -{ - kiss_fft_cpx *tw1,*tw2,*tw3; - kiss_fft_cpx scratch[6]; - const size_t m2=2*m; - const size_t m3=3*m; - int i, j; - - if (st->inverse) - { - kiss_fft_cpx * Fout_beg = Fout; - for (i=0;i<N;i++) - { - Fout = Fout_beg + i*mm; - tw3 = tw2 = tw1 = st->twiddles; - 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 = scratch[5].r - scratch[4].i; - Fout[m].i = scratch[5].i + scratch[4].r; - Fout[m3].r = scratch[5].r + scratch[4].i; - Fout[m3].i = scratch[5].i - scratch[4].r; - ++Fout; - } - } - } else - { - kiss_fft_cpx * Fout_beg = Fout; - for (i=0;i<N;i++) - { - Fout = Fout_beg + i*mm; - tw3 = tw2 = tw1 = st->twiddles; - for (j=0;j<m;j++) - { - C_MUL4(scratch[0],Fout[m] , *tw1 ); - C_MUL4(scratch[1],Fout[m2] , *tw2 ); - C_MUL4(scratch[2],Fout[m3] , *tw3 ); - - Fout->r = PSHR16(Fout->r, 2); - Fout->i = PSHR16(Fout->i, 2); - 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] ); - Fout[m2].r = PSHR16(Fout[m2].r, 2); - Fout[m2].i = PSHR16(Fout[m2].i, 2); - C_SUB( Fout[m2], *Fout, scratch[3] ); - tw1 += fstride; - tw2 += fstride*2; - tw3 += fstride*3; - C_ADDTO( *Fout , scratch[3] ); - - Fout[m].r = scratch[5].r + scratch[4].i; - Fout[m].i = scratch[5].i - scratch[4].r; - Fout[m3].r = scratch[5].r - scratch[4].i; - Fout[m3].i = scratch[5].i + scratch[4].r; - ++Fout; - } - } - } -} - -static void kf_bfly3( - kiss_fft_cpx * Fout, - const size_t fstride, - const kiss_fft_cfg st, - size_t m - ) -{ - size_t k=m; - const size_t m2 = 2*m; - kiss_fft_cpx *tw1,*tw2; - kiss_fft_cpx scratch[5]; - kiss_fft_cpx epi3; - epi3 = st->twiddles[fstride*m]; - - tw1=tw2=st->twiddles; - - do{ - if (!st->inverse) { - C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3); - } - - 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 = Fout->r - HALF_OF(scratch[3].r); - Fout[m].i = Fout->i - HALF_OF(scratch[3].i); - - C_MULBYSCALAR( scratch[0] , epi3.i ); - - C_ADDTO(*Fout,scratch[3]); - - Fout[m2].r = Fout[m].r + scratch[0].i; - Fout[m2].i = Fout[m].i - scratch[0].r; - - Fout[m].r -= scratch[0].i; - Fout[m].i += scratch[0].r; - - ++Fout; - }while(--k); -} - -static void kf_bfly5( - kiss_fft_cpx * Fout, - const size_t fstride, - const kiss_fft_cfg st, - int m - ) -{ - kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4; - int u; - kiss_fft_cpx scratch[13]; - kiss_fft_cpx * twiddles = st->twiddles; - kiss_fft_cpx *tw; - kiss_fft_cpx ya,yb; - ya = twiddles[fstride*m]; - yb = twiddles[fstride*2*m]; - - Fout0=Fout; - Fout1=Fout0+m; - Fout2=Fout0+2*m; - Fout3=Fout0+3*m; - Fout4=Fout0+4*m; - - tw=st->twiddles; - for ( u=0; u<m; ++u ) { - if (!st->inverse) { - C_FIXDIV( *Fout0,5); C_FIXDIV( *Fout1,5); C_FIXDIV( *Fout2,5); C_FIXDIV( *Fout3,5); C_FIXDIV( *Fout4,5); - } - 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 += scratch[7].r + scratch[8].r; - Fout0->i += scratch[7].i + scratch[8].i; - - scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r); - scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r); - - scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i); - scratch[6].i = -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 = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r); - scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r); - scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i); - scratch[12].i = 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; - } -} - -/* perform the butterfly for one stage of a mixed radix FFT */ -static void kf_bfly_generic( - kiss_fft_cpx * Fout, - const size_t fstride, - const kiss_fft_cfg st, - int m, - int p - ) -{ - int u,k,q1,q; - kiss_fft_cpx * twiddles = st->twiddles; - kiss_fft_cpx t; - kiss_fft_cpx scratchbuf[17]; - int Norig = st->nfft; - - /*CHECKBUF(scratchbuf,nscratchbuf,p);*/ - if (p>17) - speex_fatal("KissFFT: max radix supported is 17"); - - for ( u=0; u<m; ++u ) { - k=u; - for ( q1=0 ; q1<p ; ++q1 ) { - scratchbuf[q1] = Fout[ k ]; - if (!st->inverse) { - C_FIXDIV(scratchbuf[q1],p); - } - k += m; - } - - k=u; - for ( q1=0 ; q1<p ; ++q1 ) { - int twidx=0; - Fout[ k ] = scratchbuf[0]; - for (q=1;q<p;++q ) { - twidx += fstride * k; - if (twidx>=Norig) twidx-=Norig; - C_MUL(t,scratchbuf[q] , twiddles[twidx] ); - C_ADDTO( Fout[ k ] ,t); - } - k += m; - } - } -} - -static -void kf_shuffle( - kiss_fft_cpx * Fout, - const kiss_fft_cpx * f, - const size_t fstride, - int in_stride, - int * factors, - const kiss_fft_cfg 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++) - { - Fout[j] = *f; - f += fstride*in_stride; - } - } else { - int j; - for (j=0;j<p;j++) - { - kf_shuffle( Fout , f, fstride*p, in_stride, factors,st); - f += fstride*in_stride; - Fout += m; - } - } -} - -static -void kf_work( - kiss_fft_cpx * Fout, - const kiss_fft_cpx * f, - const size_t fstride, - int in_stride, - int * factors, - const kiss_fft_cfg st, - int N, - int s2, - int m2 - ) -{ - int i; - kiss_fft_cpx * Fout_beg=Fout; - const int p=*factors++; /* the radix */ - const int m=*factors++; /* stage's fft length/p */ -#if 0 - /*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++) - { - Fout[j] = *f; - f += fstride*in_stride; - }*/ - } else { - int j; - for (j=0;j<p;j++) - { - kf_work( Fout , f, fstride*p, in_stride, factors,st, N*p, fstride*in_stride, m); - f += fstride*in_stride; - Fout += m; - } - } - - Fout=Fout_beg; - - switch (p) { - case 2: kf_bfly2(Fout,fstride,st,m); break; - case 3: kf_bfly3(Fout,fstride,st,m); break; - case 4: kf_bfly4(Fout,fstride,st,m); break; - case 5: kf_bfly5(Fout,fstride,st,m); break; - default: kf_bfly_generic(Fout,fstride,st,m,p); break; - } -#else - /*printf ("fft %d %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N, m2);*/ - if (m==1) - { - /*for (i=0;i<N;i++) - { - int j; - Fout = Fout_beg+i*m2; - const kiss_fft_cpx * f2 = f+i*s2; - for (j=0;j<p;j++) - { - *Fout++ = *f2; - f2 += fstride*in_stride; - } - }*/ - }else{ - kf_work( Fout , f, fstride*p, in_stride, factors,st, N*p, fstride*in_stride, m); - } - - - - - switch (p) { - case 2: kf_bfly2(Fout,fstride,st,m, N, m2); break; - case 3: for (i=0;i<N;i++){Fout=Fout_beg+i*m2; kf_bfly3(Fout,fstride,st,m);} break; - case 4: kf_bfly4(Fout,fstride,st,m, N, m2); break; - case 5: for (i=0;i<N;i++){Fout=Fout_beg+i*m2; kf_bfly5(Fout,fstride,st,m);} break; - default: for (i=0;i<N;i++){Fout=Fout_beg+i*m2; kf_bfly_generic(Fout,fstride,st,m,p);} break; - } -#endif -} - -/* facbuf is populated by p1,m1,p2,m2, ... - where - p[i] * m[i] = m[i-1] - m0 = n */ -static -void kf_factor(int n,int * facbuf) -{ - int p=4; - - /*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 || (spx_int32_t)p*(spx_int32_t)p > n) - p = n; /* no more factors, skip to end */ - } - n /= p; - *facbuf++ = p; - *facbuf++ = n; - } while (n > 1); -} -/* - * - * User-callable function to allocate all necessary storage space for the fft. - * - * The return value is a contiguous block of memory, allocated with malloc. As such, - * It can be freed with free(), rather than a kiss_fft-specific function. - * */ -kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem ) -{ - kiss_fft_cfg st=NULL; - size_t memneeded = sizeof(struct kiss_fft_state) - + sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/ - - if ( lenmem==NULL ) { - st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded ); - }else{ - if (mem != NULL && *lenmem >= memneeded) - st = (kiss_fft_cfg)mem; - *lenmem = memneeded; - } - if (st) { - int i; - st->nfft=nfft; - st->inverse = inverse_fft; -#ifdef FIXED_POINT - for (i=0;i<nfft;++i) { - spx_word32_t phase = i; - if (!st->inverse) - phase = -phase; - kf_cexp2(st->twiddles+i, DIV32(SHL32(phase,17),nfft)); - } -#else - for (i=0;i<nfft;++i) { - const double pi=3.14159265358979323846264338327; - double phase = ( -2*pi /nfft ) * i; - if (st->inverse) - phase *= -1; - kf_cexp(st->twiddles+i, phase ); - } -#endif - kf_factor(nfft,st->factors); - } - return st; -} - - - - -void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride) -{ - if (fin == fout) - { - speex_fatal("In-place FFT not supported"); - /*CHECKBUF(tmpbuf,ntmpbuf,st->nfft); - kf_work(tmpbuf,fin,1,in_stride, st->factors,st); - SPEEX_MOVE(fout,tmpbuf,st->nfft);*/ - } else { - kf_shuffle( fout, fin, 1,in_stride, st->factors,st); - kf_work( fout, fin, 1,in_stride, st->factors,st, 1, in_stride, 1); - } -} - -void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) -{ - kiss_fft_stride(cfg,fin,fout,1); -} - diff --git a/drivers/speex/kiss_fft.h b/drivers/speex/kiss_fft.h deleted file mode 100644 index fa3f2c6042..0000000000 --- a/drivers/speex/kiss_fft.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef KISS_FFT_H -#define KISS_FFT_H - -#include <stdlib.h> -#include <math.h> -#include "arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - ATTENTION! - If you would like a : - -- a utility that will handle the caching of fft objects - -- real-only (no imaginary time component ) FFT - -- a multi-dimensional FFT - -- a command-line utility to perform ffts - -- a command-line utility to perform fast-convolution filtering - - Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c - in the tools/ directory. -*/ - -#ifdef USE_SIMD -# include <xmmintrin.h> -# define kiss_fft_scalar __m128 -#define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes) -#else -#define KISS_FFT_MALLOC speex_alloc -#endif - - -#ifdef FIXED_POINT -#include "arch.h" -# define kiss_fft_scalar spx_int16_t -#else -# ifndef kiss_fft_scalar -/* default is float */ -# define kiss_fft_scalar float -# endif -#endif - -typedef struct { - kiss_fft_scalar r; - kiss_fft_scalar i; -}kiss_fft_cpx; - -typedef struct kiss_fft_state* kiss_fft_cfg; - -/* - * kiss_fft_alloc - * - * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. - * - * typical usage: kiss_fft_cfg mycfg=kiss_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 kiss_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_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); - -/* - * kiss_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 kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); - -/* - A more generic version of the above function. It reads its input from every Nth sample. - * */ -void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride); - -/* If kiss_fft_alloc allocated a buffer, it is one contiguous - buffer and can be simply free()d when no longer needed*/ -#define kiss_fft_free speex_free - -/* - Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up - your compiler output to call this before you exit. -*/ -void kiss_fft_cleanup(void); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/speex/kiss_fftr.c b/drivers/speex/kiss_fftr.c deleted file mode 100644 index 819bc6f105..0000000000 --- a/drivers/speex/kiss_fftr.c +++ /dev/null @@ -1,297 +0,0 @@ -/* -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. - * Neither the author nor the names of any 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. -*/ - - -#include "config.h" - - -#include "os_support.h" -#include "kiss_fftr.h" -#include "_kiss_fft_guts.h" - -struct kiss_fftr_state{ - kiss_fft_cfg substate; - kiss_fft_cpx * tmpbuf; - kiss_fft_cpx * super_twiddles; -#ifdef USE_SIMD - long pad; -#endif -}; - -kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem) -{ - int i; - kiss_fftr_cfg st = NULL; - size_t subsize, memneeded; - - if (nfft & 1) { - speex_warning("Real FFT optimization must be even.\n"); - return NULL; - } - nfft >>= 1; - - kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize); - memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 2); - - if (lenmem == NULL) { - st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded); - } else { - if (*lenmem >= memneeded) - st = (kiss_fftr_cfg) mem; - *lenmem = memneeded; - } - if (!st) - return NULL; - - st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */ - st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize); - st->super_twiddles = st->tmpbuf + nfft; - kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize); - -#ifdef FIXED_POINT - for (i=0;i<nfft;++i) { - spx_word32_t phase = i+(nfft>>1); - if (!inverse_fft) - phase = -phase; - kf_cexp2(st->super_twiddles+i, DIV32(SHL32(phase,16),nfft)); - } -#else - for (i=0;i<nfft;++i) { - const double pi=3.14159265358979323846264338327; - double phase = pi*(((double)i) /nfft + .5); - if (!inverse_fft) - phase = -phase; - kf_cexp(st->super_twiddles+i, phase ); - } -#endif - return st; -} - -void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata) -{ - /* input buffer timedata is stored row-wise */ - int k,ncfft; - kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc; - - if ( st->substate->inverse) { - speex_fatal("kiss fft usage error: improper alloc\n"); - } - - ncfft = st->substate->nfft; - - /*perform the parallel fft of two real signals packed in real,imag*/ - kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf ); - /* The real part of the DC element of the frequency spectrum in st->tmpbuf - * contains the sum of the even-numbered elements of the input time sequence - * The imag part is the sum of the odd-numbered elements - * - * The sum of tdc.r and tdc.i is the sum of the input time sequence. - * yielding DC of input time sequence - * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... - * yielding Nyquist bin of input time sequence - */ - - tdc.r = st->tmpbuf[0].r; - tdc.i = st->tmpbuf[0].i; - C_FIXDIV(tdc,2); - CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i); - CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i); - freqdata[0].r = tdc.r + tdc.i; - freqdata[ncfft].r = tdc.r - tdc.i; -#ifdef USE_SIMD - freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0); -#else - freqdata[ncfft].i = freqdata[0].i = 0; -#endif - - for ( k=1;k <= ncfft/2 ; ++k ) { - fpk = st->tmpbuf[k]; - fpnk.r = st->tmpbuf[ncfft-k].r; - fpnk.i = - st->tmpbuf[ncfft-k].i; - C_FIXDIV(fpk,2); - C_FIXDIV(fpnk,2); - - C_ADD( f1k, fpk , fpnk ); - C_SUB( f2k, fpk , fpnk ); - C_MUL( tw , f2k , st->super_twiddles[k]); - - freqdata[k].r = HALF_OF(f1k.r + tw.r); - freqdata[k].i = HALF_OF(f1k.i + tw.i); - freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r); - freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i); - } -} - -void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata, kiss_fft_scalar *timedata) -{ - /* input buffer timedata is stored row-wise */ - int k, ncfft; - - if (st->substate->inverse == 0) { - speex_fatal("kiss fft usage error: improper alloc\n"); - } - - ncfft = st->substate->nfft; - - st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r; - st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r; - /*C_FIXDIV(st->tmpbuf[0],2);*/ - - for (k = 1; k <= ncfft / 2; ++k) { - kiss_fft_cpx fk, fnkc, fek, fok, tmp; - fk = freqdata[k]; - fnkc.r = freqdata[ncfft - k].r; - fnkc.i = -freqdata[ncfft - k].i; - /*C_FIXDIV( fk , 2 ); - C_FIXDIV( fnkc , 2 );*/ - - C_ADD (fek, fk, fnkc); - C_SUB (tmp, fk, fnkc); - C_MUL (fok, tmp, st->super_twiddles[k]); - C_ADD (st->tmpbuf[k], fek, fok); - C_SUB (st->tmpbuf[ncfft - k], fek, fok); -#ifdef USE_SIMD - st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0); -#else - st->tmpbuf[ncfft - k].i *= -1; -#endif - } - kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata); -} - -void kiss_fftr2(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_scalar *freqdata) -{ - /* input buffer timedata is stored row-wise */ - int k,ncfft; - kiss_fft_cpx f2k,tdc; - spx_word32_t f1kr, f1ki, twr, twi; - - if ( st->substate->inverse) { - speex_fatal("kiss fft usage error: improper alloc\n"); - } - - ncfft = st->substate->nfft; - - /*perform the parallel fft of two real signals packed in real,imag*/ - kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf ); - /* The real part of the DC element of the frequency spectrum in st->tmpbuf - * contains the sum of the even-numbered elements of the input time sequence - * The imag part is the sum of the odd-numbered elements - * - * The sum of tdc.r and tdc.i is the sum of the input time sequence. - * yielding DC of input time sequence - * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... - * yielding Nyquist bin of input time sequence - */ - - tdc.r = st->tmpbuf[0].r; - tdc.i = st->tmpbuf[0].i; - C_FIXDIV(tdc,2); - CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i); - CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i); - freqdata[0] = tdc.r + tdc.i; - freqdata[2*ncfft-1] = tdc.r - tdc.i; - - for ( k=1;k <= ncfft/2 ; ++k ) - { - /*fpk = st->tmpbuf[k]; - fpnk.r = st->tmpbuf[ncfft-k].r; - fpnk.i = - st->tmpbuf[ncfft-k].i; - C_FIXDIV(fpk,2); - C_FIXDIV(fpnk,2); - - C_ADD( f1k, fpk , fpnk ); - C_SUB( f2k, fpk , fpnk ); - - C_MUL( tw , f2k , st->super_twiddles[k]); - - freqdata[2*k-1] = HALF_OF(f1k.r + tw.r); - freqdata[2*k] = HALF_OF(f1k.i + tw.i); - freqdata[2*(ncfft-k)-1] = HALF_OF(f1k.r - tw.r); - freqdata[2*(ncfft-k)] = HALF_OF(tw.i - f1k.i); - */ - - /*f1k.r = PSHR32(ADD32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),1); - f1k.i = PSHR32(SUB32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1); - f2k.r = PSHR32(SUB32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),1); - f2k.i = SHR32(ADD32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1); - - C_MUL( tw , f2k , st->super_twiddles[k]); - - freqdata[2*k-1] = HALF_OF(f1k.r + tw.r); - freqdata[2*k] = HALF_OF(f1k.i + tw.i); - freqdata[2*(ncfft-k)-1] = HALF_OF(f1k.r - tw.r); - freqdata[2*(ncfft-k)] = HALF_OF(tw.i - f1k.i); - */ - f2k.r = SHR32(SUB32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),1); - f2k.i = PSHR32(ADD32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1); - - f1kr = SHL32(ADD32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),13); - f1ki = SHL32(SUB32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),13); - - twr = SHR32(SUB32(MULT16_16(f2k.r,st->super_twiddles[k].r),MULT16_16(f2k.i,st->super_twiddles[k].i)), 1); - twi = SHR32(ADD32(MULT16_16(f2k.i,st->super_twiddles[k].r),MULT16_16(f2k.r,st->super_twiddles[k].i)), 1); - -#ifdef FIXED_POINT - freqdata[2*k-1] = PSHR32(f1kr + twr, 15); - freqdata[2*k] = PSHR32(f1ki + twi, 15); - freqdata[2*(ncfft-k)-1] = PSHR32(f1kr - twr, 15); - freqdata[2*(ncfft-k)] = PSHR32(twi - f1ki, 15); -#else - freqdata[2*k-1] = .5f*(f1kr + twr); - freqdata[2*k] = .5f*(f1ki + twi); - freqdata[2*(ncfft-k)-1] = .5f*(f1kr - twr); - freqdata[2*(ncfft-k)] = .5f*(twi - f1ki); - -#endif - } -} - -void kiss_fftri2(kiss_fftr_cfg st,const kiss_fft_scalar *freqdata,kiss_fft_scalar *timedata) -{ - /* input buffer timedata is stored row-wise */ - int k, ncfft; - - if (st->substate->inverse == 0) { - speex_fatal ("kiss fft usage error: improper alloc\n"); - } - - ncfft = st->substate->nfft; - - st->tmpbuf[0].r = freqdata[0] + freqdata[2*ncfft-1]; - st->tmpbuf[0].i = freqdata[0] - freqdata[2*ncfft-1]; - /*C_FIXDIV(st->tmpbuf[0],2);*/ - - for (k = 1; k <= ncfft / 2; ++k) { - kiss_fft_cpx fk, fnkc, fek, fok, tmp; - fk.r = freqdata[2*k-1]; - fk.i = freqdata[2*k]; - fnkc.r = freqdata[2*(ncfft - k)-1]; - fnkc.i = -freqdata[2*(ncfft - k)]; - /*C_FIXDIV( fk , 2 ); - C_FIXDIV( fnkc , 2 );*/ - - C_ADD (fek, fk, fnkc); - C_SUB (tmp, fk, fnkc); - C_MUL (fok, tmp, st->super_twiddles[k]); - C_ADD (st->tmpbuf[k], fek, fok); - C_SUB (st->tmpbuf[ncfft - k], fek, fok); -#ifdef USE_SIMD - st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0); -#else - st->tmpbuf[ncfft - k].i *= -1; -#endif - } - kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata); -} diff --git a/drivers/speex/kiss_fftr.h b/drivers/speex/kiss_fftr.h deleted file mode 100644 index 7bfb423340..0000000000 --- a/drivers/speex/kiss_fftr.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef KISS_FTR_H -#define KISS_FTR_H - -#include "kiss_fft.h" -#ifdef __cplusplus -extern "C" { -#endif - - -/* - - Real optimized version can save about 45% cpu time vs. complex fft of a real seq. - - - - */ - -typedef struct kiss_fftr_state *kiss_fftr_cfg; - - -kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem); -/* - nfft must be even - - If you don't care to allocate space, use mem = lenmem = NULL -*/ - - -void kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata); -/* - input timedata has nfft scalar points - output freqdata has nfft/2+1 complex points -*/ - -void kiss_fftr2(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_scalar *freqdata); - -void kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata); - -void kiss_fftri2(kiss_fftr_cfg st,const kiss_fft_scalar *freqdata, kiss_fft_scalar *timedata); - -/* - input freqdata has nfft/2+1 complex points - output timedata has nfft scalar points -*/ - -#define kiss_fftr_free speex_free - -#ifdef __cplusplus -} -#endif -#endif diff --git a/drivers/speex/lpc.c b/drivers/speex/lpc.c deleted file mode 100644 index 6304efaa53..0000000000 --- a/drivers/speex/lpc.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann, - Technische Universitaet Berlin - - Any use of this software is permitted provided that this notice is not - removed and that neither the authors nor the Technische Universitaet Berlin - are deemed to have made any representations as to the suitability of this - software for any purpose nor are held responsible for any defects of - this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. - - As a matter of courtesy, the authors request to be informed about uses - this software has found, about bugs in this software, and about any - improvements that may be of general interest. - - Berlin, 28.11.1994 - Jutta Degener - Carsten Bormann - - - Code modified by Jean-Marc Valin - - Speex License: - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -#include "config.h" - - -#include "lpc.h" - -#ifdef BFIN_ASM -#include "lpc_bfin.h" -#endif - -/* LPC analysis - * - * The next two functions calculate linear prediction coefficients - * and/or the related reflection coefficients from the first P_MAX+1 - * values of the autocorrelation function. - */ - -/* Invented by N. Levinson in 1947, modified by J. Durbin in 1959. - */ - -/* returns minimum mean square error */ -spx_word32_t _spx_lpc( -spx_coef_t *lpc, /* out: [0...p-1] LPC coefficients */ -const spx_word16_t *ac, /* in: [0...p] autocorrelation values */ -int p -) -{ - int i, j; - spx_word16_t r; - spx_word16_t error = ac[0]; - - if (ac[0] == 0) - { - for (i = 0; i < p; i++) - lpc[i] = 0; - return 0; - } - - for (i = 0; i < p; i++) { - - /* Sum up this iteration's reflection coefficient */ - spx_word32_t rr = NEG32(SHL32(EXTEND32(ac[i + 1]),13)); - for (j = 0; j < i; j++) - rr = SUB32(rr,MULT16_16(lpc[j],ac[i - j])); -#ifdef FIXED_POINT - r = DIV32_16(rr+PSHR32(error,1),ADD16(error,8)); -#else - r = rr/(error+.003*ac[0]); -#endif - /* Update LPC coefficients and total error */ - lpc[i] = r; - for (j = 0; j < i>>1; j++) - { - spx_word16_t tmp = lpc[j]; - lpc[j] = MAC16_16_P13(lpc[j],r,lpc[i-1-j]); - lpc[i-1-j] = MAC16_16_P13(lpc[i-1-j],r,tmp); - } - if (i & 1) - lpc[j] = MAC16_16_P13(lpc[j],lpc[j],r); - - error = SUB16(error,MULT16_16_Q13(r,MULT16_16_Q13(error,r))); - } - return error; -} - - -#ifdef FIXED_POINT - -/* Compute the autocorrelation - * ,--, - * ac(i) = > x(n) * x(n-i) for all n - * `--' - * for lags between 0 and lag-1, and x == 0 outside 0...n-1 - */ - -#ifndef OVERRIDE_SPEEX_AUTOCORR -void _spx_autocorr( -const spx_word16_t *x, /* in: [0...n-1] samples x */ -spx_word16_t *ac, /* out: [0...lag-1] ac values */ -int lag, -int n -) -{ - spx_word32_t d; - int i, j; - spx_word32_t ac0=1; - int shift, ac_shift; - - for (j=0;j<n;j++) - ac0 = ADD32(ac0,SHR32(MULT16_16(x[j],x[j]),8)); - ac0 = ADD32(ac0,n); - shift = 8; - while (shift && ac0<0x40000000) - { - shift--; - ac0 <<= 1; - } - ac_shift = 18; - while (ac_shift && ac0<0x40000000) - { - ac_shift--; - ac0 <<= 1; - } - - - for (i=0;i<lag;i++) - { - d=0; - for (j=i;j<n;j++) - { - d = ADD32(d,SHR32(MULT16_16(x[j],x[j-i]), shift)); - } - - ac[i] = SHR32(d, ac_shift); - } -} -#endif - - -#else - - - -/* Compute the autocorrelation - * ,--, - * ac(i) = > x(n) * x(n-i) for all n - * `--' - * for lags between 0 and lag-1, and x == 0 outside 0...n-1 - */ -void _spx_autocorr( -const spx_word16_t *x, /* in: [0...n-1] samples x */ -float *ac, /* out: [0...lag-1] ac values */ -int lag, -int n -) -{ - float d; - int i; - while (lag--) - { - for (i = lag, d = 0; i < n; i++) - d += x[i] * x[i-lag]; - ac[lag] = d; - } - ac[0] += 10; -} - -#endif - - diff --git a/drivers/speex/lpc.h b/drivers/speex/lpc.h deleted file mode 100644 index 952ecdd933..0000000000 --- a/drivers/speex/lpc.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @file lpc.h - @brief Functions for LPC (Linear Prediction Coefficients) 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. - - - Neither the name of the Xiph.org Foundation nor the names of its - 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 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 LPC_H -#define LPC_H - -#include "arch.h" - -void _spx_autocorr( - const spx_word16_t * x, /* in: [0...n-1] samples x */ - spx_word16_t *ac, /* out: [0...lag-1] ac values */ - int lag, int n); - -spx_word32_t /* returns minimum mean square error */ -_spx_lpc( - spx_coef_t * lpc, /* [0...p-1] LPC coefficients */ - const spx_word16_t * ac, /* in: [0...p] autocorrelation values */ - int p - ); - - -#endif diff --git a/drivers/speex/lpc_bfin.h b/drivers/speex/lpc_bfin.h deleted file mode 100644 index 7310ffba52..0000000000 --- a/drivers/speex/lpc_bfin.h +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (C) 2005 Analog Devices */ -/** - @file lpc_bfin.h - @author Jean-Marc Valin - @brief Functions for LPC (Linear Prediction Coefficients) analysis (Blackfin version) -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#define OVERRIDE_SPEEX_AUTOCORR -void _spx_autocorr( -const spx_word16_t *x, /* in: [0...n-1] samples x */ -spx_word16_t *ac, /* out: [0...lag-1] ac values */ -int lag, -int n - ) -{ - spx_word32_t d; - const spx_word16_t *xs; - int i, j; - spx_word32_t ac0=1; - spx_word32_t ac32[11], *ac32top; - int shift, ac_shift; - ac32top = ac32+lag-1; - int lag_1, N_lag; - int nshift; - lag_1 = lag-1; - N_lag = n-lag_1; - for (j=0;j<n;j++) - ac0 = ADD32(ac0,SHR32(MULT16_16(x[j],x[j]),8)); - ac0 = ADD32(ac0,n); - shift = 8; - while (shift && ac0<0x40000000) - { - shift--; - ac0 <<= 1; - } - ac_shift = 18; - while (ac_shift && ac0<0x40000000) - { - ac_shift--; - ac0 <<= 1; - } - - xs = x+lag-1; - nshift = -shift; - __asm__ __volatile__ - ( - "P2 = %0;\n\t" - "I0 = P2;\n\t" /* x in I0 */ - "B0 = P2;\n\t" /* x in B0 */ - "R0 = %3;\n\t" /* len in R0 */ - "P3 = %3;\n\t" /* len in R0 */ - "P4 = %4;\n\t" /* nb_pitch in R0 */ - "R1 = R0 << 1;\n\t" /* number of bytes in x */ - "L0 = R1;\n\t" - "P0 = %1;\n\t" - "P1 = %2;\n\t" - "B1 = P1;\n\t" - "R4 = %5;\n\t" - "L1 = 0;\n\t" /*Disable looping on I1*/ - - "r0 = [I0++];\n\t" - "R2 = 0;R3=0;" - "LOOP pitch%= LC0 = P4 >> 1;\n\t" - "LOOP_BEGIN pitch%=;\n\t" - "I1 = P0;\n\t" - "A1 = A0 = 0;\n\t" - "R1 = [I1++];\n\t" - "LOOP inner_prod%= LC1 = P3 >> 1;\n\t" - "LOOP_BEGIN inner_prod%=;\n\t" - "A1 += R0.L*R1.H, A0 += R0.L*R1.L (IS) || R1.L = W[I1++];\n\t" - "A1 += R0.H*R1.L, A0 += R0.H*R1.H (IS) || R1.H = W[I1++] || R0 = [I0++];\n\t" - "LOOP_END inner_prod%=;\n\t" - "A0 = ASHIFT A0 by R4.L;\n\t" - "A1 = ASHIFT A1 by R4.L;\n\t" - - "R2 = A0, R3 = A1;\n\t" - "[P1--] = R2;\n\t" - "[P1--] = R3;\n\t" - "P0 += 4;\n\t" - "LOOP_END pitch%=;\n\t" - : : "m" (xs), "m" (x), "m" (ac32top), "m" (N_lag), "m" (lag_1), "m" (nshift) - : "A0", "A1", "P0", "P1", "P2", "P3", "P4", "R0", "R1", "R2", "R3", "R4", "I0", "I1", "L0", "L1", "B0", "B1", "memory" - ); - d=0; - for (j=0;j<n;j++) - { - d = ADD32(d,SHR32(MULT16_16(x[j],x[j]), shift)); - } - ac32[0] = d; - - for (i=0;i<lag;i++) - { - d=0; - for (j=i;j<lag_1;j++) - { - d = ADD32(d,SHR32(MULT16_16(x[j],x[j-i]), shift)); - } - if (i) - ac32[i] += d; - ac[i] = SHR32(ac32[i], ac_shift); - } -} - diff --git a/drivers/speex/lsp.c b/drivers/speex/lsp.c deleted file mode 100644 index f62323a59f..0000000000 --- a/drivers/speex/lsp.c +++ /dev/null @@ -1,656 +0,0 @@ -/*---------------------------------------------------------------------------*\ -Original copyright - FILE........: lsp.c - AUTHOR......: David Rowe - DATE CREATED: 24/2/93 - -Heavily modified by Jean-Marc Valin (c) 2002-2006 (fixed-point, - optimizations, additional functions, ...) - - This file contains functions for converting Linear Prediction - Coefficients (LPC) to Line Spectral Pair (LSP) and back. Note that the - LSP coefficients are not in radians format but in the x domain of the - unit circle. - - Speex License: - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -/*---------------------------------------------------------------------------*\ - - Introduction to Line Spectrum Pairs (LSPs) - ------------------------------------------ - - LSPs are used to encode the LPC filter coefficients {ak} for - transmission over the channel. LSPs have several properties (like - less sensitivity to quantisation noise) that make them superior to - direct quantisation of {ak}. - - A(z) is a polynomial of order lpcrdr with {ak} as the coefficients. - - A(z) is transformed to P(z) and Q(z) (using a substitution and some - algebra), to obtain something like: - - A(z) = 0.5[P(z)(z+z^-1) + Q(z)(z-z^-1)] (1) - - As you can imagine A(z) has complex zeros all over the z-plane. P(z) - and Q(z) have the very neat property of only having zeros _on_ the - unit circle. So to find them we take a test point z=exp(jw) and - evaluate P (exp(jw)) and Q(exp(jw)) using a grid of points between 0 - and pi. - - The zeros (roots) of P(z) also happen to alternate, which is why we - swap coefficients as we find roots. So the process of finding the - LSP frequencies is basically finding the roots of 5th order - polynomials. - - The root so P(z) and Q(z) occur in symmetrical pairs at +/-w, hence - the name Line Spectrum Pairs (LSPs). - - To convert back to ak we just evaluate (1), "clocking" an impulse - thru it lpcrdr times gives us the impulse response of A(z) which is - {ak}. - -\*---------------------------------------------------------------------------*/ - - -#include "config.h" - - -#include <math.h> -#include "lsp.h" -#include "stack_alloc.h" -#include "math_approx.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 /* pi */ -#endif - -#ifndef NULL -#define NULL 0 -#endif - -#ifdef FIXED_POINT - -#define FREQ_SCALE 16384 - -/*#define ANGLE2X(a) (32768*cos(((a)/8192.)))*/ -#define ANGLE2X(a) (SHL16(spx_cos(a),2)) - -/*#define X2ANGLE(x) (acos(.00006103515625*(x))*LSP_SCALING)*/ -#define X2ANGLE(x) (spx_acos(x)) - -#ifdef BFIN_ASM -#include "lsp_bfin.h" -#endif - -#else - -/*#define C1 0.99940307 -#define C2 -0.49558072 -#define C3 0.03679168*/ - -#define FREQ_SCALE 1. -#define ANGLE2X(a) (spx_cos(a)) -#define X2ANGLE(x) (acos(x)) - -#endif - - -/*---------------------------------------------------------------------------*\ - - FUNCTION....: cheb_poly_eva() - - AUTHOR......: David Rowe - DATE CREATED: 24/2/93 - - This function evaluates a series of Chebyshev polynomials - -\*---------------------------------------------------------------------------*/ - -#ifdef FIXED_POINT - -#ifndef OVERRIDE_CHEB_POLY_EVA -static inline spx_word32_t cheb_poly_eva( - spx_word16_t *coef, /* P or Q coefs in Q13 format */ - spx_word16_t x, /* cos of freq (-1.0 to 1.0) in Q14 format */ - int m, /* LPC order/2 */ - char *stack -) -{ - int i; - spx_word16_t b0, b1; - spx_word32_t sum; - - /*Prevents overflows*/ - if (x>16383) - x = 16383; - if (x<-16383) - x = -16383; - - /* Initialise values */ - b1=16384; - b0=x; - - /* Evaluate Chebyshev series formulation usin g iterative approach */ - sum = ADD32(EXTEND32(coef[m]), EXTEND32(MULT16_16_P14(coef[m-1],x))); - for(i=2;i<=m;i++) - { - spx_word16_t tmp=b0; - b0 = SUB16(MULT16_16_Q13(x,b0), b1); - b1 = tmp; - sum = ADD32(sum, EXTEND32(MULT16_16_P14(coef[m-i],b0))); - } - - return sum; -} -#endif - -#else - -static float cheb_poly_eva(spx_word32_t *coef, spx_word16_t x, int m, char *stack) -{ - int k; - float b0, b1, tmp; - - /* Initial conditions */ - b0=0; /* b_(m+1) */ - b1=0; /* b_(m+2) */ - - x*=2; - - /* Calculate the b_(k) */ - for(k=m;k>0;k--) - { - tmp=b0; /* tmp holds the previous value of b0 */ - b0=x*b0-b1+coef[m-k]; /* b0 holds its new value based on b0 and b1 */ - b1=tmp; /* b1 holds the previous value of b0 */ - } - - return(-b1+.5*x*b0+coef[m]); -} -#endif - -/*---------------------------------------------------------------------------*\ - - FUNCTION....: lpc_to_lsp() - - AUTHOR......: David Rowe - DATE CREATED: 24/2/93 - - This function converts LPC coefficients to LSP - coefficients. - -\*---------------------------------------------------------------------------*/ - -#ifdef FIXED_POINT -#define SIGN_CHANGE(a,b) (((a)&0x70000000)^((b)&0x70000000)||(b==0)) -#else -#define SIGN_CHANGE(a,b) (((a)*(b))<0.0) -#endif - - -int lpc_to_lsp (spx_coef_t *a,int lpcrdr,spx_lsp_t *freq,int nb,spx_word16_t delta, char *stack) -/* float *a lpc coefficients */ -/* int lpcrdr order of LPC coefficients (10) */ -/* float *freq LSP frequencies in the x domain */ -/* int nb number of sub-intervals (4) */ -/* float delta grid spacing interval (0.02) */ - - -{ - spx_word16_t temp_xr,xl,xr,xm=0; - spx_word32_t psuml,psumr,psumm,temp_psumr/*,temp_qsumr*/; - int i,j,m,flag,k; - VARDECL(spx_word32_t *Q); /* ptrs for memory allocation */ - VARDECL(spx_word32_t *P); - VARDECL(spx_word16_t *Q16); /* ptrs for memory allocation */ - VARDECL(spx_word16_t *P16); - spx_word32_t *px; /* ptrs of respective P'(z) & Q'(z) */ - spx_word32_t *qx; - spx_word32_t *p; - spx_word32_t *q; - spx_word16_t *pt; /* ptr used for cheb_poly_eval() - whether P' or Q' */ - int roots=0; /* DR 8/2/94: number of roots found */ - flag = 1; /* program is searching for a root when, - 1 else has found one */ - m = lpcrdr/2; /* order of P'(z) & Q'(z) polynomials */ - - /* Allocate memory space for polynomials */ - ALLOC(Q, (m+1), spx_word32_t); - ALLOC(P, (m+1), spx_word32_t); - - /* determine P'(z)'s and Q'(z)'s coefficients where - P'(z) = P(z)/(1 + z^(-1)) and Q'(z) = Q(z)/(1-z^(-1)) */ - - px = P; /* initialise ptrs */ - qx = Q; - p = px; - q = qx; - -#ifdef FIXED_POINT - *px++ = LPC_SCALING; - *qx++ = LPC_SCALING; - for(i=0;i<m;i++){ - *px++ = SUB32(ADD32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *p++); - *qx++ = ADD32(SUB32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *q++); - } - px = P; - qx = Q; - for(i=0;i<m;i++) - { - /*if (fabs(*px)>=32768) - speex_warning_int("px", *px); - if (fabs(*qx)>=32768) - speex_warning_int("qx", *qx);*/ - *px = PSHR32(*px,2); - *qx = PSHR32(*qx,2); - px++; - qx++; - } - /* The reason for this lies in the way cheb_poly_eva() is implemented for fixed-point */ - P[m] = PSHR32(P[m],3); - Q[m] = PSHR32(Q[m],3); -#else - *px++ = LPC_SCALING; - *qx++ = LPC_SCALING; - for(i=0;i<m;i++){ - *px++ = (a[i]+a[lpcrdr-1-i]) - *p++; - *qx++ = (a[i]-a[lpcrdr-1-i]) + *q++; - } - px = P; - qx = Q; - for(i=0;i<m;i++){ - *px = 2**px; - *qx = 2**qx; - px++; - qx++; - } -#endif - - px = P; /* re-initialise ptrs */ - qx = Q; - - /* now that we have computed P and Q convert to 16 bits to - speed up cheb_poly_eval */ - - ALLOC(P16, m+1, spx_word16_t); - ALLOC(Q16, m+1, spx_word16_t); - - for (i=0;i<m+1;i++) - { - P16[i] = P[i]; - Q16[i] = Q[i]; - } - - /* Search for a zero in P'(z) polynomial first and then alternate to Q'(z). - Keep alternating between the two polynomials as each zero is found */ - - xr = 0; /* initialise xr to zero */ - xl = FREQ_SCALE; /* start at point xl = 1 */ - - for(j=0;j<lpcrdr;j++){ - if(j&1) /* determines whether P' or Q' is eval. */ - pt = Q16; - else - pt = P16; - - psuml = cheb_poly_eva(pt,xl,m,stack); /* evals poly. at xl */ - flag = 1; - while(flag && (xr >= -FREQ_SCALE)){ - spx_word16_t dd; - /* Modified by JMV to provide smaller steps around x=+-1 */ -#ifdef FIXED_POINT - dd = MULT16_16_Q15(delta,SUB16(FREQ_SCALE, MULT16_16_Q14(MULT16_16_Q14(xl,xl),14000))); - if (psuml<512 && psuml>-512) - dd = PSHR16(dd,1); -#else - dd=delta*(1-.9*xl*xl); - if (fabs(psuml)<.2) - dd *= .5; -#endif - xr = SUB16(xl, dd); /* interval spacing */ - psumr = cheb_poly_eva(pt,xr,m,stack);/* poly(xl-delta_x) */ - temp_psumr = psumr; - temp_xr = xr; - - /* if no sign change increment xr and re-evaluate poly(xr). Repeat til - sign change. - if a sign change has occurred the interval is bisected and then - checked again for a sign change which determines in which - interval the zero lies in. - If there is no sign change between poly(xm) and poly(xl) set interval - between xm and xr else set interval between xl and xr and repeat till - root is located within the specified limits */ - - if(SIGN_CHANGE(psumr,psuml)) - { - roots++; - - psumm=psuml; - for(k=0;k<=nb;k++){ -#ifdef FIXED_POINT - xm = ADD16(PSHR16(xl,1),PSHR16(xr,1)); /* bisect the interval */ -#else - xm = .5*(xl+xr); /* bisect the interval */ -#endif - psumm=cheb_poly_eva(pt,xm,m,stack); - /*if(psumm*psuml>0.)*/ - if(!SIGN_CHANGE(psumm,psuml)) - { - psuml=psumm; - xl=xm; - } else { - psumr=psumm; - xr=xm; - } - } - - /* once zero is found, reset initial interval to xr */ - freq[j] = X2ANGLE(xm); - xl = xm; - flag = 0; /* reset flag for next search */ - } - else{ - psuml=temp_psumr; - xl=temp_xr; - } - } - } - return(roots); -} - -/*---------------------------------------------------------------------------*\ - - FUNCTION....: lsp_to_lpc() - - AUTHOR......: David Rowe - DATE CREATED: 24/2/93 - - Converts LSP coefficients to LPC coefficients. - -\*---------------------------------------------------------------------------*/ - -#ifdef FIXED_POINT - -void lsp_to_lpc(spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack) -/* float *freq array of LSP frequencies in the x domain */ -/* float *ak array of LPC coefficients */ -/* int lpcrdr order of LPC coefficients */ -{ - int i,j; - spx_word32_t xout1,xout2,xin; - spx_word32_t mult, a; - VARDECL(spx_word16_t *freqn); - VARDECL(spx_word32_t **xp); - VARDECL(spx_word32_t *xpmem); - VARDECL(spx_word32_t **xq); - VARDECL(spx_word32_t *xqmem); - int m = lpcrdr>>1; - - /* - - Reconstruct P(z) and Q(z) by cascading second order polynomials - in form 1 - 2cos(w)z(-1) + z(-2), where w is the LSP frequency. - In the time domain this is: - - y(n) = x(n) - 2cos(w)x(n-1) + x(n-2) - - This is what the ALLOCS below are trying to do: - - int xp[m+1][lpcrdr+1+2]; // P matrix in QIMP - int xq[m+1][lpcrdr+1+2]; // Q matrix in QIMP - - These matrices store the output of each stage on each row. The - final (m-th) row has the output of the final (m-th) cascaded - 2nd order filter. The first row is the impulse input to the - system (not written as it is known). - - The version below takes advantage of the fact that a lot of the - outputs are zero or known, for example if we put an inpulse - into the first section the "clock" it 10 times only the first 3 - outputs samples are non-zero (it's an FIR filter). - */ - - ALLOC(xp, (m+1), spx_word32_t*); - ALLOC(xpmem, (m+1)*(lpcrdr+1+2), spx_word32_t); - - ALLOC(xq, (m+1), spx_word32_t*); - ALLOC(xqmem, (m+1)*(lpcrdr+1+2), spx_word32_t); - - for(i=0; i<=m; i++) { - xp[i] = xpmem + i*(lpcrdr+1+2); - xq[i] = xqmem + i*(lpcrdr+1+2); - } - - /* work out 2cos terms in Q14 */ - - ALLOC(freqn, lpcrdr, spx_word16_t); - for (i=0;i<lpcrdr;i++) - freqn[i] = ANGLE2X(freq[i]); - - #define QIMP 21 /* scaling for impulse */ - - xin = SHL32(EXTEND32(1), (QIMP-1)); /* 0.5 in QIMP format */ - - /* first col and last non-zero values of each row are trivial */ - - for(i=0;i<=m;i++) { - xp[i][1] = 0; - xp[i][2] = xin; - xp[i][2+2*i] = xin; - xq[i][1] = 0; - xq[i][2] = xin; - xq[i][2+2*i] = xin; - } - - /* 2nd row (first output row) is trivial */ - - xp[1][3] = -MULT16_32_Q14(freqn[0],xp[0][2]); - xq[1][3] = -MULT16_32_Q14(freqn[1],xq[0][2]); - - xout1 = xout2 = 0; - - /* now generate remaining rows */ - - for(i=1;i<m;i++) { - - for(j=1;j<2*(i+1)-1;j++) { - mult = MULT16_32_Q14(freqn[2*i],xp[i][j+1]); - xp[i+1][j+2] = ADD32(SUB32(xp[i][j+2], mult), xp[i][j]); - mult = MULT16_32_Q14(freqn[2*i+1],xq[i][j+1]); - xq[i+1][j+2] = ADD32(SUB32(xq[i][j+2], mult), xq[i][j]); - } - - /* for last col xp[i][j+2] = xq[i][j+2] = 0 */ - - mult = MULT16_32_Q14(freqn[2*i],xp[i][j+1]); - xp[i+1][j+2] = SUB32(xp[i][j], mult); - mult = MULT16_32_Q14(freqn[2*i+1],xq[i][j+1]); - xq[i+1][j+2] = SUB32(xq[i][j], mult); - } - - /* process last row to extra a{k} */ - - for(j=1;j<=lpcrdr;j++) { - int shift = QIMP-13; - - /* final filter sections */ - a = PSHR32(xp[m][j+2] + xout1 + xq[m][j+2] - xout2, shift); - xout1 = xp[m][j+2]; - xout2 = xq[m][j+2]; - - /* hard limit ak's to +/- 32767 */ - - if (a < -32767) a = -32767; - if (a > 32767) a = 32767; - ak[j-1] = (short)a; - - } - -} - -#else - -void lsp_to_lpc(spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack) -/* float *freq array of LSP frequencies in the x domain */ -/* float *ak array of LPC coefficients */ -/* int lpcrdr order of LPC coefficients */ - - -{ - int i,j; - float xout1,xout2,xin1,xin2; - VARDECL(float *Wp); - float *pw,*n1,*n2,*n3,*n4=NULL; - VARDECL(float *x_freq); - int m = lpcrdr>>1; - - ALLOC(Wp, 4*m+2, float); - pw = Wp; - - /* initialise contents of array */ - - for(i=0;i<=4*m+1;i++){ /* set contents of buffer to 0 */ - *pw++ = 0.0; - } - - /* Set pointers up */ - - pw = Wp; - xin1 = 1.0; - xin2 = 1.0; - - ALLOC(x_freq, lpcrdr, float); - for (i=0;i<lpcrdr;i++) - x_freq[i] = ANGLE2X(freq[i]); - - /* reconstruct P(z) and Q(z) by cascading second order - polynomials in form 1 - 2xz(-1) +z(-2), where x is the - LSP coefficient */ - - for(j=0;j<=lpcrdr;j++){ - int i2=0; - for(i=0;i<m;i++,i2+=2){ - n1 = pw+(i*4); - n2 = n1 + 1; - n3 = n2 + 1; - n4 = n3 + 1; - xout1 = xin1 - 2.f*x_freq[i2] * *n1 + *n2; - xout2 = xin2 - 2.f*x_freq[i2+1] * *n3 + *n4; - *n2 = *n1; - *n4 = *n3; - *n1 = xin1; - *n3 = xin2; - xin1 = xout1; - xin2 = xout2; - } - xout1 = xin1 + *(n4+1); - xout2 = xin2 - *(n4+2); - if (j>0) - ak[j-1] = (xout1 + xout2)*0.5f; - *(n4+1) = xin1; - *(n4+2) = xin2; - - xin1 = 0.0; - xin2 = 0.0; - } - -} -#endif - - -#ifdef FIXED_POINT - -/*Makes sure the LSPs are stable*/ -void lsp_enforce_margin(spx_lsp_t *lsp, int len, spx_word16_t margin) -{ - int i; - spx_word16_t m = margin; - spx_word16_t m2 = 25736-margin; - - if (lsp[0]<m) - lsp[0]=m; - if (lsp[len-1]>m2) - lsp[len-1]=m2; - for (i=1;i<len-1;i++) - { - if (lsp[i]<lsp[i-1]+m) - lsp[i]=lsp[i-1]+m; - - if (lsp[i]>lsp[i+1]-m) - lsp[i]= SHR16(lsp[i],1) + SHR16(lsp[i+1]-m,1); - } -} - - -void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *interp_lsp, int len, int subframe, int nb_subframes) -{ - int i; - spx_word16_t tmp = DIV32_16(SHL32(EXTEND32(1 + subframe),14),nb_subframes); - spx_word16_t tmp2 = 16384-tmp; - for (i=0;i<len;i++) - { - interp_lsp[i] = MULT16_16_P14(tmp2,old_lsp[i]) + MULT16_16_P14(tmp,new_lsp[i]); - } -} - -#else - -/*Makes sure the LSPs are stable*/ -void lsp_enforce_margin(spx_lsp_t *lsp, int len, spx_word16_t margin) -{ - int i; - if (lsp[0]<LSP_SCALING*margin) - lsp[0]=LSP_SCALING*margin; - if (lsp[len-1]>LSP_SCALING*(M_PI-margin)) - lsp[len-1]=LSP_SCALING*(M_PI-margin); - for (i=1;i<len-1;i++) - { - if (lsp[i]<lsp[i-1]+LSP_SCALING*margin) - lsp[i]=lsp[i-1]+LSP_SCALING*margin; - - if (lsp[i]>lsp[i+1]-LSP_SCALING*margin) - lsp[i]= .5f* (lsp[i] + lsp[i+1]-LSP_SCALING*margin); - } -} - - -void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *interp_lsp, int len, int subframe, int nb_subframes) -{ - int i; - float tmp = (1.0f + subframe)/nb_subframes; - for (i=0;i<len;i++) - { - interp_lsp[i] = (1-tmp)*old_lsp[i] + tmp*new_lsp[i]; - } -} - -#endif diff --git a/drivers/speex/lsp.h b/drivers/speex/lsp.h deleted file mode 100644 index b55bd42f2c..0000000000 --- a/drivers/speex/lsp.h +++ /dev/null @@ -1,64 +0,0 @@ -/*---------------------------------------------------------------------------*\ -Original Copyright - FILE........: AK2LSPD.H - TYPE........: Turbo C header file - COMPANY.....: Voicetronix - AUTHOR......: James Whitehall - DATE CREATED: 21/11/95 - -Modified by Jean-Marc Valin - - This file contains functions for converting Linear Prediction - Coefficients (LPC) to Line Spectral Pair (LSP) and back. Note that the - LSP coefficients are not in radians format but in the x domain of the - unit circle. - -\*---------------------------------------------------------------------------*/ -/** - @file lsp.h - @brief Line Spectral Pair (LSP) functions. -*/ -/* Speex License: - - 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 the Xiph.org Foundation nor the names of its - 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 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 __AK2LSPD__ -#define __AK2LSPD__ - -#include "arch.h" - -int lpc_to_lsp (spx_coef_t *a, int lpcrdr, spx_lsp_t *freq, int nb, spx_word16_t delta, char *stack); -void lsp_to_lpc(spx_lsp_t *freq, spx_coef_t *ak, int lpcrdr, char *stack); - -/*Added by JMV*/ -void lsp_enforce_margin(spx_lsp_t *lsp, int len, spx_word16_t margin); - -void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *interp_lsp, int len, int subframe, int nb_subframes); - -#endif /* __AK2LSPD__ */ diff --git a/drivers/speex/lsp_bfin.h b/drivers/speex/lsp_bfin.h deleted file mode 100644 index 20e505287e..0000000000 --- a/drivers/speex/lsp_bfin.h +++ /dev/null @@ -1,89 +0,0 @@ -/* Copyright (C) 2006 David Rowe */ -/** - @file lsp_bfin.h - @author David Rowe - @brief LSP routines optimised for the Blackfin -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#define OVERRIDE_CHEB_POLY_EVA -#ifdef OVERRIDE_CHEB_POLY_EVA -static inline spx_word32_t cheb_poly_eva( - spx_word16_t *coef, /* P or Q coefs in Q13 format */ - spx_word16_t x, /* cos of freq (-1.0 to 1.0) in Q14 format */ - int m, /* LPC order/2 */ - char *stack -) -{ - spx_word32_t sum; - - __asm__ __volatile__ - ( - "P0 = %2;\n\t" /* P0: coef[m], coef[m-1],..., coef[0] */ - "R4 = 8192;\n\t" /* R4: rounding constant */ - "R2 = %1;\n\t" /* R2: x */ - - "R5 = -16383;\n\t" - "R2 = MAX(R2,R5);\n\t" - "R5 = 16383;\n\t" - "R2 = MIN(R2,R5);\n\t" - - "R3 = W[P0--] (X);\n\t" /* R3: sum */ - "R5 = W[P0--] (X);\n\t" - "R5 = R5.L * R2.L (IS);\n\t" - "R5 = R5 + R4;\n\t" - "R5 >>>= 14;\n\t" - "R3 = R3 + R5;\n\t" - - "R0 = R2;\n\t" /* R0: b0 */ - "R1 = 16384;\n\t" /* R1: b1 */ - "LOOP cpe%= LC0 = %3;\n\t" - "LOOP_BEGIN cpe%=;\n\t" - "P1 = R0;\n\t" - "R0 = R2.L * R0.L (IS) || R5 = W[P0--] (X);\n\t" - "R0 >>>= 13;\n\t" - "R0 = R0 - R1;\n\t" - "R1 = P1;\n\t" - "R5 = R5.L * R0.L (IS);\n\t" - "R5 = R5 + R4;\n\t" - "R5 >>>= 14;\n\t" - "R3 = R3 + R5;\n\t" - "LOOP_END cpe%=;\n\t" - "%0 = R3;\n\t" - : "=&d" (sum) - : "a" (x), "a" (&coef[m]), "a" (m-1) - : "R0", "R1", "R3", "R2", "R4", "R5", "P0", "P1" - ); - return sum; -} -#endif - - - diff --git a/drivers/speex/lsp_tables_nb.c b/drivers/speex/lsp_tables_nb.c deleted file mode 100644 index 16f2e1b64f..0000000000 --- a/drivers/speex/lsp_tables_nb.c +++ /dev/null @@ -1,360 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: lsp_tables_nb.c - Codebooks for LSPs in narrowband CELP mode - - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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. -*/ - -const signed char cdbk_nb[640]={ -30,19,38,34,40,32,46,43,58,43, -5,-18,-25,-40,-33,-55,-52,20,34,28, --20,-63,-97,-92,61,53,47,49,53,75, --14,-53,-77,-79,0,-3,-5,19,22,26, --9,-53,-55,66,90,72,85,68,74,52, --4,-41,-58,-31,-18,-31,27,32,30,18, -24,3,8,5,-12,-3,26,28,74,63, --2,-39,-67,-77,-106,-74,59,59,73,65, -44,40,71,72,82,83,98,88,89,60, --6,-31,-47,-48,-13,-39,-9,7,2,79, --1,-39,-60,-17,87,81,65,50,45,19, --21,-67,-91,-87,-41,-50,7,18,39,74, -10,-31,-28,39,24,13,23,5,56,45, -29,10,-5,-13,-11,-35,-18,-8,-10,-8, --25,-71,-77,-21,2,16,50,63,87,87, -5,-32,-40,-51,-68,0,12,6,54,34, -5,-12,32,52,68,64,69,59,65,45, -14,-16,-31,-40,-65,-67,41,49,47,37, --11,-52,-75,-84,-4,57,48,42,42,33, --11,-51,-68,-6,13,0,8,-8,26,32, --23,-53,0,36,56,76,97,105,111,97, --1,-28,-39,-40,-43,-54,-44,-40,-18,35, -16,-20,-19,-28,-42,29,47,38,74,45, -3,-29,-48,-62,-80,-104,-33,56,59,59, -10,17,46,72,84,101,117,123,123,106, --7,-33,-49,-51,-70,-67,-27,-31,70,67, --16,-62,-85,-20,82,71,86,80,85,74, --19,-58,-75,-45,-29,-33,-18,-25,45,57, --12,-42,-5,12,28,36,52,64,81,82, -13,-9,-27,-28,22,3,2,22,26,6, --6,-44,-51,2,15,10,48,43,49,34, --19,-62,-84,-89,-102,-24,8,17,61,68, -39,24,23,19,16,-5,12,15,27,15, --8,-44,-49,-60,-18,-32,-28,52,54,62, --8,-48,-77,-70,66,101,83,63,61,37, --12,-50,-75,-64,33,17,13,25,15,77, -1,-42,-29,72,64,46,49,31,61,44, --8,-47,-54,-46,-30,19,20,-1,-16,0, -16,-12,-18,-9,-26,-27,-10,-22,53,45, --10,-47,-75,-82,-105,-109,8,25,49,77, -50,65,114,117,124,118,115,96,90,61, --9,-45,-63,-60,-75,-57,8,11,20,29, -0,-35,-49,-43,40,47,35,40,55,38, --24,-76,-103,-112,-27,3,23,34,52,75, -8,-29,-43,12,63,38,35,29,24,8, -25,11,1,-15,-18,-43,-7,37,40,21, --20,-56,-19,-19,-4,-2,11,29,51,63, --2,-44,-62,-75,-89,30,57,51,74,51, -50,46,68,64,65,52,63,55,65,43, -18,-9,-26,-35,-55,-69,3,6,8,17, --15,-61,-86,-97,1,86,93,74,78,67, --1,-38,-66,-48,48,39,29,25,17,-1, -13,13,29,39,50,51,69,82,97,98, --2,-36,-46,-27,-16,-30,-13,-4,-7,-4, -25,-5,-11,-6,-25,-21,33,12,31,29, --8,-38,-52,-63,-68,-89,-33,-1,10,74, --2,-15,59,91,105,105,101,87,84,62, --7,-33,-50,-35,-54,-47,25,17,82,81, --13,-56,-83,21,58,31,42,25,72,65, --24,-66,-91,-56,9,-2,21,10,69,75, -2,-24,11,22,25,28,38,34,48,33, -7,-29,-26,17,15,-1,14,0,-2,0, --6,-41,-67,6,-2,-9,19,2,85,74, --22,-67,-84,-71,-50,3,11,-9,2,62}; - -const signed char cdbk_nb_low1[320]={ --34,-52,-15,45,2, -23,21,52,24,-33, --9,-1,9,-44,-41, --13,-17,44,22,-17, --6,-4,-1,22,38, -26,16,2,50,27, --35,-34,-9,-41,6, -0,-16,-34,51,8, --14,-31,-49,15,-33, -45,49,33,-11,-37, --62,-54,45,11,-5, --72,11,-1,-12,-11, -24,27,-11,-43,46, -43,33,-12,-9,-1, -1,-4,-23,-57,-71, -11,8,16,17,-8, --20,-31,-41,53,48, --16,3,65,-24,-8, --23,-32,-37,-32,-49, --10,-17,6,38,5, --9,-17,-46,8,52, -3,6,45,40,39, --7,-6,-34,-74,31, -8,1,-16,43,68, --11,-19,-31,4,6, -0,-6,-17,-16,-38, --16,-30,2,9,-39, --16,-1,43,-10,48, -3,3,-16,-31,-3, -62,68,43,13,3, --10,8,20,-56,12, -12,-2,-18,22,-15, --40,-36,1,7,41, -0,1,46,-6,-62, --4,-12,-2,-11,-83, --13,-2,91,33,-10, -0,4,-11,-16,79, -32,37,14,9,51, --21,-28,-56,-34,0, -21,9,-26,11,28, --42,-54,-23,-2,-15, -31,30,8,-39,-66, --39,-36,31,-28,-40, --46,35,40,22,24, -33,48,23,-34,14, -40,32,17,27,-3, -25,26,-13,-61,-17, -11,4,31,60,-6, --26,-41,-64,13,16, --26,54,31,-11,-23, --9,-11,-34,-71,-21, --34,-35,55,50,29, --22,-27,-50,-38,57, -33,42,57,48,26, -11,0,-49,-31,26, --4,-14,5,78,37, -17,0,-49,-12,-23, -26,14,2,2,-43, --17,-12,10,-8,-4, -8,18,12,-6,20, --12,-6,-13,-25,34, -15,40,49,7,8, -13,20,20,-19,-22, --2,-8,2,51,-51}; - -const signed char cdbk_nb_low2[320]={ --6,53,-21,-24,4, -26,17,-4,-37,25, -17,-36,-13,31,3, --6,27,15,-10,31, -28,26,-10,-10,-40, -16,-7,15,13,41, --9,0,-4,50,-6, --7,14,38,22,0, --48,2,1,-13,-19, -32,-3,-60,11,-17, --1,-24,-34,-1,35, --5,-27,28,44,13, -25,15,42,-11,15, -51,35,-36,20,8, --4,-12,-29,19,-47, -49,-15,-4,16,-29, --39,14,-30,4,25, --9,-5,-51,-14,-3, --40,-32,38,5,-9, --8,-4,-1,-22,71, --3,14,26,-18,-22, -24,-41,-25,-24,6, -23,19,-10,39,-26, --27,65,45,2,-7, --26,-8,22,-12,16, -15,16,-35,-5,33, --21,-8,0,23,33, -34,6,21,36,6, --7,-22,8,-37,-14, -31,38,11,-4,-3, --39,-32,-8,32,-23, --6,-12,16,20,-28, --4,23,13,-52,-1, -22,6,-33,-40,-6, -4,-62,13,5,-26, -35,39,11,2,57, --11,9,-20,-28,-33, -52,-5,-6,-2,22, --14,-16,-48,35,1, --58,20,13,33,-1, --74,56,-18,-22,-31, -12,6,-14,4,-2, --9,-47,10,-3,29, --17,-5,61,14,47, --12,2,72,-39,-17, -92,64,-53,-51,-15, --30,-38,-41,-29,-28, -27,9,36,9,-35, --42,81,-21,20,25, --16,-5,-17,-35,21, -15,-28,48,2,-2, -9,-19,29,-40,30, --18,-18,18,-16,-57, -15,-20,-12,-15,-37, --15,33,-39,21,-22, --13,35,11,13,-38, --63,29,23,-27,32, -18,3,-26,42,33, --64,-66,-17,16,56, -2,36,3,31,21, --41,-39,8,-57,14, -37,-2,19,-36,-19, --23,-29,-16,1,-3, --8,-10,31,64,-65}; - -const signed char cdbk_nb_high1[320]={ --26,-8,29,21,4, -19,-39,33,-7,-36, -56,54,48,40,29, --4,-24,-42,-66,-43, --60,19,-2,37,41, --10,-37,-60,-64,18, --22,77,73,40,25, -4,19,-19,-66,-2, -11,5,21,14,26, --25,-86,-4,18,1, -26,-37,10,37,-1, -24,-12,-59,-11,20, --6,34,-16,-16,42, -19,-28,-51,53,32, -4,10,62,21,-12, --34,27,4,-48,-48, --50,-49,31,-7,-21, --42,-25,-4,-43,-22, -59,2,27,12,-9, --6,-16,-8,-32,-58, --16,-29,-5,41,23, --30,-33,-46,-13,-10, --38,52,52,1,-17, --9,10,26,-25,-6, -33,-20,53,55,25, --32,-5,-42,23,21, -66,5,-28,20,9, -75,29,-7,-42,-39, -15,3,-23,21,6, -11,1,-29,14,63, -10,54,26,-24,-51, --49,7,-23,-51,15, --66,1,60,25,10, -0,-30,-4,-15,17, -19,59,40,4,-5, -33,6,-22,-58,-70, --5,23,-6,60,44, --29,-16,-47,-29,52, --19,50,28,16,35, -31,36,0,-21,6, -21,27,22,42,7, --66,-40,-8,7,19, -46,0,-4,60,36, -45,-7,-29,-6,-32, --39,2,6,-9,33, -20,-51,-34,18,-6, -19,6,11,5,-19, --29,-2,42,-11,-45, --21,-55,57,37,2, --14,-67,-16,-27,-38, -69,48,19,2,-17, -20,-20,-16,-34,-17, --25,-61,10,73,45, -16,-40,-64,-17,-29, --22,56,17,-39,8, --11,8,-25,-18,-13, --19,8,54,57,36, --17,-26,-4,6,-21, -40,42,-4,20,31, -53,10,-34,-53,31, --17,35,0,15,-6, --20,-63,-73,22,25, -29,17,8,-29,-39, --69,18,15,-15,-5}; - -const signed char cdbk_nb_high2[320]={ -11,47,16,-9,-46, --32,26,-64,34,-5, -38,-7,47,20,2, --73,-99,-3,-45,20, -70,-52,15,-6,-7, --82,31,21,47,51, -39,-3,9,0,-41, --7,-15,-54,2,0, -27,-31,9,-45,-22, --38,-24,-24,8,-33, -23,5,50,-36,-17, --18,-51,-2,13,19, -43,12,-15,-12,61, -38,38,7,13,0, -6,-1,3,62,9, -27,22,-33,38,-35, --9,30,-43,-9,-32, --1,4,-4,1,-5, --11,-8,38,31,11, --10,-42,-21,-37,1, -43,15,-13,-35,-19, --18,15,23,-26,59, -1,-21,53,8,-41, --50,-14,-28,4,21, -25,-28,-40,5,-40, --41,4,51,-33,-8, --8,1,17,-60,12, -25,-41,17,34,43, -19,45,7,-37,24, --15,56,-2,35,-10, -48,4,-47,-2,5, --5,-54,5,-3,-33, --10,30,-2,-44,-24, --38,9,-9,42,4, -6,-56,44,-16,9, --40,-26,18,-20,10, -28,-41,-21,-4,13, --18,32,-30,-3,37, -15,22,28,50,-40, -3,-29,-64,7,51, --19,-11,17,-27,-40, --64,24,-12,-7,-27, -3,37,48,-1,2, --9,-38,-34,46,1, -27,-6,19,-13,26, -10,34,20,25,40, -50,-6,-7,30,9, --24,0,-23,71,-61, -22,58,-34,-4,2, --49,-33,25,30,-8, --6,-16,77,2,38, --8,-35,-6,-30,56, -78,31,33,-20,13, --39,20,22,4,21, --8,4,-6,10,-83, --41,9,-25,-43,15, --7,-12,-34,-39,-37, --33,19,30,16,-33, -42,-25,25,-68,44, --15,-11,-4,23,50, -14,4,-39,-43,20, --30,60,9,-20,7, -16,19,-33,37,29, -16,-35,7,38,-27}; diff --git a/drivers/speex/ltp.c b/drivers/speex/ltp.c deleted file mode 100644 index 9134506c17..0000000000 --- a/drivers/speex/ltp.c +++ /dev/null @@ -1,839 +0,0 @@ -/* Copyright (C) 2002-2006 Jean-Marc Valin - File: ltp.c - Long-Term Prediction 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. - - - Neither the name of the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -#include "config.h" - - -#include <math.h> -#include "ltp.h" -#include "stack_alloc.h" -#include "filters.h" -#include <speex/speex_bits.h> -#include "math_approx.h" -#include "os_support.h" - -#ifndef NULL -#define NULL 0 -#endif - - -#ifdef _USE_SSE -#include "ltp_sse.h" -#elif defined (ARM4_ASM) || defined(ARM5E_ASM) -#include "ltp_arm4.h" -#elif defined (BFIN_ASM) -#include "ltp_bfin.h" -#endif - -#ifndef OVERRIDE_INNER_PROD -spx_word32_t inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len) -{ - spx_word32_t sum=0; - len >>= 2; - while(len--) - { - spx_word32_t part=0; - part = MAC16_16(part,*x++,*y++); - part = MAC16_16(part,*x++,*y++); - part = MAC16_16(part,*x++,*y++); - part = MAC16_16(part,*x++,*y++); - /* HINT: If you had a 40-bit accumulator, you could shift only at the end */ - sum = ADD32(sum,SHR32(part,6)); - } - return sum; -} -#endif - -#ifndef OVERRIDE_PITCH_XCORR -#if 0 /* HINT: Enable this for machines with enough registers (i.e. not x86) */ -void pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack) -{ - int i,j; - for (i=0;i<nb_pitch;i+=4) - { - /* Compute correlation*/ - /*corr[nb_pitch-1-i]=inner_prod(x, _y+i, len);*/ - spx_word32_t sum1=0; - spx_word32_t sum2=0; - spx_word32_t sum3=0; - spx_word32_t sum4=0; - const spx_word16_t *y = _y+i; - const spx_word16_t *x = _x; - spx_word16_t y0, y1, y2, y3; - /*y0=y[0];y1=y[1];y2=y[2];y3=y[3];*/ - y0=*y++; - y1=*y++; - y2=*y++; - y3=*y++; - for (j=0;j<len;j+=4) - { - spx_word32_t part1; - spx_word32_t part2; - spx_word32_t part3; - spx_word32_t part4; - part1 = MULT16_16(*x,y0); - part2 = MULT16_16(*x,y1); - part3 = MULT16_16(*x,y2); - part4 = MULT16_16(*x,y3); - x++; - y0=*y++; - part1 = MAC16_16(part1,*x,y1); - part2 = MAC16_16(part2,*x,y2); - part3 = MAC16_16(part3,*x,y3); - part4 = MAC16_16(part4,*x,y0); - x++; - y1=*y++; - part1 = MAC16_16(part1,*x,y2); - part2 = MAC16_16(part2,*x,y3); - part3 = MAC16_16(part3,*x,y0); - part4 = MAC16_16(part4,*x,y1); - x++; - y2=*y++; - part1 = MAC16_16(part1,*x,y3); - part2 = MAC16_16(part2,*x,y0); - part3 = MAC16_16(part3,*x,y1); - part4 = MAC16_16(part4,*x,y2); - x++; - y3=*y++; - - sum1 = ADD32(sum1,SHR32(part1,6)); - sum2 = ADD32(sum2,SHR32(part2,6)); - sum3 = ADD32(sum3,SHR32(part3,6)); - sum4 = ADD32(sum4,SHR32(part4,6)); - } - corr[nb_pitch-1-i]=sum1; - corr[nb_pitch-2-i]=sum2; - corr[nb_pitch-3-i]=sum3; - corr[nb_pitch-4-i]=sum4; - } - -} -#else -void pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack) -{ - int i; - for (i=0;i<nb_pitch;i++) - { - /* Compute correlation*/ - corr[nb_pitch-1-i]=inner_prod(_x, _y+i, len); - } - -} -#endif -#endif - -#ifndef OVERRIDE_COMPUTE_PITCH_ERROR -static SPEEX_INLINE spx_word32_t compute_pitch_error(spx_word16_t *C, spx_word16_t *g, spx_word16_t pitch_control) -{ - spx_word32_t sum = 0; - sum = ADD32(sum,MULT16_16(MULT16_16_16(g[0],pitch_control),C[0])); - sum = ADD32(sum,MULT16_16(MULT16_16_16(g[1],pitch_control),C[1])); - sum = ADD32(sum,MULT16_16(MULT16_16_16(g[2],pitch_control),C[2])); - sum = SUB32(sum,MULT16_16(MULT16_16_16(g[0],g[1]),C[3])); - sum = SUB32(sum,MULT16_16(MULT16_16_16(g[2],g[1]),C[4])); - sum = SUB32(sum,MULT16_16(MULT16_16_16(g[2],g[0]),C[5])); - sum = SUB32(sum,MULT16_16(MULT16_16_16(g[0],g[0]),C[6])); - sum = SUB32(sum,MULT16_16(MULT16_16_16(g[1],g[1]),C[7])); - sum = SUB32(sum,MULT16_16(MULT16_16_16(g[2],g[2]),C[8])); - return sum; -} -#endif - -#ifndef OVERRIDE_OPEN_LOOP_NBEST_PITCH -void open_loop_nbest_pitch(spx_word16_t *sw, int start, int end, int len, int *pitch, spx_word16_t *gain, int N, char *stack) -{ - int i,j,k; - VARDECL(spx_word32_t *best_score); - VARDECL(spx_word32_t *best_ener); - spx_word32_t e0; - VARDECL(spx_word32_t *corr); -#ifdef FIXED_POINT - /* In fixed-point, we need only one (temporary) array of 32-bit values and two (corr16, ener16) - arrays for (normalized) 16-bit values */ - VARDECL(spx_word16_t *corr16); - VARDECL(spx_word16_t *ener16); - spx_word32_t *energy; - int cshift=0, eshift=0; - int scaledown = 0; - ALLOC(corr16, end-start+1, spx_word16_t); - ALLOC(ener16, end-start+1, spx_word16_t); - ALLOC(corr, end-start+1, spx_word32_t); - energy = corr; -#else - /* In floating-point, we need to float arrays and no normalized copies */ - VARDECL(spx_word32_t *energy); - spx_word16_t *corr16; - spx_word16_t *ener16; - ALLOC(energy, end-start+2, spx_word32_t); - ALLOC(corr, end-start+1, spx_word32_t); - corr16 = corr; - ener16 = energy; -#endif - - ALLOC(best_score, N, spx_word32_t); - ALLOC(best_ener, N, spx_word32_t); - for (i=0;i<N;i++) - { - best_score[i]=-1; - best_ener[i]=0; - pitch[i]=start; - } - -#ifdef FIXED_POINT - for (i=-end;i<len;i++) - { - if (ABS16(sw[i])>16383) - { - scaledown=1; - break; - } - } - /* If the weighted input is close to saturation, then we scale it down */ - if (scaledown) - { - for (i=-end;i<len;i++) - { - sw[i]=SHR16(sw[i],1); - } - } -#endif - energy[0]=inner_prod(sw-start, sw-start, len); - e0=inner_prod(sw, sw, len); - for (i=start;i<end;i++) - { - /* Update energy for next pitch*/ - energy[i-start+1] = SUB32(ADD32(energy[i-start],SHR32(MULT16_16(sw[-i-1],sw[-i-1]),6)), SHR32(MULT16_16(sw[-i+len-1],sw[-i+len-1]),6)); - if (energy[i-start+1] < 0) - energy[i-start+1] = 0; - } - -#ifdef FIXED_POINT - eshift = normalize16(energy, ener16, 32766, end-start+1); -#endif - - /* In fixed-point, this actually overrites the energy array (aliased to corr) */ - pitch_xcorr(sw, sw-end, corr, len, end-start+1, stack); - -#ifdef FIXED_POINT - /* Normalize to 180 so we can square it and it still fits in 16 bits */ - cshift = normalize16(corr, corr16, 180, end-start+1); - /* If we scaled weighted input down, we need to scale it up again (OK, so we've just lost the LSB, who cares?) */ - if (scaledown) - { - for (i=-end;i<len;i++) - { - sw[i]=SHL16(sw[i],1); - } - } -#endif - - /* Search for the best pitch prediction gain */ - for (i=start;i<=end;i++) - { - spx_word16_t tmp = MULT16_16_16(corr16[i-start],corr16[i-start]); - /* Instead of dividing the tmp by the energy, we multiply on the other side */ - if (MULT16_16(tmp,best_ener[N-1])>MULT16_16(best_score[N-1],ADD16(1,ener16[i-start]))) - { - /* We can safely put it last and then check */ - best_score[N-1]=tmp; - best_ener[N-1]=ener16[i-start]+1; - pitch[N-1]=i; - /* Check if it comes in front of others */ - for (j=0;j<N-1;j++) - { - if (MULT16_16(tmp,best_ener[j])>MULT16_16(best_score[j],ADD16(1,ener16[i-start]))) - { - for (k=N-1;k>j;k--) - { - best_score[k]=best_score[k-1]; - best_ener[k]=best_ener[k-1]; - pitch[k]=pitch[k-1]; - } - best_score[j]=tmp; - best_ener[j]=ener16[i-start]+1; - pitch[j]=i; - break; - } - } - } - } - - /* Compute open-loop gain if necessary */ - if (gain) - { - for (j=0;j<N;j++) - { - spx_word16_t g; - i=pitch[j]; - g = DIV32(SHL32(EXTEND32(corr16[i-start]),cshift), 10+SHR32(MULT16_16(spx_sqrt(e0),spx_sqrt(SHL32(EXTEND32(ener16[i-start]),eshift))),6)); - /* FIXME: g = max(g,corr/energy) */ - if (g<0) - g = 0; - gain[j]=g; - } - } - - -} -#endif - -#ifndef OVERRIDE_PITCH_GAIN_SEARCH_3TAP_VQ -static int pitch_gain_search_3tap_vq( - const signed char *gain_cdbk, - int gain_cdbk_size, - spx_word16_t *C16, - spx_word16_t max_gain -) -{ - const signed char *ptr=gain_cdbk; - int best_cdbk=0; - spx_word32_t best_sum=-VERY_LARGE32; - spx_word32_t sum=0; - spx_word16_t g[3]; - spx_word16_t pitch_control=64; - spx_word16_t gain_sum; - int i; - - for (i=0;i<gain_cdbk_size;i++) { - - ptr = gain_cdbk+4*i; - g[0]=ADD16((spx_word16_t)ptr[0],32); - g[1]=ADD16((spx_word16_t)ptr[1],32); - g[2]=ADD16((spx_word16_t)ptr[2],32); - gain_sum = (spx_word16_t)ptr[3]; - - sum = compute_pitch_error(C16, g, pitch_control); - - if (sum>best_sum && gain_sum<=max_gain) { - best_sum=sum; - best_cdbk=i; - } - } - - return best_cdbk; -} -#endif - -/** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */ -static spx_word32_t pitch_gain_search_3tap( -const spx_word16_t target[], /* Target vector */ -const spx_coef_t ak[], /* LPCs for this subframe */ -const spx_coef_t awk1[], /* Weighted LPCs #1 for this subframe */ -const spx_coef_t awk2[], /* Weighted LPCs #2 for this subframe */ -spx_sig_t exc[], /* Excitation */ -const signed char *gain_cdbk, -int gain_cdbk_size, -int pitch, /* Pitch value */ -int p, /* Number of LPC coeffs */ -int nsf, /* Number of samples in subframe */ -SpeexBits *bits, -char *stack, -const spx_word16_t *exc2, -const spx_word16_t *r, -spx_word16_t *new_target, -int *cdbk_index, -int plc_tuning, -spx_word32_t cumul_gain, -int scaledown -) -{ - int i,j; - VARDECL(spx_word16_t *tmp1); - VARDECL(spx_word16_t *e); - spx_word16_t *x[3]; - spx_word32_t corr[3]; - spx_word32_t A[3][3]; - spx_word16_t gain[3]; - spx_word32_t err; - spx_word16_t max_gain=128; - int best_cdbk=0; - - ALLOC(tmp1, 3*nsf, spx_word16_t); - ALLOC(e, nsf, spx_word16_t); - - if (cumul_gain > 262144) - max_gain = 31; - - x[0]=tmp1; - x[1]=tmp1+nsf; - x[2]=tmp1+2*nsf; - - for (j=0;j<nsf;j++) - new_target[j] = target[j]; - - { - VARDECL(spx_mem_t *mm); - int pp=pitch-1; - ALLOC(mm, p, spx_mem_t); - for (j=0;j<nsf;j++) - { - if (j-pp<0) - e[j]=exc2[j-pp]; - else if (j-pp-pitch<0) - e[j]=exc2[j-pp-pitch]; - else - e[j]=0; - } -#ifdef FIXED_POINT - /* Scale target and excitation down if needed (avoiding overflow) */ - if (scaledown) - { - for (j=0;j<nsf;j++) - e[j] = SHR16(e[j],1); - for (j=0;j<nsf;j++) - new_target[j] = SHR16(new_target[j],1); - } -#endif - for (j=0;j<p;j++) - mm[j] = 0; - iir_mem16(e, ak, e, nsf, p, mm, stack); - for (j=0;j<p;j++) - mm[j] = 0; - filter_mem16(e, awk1, awk2, e, nsf, p, mm, stack); - for (j=0;j<nsf;j++) - x[2][j] = e[j]; - } - for (i=1;i>=0;i--) - { - spx_word16_t e0=exc2[-pitch-1+i]; -#ifdef FIXED_POINT - /* Scale excitation down if needed (avoiding overflow) */ - if (scaledown) - e0 = SHR16(e0,1); -#endif - x[i][0]=MULT16_16_Q14(r[0], e0); - for (j=0;j<nsf-1;j++) - x[i][j+1]=ADD32(x[i+1][j],MULT16_16_P14(r[j+1], e0)); - } - - for (i=0;i<3;i++) - corr[i]=inner_prod(x[i],new_target,nsf); - for (i=0;i<3;i++) - for (j=0;j<=i;j++) - A[i][j]=A[j][i]=inner_prod(x[i],x[j],nsf); - - { - spx_word32_t C[9]; -#ifdef FIXED_POINT - spx_word16_t C16[9]; -#else - spx_word16_t *C16=C; -#endif - C[0]=corr[2]; - C[1]=corr[1]; - C[2]=corr[0]; - C[3]=A[1][2]; - C[4]=A[0][1]; - C[5]=A[0][2]; - C[6]=A[2][2]; - C[7]=A[1][1]; - C[8]=A[0][0]; - - /*plc_tuning *= 2;*/ - if (plc_tuning<2) - plc_tuning=2; - if (plc_tuning>30) - plc_tuning=30; -#ifdef FIXED_POINT - C[0] = SHL32(C[0],1); - C[1] = SHL32(C[1],1); - C[2] = SHL32(C[2],1); - C[3] = SHL32(C[3],1); - C[4] = SHL32(C[4],1); - C[5] = SHL32(C[5],1); - C[6] = MAC16_32_Q15(C[6],MULT16_16_16(plc_tuning,655),C[6]); - C[7] = MAC16_32_Q15(C[7],MULT16_16_16(plc_tuning,655),C[7]); - C[8] = MAC16_32_Q15(C[8],MULT16_16_16(plc_tuning,655),C[8]); - normalize16(C, C16, 32767, 9); -#else - C[6]*=.5*(1+.02*plc_tuning); - C[7]*=.5*(1+.02*plc_tuning); - C[8]*=.5*(1+.02*plc_tuning); -#endif - - best_cdbk = pitch_gain_search_3tap_vq(gain_cdbk, gain_cdbk_size, C16, max_gain); - -#ifdef FIXED_POINT - gain[0] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4]); - gain[1] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4+1]); - gain[2] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4+2]); - /*printf ("%d %d %d %d\n",gain[0],gain[1],gain[2], best_cdbk);*/ -#else - gain[0] = 0.015625*gain_cdbk[best_cdbk*4] + .5; - gain[1] = 0.015625*gain_cdbk[best_cdbk*4+1]+ .5; - gain[2] = 0.015625*gain_cdbk[best_cdbk*4+2]+ .5; -#endif - *cdbk_index=best_cdbk; - } - - SPEEX_MEMSET(exc, 0, nsf); - for (i=0;i<3;i++) - { - int j; - int tmp1, tmp3; - int pp=pitch+1-i; - tmp1=nsf; - if (tmp1>pp) - tmp1=pp; - for (j=0;j<tmp1;j++) - exc[j]=MAC16_16(exc[j],SHL16(gain[2-i],7),exc2[j-pp]); - tmp3=nsf; - if (tmp3>pp+pitch) - tmp3=pp+pitch; - for (j=tmp1;j<tmp3;j++) - exc[j]=MAC16_16(exc[j],SHL16(gain[2-i],7),exc2[j-pp-pitch]); - } - for (i=0;i<nsf;i++) - { - spx_word32_t tmp = ADD32(ADD32(MULT16_16(gain[0],x[2][i]),MULT16_16(gain[1],x[1][i])), - MULT16_16(gain[2],x[0][i])); - new_target[i] = SUB16(new_target[i], EXTRACT16(PSHR32(tmp,6))); - } - err = inner_prod(new_target, new_target, nsf); - - return err; -} - -/** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */ -int pitch_search_3tap( -spx_word16_t target[], /* Target vector */ -spx_word16_t *sw, -spx_coef_t ak[], /* LPCs for this subframe */ -spx_coef_t awk1[], /* Weighted LPCs #1 for this subframe */ -spx_coef_t awk2[], /* Weighted LPCs #2 for this subframe */ -spx_sig_t exc[], /* Excitation */ -const void *par, -int start, /* Smallest pitch value allowed */ -int end, /* Largest pitch value allowed */ -spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ -int p, /* Number of LPC coeffs */ -int nsf, /* Number of samples in subframe */ -SpeexBits *bits, -char *stack, -spx_word16_t *exc2, -spx_word16_t *r, -int complexity, -int cdbk_offset, -int plc_tuning, -spx_word32_t *cumul_gain -) -{ - int i; - int cdbk_index, pitch=0, best_gain_index=0; - VARDECL(spx_sig_t *best_exc); - VARDECL(spx_word16_t *new_target); - VARDECL(spx_word16_t *best_target); - int best_pitch=0; - spx_word32_t err, best_err=-1; - int N; - const ltp_params *params; - const signed char *gain_cdbk; - int gain_cdbk_size; - int scaledown=0; - - VARDECL(int *nbest); - - params = (const ltp_params*) par; - gain_cdbk_size = 1<<params->gain_bits; - gain_cdbk = params->gain_cdbk + 4*gain_cdbk_size*cdbk_offset; - - N=complexity; - if (N>10) - N=10; - if (N<1) - N=1; - - ALLOC(nbest, N, int); - params = (const ltp_params*) par; - - if (end<start) - { - speex_bits_pack(bits, 0, params->pitch_bits); - speex_bits_pack(bits, 0, params->gain_bits); - SPEEX_MEMSET(exc, 0, nsf); - return start; - } - -#ifdef FIXED_POINT - /* Check if we need to scale everything down in the pitch search to avoid overflows */ - for (i=0;i<nsf;i++) - { - if (ABS16(target[i])>16383) - { - scaledown=1; - break; - } - } - for (i=-end;i<nsf;i++) - { - if (ABS16(exc2[i])>16383) - { - scaledown=1; - break; - } - } -#endif - if (N>end-start+1) - N=end-start+1; - if (end != start) - open_loop_nbest_pitch(sw, start, end, nsf, nbest, NULL, N, stack); - else - nbest[0] = start; - - ALLOC(best_exc, nsf, spx_sig_t); - ALLOC(new_target, nsf, spx_word16_t); - ALLOC(best_target, nsf, spx_word16_t); - - for (i=0;i<N;i++) - { - pitch=nbest[i]; - SPEEX_MEMSET(exc, 0, nsf); - err=pitch_gain_search_3tap(target, ak, awk1, awk2, exc, gain_cdbk, gain_cdbk_size, pitch, p, nsf, - bits, stack, exc2, r, new_target, &cdbk_index, plc_tuning, *cumul_gain, scaledown); - if (err<best_err || best_err<0) - { - SPEEX_COPY(best_exc, exc, nsf); - SPEEX_COPY(best_target, new_target, nsf); - best_err=err; - best_pitch=pitch; - best_gain_index=cdbk_index; - } - } - /*printf ("pitch: %d %d\n", best_pitch, best_gain_index);*/ - speex_bits_pack(bits, best_pitch-start, params->pitch_bits); - speex_bits_pack(bits, best_gain_index, params->gain_bits); -#ifdef FIXED_POINT - *cumul_gain = MULT16_32_Q13(SHL16(params->gain_cdbk[4*best_gain_index+3],8), MAX32(1024,*cumul_gain)); -#else - *cumul_gain = 0.03125*MAX32(1024,*cumul_gain)*params->gain_cdbk[4*best_gain_index+3]; -#endif - /*printf ("%f\n", cumul_gain);*/ - /*printf ("encode pitch: %d %d\n", best_pitch, best_gain_index);*/ - SPEEX_COPY(exc, best_exc, nsf); - SPEEX_COPY(target, best_target, nsf); -#ifdef FIXED_POINT - /* Scale target back up if needed */ - if (scaledown) - { - for (i=0;i<nsf;i++) - target[i]=SHL16(target[i],1); - } -#endif - return pitch; -} - -void pitch_unquant_3tap( -spx_word16_t exc[], /* Input excitation */ -spx_word32_t exc_out[], /* Output excitation */ -int start, /* Smallest pitch value allowed */ -int end, /* Largest pitch value allowed */ -spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ -const void *par, -int nsf, /* Number of samples in subframe */ -int *pitch_val, -spx_word16_t *gain_val, -SpeexBits *bits, -char *stack, -int count_lost, -int subframe_offset, -spx_word16_t last_pitch_gain, -int cdbk_offset -) -{ - int i; - int pitch; - int gain_index; - spx_word16_t gain[3]; - const signed char *gain_cdbk; - int gain_cdbk_size; - const ltp_params *params; - - params = (const ltp_params*) par; - gain_cdbk_size = 1<<params->gain_bits; - gain_cdbk = params->gain_cdbk + 4*gain_cdbk_size*cdbk_offset; - - pitch = speex_bits_unpack_unsigned(bits, params->pitch_bits); - pitch += start; - gain_index = speex_bits_unpack_unsigned(bits, params->gain_bits); - /*printf ("decode pitch: %d %d\n", pitch, gain_index);*/ -#ifdef FIXED_POINT - gain[0] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4]); - gain[1] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4+1]); - gain[2] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4+2]); -#else - gain[0] = 0.015625*gain_cdbk[gain_index*4]+.5; - gain[1] = 0.015625*gain_cdbk[gain_index*4+1]+.5; - gain[2] = 0.015625*gain_cdbk[gain_index*4+2]+.5; -#endif - - if (count_lost && pitch > subframe_offset) - { - spx_word16_t gain_sum; - if (1) { -#ifdef FIXED_POINT - spx_word16_t tmp = count_lost < 4 ? last_pitch_gain : SHR16(last_pitch_gain,1); - if (tmp>62) - tmp=62; -#else - spx_word16_t tmp = count_lost < 4 ? last_pitch_gain : 0.5 * last_pitch_gain; - if (tmp>.95) - tmp=.95; -#endif - gain_sum = gain_3tap_to_1tap(gain); - - if (gain_sum > tmp) - { - spx_word16_t fact = DIV32_16(SHL32(EXTEND32(tmp),14),gain_sum); - for (i=0;i<3;i++) - gain[i]=MULT16_16_Q14(fact,gain[i]); - } - - } - - } - - *pitch_val = pitch; - gain_val[0]=gain[0]; - gain_val[1]=gain[1]; - gain_val[2]=gain[2]; - gain[0] = SHL16(gain[0],7); - gain[1] = SHL16(gain[1],7); - gain[2] = SHL16(gain[2],7); - SPEEX_MEMSET(exc_out, 0, nsf); - for (i=0;i<3;i++) - { - int j; - int tmp1, tmp3; - int pp=pitch+1-i; - tmp1=nsf; - if (tmp1>pp) - tmp1=pp; - for (j=0;j<tmp1;j++) - exc_out[j]=MAC16_16(exc_out[j],gain[2-i],exc[j-pp]); - tmp3=nsf; - if (tmp3>pp+pitch) - tmp3=pp+pitch; - for (j=tmp1;j<tmp3;j++) - exc_out[j]=MAC16_16(exc_out[j],gain[2-i],exc[j-pp-pitch]); - } - /*for (i=0;i<nsf;i++) - exc[i]=PSHR32(exc32[i],13);*/ -} - - -/** Forced pitch delay and gain */ -int forced_pitch_quant( -spx_word16_t target[], /* Target vector */ -spx_word16_t *sw, -spx_coef_t ak[], /* LPCs for this subframe */ -spx_coef_t awk1[], /* Weighted LPCs #1 for this subframe */ -spx_coef_t awk2[], /* Weighted LPCs #2 for this subframe */ -spx_sig_t exc[], /* Excitation */ -const void *par, -int start, /* Smallest pitch value allowed */ -int end, /* Largest pitch value allowed */ -spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ -int p, /* Number of LPC coeffs */ -int nsf, /* Number of samples in subframe */ -SpeexBits *bits, -char *stack, -spx_word16_t *exc2, -spx_word16_t *r, -int complexity, -int cdbk_offset, -int plc_tuning, -spx_word32_t *cumul_gain -) -{ - int i; - VARDECL(spx_word16_t *res); - ALLOC(res, nsf, spx_word16_t); -#ifdef FIXED_POINT - if (pitch_coef>63) - pitch_coef=63; -#else - if (pitch_coef>.99) - pitch_coef=.99; -#endif - for (i=0;i<nsf&&i<start;i++) - { - exc[i]=MULT16_16(SHL16(pitch_coef, 7),exc2[i-start]); - } - for (;i<nsf;i++) - { - exc[i]=MULT16_32_Q15(SHL16(pitch_coef, 9),exc[i-start]); - } - for (i=0;i<nsf;i++) - res[i] = EXTRACT16(PSHR32(exc[i], SIG_SHIFT-1)); - syn_percep_zero16(res, ak, awk1, awk2, res, nsf, p, stack); - for (i=0;i<nsf;i++) - target[i]=EXTRACT16(SATURATE(SUB32(EXTEND32(target[i]),EXTEND32(res[i])),32700)); - return start; -} - -/** Unquantize forced pitch delay and gain */ -void forced_pitch_unquant( -spx_word16_t exc[], /* Input excitation */ -spx_word32_t exc_out[], /* Output excitation */ -int start, /* Smallest pitch value allowed */ -int end, /* Largest pitch value allowed */ -spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ -const void *par, -int nsf, /* Number of samples in subframe */ -int *pitch_val, -spx_word16_t *gain_val, -SpeexBits *bits, -char *stack, -int count_lost, -int subframe_offset, -spx_word16_t last_pitch_gain, -int cdbk_offset -) -{ - int i; -#ifdef FIXED_POINT - if (pitch_coef>63) - pitch_coef=63; -#else - if (pitch_coef>.99) - pitch_coef=.99; -#endif - for (i=0;i<nsf;i++) - { - exc_out[i]=MULT16_16(exc[i-start],SHL16(pitch_coef,7)); - exc[i] = EXTRACT16(PSHR32(exc_out[i],13)); - } - *pitch_val = start; - gain_val[0]=gain_val[2]=0; - gain_val[1] = pitch_coef; -} diff --git a/drivers/speex/ltp.h b/drivers/speex/ltp.h deleted file mode 100644 index 1e435bc36e..0000000000 --- a/drivers/speex/ltp.h +++ /dev/null @@ -1,141 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @file ltp.h - @brief Long-Term Prediction 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. - - - Neither the name of the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#include <speex/speex_bits.h> -#include "arch.h" - -/** LTP parameters. */ -typedef struct { - const signed char *gain_cdbk; - int gain_bits; - int pitch_bits; -} ltp_params; - -#ifdef FIXED_POINT -#define gain_3tap_to_1tap(g) (ABS(g[1]) + (g[0]>0 ? g[0] : -SHR16(g[0],1)) + (g[2]>0 ? g[2] : -SHR16(g[2],1))) -#else -#define gain_3tap_to_1tap(g) (ABS(g[1]) + (g[0]>0 ? g[0] : -.5*g[0]) + (g[2]>0 ? g[2] : -.5*g[2])) -#endif - -spx_word32_t inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len); -void pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack); - -void open_loop_nbest_pitch(spx_word16_t *sw, int start, int end, int len, int *pitch, spx_word16_t *gain, int N, char *stack); - - -/** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */ -int pitch_search_3tap( -spx_word16_t target[], /* Target vector */ -spx_word16_t *sw, -spx_coef_t ak[], /* LPCs for this subframe */ -spx_coef_t awk1[], /* Weighted LPCs #1 for this subframe */ -spx_coef_t awk2[], /* Weighted LPCs #2 for this subframe */ -spx_sig_t exc[], /* Overlapping codebook */ -const void *par, -int start, /* Smallest pitch value allowed */ -int end, /* Largest pitch value allowed */ -spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ -int p, /* Number of LPC coeffs */ -int nsf, /* Number of samples in subframe */ -SpeexBits *bits, -char *stack, -spx_word16_t *exc2, -spx_word16_t *r, -int complexity, -int cdbk_offset, -int plc_tuning, -spx_word32_t *cumul_gain -); - -/*Unquantize adaptive codebook and update pitch contribution*/ -void pitch_unquant_3tap( -spx_word16_t exc[], /* Input excitation */ -spx_word32_t exc_out[], /* Output excitation */ -int start, /* Smallest pitch value allowed */ -int end, /* Largest pitch value allowed */ -spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ -const void *par, -int nsf, /* Number of samples in subframe */ -int *pitch_val, -spx_word16_t *gain_val, -SpeexBits *bits, -char *stack, -int lost, -int subframe_offset, -spx_word16_t last_pitch_gain, -int cdbk_offset -); - -/** Forced pitch delay and gain */ -int forced_pitch_quant( -spx_word16_t target[], /* Target vector */ -spx_word16_t *sw, -spx_coef_t ak[], /* LPCs for this subframe */ -spx_coef_t awk1[], /* Weighted LPCs #1 for this subframe */ -spx_coef_t awk2[], /* Weighted LPCs #2 for this subframe */ -spx_sig_t exc[], /* Excitation */ -const void *par, -int start, /* Smallest pitch value allowed */ -int end, /* Largest pitch value allowed */ -spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ -int p, /* Number of LPC coeffs */ -int nsf, /* Number of samples in subframe */ -SpeexBits *bits, -char *stack, -spx_word16_t *exc2, -spx_word16_t *r, -int complexity, -int cdbk_offset, -int plc_tuning, -spx_word32_t *cumul_gain -); - -/** Unquantize forced pitch delay and gain */ -void forced_pitch_unquant( -spx_word16_t exc[], /* Input excitation */ -spx_word32_t exc_out[], /* Output excitation */ -int start, /* Smallest pitch value allowed */ -int end, /* Largest pitch value allowed */ -spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ -const void *par, -int nsf, /* Number of samples in subframe */ -int *pitch_val, -spx_word16_t *gain_val, -SpeexBits *bits, -char *stack, -int lost, -int subframe_offset, -spx_word16_t last_pitch_gain, -int cdbk_offset -); diff --git a/drivers/speex/ltp_arm4.h b/drivers/speex/ltp_arm4.h deleted file mode 100644 index cdb94e603a..0000000000 --- a/drivers/speex/ltp_arm4.h +++ /dev/null @@ -1,187 +0,0 @@ -/* Copyright (C) 2004 Jean-Marc Valin */ -/** - @file ltp_arm4.h - @brief Long-Term Prediction functions (ARM4 version) -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#define OVERRIDE_INNER_PROD -spx_word32_t inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len) -{ - spx_word32_t sum1=0,sum2=0; - spx_word16_t *deadx, *deady; - int deadlen, dead1, dead2, dead3, dead4, dead5, dead6; - __asm__ __volatile__ ( - "\tldrsh %5, [%0], #2 \n" - "\tldrsh %6, [%1], #2 \n" - ".inner_prod_loop%=:\n" - "\tsub %7, %7, %7\n" - "\tsub %10, %10, %10\n" - - "\tldrsh %8, [%0], #2 \n" - "\tldrsh %9, [%1], #2 \n" - "\tmla %7, %5, %6, %7\n" - "\tldrsh %5, [%0], #2 \n" - "\tldrsh %6, [%1], #2 \n" - "\tmla %10, %8, %9, %10\n" - "\tldrsh %8, [%0], #2 \n" - "\tldrsh %9, [%1], #2 \n" - "\tmla %7, %5, %6, %7\n" - "\tldrsh %5, [%0], #2 \n" - "\tldrsh %6, [%1], #2 \n" - "\tmla %10, %8, %9, %10\n" - - "\tldrsh %8, [%0], #2 \n" - "\tldrsh %9, [%1], #2 \n" - "\tmla %7, %5, %6, %7\n" - "\tldrsh %5, [%0], #2 \n" - "\tldrsh %6, [%1], #2 \n" - "\tmla %10, %8, %9, %10\n" - "\tldrsh %8, [%0], #2 \n" - "\tldrsh %9, [%1], #2 \n" - "\tmla %7, %5, %6, %7\n" - "\tldrsh %5, [%0], #2 \n" - "\tldrsh %6, [%1], #2 \n" - "\tmla %10, %8, %9, %10\n" - - "\tsubs %4, %4, #1\n" - "\tadd %2, %2, %7, asr #5\n" - "\tadd %3, %3, %10, asr #5\n" - "\tbne .inner_prod_loop%=\n" - : "=r" (deadx), "=r" (deady), "+r" (sum1), "+r" (sum2), - "=r" (deadlen), "=r" (dead1), "=r" (dead2), "=r" (dead3), - "=r" (dead4), "=r" (dead5), "=r" (dead6) - : "0" (x), "1" (y), "4" (len>>3) - : "cc" - ); - return (sum1+sum2)>>1; -} - -#define OVERRIDE_PITCH_XCORR -void pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack) -{ - int i,j; - for (i=0;i<nb_pitch;i+=4) - { - /* Compute correlation*/ - //corr[nb_pitch-1-i]=inner_prod(x, _y+i, len); - spx_word32_t sum1=0; - spx_word32_t sum2=0; - spx_word32_t sum3=0; - spx_word32_t sum4=0; - const spx_word16_t *y = _y+i; - const spx_word16_t *x = _x; - spx_word32_t y0, y1, y2, y3; - y0=*y++; - y1=*y++; - y2=*y++; - y3=*y++; - for (j=0;j<len;j+=4) - { - spx_word32_t part1, part2, part3, part4, x0; - spx_word32_t dead1; - __asm__ __volatile__ ( -#ifdef SHORTCUTS - "\tldrsh %10, [%8], #4 \n" - "\tmul %4, %10, %0 \n" - "\tldrsh %15, [%8], #4 \n" - "\tmul %5, %10, %1 \n" - "\tldrsh %0, [%9], #2 \n" - "\tmul %6, %10, %2 \n" - "\tldrsh %1, [%9], #2 \n" - "\tmul %7, %10, %3 \n" - - - "\tmla %4, %15, %2, %4 \n" - "\tldrsh %2, [%9], #2 \n" - "\tmla %5, %15, %3, %5 \n" - "\tldrsh %3, [%9], #2 \n" - "\tmla %6, %15, %0, %6 \n" - "\tmla %7, %15, %1, %7 \n" - -#else - "\tldrsh %10, [%8], #2 \n" - "\tmul %4, %10, %0 \n" - "\tmul %5, %10, %1 \n" - "\tmul %6, %10, %2 \n" - "\tmul %7, %10, %3 \n" - - "\tldrsh %10, [%8], #2 \n" - "\tldrsh %0, [%9], #2 \n" - "\tmla %4, %10, %1, %4 \n" - "\tmla %5, %10, %2, %5 \n" - "\tmla %6, %10, %3, %6 \n" - "\tmla %7, %10, %0, %7 \n" - - "\tldrsh %10, [%8], #2 \n" - "\tldrsh %1, [%9], #2 \n" - "\tmla %4, %10, %2, %4 \n" - "\tmla %5, %10, %3, %5 \n" - "\tmla %6, %10, %0, %6 \n" - "\tmla %7, %10, %1, %7 \n" - - "\tldrsh %10, [%8], #2 \n" - "\tldrsh %2, [%9], #2 \n" - "\tmla %4, %10, %3, %4 \n" - "\tmla %5, %10, %0, %5 \n" - "\tmla %6, %10, %1, %6 \n" - "\tmla %7, %10, %2, %7 \n" - - "\tldrsh %3, [%9], #2 \n" -#endif - - "\tldr %10, %11 \n" - "\tldr %15, %12 \n" - "\tadd %4, %10, %4, asr #6 \n" - "\tstr %4, %11 \n" - "\tldr %10, %13 \n" - "\tadd %5, %15, %5, asr #6 \n" - "\tstr %5, %12 \n" - "\tldr %15, %14 \n" - "\tadd %6, %10, %6, asr #6 \n" - "\tadd %7, %15, %7, asr #6 \n" - "\tstr %6, %13 \n" - "\tstr %7, %14 \n" - - : "+r" (y0), "+r" (y1), "+r" (y2), "+r" (y3), - "=r" (part1), "=r" (part2), "=r" (part3), "=r" (part4), - "+r" (x), "+r" (y), "=r" (x0), "+m" (sum1), - "+m" (sum2), "+m" (sum3), "+m" (sum4), "=r" (dead1) - : - : "cc", "memory" - ); - } - corr[nb_pitch-1-i]=sum1; - corr[nb_pitch-2-i]=sum2; - corr[nb_pitch-3-i]=sum3; - corr[nb_pitch-4-i]=sum4; - } - -} diff --git a/drivers/speex/ltp_bfin.h b/drivers/speex/ltp_bfin.h deleted file mode 100644 index b530f85986..0000000000 --- a/drivers/speex/ltp_bfin.h +++ /dev/null @@ -1,419 +0,0 @@ -/* Copyright (C) 2005 Analog Devices */ -/** - @file ltp_bfin.h - @author Jean-Marc Valin - @brief Long-Term Prediction functions (Blackfin version) -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#define OVERRIDE_INNER_PROD -spx_word32_t inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len) -{ - spx_word32_t sum=0; - __asm__ __volatile__ ( - "P0 = %3;\n\t" - "P1 = %1;\n\t" - "P2 = %2;\n\t" - "I0 = P1;\n\t" - "I1 = P2;\n\t" - "L0 = 0;\n\t" - "L1 = 0;\n\t" - "A0 = 0;\n\t" - "R0.L = W[I0++] || R1.L = W[I1++];\n\t" - "LOOP inner%= LC0 = P0;\n\t" - "LOOP_BEGIN inner%=;\n\t" - "A0 += R0.L*R1.L (IS) || R0.L = W[I0++] || R1.L = W[I1++];\n\t" - "LOOP_END inner%=;\n\t" - "A0 += R0.L*R1.L (IS);\n\t" - "A0 = A0 >>> 6;\n\t" - "R0 = A0;\n\t" - "%0 = R0;\n\t" - : "=m" (sum) - : "m" (x), "m" (y), "d" (len-1) - : "P0", "P1", "P2", "R0", "R1", "A0", "I0", "I1", "L0", "L1", "R3" - ); - return sum; -} - -#define OVERRIDE_PITCH_XCORR -void pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack) -{ - corr += nb_pitch - 1; - __asm__ __volatile__ ( - "P2 = %0;\n\t" - "I0 = P2;\n\t" /* x in I0 */ - "B0 = P2;\n\t" /* x in B0 */ - "R0 = %3;\n\t" /* len in R0 */ - "P3 = %3;\n\t" - "P3 += -2;\n\t" /* len in R0 */ - "P4 = %4;\n\t" /* nb_pitch in R0 */ - "R1 = R0 << 1;\n\t" /* number of bytes in x */ - "L0 = R1;\n\t" - "P0 = %1;\n\t" - - "P1 = %2;\n\t" - "B1 = P1;\n\t" - "L1 = 0;\n\t" /*Disable looping on I1*/ - - "r0 = [I0++];\n\t" - "LOOP pitch%= LC0 = P4 >> 1;\n\t" - "LOOP_BEGIN pitch%=;\n\t" - "I1 = P0;\n\t" - "A1 = A0 = 0;\n\t" - "R1 = [I1++];\n\t" - "LOOP inner_prod%= LC1 = P3 >> 1;\n\t" - "LOOP_BEGIN inner_prod%=;\n\t" - "A1 += R0.L*R1.H, A0 += R0.L*R1.L (IS) || R1.L = W[I1++];\n\t" - "A1 += R0.H*R1.L, A0 += R0.H*R1.H (IS) || R1.H = W[I1++] || R0 = [I0++];\n\t" - "LOOP_END inner_prod%=;\n\t" - "A1 += R0.L*R1.H, A0 += R0.L*R1.L (IS) || R1.L = W[I1++];\n\t" - "A1 += R0.H*R1.L, A0 += R0.H*R1.H (IS) || R0 = [I0++];\n\t" - "A0 = A0 >>> 6;\n\t" - "A1 = A1 >>> 6;\n\t" - "R2 = A0, R3 = A1;\n\t" - "[P1--] = r2;\n\t" - "[P1--] = r3;\n\t" - "P0 += 4;\n\t" - "LOOP_END pitch%=;\n\t" - "L0 = 0;\n\t" - : : "m" (_x), "m" (_y), "m" (corr), "m" (len), "m" (nb_pitch) - : "A0", "A1", "P0", "P1", "P2", "P3", "P4", "R0", "R1", "R2", "R3", "I0", "I1", "L0", "L1", "B0", "B1", "memory" - ); -} - -#define OVERRIDE_COMPUTE_PITCH_ERROR -static inline spx_word32_t compute_pitch_error(spx_word16_t *C, spx_word16_t *g, spx_word16_t pitch_control) -{ - spx_word32_t sum; - __asm__ __volatile__ - ( - "A0 = 0;\n\t" - - "R0 = W[%1++];\n\t" - "R1.L = %2.L*%5.L (IS);\n\t" - "A0 += R1.L*R0.L (IS) || R0 = W[%1++];\n\t" - - "R1.L = %3.L*%5.L (IS);\n\t" - "A0 += R1.L*R0.L (IS) || R0 = W[%1++];\n\t" - - "R1.L = %4.L*%5.L (IS);\n\t" - "A0 += R1.L*R0.L (IS) || R0 = W[%1++];\n\t" - - "R1.L = %2.L*%3.L (IS);\n\t" - "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t" - - "R1.L = %4.L*%3.L (IS);\n\t" - "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t" - - "R1.L = %4.L*%2.L (IS);\n\t" - "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t" - - "R1.L = %2.L*%2.L (IS);\n\t" - "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t" - - "R1.L = %3.L*%3.L (IS);\n\t" - "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t" - - "R1.L = %4.L*%4.L (IS);\n\t" - "A0 -= R1.L*R0.L (IS);\n\t" - - "%0 = A0;\n\t" - : "=&D" (sum), "=a" (C) - : "d" (g[0]), "d" (g[1]), "d" (g[2]), "d" (pitch_control), "1" (C) - : "R0", "R1", "R2", "A0" - ); - return sum; -} - -#define OVERRIDE_OPEN_LOOP_NBEST_PITCH -#ifdef OVERRIDE_OPEN_LOOP_NBEST_PITCH -void open_loop_nbest_pitch(spx_word16_t *sw, int start, int end, int len, int *pitch, spx_word16_t *gain, int N, char *stack) -{ - int i,j,k; - VARDECL(spx_word32_t *best_score); - VARDECL(spx_word32_t *best_ener); - spx_word32_t e0; - VARDECL(spx_word32_t *corr); - VARDECL(spx_word32_t *energy); - - ALLOC(best_score, N, spx_word32_t); - ALLOC(best_ener, N, spx_word32_t); - ALLOC(corr, end-start+1, spx_word32_t); - ALLOC(energy, end-start+2, spx_word32_t); - - for (i=0;i<N;i++) - { - best_score[i]=-1; - best_ener[i]=0; - pitch[i]=start; - } - - energy[0]=inner_prod(sw-start, sw-start, len); - e0=inner_prod(sw, sw, len); - - /* energy update -------------------------------------*/ - - __asm__ __volatile__ - ( -" P0 = %0;\n\t" -" I1 = %1;\n\t" -" L1 = 0;\n\t" -" I2 = %2;\n\t" -" L2 = 0;\n\t" -" R2 = [P0++];\n\t" -" R3 = 0;\n\t" -" LSETUP (eu1, eu2) LC1 = %3;\n\t" -"eu1: R1.L = W [I1--] || R0.L = W [I2--] ;\n\t" -" R1 = R1.L * R1.L (IS);\n\t" -" R0 = R0.L * R0.L (IS);\n\t" -" R1 >>>= 6;\n\t" -" R1 = R1 + R2;\n\t" -" R0 >>>= 6;\n\t" -" R1 = R1 - R0;\n\t" -" R2 = MAX(R1,R3);\n\t" -"eu2: [P0++] = R2;\n\t" - : : "d" (energy), "d" (&sw[-start-1]), "d" (&sw[-start+len-1]), - "a" (end-start) - : "P0", "I1", "I2", "R0", "R1", "R2", "R3" -#if (__GNUC__ == 4) - , "LC1" -#endif - ); - - pitch_xcorr(sw, sw-end, corr, len, end-start+1, stack); - - /* FIXME: Fixed-point and floating-point code should be merged */ - { - VARDECL(spx_word16_t *corr16); - VARDECL(spx_word16_t *ener16); - ALLOC(corr16, end-start+1, spx_word16_t); - ALLOC(ener16, end-start+1, spx_word16_t); - /* Normalize to 180 so we can square it and it still fits in 16 bits */ - normalize16(corr, corr16, 180, end-start+1); - normalize16(energy, ener16, 180, end-start+1); - - if (N == 1) { - /* optimised asm to handle N==1 case */ - __asm__ __volatile__ - ( -" I0 = %1;\n\t" /* I0: corr16[] */ -" L0 = 0;\n\t" -" I1 = %2;\n\t" /* I1: energy */ -" L1 = 0;\n\t" -" R2 = -1;\n\t" /* R2: best score */ -" R3 = 0;\n\t" /* R3: best energy */ -" P0 = %4;\n\t" /* P0: best pitch */ -" P1 = %4;\n\t" /* P1: counter */ -" LSETUP (sl1, sl2) LC1 = %3;\n\t" -"sl1: R0.L = W [I0++] || R1.L = W [I1++];\n\t" -" R0 = R0.L * R0.L (IS);\n\t" -" R1 += 1;\n\t" -" R4 = R0.L * R3.L;\n\t" -" R5 = R2.L * R1.L;\n\t" -" cc = R5 < R4;\n\t" -" if cc R2 = R0;\n\t" -" if cc R3 = R1;\n\t" -" if cc P0 = P1;\n\t" -"sl2: P1 += 1;\n\t" -" %0 = P0;\n\t" - : "=&d" (pitch[0]) - : "a" (corr16), "a" (ener16), "a" (end+1-start), "d" (start) - : "P0", "P1", "I0", "I1", "R0", "R1", "R2", "R3", "R4", "R5" -#if (__GNUC__ == 4) - , "LC1" -#endif - ); - - } - else { - for (i=start;i<=end;i++) - { - spx_word16_t tmp = MULT16_16_16(corr16[i-start],corr16[i-start]); - /* Instead of dividing the tmp by the energy, we multiply on the other side */ - if (MULT16_16(tmp,best_ener[N-1])>MULT16_16(best_score[N-1],ADD16(1,ener16[i-start]))) - { - /* We can safely put it last and then check */ - best_score[N-1]=tmp; - best_ener[N-1]=ener16[i-start]+1; - pitch[N-1]=i; - /* Check if it comes in front of others */ - for (j=0;j<N-1;j++) - { - if (MULT16_16(tmp,best_ener[j])>MULT16_16(best_score[j],ADD16(1,ener16[i-start]))) - { - for (k=N-1;k>j;k--) - { - best_score[k]=best_score[k-1]; - best_ener[k]=best_ener[k-1]; - pitch[k]=pitch[k-1]; - } - best_score[j]=tmp; - best_ener[j]=ener16[i-start]+1; - pitch[j]=i; - break; - } - } - } - } - } - } - - /* Compute open-loop gain */ - if (gain) - { - for (j=0;j<N;j++) - { - spx_word16_t g; - i=pitch[j]; - g = DIV32(corr[i-start], 10+SHR32(MULT16_16(spx_sqrt(e0),spx_sqrt(energy[i-start])),6)); - /* FIXME: g = max(g,corr/energy) */ - if (g<0) - g = 0; - gain[j]=g; - } - } -} -#endif - -#define OVERRIDE_PITCH_GAIN_SEARCH_3TAP_VQ -#ifdef OVERRIDE_PITCH_GAIN_SEARCH_3TAP_VQ -static int pitch_gain_search_3tap_vq( - const signed char *gain_cdbk, - int gain_cdbk_size, - spx_word16_t *C16, - spx_word16_t max_gain -) -{ - const signed char *ptr=gain_cdbk; - int best_cdbk=0; - spx_word32_t best_sum=-VERY_LARGE32; - spx_word32_t sum=0; - spx_word16_t g[3]; - spx_word16_t pitch_control=64; - spx_word16_t gain_sum; - int i; - - /* fast asm version of VQ codebook search */ - - __asm__ __volatile__ - ( - -" P0 = %2;\n\t" /* P0: ptr to gain_cdbk */ -" L1 = 0;\n\t" /* no circ addr for L1 */ -" %0 = 0;\n\t" /* %0: best_sum */ -" %1 = 0;\n\t" /* %1: best_cbdk */ -" P1 = 0;\n\t" /* P1: loop counter */ - -" LSETUP (pgs1, pgs2) LC1 = %4;\n\t" -"pgs1: R2 = B [P0++] (X);\n\t" /* R2: g[0] */ -" R3 = B [P0++] (X);\n\t" /* R3: g[1] */ -" R4 = B [P0++] (X);\n\t" /* R4: g[2] */ -" R2 += 32;\n\t" -" R3 += 32;\n\t" -" R4 += 32;\n\t" -" R4.H = 64;\n\t" /* R4.H: pitch_control */ - -" R0 = B [P0++] (X);\n\t" -" B0 = R0;\n\t" /* BO: gain_sum */ - - /* compute_pitch_error() -------------------------------*/ - -" I1 = %3;\n\t" /* I1: ptr to C */ -" A0 = 0;\n\t" - -" R0.L = W[I1++];\n\t" -" R1.L = R2.L*R4.H (IS);\n\t" -" A0 += R1.L*R0.L (IS) || R0.L = W[I1++];\n\t" - -" R1.L = R3.L*R4.H (IS);\n\t" -" A0 += R1.L*R0.L (IS) || R0.L = W[I1++];\n\t" - -" R1.L = R4.L*R4.H (IS);\n\t" -" A0 += R1.L*R0.L (IS) || R0.L = W[I1++];\n\t" - -" R1.L = R2.L*R3.L (IS);\n\t" -" A0 -= R1.L*R0.L (IS) || R0.L = W[I1++];\n\t" - -" R1.L = R4.L*R3.L (IS);\n\t" -" A0 -= R1.L*R0.L (IS) || R0.L = W[I1++];\n\t" - -" R1.L = R4.L*R2.L (IS);\n\t" -" A0 -= R1.L*R0.L (IS) || R0.L = W[I1++];\n\t" - -" R1.L = R2.L*R2.L (IS);\n\t" -" A0 -= R1.L*R0.L (IS) || R0.L = W[I1++];\n\t" - -" R1.L = R3.L*R3.L (IS);\n\t" -" A0 -= R1.L*R0.L (IS) || R0.L = W[I1++];\n\t" - -" R1.L = R4.L*R4.L (IS);\n\t" -" R0 = (A0 -= R1.L*R0.L) (IS);\n\t" - -/* - Re-arrange the if-then to code efficiently on the Blackfin: - - if (sum>best_sum && gain_sum<=max_gain) ------ (1) - - if (sum>best_sum && !(gain_sum>max_gain)) ------ (2) - - if (max_gain<=gain_sum) { ------ (3) - sum = -VERY_LARGE32; - } - if (best_sum<=sum) - - The blackin cc instructions are all of the form: - - cc = x < y (or cc = x <= y) -*/ -" R1 = B0\n\t" -" R2 = %5\n\t" -" R3 = %6\n\t" -" cc = R2 <= R1;\n\t" -" if cc R0 = R3;\n\t" -" cc = %0 <= R0;\n\t" -" if cc %0 = R0;\n\t" -" if cc %1 = P1;\n\t" - -"pgs2: P1 += 1;\n\t" - - : "=&d" (best_sum), "=&d" (best_cdbk) - : "a" (gain_cdbk), "a" (C16), "a" (gain_cdbk_size), "a" (max_gain), - "b" (-VERY_LARGE32) - : "R0", "R1", "R2", "R3", "R4", "P0", - "P1", "I1", "L1", "A0", "B0" -#if (__GNUC__ == 4) - , "LC1" -#endif - ); - - return best_cdbk; -} -#endif - diff --git a/drivers/speex/ltp_sse.h b/drivers/speex/ltp_sse.h deleted file mode 100644 index bed6eaac9a..0000000000 --- a/drivers/speex/ltp_sse.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @file ltp_sse.h - @brief Long-Term Prediction functions (SSE version) -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#include <xmmintrin.h> - -#define OVERRIDE_INNER_PROD -float inner_prod(const float *a, const float *b, int len) -{ - int i; - float ret; - __m128 sum = _mm_setzero_ps(); - for (i=0;i<(len>>2);i+=2) - { - sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+0), _mm_loadu_ps(b+0))); - sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+4), _mm_loadu_ps(b+4))); - a += 8; - b += 8; - } - sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum)); - sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55)); - _mm_store_ss(&ret, sum); - return ret; -} - -#define OVERRIDE_PITCH_XCORR -void pitch_xcorr(const float *_x, const float *_y, float *corr, int len, int nb_pitch, char *stack) -{ - int i, offset; - VARDECL(__m128 *x); - VARDECL(__m128 *y); - int N, L; - N = len>>2; - L = nb_pitch>>2; - ALLOC(x, N, __m128); - ALLOC(y, N+L, __m128); - for (i=0;i<N;i++) - x[i] = _mm_loadu_ps(_x+(i<<2)); - for (offset=0;offset<4;offset++) - { - for (i=0;i<N+L;i++) - y[i] = _mm_loadu_ps(_y+(i<<2)+offset); - for (i=0;i<L;i++) - { - int j; - __m128 sum, *xx, *yy; - sum = _mm_setzero_ps(); - yy = y+i; - xx = x; - for (j=0;j<N;j+=2) - { - sum = _mm_add_ps(sum, _mm_mul_ps(xx[0], yy[0])); - sum = _mm_add_ps(sum, _mm_mul_ps(xx[1], yy[1])); - xx += 2; - yy += 2; - } - sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum)); - sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55)); - _mm_store_ss(corr+nb_pitch-1-(i<<2)-offset, sum); - } - } -} diff --git a/drivers/speex/math_approx.h b/drivers/speex/math_approx.h deleted file mode 100644 index 8a82ab5269..0000000000 --- a/drivers/speex/math_approx.h +++ /dev/null @@ -1,333 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @file math_approx.h - @brief Various math approximation functions for Speex -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 MATH_APPROX_H -#define MATH_APPROX_H - -#include "arch.h" -#include "os_support.h" - -#ifndef FIXED_POINT - -#define spx_sqrt sqrt -#define spx_acos acos -#define spx_exp exp -#define spx_cos_norm(x) (cos((.5f*M_PI)*(x))) -#define spx_atan atan - -/** Generate a pseudo-random number */ -static SPEEX_INLINE spx_word16_t speex_rand(spx_word16_t std, spx_int32_t *seed) -{ - const unsigned int jflone = 0x3f800000; - const unsigned int jflmsk = 0x007fffff; - union {int i; float f;} ran; - *seed = 1664525 * *seed + 1013904223; - ran.i = jflone | (jflmsk & *seed); - ran.f -= 1.5; - return 3.4642*std*ran.f; -} - - -#endif - - -static SPEEX_INLINE spx_int16_t spx_ilog2(spx_uint32_t x) -{ - int r=0; - if (x>=(spx_int32_t)65536) - { - x >>= 16; - r += 16; - } - if (x>=256) - { - x >>= 8; - r += 8; - } - if (x>=16) - { - x >>= 4; - r += 4; - } - if (x>=4) - { - x >>= 2; - r += 2; - } - if (x>=2) - { - r += 1; - } - return r; -} - -static SPEEX_INLINE spx_int16_t spx_ilog4(spx_uint32_t x) -{ - int r=0; - if (x>=(spx_int32_t)65536) - { - x >>= 16; - r += 8; - } - if (x>=256) - { - x >>= 8; - r += 4; - } - if (x>=16) - { - x >>= 4; - r += 2; - } - if (x>=4) - { - r += 1; - } - return r; -} - -#ifdef FIXED_POINT - -/** Generate a pseudo-random number */ -static SPEEX_INLINE spx_word16_t speex_rand(spx_word16_t std, spx_int32_t *seed) -{ - spx_word32_t res; - *seed = 1664525 * *seed + 1013904223; - res = MULT16_16(EXTRACT16(SHR32(*seed,16)),std); - return EXTRACT16(PSHR32(SUB32(res, SHR32(res, 3)),14)); -} - -/* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25723*x^3 (for .25 < x < 1) */ -/*#define C0 3634 -#define C1 21173 -#define C2 -12627 -#define C3 4215*/ - -/* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25659*x^3 (for .25 < x < 1) */ -#define C0 3634 -#define C1 21173 -#define C2 -12627 -#define C3 4204 - -static SPEEX_INLINE spx_word16_t spx_sqrt(spx_word32_t x) -{ - int k; - spx_word32_t rt; - k = spx_ilog4(x)-6; - x = VSHR32(x, (k<<1)); - rt = ADD16(C0, MULT16_16_Q14(x, ADD16(C1, MULT16_16_Q14(x, ADD16(C2, MULT16_16_Q14(x, (C3))))))); - rt = VSHR32(rt,7-k); - return rt; -} - -/* log(x) ~= -2.18151 + 4.20592*x - 2.88938*x^2 + 0.86535*x^3 (for .5 < x < 1) */ - - -#define A1 16469 -#define A2 2242 -#define A3 1486 - -static SPEEX_INLINE spx_word16_t spx_acos(spx_word16_t x) -{ - int s=0; - spx_word16_t ret; - spx_word16_t sq; - if (x<0) - { - s=1; - x = NEG16(x); - } - x = SUB16(16384,x); - - x = x >> 1; - sq = MULT16_16_Q13(x, ADD16(A1, MULT16_16_Q13(x, ADD16(A2, MULT16_16_Q13(x, (A3)))))); - ret = spx_sqrt(SHL32(EXTEND32(sq),13)); - - /*ret = spx_sqrt(67108864*(-1.6129e-04 + 2.0104e+00*f + 2.7373e-01*f*f + 1.8136e-01*f*f*f));*/ - if (s) - ret = SUB16(25736,ret); - return ret; -} - - -#define K1 8192 -#define K2 -4096 -#define K3 340 -#define K4 -10 - -static SPEEX_INLINE spx_word16_t spx_cos(spx_word16_t x) -{ - spx_word16_t x2; - - if (x<12868) - { - x2 = MULT16_16_P13(x,x); - return ADD32(K1, MULT16_16_P13(x2, ADD32(K2, MULT16_16_P13(x2, ADD32(K3, MULT16_16_P13(K4, x2)))))); - } else { - x = SUB16(25736,x); - x2 = MULT16_16_P13(x,x); - return SUB32(-K1, MULT16_16_P13(x2, ADD32(K2, MULT16_16_P13(x2, ADD32(K3, MULT16_16_P13(K4, x2)))))); - } -} - -#define L1 32767 -#define L2 -7651 -#define L3 8277 -#define L4 -626 - -static SPEEX_INLINE spx_word16_t _spx_cos_pi_2(spx_word16_t x) -{ - spx_word16_t 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)))))))); -} - -static SPEEX_INLINE spx_word16_t spx_cos_norm(spx_word32_t 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 _spx_cos_pi_2(EXTRACT16(x)); - } else { - return NEG32(_spx_cos_pi_2(EXTRACT16(65536-x))); - } - } else { - if (x&0x0000ffff) - return 0; - else if (x&0x0001ffff) - return -32767; - else - return 32767; - } -} - -/* - K0 = 1 - K1 = log(2) - K2 = 3-4*log(2) - K3 = 3*log(2) - 2 -*/ -#define D0 16384 -#define D1 11356 -#define D2 3726 -#define D3 1301 -/* Input in Q11 format, output in Q16 */ -static SPEEX_INLINE spx_word32_t spx_exp2(spx_word16_t x) -{ - int integer; - spx_word16_t frac; - integer = SHR16(x,11); - if (integer>14) - return 0x7fffffff; - else if (integer < -15) - return 0; - frac = SHL16(x-SHL16(integer,11),3); - frac = ADD16(D0, MULT16_16_Q14(frac, ADD16(D1, MULT16_16_Q14(frac, ADD16(D2 , MULT16_16_Q14(D3,frac)))))); - return VSHR32(EXTEND32(frac), -integer-2); -} - -/* Input in Q11 format, output in Q16 */ -static SPEEX_INLINE spx_word32_t spx_exp(spx_word16_t x) -{ - if (x>21290) - return 0x7fffffff; - else if (x<-21290) - return 0; - else - return spx_exp2(MULT16_16_P14(23637,x)); -} -#define M1 32767 -#define M2 -21 -#define M3 -11943 -#define M4 4936 - -static SPEEX_INLINE spx_word16_t spx_atan01(spx_word16_t 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 - -/* Input in Q15, output in Q14 */ -static SPEEX_INLINE spx_word16_t spx_atan(spx_word32_t x) -{ - if (x <= 32767) - { - return SHR16(spx_atan01(x),1); - } else { - int e = spx_ilog2(x); - if (e>=29) - return 25736; - x = DIV32_16(SHL32(EXTEND32(32767),29-e), EXTRACT16(SHR32(x, e-14))); - return SUB16(25736, SHR16(spx_atan01(x),1)); - } -} -#else - -#ifndef M_PI -#define M_PI 3.14159265358979323846 /* pi */ -#endif - -#define C1 0.9999932946f -#define C2 -0.4999124376f -#define C3 0.0414877472f -#define C4 -0.0012712095f - - -#define SPX_PI_2 1.5707963268 -static SPEEX_INLINE spx_word16_t spx_cos(spx_word16_t x) -{ - if (x<SPX_PI_2) - { - x *= x; - return C1 + x*(C2+x*(C3+C4*x)); - } else { - x = M_PI-x; - x *= x; - return NEG16(C1 + x*(C2+x*(C3+C4*x))); - } -} - -#endif - - -#endif diff --git a/drivers/speex/mdf.c b/drivers/speex/mdf.c deleted file mode 100644 index 1f9ff93f75..0000000000 --- a/drivers/speex/mdf.c +++ /dev/null @@ -1,1285 +0,0 @@ -/* Copyright (C) 2003-2008 Jean-Marc Valin - - File: mdf.c - Echo canceller based on the MDF algorithm (see below) - - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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. -*/ - -/* - The echo canceller is based on the MDF algorithm described in: - - J. S. Soo, K. K. Pang Multidelay block frequency adaptive filter, - IEEE Trans. Acoust. Speech Signal Process., Vol. ASSP-38, No. 2, - February 1990. - - We use the Alternatively Updated MDF (AUMDF) variant. Robustness to - double-talk is achieved using a variable learning rate as described in: - - Valin, J.-M., On Adjusting the Learning Rate in Frequency Domain Echo - Cancellation With Double-Talk. IEEE Transactions on Audio, - Speech and Language Processing, Vol. 15, No. 3, pp. 1030-1034, 2007. - http://people.xiph.org/~jm/papers/valin_taslp2006.pdf - - There is no explicit double-talk detection, but a continuous variation - in the learning rate based on residual echo, double-talk and background - noise. - - About the fixed-point version: - All the signals are represented with 16-bit words. The filter weights - are represented with 32-bit words, but only the top 16 bits are used - in most cases. The lower 16 bits are completely unreliable (due to the - fact that the update is done only on the top bits), but help in the - adaptation -- probably by removing a "threshold effect" due to - quantization (rounding going to zero) when the gradient is small. - - Another kludge that seems to work good: when performing the weight - update, we only move half the way toward the "goal" this seems to - reduce the effect of quantization noise in the update phase. This - can be seen as applying a gradient descent on a "soft constraint" - instead of having a hard constraint. - -*/ - - -#include "config.h" - - -#include "arch.h" -#include "speex/speex_echo.h" -#include "fftwrap.h" -#include "pseudofloat.h" -#include "math_approx.h" -#include "os_support.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#ifdef FIXED_POINT -#define WEIGHT_SHIFT 11 -#define NORMALIZE_SCALEDOWN 5 -#define NORMALIZE_SCALEUP 3 -#else -#define WEIGHT_SHIFT 0 -#endif - -#ifdef FIXED_POINT -#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) -#else -#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) -#endif - -/* If enabled, the AEC will use a foreground filter and a background filter to be more robust to double-talk - and difficult signals in general. The cost is an extra FFT and a matrix-vector multiply */ -#define TWO_PATH - -#ifdef FIXED_POINT -static const spx_float_t MIN_LEAK = {20972, -22}; - -/* Constants for the two-path filter */ -static const spx_float_t VAR1_SMOOTH = {23593, -16}; -static const spx_float_t VAR2_SMOOTH = {23675, -15}; -static const spx_float_t VAR1_UPDATE = {16384, -15}; -static const spx_float_t VAR2_UPDATE = {16384, -16}; -static const spx_float_t VAR_BACKTRACK = {16384, -12}; -#define TOP16(x) ((x)>>16) - -#else - -static const spx_float_t MIN_LEAK = .005f; - -/* Constants for the two-path filter */ -static const spx_float_t VAR1_SMOOTH = .36f; -static const spx_float_t VAR2_SMOOTH = .7225f; -static const spx_float_t VAR1_UPDATE = .5f; -static const spx_float_t VAR2_UPDATE = .25f; -static const spx_float_t VAR_BACKTRACK = 4.f; -#define TOP16(x) (x) -#endif - - -#define PLAYBACK_DELAY 2 - -void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *Yout, int len); - - -/** Speex echo cancellation state. */ -struct SpeexEchoState_ { - int frame_size; /**< Number of samples processed each time */ - int window_size; - int M; - int cancel_count; - int adapted; - int saturated; - int screwed_up; - int C; /** Number of input channels (microphones) */ - int K; /** Number of output channels (loudspeakers) */ - spx_int32_t sampling_rate; - spx_word16_t spec_average; - spx_word16_t beta0; - spx_word16_t beta_max; - spx_word32_t sum_adapt; - spx_word16_t leak_estimate; - - spx_word16_t *e; /* scratch */ - spx_word16_t *x; /* Far-end input buffer (2N) */ - spx_word16_t *X; /* Far-end buffer (M+1 frames) in frequency domain */ - spx_word16_t *input; /* scratch */ - spx_word16_t *y; /* scratch */ - spx_word16_t *last_y; - spx_word16_t *Y; /* scratch */ - spx_word16_t *E; - spx_word32_t *PHI; /* scratch */ - spx_word32_t *W; /* (Background) filter weights */ -#ifdef TWO_PATH - spx_word16_t *foreground; /* Foreground filter weights */ - spx_word32_t Davg1; /* 1st recursive average of the residual power difference */ - spx_word32_t Davg2; /* 2nd recursive average of the residual power difference */ - spx_float_t Dvar1; /* Estimated variance of 1st estimator */ - spx_float_t Dvar2; /* Estimated variance of 2nd estimator */ -#endif - spx_word32_t *power; /* Power of the far-end signal */ - spx_float_t *power_1;/* Inverse power of far-end */ - spx_word16_t *wtmp; /* scratch */ -#ifdef FIXED_POINT - spx_word16_t *wtmp2; /* scratch */ -#endif - spx_word32_t *Rf; /* scratch */ - spx_word32_t *Yf; /* scratch */ - spx_word32_t *Xf; /* scratch */ - spx_word32_t *Eh; - spx_word32_t *Yh; - spx_float_t Pey; - spx_float_t Pyy; - spx_word16_t *window; - spx_word16_t *prop; - void *fft_table; - spx_word16_t *memX, *memD, *memE; - spx_word16_t preemph; - spx_word16_t notch_radius; - spx_mem_t *notch_mem; - - /* NOTE: If you only use speex_echo_cancel() and want to save some memory, remove this */ - spx_int16_t *play_buf; - int play_buf_pos; - int play_buf_started; -}; - -static SPEEX_INLINE void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem, int stride) -{ - int i; - spx_word16_t den2; -#ifdef FIXED_POINT - den2 = MULT16_16_Q15(radius,radius) + MULT16_16_Q15(QCONST16(.7,15),MULT16_16_Q15(32767-radius,32767-radius)); -#else - den2 = radius*radius + .7*(1-radius)*(1-radius); -#endif - /*printf ("%d %d %d %d %d %d\n", num[0], num[1], num[2], den[0], den[1], den[2]);*/ - for (i=0;i<len;i++) - { - spx_word16_t vin = in[i*stride]; - spx_word32_t vout = mem[0] + SHL32(EXTEND32(vin),15); -#ifdef FIXED_POINT - mem[0] = mem[1] + SHL32(SHL32(-EXTEND32(vin),15) + MULT16_32_Q15(radius,vout),1); -#else - mem[0] = mem[1] + 2*(-vin + radius*vout); -#endif - mem[1] = SHL32(EXTEND32(vin),15) - MULT16_32_Q15(den2,vout); - out[i] = SATURATE32(PSHR32(MULT16_32_Q15(radius,vout),15),32767); - } -} - -/* This inner product is slightly different from the codec version because of fixed-point */ -static SPEEX_INLINE spx_word32_t mdf_inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len) -{ - spx_word32_t sum=0; - len >>= 1; - while(len--) - { - spx_word32_t part=0; - part = MAC16_16(part,*x++,*y++); - part = MAC16_16(part,*x++,*y++); - /* HINT: If you had a 40-bit accumulator, you could shift only at the end */ - sum = ADD32(sum,SHR32(part,6)); - } - return sum; -} - -/** Compute power spectrum of a half-complex (packed) vector */ -static SPEEX_INLINE void power_spectrum(const spx_word16_t *X, spx_word32_t *ps, int N) -{ - int i, j; - ps[0]=MULT16_16(X[0],X[0]); - for (i=1,j=1;i<N-1;i+=2,j++) - { - ps[j] = MULT16_16(X[i],X[i]) + MULT16_16(X[i+1],X[i+1]); - } - ps[j]=MULT16_16(X[i],X[i]); -} - -/** Compute power spectrum of a half-complex (packed) vector and accumulate */ -static SPEEX_INLINE void power_spectrum_accum(const spx_word16_t *X, spx_word32_t *ps, int N) -{ - int i, j; - ps[0]+=MULT16_16(X[0],X[0]); - for (i=1,j=1;i<N-1;i+=2,j++) - { - ps[j] += MULT16_16(X[i],X[i]) + MULT16_16(X[i+1],X[i+1]); - } - ps[j]+=MULT16_16(X[i],X[i]); -} - -/** Compute cross-power spectrum of a half-complex (packed) vectors and add to acc */ -#ifdef FIXED_POINT -static SPEEX_INLINE void spectral_mul_accum(const spx_word16_t *X, const spx_word32_t *Y, spx_word16_t *acc, int N, int M) -{ - int i,j; - spx_word32_t tmp1=0,tmp2=0; - for (j=0;j<M;j++) - { - tmp1 = MAC16_16(tmp1, X[j*N],TOP16(Y[j*N])); - } - acc[0] = PSHR32(tmp1,WEIGHT_SHIFT); - for (i=1;i<N-1;i+=2) - { - tmp1 = tmp2 = 0; - for (j=0;j<M;j++) - { - tmp1 = SUB32(MAC16_16(tmp1, X[j*N+i],TOP16(Y[j*N+i])), MULT16_16(X[j*N+i+1],TOP16(Y[j*N+i+1]))); - tmp2 = MAC16_16(MAC16_16(tmp2, X[j*N+i+1],TOP16(Y[j*N+i])), X[j*N+i], TOP16(Y[j*N+i+1])); - } - acc[i] = PSHR32(tmp1,WEIGHT_SHIFT); - acc[i+1] = PSHR32(tmp2,WEIGHT_SHIFT); - } - tmp1 = tmp2 = 0; - for (j=0;j<M;j++) - { - tmp1 = MAC16_16(tmp1, X[(j+1)*N-1],TOP16(Y[(j+1)*N-1])); - } - acc[N-1] = PSHR32(tmp1,WEIGHT_SHIFT); -} -static SPEEX_INLINE void spectral_mul_accum16(const spx_word16_t *X, const spx_word16_t *Y, spx_word16_t *acc, int N, int M) -{ - int i,j; - spx_word32_t tmp1=0,tmp2=0; - for (j=0;j<M;j++) - { - tmp1 = MAC16_16(tmp1, X[j*N],Y[j*N]); - } - acc[0] = PSHR32(tmp1,WEIGHT_SHIFT); - for (i=1;i<N-1;i+=2) - { - tmp1 = tmp2 = 0; - for (j=0;j<M;j++) - { - tmp1 = SUB32(MAC16_16(tmp1, X[j*N+i],Y[j*N+i]), MULT16_16(X[j*N+i+1],Y[j*N+i+1])); - tmp2 = MAC16_16(MAC16_16(tmp2, X[j*N+i+1],Y[j*N+i]), X[j*N+i], Y[j*N+i+1]); - } - acc[i] = PSHR32(tmp1,WEIGHT_SHIFT); - acc[i+1] = PSHR32(tmp2,WEIGHT_SHIFT); - } - tmp1 = tmp2 = 0; - for (j=0;j<M;j++) - { - tmp1 = MAC16_16(tmp1, X[(j+1)*N-1],Y[(j+1)*N-1]); - } - acc[N-1] = PSHR32(tmp1,WEIGHT_SHIFT); -} - -#else -static SPEEX_INLINE void spectral_mul_accum(const spx_word16_t *X, const spx_word32_t *Y, spx_word16_t *acc, int N, int M) -{ - int i,j; - for (i=0;i<N;i++) - acc[i] = 0; - for (j=0;j<M;j++) - { - acc[0] += X[0]*Y[0]; - for (i=1;i<N-1;i+=2) - { - acc[i] += (X[i]*Y[i] - X[i+1]*Y[i+1]); - acc[i+1] += (X[i+1]*Y[i] + X[i]*Y[i+1]); - } - acc[i] += X[i]*Y[i]; - X += N; - Y += N; - } -} -#define spectral_mul_accum16 spectral_mul_accum -#endif - -/** Compute weighted cross-power spectrum of a half-complex (packed) vector with conjugate */ -static SPEEX_INLINE void weighted_spectral_mul_conj(const spx_float_t *w, const spx_float_t p, const spx_word16_t *X, const spx_word16_t *Y, spx_word32_t *prod, int N) -{ - int i, j; - spx_float_t W; - W = FLOAT_AMULT(p, w[0]); - prod[0] = FLOAT_MUL32(W,MULT16_16(X[0],Y[0])); - for (i=1,j=1;i<N-1;i+=2,j++) - { - W = FLOAT_AMULT(p, w[j]); - prod[i] = FLOAT_MUL32(W,MAC16_16(MULT16_16(X[i],Y[i]), X[i+1],Y[i+1])); - prod[i+1] = FLOAT_MUL32(W,MAC16_16(MULT16_16(-X[i+1],Y[i]), X[i],Y[i+1])); - } - W = FLOAT_AMULT(p, w[j]); - prod[i] = FLOAT_MUL32(W,MULT16_16(X[i],Y[i])); -} - -static SPEEX_INLINE void mdf_adjust_prop(const spx_word32_t *W, int N, int M, int P, spx_word16_t *prop) -{ - int i, j, p; - spx_word16_t max_sum = 1; - spx_word32_t prop_sum = 1; - for (i=0;i<M;i++) - { - spx_word32_t tmp = 1; - for (p=0;p<P;p++) - for (j=0;j<N;j++) - tmp += MULT16_16(EXTRACT16(SHR32(W[p*N*M + i*N+j],18)), EXTRACT16(SHR32(W[p*N*M + i*N+j],18))); -#ifdef FIXED_POINT - /* Just a security in case an overflow were to occur */ - tmp = MIN32(ABS32(tmp), 536870912); -#endif - prop[i] = spx_sqrt(tmp); - if (prop[i] > max_sum) - max_sum = prop[i]; - } - for (i=0;i<M;i++) - { - prop[i] += MULT16_16_Q15(QCONST16(.1f,15),max_sum); - prop_sum += EXTEND32(prop[i]); - } - for (i=0;i<M;i++) - { - prop[i] = DIV32(MULT16_16(QCONST16(.99f,15), prop[i]),prop_sum); - /*printf ("%f ", prop[i]);*/ - } - /*printf ("\n");*/ -} - -#ifdef DUMP_ECHO_CANCEL_DATA -#include <stdio.h> -static FILE *rFile=NULL, *pFile=NULL, *oFile=NULL; - -static void dump_audio(const spx_int16_t *rec, const spx_int16_t *play, const spx_int16_t *out, int len) -{ - if (!(rFile && pFile && oFile)) - { - speex_fatal("Dump files not open"); - } - fwrite(rec, sizeof(spx_int16_t), len, rFile); - fwrite(play, sizeof(spx_int16_t), len, pFile); - fwrite(out, sizeof(spx_int16_t), len, oFile); -} -#endif - -/** Creates a new echo canceller state */ -EXPORT SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length) -{ - return speex_echo_state_init_mc(frame_size, filter_length, 1, 1); -} - -EXPORT SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_length, int nb_mic, int nb_speakers) -{ - int i,N,M, C, K; - SpeexEchoState *st = (SpeexEchoState *)speex_alloc(sizeof(SpeexEchoState)); - - st->K = nb_speakers; - st->C = nb_mic; - C=st->C; - K=st->K; -#ifdef DUMP_ECHO_CANCEL_DATA - if (rFile || pFile || oFile) - speex_fatal("Opening dump files twice"); - rFile = fopen("aec_rec.sw", "wb"); - pFile = fopen("aec_play.sw", "wb"); - oFile = fopen("aec_out.sw", "wb"); -#endif - - st->frame_size = frame_size; - st->window_size = 2*frame_size; - N = st->window_size; - M = st->M = (filter_length+st->frame_size-1)/frame_size; - st->cancel_count=0; - st->sum_adapt = 0; - st->saturated = 0; - st->screwed_up = 0; - /* This is the default sampling rate */ - st->sampling_rate = 8000; - st->spec_average = DIV32_16(SHL32(EXTEND32(st->frame_size), 15), st->sampling_rate); -#ifdef FIXED_POINT - st->beta0 = DIV32_16(SHL32(EXTEND32(st->frame_size), 16), st->sampling_rate); - st->beta_max = DIV32_16(SHL32(EXTEND32(st->frame_size), 14), st->sampling_rate); -#else - st->beta0 = (2.0f*st->frame_size)/st->sampling_rate; - st->beta_max = (.5f*st->frame_size)/st->sampling_rate; -#endif - st->leak_estimate = 0; - - st->fft_table = spx_fft_init(N); - - st->e = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); - st->x = (spx_word16_t*)speex_alloc(K*N*sizeof(spx_word16_t)); - st->input = (spx_word16_t*)speex_alloc(C*st->frame_size*sizeof(spx_word16_t)); - st->y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); - st->last_y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); - st->Yf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); - st->Rf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); - st->Xf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); - st->Yh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); - st->Eh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); - - st->X = (spx_word16_t*)speex_alloc(K*(M+1)*N*sizeof(spx_word16_t)); - st->Y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); - st->E = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); - st->W = (spx_word32_t*)speex_alloc(C*K*M*N*sizeof(spx_word32_t)); -#ifdef TWO_PATH - st->foreground = (spx_word16_t*)speex_alloc(M*N*C*K*sizeof(spx_word16_t)); -#endif - st->PHI = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); - st->power = (spx_word32_t*)speex_alloc((frame_size+1)*sizeof(spx_word32_t)); - st->power_1 = (spx_float_t*)speex_alloc((frame_size+1)*sizeof(spx_float_t)); - st->window = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); - st->prop = (spx_word16_t*)speex_alloc(M*sizeof(spx_word16_t)); - st->wtmp = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); -#ifdef FIXED_POINT - st->wtmp2 = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); - for (i=0;i<N>>1;i++) - { - st->window[i] = (16383-SHL16(spx_cos(DIV32_16(MULT16_16(25736,i<<1),N)),1)); - st->window[N-i-1] = st->window[i]; - } -#else - for (i=0;i<N;i++) - st->window[i] = .5-.5*cos(2*M_PI*i/N); -#endif - for (i=0;i<=st->frame_size;i++) - st->power_1[i] = FLOAT_ONE; - for (i=0;i<N*M*K*C;i++) - st->W[i] = 0; - { - spx_word32_t sum = 0; - /* Ratio of ~10 between adaptation rate of first and last block */ - spx_word16_t decay = SHR32(spx_exp(NEG16(DIV32_16(QCONST16(2.4,11),M))),1); - st->prop[0] = QCONST16(.7, 15); - sum = EXTEND32(st->prop[0]); - for (i=1;i<M;i++) - { - st->prop[i] = MULT16_16_Q15(st->prop[i-1], decay); - sum = ADD32(sum, EXTEND32(st->prop[i])); - } - for (i=M-1;i>=0;i--) - { - st->prop[i] = DIV32(MULT16_16(QCONST16(.8f,15), st->prop[i]),sum); - } - } - - st->memX = (spx_word16_t*)speex_alloc(K*sizeof(spx_word16_t)); - st->memD = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t)); - st->memE = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t)); - st->preemph = QCONST16(.9,15); - if (st->sampling_rate<12000) - st->notch_radius = QCONST16(.9, 15); - else if (st->sampling_rate<24000) - st->notch_radius = QCONST16(.982, 15); - else - st->notch_radius = QCONST16(.992, 15); - - st->notch_mem = (spx_mem_t*)speex_alloc(2*C*sizeof(spx_mem_t)); - st->adapted = 0; - st->Pey = st->Pyy = FLOAT_ONE; - -#ifdef TWO_PATH - st->Davg1 = st->Davg2 = 0; - st->Dvar1 = st->Dvar2 = FLOAT_ZERO; -#endif - - st->play_buf = (spx_int16_t*)speex_alloc(K*(PLAYBACK_DELAY+1)*st->frame_size*sizeof(spx_int16_t)); - st->play_buf_pos = PLAYBACK_DELAY*st->frame_size; - st->play_buf_started = 0; - - return st; -} - -/** Resets echo canceller state */ -EXPORT void speex_echo_state_reset(SpeexEchoState *st) -{ - int i, M, N, C, K; - st->cancel_count=0; - st->screwed_up = 0; - N = st->window_size; - M = st->M; - C=st->C; - K=st->K; - for (i=0;i<N*M;i++) - st->W[i] = 0; -#ifdef TWO_PATH - for (i=0;i<N*M;i++) - st->foreground[i] = 0; -#endif - for (i=0;i<N*(M+1);i++) - st->X[i] = 0; - for (i=0;i<=st->frame_size;i++) - { - st->power[i] = 0; - st->power_1[i] = FLOAT_ONE; - st->Eh[i] = 0; - st->Yh[i] = 0; - } - for (i=0;i<st->frame_size;i++) - { - st->last_y[i] = 0; - } - for (i=0;i<N*C;i++) - { - st->E[i] = 0; - } - for (i=0;i<N*K;i++) - { - st->x[i] = 0; - } - for (i=0;i<2*C;i++) - st->notch_mem[i] = 0; - for (i=0;i<C;i++) - st->memD[i]=st->memE[i]=0; - for (i=0;i<K;i++) - st->memX[i]=0; - - st->saturated = 0; - st->adapted = 0; - st->sum_adapt = 0; - st->Pey = st->Pyy = FLOAT_ONE; -#ifdef TWO_PATH - st->Davg1 = st->Davg2 = 0; - st->Dvar1 = st->Dvar2 = FLOAT_ZERO; -#endif - for (i=0;i<3*st->frame_size;i++) - st->play_buf[i] = 0; - st->play_buf_pos = PLAYBACK_DELAY*st->frame_size; - st->play_buf_started = 0; - -} - -/** Destroys an echo canceller state */ -EXPORT void speex_echo_state_destroy(SpeexEchoState *st) -{ - spx_fft_destroy(st->fft_table); - - speex_free(st->e); - speex_free(st->x); - speex_free(st->input); - speex_free(st->y); - speex_free(st->last_y); - speex_free(st->Yf); - speex_free(st->Rf); - speex_free(st->Xf); - speex_free(st->Yh); - speex_free(st->Eh); - - speex_free(st->X); - speex_free(st->Y); - speex_free(st->E); - speex_free(st->W); -#ifdef TWO_PATH - speex_free(st->foreground); -#endif - speex_free(st->PHI); - speex_free(st->power); - speex_free(st->power_1); - speex_free(st->window); - speex_free(st->prop); - speex_free(st->wtmp); -#ifdef FIXED_POINT - speex_free(st->wtmp2); -#endif - speex_free(st->memX); - speex_free(st->memD); - speex_free(st->memE); - speex_free(st->notch_mem); - - speex_free(st->play_buf); - speex_free(st); - -#ifdef DUMP_ECHO_CANCEL_DATA - fclose(rFile); - fclose(pFile); - fclose(oFile); - rFile = pFile = oFile = NULL; -#endif -} - -EXPORT void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out) -{ - int i; - /*speex_warning_int("capture with fill level ", st->play_buf_pos/st->frame_size);*/ - st->play_buf_started = 1; - if (st->play_buf_pos>=st->frame_size) - { - speex_echo_cancellation(st, rec, st->play_buf, out); - st->play_buf_pos -= st->frame_size; - for (i=0;i<st->play_buf_pos;i++) - st->play_buf[i] = st->play_buf[i+st->frame_size]; - } else { - speex_warning("No playback frame available (your application is buggy and/or got xruns)"); - if (st->play_buf_pos!=0) - { - speex_warning("internal playback buffer corruption?"); - st->play_buf_pos = 0; - } - for (i=0;i<st->frame_size;i++) - out[i] = rec[i]; - } -} - -EXPORT void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play) -{ - /*speex_warning_int("playback with fill level ", st->play_buf_pos/st->frame_size);*/ - if (!st->play_buf_started) - { - speex_warning("discarded first playback frame"); - return; - } - if (st->play_buf_pos<=PLAYBACK_DELAY*st->frame_size) - { - int i; - for (i=0;i<st->frame_size;i++) - st->play_buf[st->play_buf_pos+i] = play[i]; - st->play_buf_pos += st->frame_size; - if (st->play_buf_pos <= (PLAYBACK_DELAY-1)*st->frame_size) - { - speex_warning("Auto-filling the buffer (your application is buggy and/or got xruns)"); - for (i=0;i<st->frame_size;i++) - st->play_buf[st->play_buf_pos+i] = play[i]; - st->play_buf_pos += st->frame_size; - } - } else { - speex_warning("Had to discard a playback frame (your application is buggy and/or got xruns)"); - } -} - -/** Performs echo cancellation on a frame (deprecated, last arg now ignored) */ -EXPORT void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out, spx_int32_t *Yout) -{ - speex_echo_cancellation(st, in, far_end, out); -} - -/** Performs echo cancellation on a frame */ -EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out) -{ - int i,j, chan, speak; - int N,M, C, K; - spx_word32_t Syy,See,Sxx,Sdd, Sff; -#ifdef TWO_PATH - spx_word32_t Dbf; - int update_foreground; -#endif - spx_word32_t Sey; - spx_word16_t ss, ss_1; - spx_float_t Pey = FLOAT_ONE, Pyy=FLOAT_ONE; - spx_float_t alpha, alpha_1; - spx_word16_t RER; - spx_word32_t tmp32; - - N = st->window_size; - M = st->M; - C = st->C; - K = st->K; - - st->cancel_count++; -#ifdef FIXED_POINT - ss=DIV32_16(11469,M); - ss_1 = SUB16(32767,ss); -#else - ss=.35/M; - ss_1 = 1-ss; -#endif - - for (chan = 0; chan < C; chan++) - { - /* Apply a notch filter to make sure DC doesn't end up causing problems */ - filter_dc_notch16(in+chan, st->notch_radius, st->input+chan*st->frame_size, st->frame_size, st->notch_mem+2*chan, C); - /* Copy input data to buffer and apply pre-emphasis */ - /* Copy input data to buffer */ - for (i=0;i<st->frame_size;i++) - { - spx_word32_t tmp32; - /* FIXME: This core has changed a bit, need to merge properly */ - tmp32 = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(MULT16_16_P15(st->preemph, st->memD[chan]))); -#ifdef FIXED_POINT - if (tmp32 > 32767) - { - tmp32 = 32767; - if (st->saturated == 0) - st->saturated = 1; - } - if (tmp32 < -32767) - { - tmp32 = -32767; - if (st->saturated == 0) - st->saturated = 1; - } -#endif - st->memD[chan] = st->input[chan*st->frame_size+i]; - st->input[chan*st->frame_size+i] = EXTRACT16(tmp32); - } - } - - for (speak = 0; speak < K; speak++) - { - for (i=0;i<st->frame_size;i++) - { - spx_word32_t tmp32; - st->x[speak*N+i] = st->x[speak*N+i+st->frame_size]; - tmp32 = SUB32(EXTEND32(far_end[i*K+speak]), EXTEND32(MULT16_16_P15(st->preemph, st->memX[speak]))); -#ifdef FIXED_POINT - /*FIXME: If saturation occurs here, we need to freeze adaptation for M frames (not just one) */ - if (tmp32 > 32767) - { - tmp32 = 32767; - st->saturated = M+1; - } - if (tmp32 < -32767) - { - tmp32 = -32767; - st->saturated = M+1; - } -#endif - st->x[speak*N+i+st->frame_size] = EXTRACT16(tmp32); - st->memX[speak] = far_end[i*K+speak]; - } - } - - for (speak = 0; speak < K; speak++) - { - /* Shift memory: this could be optimized eventually*/ - for (j=M-1;j>=0;j--) - { - for (i=0;i<N;i++) - st->X[(j+1)*N*K+speak*N+i] = st->X[j*N*K+speak*N+i]; - } - /* Convert x (echo input) to frequency domain */ - spx_fft(st->fft_table, st->x+speak*N, &st->X[speak*N]); - } - - Sxx = 0; - for (speak = 0; speak < K; speak++) - { - Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size); - power_spectrum_accum(st->X+speak*N, st->Xf, N); - } - - Sff = 0; - for (chan = 0; chan < C; chan++) - { -#ifdef TWO_PATH - /* Compute foreground filter */ - spectral_mul_accum16(st->X, st->foreground+chan*N*K*M, st->Y+chan*N, N, M*K); - spx_ifft(st->fft_table, st->Y+chan*N, st->e+chan*N); - for (i=0;i<st->frame_size;i++) - st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->e[chan*N+i+st->frame_size]); - Sff += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); -#endif - } - - /* Adjust proportional adaption rate */ - /* FIXME: Adjust that for C, K*/ - if (st->adapted) - mdf_adjust_prop (st->W, N, M, C*K, st->prop); - /* Compute weight gradient */ - if (st->saturated == 0) - { - for (chan = 0; chan < C; chan++) - { - for (speak = 0; speak < K; speak++) - { - for (j=M-1;j>=0;j--) - { - weighted_spectral_mul_conj(st->power_1, FLOAT_SHL(PSEUDOFLOAT(st->prop[j]),-15), &st->X[(j+1)*N*K+speak*N], st->E+chan*N, st->PHI, N); - for (i=0;i<N;i++) - st->W[chan*N*K*M + j*N*K + speak*N + i] += st->PHI[i]; - } - } - } - } else { - st->saturated--; - } - - /* FIXME: MC conversion required */ - /* Update weight to prevent circular convolution (MDF / AUMDF) */ - for (chan = 0; chan < C; chan++) - { - for (speak = 0; speak < K; speak++) - { - for (j=0;j<M;j++) - { - /* This is a variant of the Alternatively Updated MDF (AUMDF) */ - /* Remove the "if" to make this an MDF filter */ - if (j==0 || st->cancel_count%(M-1) == j-1) - { -#ifdef FIXED_POINT - for (i=0;i<N;i++) - st->wtmp2[i] = EXTRACT16(PSHR32(st->W[chan*N*K*M + j*N*K + speak*N + i],NORMALIZE_SCALEDOWN+16)); - spx_ifft(st->fft_table, st->wtmp2, st->wtmp); - for (i=0;i<st->frame_size;i++) - { - st->wtmp[i]=0; - } - for (i=st->frame_size;i<N;i++) - { - st->wtmp[i]=SHL16(st->wtmp[i],NORMALIZE_SCALEUP); - } - spx_fft(st->fft_table, st->wtmp, st->wtmp2); - /* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */ - for (i=0;i<N;i++) - st->W[chan*N*K*M + j*N*K + speak*N + i] -= SHL32(EXTEND32(st->wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1); -#else - spx_ifft(st->fft_table, &st->W[chan*N*K*M + j*N*K + speak*N], st->wtmp); - for (i=st->frame_size;i<N;i++) - { - st->wtmp[i]=0; - } - spx_fft(st->fft_table, st->wtmp, &st->W[chan*N*K*M + j*N*K + speak*N]); -#endif - } - } - } - } - - /* So we can use power_spectrum_accum */ - for (i=0;i<=st->frame_size;i++) - st->Rf[i] = st->Yf[i] = st->Xf[i] = 0; - - Dbf = 0; - See = 0; -#ifdef TWO_PATH - /* Difference in response, this is used to estimate the variance of our residual power estimate */ - for (chan = 0; chan < C; chan++) - { - spectral_mul_accum(st->X, st->W+chan*N*K*M, st->Y+chan*N, N, M*K); - spx_ifft(st->fft_table, st->Y+chan*N, st->y+chan*N); - for (i=0;i<st->frame_size;i++) - st->e[chan*N+i] = SUB16(st->e[chan*N+i+st->frame_size], st->y[chan*N+i+st->frame_size]); - Dbf += 10+mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); - for (i=0;i<st->frame_size;i++) - st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]); - See += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); - } -#endif - -#ifndef TWO_PATH - Sff = See; -#endif - -#ifdef TWO_PATH - /* Logic for updating the foreground filter */ - - /* For two time windows, compute the mean of the energy difference, as well as the variance */ - st->Davg1 = ADD32(MULT16_32_Q15(QCONST16(.6f,15),st->Davg1), MULT16_32_Q15(QCONST16(.4f,15),SUB32(Sff,See))); - st->Davg2 = ADD32(MULT16_32_Q15(QCONST16(.85f,15),st->Davg2), MULT16_32_Q15(QCONST16(.15f,15),SUB32(Sff,See))); - st->Dvar1 = FLOAT_ADD(FLOAT_MULT(VAR1_SMOOTH, st->Dvar1), FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.4f,15),Sff), MULT16_32_Q15(QCONST16(.4f,15),Dbf))); - st->Dvar2 = FLOAT_ADD(FLOAT_MULT(VAR2_SMOOTH, st->Dvar2), FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.15f,15),Sff), MULT16_32_Q15(QCONST16(.15f,15),Dbf))); - - /* Equivalent float code: - st->Davg1 = .6*st->Davg1 + .4*(Sff-See); - st->Davg2 = .85*st->Davg2 + .15*(Sff-See); - st->Dvar1 = .36*st->Dvar1 + .16*Sff*Dbf; - st->Dvar2 = .7225*st->Dvar2 + .0225*Sff*Dbf; - */ - - update_foreground = 0; - /* Check if we have a statistically significant reduction in the residual echo */ - /* Note that this is *not* Gaussian, so we need to be careful about the longer tail */ - if (FLOAT_GT(FLOAT_MUL32U(SUB32(Sff,See),ABS32(SUB32(Sff,See))), FLOAT_MUL32U(Sff,Dbf))) - update_foreground = 1; - else if (FLOAT_GT(FLOAT_MUL32U(st->Davg1, ABS32(st->Davg1)), FLOAT_MULT(VAR1_UPDATE,(st->Dvar1)))) - update_foreground = 1; - else if (FLOAT_GT(FLOAT_MUL32U(st->Davg2, ABS32(st->Davg2)), FLOAT_MULT(VAR2_UPDATE,(st->Dvar2)))) - update_foreground = 1; - - /* Do we update? */ - if (update_foreground) - { - st->Davg1 = st->Davg2 = 0; - st->Dvar1 = st->Dvar2 = FLOAT_ZERO; - /* Copy background filter to foreground filter */ - for (i=0;i<N*M*C*K;i++) - st->foreground[i] = EXTRACT16(PSHR32(st->W[i],16)); - /* Apply a smooth transition so as to not introduce blocking artifacts */ - for (chan = 0; chan < C; chan++) - for (i=0;i<st->frame_size;i++) - st->e[chan*N+i+st->frame_size] = MULT16_16_Q15(st->window[i+st->frame_size],st->e[chan*N+i+st->frame_size]) + MULT16_16_Q15(st->window[i],st->y[chan*N+i+st->frame_size]); - } else { - int reset_background=0; - /* Otherwise, check if the background filter is significantly worse */ - if (FLOAT_GT(FLOAT_MUL32U(NEG32(SUB32(Sff,See)),ABS32(SUB32(Sff,See))), FLOAT_MULT(VAR_BACKTRACK,FLOAT_MUL32U(Sff,Dbf)))) - reset_background = 1; - if (FLOAT_GT(FLOAT_MUL32U(NEG32(st->Davg1), ABS32(st->Davg1)), FLOAT_MULT(VAR_BACKTRACK,st->Dvar1))) - reset_background = 1; - if (FLOAT_GT(FLOAT_MUL32U(NEG32(st->Davg2), ABS32(st->Davg2)), FLOAT_MULT(VAR_BACKTRACK,st->Dvar2))) - reset_background = 1; - if (reset_background) - { - /* Copy foreground filter to background filter */ - for (i=0;i<N*M*C*K;i++) - st->W[i] = SHL32(EXTEND32(st->foreground[i]),16); - /* We also need to copy the output so as to get correct adaptation */ - for (chan = 0; chan < C; chan++) - { - for (i=0;i<st->frame_size;i++) - st->y[chan*N+i+st->frame_size] = st->e[chan*N+i+st->frame_size]; - for (i=0;i<st->frame_size;i++) - st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]); - } - See = Sff; - st->Davg1 = st->Davg2 = 0; - st->Dvar1 = st->Dvar2 = FLOAT_ZERO; - } - } -#endif - - Sey = Syy = Sdd = 0; - for (chan = 0; chan < C; chan++) - { - /* Compute error signal (for the output with de-emphasis) */ - for (i=0;i<st->frame_size;i++) - { - spx_word32_t tmp_out; -#ifdef TWO_PATH - tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->e[chan*N+i+st->frame_size])); -#else - tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->y[chan*N+i+st->frame_size])); -#endif - tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(st->preemph, st->memE[chan]))); - /* This is an arbitrary test for saturation in the microphone signal */ - if (in[i*C+chan] <= -32000 || in[i*C+chan] >= 32000) - { - if (st->saturated == 0) - st->saturated = 1; - } - out[i*C+chan] = WORD2INT(tmp_out); - st->memE[chan] = tmp_out; - } - -#ifdef DUMP_ECHO_CANCEL_DATA - dump_audio(in, far_end, out, st->frame_size); -#endif - - /* Compute error signal (filter update version) */ - for (i=0;i<st->frame_size;i++) - { - st->e[chan*N+i+st->frame_size] = st->e[chan*N+i]; - st->e[chan*N+i] = 0; - } - - /* Compute a bunch of correlations */ - /* FIXME: bad merge */ - Sey += mdf_inner_prod(st->e+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size); - Syy += mdf_inner_prod(st->y+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size); - Sdd += mdf_inner_prod(st->input+chan*st->frame_size, st->input+chan*st->frame_size, st->frame_size); - - /* Convert error to frequency domain */ - spx_fft(st->fft_table, st->e+chan*N, st->E+chan*N); - for (i=0;i<st->frame_size;i++) - st->y[i+chan*N] = 0; - spx_fft(st->fft_table, st->y+chan*N, st->Y+chan*N); - - /* Compute power spectrum of echo (X), error (E) and filter response (Y) */ - power_spectrum_accum(st->E+chan*N, st->Rf, N); - power_spectrum_accum(st->Y+chan*N, st->Yf, N); - - } - - /*printf ("%f %f %f %f\n", Sff, See, Syy, Sdd, st->update_cond);*/ - - /* Do some sanity check */ - if (!(Syy>=0 && Sxx>=0 && See >= 0) -#ifndef FIXED_POINT - || !(Sff < N*1e9 && Syy < N*1e9 && Sxx < N*1e9) -#endif - ) - { - /* Things have gone really bad */ - st->screwed_up += 50; - for (i=0;i<st->frame_size*C;i++) - out[i] = 0; - } else if (SHR32(Sff, 2) > ADD32(Sdd, SHR32(MULT16_16(N, 10000),6))) - { - /* AEC seems to add lots of echo instead of removing it, let's see if it will improve */ - st->screwed_up++; - } else { - /* Everything's fine */ - st->screwed_up=0; - } - if (st->screwed_up>=50) - { - speex_warning("The echo canceller started acting funny and got slapped (reset). It swears it will behave now."); - speex_echo_state_reset(st); - return; - } - - /* Add a small noise floor to make sure not to have problems when dividing */ - See = MAX32(See, SHR32(MULT16_16(N, 100),6)); - - for (speak = 0; speak < K; speak++) - { - Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size); - power_spectrum_accum(st->X+speak*N, st->Xf, N); - } - - - /* Smooth far end energy estimate over time */ - for (j=0;j<=st->frame_size;j++) - st->power[j] = MULT16_32_Q15(ss_1,st->power[j]) + 1 + MULT16_32_Q15(ss,st->Xf[j]); - - /* Compute filtered spectra and (cross-)correlations */ - for (j=st->frame_size;j>=0;j--) - { - spx_float_t Eh, Yh; - Eh = PSEUDOFLOAT(st->Rf[j] - st->Eh[j]); - Yh = PSEUDOFLOAT(st->Yf[j] - st->Yh[j]); - Pey = FLOAT_ADD(Pey,FLOAT_MULT(Eh,Yh)); - Pyy = FLOAT_ADD(Pyy,FLOAT_MULT(Yh,Yh)); -#ifdef FIXED_POINT - st->Eh[j] = MAC16_32_Q15(MULT16_32_Q15(SUB16(32767,st->spec_average),st->Eh[j]), st->spec_average, st->Rf[j]); - st->Yh[j] = MAC16_32_Q15(MULT16_32_Q15(SUB16(32767,st->spec_average),st->Yh[j]), st->spec_average, st->Yf[j]); -#else - st->Eh[j] = (1-st->spec_average)*st->Eh[j] + st->spec_average*st->Rf[j]; - st->Yh[j] = (1-st->spec_average)*st->Yh[j] + st->spec_average*st->Yf[j]; -#endif - } - - Pyy = FLOAT_SQRT(Pyy); - Pey = FLOAT_DIVU(Pey,Pyy); - - /* Compute correlation updatete rate */ - tmp32 = MULT16_32_Q15(st->beta0,Syy); - if (tmp32 > MULT16_32_Q15(st->beta_max,See)) - tmp32 = MULT16_32_Q15(st->beta_max,See); - alpha = FLOAT_DIV32(tmp32, See); - alpha_1 = FLOAT_SUB(FLOAT_ONE, alpha); - /* Update correlations (recursive average) */ - st->Pey = FLOAT_ADD(FLOAT_MULT(alpha_1,st->Pey) , FLOAT_MULT(alpha,Pey)); - st->Pyy = FLOAT_ADD(FLOAT_MULT(alpha_1,st->Pyy) , FLOAT_MULT(alpha,Pyy)); - if (FLOAT_LT(st->Pyy, FLOAT_ONE)) - st->Pyy = FLOAT_ONE; - /* We don't really hope to get better than 33 dB (MIN_LEAK-3dB) attenuation anyway */ - if (FLOAT_LT(st->Pey, FLOAT_MULT(MIN_LEAK,st->Pyy))) - st->Pey = FLOAT_MULT(MIN_LEAK,st->Pyy); - if (FLOAT_GT(st->Pey, st->Pyy)) - st->Pey = st->Pyy; - /* leak_estimate is the linear regression result */ - st->leak_estimate = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIVU(st->Pey, st->Pyy),14)); - /* This looks like a stupid bug, but it's right (because we convert from Q14 to Q15) */ - if (st->leak_estimate > 16383) - st->leak_estimate = 32767; - else - st->leak_estimate = SHL16(st->leak_estimate,1); - /*printf ("%f\n", st->leak_estimate);*/ - - /* Compute Residual to Error Ratio */ -#ifdef FIXED_POINT - tmp32 = MULT16_32_Q15(st->leak_estimate,Syy); - tmp32 = ADD32(SHR32(Sxx,13), ADD32(tmp32, SHL32(tmp32,1))); - /* Check for y in e (lower bound on RER) */ - { - spx_float_t bound = PSEUDOFLOAT(Sey); - bound = FLOAT_DIVU(FLOAT_MULT(bound, bound), PSEUDOFLOAT(ADD32(1,Syy))); - if (FLOAT_GT(bound, PSEUDOFLOAT(See))) - tmp32 = See; - else if (tmp32 < FLOAT_EXTRACT32(bound)) - tmp32 = FLOAT_EXTRACT32(bound); - } - if (tmp32 > SHR32(See,1)) - tmp32 = SHR32(See,1); - RER = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIV32(tmp32,See),15)); -#else - RER = (.0001*Sxx + 3.*MULT16_32_Q15(st->leak_estimate,Syy)) / See; - /* Check for y in e (lower bound on RER) */ - if (RER < Sey*Sey/(1+See*Syy)) - RER = Sey*Sey/(1+See*Syy); - if (RER > .5) - RER = .5; -#endif - - /* We consider that the filter has had minimal adaptation if the following is true*/ - if (!st->adapted && st->sum_adapt > SHL32(EXTEND32(M),15) && MULT16_32_Q15(st->leak_estimate,Syy) > MULT16_32_Q15(QCONST16(.03f,15),Syy)) - { - st->adapted = 1; - } - - if (st->adapted) - { - /* Normal learning rate calculation once we're past the minimal adaptation phase */ - for (i=0;i<=st->frame_size;i++) - { - spx_word32_t r, e; - /* Compute frequency-domain adaptation mask */ - r = MULT16_32_Q15(st->leak_estimate,SHL32(st->Yf[i],3)); - e = SHL32(st->Rf[i],3)+1; -#ifdef FIXED_POINT - if (r>SHR32(e,1)) - r = SHR32(e,1); -#else - if (r>.5*e) - r = .5*e; -#endif - r = MULT16_32_Q15(QCONST16(.7,15),r) + MULT16_32_Q15(QCONST16(.3,15),(spx_word32_t)(MULT16_32_Q15(RER,e))); - /*st->power_1[i] = adapt_rate*r/(e*(1+st->power[i]));*/ - st->power_1[i] = FLOAT_SHL(FLOAT_DIV32_FLOAT(r,FLOAT_MUL32U(e,st->power[i]+10)),WEIGHT_SHIFT+16); - } - } else { - /* Temporary adaption rate if filter is not yet adapted enough */ - spx_word16_t adapt_rate=0; - - if (Sxx > SHR32(MULT16_16(N, 1000),6)) - { - tmp32 = MULT16_32_Q15(QCONST16(.25f, 15), Sxx); -#ifdef FIXED_POINT - if (tmp32 > SHR32(See,2)) - tmp32 = SHR32(See,2); -#else - if (tmp32 > .25*See) - tmp32 = .25*See; -#endif - adapt_rate = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIV32(tmp32, See),15)); - } - for (i=0;i<=st->frame_size;i++) - st->power_1[i] = FLOAT_SHL(FLOAT_DIV32(EXTEND32(adapt_rate),ADD32(st->power[i],10)),WEIGHT_SHIFT+1); - - - /* How much have we adapted so far? */ - st->sum_adapt = ADD32(st->sum_adapt,adapt_rate); - } - - /* FIXME: MC conversion required */ - for (i=0;i<st->frame_size;i++) - st->last_y[i] = st->last_y[st->frame_size+i]; - if (st->adapted) - { - /* If the filter is adapted, take the filtered echo */ - for (i=0;i<st->frame_size;i++) - st->last_y[st->frame_size+i] = in[i]-out[i]; - } else { - /* If filter isn't adapted yet, all we can do is take the far end signal directly */ - /* moved earlier: for (i=0;i<N;i++) - st->last_y[i] = st->x[i];*/ - } - -} - -/* Compute spectrum of estimated echo for use in an echo post-filter */ -void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *residual_echo, int len) -{ - int i; - spx_word16_t leak2; - int N; - - N = st->window_size; - - /* Apply hanning window (should pre-compute it)*/ - for (i=0;i<N;i++) - st->y[i] = MULT16_16_Q15(st->window[i],st->last_y[i]); - - /* Compute power spectrum of the echo */ - spx_fft(st->fft_table, st->y, st->Y); - power_spectrum(st->Y, residual_echo, N); - -#ifdef FIXED_POINT - if (st->leak_estimate > 16383) - leak2 = 32767; - else - leak2 = SHL16(st->leak_estimate, 1); -#else - if (st->leak_estimate>.5) - leak2 = 1; - else - leak2 = 2*st->leak_estimate; -#endif - /* Estimate residual echo */ - for (i=0;i<=st->frame_size;i++) - residual_echo[i] = (spx_int32_t)MULT16_32_Q15(leak2,residual_echo[i]); - -} - -EXPORT int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr) -{ - switch(request) - { - - case SPEEX_ECHO_GET_FRAME_SIZE: - (*(int*)ptr) = st->frame_size; - break; - case SPEEX_ECHO_SET_SAMPLING_RATE: - st->sampling_rate = (*(int*)ptr); - st->spec_average = DIV32_16(SHL32(EXTEND32(st->frame_size), 15), st->sampling_rate); -#ifdef FIXED_POINT - st->beta0 = DIV32_16(SHL32(EXTEND32(st->frame_size), 16), st->sampling_rate); - st->beta_max = DIV32_16(SHL32(EXTEND32(st->frame_size), 14), st->sampling_rate); -#else - st->beta0 = (2.0f*st->frame_size)/st->sampling_rate; - st->beta_max = (.5f*st->frame_size)/st->sampling_rate; -#endif - if (st->sampling_rate<12000) - st->notch_radius = QCONST16(.9, 15); - else if (st->sampling_rate<24000) - st->notch_radius = QCONST16(.982, 15); - else - st->notch_radius = QCONST16(.992, 15); - break; - case SPEEX_ECHO_GET_SAMPLING_RATE: - (*(int*)ptr) = st->sampling_rate; - break; - case SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE: - /*FIXME: Implement this for multiple channels */ - *((spx_int32_t *)ptr) = st->M * st->frame_size; - break; - case SPEEX_ECHO_GET_IMPULSE_RESPONSE: - { - int M = st->M, N = st->window_size, n = st->frame_size, i, j; - spx_int32_t *filt = (spx_int32_t *) ptr; - for(j=0;j<M;j++) - { - /*FIXME: Implement this for multiple channels */ -#ifdef FIXED_POINT - for (i=0;i<N;i++) - st->wtmp2[i] = EXTRACT16(PSHR32(st->W[j*N+i],16+NORMALIZE_SCALEDOWN)); - spx_ifft(st->fft_table, st->wtmp2, st->wtmp); -#else - spx_ifft(st->fft_table, &st->W[j*N], st->wtmp); -#endif - for(i=0;i<n;i++) - filt[j*n+i] = PSHR32(MULT16_16(32767,st->wtmp[i]), WEIGHT_SHIFT-NORMALIZE_SCALEDOWN); - } - } - break; - default: - speex_warning_int("Unknown speex_echo_ctl request: ", request); - return -1; - } - return 0; -} diff --git a/drivers/speex/misc_bfin.h b/drivers/speex/misc_bfin.h deleted file mode 100644 index 77b082c057..0000000000 --- a/drivers/speex/misc_bfin.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (C) 2005 Analog Devices */ -/** - @file misc_bfin.h - @author Jean-Marc Valin - @brief Various compatibility routines for Speex (Blackfin version) -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#define OVERRIDE_SPEEX_MOVE -void *speex_move (void *dest, void *src, int n) -{ - __asm__ __volatile__ - ( - "L0 = 0;\n\t" - "I0 = %0;\n\t" - "R0 = [I0++];\n\t" - "LOOP move%= LC0 = %2;\n\t" - "LOOP_BEGIN move%=;\n\t" - "[%1++] = R0 || R0 = [I0++];\n\t" - "LOOP_END move%=;\n\t" - "[%1++] = R0;\n\t" - : "=a" (src), "=a" (dest) - : "a" ((n>>2)-1), "0" (src), "1" (dest) - : "R0", "I0", "L0", "memory" - ); - return dest; -} diff --git a/drivers/speex/modes.c b/drivers/speex/modes.c deleted file mode 100644 index 08c8633a73..0000000000 --- a/drivers/speex/modes.c +++ /dev/null @@ -1,366 +0,0 @@ -/* Copyright (C) 2002-2006 Jean-Marc Valin - File: modes.c - - Describes the different modes of the codec - - 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 the Xiph.org Foundation nor the names of its - 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 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. - -*/ - - -#include "config.h" - - -#include "modes.h" -#include "ltp.h" -#include "quant_lsp.h" -#include "cb_search.h" -#include "sb_celp.h" -#include "nb_celp.h" -#include "vbr.h" -#include "arch.h" -#include <math.h> - -#ifndef NULL -#define NULL 0 -#endif - - -/* Extern declarations for all codebooks we use here */ -extern const signed char gain_cdbk_nb[]; -extern const signed char gain_cdbk_lbr[]; -extern const signed char exc_5_256_table[]; -extern const signed char exc_5_64_table[]; -extern const signed char exc_8_128_table[]; -extern const signed char exc_10_32_table[]; -extern const signed char exc_10_16_table[]; -extern const signed char exc_20_32_table[]; - - -/* Parameters for Long-Term Prediction (LTP)*/ -static const ltp_params ltp_params_nb = { - gain_cdbk_nb, - 7, - 7 -}; - -/* Parameters for Long-Term Prediction (LTP)*/ -static const ltp_params ltp_params_vlbr = { - gain_cdbk_lbr, - 5, - 0 -}; - -/* Parameters for Long-Term Prediction (LTP)*/ -static const ltp_params ltp_params_lbr = { - gain_cdbk_lbr, - 5, - 7 -}; - -/* Parameters for Long-Term Prediction (LTP)*/ -static const ltp_params ltp_params_med = { - gain_cdbk_lbr, - 5, - 7 -}; - -/* Split-VQ innovation parameters for very low bit-rate narrowband */ -static const split_cb_params split_cb_nb_vlbr = { - 10, /*subvect_size*/ - 4, /*nb_subvect*/ - exc_10_16_table, /*shape_cb*/ - 4, /*shape_bits*/ - 0, -}; - -/* Split-VQ innovation parameters for very low bit-rate narrowband */ -static const split_cb_params split_cb_nb_ulbr = { - 20, /*subvect_size*/ - 2, /*nb_subvect*/ - exc_20_32_table, /*shape_cb*/ - 5, /*shape_bits*/ - 0, -}; - -/* Split-VQ innovation parameters for low bit-rate narrowband */ -static const split_cb_params split_cb_nb_lbr = { - 10, /*subvect_size*/ - 4, /*nb_subvect*/ - exc_10_32_table, /*shape_cb*/ - 5, /*shape_bits*/ - 0, -}; - - -/* Split-VQ innovation parameters narrowband */ -static const split_cb_params split_cb_nb = { - 5, /*subvect_size*/ - 8, /*nb_subvect*/ - exc_5_64_table, /*shape_cb*/ - 6, /*shape_bits*/ - 0, -}; - -/* Split-VQ innovation parameters narrowband */ -static const split_cb_params split_cb_nb_med = { - 8, /*subvect_size*/ - 5, /*nb_subvect*/ - exc_8_128_table, /*shape_cb*/ - 7, /*shape_bits*/ - 0, -}; - -/* Split-VQ innovation for low-band wideband */ -static const split_cb_params split_cb_sb = { - 5, /*subvect_size*/ - 8, /*nb_subvect*/ - exc_5_256_table, /*shape_cb*/ - 8, /*shape_bits*/ - 0, -}; - - - -/* 2150 bps "vocoder-like" mode for comfort noise */ -static const SpeexSubmode nb_submode1 = { - 0, - 1, - 0, - 0, - /* LSP quantization */ - lsp_quant_lbr, - lsp_unquant_lbr, - /* No pitch quantization */ - forced_pitch_quant, - forced_pitch_unquant, - NULL, - /* No innovation quantization (noise only) */ - noise_codebook_quant, - noise_codebook_unquant, - NULL, - -1, - 43 -}; - -/* 3.95 kbps very low bit-rate mode */ -static const SpeexSubmode nb_submode8 = { - 0, - 1, - 0, - 0, - /*LSP quantization*/ - lsp_quant_lbr, - lsp_unquant_lbr, - /*No pitch quantization*/ - forced_pitch_quant, - forced_pitch_unquant, - NULL, - /*Innovation quantization*/ - split_cb_search_shape_sign, - split_cb_shape_sign_unquant, - &split_cb_nb_ulbr, - QCONST16(.5,15), - 79 -}; - -/* 5.95 kbps very low bit-rate mode */ -static const SpeexSubmode nb_submode2 = { - 0, - 0, - 0, - 0, - /*LSP quantization*/ - lsp_quant_lbr, - lsp_unquant_lbr, - /*No pitch quantization*/ - pitch_search_3tap, - pitch_unquant_3tap, - <p_params_vlbr, - /*Innovation quantization*/ - split_cb_search_shape_sign, - split_cb_shape_sign_unquant, - &split_cb_nb_vlbr, - QCONST16(.6,15), - 119 -}; - -/* 8 kbps low bit-rate mode */ -static const SpeexSubmode nb_submode3 = { - -1, - 0, - 1, - 0, - /*LSP quantization*/ - lsp_quant_lbr, - lsp_unquant_lbr, - /*Pitch quantization*/ - pitch_search_3tap, - pitch_unquant_3tap, - <p_params_lbr, - /*Innovation quantization*/ - split_cb_search_shape_sign, - split_cb_shape_sign_unquant, - &split_cb_nb_lbr, - QCONST16(.55,15), - 160 -}; - -/* 11 kbps medium bit-rate mode */ -static const SpeexSubmode nb_submode4 = { - -1, - 0, - 1, - 0, - /*LSP quantization*/ - lsp_quant_lbr, - lsp_unquant_lbr, - /*Pitch quantization*/ - pitch_search_3tap, - pitch_unquant_3tap, - <p_params_med, - /*Innovation quantization*/ - split_cb_search_shape_sign, - split_cb_shape_sign_unquant, - &split_cb_nb_med, - QCONST16(.45,15), - 220 -}; - -/* 15 kbps high bit-rate mode */ -static const SpeexSubmode nb_submode5 = { - -1, - 0, - 3, - 0, - /*LSP quantization*/ - lsp_quant_nb, - lsp_unquant_nb, - /*Pitch quantization*/ - pitch_search_3tap, - pitch_unquant_3tap, - <p_params_nb, - /*Innovation quantization*/ - split_cb_search_shape_sign, - split_cb_shape_sign_unquant, - &split_cb_nb, - QCONST16(.3,15), - 300 -}; - -/* 18.2 high bit-rate mode */ -static const SpeexSubmode nb_submode6 = { - -1, - 0, - 3, - 0, - /*LSP quantization*/ - lsp_quant_nb, - lsp_unquant_nb, - /*Pitch quantization*/ - pitch_search_3tap, - pitch_unquant_3tap, - <p_params_nb, - /*Innovation quantization*/ - split_cb_search_shape_sign, - split_cb_shape_sign_unquant, - &split_cb_sb, - QCONST16(.2,15), - 364 -}; - -/* 24.6 kbps high bit-rate mode */ -static const SpeexSubmode nb_submode7 = { - -1, - 0, - 3, - 1, - /*LSP quantization*/ - lsp_quant_nb, - lsp_unquant_nb, - /*Pitch quantization*/ - pitch_search_3tap, - pitch_unquant_3tap, - <p_params_nb, - /*Innovation quantization*/ - split_cb_search_shape_sign, - split_cb_shape_sign_unquant, - &split_cb_nb, - QCONST16(.1,15), - 492 -}; - - -/* Default mode for narrowband */ -static const SpeexNBMode nb_mode = { - 160, /*frameSize*/ - 40, /*subframeSize*/ - 10, /*lpcSize*/ - 17, /*pitchStart*/ - 144, /*pitchEnd*/ -#ifdef FIXED_POINT - 29491, 19661, /* gamma1, gamma2 */ -#else - 0.9, 0.6, /* gamma1, gamma2 */ -#endif - QCONST16(.0002,15), /*lpc_floor*/ - {NULL, &nb_submode1, &nb_submode2, &nb_submode3, &nb_submode4, &nb_submode5, &nb_submode6, &nb_submode7, - &nb_submode8, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - 5, - {1, 8, 2, 3, 3, 4, 4, 5, 5, 6, 7} -}; - - -/* Default mode for narrowband */ -EXPORT const SpeexMode speex_nb_mode = { - &nb_mode, - nb_mode_query, - "narrowband", - 0, - 4, - &nb_encoder_init, - &nb_encoder_destroy, - &nb_encode, - &nb_decoder_init, - &nb_decoder_destroy, - &nb_decode, - &nb_encoder_ctl, - &nb_decoder_ctl, -}; - - - -EXPORT int speex_mode_query(const SpeexMode *mode, int request, void *ptr) -{ - return mode->query(mode->mode, request, ptr); -} - -#ifdef FIXED_DEBUG -long long spx_mips=0; -#endif - diff --git a/drivers/speex/modes.h b/drivers/speex/modes.h deleted file mode 100644 index 26e2d86180..0000000000 --- a/drivers/speex/modes.h +++ /dev/null @@ -1,161 +0,0 @@ -/* Copyright (C) 2002-2006 Jean-Marc Valin */ -/** - @file modes.h - @brief Describes the different modes of the codec -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 MODES_H -#define MODES_H - -#include <speex/speex.h> -#include <speex/speex_bits.h> -#include "arch.h" - -#define NB_SUBMODES 16 -#define NB_SUBMODE_BITS 4 - -#define SB_SUBMODES 8 -#define SB_SUBMODE_BITS 3 - -/* Used internally, NOT TO BE USED in applications */ -/** Used internally*/ -#define SPEEX_GET_PI_GAIN 100 -/** Used internally*/ -#define SPEEX_GET_EXC 101 -/** Used internally*/ -#define SPEEX_GET_INNOV 102 -/** Used internally*/ -#define SPEEX_GET_DTX_STATUS 103 -/** Used internally*/ -#define SPEEX_SET_INNOVATION_SAVE 104 -/** Used internally*/ -#define SPEEX_SET_WIDEBAND 105 - -/** Used internally*/ -#define SPEEX_GET_STACK 106 - - -/** Quantizes LSPs */ -typedef void (*lsp_quant_func)(spx_lsp_t *, spx_lsp_t *, int, SpeexBits *); - -/** Decodes quantized LSPs */ -typedef void (*lsp_unquant_func)(spx_lsp_t *, int, SpeexBits *); - - -/** Long-term predictor quantization */ -typedef int (*ltp_quant_func)(spx_word16_t *, spx_word16_t *, spx_coef_t *, spx_coef_t *, - spx_coef_t *, spx_sig_t *, const void *, int, int, spx_word16_t, - int, int, SpeexBits*, char *, spx_word16_t *, spx_word16_t *, int, int, int, spx_word32_t *); - -/** Long-term un-quantize */ -typedef void (*ltp_unquant_func)(spx_word16_t *, spx_word32_t *, int, int, spx_word16_t, const void *, int, int *, - spx_word16_t *, SpeexBits*, char*, int, int, spx_word16_t, int); - - -/** Innovation quantization function */ -typedef void (*innovation_quant_func)(spx_word16_t *, spx_coef_t *, spx_coef_t *, spx_coef_t *, const void *, int, int, - spx_sig_t *, spx_word16_t *, SpeexBits *, char *, int, int); - -/** Innovation unquantization function */ -typedef void (*innovation_unquant_func)(spx_sig_t *, const void *, int, SpeexBits*, char *, spx_int32_t *); - -/** Description of a Speex sub-mode (wither narrowband or wideband */ -typedef struct SpeexSubmode { - int lbr_pitch; /**< Set to -1 for "normal" modes, otherwise encode pitch using a global pitch and allowing a +- lbr_pitch variation (for low not-rates)*/ - int forced_pitch_gain; /**< Use the same (forced) pitch gain for all sub-frames */ - int have_subframe_gain; /**< Number of bits to use as sub-frame innovation gain */ - int double_codebook; /**< Apply innovation quantization twice for higher quality (and higher bit-rate)*/ - /*LSP functions*/ - lsp_quant_func lsp_quant; /**< LSP quantization function */ - lsp_unquant_func lsp_unquant; /**< LSP unquantization function */ - - /*Long-term predictor functions*/ - ltp_quant_func ltp_quant; /**< Long-term predictor (pitch) quantizer */ - ltp_unquant_func ltp_unquant; /**< Long-term predictor (pitch) un-quantizer */ - const void *ltp_params; /**< Pitch parameters (options) */ - - /*Quantization of innovation*/ - innovation_quant_func innovation_quant; /**< Innovation quantization */ - innovation_unquant_func innovation_unquant; /**< Innovation un-quantization */ - const void *innovation_params; /**< Innovation quantization parameters*/ - - spx_word16_t comb_gain; /**< Gain of enhancer comb filter */ - - int bits_per_frame; /**< Number of bits per frame after encoding*/ -} SpeexSubmode; - -/** Struct defining the encoding/decoding mode*/ -typedef struct SpeexNBMode { - int frameSize; /**< Size of frames used for encoding */ - int subframeSize; /**< Size of sub-frames used for encoding */ - int lpcSize; /**< Order of LPC filter */ - int pitchStart; /**< Smallest pitch value allowed */ - int pitchEnd; /**< Largest pitch value allowed */ - - spx_word16_t gamma1; /**< Perceptual filter parameter #1 */ - spx_word16_t gamma2; /**< Perceptual filter parameter #2 */ - spx_word16_t lpc_floor; /**< Noise floor for LPC analysis */ - - const SpeexSubmode *submodes[NB_SUBMODES]; /**< Sub-mode data for the mode */ - int defaultSubmode; /**< Default sub-mode to use when encoding */ - int quality_map[11]; /**< Mode corresponding to each quality setting */ -} SpeexNBMode; - - -/** Struct defining the encoding/decoding mode for SB-CELP (wideband) */ -typedef struct SpeexSBMode { - const SpeexMode *nb_mode; /**< Embedded narrowband mode */ - int frameSize; /**< Size of frames used for encoding */ - int subframeSize; /**< Size of sub-frames used for encoding */ - int lpcSize; /**< Order of LPC filter */ - spx_word16_t gamma1; /**< Perceptual filter parameter #1 */ - spx_word16_t gamma2; /**< Perceptual filter parameter #1 */ - spx_word16_t lpc_floor; /**< Noise floor for LPC analysis */ - spx_word16_t folding_gain; - - const SpeexSubmode *submodes[SB_SUBMODES]; /**< Sub-mode data for the mode */ - int defaultSubmode; /**< Default sub-mode to use when encoding */ - int low_quality_map[11]; /**< Mode corresponding to each quality setting */ - int quality_map[11]; /**< Mode corresponding to each quality setting */ -#ifndef DISABLE_VBR - const float (*vbr_thresh)[11]; -#endif - int nb_modes; -} SpeexSBMode; - -int speex_encode_native(void *state, spx_word16_t *in, SpeexBits *bits); -int speex_decode_native(void *state, SpeexBits *bits, spx_word16_t *out); - -int nb_mode_query(const void *mode, int request, void *ptr); -int wb_mode_query(const void *mode, int request, void *ptr); - -#endif diff --git a/drivers/speex/modes_wb.c b/drivers/speex/modes_wb.c deleted file mode 100644 index e9bab88ab7..0000000000 --- a/drivers/speex/modes_wb.c +++ /dev/null @@ -1,300 +0,0 @@ -/* Copyright (C) 2002-2007 Jean-Marc Valin - File: modes.c - - Describes the wideband modes of the codec - - 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 the Xiph.org Foundation nor the names of its - 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 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. - -*/ - - -#include "config.h" - - -#include "modes.h" -#include "ltp.h" -#include "quant_lsp.h" -#include "cb_search.h" -#include "sb_celp.h" -#include "nb_celp.h" -#include "vbr.h" -#include "arch.h" -#include <math.h> -#include "os_support.h" - - -#ifndef NULL -#define NULL 0 -#endif - -EXPORT const SpeexMode * const speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, &speex_uwb_mode}; - -extern const signed char hexc_table[]; -extern const signed char hexc_10_32_table[]; - -#ifndef DISABLE_WIDEBAND - -/* Split-VQ innovation for high-band wideband */ -static const split_cb_params split_cb_high = { - 8, /*subvect_size*/ - 5, /*nb_subvect*/ - hexc_table, /*shape_cb*/ - 7, /*shape_bits*/ - 1, -}; - - -/* Split-VQ innovation for high-band wideband */ -static const split_cb_params split_cb_high_lbr = { - 10, /*subvect_size*/ - 4, /*nb_subvect*/ - hexc_10_32_table, /*shape_cb*/ - 5, /*shape_bits*/ - 0, -}; - -#endif - - -static const SpeexSubmode wb_submode1 = { - 0, - 0, - 1, - 0, - /*LSP quantization*/ - lsp_quant_high, - lsp_unquant_high, - /*Pitch quantization*/ - NULL, - NULL, - NULL, - /*No innovation quantization*/ - NULL, - NULL, - NULL, - -1, - 36 -}; - - -static const SpeexSubmode wb_submode2 = { - 0, - 0, - 1, - 0, - /*LSP quantization*/ - lsp_quant_high, - lsp_unquant_high, - /*Pitch quantization*/ - NULL, - NULL, - NULL, - /*Innovation quantization*/ - split_cb_search_shape_sign, - split_cb_shape_sign_unquant, -#ifdef DISABLE_WIDEBAND - NULL, -#else - &split_cb_high_lbr, -#endif - -1, - 112 -}; - - -static const SpeexSubmode wb_submode3 = { - 0, - 0, - 1, - 0, - /*LSP quantization*/ - lsp_quant_high, - lsp_unquant_high, - /*Pitch quantization*/ - NULL, - NULL, - NULL, - /*Innovation quantization*/ - split_cb_search_shape_sign, - split_cb_shape_sign_unquant, -#ifdef DISABLE_WIDEBAND - NULL, -#else - &split_cb_high, -#endif - -1, - 192 -}; - -static const SpeexSubmode wb_submode4 = { - 0, - 0, - 1, - 1, - /*LSP quantization*/ - lsp_quant_high, - lsp_unquant_high, - /*Pitch quantization*/ - NULL, - NULL, - NULL, - /*Innovation quantization*/ - split_cb_search_shape_sign, - split_cb_shape_sign_unquant, -#ifdef DISABLE_WIDEBAND - NULL, -#else - &split_cb_high, -#endif - -1, - 352 -}; - - -/* Split-band wideband CELP mode*/ -static const SpeexSBMode sb_wb_mode = { - &speex_nb_mode, - 160, /*frameSize*/ - 40, /*subframeSize*/ - 8, /*lpcSize*/ -#ifdef FIXED_POINT - 29491, 19661, /* gamma1, gamma2 */ -#else - 0.9, 0.6, /* gamma1, gamma2 */ -#endif - QCONST16(.0002,15), /*lpc_floor*/ - QCONST16(0.9f,15), - {NULL, &wb_submode1, &wb_submode2, &wb_submode3, &wb_submode4, NULL, NULL, NULL}, - 3, - {1, 8, 2, 3, 4, 5, 5, 6, 6, 7, 7}, - {1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4}, -#ifndef DISABLE_VBR - vbr_hb_thresh, -#endif - 5 -}; - - -EXPORT const SpeexMode speex_wb_mode = { - &sb_wb_mode, - wb_mode_query, - "wideband (sub-band CELP)", - 1, - 4, - &sb_encoder_init, - &sb_encoder_destroy, - &sb_encode, - &sb_decoder_init, - &sb_decoder_destroy, - &sb_decode, - &sb_encoder_ctl, - &sb_decoder_ctl, -}; - - - -/* "Ultra-wideband" mode stuff */ - - - -/* Split-band "ultra-wideband" (32 kbps) CELP mode*/ -static const SpeexSBMode sb_uwb_mode = { - &speex_wb_mode, - 320, /*frameSize*/ - 80, /*subframeSize*/ - 8, /*lpcSize*/ -#ifdef FIXED_POINT - 29491, 19661, /* gamma1, gamma2 */ -#else - 0.9, 0.6, /* gamma1, gamma2 */ -#endif - QCONST16(.0002,15), /*lpc_floor*/ - QCONST16(0.7f,15), - {NULL, &wb_submode1, NULL, NULL, NULL, NULL, NULL, NULL}, - 1, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, - {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, -#ifndef DISABLE_VBR - vbr_uhb_thresh, -#endif - 2 -}; - -int wb_mode_query(const void *mode, int request, void *ptr) -{ - const SpeexSBMode *m = (const SpeexSBMode*)mode; - - switch (request) - { - case SPEEX_MODE_FRAME_SIZE: - *((int*)ptr)=2*m->frameSize; - break; - case SPEEX_SUBMODE_BITS_PER_FRAME: - if (*((int*)ptr)==0) - *((int*)ptr) = SB_SUBMODE_BITS+1; - else if (m->submodes[*((int*)ptr)]==NULL) - *((int*)ptr) = -1; - else - *((int*)ptr) = m->submodes[*((int*)ptr)]->bits_per_frame; - break; - default: - speex_warning_int("Unknown wb_mode_query request: ", request); - return -1; - } - return 0; -} - - -EXPORT const SpeexMode speex_uwb_mode = { - &sb_uwb_mode, - wb_mode_query, - "ultra-wideband (sub-band CELP)", - 2, - 4, - &sb_encoder_init, - &sb_encoder_destroy, - &sb_encode, - &sb_decoder_init, - &sb_decoder_destroy, - &sb_decode, - &sb_encoder_ctl, - &sb_decoder_ctl, -}; - -/* We have defined speex_lib_get_mode() as a macro in speex.h */ -#undef speex_lib_get_mode - -EXPORT const SpeexMode * speex_lib_get_mode (int mode) -{ - if (mode < 0 || mode >= SPEEX_NB_MODES) return NULL; - - return speex_mode_list[mode]; -} - - - diff --git a/drivers/speex/nb_celp.c b/drivers/speex/nb_celp.c deleted file mode 100644 index 6807c16c9e..0000000000 --- a/drivers/speex/nb_celp.c +++ /dev/null @@ -1,1903 +0,0 @@ -/* Copyright (C) 2002-2006 Jean-Marc Valin - File: nb_celp.c - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -#include "config.h" - - -#include <math.h> -#include "nb_celp.h" -#include "lpc.h" -#include "lsp.h" -#include "ltp.h" -#include "quant_lsp.h" -#include "cb_search.h" -#include "filters.h" -#include "stack_alloc.h" -#include "vq.h" -#include <speex/speex_bits.h> -#include "vbr.h" -#include "arch.h" -#include "math_approx.h" -#include "os_support.h" -#include <speex/speex_callbacks.h> - -#ifdef VORBIS_PSYCHO -#include "vorbis_psy.h" -#endif - -#ifndef M_PI -#define M_PI 3.14159265358979323846 /* pi */ -#endif - -#ifndef NULL -#define NULL 0 -#endif - -#define SUBMODE(x) st->submodes[st->submodeID]->x - -/* Default size for the encoder and decoder stack (can be changed at compile time). - This does not apply when using variable-size arrays or alloca. */ -#ifndef NB_ENC_STACK -#define NB_ENC_STACK (8000*sizeof(spx_sig_t)) -#endif - -#ifndef NB_DEC_STACK -#define NB_DEC_STACK (4000*sizeof(spx_sig_t)) -#endif - - -#ifdef FIXED_POINT -const spx_word32_t ol_gain_table[32]={18900, 25150, 33468, 44536, 59265, 78865, 104946, 139653, 185838, 247297, 329081, 437913, 582736, 775454, 1031906, 1373169, 1827293, 2431601, 3235761, 4305867, 5729870, 7624808, 10146425, 13501971, 17967238, 23909222, 31816294, 42338330, 56340132, 74972501, 99766822, 132760927}; -const spx_word16_t exc_gain_quant_scal3_bound[7]={1841, 3883, 6051, 8062, 10444, 13580, 18560}; -const spx_word16_t exc_gain_quant_scal3[8]={1002, 2680, 5086, 7016, 9108, 11781, 15380, 21740}; -const spx_word16_t exc_gain_quant_scal1_bound[1]={14385}; -const spx_word16_t exc_gain_quant_scal1[2]={11546, 17224}; - -#define LSP_MARGIN 16 -#define LSP_DELTA1 6553 -#define LSP_DELTA2 1638 - -#else - -const float exc_gain_quant_scal3_bound[7]={0.112338f, 0.236980f, 0.369316f, 0.492054f, 0.637471f, 0.828874f, 1.132784f}; -const float exc_gain_quant_scal3[8]={0.061130f, 0.163546f, 0.310413f, 0.428220f, 0.555887f, 0.719055f, 0.938694f, 1.326874f}; -const float exc_gain_quant_scal1_bound[1]={0.87798f}; -const float exc_gain_quant_scal1[2]={0.70469f, 1.05127f}; - -#define LSP_MARGIN .002f -#define LSP_DELTA1 .2f -#define LSP_DELTA2 .05f - -#endif - -#ifdef VORBIS_PSYCHO -#define EXTRA_BUFFER 100 -#else -#define EXTRA_BUFFER 0 -#endif - - -#define sqr(x) ((x)*(x)) - -extern const spx_word16_t lag_window[]; -extern const spx_word16_t lpc_window[]; - -void *nb_encoder_init(const SpeexMode *m) -{ - EncState *st; - const SpeexNBMode *mode; - int i; - - mode=(const SpeexNBMode *)m->mode; - st = (EncState*)speex_alloc(sizeof(EncState)); - if (!st) - return NULL; -#if defined(VAR_ARRAYS) || defined (USE_ALLOCA) - st->stack = NULL; -#else - st->stack = (char*)speex_alloc_scratch(NB_ENC_STACK); -#endif - - st->mode=m; - - st->frameSize = mode->frameSize; - st->nbSubframes=mode->frameSize/mode->subframeSize; - st->subframeSize=mode->subframeSize; - st->windowSize = st->frameSize+st->subframeSize; - st->lpcSize = mode->lpcSize; - st->gamma1=mode->gamma1; - st->gamma2=mode->gamma2; - st->min_pitch=mode->pitchStart; - st->max_pitch=mode->pitchEnd; - st->lpc_floor = mode->lpc_floor; - - st->submodes=mode->submodes; - st->submodeID=st->submodeSelect=mode->defaultSubmode; - st->bounded_pitch = 1; - - st->encode_submode = 1; - -#ifdef VORBIS_PSYCHO - st->psy = vorbis_psy_init(8000, 256); - st->curve = (float*)speex_alloc(128*sizeof(float)); - st->old_curve = (float*)speex_alloc(128*sizeof(float)); - st->psy_window = (float*)speex_alloc(256*sizeof(float)); -#endif - - st->cumul_gain = 1024; - - /* Allocating input buffer */ - st->winBuf = (spx_word16_t*)speex_alloc((st->windowSize-st->frameSize)*sizeof(spx_word16_t)); - /* Allocating excitation buffer */ - st->excBuf = (spx_word16_t*)speex_alloc((mode->frameSize+mode->pitchEnd+2)*sizeof(spx_word16_t)); - st->exc = st->excBuf + mode->pitchEnd + 2; - st->swBuf = (spx_word16_t*)speex_alloc((mode->frameSize+mode->pitchEnd+2)*sizeof(spx_word16_t)); - st->sw = st->swBuf + mode->pitchEnd + 2; - - st->window= lpc_window; - - /* Create the window for autocorrelation (lag-windowing) */ - st->lagWindow = lag_window; - - st->old_lsp = (spx_lsp_t*)speex_alloc((st->lpcSize)*sizeof(spx_lsp_t)); - st->old_qlsp = (spx_lsp_t*)speex_alloc((st->lpcSize)*sizeof(spx_lsp_t)); - st->first = 1; - for (i=0;i<st->lpcSize;i++) - st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), st->lpcSize+1); - - st->mem_sp = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); - st->mem_sw = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); - st->mem_sw_whole = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); - st->mem_exc = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); - st->mem_exc2 = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); - - st->pi_gain = (spx_word32_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word32_t)); - st->innov_rms_save = NULL; - - st->pitch = (int*)speex_alloc((st->nbSubframes)*sizeof(int)); - -#ifndef DISABLE_VBR - st->vbr = (VBRState*)speex_alloc(sizeof(VBRState)); - vbr_init(st->vbr); - st->vbr_quality = 8; - st->vbr_enabled = 0; - st->vbr_max = 0; - st->vad_enabled = 0; - st->dtx_enabled = 0; - st->dtx_count=0; - st->abr_enabled = 0; - st->abr_drift = 0; - st->abr_drift2 = 0; -#endif /* #ifndef DISABLE_VBR */ - - st->plc_tuning = 2; - st->complexity=2; - st->sampling_rate=8000; - st->isWideband = 0; - st->highpass_enabled = 1; - -#ifdef ENABLE_VALGRIND - VALGRIND_MAKE_READABLE(st, NB_ENC_STACK); -#endif - return st; -} - -void nb_encoder_destroy(void *state) -{ - EncState *st=(EncState *)state; - /* Free all allocated memory */ -#if !(defined(VAR_ARRAYS) || defined (USE_ALLOCA)) - speex_free_scratch(st->stack); -#endif - - speex_free (st->winBuf); - speex_free (st->excBuf); - speex_free (st->old_qlsp); - speex_free (st->swBuf); - - speex_free (st->old_lsp); - speex_free (st->mem_sp); - speex_free (st->mem_sw); - speex_free (st->mem_sw_whole); - speex_free (st->mem_exc); - speex_free (st->mem_exc2); - speex_free (st->pi_gain); - speex_free (st->pitch); - -#ifndef DISABLE_VBR - vbr_destroy(st->vbr); - speex_free (st->vbr); -#endif /* #ifndef DISABLE_VBR */ - -#ifdef VORBIS_PSYCHO - vorbis_psy_destroy(st->psy); - speex_free (st->curve); - speex_free (st->old_curve); - speex_free (st->psy_window); -#endif - - /*Free state memory... should be last*/ - speex_free(st); -} - -int nb_encode(void *state, void *vin, SpeexBits *bits) -{ - EncState *st; - int i, sub, roots; - int ol_pitch; - spx_word16_t ol_pitch_coef; - spx_word32_t ol_gain; - VARDECL(spx_word16_t *ringing); - VARDECL(spx_word16_t *target); - VARDECL(spx_sig_t *innov); - VARDECL(spx_word32_t *exc32); - VARDECL(spx_mem_t *mem); - VARDECL(spx_coef_t *bw_lpc1); - VARDECL(spx_coef_t *bw_lpc2); - VARDECL(spx_coef_t *lpc); - VARDECL(spx_lsp_t *lsp); - VARDECL(spx_lsp_t *qlsp); - VARDECL(spx_lsp_t *interp_lsp); - VARDECL(spx_lsp_t *interp_qlsp); - VARDECL(spx_coef_t *interp_lpc); - VARDECL(spx_coef_t *interp_qlpc); - char *stack; - VARDECL(spx_word16_t *syn_resp); - VARDECL(spx_word16_t *real_exc); - - spx_word32_t ener=0; - spx_word16_t fine_gain; - spx_word16_t *in = (spx_word16_t*)vin; - - st=(EncState *)state; - stack=st->stack; - - ALLOC(lpc, st->lpcSize, spx_coef_t); - ALLOC(bw_lpc1, st->lpcSize, spx_coef_t); - ALLOC(bw_lpc2, st->lpcSize, spx_coef_t); - ALLOC(lsp, st->lpcSize, spx_lsp_t); - ALLOC(qlsp, st->lpcSize, spx_lsp_t); - ALLOC(interp_lsp, st->lpcSize, spx_lsp_t); - ALLOC(interp_qlsp, st->lpcSize, spx_lsp_t); - ALLOC(interp_lpc, st->lpcSize, spx_coef_t); - ALLOC(interp_qlpc, st->lpcSize, spx_coef_t); - - /* Move signals 1 frame towards the past */ - SPEEX_MOVE(st->excBuf, st->excBuf+st->frameSize, st->max_pitch+2); - SPEEX_MOVE(st->swBuf, st->swBuf+st->frameSize, st->max_pitch+2); - - if (st->highpass_enabled) - highpass(in, in, st->frameSize, (st->isWideband?HIGHPASS_WIDEBAND:HIGHPASS_NARROWBAND)|HIGHPASS_INPUT, st->mem_hp); - - { - VARDECL(spx_word16_t *w_sig); - VARDECL(spx_word16_t *autocorr); - ALLOC(w_sig, st->windowSize, spx_word16_t); - ALLOC(autocorr, st->lpcSize+1, spx_word16_t); - /* Window for analysis */ - for (i=0;i<st->windowSize-st->frameSize;i++) - w_sig[i] = EXTRACT16(SHR32(MULT16_16(st->winBuf[i],st->window[i]),SIG_SHIFT)); - for (;i<st->windowSize;i++) - w_sig[i] = EXTRACT16(SHR32(MULT16_16(in[i-st->windowSize+st->frameSize],st->window[i]),SIG_SHIFT)); - /* Compute auto-correlation */ - _spx_autocorr(w_sig, autocorr, st->lpcSize+1, st->windowSize); - autocorr[0] = ADD16(autocorr[0],MULT16_16_Q15(autocorr[0],st->lpc_floor)); /* Noise floor in auto-correlation domain */ - - /* Lag windowing: equivalent to filtering in the power-spectrum domain */ - for (i=0;i<st->lpcSize+1;i++) - autocorr[i] = MULT16_16_Q14(autocorr[i],st->lagWindow[i]); - - /* Levinson-Durbin */ - _spx_lpc(lpc, autocorr, st->lpcSize); - /* LPC to LSPs (x-domain) transform */ - roots=lpc_to_lsp (lpc, st->lpcSize, lsp, 10, LSP_DELTA1, stack); - /* Check if we found all the roots */ - if (roots!=st->lpcSize) - { - /*If we can't find all LSP's, do some damage control and use previous filter*/ - for (i=0;i<st->lpcSize;i++) - { - lsp[i]=st->old_lsp[i]; - } - } - } - - - - - /* Whole frame analysis (open-loop estimation of pitch and excitation gain) */ - { - int diff = st->windowSize-st->frameSize; - if (st->first) - for (i=0;i<st->lpcSize;i++) - interp_lsp[i] = lsp[i]; - else - lsp_interpolate(st->old_lsp, lsp, interp_lsp, st->lpcSize, st->nbSubframes, st->nbSubframes<<1); - - lsp_enforce_margin(interp_lsp, st->lpcSize, LSP_MARGIN); - - /* Compute interpolated LPCs (unquantized) for whole frame*/ - lsp_to_lpc(interp_lsp, interp_lpc, st->lpcSize,stack); - - - /*Open-loop pitch*/ - if (!st->submodes[st->submodeID] || (st->complexity>2 && SUBMODE(have_subframe_gain)<3) || SUBMODE(forced_pitch_gain) || SUBMODE(lbr_pitch) != -1 -#ifndef DISABLE_VBR - || st->vbr_enabled || st->vad_enabled -#endif - ) - { - int nol_pitch[6]; - spx_word16_t nol_pitch_coef[6]; - - bw_lpc(st->gamma1, interp_lpc, bw_lpc1, st->lpcSize); - bw_lpc(st->gamma2, interp_lpc, bw_lpc2, st->lpcSize); - - SPEEX_COPY(st->sw, st->winBuf, diff); - SPEEX_COPY(st->sw+diff, in, st->frameSize-diff); - filter_mem16(st->sw, bw_lpc1, bw_lpc2, st->sw, st->frameSize, st->lpcSize, st->mem_sw_whole, stack); - - open_loop_nbest_pitch(st->sw, st->min_pitch, st->max_pitch, st->frameSize, - nol_pitch, nol_pitch_coef, 6, stack); - ol_pitch=nol_pitch[0]; - ol_pitch_coef = nol_pitch_coef[0]; - /*Try to remove pitch multiples*/ - for (i=1;i<6;i++) - { -#ifdef FIXED_POINT - if ((nol_pitch_coef[i]>MULT16_16_Q15(nol_pitch_coef[0],27853)) && -#else - if ((nol_pitch_coef[i]>.85*nol_pitch_coef[0]) && -#endif - (ABS(2*nol_pitch[i]-ol_pitch)<=2 || ABS(3*nol_pitch[i]-ol_pitch)<=3 || - ABS(4*nol_pitch[i]-ol_pitch)<=4 || ABS(5*nol_pitch[i]-ol_pitch)<=5)) - { - /*ol_pitch_coef=nol_pitch_coef[i];*/ - ol_pitch = nol_pitch[i]; - } - } - /*if (ol_pitch>50) - ol_pitch/=2;*/ - /*ol_pitch_coef = sqrt(ol_pitch_coef);*/ - - } else { - ol_pitch=0; - ol_pitch_coef=0; - } - - /*Compute "real" excitation*/ - SPEEX_COPY(st->exc, st->winBuf, diff); - SPEEX_COPY(st->exc+diff, in, st->frameSize-diff); - fir_mem16(st->exc, interp_lpc, st->exc, st->frameSize, st->lpcSize, st->mem_exc, stack); - - /* Compute open-loop excitation gain */ - { - spx_word16_t g = compute_rms16(st->exc, st->frameSize); - if (st->submodeID!=1 && ol_pitch>0) - ol_gain = MULT16_16(g, MULT16_16_Q14(QCONST16(1.1,14), - spx_sqrt(QCONST32(1.,28)-MULT16_32_Q15(QCONST16(.8,15),SHL32(MULT16_16(ol_pitch_coef,ol_pitch_coef),16))))); - else - ol_gain = SHL32(EXTEND32(g),SIG_SHIFT); - } - } - -#ifdef VORBIS_PSYCHO - SPEEX_MOVE(st->psy_window, st->psy_window+st->frameSize, 256-st->frameSize); - SPEEX_COPY(&st->psy_window[256-st->frameSize], in, st->frameSize); - compute_curve(st->psy, st->psy_window, st->curve); - /*print_vec(st->curve, 128, "curve");*/ - if (st->first) - SPEEX_COPY(st->old_curve, st->curve, 128); -#endif - - /*VBR stuff*/ -#ifndef DISABLE_VBR - if (st->vbr && (st->vbr_enabled||st->vad_enabled)) - { - float lsp_dist=0; - for (i=0;i<st->lpcSize;i++) - lsp_dist += (st->old_lsp[i] - lsp[i])*(st->old_lsp[i] - lsp[i]); - lsp_dist /= LSP_SCALING*LSP_SCALING; - - if (st->abr_enabled) - { - float qual_change=0; - if (st->abr_drift2 * st->abr_drift > 0) - { - /* Only adapt if long-term and short-term drift are the same sign */ - qual_change = -.00001*st->abr_drift/(1+st->abr_count); - if (qual_change>.05) - qual_change=.05; - if (qual_change<-.05) - qual_change=-.05; - } - st->vbr_quality += qual_change; - if (st->vbr_quality>10) - st->vbr_quality=10; - if (st->vbr_quality<0) - st->vbr_quality=0; - } - - st->relative_quality = vbr_analysis(st->vbr, in, st->frameSize, ol_pitch, GAIN_SCALING_1*ol_pitch_coef); - /*if (delta_qual<0)*/ - /* delta_qual*=.1*(3+st->vbr_quality);*/ - if (st->vbr_enabled) - { - spx_int32_t mode; - int choice=0; - float min_diff=100; - mode = 8; - while (mode) - { - int v1; - float thresh; - v1=(int)floor(st->vbr_quality); - if (v1==10) - thresh = vbr_nb_thresh[mode][v1]; - else - thresh = (st->vbr_quality-v1)*vbr_nb_thresh[mode][v1+1] + (1+v1-st->vbr_quality)*vbr_nb_thresh[mode][v1]; - if (st->relative_quality > thresh && - st->relative_quality-thresh<min_diff) - { - choice = mode; - min_diff = st->relative_quality-thresh; - } - mode--; - } - mode=choice; - if (mode==0) - { - if (st->dtx_count==0 || lsp_dist>.05 || !st->dtx_enabled || st->dtx_count>20) - { - mode=1; - st->dtx_count=1; - } else { - mode=0; - st->dtx_count++; - } - } else { - st->dtx_count=0; - } - - speex_encoder_ctl(state, SPEEX_SET_MODE, &mode); - if (st->vbr_max>0) - { - spx_int32_t rate; - speex_encoder_ctl(state, SPEEX_GET_BITRATE, &rate); - if (rate > st->vbr_max) - { - rate = st->vbr_max; - speex_encoder_ctl(state, SPEEX_SET_BITRATE, &rate); - } - } - - if (st->abr_enabled) - { - spx_int32_t bitrate; - speex_encoder_ctl(state, SPEEX_GET_BITRATE, &bitrate); - st->abr_drift+=(bitrate-st->abr_enabled); - st->abr_drift2 = .95*st->abr_drift2 + .05*(bitrate-st->abr_enabled); - st->abr_count += 1.0; - } - - } else { - /*VAD only case*/ - int mode; - if (st->relative_quality<2) - { - if (st->dtx_count==0 || lsp_dist>.05 || !st->dtx_enabled || st->dtx_count>20) - { - st->dtx_count=1; - mode=1; - } else { - mode=0; - st->dtx_count++; - } - } else { - st->dtx_count = 0; - mode=st->submodeSelect; - } - /*speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);*/ - st->submodeID=mode; - } - } else { - st->relative_quality = -1; - } -#endif /* #ifndef DISABLE_VBR */ - - if (st->encode_submode) - { - /* First, transmit a zero for narrowband */ - speex_bits_pack(bits, 0, 1); - - /* Transmit the sub-mode we use for this frame */ - speex_bits_pack(bits, st->submodeID, NB_SUBMODE_BITS); - - } - - /* If null mode (no transmission), just set a couple things to zero*/ - if (st->submodes[st->submodeID] == NULL) - { - for (i=0;i<st->frameSize;i++) - st->exc[i]=st->sw[i]=VERY_SMALL; - - for (i=0;i<st->lpcSize;i++) - st->mem_sw[i]=0; - st->first=1; - st->bounded_pitch = 1; - - SPEEX_COPY(st->winBuf, in+2*st->frameSize-st->windowSize, st->windowSize-st->frameSize); - - /* Clear memory (no need to really compute it) */ - for (i=0;i<st->lpcSize;i++) - st->mem_sp[i] = 0; - return 0; - - } - - /* LSP Quantization */ - if (st->first) - { - for (i=0;i<st->lpcSize;i++) - st->old_lsp[i] = lsp[i]; - } - - - /*Quantize LSPs*/ -#if 1 /*0 for unquantized*/ - SUBMODE(lsp_quant)(lsp, qlsp, st->lpcSize, bits); -#else - for (i=0;i<st->lpcSize;i++) - qlsp[i]=lsp[i]; -#endif - - /*If we use low bit-rate pitch mode, transmit open-loop pitch*/ - if (SUBMODE(lbr_pitch)!=-1) - { - speex_bits_pack(bits, ol_pitch-st->min_pitch, 7); - } - - if (SUBMODE(forced_pitch_gain)) - { - int quant; - /* This just damps the pitch a bit, because it tends to be too aggressive when forced */ - ol_pitch_coef = MULT16_16_Q15(QCONST16(.9,15), ol_pitch_coef); -#ifdef FIXED_POINT - quant = PSHR16(MULT16_16_16(15, ol_pitch_coef),GAIN_SHIFT); -#else - quant = (int)floor(.5+15*ol_pitch_coef*GAIN_SCALING_1); -#endif - if (quant>15) - quant=15; - if (quant<0) - quant=0; - speex_bits_pack(bits, quant, 4); - ol_pitch_coef=MULT16_16_P15(QCONST16(0.066667,15),SHL16(quant,GAIN_SHIFT)); - } - - - /*Quantize and transmit open-loop excitation gain*/ -#ifdef FIXED_POINT - { - int qe = scal_quant32(ol_gain, ol_gain_table, 32); - /*ol_gain = exp(qe/3.5)*SIG_SCALING;*/ - ol_gain = MULT16_32_Q15(28406,ol_gain_table[qe]); - speex_bits_pack(bits, qe, 5); - } -#else - { - int qe = (int)(floor(.5+3.5*log(ol_gain*1.0/SIG_SCALING))); - if (qe<0) - qe=0; - if (qe>31) - qe=31; - ol_gain = exp(qe/3.5)*SIG_SCALING; - speex_bits_pack(bits, qe, 5); - } -#endif - - - - /* Special case for first frame */ - if (st->first) - { - for (i=0;i<st->lpcSize;i++) - st->old_qlsp[i] = qlsp[i]; - } - - /* Target signal */ - ALLOC(target, st->subframeSize, spx_word16_t); - ALLOC(innov, st->subframeSize, spx_sig_t); - ALLOC(exc32, st->subframeSize, spx_word32_t); - ALLOC(ringing, st->subframeSize, spx_word16_t); - ALLOC(syn_resp, st->subframeSize, spx_word16_t); - ALLOC(real_exc, st->subframeSize, spx_word16_t); - ALLOC(mem, st->lpcSize, spx_mem_t); - - /* Loop on sub-frames */ - for (sub=0;sub<st->nbSubframes;sub++) - { - int offset; - spx_word16_t *sw; - spx_word16_t *exc; - int pitch; - int response_bound = st->subframeSize; - - /* Offset relative to start of frame */ - offset = st->subframeSize*sub; - /* Excitation */ - exc=st->exc+offset; - /* Weighted signal */ - sw=st->sw+offset; - - /* LSP interpolation (quantized and unquantized) */ - lsp_interpolate(st->old_lsp, lsp, interp_lsp, st->lpcSize, sub, st->nbSubframes); - lsp_interpolate(st->old_qlsp, qlsp, interp_qlsp, st->lpcSize, sub, st->nbSubframes); - - /* Make sure the filters are stable */ - lsp_enforce_margin(interp_lsp, st->lpcSize, LSP_MARGIN); - lsp_enforce_margin(interp_qlsp, st->lpcSize, LSP_MARGIN); - - /* Compute interpolated LPCs (quantized and unquantized) */ - lsp_to_lpc(interp_lsp, interp_lpc, st->lpcSize,stack); - - lsp_to_lpc(interp_qlsp, interp_qlpc, st->lpcSize, stack); - - /* Compute analysis filter gain at w=pi (for use in SB-CELP) */ - { - spx_word32_t pi_g=LPC_SCALING; - for (i=0;i<st->lpcSize;i+=2) - { - /*pi_g += -st->interp_qlpc[i] + st->interp_qlpc[i+1];*/ - pi_g = ADD32(pi_g, SUB32(EXTEND32(interp_qlpc[i+1]),EXTEND32(interp_qlpc[i]))); - } - st->pi_gain[sub] = pi_g; - } - -#ifdef VORBIS_PSYCHO - { - float curr_curve[128]; - float fact = ((float)sub+1.0f)/st->nbSubframes; - for (i=0;i<128;i++) - curr_curve[i] = (1.0f-fact)*st->old_curve[i] + fact*st->curve[i]; - curve_to_lpc(st->psy, curr_curve, bw_lpc1, bw_lpc2, 10); - } -#else - /* Compute bandwidth-expanded (unquantized) LPCs for perceptual weighting */ - bw_lpc(st->gamma1, interp_lpc, bw_lpc1, st->lpcSize); - if (st->gamma2>=0) - bw_lpc(st->gamma2, interp_lpc, bw_lpc2, st->lpcSize); - else - { - for (i=0;i<st->lpcSize;i++) - bw_lpc2[i]=0; - } - /*print_vec(st->bw_lpc1, 10, "bw_lpc");*/ -#endif - - /*FIXME: This will break if we change the window size */ - speex_assert(st->windowSize-st->frameSize == st->subframeSize); - if (sub==0) - { - for (i=0;i<st->subframeSize;i++) - real_exc[i] = sw[i] = st->winBuf[i]; - } else { - for (i=0;i<st->subframeSize;i++) - real_exc[i] = sw[i] = in[i+((sub-1)*st->subframeSize)]; - } - fir_mem16(real_exc, interp_qlpc, real_exc, st->subframeSize, st->lpcSize, st->mem_exc2, stack); - - if (st->complexity==0) - response_bound >>= 1; - compute_impulse_response(interp_qlpc, bw_lpc1, bw_lpc2, syn_resp, response_bound, st->lpcSize, stack); - for (i=response_bound;i<st->subframeSize;i++) - syn_resp[i]=VERY_SMALL; - - /* Compute zero response of A(z/g1) / ( A(z/g2) * A(z) ) */ - for (i=0;i<st->lpcSize;i++) - mem[i]=SHL32(st->mem_sp[i],1); - for (i=0;i<st->subframeSize;i++) - ringing[i] = VERY_SMALL; -#ifdef SHORTCUTS2 - iir_mem16(ringing, interp_qlpc, ringing, response_bound, st->lpcSize, mem, stack); - for (i=0;i<st->lpcSize;i++) - mem[i]=SHL32(st->mem_sw[i],1); - filter_mem16(ringing, st->bw_lpc1, st->bw_lpc2, ringing, response_bound, st->lpcSize, mem, stack); - SPEEX_MEMSET(&ringing[response_bound], 0, st->subframeSize-response_bound); -#else - iir_mem16(ringing, interp_qlpc, ringing, st->subframeSize, st->lpcSize, mem, stack); - for (i=0;i<st->lpcSize;i++) - mem[i]=SHL32(st->mem_sw[i],1); - filter_mem16(ringing, bw_lpc1, bw_lpc2, ringing, st->subframeSize, st->lpcSize, mem, stack); -#endif - - /* Compute weighted signal */ - for (i=0;i<st->lpcSize;i++) - mem[i]=st->mem_sw[i]; - filter_mem16(sw, bw_lpc1, bw_lpc2, sw, st->subframeSize, st->lpcSize, mem, stack); - - if (st->complexity==0) - for (i=0;i<st->lpcSize;i++) - st->mem_sw[i]=mem[i]; - - /* Compute target signal (saturation prevents overflows on clipped input speech) */ - for (i=0;i<st->subframeSize;i++) - target[i]=EXTRACT16(SATURATE(SUB32(sw[i],PSHR32(ringing[i],1)),32767)); - - /* Reset excitation */ - SPEEX_MEMSET(exc, 0, st->subframeSize); - - /* If we have a long-term predictor (otherwise, something's wrong) */ - speex_assert (SUBMODE(ltp_quant)); - { - int pit_min, pit_max; - /* Long-term prediction */ - if (SUBMODE(lbr_pitch) != -1) - { - /* Low bit-rate pitch handling */ - int margin; - margin = SUBMODE(lbr_pitch); - if (margin) - { - if (ol_pitch < st->min_pitch+margin-1) - ol_pitch=st->min_pitch+margin-1; - if (ol_pitch > st->max_pitch-margin) - ol_pitch=st->max_pitch-margin; - pit_min = ol_pitch-margin+1; - pit_max = ol_pitch+margin; - } else { - pit_min=pit_max=ol_pitch; - } - } else { - pit_min = st->min_pitch; - pit_max = st->max_pitch; - } - - /* Force pitch to use only the current frame if needed */ - if (st->bounded_pitch && pit_max>offset) - pit_max=offset; - - /* Perform pitch search */ - pitch = SUBMODE(ltp_quant)(target, sw, interp_qlpc, bw_lpc1, bw_lpc2, - exc32, SUBMODE(ltp_params), pit_min, pit_max, ol_pitch_coef, - st->lpcSize, st->subframeSize, bits, stack, - exc, syn_resp, st->complexity, 0, st->plc_tuning, &st->cumul_gain); - - st->pitch[sub]=pitch; - } - /* Quantization of innovation */ - SPEEX_MEMSET(innov, 0, st->subframeSize); - - /* FIXME: Make sure this is save from overflows (so far so good) */ - for (i=0;i<st->subframeSize;i++) - real_exc[i] = EXTRACT16(SUB32(EXTEND32(real_exc[i]), PSHR32(exc32[i],SIG_SHIFT-1))); - - ener = SHL32(EXTEND32(compute_rms16(real_exc, st->subframeSize)),SIG_SHIFT); - - /*FIXME: Should use DIV32_16 and make sure result fits in 16 bits */ -#ifdef FIXED_POINT - { - spx_word32_t f = PDIV32(ener,PSHR32(ol_gain,SIG_SHIFT)); - if (f<=32767) - fine_gain = f; - else - fine_gain = 32767; - } -#else - fine_gain = PDIV32_16(ener,PSHR32(ol_gain,SIG_SHIFT)); -#endif - /* Calculate gain correction for the sub-frame (if any) */ - if (SUBMODE(have_subframe_gain)) - { - int qe; - if (SUBMODE(have_subframe_gain)==3) - { - qe = scal_quant(fine_gain, exc_gain_quant_scal3_bound, 8); - speex_bits_pack(bits, qe, 3); - ener=MULT16_32_Q14(exc_gain_quant_scal3[qe],ol_gain); - } else { - qe = scal_quant(fine_gain, exc_gain_quant_scal1_bound, 2); - speex_bits_pack(bits, qe, 1); - ener=MULT16_32_Q14(exc_gain_quant_scal1[qe],ol_gain); - } - } else { - ener=ol_gain; - } - - /*printf ("%f %f\n", ener, ol_gain);*/ - - /* Normalize innovation */ - signal_div(target, target, ener, st->subframeSize); - - /* Quantize innovation */ - speex_assert (SUBMODE(innovation_quant)); - { - /* Codebook search */ - SUBMODE(innovation_quant)(target, interp_qlpc, bw_lpc1, bw_lpc2, - SUBMODE(innovation_params), st->lpcSize, st->subframeSize, - innov, syn_resp, bits, stack, st->complexity, SUBMODE(double_codebook)); - - /* De-normalize innovation and update excitation */ - signal_mul(innov, innov, ener, st->subframeSize); - - for (i=0;i<st->subframeSize;i++) - exc[i] = EXTRACT16(SATURATE32(PSHR32(ADD32(SHL32(exc32[i],1),innov[i]),SIG_SHIFT),32767)); - - /* In some (rare) modes, we do a second search (more bits) to reduce noise even more */ - if (SUBMODE(double_codebook)) { - char *tmp_stack=stack; - VARDECL(spx_sig_t *innov2); - ALLOC(innov2, st->subframeSize, spx_sig_t); - SPEEX_MEMSET(innov2, 0, st->subframeSize); - for (i=0;i<st->subframeSize;i++) - target[i]=MULT16_16_P13(QCONST16(2.2f,13), target[i]); - SUBMODE(innovation_quant)(target, interp_qlpc, bw_lpc1, bw_lpc2, - SUBMODE(innovation_params), st->lpcSize, st->subframeSize, - innov2, syn_resp, bits, stack, st->complexity, 0); - signal_mul(innov2, innov2, MULT16_32_Q15(QCONST16(0.454545f,15),ener), st->subframeSize); - for (i=0;i<st->subframeSize;i++) - innov[i] = ADD32(innov[i],innov2[i]); - stack = tmp_stack; - } - for (i=0;i<st->subframeSize;i++) - exc[i] = EXTRACT16(SATURATE32(PSHR32(ADD32(SHL32(exc32[i],1),innov[i]),SIG_SHIFT),32767)); - if (st->innov_rms_save) - { - st->innov_rms_save[sub] = compute_rms(innov, st->subframeSize); - } - } - - /* Final signal synthesis from excitation */ - iir_mem16(exc, interp_qlpc, sw, st->subframeSize, st->lpcSize, st->mem_sp, stack); - - /* Compute weighted signal again, from synthesized speech (not sure it's the right thing) */ - if (st->complexity!=0) - filter_mem16(sw, bw_lpc1, bw_lpc2, sw, st->subframeSize, st->lpcSize, st->mem_sw, stack); - - } - - /* Store the LSPs for interpolation in the next frame */ - if (st->submodeID>=1) - { - for (i=0;i<st->lpcSize;i++) - st->old_lsp[i] = lsp[i]; - for (i=0;i<st->lpcSize;i++) - st->old_qlsp[i] = qlsp[i]; - } - -#ifdef VORBIS_PSYCHO - if (st->submodeID>=1) - SPEEX_COPY(st->old_curve, st->curve, 128); -#endif - - if (st->submodeID==1) - { -#ifndef DISABLE_VBR - if (st->dtx_count) - speex_bits_pack(bits, 15, 4); - else -#endif - speex_bits_pack(bits, 0, 4); - } - - /* The next frame will not be the first (Duh!) */ - st->first = 0; - SPEEX_COPY(st->winBuf, in+2*st->frameSize-st->windowSize, st->windowSize-st->frameSize); - - if (SUBMODE(innovation_quant) == noise_codebook_quant || st->submodeID==0) - st->bounded_pitch = 1; - else - st->bounded_pitch = 0; - - return 1; -} - -void *nb_decoder_init(const SpeexMode *m) -{ - DecState *st; - const SpeexNBMode *mode; - int i; - - mode=(const SpeexNBMode*)m->mode; - st = (DecState *)speex_alloc(sizeof(DecState)); - if (!st) - return NULL; -#if defined(VAR_ARRAYS) || defined (USE_ALLOCA) - st->stack = NULL; -#else - st->stack = (char*)speex_alloc_scratch(NB_DEC_STACK); -#endif - - st->mode=m; - - - st->encode_submode = 1; - - st->first=1; - /* Codec parameters, should eventually have several "modes"*/ - st->frameSize = mode->frameSize; - st->nbSubframes=mode->frameSize/mode->subframeSize; - st->subframeSize=mode->subframeSize; - st->lpcSize = mode->lpcSize; - st->min_pitch=mode->pitchStart; - st->max_pitch=mode->pitchEnd; - - st->submodes=mode->submodes; - st->submodeID=mode->defaultSubmode; - - st->lpc_enh_enabled=1; - - st->excBuf = (spx_word16_t*)speex_alloc((st->frameSize + 2*st->max_pitch + st->subframeSize + 12)*sizeof(spx_word16_t)); - st->exc = st->excBuf + 2*st->max_pitch + st->subframeSize + 6; - SPEEX_MEMSET(st->excBuf, 0, st->frameSize + st->max_pitch); - - st->interp_qlpc = (spx_coef_t*)speex_alloc(st->lpcSize*sizeof(spx_coef_t)); - st->old_qlsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t)); - st->mem_sp = (spx_mem_t*)speex_alloc(st->lpcSize*sizeof(spx_mem_t)); - st->pi_gain = (spx_word32_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word32_t)); - st->last_pitch = 40; - st->count_lost=0; - st->pitch_gain_buf[0] = st->pitch_gain_buf[1] = st->pitch_gain_buf[2] = 0; - st->pitch_gain_buf_idx = 0; - st->seed = 1000; - - st->sampling_rate=8000; - st->last_ol_gain = 0; - - st->user_callback.func = &speex_default_user_handler; - st->user_callback.data = NULL; - for (i=0;i<16;i++) - st->speex_callbacks[i].func = NULL; - - st->voc_m1=st->voc_m2=st->voc_mean=0; - st->voc_offset=0; - st->dtx_enabled=0; - st->isWideband = 0; - st->highpass_enabled = 1; - -#ifdef ENABLE_VALGRIND - VALGRIND_MAKE_READABLE(st, NB_DEC_STACK); -#endif - return st; -} - -void nb_decoder_destroy(void *state) -{ - DecState *st; - st=(DecState*)state; - -#if !(defined(VAR_ARRAYS) || defined (USE_ALLOCA)) - speex_free_scratch(st->stack); -#endif - - speex_free (st->excBuf); - speex_free (st->interp_qlpc); - speex_free (st->old_qlsp); - speex_free (st->mem_sp); - speex_free (st->pi_gain); - - speex_free(state); -} - -#define median3(a, b, c) ((a) < (b) ? ((b) < (c) ? (b) : ((a) < (c) ? (c) : (a))) : ((c) < (b) ? (b) : ((c) < (a) ? (c) : (a)))) - -#ifdef FIXED_POINT -const spx_word16_t attenuation[10] = {32767, 31483, 27923, 22861, 17278, 12055, 7764, 4616, 2533, 1283}; -#else -const spx_word16_t attenuation[10] = {1., 0.961, 0.852, 0.698, 0.527, 0.368, 0.237, 0.141, 0.077, 0.039}; - -#endif - -static void nb_decode_lost(DecState *st, spx_word16_t *out, char *stack) -{ - int i; - int pitch_val; - spx_word16_t pitch_gain; - spx_word16_t fact; - spx_word16_t gain_med; - spx_word16_t innov_gain; - spx_word16_t noise_gain; - - if (st->count_lost<10) - fact = attenuation[st->count_lost]; - else - fact = 0; - - gain_med = median3(st->pitch_gain_buf[0], st->pitch_gain_buf[1], st->pitch_gain_buf[2]); - if (gain_med < st->last_pitch_gain) - st->last_pitch_gain = gain_med; - -#ifdef FIXED_POINT - pitch_gain = st->last_pitch_gain; - if (pitch_gain>54) - pitch_gain = 54; - pitch_gain = SHL16(pitch_gain, 9); -#else - pitch_gain = GAIN_SCALING_1*st->last_pitch_gain; - if (pitch_gain>.85) - pitch_gain=.85; -#endif - pitch_gain = MULT16_16_Q15(fact,pitch_gain) + VERY_SMALL; - /* FIXME: This was rms of innovation (not exc) */ - innov_gain = compute_rms16(st->exc, st->frameSize); - noise_gain = MULT16_16_Q15(innov_gain, MULT16_16_Q15(fact, SUB16(Q15ONE,MULT16_16_Q15(pitch_gain,pitch_gain)))); - /* Shift all buffers by one frame */ - SPEEX_MOVE(st->excBuf, st->excBuf+st->frameSize, 2*st->max_pitch + st->subframeSize + 12); - - - pitch_val = st->last_pitch + SHR32((spx_int32_t)speex_rand(1+st->count_lost, &st->seed),SIG_SHIFT); - if (pitch_val > st->max_pitch) - pitch_val = st->max_pitch; - if (pitch_val < st->min_pitch) - pitch_val = st->min_pitch; - for (i=0;i<st->frameSize;i++) - { - st->exc[i]= MULT16_16_Q15(pitch_gain, (st->exc[i-pitch_val]+VERY_SMALL)) + - speex_rand(noise_gain, &st->seed); - } - - bw_lpc(QCONST16(.98,15), st->interp_qlpc, st->interp_qlpc, st->lpcSize); - iir_mem16(&st->exc[-st->subframeSize], st->interp_qlpc, out, st->frameSize, - st->lpcSize, st->mem_sp, stack); - highpass(out, out, st->frameSize, HIGHPASS_NARROWBAND|HIGHPASS_OUTPUT, st->mem_hp); - - st->first = 0; - st->count_lost++; - st->pitch_gain_buf[st->pitch_gain_buf_idx++] = PSHR16(pitch_gain,9); - if (st->pitch_gain_buf_idx > 2) /* rollover */ - st->pitch_gain_buf_idx = 0; -} - -/* Just so we don't need to carry the complete wideband mode information */ -static const int wb_skip_table[8] = {0, 36, 112, 192, 352, 0, 0, 0}; - -int nb_decode(void *state, SpeexBits *bits, void *vout) -{ - DecState *st; - int i, sub; - int pitch; - spx_word16_t pitch_gain[3]; - spx_word32_t ol_gain=0; - int ol_pitch=0; - spx_word16_t ol_pitch_coef=0; - int best_pitch=40; - spx_word16_t best_pitch_gain=0; - int wideband; - int m; - char *stack; - VARDECL(spx_sig_t *innov); - VARDECL(spx_word32_t *exc32); - VARDECL(spx_coef_t *ak); - VARDECL(spx_lsp_t *qlsp); - spx_word16_t pitch_average=0; - - spx_word16_t *out = (spx_word16_t*)vout; - VARDECL(spx_lsp_t *interp_qlsp); - - st=(DecState*)state; - stack=st->stack; - - /* Check if we're in DTX mode*/ - if (!bits && st->dtx_enabled) - { - st->submodeID=0; - } else - { - /* If bits is NULL, consider the packet to be lost (what could we do anyway) */ - if (!bits) - { - nb_decode_lost(st, out, stack); - return 0; - } - - if (st->encode_submode) - { - - /* Search for next narrowband block (handle requests, skip wideband blocks) */ - do { - if (speex_bits_remaining(bits)<5) - return -1; - wideband = speex_bits_unpack_unsigned(bits, 1); - if (wideband) /* Skip wideband block (for compatibility) */ - { - int submode; - int advance; - advance = submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS); - /*speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance);*/ - advance = wb_skip_table[submode]; - if (advance < 0) - { - speex_notify("Invalid mode encountered. The stream is corrupted."); - return -2; - } - advance -= (SB_SUBMODE_BITS+1); - speex_bits_advance(bits, advance); - - if (speex_bits_remaining(bits)<5) - return -1; - wideband = speex_bits_unpack_unsigned(bits, 1); - if (wideband) - { - advance = submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS); - /*speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance);*/ - advance = wb_skip_table[submode]; - if (advance < 0) - { - speex_notify("Invalid mode encountered. The stream is corrupted."); - return -2; - } - advance -= (SB_SUBMODE_BITS+1); - speex_bits_advance(bits, advance); - wideband = speex_bits_unpack_unsigned(bits, 1); - if (wideband) - { - speex_notify("More than two wideband layers found. The stream is corrupted."); - return -2; - } - - } - } - if (speex_bits_remaining(bits)<4) - return -1; - /* FIXME: Check for overflow */ - m = speex_bits_unpack_unsigned(bits, 4); - if (m==15) /* We found a terminator */ - { - return -1; - } else if (m==14) /* Speex in-band request */ - { - int ret = speex_inband_handler(bits, st->speex_callbacks, state); - if (ret) - return ret; - } else if (m==13) /* User in-band request */ - { - int ret = st->user_callback.func(bits, state, st->user_callback.data); - if (ret) - return ret; - } else if (m>8) /* Invalid mode */ - { - speex_notify("Invalid mode encountered. The stream is corrupted."); - return -2; - } - - } while (m>8); - - /* Get the sub-mode that was used */ - st->submodeID = m; - } - - } - - /* Shift all buffers by one frame */ - SPEEX_MOVE(st->excBuf, st->excBuf+st->frameSize, 2*st->max_pitch + st->subframeSize + 12); - - /* If null mode (no transmission), just set a couple things to zero*/ - if (st->submodes[st->submodeID] == NULL) - { - VARDECL(spx_coef_t *lpc); - ALLOC(lpc, st->lpcSize, spx_coef_t); - bw_lpc(QCONST16(0.93f,15), st->interp_qlpc, lpc, st->lpcSize); - { - spx_word16_t innov_gain=0; - /* FIXME: This was innov, not exc */ - innov_gain = compute_rms16(st->exc, st->frameSize); - for (i=0;i<st->frameSize;i++) - st->exc[i]=speex_rand(innov_gain, &st->seed); - } - - - st->first=1; - - /* Final signal synthesis from excitation */ - iir_mem16(st->exc, lpc, out, st->frameSize, st->lpcSize, st->mem_sp, stack); - - st->count_lost=0; - return 0; - } - - ALLOC(qlsp, st->lpcSize, spx_lsp_t); - - /* Unquantize LSPs */ - SUBMODE(lsp_unquant)(qlsp, st->lpcSize, bits); - - /*Damp memory if a frame was lost and the LSP changed too much*/ - if (st->count_lost) - { - spx_word16_t fact; - spx_word32_t lsp_dist=0; - for (i=0;i<st->lpcSize;i++) - lsp_dist = ADD32(lsp_dist, EXTEND32(ABS(st->old_qlsp[i] - qlsp[i]))); -#ifdef FIXED_POINT - fact = SHR16(19661,SHR32(lsp_dist,LSP_SHIFT+2)); -#else - fact = .6*exp(-.2*lsp_dist); -#endif - for (i=0;i<st->lpcSize;i++) - st->mem_sp[i] = MULT16_32_Q15(fact,st->mem_sp[i]); - } - - - /* Handle first frame and lost-packet case */ - if (st->first || st->count_lost) - { - for (i=0;i<st->lpcSize;i++) - st->old_qlsp[i] = qlsp[i]; - } - - /* Get open-loop pitch estimation for low bit-rate pitch coding */ - if (SUBMODE(lbr_pitch)!=-1) - { - ol_pitch = st->min_pitch+speex_bits_unpack_unsigned(bits, 7); - } - - if (SUBMODE(forced_pitch_gain)) - { - int quant; - quant = speex_bits_unpack_unsigned(bits, 4); - ol_pitch_coef=MULT16_16_P15(QCONST16(0.066667,15),SHL16(quant,GAIN_SHIFT)); - } - - /* Get global excitation gain */ - { - int qe; - qe = speex_bits_unpack_unsigned(bits, 5); -#ifdef FIXED_POINT - /* FIXME: Perhaps we could slightly lower the gain here when the output is going to saturate? */ - ol_gain = MULT16_32_Q15(28406,ol_gain_table[qe]); -#else - ol_gain = SIG_SCALING*exp(qe/3.5); -#endif - } - - ALLOC(ak, st->lpcSize, spx_coef_t); - ALLOC(innov, st->subframeSize, spx_sig_t); - ALLOC(exc32, st->subframeSize, spx_word32_t); - - if (st->submodeID==1) - { - int extra; - extra = speex_bits_unpack_unsigned(bits, 4); - - if (extra==15) - st->dtx_enabled=1; - else - st->dtx_enabled=0; - } - if (st->submodeID>1) - st->dtx_enabled=0; - - /*Loop on subframes */ - for (sub=0;sub<st->nbSubframes;sub++) - { - int offset; - spx_word16_t *exc; - spx_word16_t *sp; - spx_word16_t *innov_save = NULL; - spx_word16_t tmp; - - /* Offset relative to start of frame */ - offset = st->subframeSize*sub; - /* Excitation */ - exc=st->exc+offset; - /* Original signal */ - sp=out+offset; - if (st->innov_save) - innov_save = st->innov_save+offset; - - - /* Reset excitation */ - SPEEX_MEMSET(exc, 0, st->subframeSize); - - /*Adaptive codebook contribution*/ - speex_assert (SUBMODE(ltp_unquant)); - { - int pit_min, pit_max; - /* Handle pitch constraints if any */ - if (SUBMODE(lbr_pitch) != -1) - { - int margin; - margin = SUBMODE(lbr_pitch); - if (margin) - { -/* GT - need optimization? - if (ol_pitch < st->min_pitch+margin-1) - ol_pitch=st->min_pitch+margin-1; - if (ol_pitch > st->max_pitch-margin) - ol_pitch=st->max_pitch-margin; - pit_min = ol_pitch-margin+1; - pit_max = ol_pitch+margin; -*/ - pit_min = ol_pitch-margin+1; - if (pit_min < st->min_pitch) - pit_min = st->min_pitch; - pit_max = ol_pitch+margin; - if (pit_max > st->max_pitch) - pit_max = st->max_pitch; - } else { - pit_min = pit_max = ol_pitch; - } - } else { - pit_min = st->min_pitch; - pit_max = st->max_pitch; - } - - - - SUBMODE(ltp_unquant)(exc, exc32, pit_min, pit_max, ol_pitch_coef, SUBMODE(ltp_params), - st->subframeSize, &pitch, &pitch_gain[0], bits, stack, - st->count_lost, offset, st->last_pitch_gain, 0); - - /* Ensuring that things aren't blowing up as would happen if e.g. an encoder is - crafting packets to make us produce NaNs and slow down the decoder (vague DoS threat). - We can probably be even more aggressive and limit to 15000 or so. */ - sanitize_values32(exc32, NEG32(QCONST32(32000,SIG_SHIFT-1)), QCONST32(32000,SIG_SHIFT-1), st->subframeSize); - - tmp = gain_3tap_to_1tap(pitch_gain); - - pitch_average += tmp; - if ((tmp>best_pitch_gain&&ABS(2*best_pitch-pitch)>=3&&ABS(3*best_pitch-pitch)>=4&&ABS(4*best_pitch-pitch)>=5) - || (tmp>MULT16_16_Q15(QCONST16(.6,15),best_pitch_gain)&&(ABS(best_pitch-2*pitch)<3||ABS(best_pitch-3*pitch)<4||ABS(best_pitch-4*pitch)<5)) - || (MULT16_16_Q15(QCONST16(.67,15),tmp)>best_pitch_gain&&(ABS(2*best_pitch-pitch)<3||ABS(3*best_pitch-pitch)<4||ABS(4*best_pitch-pitch)<5)) ) - { - best_pitch = pitch; - if (tmp > best_pitch_gain) - best_pitch_gain = tmp; - } - } - - /* Unquantize the innovation */ - { - int q_energy; - spx_word32_t ener; - - SPEEX_MEMSET(innov, 0, st->subframeSize); - - /* Decode sub-frame gain correction */ - if (SUBMODE(have_subframe_gain)==3) - { - q_energy = speex_bits_unpack_unsigned(bits, 3); - ener = MULT16_32_Q14(exc_gain_quant_scal3[q_energy],ol_gain); - } else if (SUBMODE(have_subframe_gain)==1) - { - q_energy = speex_bits_unpack_unsigned(bits, 1); - ener = MULT16_32_Q14(exc_gain_quant_scal1[q_energy],ol_gain); - } else { - ener = ol_gain; - } - - speex_assert (SUBMODE(innovation_unquant)); - { - /*Fixed codebook contribution*/ - SUBMODE(innovation_unquant)(innov, SUBMODE(innovation_params), st->subframeSize, bits, stack, &st->seed); - /* De-normalize innovation and update excitation */ - - signal_mul(innov, innov, ener, st->subframeSize); - - /* Decode second codebook (only for some modes) */ - if (SUBMODE(double_codebook)) - { - char *tmp_stack=stack; - VARDECL(spx_sig_t *innov2); - ALLOC(innov2, st->subframeSize, spx_sig_t); - SPEEX_MEMSET(innov2, 0, st->subframeSize); - SUBMODE(innovation_unquant)(innov2, SUBMODE(innovation_params), st->subframeSize, bits, stack, &st->seed); - signal_mul(innov2, innov2, MULT16_32_Q15(QCONST16(0.454545f,15),ener), st->subframeSize); - for (i=0;i<st->subframeSize;i++) - innov[i] = ADD32(innov[i], innov2[i]); - stack = tmp_stack; - } - for (i=0;i<st->subframeSize;i++) - exc[i]=EXTRACT16(SATURATE32(PSHR32(ADD32(SHL32(exc32[i],1),innov[i]),SIG_SHIFT),32767)); - /*print_vec(exc, 40, "innov");*/ - if (innov_save) - { - for (i=0;i<st->subframeSize;i++) - innov_save[i] = EXTRACT16(PSHR32(innov[i], SIG_SHIFT)); - } - } - - /*Vocoder mode*/ - if (st->submodeID==1) - { - spx_word16_t g=ol_pitch_coef; - g=MULT16_16_P14(QCONST16(1.5f,14),(g-QCONST16(.2f,6))); - if (g<0) - g=0; - if (g>GAIN_SCALING) - g=GAIN_SCALING; - - SPEEX_MEMSET(exc, 0, st->subframeSize); - while (st->voc_offset<st->subframeSize) - { - /* exc[st->voc_offset]= g*sqrt(2*ol_pitch)*ol_gain; - Not quite sure why we need the factor of two in the sqrt */ - if (st->voc_offset>=0) - exc[st->voc_offset]=MULT16_16(spx_sqrt(MULT16_16_16(2,ol_pitch)),EXTRACT16(PSHR32(MULT16_16(g,PSHR32(ol_gain,SIG_SHIFT)),6))); - st->voc_offset+=ol_pitch; - } - st->voc_offset -= st->subframeSize; - - for (i=0;i<st->subframeSize;i++) - { - spx_word16_t exci=exc[i]; - exc[i]= ADD16(ADD16(MULT16_16_Q15(QCONST16(.7f,15),exc[i]) , MULT16_16_Q15(QCONST16(.3f,15),st->voc_m1)), - SUB16(MULT16_16_Q15(Q15_ONE-MULT16_16_16(QCONST16(.85f,9),g),EXTRACT16(PSHR32(innov[i],SIG_SHIFT))), - MULT16_16_Q15(MULT16_16_16(QCONST16(.15f,9),g),EXTRACT16(PSHR32(st->voc_m2,SIG_SHIFT))) - )); - st->voc_m1 = exci; - st->voc_m2=innov[i]; - st->voc_mean = EXTRACT16(PSHR32(ADD32(MULT16_16(QCONST16(.8f,15),st->voc_mean), MULT16_16(QCONST16(.2f,15),exc[i])), 15)); - exc[i]-=st->voc_mean; - } - } - - } - } - - ALLOC(interp_qlsp, st->lpcSize, spx_lsp_t); - - if (st->lpc_enh_enabled && SUBMODE(comb_gain)>0 && !st->count_lost) - { - multicomb(st->exc-st->subframeSize, out, st->interp_qlpc, st->lpcSize, 2*st->subframeSize, best_pitch, 40, SUBMODE(comb_gain), stack); - multicomb(st->exc+st->subframeSize, out+2*st->subframeSize, st->interp_qlpc, st->lpcSize, 2*st->subframeSize, best_pitch, 40, SUBMODE(comb_gain), stack); - } else { - SPEEX_COPY(out, &st->exc[-st->subframeSize], st->frameSize); - } - - /* If the last packet was lost, re-scale the excitation to obtain the same energy as encoded in ol_gain */ - if (st->count_lost) - { - spx_word16_t exc_ener; - spx_word32_t gain32; - spx_word16_t gain; - exc_ener = compute_rms16 (st->exc, st->frameSize); - gain32 = PDIV32(ol_gain, ADD16(exc_ener,1)); -#ifdef FIXED_POINT - if (gain32 > 32767) - gain32 = 32767; - gain = EXTRACT16(gain32); -#else - if (gain32 > 2) - gain32=2; - gain = gain32; -#endif - for (i=0;i<st->frameSize;i++) - { - st->exc[i] = MULT16_16_Q14(gain, st->exc[i]); - out[i]=st->exc[i-st->subframeSize]; - } - } - - /*Loop on subframes */ - for (sub=0;sub<st->nbSubframes;sub++) - { - int offset; - spx_word16_t *sp; - spx_word16_t *exc; - /* Offset relative to start of frame */ - offset = st->subframeSize*sub; - /* Original signal */ - sp=out+offset; - /* Excitation */ - exc=st->exc+offset; - - /* LSP interpolation (quantized and unquantized) */ - lsp_interpolate(st->old_qlsp, qlsp, interp_qlsp, st->lpcSize, sub, st->nbSubframes); - - /* Make sure the LSP's are stable */ - lsp_enforce_margin(interp_qlsp, st->lpcSize, LSP_MARGIN); - - /* Compute interpolated LPCs (unquantized) */ - lsp_to_lpc(interp_qlsp, ak, st->lpcSize, stack); - - /* Compute analysis filter at w=pi */ - { - spx_word32_t pi_g=LPC_SCALING; - for (i=0;i<st->lpcSize;i+=2) - { - /*pi_g += -st->interp_qlpc[i] + st->interp_qlpc[i+1];*/ - pi_g = ADD32(pi_g, SUB32(EXTEND32(ak[i+1]),EXTEND32(ak[i]))); - } - st->pi_gain[sub] = pi_g; - } - - iir_mem16(sp, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, - st->mem_sp, stack); - - for (i=0;i<st->lpcSize;i++) - st->interp_qlpc[i] = ak[i]; - - } - - if (st->highpass_enabled) - highpass(out, out, st->frameSize, (st->isWideband?HIGHPASS_WIDEBAND:HIGHPASS_NARROWBAND)|HIGHPASS_OUTPUT, st->mem_hp); - /*for (i=0;i<st->frameSize;i++) - printf ("%d\n", (int)st->frame[i]);*/ - - /* Tracking output level */ - st->level = 1+PSHR32(ol_gain,SIG_SHIFT); - st->max_level = MAX16(MULT16_16_Q15(QCONST16(.99f,15), st->max_level), st->level); - st->min_level = MIN16(ADD16(1,MULT16_16_Q14(QCONST16(1.01f,14), st->min_level)), st->level); - if (st->max_level < st->min_level+1) - st->max_level = st->min_level+1; - /*printf ("%f %f %f %d\n", og, st->min_level, st->max_level, update);*/ - - /* Store the LSPs for interpolation in the next frame */ - for (i=0;i<st->lpcSize;i++) - st->old_qlsp[i] = qlsp[i]; - - /* The next frame will not be the first (Duh!) */ - st->first = 0; - st->count_lost=0; - st->last_pitch = best_pitch; -#ifdef FIXED_POINT - st->last_pitch_gain = PSHR16(pitch_average,2); -#else - st->last_pitch_gain = .25*pitch_average; -#endif - st->pitch_gain_buf[st->pitch_gain_buf_idx++] = st->last_pitch_gain; - if (st->pitch_gain_buf_idx > 2) /* rollover */ - st->pitch_gain_buf_idx = 0; - - st->last_ol_gain = ol_gain; - - return 0; -} - -int nb_encoder_ctl(void *state, int request, void *ptr) -{ - EncState *st; - st=(EncState*)state; - switch(request) - { - case SPEEX_GET_FRAME_SIZE: - (*(spx_int32_t*)ptr) = st->frameSize; - break; - case SPEEX_SET_LOW_MODE: - case SPEEX_SET_MODE: - st->submodeSelect = st->submodeID = (*(spx_int32_t*)ptr); - break; - case SPEEX_GET_LOW_MODE: - case SPEEX_GET_MODE: - (*(spx_int32_t*)ptr) = st->submodeID; - break; -#ifndef DISABLE_VBR - case SPEEX_SET_VBR: - st->vbr_enabled = (*(spx_int32_t*)ptr); - break; - case SPEEX_GET_VBR: - (*(spx_int32_t*)ptr) = st->vbr_enabled; - break; - case SPEEX_SET_VAD: - st->vad_enabled = (*(spx_int32_t*)ptr); - break; - case SPEEX_GET_VAD: - (*(spx_int32_t*)ptr) = st->vad_enabled; - break; - case SPEEX_SET_DTX: - st->dtx_enabled = (*(spx_int32_t*)ptr); - break; - case SPEEX_GET_DTX: - (*(spx_int32_t*)ptr) = st->dtx_enabled; - break; - case SPEEX_SET_ABR: - st->abr_enabled = (*(spx_int32_t*)ptr); - st->vbr_enabled = st->abr_enabled!=0; - if (st->vbr_enabled) - { - spx_int32_t i=10; - spx_int32_t rate, target; - float vbr_qual; - target = (*(spx_int32_t*)ptr); - while (i>=0) - { - speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i); - speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate); - if (rate <= target) - break; - i--; - } - vbr_qual=i; - if (vbr_qual<0) - vbr_qual=0; - speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_qual); - st->abr_count=0; - st->abr_drift=0; - st->abr_drift2=0; - } - - break; - case SPEEX_GET_ABR: - (*(spx_int32_t*)ptr) = st->abr_enabled; - break; -#endif /* #ifndef DISABLE_VBR */ -#if !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API) - case SPEEX_SET_VBR_QUALITY: - st->vbr_quality = (*(float*)ptr); - break; - case SPEEX_GET_VBR_QUALITY: - (*(float*)ptr) = st->vbr_quality; - break; -#endif /* !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API) */ - case SPEEX_SET_QUALITY: - { - int quality = (*(spx_int32_t*)ptr); - if (quality < 0) - quality = 0; - if (quality > 10) - quality = 10; - st->submodeSelect = st->submodeID = ((const SpeexNBMode*)(st->mode->mode))->quality_map[quality]; - } - break; - case SPEEX_SET_COMPLEXITY: - st->complexity = (*(spx_int32_t*)ptr); - if (st->complexity<0) - st->complexity=0; - break; - case SPEEX_GET_COMPLEXITY: - (*(spx_int32_t*)ptr) = st->complexity; - break; - case SPEEX_SET_BITRATE: - { - spx_int32_t i=10; - spx_int32_t rate, target; - target = (*(spx_int32_t*)ptr); - while (i>=0) - { - speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i); - speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate); - if (rate <= target) - break; - i--; - } - } - break; - case SPEEX_GET_BITRATE: - if (st->submodes[st->submodeID]) - (*(spx_int32_t*)ptr) = st->sampling_rate*SUBMODE(bits_per_frame)/st->frameSize; - else - (*(spx_int32_t*)ptr) = st->sampling_rate*(NB_SUBMODE_BITS+1)/st->frameSize; - break; - case SPEEX_SET_SAMPLING_RATE: - st->sampling_rate = (*(spx_int32_t*)ptr); - break; - case SPEEX_GET_SAMPLING_RATE: - (*(spx_int32_t*)ptr)=st->sampling_rate; - break; - case SPEEX_RESET_STATE: - { - int i; - st->bounded_pitch = 1; - st->first = 1; - for (i=0;i<st->lpcSize;i++) - st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), st->lpcSize+1); - for (i=0;i<st->lpcSize;i++) - st->mem_sw[i]=st->mem_sw_whole[i]=st->mem_sp[i]=st->mem_exc[i]=0; - for (i=0;i<st->frameSize+st->max_pitch+1;i++) - st->excBuf[i]=st->swBuf[i]=0; - for (i=0;i<st->windowSize-st->frameSize;i++) - st->winBuf[i]=0; - } - break; - case SPEEX_SET_SUBMODE_ENCODING: - st->encode_submode = (*(spx_int32_t*)ptr); - break; - case SPEEX_GET_SUBMODE_ENCODING: - (*(spx_int32_t*)ptr) = st->encode_submode; - break; - case SPEEX_GET_LOOKAHEAD: - (*(spx_int32_t*)ptr)=(st->windowSize-st->frameSize); - break; - case SPEEX_SET_PLC_TUNING: - st->plc_tuning = (*(spx_int32_t*)ptr); - if (st->plc_tuning>100) - st->plc_tuning=100; - break; - case SPEEX_GET_PLC_TUNING: - (*(spx_int32_t*)ptr)=(st->plc_tuning); - break; -#ifndef DISABLE_VBR - case SPEEX_SET_VBR_MAX_BITRATE: - st->vbr_max = (*(spx_int32_t*)ptr); - break; - case SPEEX_GET_VBR_MAX_BITRATE: - (*(spx_int32_t*)ptr) = st->vbr_max; - break; -#endif /* #ifndef DISABLE_VBR */ - case SPEEX_SET_HIGHPASS: - st->highpass_enabled = (*(spx_int32_t*)ptr); - break; - case SPEEX_GET_HIGHPASS: - (*(spx_int32_t*)ptr) = st->highpass_enabled; - break; - - /* This is all internal stuff past this point */ - case SPEEX_GET_PI_GAIN: - { - int i; - spx_word32_t *g = (spx_word32_t*)ptr; - for (i=0;i<st->nbSubframes;i++) - g[i]=st->pi_gain[i]; - } - break; - case SPEEX_GET_EXC: - { - int i; - for (i=0;i<st->nbSubframes;i++) - ((spx_word16_t*)ptr)[i] = compute_rms16(st->exc+i*st->subframeSize, st->subframeSize); - } - break; -#ifndef DISABLE_VBR - case SPEEX_GET_RELATIVE_QUALITY: - (*(float*)ptr)=st->relative_quality; - break; -#endif /* #ifndef DISABLE_VBR */ - case SPEEX_SET_INNOVATION_SAVE: - st->innov_rms_save = (spx_word16_t*)ptr; - break; - case SPEEX_SET_WIDEBAND: - st->isWideband = *((spx_int32_t*)ptr); - break; - case SPEEX_GET_STACK: - *((char**)ptr) = st->stack; - break; - default: - speex_warning_int("Unknown nb_ctl request: ", request); - return -1; - } - return 0; -} - -int nb_decoder_ctl(void *state, int request, void *ptr) -{ - DecState *st; - st=(DecState*)state; - switch(request) - { - case SPEEX_SET_LOW_MODE: - case SPEEX_SET_MODE: - st->submodeID = (*(spx_int32_t*)ptr); - break; - case SPEEX_GET_LOW_MODE: - case SPEEX_GET_MODE: - (*(spx_int32_t*)ptr) = st->submodeID; - break; - case SPEEX_SET_ENH: - st->lpc_enh_enabled = *((spx_int32_t*)ptr); - break; - case SPEEX_GET_ENH: - *((spx_int32_t*)ptr) = st->lpc_enh_enabled; - break; - case SPEEX_GET_FRAME_SIZE: - (*(spx_int32_t*)ptr) = st->frameSize; - break; - case SPEEX_GET_BITRATE: - if (st->submodes[st->submodeID]) - (*(spx_int32_t*)ptr) = st->sampling_rate*SUBMODE(bits_per_frame)/st->frameSize; - else - (*(spx_int32_t*)ptr) = st->sampling_rate*(NB_SUBMODE_BITS+1)/st->frameSize; - break; - case SPEEX_SET_SAMPLING_RATE: - st->sampling_rate = (*(spx_int32_t*)ptr); - break; - case SPEEX_GET_SAMPLING_RATE: - (*(spx_int32_t*)ptr)=st->sampling_rate; - break; - case SPEEX_SET_HANDLER: - { - SpeexCallback *c = (SpeexCallback*)ptr; - st->speex_callbacks[c->callback_id].func=c->func; - st->speex_callbacks[c->callback_id].data=c->data; - st->speex_callbacks[c->callback_id].callback_id=c->callback_id; - } - break; - case SPEEX_SET_USER_HANDLER: - { - SpeexCallback *c = (SpeexCallback*)ptr; - st->user_callback.func=c->func; - st->user_callback.data=c->data; - st->user_callback.callback_id=c->callback_id; - } - break; - case SPEEX_RESET_STATE: - { - int i; - for (i=0;i<st->lpcSize;i++) - st->mem_sp[i]=0; - for (i=0;i<st->frameSize + st->max_pitch + 1;i++) - st->excBuf[i]=0; - } - break; - case SPEEX_SET_SUBMODE_ENCODING: - st->encode_submode = (*(spx_int32_t*)ptr); - break; - case SPEEX_GET_SUBMODE_ENCODING: - (*(spx_int32_t*)ptr) = st->encode_submode; - break; - case SPEEX_GET_LOOKAHEAD: - (*(spx_int32_t*)ptr)=st->subframeSize; - break; - case SPEEX_SET_HIGHPASS: - st->highpass_enabled = (*(spx_int32_t*)ptr); - break; - case SPEEX_GET_HIGHPASS: - (*(spx_int32_t*)ptr) = st->highpass_enabled; - break; - /* FIXME: Convert to fixed-point and re-enable even when float API is disabled */ -#ifndef DISABLE_FLOAT_API - case SPEEX_GET_ACTIVITY: - { - float ret; - ret = log(st->level/st->min_level)/log(st->max_level/st->min_level); - if (ret>1) - ret = 1; - /* Done in a strange way to catch NaNs as well */ - if (!(ret > 0)) - ret = 0; - /*printf ("%f %f %f %f\n", st->level, st->min_level, st->max_level, ret);*/ - (*(spx_int32_t*)ptr) = (int)(100*ret); - } - break; -#endif - case SPEEX_GET_PI_GAIN: - { - int i; - spx_word32_t *g = (spx_word32_t*)ptr; - for (i=0;i<st->nbSubframes;i++) - g[i]=st->pi_gain[i]; - } - break; - case SPEEX_GET_EXC: - { - int i; - for (i=0;i<st->nbSubframes;i++) - ((spx_word16_t*)ptr)[i] = compute_rms16(st->exc+i*st->subframeSize, st->subframeSize); - } - break; - case SPEEX_GET_DTX_STATUS: - *((spx_int32_t*)ptr) = st->dtx_enabled; - break; - case SPEEX_SET_INNOVATION_SAVE: - st->innov_save = (spx_word16_t*)ptr; - break; - case SPEEX_SET_WIDEBAND: - st->isWideband = *((spx_int32_t*)ptr); - break; - case SPEEX_GET_STACK: - *((char**)ptr) = st->stack; - break; - default: - speex_warning_int("Unknown nb_ctl request: ", request); - return -1; - } - return 0; -} diff --git a/drivers/speex/nb_celp.h b/drivers/speex/nb_celp.h deleted file mode 100644 index 14c776ff35..0000000000 --- a/drivers/speex/nb_celp.h +++ /dev/null @@ -1,203 +0,0 @@ -/* Copyright (C) 2002-2006 Jean-Marc Valin */ -/** - @file nb_celp.h - @brief Narrowband CELP encoder/decoder -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 NB_CELP_H -#define NB_CELP_H - -#include "modes.h" -#include <speex/speex_bits.h> -#include <speex/speex_callbacks.h> -#include "vbr.h" -#include "filters.h" - -#ifdef VORBIS_PSYCHO -#include "vorbis_psy.h" -#endif - -/**Structure representing the full state of the narrowband encoder*/ -typedef struct EncState { - const SpeexMode *mode; /**< Mode corresponding to the state */ - int first; /**< Is this the first frame? */ - int frameSize; /**< Size of frames */ - int subframeSize; /**< Size of sub-frames */ - int nbSubframes; /**< Number of sub-frames */ - int windowSize; /**< Analysis (LPC) window length */ - int lpcSize; /**< LPC order */ - int min_pitch; /**< Minimum pitch value allowed */ - int max_pitch; /**< Maximum pitch value allowed */ - - spx_word32_t cumul_gain; /**< Product of previously used pitch gains (Q10) */ - int bounded_pitch; /**< Next frame should not rely on previous frames for pitch */ - int ol_pitch; /**< Open-loop pitch */ - int ol_voiced; /**< Open-loop voiced/non-voiced decision */ - int *pitch; - -#ifdef VORBIS_PSYCHO - VorbisPsy *psy; - float *psy_window; - float *curve; - float *old_curve; -#endif - - spx_word16_t gamma1; /**< Perceptual filter: A(z/gamma1) */ - spx_word16_t gamma2; /**< Perceptual filter: A(z/gamma2) */ - spx_word16_t lpc_floor; /**< Noise floor multiplier for A[0] in LPC analysis*/ - char *stack; /**< Pseudo-stack allocation for temporary memory */ - spx_word16_t *winBuf; /**< Input buffer (original signal) */ - spx_word16_t *excBuf; /**< Excitation buffer */ - spx_word16_t *exc; /**< Start of excitation frame */ - spx_word16_t *swBuf; /**< Weighted signal buffer */ - spx_word16_t *sw; /**< Start of weighted signal frame */ - const spx_word16_t *window; /**< Temporary (Hanning) window */ - const spx_word16_t *lagWindow; /**< Window applied to auto-correlation */ - spx_lsp_t *old_lsp; /**< LSPs for previous frame */ - spx_lsp_t *old_qlsp; /**< Quantized LSPs for previous frame */ - spx_mem_t *mem_sp; /**< Filter memory for signal synthesis */ - spx_mem_t *mem_sw; /**< Filter memory for perceptually-weighted signal */ - spx_mem_t *mem_sw_whole; /**< Filter memory for perceptually-weighted signal (whole frame)*/ - spx_mem_t *mem_exc; /**< Filter memory for excitation (whole frame) */ - spx_mem_t *mem_exc2; /**< Filter memory for excitation (whole frame) */ - spx_mem_t mem_hp[2]; /**< High-pass filter memory */ - spx_word32_t *pi_gain; /**< Gain of LPC filter at theta=pi (fe/2) */ - spx_word16_t *innov_rms_save; /**< If non-NULL, innovation RMS is copied here */ - -#ifndef DISABLE_VBR - VBRState *vbr; /**< State of the VBR data */ - float vbr_quality; /**< Quality setting for VBR encoding */ - float relative_quality; /**< Relative quality that will be needed by VBR */ - spx_int32_t vbr_enabled; /**< 1 for enabling VBR, 0 otherwise */ - spx_int32_t vbr_max; /**< Max bit-rate allowed in VBR mode */ - int vad_enabled; /**< 1 for enabling VAD, 0 otherwise */ - int dtx_enabled; /**< 1 for enabling DTX, 0 otherwise */ - int dtx_count; /**< Number of consecutive DTX frames */ - spx_int32_t abr_enabled; /**< ABR setting (in bps), 0 if off */ - float abr_drift; - float abr_drift2; - float abr_count; -#endif /* #ifndef DISABLE_VBR */ - - int complexity; /**< Complexity setting (0-10 from least complex to most complex) */ - spx_int32_t sampling_rate; - int plc_tuning; - int encode_submode; - const SpeexSubmode * const *submodes; /**< Sub-mode data */ - int submodeID; /**< Activated sub-mode */ - int submodeSelect; /**< Mode chosen by the user (may differ from submodeID if VAD is on) */ - int isWideband; /**< Is this used as part of the embedded wideband codec */ - int highpass_enabled; /**< Is the input filter enabled */ -} EncState; - -/**Structure representing the full state of the narrowband decoder*/ -typedef struct DecState { - const SpeexMode *mode; /**< Mode corresponding to the state */ - int first; /**< Is this the first frame? */ - int count_lost; /**< Was the last frame lost? */ - int frameSize; /**< Size of frames */ - int subframeSize; /**< Size of sub-frames */ - int nbSubframes; /**< Number of sub-frames */ - int lpcSize; /**< LPC order */ - int min_pitch; /**< Minimum pitch value allowed */ - int max_pitch; /**< Maximum pitch value allowed */ - spx_int32_t sampling_rate; - - spx_word16_t last_ol_gain; /**< Open-loop gain for previous frame */ - - char *stack; /**< Pseudo-stack allocation for temporary memory */ - spx_word16_t *excBuf; /**< Excitation buffer */ - spx_word16_t *exc; /**< Start of excitation frame */ - spx_lsp_t *old_qlsp; /**< Quantized LSPs for previous frame */ - spx_coef_t *interp_qlpc; /**< Interpolated quantized LPCs */ - spx_mem_t *mem_sp; /**< Filter memory for synthesis signal */ - spx_mem_t mem_hp[2]; /**< High-pass filter memory */ - spx_word32_t *pi_gain; /**< Gain of LPC filter at theta=pi (fe/2) */ - spx_word16_t *innov_save; /** If non-NULL, innovation is copied here */ - - spx_word16_t level; - spx_word16_t max_level; - spx_word16_t min_level; - - /* This is used in packet loss concealment */ - int last_pitch; /**< Pitch of last correctly decoded frame */ - spx_word16_t last_pitch_gain; /**< Pitch gain of last correctly decoded frame */ - spx_word16_t pitch_gain_buf[3]; /**< Pitch gain of last decoded frames */ - int pitch_gain_buf_idx; /**< Tail of the buffer */ - spx_int32_t seed; /** Seed used for random number generation */ - - int encode_submode; - const SpeexSubmode * const *submodes; /**< Sub-mode data */ - int submodeID; /**< Activated sub-mode */ - int lpc_enh_enabled; /**< 1 when LPC enhancer is on, 0 otherwise */ - SpeexCallback speex_callbacks[SPEEX_MAX_CALLBACKS]; - - SpeexCallback user_callback; - - /*Vocoder data*/ - spx_word16_t voc_m1; - spx_word32_t voc_m2; - spx_word16_t voc_mean; - int voc_offset; - - int dtx_enabled; - int isWideband; /**< Is this used as part of the embedded wideband codec */ - int highpass_enabled; /**< Is the input filter enabled */ -} DecState; - -/** Initializes encoder state*/ -void *nb_encoder_init(const SpeexMode *m); - -/** De-allocates encoder state resources*/ -void nb_encoder_destroy(void *state); - -/** Encodes one frame*/ -int nb_encode(void *state, void *in, SpeexBits *bits); - - -/** Initializes decoder state*/ -void *nb_decoder_init(const SpeexMode *m); - -/** De-allocates decoder state resources*/ -void nb_decoder_destroy(void *state); - -/** Decodes one frame*/ -int nb_decode(void *state, SpeexBits *bits, void *out); - -/** ioctl-like function for controlling a narrowband encoder */ -int nb_encoder_ctl(void *state, int request, void *ptr); - -/** ioctl-like function for controlling a narrowband decoder */ -int nb_decoder_ctl(void *state, int request, void *ptr); - - -#endif diff --git a/drivers/speex/os_support.h b/drivers/speex/os_support.h deleted file mode 100644 index 9a18247aa7..0000000000 --- a/drivers/speex/os_support.h +++ /dev/null @@ -1,172 +0,0 @@ -/* 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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 - -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - - -#include "config.h" - -#ifdef OS_SUPPORT_CUSTOM -#include "os_support_custom.h" -#endif - -#include "speex_bind.h" - - -/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free - NOTE: speex_alloc needs to CLEAR THE MEMORY */ -#ifndef OVERRIDE_SPEEX_ALLOC -static SPEEX_INLINE void *speex_alloc (int size) -{ - /* WARNING: this is not equivalent to malloc(). If you want to use malloc() - or your own allocator, YOU NEED TO CLEAR THE MEMORY ALLOCATED. Otherwise - you will experience strange bugs */ - return calloc(size,1); -} -#endif - -/** Same as speex_alloc, except that the area is only needed inside a Speex call (might cause problem with wideband though) */ -#ifndef OVERRIDE_SPEEX_ALLOC_SCRATCH -static SPEEX_INLINE void *speex_alloc_scratch (int size) -{ - /* Scratch space doesn't need to be cleared */ - return calloc(size,1); -} -#endif - -/** Speex wrapper for realloc. To do your own dynamic allocation, all you need to do is replace this function, speex_alloc and speex_free */ -#ifndef OVERRIDE_SPEEX_REALLOC -static SPEEX_INLINE void *speex_realloc (void *ptr, int size) -{ - return realloc(ptr, size); -} -#endif - -/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_alloc */ -#ifndef OVERRIDE_SPEEX_FREE -static SPEEX_INLINE void speex_free (void *ptr) -{ - free(ptr); -} -#endif - -/** Same as speex_free, except that the area is only needed inside a Speex call (might cause problem with wideband though) */ -#ifndef OVERRIDE_SPEEX_FREE_SCRATCH -static SPEEX_INLINE void speex_free_scratch (void *ptr) -{ - free(ptr); -} -#endif - -/** Copy n bytes of memory from src to dst. The 0* term provides compile-time type checking */ -#ifndef OVERRIDE_SPEEX_COPY -#define SPEEX_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) -#endif - -/** Copy n bytes of memory from src to dst, allowing overlapping regions. The 0* term - provides compile-time type checking */ -#ifndef OVERRIDE_SPEEX_MOVE -#define SPEEX_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) -#endif - -/** Set n bytes of memory to value of c, starting at address s */ -#ifndef OVERRIDE_SPEEX_MEMSET -#define SPEEX_MEMSET(dst, c, n) (memset((dst), (c), (n)*sizeof(*(dst)))) -#endif - - -#ifndef OVERRIDE_SPEEX_FATAL -static SPEEX_INLINE void _speex_fatal(const char *str, const char *file, int line) -{ - fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str); - exit(1); -} -#endif - -#ifndef OVERRIDE_SPEEX_WARNING -static SPEEX_INLINE void speex_warning(const char *str) -{ -#ifndef DISABLE_WARNINGS - fprintf (stderr, "warning: %s\n", str); -#endif -} -#endif - -#ifndef OVERRIDE_SPEEX_WARNING_INT -static SPEEX_INLINE void speex_warning_int(const char *str, int val) -{ -#ifndef DISABLE_WARNINGS - fprintf (stderr, "warning: %s %d\n", str, val); -#endif -} -#endif - -#ifndef OVERRIDE_SPEEX_NOTIFY -static SPEEX_INLINE void speex_notify(const char *str) -{ -#ifndef DISABLE_NOTIFICATIONS - fprintf (stderr, "notification: %s\n", str); -#endif -} -#endif - -#ifndef OVERRIDE_SPEEX_PUTC -/** Speex wrapper for putc */ -static SPEEX_INLINE void _speex_putc(int ch, void *file) -{ - FILE *f = (FILE *)file; - fprintf(f, "%c", ch); -} -#endif - -#define speex_fatal(str) _speex_fatal(str, __FILE__, __LINE__); -#define speex_assert(cond) {if (!(cond)) {speex_fatal("assertion failed: " #cond);}} - -#ifndef RELEASE -static SPEEX_INLINE void print_vec(float *vec, int len, char *name) -{ - int i; - printf ("%s ", name); - for (i=0;i<len;i++) - printf (" %f", vec[i]); - printf ("\n"); -} -#endif - -#endif - diff --git a/drivers/speex/preprocess.c b/drivers/speex/preprocess.c deleted file mode 100644 index 40b7979665..0000000000 --- a/drivers/speex/preprocess.c +++ /dev/null @@ -1,1219 +0,0 @@ -/* Copyright (C) 2003 Epic Games (written by Jean-Marc Valin) - Copyright (C) 2004-2006 Epic Games - - File: preprocess.c - Preprocessor with denoising based on the algorithm by Ephraim and Malah - - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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. -*/ - - -/* - Recommended papers: - - Y. Ephraim and D. Malah, "Speech enhancement using minimum mean-square error - short-time spectral amplitude estimator". IEEE Transactions on Acoustics, - Speech and Signal Processing, vol. ASSP-32, no. 6, pp. 1109-1121, 1984. - - Y. Ephraim and D. Malah, "Speech enhancement using minimum mean-square error - log-spectral amplitude estimator". IEEE Transactions on Acoustics, Speech and - Signal Processing, vol. ASSP-33, no. 2, pp. 443-445, 1985. - - I. Cohen and B. Berdugo, "Speech enhancement for non-stationary noise environments". - Signal Processing, vol. 81, no. 2, pp. 2403-2418, 2001. - - Stefan Gustafsson, Rainer Martin, Peter Jax, and Peter Vary. "A psychoacoustic - approach to combined acoustic echo cancellation and noise reduction". IEEE - Transactions on Speech and Audio Processing, 2002. - - J.-M. Valin, J. Rouat, and F. Michaud, "Microphone array post-filter for separation - of simultaneous non-stationary sources". In Proceedings IEEE International - Conference on Acoustics, Speech, and Signal Processing, 2004. -*/ - - -#include "config.h" - - -#include <math.h> -#include "speex/speex_preprocess.h" -#include "speex/speex_echo.h" -#include "arch.h" -#include "fftwrap.h" -#include "filterbank.h" -#include "math_approx.h" -#include "os_support.h" - -#ifndef M_PI -#define M_PI 3.14159263 -#endif - -#define LOUDNESS_EXP 5.f -#define AMP_SCALE .001f -#define AMP_SCALE_1 1000.f - -#define NB_BANDS 24 - -#define SPEECH_PROB_START_DEFAULT QCONST16(0.35f,15) -#define SPEECH_PROB_CONTINUE_DEFAULT QCONST16(0.20f,15) -#define NOISE_SUPPRESS_DEFAULT -15 -#define ECHO_SUPPRESS_DEFAULT -40 -#define ECHO_SUPPRESS_ACTIVE_DEFAULT -15 - -#ifndef NULL -#define NULL 0 -#endif - -#define SQR(x) ((x)*(x)) -#define SQR16(x) (MULT16_16((x),(x))) -#define SQR16_Q15(x) (MULT16_16_Q15((x),(x))) - -#ifdef FIXED_POINT -static SPEEX_INLINE spx_word16_t DIV32_16_Q8(spx_word32_t a, spx_word32_t b) -{ - if (SHR32(a,7) >= b) - { - return 32767; - } else { - if (b>=QCONST32(1,23)) - { - a = SHR32(a,8); - b = SHR32(b,8); - } - if (b>=QCONST32(1,19)) - { - a = SHR32(a,4); - b = SHR32(b,4); - } - if (b>=QCONST32(1,15)) - { - a = SHR32(a,4); - b = SHR32(b,4); - } - a = SHL32(a,8); - return PDIV32_16(a,b); - } - -} -static SPEEX_INLINE spx_word16_t DIV32_16_Q15(spx_word32_t a, spx_word32_t b) -{ - if (SHR32(a,15) >= b) - { - return 32767; - } else { - if (b>=QCONST32(1,23)) - { - a = SHR32(a,8); - b = SHR32(b,8); - } - if (b>=QCONST32(1,19)) - { - a = SHR32(a,4); - b = SHR32(b,4); - } - if (b>=QCONST32(1,15)) - { - a = SHR32(a,4); - b = SHR32(b,4); - } - a = SHL32(a,15)-a; - return DIV32_16(a,b); - } -} -#define SNR_SCALING 256.f -#define SNR_SCALING_1 0.0039062f -#define SNR_SHIFT 8 - -#define FRAC_SCALING 32767.f -#define FRAC_SCALING_1 3.0518e-05 -#define FRAC_SHIFT 1 - -#define EXPIN_SCALING 2048.f -#define EXPIN_SCALING_1 0.00048828f -#define EXPIN_SHIFT 11 -#define EXPOUT_SCALING_1 1.5259e-05 - -#define NOISE_SHIFT 7 - -#else - -#define DIV32_16_Q8(a,b) ((a)/(b)) -#define DIV32_16_Q15(a,b) ((a)/(b)) -#define SNR_SCALING 1.f -#define SNR_SCALING_1 1.f -#define SNR_SHIFT 0 -#define FRAC_SCALING 1.f -#define FRAC_SCALING_1 1.f -#define FRAC_SHIFT 0 -#define NOISE_SHIFT 0 - -#define EXPIN_SCALING 1.f -#define EXPIN_SCALING_1 1.f -#define EXPOUT_SCALING_1 1.f - -#endif - -/** Speex pre-processor state. */ -struct SpeexPreprocessState_ { - /* Basic info */ - int frame_size; /**< Number of samples processed each time */ - int ps_size; /**< Number of points in the power spectrum */ - int sampling_rate; /**< Sampling rate of the input/output */ - int nbands; - FilterBank *bank; - - /* Parameters */ - int denoise_enabled; - int vad_enabled; - int dereverb_enabled; - spx_word16_t reverb_decay; - spx_word16_t reverb_level; - spx_word16_t speech_prob_start; - spx_word16_t speech_prob_continue; - int noise_suppress; - int echo_suppress; - int echo_suppress_active; - SpeexEchoState *echo_state; - - spx_word16_t speech_prob; /**< Probability last frame was speech */ - - /* DSP-related arrays */ - spx_word16_t *frame; /**< Processing frame (2*ps_size) */ - spx_word16_t *ft; /**< Processing frame in freq domain (2*ps_size) */ - spx_word32_t *ps; /**< Current power spectrum */ - spx_word16_t *gain2; /**< Adjusted gains */ - spx_word16_t *gain_floor; /**< Minimum gain allowed */ - spx_word16_t *window; /**< Analysis/Synthesis window */ - spx_word32_t *noise; /**< Noise estimate */ - spx_word32_t *reverb_estimate; /**< Estimate of reverb energy */ - spx_word32_t *old_ps; /**< Power spectrum for last frame */ - spx_word16_t *gain; /**< Ephraim Malah gain */ - spx_word16_t *prior; /**< A-priori SNR */ - spx_word16_t *post; /**< A-posteriori SNR */ - - spx_word32_t *S; /**< Smoothed power spectrum */ - spx_word32_t *Smin; /**< See Cohen paper */ - spx_word32_t *Stmp; /**< See Cohen paper */ - int *update_prob; /**< Probability of speech presence for noise update */ - - spx_word16_t *zeta; /**< Smoothed a priori SNR */ - spx_word32_t *echo_noise; - spx_word32_t *residual_echo; - - /* Misc */ - spx_word16_t *inbuf; /**< Input buffer (overlapped analysis) */ - spx_word16_t *outbuf; /**< Output buffer (for overlap and add) */ - - /* AGC stuff, only for floating point for now */ -#ifndef FIXED_POINT - int agc_enabled; - float agc_level; - float loudness_accum; - float *loudness_weight; /**< Perceptual loudness curve */ - float loudness; /**< Loudness estimate */ - float agc_gain; /**< Current AGC gain */ - float max_gain; /**< Maximum gain allowed */ - float max_increase_step; /**< Maximum increase in gain from one frame to another */ - float max_decrease_step; /**< Maximum decrease in gain from one frame to another */ - float prev_loudness; /**< Loudness of previous frame */ - float init_max; /**< Current gain limit during initialisation */ -#endif - int nb_adapt; /**< Number of frames used for adaptation so far */ - int was_speech; - int min_count; /**< Number of frames processed so far */ - void *fft_lookup; /**< Lookup table for the FFT */ -#ifdef FIXED_POINT - int frame_shift; -#endif -}; - - -static void conj_window(spx_word16_t *w, int len) -{ - int i; - for (i=0;i<len;i++) - { - spx_word16_t tmp; -#ifdef FIXED_POINT - spx_word16_t x = DIV32_16(MULT16_16(32767,i),len); -#else - spx_word16_t x = DIV32_16(MULT16_16(QCONST16(4.f,13),i),len); -#endif - int inv=0; - if (x<QCONST16(1.f,13)) - { - } else if (x<QCONST16(2.f,13)) - { - x=QCONST16(2.f,13)-x; - inv=1; - } else if (x<QCONST16(3.f,13)) - { - x=x-QCONST16(2.f,13); - inv=1; - } else { - x=QCONST16(2.f,13)-x+QCONST16(2.f,13); /* 4 - x */ - } - x = MULT16_16_Q14(QCONST16(1.271903f,14), x); - tmp = SQR16_Q15(QCONST16(.5f,15)-MULT16_16_P15(QCONST16(.5f,15),spx_cos_norm(SHL32(EXTEND32(x),2)))); - if (inv) - tmp=SUB16(Q15_ONE,tmp); - w[i]=spx_sqrt(SHL32(EXTEND32(tmp),15)); - } -} - - -#ifdef FIXED_POINT -/* This function approximates the gain function - y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x) - which multiplied by xi/(1+xi) is the optimal gain - in the loudness domain ( sqrt[amplitude] ) - Input in Q11 format, output in Q15 -*/ -static SPEEX_INLINE spx_word32_t hypergeom_gain(spx_word32_t xx) -{ - int ind; - spx_word16_t frac; - /* Q13 table */ - static const spx_word16_t table[21] = { - 6730, 8357, 9868, 11267, 12563, 13770, 14898, - 15959, 16961, 17911, 18816, 19682, 20512, 21311, - 22082, 22827, 23549, 24250, 24931, 25594, 26241}; - ind = SHR32(xx,10); - if (ind<0) - return Q15_ONE; - if (ind>19) - return ADD32(EXTEND32(Q15_ONE),EXTEND32(DIV32_16(QCONST32(.1296,23), SHR32(xx,EXPIN_SHIFT-SNR_SHIFT)))); - frac = SHL32(xx-SHL32(ind,10),5); - return SHL32(DIV32_16(PSHR32(MULT16_16(Q15_ONE-frac,table[ind]) + MULT16_16(frac,table[ind+1]),7),(spx_sqrt(SHL32(xx,15)+6711))),7); -} - -static SPEEX_INLINE spx_word16_t qcurve(spx_word16_t x) -{ - x = MAX16(x, 1); - return DIV32_16(SHL32(EXTEND32(32767),9),ADD16(512,MULT16_16_Q15(QCONST16(.60f,15),DIV32_16(32767,x)))); -} - -/* Compute the gain floor based on different floors for the background noise and residual echo */ -static void compute_gain_floor(int noise_suppress, int effective_echo_suppress, spx_word32_t *noise, spx_word32_t *echo, spx_word16_t *gain_floor, int len) -{ - int i; - - if (noise_suppress > effective_echo_suppress) - { - spx_word16_t noise_gain, gain_ratio; - noise_gain = EXTRACT16(MIN32(Q15_ONE,SHR32(spx_exp(MULT16_16(QCONST16(0.11513,11),noise_suppress)),1))); - gain_ratio = EXTRACT16(MIN32(Q15_ONE,SHR32(spx_exp(MULT16_16(QCONST16(.2302585f,11),effective_echo_suppress-noise_suppress)),1))); - - /* gain_floor = sqrt [ (noise*noise_floor + echo*echo_floor) / (noise+echo) ] */ - for (i=0;i<len;i++) - gain_floor[i] = MULT16_16_Q15(noise_gain, - spx_sqrt(SHL32(EXTEND32(DIV32_16_Q15(PSHR32(noise[i],NOISE_SHIFT) + MULT16_32_Q15(gain_ratio,echo[i]), - (1+PSHR32(noise[i],NOISE_SHIFT) + echo[i]) )),15))); - } else { - spx_word16_t echo_gain, gain_ratio; - echo_gain = EXTRACT16(MIN32(Q15_ONE,SHR32(spx_exp(MULT16_16(QCONST16(0.11513,11),effective_echo_suppress)),1))); - gain_ratio = EXTRACT16(MIN32(Q15_ONE,SHR32(spx_exp(MULT16_16(QCONST16(.2302585f,11),noise_suppress-effective_echo_suppress)),1))); - - /* gain_floor = sqrt [ (noise*noise_floor + echo*echo_floor) / (noise+echo) ] */ - for (i=0;i<len;i++) - gain_floor[i] = MULT16_16_Q15(echo_gain, - spx_sqrt(SHL32(EXTEND32(DIV32_16_Q15(MULT16_32_Q15(gain_ratio,PSHR32(noise[i],NOISE_SHIFT)) + echo[i], - (1+PSHR32(noise[i],NOISE_SHIFT) + echo[i]) )),15))); - } -} - -#else -/* This function approximates the gain function - y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x) - which multiplied by xi/(1+xi) is the optimal gain - in the loudness domain ( sqrt[amplitude] ) -*/ -static SPEEX_INLINE spx_word32_t hypergeom_gain(spx_word32_t xx) -{ - int ind; - float integer, frac; - float x; - static const float table[21] = { - 0.82157f, 1.02017f, 1.20461f, 1.37534f, 1.53363f, 1.68092f, 1.81865f, - 1.94811f, 2.07038f, 2.18638f, 2.29688f, 2.40255f, 2.50391f, 2.60144f, - 2.69551f, 2.78647f, 2.87458f, 2.96015f, 3.04333f, 3.12431f, 3.20326f}; - x = EXPIN_SCALING_1*xx; - integer = floor(2*x); - ind = (int)integer; - if (ind<0) - return FRAC_SCALING; - if (ind>19) - return FRAC_SCALING*(1+.1296/x); - frac = 2*x-integer; - return FRAC_SCALING*((1-frac)*table[ind] + frac*table[ind+1])/sqrt(x+.0001f); -} - -static SPEEX_INLINE spx_word16_t qcurve(spx_word16_t x) -{ - return 1.f/(1.f+.15f/(SNR_SCALING_1*x)); -} - -static void compute_gain_floor(int noise_suppress, int effective_echo_suppress, spx_word32_t *noise, spx_word32_t *echo, spx_word16_t *gain_floor, int len) -{ - int i; - float echo_floor; - float noise_floor; - - noise_floor = exp(.2302585f*noise_suppress); - echo_floor = exp(.2302585f*effective_echo_suppress); - - /* Compute the gain floor based on different floors for the background noise and residual echo */ - for (i=0;i<len;i++) - gain_floor[i] = FRAC_SCALING*sqrt(noise_floor*PSHR32(noise[i],NOISE_SHIFT) + echo_floor*echo[i])/sqrt(1+PSHR32(noise[i],NOISE_SHIFT) + echo[i]); -} - -#endif -EXPORT SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate) -{ - int i; - int N, N3, N4, M; - - SpeexPreprocessState *st = (SpeexPreprocessState *)speex_alloc(sizeof(SpeexPreprocessState)); - st->frame_size = frame_size; - - /* Round ps_size down to the nearest power of two */ -#if 0 - i=1; - st->ps_size = st->frame_size; - while(1) - { - if (st->ps_size & ~i) - { - st->ps_size &= ~i; - i<<=1; - } else { - break; - } - } - - - if (st->ps_size < 3*st->frame_size/4) - st->ps_size = st->ps_size * 3 / 2; -#else - st->ps_size = st->frame_size; -#endif - - N = st->ps_size; - N3 = 2*N - st->frame_size; - N4 = st->frame_size - N3; - - st->sampling_rate = sampling_rate; - st->denoise_enabled = 1; - st->vad_enabled = 0; - st->dereverb_enabled = 0; - st->reverb_decay = 0; - st->reverb_level = 0; - st->noise_suppress = NOISE_SUPPRESS_DEFAULT; - st->echo_suppress = ECHO_SUPPRESS_DEFAULT; - st->echo_suppress_active = ECHO_SUPPRESS_ACTIVE_DEFAULT; - - st->speech_prob_start = SPEECH_PROB_START_DEFAULT; - st->speech_prob_continue = SPEECH_PROB_CONTINUE_DEFAULT; - - st->echo_state = NULL; - - st->nbands = NB_BANDS; - M = st->nbands; - st->bank = filterbank_new(M, sampling_rate, N, 1); - - st->frame = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t)); - st->window = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t)); - st->ft = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t)); - - st->ps = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); - st->noise = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); - st->echo_noise = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); - st->residual_echo = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); - st->reverb_estimate = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); - st->old_ps = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); - st->prior = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); - st->post = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); - st->gain = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); - st->gain2 = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); - st->gain_floor = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); - st->zeta = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); - - st->S = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); - st->Smin = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); - st->Stmp = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); - st->update_prob = (int*)speex_alloc(N*sizeof(int)); - - st->inbuf = (spx_word16_t*)speex_alloc(N3*sizeof(spx_word16_t)); - st->outbuf = (spx_word16_t*)speex_alloc(N3*sizeof(spx_word16_t)); - - conj_window(st->window, 2*N3); - for (i=2*N3;i<2*st->ps_size;i++) - st->window[i]=Q15_ONE; - - if (N4>0) - { - for (i=N3-1;i>=0;i--) - { - st->window[i+N3+N4]=st->window[i+N3]; - st->window[i+N3]=1; - } - } - for (i=0;i<N+M;i++) - { - st->noise[i]=QCONST32(1.f,NOISE_SHIFT); - st->reverb_estimate[i]=0; - st->old_ps[i]=1; - st->gain[i]=Q15_ONE; - st->post[i]=SHL16(1, SNR_SHIFT); - st->prior[i]=SHL16(1, SNR_SHIFT); - } - - for (i=0;i<N;i++) - st->update_prob[i] = 1; - for (i=0;i<N3;i++) - { - st->inbuf[i]=0; - st->outbuf[i]=0; - } -#ifndef FIXED_POINT - st->agc_enabled = 0; - st->agc_level = 8000; - st->loudness_weight = (float*)speex_alloc(N*sizeof(float)); - for (i=0;i<N;i++) - { - float ff=((float)i)*.5*sampling_rate/((float)N); - /*st->loudness_weight[i] = .5f*(1.f/(1.f+ff/8000.f))+1.f*exp(-.5f*(ff-3800.f)*(ff-3800.f)/9e5f);*/ - st->loudness_weight[i] = .35f-.35f*ff/16000.f+.73f*exp(-.5f*(ff-3800)*(ff-3800)/9e5f); - if (st->loudness_weight[i]<.01f) - st->loudness_weight[i]=.01f; - st->loudness_weight[i] *= st->loudness_weight[i]; - } - /*st->loudness = pow(AMP_SCALE*st->agc_level,LOUDNESS_EXP);*/ - st->loudness = 1e-15; - st->agc_gain = 1; - st->max_gain = 30; - st->max_increase_step = exp(0.11513f * 12.*st->frame_size / st->sampling_rate); - st->max_decrease_step = exp(-0.11513f * 40.*st->frame_size / st->sampling_rate); - st->prev_loudness = 1; - st->init_max = 1; -#endif - st->was_speech = 0; - - st->fft_lookup = spx_fft_init(2*N); - - st->nb_adapt=0; - st->min_count=0; - return st; -} - -EXPORT void speex_preprocess_state_destroy(SpeexPreprocessState *st) -{ - speex_free(st->frame); - speex_free(st->ft); - speex_free(st->ps); - speex_free(st->gain2); - speex_free(st->gain_floor); - speex_free(st->window); - speex_free(st->noise); - speex_free(st->reverb_estimate); - speex_free(st->old_ps); - speex_free(st->gain); - speex_free(st->prior); - speex_free(st->post); -#ifndef FIXED_POINT - speex_free(st->loudness_weight); -#endif - speex_free(st->echo_noise); - speex_free(st->residual_echo); - - speex_free(st->S); - speex_free(st->Smin); - speex_free(st->Stmp); - speex_free(st->update_prob); - speex_free(st->zeta); - - speex_free(st->inbuf); - speex_free(st->outbuf); - - spx_fft_destroy(st->fft_lookup); - filterbank_destroy(st->bank); - speex_free(st); -} - -/* FIXME: The AGC doesn't work yet with fixed-point*/ -#ifndef FIXED_POINT -static void speex_compute_agc(SpeexPreprocessState *st, spx_word16_t Pframe, spx_word16_t *ft) -{ - int i; - int N = st->ps_size; - float target_gain; - float loudness=1.f; - float rate; - - for (i=2;i<N;i++) - { - loudness += 2.f*N*st->ps[i]* st->loudness_weight[i]; - } - loudness=sqrt(loudness); - /*if (loudness < 2*pow(st->loudness, 1.0/LOUDNESS_EXP) && - loudness*2 > pow(st->loudness, 1.0/LOUDNESS_EXP))*/ - if (Pframe>.3f) - { - /*rate=2.0f*Pframe*Pframe/(1+st->nb_loudness_adapt);*/ - rate = .03*Pframe*Pframe; - st->loudness = (1-rate)*st->loudness + (rate)*pow(AMP_SCALE*loudness, LOUDNESS_EXP); - st->loudness_accum = (1-rate)*st->loudness_accum + rate; - if (st->init_max < st->max_gain && st->nb_adapt > 20) - st->init_max *= 1.f + .1f*Pframe*Pframe; - } - /*printf ("%f %f %f %f\n", Pframe, loudness, pow(st->loudness, 1.0f/LOUDNESS_EXP), st->loudness2);*/ - - target_gain = AMP_SCALE*st->agc_level*pow(st->loudness/(1e-4+st->loudness_accum), -1.0f/LOUDNESS_EXP); - - if ((Pframe>.5 && st->nb_adapt > 20) || target_gain < st->agc_gain) - { - if (target_gain > st->max_increase_step*st->agc_gain) - target_gain = st->max_increase_step*st->agc_gain; - if (target_gain < st->max_decrease_step*st->agc_gain && loudness < 10*st->prev_loudness) - target_gain = st->max_decrease_step*st->agc_gain; - if (target_gain > st->max_gain) - target_gain = st->max_gain; - if (target_gain > st->init_max) - target_gain = st->init_max; - - st->agc_gain = target_gain; - } - /*fprintf (stderr, "%f %f %f\n", loudness, (float)AMP_SCALE_1*pow(st->loudness, 1.0f/LOUDNESS_EXP), st->agc_gain);*/ - - for (i=0;i<2*N;i++) - ft[i] *= st->agc_gain; - st->prev_loudness = loudness; -} -#endif - -static void preprocess_analysis(SpeexPreprocessState *st, spx_int16_t *x) -{ - int i; - int N = st->ps_size; - int N3 = 2*N - st->frame_size; - int N4 = st->frame_size - N3; - spx_word32_t *ps=st->ps; - - /* 'Build' input frame */ - for (i=0;i<N3;i++) - st->frame[i]=st->inbuf[i]; - for (i=0;i<st->frame_size;i++) - st->frame[N3+i]=x[i]; - - /* Update inbuf */ - for (i=0;i<N3;i++) - st->inbuf[i]=x[N4+i]; - - /* Windowing */ - for (i=0;i<2*N;i++) - st->frame[i] = MULT16_16_Q15(st->frame[i], st->window[i]); - -#ifdef FIXED_POINT - { - spx_word16_t max_val=0; - for (i=0;i<2*N;i++) - max_val = MAX16(max_val, ABS16(st->frame[i])); - st->frame_shift = 14-spx_ilog2(EXTEND32(max_val)); - for (i=0;i<2*N;i++) - st->frame[i] = SHL16(st->frame[i], st->frame_shift); - } -#endif - - /* Perform FFT */ - spx_fft(st->fft_lookup, st->frame, st->ft); - - /* Power spectrum */ - ps[0]=MULT16_16(st->ft[0],st->ft[0]); - for (i=1;i<N;i++) - ps[i]=MULT16_16(st->ft[2*i-1],st->ft[2*i-1]) + MULT16_16(st->ft[2*i],st->ft[2*i]); - for (i=0;i<N;i++) - st->ps[i] = PSHR32(st->ps[i], 2*st->frame_shift); - - filterbank_compute_bank32(st->bank, ps, ps+N); -} - -static void update_noise_prob(SpeexPreprocessState *st) -{ - int i; - int min_range; - int N = st->ps_size; - - for (i=1;i<N-1;i++) - st->S[i] = MULT16_32_Q15(QCONST16(.8f,15),st->S[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i-1]) - + MULT16_32_Q15(QCONST16(.1f,15),st->ps[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i+1]); - st->S[0] = MULT16_32_Q15(QCONST16(.8f,15),st->S[0]) + MULT16_32_Q15(QCONST16(.2f,15),st->ps[0]); - st->S[N-1] = MULT16_32_Q15(QCONST16(.8f,15),st->S[N-1]) + MULT16_32_Q15(QCONST16(.2f,15),st->ps[N-1]); - - if (st->nb_adapt==1) - { - for (i=0;i<N;i++) - st->Smin[i] = st->Stmp[i] = 0; - } - - if (st->nb_adapt < 100) - min_range = 15; - else if (st->nb_adapt < 1000) - min_range = 50; - else if (st->nb_adapt < 10000) - min_range = 150; - else - min_range = 300; - if (st->min_count > min_range) - { - st->min_count = 0; - for (i=0;i<N;i++) - { - st->Smin[i] = MIN32(st->Stmp[i], st->S[i]); - st->Stmp[i] = st->S[i]; - } - } else { - for (i=0;i<N;i++) - { - st->Smin[i] = MIN32(st->Smin[i], st->S[i]); - st->Stmp[i] = MIN32(st->Stmp[i], st->S[i]); - } - } - for (i=0;i<N;i++) - { - if (MULT16_32_Q15(QCONST16(.4f,15),st->S[i]) > st->Smin[i]) - st->update_prob[i] = 1; - else - st->update_prob[i] = 0; - /*fprintf (stderr, "%f ", st->S[i]/st->Smin[i]);*/ - /*fprintf (stderr, "%f ", st->update_prob[i]);*/ - } - -} - -#define NOISE_OVERCOMPENS 1. - -void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *Yout, int len); - -EXPORT int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo) -{ - return speex_preprocess_run(st, x); -} - -EXPORT int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x) -{ - int i; - int M; - int N = st->ps_size; - int N3 = 2*N - st->frame_size; - int N4 = st->frame_size - N3; - spx_word32_t *ps=st->ps; - spx_word32_t Zframe; - spx_word16_t Pframe; - spx_word16_t beta, beta_1; - spx_word16_t effective_echo_suppress; - - st->nb_adapt++; - if (st->nb_adapt>20000) - st->nb_adapt = 20000; - st->min_count++; - - beta = MAX16(QCONST16(.03,15),DIV32_16(Q15_ONE,st->nb_adapt)); - beta_1 = Q15_ONE-beta; - M = st->nbands; - /* Deal with residual echo if provided */ - if (st->echo_state) - { - speex_echo_get_residual(st->echo_state, st->residual_echo, N); -#ifndef FIXED_POINT - /* If there are NaNs or ridiculous values, it'll show up in the DC and we just reset everything to zero */ - if (!(st->residual_echo[0] >=0 && st->residual_echo[0]<N*1e9f)) - { - for (i=0;i<N;i++) - st->residual_echo[i] = 0; - } -#endif - for (i=0;i<N;i++) - st->echo_noise[i] = MAX32(MULT16_32_Q15(QCONST16(.6f,15),st->echo_noise[i]), st->residual_echo[i]); - filterbank_compute_bank32(st->bank, st->echo_noise, st->echo_noise+N); - } else { - for (i=0;i<N+M;i++) - st->echo_noise[i] = 0; - } - preprocess_analysis(st, x); - - update_noise_prob(st); - - /* Noise estimation always updated for the 10 first frames */ - /*if (st->nb_adapt<10) - { - for (i=1;i<N-1;i++) - st->update_prob[i] = 0; - } - */ - - /* Update the noise estimate for the frequencies where it can be */ - for (i=0;i<N;i++) - { - if (!st->update_prob[i] || st->ps[i] < PSHR32(st->noise[i], NOISE_SHIFT)) - st->noise[i] = MAX32(EXTEND32(0),MULT16_32_Q15(beta_1,st->noise[i]) + MULT16_32_Q15(beta,SHL32(st->ps[i],NOISE_SHIFT))); - } - filterbank_compute_bank32(st->bank, st->noise, st->noise+N); - - /* Special case for first frame */ - if (st->nb_adapt==1) - for (i=0;i<N+M;i++) - st->old_ps[i] = ps[i]; - - /* Compute a posteriori SNR */ - for (i=0;i<N+M;i++) - { - spx_word16_t gamma; - - /* Total noise estimate including residual echo and reverberation */ - spx_word32_t tot_noise = ADD32(ADD32(ADD32(EXTEND32(1), PSHR32(st->noise[i],NOISE_SHIFT)) , st->echo_noise[i]) , st->reverb_estimate[i]); - - /* A posteriori SNR = ps/noise - 1*/ - st->post[i] = SUB16(DIV32_16_Q8(ps[i],tot_noise), QCONST16(1.f,SNR_SHIFT)); - st->post[i]=MIN16(st->post[i], QCONST16(100.f,SNR_SHIFT)); - - /* Computing update gamma = .1 + .9*(old/(old+noise))^2 */ - gamma = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.89f,15),SQR16_Q15(DIV32_16_Q15(st->old_ps[i],ADD32(st->old_ps[i],tot_noise)))); - - /* A priori SNR update = gamma*max(0,post) + (1-gamma)*old/noise */ - st->prior[i] = EXTRACT16(PSHR32(ADD32(MULT16_16(gamma,MAX16(0,st->post[i])), MULT16_16(Q15_ONE-gamma,DIV32_16_Q8(st->old_ps[i],tot_noise))), 15)); - st->prior[i]=MIN16(st->prior[i], QCONST16(100.f,SNR_SHIFT)); - } - - /*print_vec(st->post, N+M, "");*/ - - /* Recursive average of the a priori SNR. A bit smoothed for the psd components */ - st->zeta[0] = PSHR32(ADD32(MULT16_16(QCONST16(.7f,15),st->zeta[0]), MULT16_16(QCONST16(.3f,15),st->prior[0])),15); - for (i=1;i<N-1;i++) - st->zeta[i] = PSHR32(ADD32(ADD32(ADD32(MULT16_16(QCONST16(.7f,15),st->zeta[i]), MULT16_16(QCONST16(.15f,15),st->prior[i])), - MULT16_16(QCONST16(.075f,15),st->prior[i-1])), MULT16_16(QCONST16(.075f,15),st->prior[i+1])),15); - for (i=N-1;i<N+M;i++) - st->zeta[i] = PSHR32(ADD32(MULT16_16(QCONST16(.7f,15),st->zeta[i]), MULT16_16(QCONST16(.3f,15),st->prior[i])),15); - - /* Speech probability of presence for the entire frame is based on the average filterbank a priori SNR */ - Zframe = 0; - for (i=N;i<N+M;i++) - Zframe = ADD32(Zframe, EXTEND32(st->zeta[i])); - Pframe = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.899f,15),qcurve(DIV32_16(Zframe,st->nbands))); - - effective_echo_suppress = EXTRACT16(PSHR32(ADD32(MULT16_16(SUB16(Q15_ONE,Pframe), st->echo_suppress), MULT16_16(Pframe, st->echo_suppress_active)),15)); - - compute_gain_floor(st->noise_suppress, effective_echo_suppress, st->noise+N, st->echo_noise+N, st->gain_floor+N, M); - - /* Compute Ephraim & Malah gain speech probability of presence for each critical band (Bark scale) - Technically this is actually wrong because the EM gaim assumes a slightly different probability - distribution */ - for (i=N;i<N+M;i++) - { - /* See EM and Cohen papers*/ - spx_word32_t theta; - /* Gain from hypergeometric function */ - spx_word32_t MM; - /* Weiner filter gain */ - spx_word16_t prior_ratio; - /* a priority probability of speech presence based on Bark sub-band alone */ - spx_word16_t P1; - /* Speech absence a priori probability (considering sub-band and frame) */ - spx_word16_t q; -#ifdef FIXED_POINT - spx_word16_t tmp; -#endif - - prior_ratio = PDIV32_16(SHL32(EXTEND32(st->prior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT))); - theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT)); - - MM = hypergeom_gain(theta); - /* Gain with bound */ - st->gain[i] = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM))); - /* Save old Bark power spectrum */ - st->old_ps[i] = MULT16_32_P15(QCONST16(.2f,15),st->old_ps[i]) + MULT16_32_P15(MULT16_16_P15(QCONST16(.8f,15),SQR16_Q15(st->gain[i])),ps[i]); - - P1 = QCONST16(.199f,15)+MULT16_16_Q15(QCONST16(.8f,15),qcurve (st->zeta[i])); - q = Q15_ONE-MULT16_16_Q15(Pframe,P1); -#ifdef FIXED_POINT - theta = MIN32(theta, EXTEND32(32767)); -/*Q8*/tmp = MULT16_16_Q15((SHL32(1,SNR_SHIFT)+st->prior[i]),EXTRACT16(MIN32(Q15ONE,SHR32(spx_exp(-EXTRACT16(theta)),1)))); - tmp = MIN16(QCONST16(3.,SNR_SHIFT), tmp); /* Prevent overflows in the next line*/ -/*Q8*/tmp = EXTRACT16(PSHR32(MULT16_16(PDIV32_16(SHL32(EXTEND32(q),8),(Q15_ONE-q)),tmp),8)); - st->gain2[i]=DIV32_16(SHL32(EXTEND32(32767),SNR_SHIFT), ADD16(256,tmp)); -#else - st->gain2[i]=1/(1.f + (q/(1.f-q))*(1+st->prior[i])*exp(-theta)); -#endif - } - /* Convert the EM gains and speech prob to linear frequency */ - filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2); - filterbank_compute_psd16(st->bank,st->gain+N, st->gain); - - /* Use 1 for linear gain resolution (best) or 0 for Bark gain resolution (faster) */ - if (1) - { - filterbank_compute_psd16(st->bank,st->gain_floor+N, st->gain_floor); - - /* Compute gain according to the Ephraim-Malah algorithm -- linear frequency */ - for (i=0;i<N;i++) - { - spx_word32_t MM; - spx_word32_t theta; - spx_word16_t prior_ratio; - spx_word16_t tmp; - spx_word16_t p; - spx_word16_t g; - - /* Wiener filter gain */ - prior_ratio = PDIV32_16(SHL32(EXTEND32(st->prior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT))); - theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT)); - - /* Optimal estimator for loudness domain */ - MM = hypergeom_gain(theta); - /* EM gain with bound */ - g = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM))); - /* Interpolated speech probability of presence */ - p = st->gain2[i]; - - /* Constrain the gain to be close to the Bark scale gain */ - if (MULT16_16_Q15(QCONST16(.333f,15),g) > st->gain[i]) - g = MULT16_16(3,st->gain[i]); - st->gain[i] = g; - - /* Save old power spectrum */ - st->old_ps[i] = MULT16_32_P15(QCONST16(.2f,15),st->old_ps[i]) + MULT16_32_P15(MULT16_16_P15(QCONST16(.8f,15),SQR16_Q15(st->gain[i])),ps[i]); - - /* Apply gain floor */ - if (st->gain[i] < st->gain_floor[i]) - st->gain[i] = st->gain_floor[i]; - - /* Exponential decay model for reverberation (unused) */ - /*st->reverb_estimate[i] = st->reverb_decay*st->reverb_estimate[i] + st->reverb_decay*st->reverb_level*st->gain[i]*st->gain[i]*st->ps[i];*/ - - /* Take into account speech probability of presence (loudness domain MMSE estimator) */ - /* gain2 = [p*sqrt(gain)+(1-p)*sqrt(gain _floor) ]^2 */ - tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15))); - st->gain2[i]=SQR16_Q15(tmp); - - /* Use this if you want a log-domain MMSE estimator instead */ - /*st->gain2[i] = pow(st->gain[i], p) * pow(st->gain_floor[i],1.f-p);*/ - } - } else { - for (i=N;i<N+M;i++) - { - spx_word16_t tmp; - spx_word16_t p = st->gain2[i]; - st->gain[i] = MAX16(st->gain[i], st->gain_floor[i]); - tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15))); - st->gain2[i]=SQR16_Q15(tmp); - } - filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2); - } - - /* If noise suppression is off, don't apply the gain (but then why call this in the first place!) */ - if (!st->denoise_enabled) - { - for (i=0;i<N+M;i++) - st->gain2[i]=Q15_ONE; - } - - /* Apply computed gain */ - for (i=1;i<N;i++) - { - st->ft[2*i-1] = MULT16_16_P15(st->gain2[i],st->ft[2*i-1]); - st->ft[2*i] = MULT16_16_P15(st->gain2[i],st->ft[2*i]); - } - st->ft[0] = MULT16_16_P15(st->gain2[0],st->ft[0]); - st->ft[2*N-1] = MULT16_16_P15(st->gain2[N-1],st->ft[2*N-1]); - - /*FIXME: This *will* not work for fixed-point */ -#ifndef FIXED_POINT - if (st->agc_enabled) - speex_compute_agc(st, Pframe, st->ft); -#endif - - /* Inverse FFT with 1/N scaling */ - spx_ifft(st->fft_lookup, st->ft, st->frame); - /* Scale back to original (lower) amplitude */ - for (i=0;i<2*N;i++) - st->frame[i] = PSHR16(st->frame[i], st->frame_shift); - - /*FIXME: This *will* not work for fixed-point */ -#ifndef FIXED_POINT - if (st->agc_enabled) - { - float max_sample=0; - for (i=0;i<2*N;i++) - if (fabs(st->frame[i])>max_sample) - max_sample = fabs(st->frame[i]); - if (max_sample>28000.f) - { - float damp = 28000.f/max_sample; - for (i=0;i<2*N;i++) - st->frame[i] *= damp; - } - } -#endif - - /* Synthesis window (for WOLA) */ - for (i=0;i<2*N;i++) - st->frame[i] = MULT16_16_Q15(st->frame[i], st->window[i]); - - /* Perform overlap and add */ - for (i=0;i<N3;i++) - x[i] = st->outbuf[i] + st->frame[i]; - for (i=0;i<N4;i++) - x[N3+i] = st->frame[N3+i]; - - /* Update outbuf */ - for (i=0;i<N3;i++) - st->outbuf[i] = st->frame[st->frame_size+i]; - - /* FIXME: This VAD is a kludge */ - st->speech_prob = Pframe; - if (st->vad_enabled) - { - if (st->speech_prob > st->speech_prob_start || (st->was_speech && st->speech_prob > st->speech_prob_continue)) - { - st->was_speech=1; - return 1; - } else - { - st->was_speech=0; - return 0; - } - } else { - return 1; - } -} - -EXPORT void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x) -{ - int i; - int N = st->ps_size; - int N3 = 2*N - st->frame_size; - int M; - spx_word32_t *ps=st->ps; - - M = st->nbands; - st->min_count++; - - preprocess_analysis(st, x); - - update_noise_prob(st); - - for (i=1;i<N-1;i++) - { - if (!st->update_prob[i] || st->ps[i] < PSHR32(st->noise[i],NOISE_SHIFT)) - { - st->noise[i] = MULT16_32_Q15(QCONST16(.95f,15),st->noise[i]) + MULT16_32_Q15(QCONST16(.05f,15),SHL32(st->ps[i],NOISE_SHIFT)); - } - } - - for (i=0;i<N3;i++) - st->outbuf[i] = MULT16_16_Q15(x[st->frame_size-N3+i],st->window[st->frame_size+i]); - - /* Save old power spectrum */ - for (i=0;i<N+M;i++) - st->old_ps[i] = ps[i]; - - for (i=0;i<N;i++) - st->reverb_estimate[i] = MULT16_32_Q15(st->reverb_decay, st->reverb_estimate[i]); -} - - -EXPORT int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr) -{ - int i; - SpeexPreprocessState *st; - st=(SpeexPreprocessState*)state; - switch(request) - { - case SPEEX_PREPROCESS_SET_DENOISE: - st->denoise_enabled = (*(spx_int32_t*)ptr); - break; - case SPEEX_PREPROCESS_GET_DENOISE: - (*(spx_int32_t*)ptr) = st->denoise_enabled; - break; -#ifndef FIXED_POINT - case SPEEX_PREPROCESS_SET_AGC: - st->agc_enabled = (*(spx_int32_t*)ptr); - break; - case SPEEX_PREPROCESS_GET_AGC: - (*(spx_int32_t*)ptr) = st->agc_enabled; - break; -#ifndef DISABLE_FLOAT_API - case SPEEX_PREPROCESS_SET_AGC_LEVEL: - st->agc_level = (*(float*)ptr); - if (st->agc_level<1) - st->agc_level=1; - if (st->agc_level>32768) - st->agc_level=32768; - break; - case SPEEX_PREPROCESS_GET_AGC_LEVEL: - (*(float*)ptr) = st->agc_level; - break; -#endif /* #ifndef DISABLE_FLOAT_API */ - case SPEEX_PREPROCESS_SET_AGC_INCREMENT: - st->max_increase_step = exp(0.11513f * (*(spx_int32_t*)ptr)*st->frame_size / st->sampling_rate); - break; - case SPEEX_PREPROCESS_GET_AGC_INCREMENT: - (*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->max_increase_step)*st->sampling_rate/st->frame_size); - break; - case SPEEX_PREPROCESS_SET_AGC_DECREMENT: - st->max_decrease_step = exp(0.11513f * (*(spx_int32_t*)ptr)*st->frame_size / st->sampling_rate); - break; - case SPEEX_PREPROCESS_GET_AGC_DECREMENT: - (*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->max_decrease_step)*st->sampling_rate/st->frame_size); - break; - case SPEEX_PREPROCESS_SET_AGC_MAX_GAIN: - st->max_gain = exp(0.11513f * (*(spx_int32_t*)ptr)); - break; - case SPEEX_PREPROCESS_GET_AGC_MAX_GAIN: - (*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->max_gain)); - break; -#endif - case SPEEX_PREPROCESS_SET_VAD: - speex_warning("The VAD has been replaced by a hack pending a complete rewrite"); - st->vad_enabled = (*(spx_int32_t*)ptr); - break; - case SPEEX_PREPROCESS_GET_VAD: - (*(spx_int32_t*)ptr) = st->vad_enabled; - break; - - case SPEEX_PREPROCESS_SET_DEREVERB: - st->dereverb_enabled = (*(spx_int32_t*)ptr); - for (i=0;i<st->ps_size;i++) - st->reverb_estimate[i]=0; - break; - case SPEEX_PREPROCESS_GET_DEREVERB: - (*(spx_int32_t*)ptr) = st->dereverb_enabled; - break; - - case SPEEX_PREPROCESS_SET_DEREVERB_LEVEL: - /* FIXME: Re-enable when de-reverberation is actually enabled again */ - /*st->reverb_level = (*(float*)ptr);*/ - break; - case SPEEX_PREPROCESS_GET_DEREVERB_LEVEL: - /* FIXME: Re-enable when de-reverberation is actually enabled again */ - /*(*(float*)ptr) = st->reverb_level;*/ - break; - - case SPEEX_PREPROCESS_SET_DEREVERB_DECAY: - /* FIXME: Re-enable when de-reverberation is actually enabled again */ - /*st->reverb_decay = (*(float*)ptr);*/ - break; - case SPEEX_PREPROCESS_GET_DEREVERB_DECAY: - /* FIXME: Re-enable when de-reverberation is actually enabled again */ - /*(*(float*)ptr) = st->reverb_decay;*/ - break; - - case SPEEX_PREPROCESS_SET_PROB_START: - *(spx_int32_t*)ptr = MIN32(100,MAX32(0, *(spx_int32_t*)ptr)); - st->speech_prob_start = DIV32_16(MULT16_16(Q15ONE,*(spx_int32_t*)ptr), 100); - break; - case SPEEX_PREPROCESS_GET_PROB_START: - (*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob_start, 100); - break; - - case SPEEX_PREPROCESS_SET_PROB_CONTINUE: - *(spx_int32_t*)ptr = MIN32(100,MAX32(0, *(spx_int32_t*)ptr)); - st->speech_prob_continue = DIV32_16(MULT16_16(Q15ONE,*(spx_int32_t*)ptr), 100); - break; - case SPEEX_PREPROCESS_GET_PROB_CONTINUE: - (*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob_continue, 100); - break; - - case SPEEX_PREPROCESS_SET_NOISE_SUPPRESS: - st->noise_suppress = -ABS(*(spx_int32_t*)ptr); - break; - case SPEEX_PREPROCESS_GET_NOISE_SUPPRESS: - (*(spx_int32_t*)ptr) = st->noise_suppress; - break; - case SPEEX_PREPROCESS_SET_ECHO_SUPPRESS: - st->echo_suppress = -ABS(*(spx_int32_t*)ptr); - break; - case SPEEX_PREPROCESS_GET_ECHO_SUPPRESS: - (*(spx_int32_t*)ptr) = st->echo_suppress; - break; - case SPEEX_PREPROCESS_SET_ECHO_SUPPRESS_ACTIVE: - st->echo_suppress_active = -ABS(*(spx_int32_t*)ptr); - break; - case SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE: - (*(spx_int32_t*)ptr) = st->echo_suppress_active; - break; - case SPEEX_PREPROCESS_SET_ECHO_STATE: - st->echo_state = (SpeexEchoState*)ptr; - break; - case SPEEX_PREPROCESS_GET_ECHO_STATE: - (*(SpeexEchoState**)ptr) = (SpeexEchoState*)st->echo_state; - break; -#ifndef FIXED_POINT - case SPEEX_PREPROCESS_GET_AGC_LOUDNESS: - (*(spx_int32_t*)ptr) = pow(st->loudness, 1.0/LOUDNESS_EXP); - break; - case SPEEX_PREPROCESS_GET_AGC_GAIN: - (*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->agc_gain)); - break; -#endif - case SPEEX_PREPROCESS_GET_PSD_SIZE: - case SPEEX_PREPROCESS_GET_NOISE_PSD_SIZE: - (*(spx_int32_t*)ptr) = st->ps_size; - break; - case SPEEX_PREPROCESS_GET_PSD: - for(i=0;i<st->ps_size;i++) - ((spx_int32_t *)ptr)[i] = (spx_int32_t) st->ps[i]; - break; - case SPEEX_PREPROCESS_GET_NOISE_PSD: - for(i=0;i<st->ps_size;i++) - ((spx_int32_t *)ptr)[i] = (spx_int32_t) PSHR32(st->noise[i], NOISE_SHIFT); - break; - case SPEEX_PREPROCESS_GET_PROB: - (*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob, 100); - break; -#ifndef FIXED_POINT - case SPEEX_PREPROCESS_SET_AGC_TARGET: - st->agc_level = (*(spx_int32_t*)ptr); - if (st->agc_level<1) - st->agc_level=1; - if (st->agc_level>32768) - st->agc_level=32768; - break; - case SPEEX_PREPROCESS_GET_AGC_TARGET: - (*(spx_int32_t*)ptr) = st->agc_level; - break; -#endif - default: - speex_warning_int("Unknown speex_preprocess_ctl request: ", request); - return -1; - } - return 0; -} - -#ifdef FIXED_DEBUG -long long spx_mips=0; -#endif - diff --git a/drivers/speex/pseudofloat.h b/drivers/speex/pseudofloat.h deleted file mode 100644 index fa841a0101..0000000000 --- a/drivers/speex/pseudofloat.h +++ /dev/null @@ -1,379 +0,0 @@ -/* Copyright (C) 2005 Jean-Marc Valin */ -/** - @file pseudofloat.h - @brief Pseudo-floating point - * This header file provides a lightweight floating point type for - * use on fixed-point platforms when a large dynamic range is - * required. The new type is not compatible with the 32-bit IEEE format, - * it is not even remotely as accurate as 32-bit floats, and is not - * even guaranteed to produce even remotely correct results for code - * other than Speex. It makes all kinds of shortcuts that are acceptable - * for Speex, but may not be acceptable for your application. You're - * quite welcome to reuse this code and improve it, but don't assume - * it works out of the box. Most likely, it doesn't. - */ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 PSEUDOFLOAT_H -#define PSEUDOFLOAT_H - -#include "arch.h" -#include "os_support.h" -#include "math_approx.h" -#include <math.h> - -#ifdef FIXED_POINT - -typedef struct { - spx_int16_t m; - spx_int16_t e; -} spx_float_t; - -static const spx_float_t FLOAT_ZERO = {0,0}; -static const spx_float_t FLOAT_ONE = {16384,-14}; -static const spx_float_t FLOAT_HALF = {16384,-15}; - -#define MIN(a,b) ((a)<(b)?(a):(b)) -static inline spx_float_t PSEUDOFLOAT(spx_int32_t x) -{ - int e=0; - int sign=0; - if (x<0) - { - sign = 1; - x = -x; - } - if (x==0) - { - spx_float_t r = {0,0}; - return r; - } - e = spx_ilog2(ABS32(x))-14; - x = VSHR32(x, e); - if (sign) - { - spx_float_t r; - r.m = -x; - r.e = e; - return r; - } - else - { - spx_float_t r; - r.m = x; - r.e = e; - return r; - } -} - - -static inline spx_float_t FLOAT_ADD(spx_float_t a, spx_float_t b) -{ - spx_float_t r; - if (a.m==0) - return b; - else if (b.m==0) - return a; - if ((a).e > (b).e) - { - r.m = ((a).m>>1) + ((b).m>>MIN(15,(a).e-(b).e+1)); - r.e = (a).e+1; - } - else - { - r.m = ((b).m>>1) + ((a).m>>MIN(15,(b).e-(a).e+1)); - r.e = (b).e+1; - } - if (r.m>0) - { - if (r.m<16384) - { - r.m<<=1; - r.e-=1; - } - } else { - if (r.m>-16384) - { - r.m<<=1; - r.e-=1; - } - } - /*printf ("%f + %f = %f\n", REALFLOAT(a), REALFLOAT(b), REALFLOAT(r));*/ - return r; -} - -static inline spx_float_t FLOAT_SUB(spx_float_t a, spx_float_t b) -{ - spx_float_t r; - if (a.m==0) - return b; - else if (b.m==0) - return a; - if ((a).e > (b).e) - { - r.m = ((a).m>>1) - ((b).m>>MIN(15,(a).e-(b).e+1)); - r.e = (a).e+1; - } - else - { - r.m = ((a).m>>MIN(15,(b).e-(a).e+1)) - ((b).m>>1); - r.e = (b).e+1; - } - if (r.m>0) - { - if (r.m<16384) - { - r.m<<=1; - r.e-=1; - } - } else { - if (r.m>-16384) - { - r.m<<=1; - r.e-=1; - } - } - /*printf ("%f + %f = %f\n", REALFLOAT(a), REALFLOAT(b), REALFLOAT(r));*/ - return r; -} - -static inline int FLOAT_LT(spx_float_t a, spx_float_t b) -{ - if (a.m==0) - return b.m>0; - else if (b.m==0) - return a.m<0; - if ((a).e > (b).e) - return ((a).m>>1) < ((b).m>>MIN(15,(a).e-(b).e+1)); - else - return ((b).m>>1) > ((a).m>>MIN(15,(b).e-(a).e+1)); - -} - -static inline int FLOAT_GT(spx_float_t a, spx_float_t b) -{ - return FLOAT_LT(b,a); -} - -static inline spx_float_t FLOAT_MULT(spx_float_t a, spx_float_t b) -{ - spx_float_t r; - r.m = (spx_int16_t)((spx_int32_t)(a).m*(b).m>>15); - r.e = (a).e+(b).e+15; - if (r.m>0) - { - if (r.m<16384) - { - r.m<<=1; - r.e-=1; - } - } else { - if (r.m>-16384) - { - r.m<<=1; - r.e-=1; - } - } - /*printf ("%f * %f = %f\n", REALFLOAT(a), REALFLOAT(b), REALFLOAT(r));*/ - return r; -} - -static inline spx_float_t FLOAT_AMULT(spx_float_t a, spx_float_t b) -{ - spx_float_t r; - r.m = (spx_int16_t)((spx_int32_t)(a).m*(b).m>>15); - r.e = (a).e+(b).e+15; - return r; -} - - -static inline spx_float_t FLOAT_SHL(spx_float_t a, int b) -{ - spx_float_t r; - r.m = a.m; - r.e = a.e+b; - return r; -} - -static inline spx_int16_t FLOAT_EXTRACT16(spx_float_t a) -{ - if (a.e<0) - return EXTRACT16((EXTEND32(a.m)+(EXTEND32(1)<<(-a.e-1)))>>-a.e); - else - return a.m<<a.e; -} - -static inline spx_int32_t FLOAT_EXTRACT32(spx_float_t a) -{ - if (a.e<0) - return (EXTEND32(a.m)+(EXTEND32(1)<<(-a.e-1)))>>-a.e; - else - return EXTEND32(a.m)<<a.e; -} - -static inline spx_int32_t FLOAT_MUL32(spx_float_t a, spx_word32_t b) -{ - return VSHR32(MULT16_32_Q15(a.m, b),-a.e-15); -} - -static inline spx_float_t FLOAT_MUL32U(spx_word32_t a, spx_word32_t b) -{ - int e1, e2; - spx_float_t r; - if (a==0 || b==0) - { - return FLOAT_ZERO; - } - e1 = spx_ilog2(ABS32(a)); - a = VSHR32(a, e1-14); - e2 = spx_ilog2(ABS32(b)); - b = VSHR32(b, e2-14); - r.m = MULT16_16_Q15(a,b); - r.e = e1+e2-13; - return r; -} - -/* Do NOT attempt to divide by a negative number */ -static inline spx_float_t FLOAT_DIV32_FLOAT(spx_word32_t a, spx_float_t b) -{ - int e=0; - spx_float_t r; - if (a==0) - { - return FLOAT_ZERO; - } - e = spx_ilog2(ABS32(a))-spx_ilog2(b.m-1)-15; - a = VSHR32(a, e); - if (ABS32(a)>=SHL32(EXTEND32(b.m-1),15)) - { - a >>= 1; - e++; - } - r.m = DIV32_16(a,b.m); - r.e = e-b.e; - return r; -} - - -/* Do NOT attempt to divide by a negative number */ -static inline spx_float_t FLOAT_DIV32(spx_word32_t a, spx_word32_t b) -{ - int e0=0,e=0; - spx_float_t r; - if (a==0) - { - return FLOAT_ZERO; - } - if (b>32767) - { - e0 = spx_ilog2(b)-14; - b = VSHR32(b, e0); - e0 = -e0; - } - e = spx_ilog2(ABS32(a))-spx_ilog2(b-1)-15; - a = VSHR32(a, e); - if (ABS32(a)>=SHL32(EXTEND32(b-1),15)) - { - a >>= 1; - e++; - } - e += e0; - r.m = DIV32_16(a,b); - r.e = e; - return r; -} - -/* Do NOT attempt to divide by a negative number */ -static inline spx_float_t FLOAT_DIVU(spx_float_t a, spx_float_t b) -{ - int e=0; - spx_int32_t num; - spx_float_t r; - if (b.m<=0) - { - speex_warning_int("Attempted to divide by", b.m); - return FLOAT_ONE; - } - num = a.m; - a.m = ABS16(a.m); - while (a.m >= b.m) - { - e++; - a.m >>= 1; - } - num = num << (15-e); - r.m = DIV32_16(num,b.m); - r.e = a.e-b.e-15+e; - return r; -} - -static inline spx_float_t FLOAT_SQRT(spx_float_t a) -{ - spx_float_t r; - spx_int32_t m; - m = SHL32(EXTEND32(a.m), 14); - r.e = a.e - 14; - if (r.e & 1) - { - r.e -= 1; - m <<= 1; - } - r.e >>= 1; - r.m = spx_sqrt(m); - return r; -} - -#else - -#define spx_float_t float -#define FLOAT_ZERO 0.f -#define FLOAT_ONE 1.f -#define FLOAT_HALF 0.5f -#define PSEUDOFLOAT(x) (x) -#define FLOAT_MULT(a,b) ((a)*(b)) -#define FLOAT_AMULT(a,b) ((a)*(b)) -#define FLOAT_MUL32(a,b) ((a)*(b)) -#define FLOAT_DIV32(a,b) ((a)/(b)) -#define FLOAT_EXTRACT16(a) (a) -#define FLOAT_EXTRACT32(a) (a) -#define FLOAT_ADD(a,b) ((a)+(b)) -#define FLOAT_SUB(a,b) ((a)-(b)) -#define REALFLOAT(x) (x) -#define FLOAT_DIV32_FLOAT(a,b) ((a)/(b)) -#define FLOAT_MUL32U(a,b) ((a)*(b)) -#define FLOAT_SHL(a,b) (a) -#define FLOAT_LT(a,b) ((a)<(b)) -#define FLOAT_GT(a,b) ((a)>(b)) -#define FLOAT_DIVU(a,b) ((a)/(b)) -#define FLOAT_SQRT(a) (spx_sqrt(a)) - -#endif - -#endif diff --git a/drivers/speex/quant_lsp.c b/drivers/speex/quant_lsp.c deleted file mode 100644 index a09e370ef8..0000000000 --- a/drivers/speex/quant_lsp.c +++ /dev/null @@ -1,385 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: quant_lsp.c - LSP vector quantization - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -#include "config.h" - - -#include "quant_lsp.h" -#include "os_support.h" -#include <math.h> -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#include "arch.h" - -#ifdef BFIN_ASM -#include "quant_lsp_bfin.h" -#endif - -#ifdef FIXED_POINT - -#define LSP_LINEAR(i) (SHL16(i+1,11)) -#define LSP_LINEAR_HIGH(i) (ADD16(MULT16_16_16(i,2560),6144)) -#define LSP_DIV_256(x) (SHL16((spx_word16_t)x, 5)) -#define LSP_DIV_512(x) (SHL16((spx_word16_t)x, 4)) -#define LSP_DIV_1024(x) (SHL16((spx_word16_t)x, 3)) -#define LSP_PI 25736 - -#else - -#define LSP_LINEAR(i) (.25*(i)+.25) -#define LSP_LINEAR_HIGH(i) (.3125*(i)+.75) -#define LSP_SCALE 256. -#define LSP_DIV_256(x) (0.0039062*(x)) -#define LSP_DIV_512(x) (0.0019531*(x)) -#define LSP_DIV_1024(x) (0.00097656*(x)) -#define LSP_PI M_PI - -#endif - -static void compute_quant_weights(spx_lsp_t *qlsp, spx_word16_t *quant_weight, int order) -{ - int i; - spx_word16_t tmp1, tmp2; - for (i=0;i<order;i++) - { - if (i==0) - tmp1 = qlsp[i]; - else - tmp1 = qlsp[i]-qlsp[i-1]; - if (i==order-1) - tmp2 = LSP_PI-qlsp[i]; - else - tmp2 = qlsp[i+1]-qlsp[i]; - if (tmp2<tmp1) - tmp1 = tmp2; -#ifdef FIXED_POINT - quant_weight[i] = DIV32_16(81920,ADD16(300,tmp1)); -#else - quant_weight[i] = 10/(.04+tmp1); -#endif - } - -} - -/* Note: x is modified*/ -#ifndef OVERRIDE_LSP_QUANT -static int lsp_quant(spx_word16_t *x, const signed char *cdbk, int nbVec, int nbDim) -{ - int i,j; - spx_word32_t dist; - spx_word16_t tmp; - spx_word32_t best_dist=VERY_LARGE32; - int best_id=0; - const signed char *ptr=cdbk; - for (i=0;i<nbVec;i++) - { - dist=0; - for (j=0;j<nbDim;j++) - { - tmp=SUB16(x[j],SHL16((spx_word16_t)*ptr++,5)); - dist=MAC16_16(dist,tmp,tmp); - } - if (dist<best_dist) - { - best_dist=dist; - best_id=i; - } - } - - for (j=0;j<nbDim;j++) - x[j] = SUB16(x[j],SHL16((spx_word16_t)cdbk[best_id*nbDim+j],5)); - - return best_id; -} -#endif - -/* Note: x is modified*/ -#ifndef OVERRIDE_LSP_WEIGHT_QUANT -static int lsp_weight_quant(spx_word16_t *x, spx_word16_t *weight, const signed char *cdbk, int nbVec, int nbDim) -{ - int i,j; - spx_word32_t dist; - spx_word16_t tmp; - spx_word32_t best_dist=VERY_LARGE32; - int best_id=0; - const signed char *ptr=cdbk; - for (i=0;i<nbVec;i++) - { - dist=0; - for (j=0;j<nbDim;j++) - { - tmp=SUB16(x[j],SHL16((spx_word16_t)*ptr++,5)); - dist=MAC16_32_Q15(dist,weight[j],MULT16_16(tmp,tmp)); - } - if (dist<best_dist) - { - best_dist=dist; - best_id=i; - } - } - - for (j=0;j<nbDim;j++) - x[j] = SUB16(x[j],SHL16((spx_word16_t)cdbk[best_id*nbDim+j],5)); - return best_id; -} -#endif - -void lsp_quant_nb(spx_lsp_t *lsp, spx_lsp_t *qlsp, int order, SpeexBits *bits) -{ - int i; - int id; - spx_word16_t quant_weight[10]; - - for (i=0;i<order;i++) - qlsp[i]=lsp[i]; - - compute_quant_weights(qlsp, quant_weight, order); - - for (i=0;i<order;i++) - qlsp[i]=SUB16(qlsp[i],LSP_LINEAR(i)); - -#ifndef FIXED_POINT - for (i=0;i<order;i++) - qlsp[i] = LSP_SCALE*qlsp[i]; -#endif - id = lsp_quant(qlsp, cdbk_nb, NB_CDBK_SIZE, order); - speex_bits_pack(bits, id, 6); - - for (i=0;i<order;i++) - qlsp[i]*=2; - - id = lsp_weight_quant(qlsp, quant_weight, cdbk_nb_low1, NB_CDBK_SIZE_LOW1, 5); - speex_bits_pack(bits, id, 6); - - for (i=0;i<5;i++) - qlsp[i]*=2; - - id = lsp_weight_quant(qlsp, quant_weight, cdbk_nb_low2, NB_CDBK_SIZE_LOW2, 5); - speex_bits_pack(bits, id, 6); - - id = lsp_weight_quant(qlsp+5, quant_weight+5, cdbk_nb_high1, NB_CDBK_SIZE_HIGH1, 5); - speex_bits_pack(bits, id, 6); - - for (i=5;i<10;i++) - qlsp[i]*=2; - - id = lsp_weight_quant(qlsp+5, quant_weight+5, cdbk_nb_high2, NB_CDBK_SIZE_HIGH2, 5); - speex_bits_pack(bits, id, 6); - -#ifdef FIXED_POINT - for (i=0;i<order;i++) - qlsp[i]=PSHR16(qlsp[i],2); -#else - for (i=0;i<order;i++) - qlsp[i]=qlsp[i] * .00097656; -#endif - - for (i=0;i<order;i++) - qlsp[i]=lsp[i]-qlsp[i]; -} - -void lsp_unquant_nb(spx_lsp_t *lsp, int order, SpeexBits *bits) -{ - int i, id; - for (i=0;i<order;i++) - lsp[i]=LSP_LINEAR(i); - - - id=speex_bits_unpack_unsigned(bits, 6); - for (i=0;i<10;i++) - lsp[i] = ADD32(lsp[i], LSP_DIV_256(cdbk_nb[id*10+i])); - - id=speex_bits_unpack_unsigned(bits, 6); - for (i=0;i<5;i++) - lsp[i] = ADD16(lsp[i], LSP_DIV_512(cdbk_nb_low1[id*5+i])); - - id=speex_bits_unpack_unsigned(bits, 6); - for (i=0;i<5;i++) - lsp[i] = ADD32(lsp[i], LSP_DIV_1024(cdbk_nb_low2[id*5+i])); - - id=speex_bits_unpack_unsigned(bits, 6); - for (i=0;i<5;i++) - lsp[i+5] = ADD32(lsp[i+5], LSP_DIV_512(cdbk_nb_high1[id*5+i])); - - id=speex_bits_unpack_unsigned(bits, 6); - for (i=0;i<5;i++) - lsp[i+5] = ADD32(lsp[i+5], LSP_DIV_1024(cdbk_nb_high2[id*5+i])); -} - - -void lsp_quant_lbr(spx_lsp_t *lsp, spx_lsp_t *qlsp, int order, SpeexBits *bits) -{ - int i; - int id; - spx_word16_t quant_weight[10]; - - for (i=0;i<order;i++) - qlsp[i]=lsp[i]; - - compute_quant_weights(qlsp, quant_weight, order); - - for (i=0;i<order;i++) - qlsp[i]=SUB16(qlsp[i],LSP_LINEAR(i)); -#ifndef FIXED_POINT - for (i=0;i<order;i++) - qlsp[i]=qlsp[i]*LSP_SCALE; -#endif - id = lsp_quant(qlsp, cdbk_nb, NB_CDBK_SIZE, order); - speex_bits_pack(bits, id, 6); - - for (i=0;i<order;i++) - qlsp[i]*=2; - - id = lsp_weight_quant(qlsp, quant_weight, cdbk_nb_low1, NB_CDBK_SIZE_LOW1, 5); - speex_bits_pack(bits, id, 6); - - id = lsp_weight_quant(qlsp+5, quant_weight+5, cdbk_nb_high1, NB_CDBK_SIZE_HIGH1, 5); - speex_bits_pack(bits, id, 6); - -#ifdef FIXED_POINT - for (i=0;i<order;i++) - qlsp[i] = PSHR16(qlsp[i],1); -#else - for (i=0;i<order;i++) - qlsp[i] = qlsp[i]*0.0019531; -#endif - - for (i=0;i<order;i++) - qlsp[i]=lsp[i]-qlsp[i]; -} - -void lsp_unquant_lbr(spx_lsp_t *lsp, int order, SpeexBits *bits) -{ - int i, id; - for (i=0;i<order;i++) - lsp[i]=LSP_LINEAR(i); - - - id=speex_bits_unpack_unsigned(bits, 6); - for (i=0;i<10;i++) - lsp[i] += LSP_DIV_256(cdbk_nb[id*10+i]); - - id=speex_bits_unpack_unsigned(bits, 6); - for (i=0;i<5;i++) - lsp[i] += LSP_DIV_512(cdbk_nb_low1[id*5+i]); - - id=speex_bits_unpack_unsigned(bits, 6); - for (i=0;i<5;i++) - lsp[i+5] += LSP_DIV_512(cdbk_nb_high1[id*5+i]); - -} - - -#ifdef DISABLE_WIDEBAND -void lsp_quant_high(spx_lsp_t *lsp, spx_lsp_t *qlsp, int order, SpeexBits *bits) -{ - speex_fatal("Wideband and Ultra-wideband are disabled"); -} -void lsp_unquant_high(spx_lsp_t *lsp, int order, SpeexBits *bits) -{ - speex_fatal("Wideband and Ultra-wideband are disabled"); -} -#else -extern const signed char high_lsp_cdbk[]; -extern const signed char high_lsp_cdbk2[]; - - -void lsp_quant_high(spx_lsp_t *lsp, spx_lsp_t *qlsp, int order, SpeexBits *bits) -{ - int i; - int id; - spx_word16_t quant_weight[10]; - - for (i=0;i<order;i++) - qlsp[i]=lsp[i]; - - compute_quant_weights(qlsp, quant_weight, order); - - /* quant_weight[0] = 10/(qlsp[1]-qlsp[0]); - quant_weight[order-1] = 10/(qlsp[order-1]-qlsp[order-2]); - for (i=1;i<order-1;i++) - { - tmp1 = 10/(qlsp[i]-qlsp[i-1]); - tmp2 = 10/(qlsp[i+1]-qlsp[i]); - quant_weight[i] = tmp1 > tmp2 ? tmp1 : tmp2; - }*/ - - for (i=0;i<order;i++) - qlsp[i]=SUB16(qlsp[i],LSP_LINEAR_HIGH(i)); -#ifndef FIXED_POINT - for (i=0;i<order;i++) - qlsp[i] = qlsp[i]*LSP_SCALE; -#endif - id = lsp_quant(qlsp, high_lsp_cdbk, 64, order); - speex_bits_pack(bits, id, 6); - - for (i=0;i<order;i++) - qlsp[i]*=2; - - id = lsp_weight_quant(qlsp, quant_weight, high_lsp_cdbk2, 64, order); - speex_bits_pack(bits, id, 6); - -#ifdef FIXED_POINT - for (i=0;i<order;i++) - qlsp[i] = PSHR16(qlsp[i],1); -#else - for (i=0;i<order;i++) - qlsp[i] = qlsp[i]*0.0019531; -#endif - - for (i=0;i<order;i++) - qlsp[i]=lsp[i]-qlsp[i]; -} - -void lsp_unquant_high(spx_lsp_t *lsp, int order, SpeexBits *bits) -{ - - int i, id; - for (i=0;i<order;i++) - lsp[i]=LSP_LINEAR_HIGH(i); - - - id=speex_bits_unpack_unsigned(bits, 6); - for (i=0;i<order;i++) - lsp[i] += LSP_DIV_256(high_lsp_cdbk[id*order+i]); - - - id=speex_bits_unpack_unsigned(bits, 6); - for (i=0;i<order;i++) - lsp[i] += LSP_DIV_512(high_lsp_cdbk2[id*order+i]); -} - -#endif - diff --git a/drivers/speex/quant_lsp.h b/drivers/speex/quant_lsp.h deleted file mode 100644 index 3bf4d4021c..0000000000 --- a/drivers/speex/quant_lsp.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @file quant_lsp.h - @brief LSP vector quantization -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 QUANT_LSP_H -#define QUANT_LSP_H - -#include <speex/speex_bits.h> -#include "arch.h" - -#define MAX_LSP_SIZE 20 - -#define NB_CDBK_SIZE 64 -#define NB_CDBK_SIZE_LOW1 64 -#define NB_CDBK_SIZE_LOW2 64 -#define NB_CDBK_SIZE_HIGH1 64 -#define NB_CDBK_SIZE_HIGH2 64 - -/*Narrowband codebooks*/ -extern const signed char cdbk_nb[]; -extern const signed char cdbk_nb_low1[]; -extern const signed char cdbk_nb_low2[]; -extern const signed char cdbk_nb_high1[]; -extern const signed char cdbk_nb_high2[]; - -/* Quantizes narrowband LSPs with 30 bits */ -void lsp_quant_nb(spx_lsp_t *lsp, spx_lsp_t *qlsp, int order, SpeexBits *bits); - -/* Decodes quantized narrowband LSPs */ -void lsp_unquant_nb(spx_lsp_t *lsp, int order, SpeexBits *bits); - -/* Quantizes low bit-rate narrowband LSPs with 18 bits */ -void lsp_quant_lbr(spx_lsp_t *lsp, spx_lsp_t *qlsp, int order, SpeexBits *bits); - -/* Decodes quantized low bit-rate narrowband LSPs */ -void lsp_unquant_lbr(spx_lsp_t *lsp, int order, SpeexBits *bits); - -/* Quantizes high-band LSPs with 12 bits */ -void lsp_quant_high(spx_lsp_t *lsp, spx_lsp_t *qlsp, int order, SpeexBits *bits); - -/* Decodes high-band LSPs */ -void lsp_unquant_high(spx_lsp_t *lsp, int order, SpeexBits *bits); - -#endif diff --git a/drivers/speex/quant_lsp_bfin.h b/drivers/speex/quant_lsp_bfin.h deleted file mode 100644 index 087b466b75..0000000000 --- a/drivers/speex/quant_lsp_bfin.h +++ /dev/null @@ -1,165 +0,0 @@ -/* Copyright (C) 2006 David Rowe */ -/** - @file quant_lsp_bfin.h - @author David Rowe - @brief Various compatibility routines for Speex (Blackfin version) -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#define OVERRIDE_LSP_QUANT -#ifdef OVERRIDE_LSP_QUANT - -/* - Note http://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html - well tell you all the magic resgister constraints used below - for gcc in-line asm. -*/ - -static int lsp_quant( - spx_word16_t *x, - const signed char *cdbk, - int nbVec, - int nbDim -) -{ - int j; - spx_word32_t best_dist=1<<30; - int best_id=0; - - __asm__ __volatile__ - ( -" %0 = 1 (X);\n\t" /* %0: best_dist */ -" %0 <<= 30;\n\t" -" %1 = 0 (X);\n\t" /* %1: best_i */ -" P2 = %3\n\t" /* P2: ptr to cdbk */ -" R5 = 0;\n\t" /* R5: best cb entry */ - -" R0 = %5;\n\t" /* set up circ addr */ -" R0 <<= 1;\n\t" -" L0 = R0;\n\t" -" I0 = %2;\n\t" /* %2: &x[0] */ -" B0 = %2;\n\t" - -" R2.L = W [I0++];\n\t" -" LSETUP (1f, 2f) LC0 = %4;\n\t" -"1: R3 = 0;\n\t" /* R3: dist */ -" LSETUP (3f, 4f) LC1 = %5;\n\t" -"3: R1 = B [P2++] (X);\n\t" -" R1 <<= 5;\n\t" -" R0.L = R2.L - R1.L || R2.L = W [I0++];\n\t" -" R0 = R0.L*R0.L;\n\t" -"4: R3 = R3 + R0;\n\t" - -" cc =R3<%0;\n\t" -" if cc %0=R3;\n\t" -" if cc %1=R5;\n\t" -"2: R5 += 1;\n\t" -" L0 = 0;\n\t" - : "=&d" (best_dist), "=&d" (best_id) - : "a" (x), "b" (cdbk), "a" (nbVec), "a" (nbDim) - : "I0", "P2", "R0", "R1", "R2", "R3", "R5", "L0", "B0", "A0" - ); - - for (j=0;j<nbDim;j++) { - x[j] = SUB16(x[j],SHL16((spx_word16_t)cdbk[best_id*nbDim+j],5)); - } - return best_id; -} -#endif - -#define OVERRIDE_LSP_WEIGHT_QUANT -#ifdef OVERRIDE_LSP_WEIGHT_QUANT - -/* - Note http://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html - well tell you all the magic resgister constraints used below - for gcc in-line asm. -*/ - -static int lsp_weight_quant( - spx_word16_t *x, - spx_word16_t *weight, - const signed char *cdbk, - int nbVec, - int nbDim -) -{ - int j; - spx_word32_t best_dist=1<<30; - int best_id=0; - - __asm__ __volatile__ - ( -" %0 = 1 (X);\n\t" /* %0: best_dist */ -" %0 <<= 30;\n\t" -" %1 = 0 (X);\n\t" /* %1: best_i */ -" P2 = %4\n\t" /* P2: ptr to cdbk */ -" R5 = 0;\n\t" /* R5: best cb entry */ - -" R0 = %6;\n\t" /* set up circ addr */ -" R0 <<= 1;\n\t" -" L0 = R0;\n\t" -" L1 = R0;\n\t" -" I0 = %2;\n\t" /* %2: &x[0] */ -" I1 = %3;\n\t" /* %3: &weight[0] */ -" B0 = %2;\n\t" -" B1 = %3;\n\t" - -" LSETUP (1f, 2f) LC0 = %5;\n\t" -"1: R3 = 0 (X);\n\t" /* R3: dist */ -" LSETUP (3f, 4f) LC1 = %6;\n\t" -"3: R0.L = W [I0++] || R2.L = W [I1++];\n\t" -" R1 = B [P2++] (X);\n\t" -" R1 <<= 5;\n\t" -" R0.L = R0.L - R1.L;\n\t" -" R0 = R0.L*R0.L;\n\t" -" A1 = R2.L*R0.L (M,IS);\n\t" -" A1 = A1 >>> 16;\n\t" -" R1 = (A1 += R2.L*R0.H) (IS);\n\t" -"4: R3 = R3 + R1;\n\t" - -" cc =R3<%0;\n\t" -" if cc %0=R3;\n\t" -" if cc %1=R5;\n\t" -"2: R5 += 1;\n\t" -" L0 = 0;\n\t" -" L1 = 0;\n\t" - : "=&d" (best_dist), "=&d" (best_id) - : "a" (x), "a" (weight), "b" (cdbk), "a" (nbVec), "a" (nbDim) - : "I0", "I1", "P2", "R0", "R1", "R2", "R3", "R5", "A1", - "L0", "L1", "B0", "B1" - ); - - for (j=0;j<nbDim;j++) { - x[j] = SUB16(x[j],SHL16((spx_word16_t)cdbk[best_id*nbDim+j],5)); - } - return best_id; -} -#endif diff --git a/drivers/speex/resample.c b/drivers/speex/resample.c deleted file mode 100644 index be02e5ef42..0000000000 --- a/drivers/speex/resample.c +++ /dev/null @@ -1,1131 +0,0 @@ -/* Copyright (C) 2007-2008 Jean-Marc Valin - Copyright (C) 2008 Thorvald Natvig - - File: resample.c - Arbitrary resampling code - - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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. -*/ - -/* - The design goals of this code are: - - Very fast algorithm - - SIMD-friendly algorithm - - Low memory requirement - - Good *perceptual* quality (and not best SNR) - - Warning: This resampler is relatively new. Although I think I got rid of - all the major bugs and I don't expect the API to change anymore, there - may be something I've missed. So use with caution. - - This algorithm is based on this original resampling algorithm: - Smith, Julius O. Digital Audio Resampling Home Page - Center for Computer Research in Music and Acoustics (CCRMA), - Stanford University, 2007. - Web published at http://www-ccrma.stanford.edu/~jos/resample/. - - There is one main difference, though. This resampler uses cubic - interpolation instead of linear interpolation in the above paper. This - makes the table much smaller and makes it possible to compute that table - on a per-stream basis. In turn, being able to tweak the table for each - stream makes it possible to both reduce complexity on simple ratios - (e.g. 2/3), and get rid of the rounding operations in the inner loop. - The latter both reduces CPU time and makes the algorithm more SIMD-friendly. -*/ - - -#include "config.h" - - -#ifdef OUTSIDE_SPEEX -#include <stdlib.h> -static void *speex_alloc (int size) {return calloc(size,1);} -static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);} -static void speex_free (void *ptr) {free(ptr);} -#include "speex_resampler.h" -#include "arch.h" -#else /* OUTSIDE_SPEEX */ - -#include "speex/speex_resampler.h" -#include "arch.h" -#include "os_support.h" -#endif /* OUTSIDE_SPEEX */ - -#include "stack_alloc.h" -#include <math.h> - -#ifndef M_PI -#define M_PI 3.14159263 -#endif - -#ifdef FIXED_POINT -#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) -#else -#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) -#endif - -#define IMAX(a,b) ((a) > (b) ? (a) : (b)) -#define IMIN(a,b) ((a) < (b) ? (a) : (b)) - -#ifndef NULL -#define NULL 0 -#endif - -#ifdef _USE_SSE -#include "resample_sse.h" -#endif - -/* Numer of elements to allocate on the stack */ -#ifdef VAR_ARRAYS -#define FIXED_STACK_ALLOC 8192 -#else -#define FIXED_STACK_ALLOC 1024 -#endif - -typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *); - -struct SpeexResamplerState_ { - spx_uint32_t in_rate; - spx_uint32_t out_rate; - spx_uint32_t num_rate; - spx_uint32_t den_rate; - - int quality; - spx_uint32_t nb_channels; - spx_uint32_t filt_len; - spx_uint32_t mem_alloc_size; - spx_uint32_t buffer_size; - int int_advance; - int frac_advance; - float cutoff; - spx_uint32_t oversample; - int initialised; - int started; - - /* These are per-channel */ - spx_int32_t *last_sample; - spx_uint32_t *samp_frac_num; - spx_uint32_t *magic_samples; - - spx_word16_t *mem; - spx_word16_t *sinc_table; - spx_uint32_t sinc_table_length; - resampler_basic_func resampler_ptr; - - int in_stride; - int out_stride; -} ; - -static double kaiser12_table[68] = { - 0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076, - 0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014, - 0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601, - 0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014, - 0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490, - 0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546, - 0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178, - 0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947, - 0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058, - 0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438, - 0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734, - 0.00001000, 0.00000000}; -/* -static double kaiser12_table[36] = { - 0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741, - 0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762, - 0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274, - 0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466, - 0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291, - 0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000}; -*/ -static double kaiser10_table[36] = { - 0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446, - 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347, - 0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962, - 0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451, - 0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739, - 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000}; - -static double kaiser8_table[36] = { - 0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200, - 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126, - 0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272, - 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758, - 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490, - 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000}; - -static double kaiser6_table[36] = { - 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003, - 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565, - 0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561, - 0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058, - 0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600, - 0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000}; - -struct FuncDef { - double *table; - int oversample; -}; - -static struct FuncDef _KAISER12 = {kaiser12_table, 64}; -#define KAISER12 (&_KAISER12) -/*static struct FuncDef _KAISER12 = {kaiser12_table, 32}; -#define KAISER12 (&_KAISER12)*/ -static struct FuncDef _KAISER10 = {kaiser10_table, 32}; -#define KAISER10 (&_KAISER10) -static struct FuncDef _KAISER8 = {kaiser8_table, 32}; -#define KAISER8 (&_KAISER8) -static struct FuncDef _KAISER6 = {kaiser6_table, 32}; -#define KAISER6 (&_KAISER6) - -struct QualityMapping { - int base_length; - int oversample; - float downsample_bandwidth; - float upsample_bandwidth; - struct FuncDef *window_func; -}; - - -/* This table maps conversion quality to internal parameters. There are two - reasons that explain why the up-sampling bandwidth is larger than the - down-sampling bandwidth: - 1) When up-sampling, we can assume that the spectrum is already attenuated - close to the Nyquist rate (from an A/D or a previous resampling filter) - 2) Any aliasing that occurs very close to the Nyquist rate will be masked - by the sinusoids/noise just below the Nyquist rate (guaranteed only for - up-sampling). -*/ -static const struct QualityMapping quality_map[11] = { - { 8, 4, 0.830f, 0.860f, KAISER6 }, /* Q0 */ - { 16, 4, 0.850f, 0.880f, KAISER6 }, /* Q1 */ - { 32, 4, 0.882f, 0.910f, KAISER6 }, /* Q2 */ /* 82.3% cutoff ( ~60 dB stop) 6 */ - { 48, 8, 0.895f, 0.917f, KAISER8 }, /* Q3 */ /* 84.9% cutoff ( ~80 dB stop) 8 */ - { 64, 8, 0.921f, 0.940f, KAISER8 }, /* Q4 */ /* 88.7% cutoff ( ~80 dB stop) 8 */ - { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */ - { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */ - {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */ /* 93.1% cutoff (~100 dB stop) 10 */ - {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */ /* 94.5% cutoff (~100 dB stop) 10 */ - {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */ - {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */ -}; -/*8,24,40,56,80,104,128,160,200,256,320*/ -static double compute_func(float x, struct FuncDef *func) -{ - float y, frac; - double interp[4]; - int ind; - y = x*func->oversample; - ind = (int)floor(y); - frac = (y-ind); - /* CSE with handle the repeated powers */ - interp[3] = -0.1666666667*frac + 0.1666666667*(frac*frac*frac); - interp[2] = frac + 0.5*(frac*frac) - 0.5*(frac*frac*frac); - /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/ - interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac); - /* Just to make sure we don't have rounding problems */ - interp[1] = 1.f-interp[3]-interp[2]-interp[0]; - - /*sum = frac*accum[1] + (1-frac)*accum[2];*/ - return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3]; -} - -#if 0 -#include <stdio.h> -int main(int argc, char **argv) -{ - int i; - for (i=0;i<256;i++) - { - printf ("%f\n", compute_func(i/256., KAISER12)); - } - return 0; -} -#endif - -#ifdef FIXED_POINT -/* The slow way of computing a sinc for the table. Should improve that some day */ -static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func) -{ - /*fprintf (stderr, "%f ", x);*/ - float xx = x * cutoff; - if (fabs(x)<1e-6f) - return WORD2INT(32768.*cutoff); - else if (fabs(x) > .5f*N) - return 0; - /*FIXME: Can it really be any slower than this? */ - return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func)); -} -#else -/* The slow way of computing a sinc for the table. Should improve that some day */ -static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func) -{ - /*fprintf (stderr, "%f ", x);*/ - float xx = x * cutoff; - if (fabs(x)<1e-6) - return cutoff; - else if (fabs(x) > .5*N) - return 0; - /*FIXME: Can it really be any slower than this? */ - return cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func); -} -#endif - -#ifdef FIXED_POINT -static void cubic_coef(spx_word16_t x, spx_word16_t interp[4]) -{ - /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation - but I know it's MMSE-optimal on a sinc */ - spx_word16_t x2, x3; - x2 = MULT16_16_P15(x, x); - x3 = MULT16_16_P15(x, x2); - interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15); - interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1)); - interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15); - /* Just to make sure we don't have rounding problems */ - interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3]; - if (interp[2]<32767) - interp[2]+=1; -} -#else -static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4]) -{ - /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation - but I know it's MMSE-optimal on a sinc */ - interp[0] = -0.16667f*frac + 0.16667f*frac*frac*frac; - interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac; - /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/ - interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac; - /* Just to make sure we don't have rounding problems */ - interp[2] = 1.-interp[0]-interp[1]-interp[3]; -} -#endif - -static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) -{ - const int N = st->filt_len; - int out_sample = 0; - int last_sample = st->last_sample[channel_index]; - spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; - const spx_word16_t *sinc_table = st->sinc_table; - const int out_stride = st->out_stride; - const int int_advance = st->int_advance; - const int frac_advance = st->frac_advance; - const spx_uint32_t den_rate = st->den_rate; - spx_word32_t sum; - int j; - - while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) - { - const spx_word16_t *sinc = & sinc_table[samp_frac_num*N]; - const spx_word16_t *iptr = & in[last_sample]; - -#ifndef OVERRIDE_INNER_PRODUCT_SINGLE - float accum[4] = {0,0,0,0}; - - for(j=0;j<N;j+=4) { - accum[0] += sinc[j]*iptr[j]; - accum[1] += sinc[j+1]*iptr[j+1]; - accum[2] += sinc[j+2]*iptr[j+2]; - accum[3] += sinc[j+3]*iptr[j+3]; - } - sum = accum[0] + accum[1] + accum[2] + accum[3]; -#else - sum = inner_product_single(sinc, iptr, N); -#endif - - out[out_stride * out_sample++] = PSHR32(sum, 15); - last_sample += int_advance; - samp_frac_num += frac_advance; - if (samp_frac_num >= den_rate) - { - samp_frac_num -= den_rate; - last_sample++; - } - } - - st->last_sample[channel_index] = last_sample; - st->samp_frac_num[channel_index] = samp_frac_num; - return out_sample; -} - -#ifdef FIXED_POINT -#else -/* This is the same as the previous function, except with a double-precision accumulator */ -static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) -{ - const int N = st->filt_len; - int out_sample = 0; - int last_sample = st->last_sample[channel_index]; - spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; - const spx_word16_t *sinc_table = st->sinc_table; - const int out_stride = st->out_stride; - const int int_advance = st->int_advance; - const int frac_advance = st->frac_advance; - const spx_uint32_t den_rate = st->den_rate; - double sum; - int j; - - while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) - { - const spx_word16_t *sinc = & sinc_table[samp_frac_num*N]; - const spx_word16_t *iptr = & in[last_sample]; - -#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE - double accum[4] = {0,0,0,0}; - - for(j=0;j<N;j+=4) { - accum[0] += sinc[j]*iptr[j]; - accum[1] += sinc[j+1]*iptr[j+1]; - accum[2] += sinc[j+2]*iptr[j+2]; - accum[3] += sinc[j+3]*iptr[j+3]; - } - sum = accum[0] + accum[1] + accum[2] + accum[3]; -#else - sum = inner_product_double(sinc, iptr, N); -#endif - - out[out_stride * out_sample++] = PSHR32(sum, 15); - last_sample += int_advance; - samp_frac_num += frac_advance; - if (samp_frac_num >= den_rate) - { - samp_frac_num -= den_rate; - last_sample++; - } - } - - st->last_sample[channel_index] = last_sample; - st->samp_frac_num[channel_index] = samp_frac_num; - return out_sample; -} -#endif - -static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) -{ - const int N = st->filt_len; - int out_sample = 0; - int last_sample = st->last_sample[channel_index]; - spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; - const int out_stride = st->out_stride; - const int int_advance = st->int_advance; - const int frac_advance = st->frac_advance; - const spx_uint32_t den_rate = st->den_rate; - int j; - spx_word32_t sum; - - while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) - { - const spx_word16_t *iptr = & in[last_sample]; - - const int offset = samp_frac_num*st->oversample/st->den_rate; -#ifdef FIXED_POINT - const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); -#else - const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; -#endif - spx_word16_t interp[4]; - - -#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE - spx_word32_t accum[4] = {0,0,0,0}; - - for(j=0;j<N;j++) { - const spx_word16_t curr_in=iptr[j]; - accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); - accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); - accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); - accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); - } - - cubic_coef(frac, interp); - sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]); -#else - cubic_coef(frac, interp); - sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); -#endif - - out[out_stride * out_sample++] = PSHR32(sum,15); - last_sample += int_advance; - samp_frac_num += frac_advance; - if (samp_frac_num >= den_rate) - { - samp_frac_num -= den_rate; - last_sample++; - } - } - - st->last_sample[channel_index] = last_sample; - st->samp_frac_num[channel_index] = samp_frac_num; - return out_sample; -} - -#ifdef FIXED_POINT -#else -/* This is the same as the previous function, except with a double-precision accumulator */ -static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) -{ - const int N = st->filt_len; - int out_sample = 0; - int last_sample = st->last_sample[channel_index]; - spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; - const int out_stride = st->out_stride; - const int int_advance = st->int_advance; - const int frac_advance = st->frac_advance; - const spx_uint32_t den_rate = st->den_rate; - int j; - spx_word32_t sum; - - while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) - { - const spx_word16_t *iptr = & in[last_sample]; - - const int offset = samp_frac_num*st->oversample/st->den_rate; -#ifdef FIXED_POINT - const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); -#else - const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; -#endif - spx_word16_t interp[4]; - - -#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE - double accum[4] = {0,0,0,0}; - - for(j=0;j<N;j++) { - const double curr_in=iptr[j]; - accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); - accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); - accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); - accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); - } - - cubic_coef(frac, interp); - sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]); -#else - cubic_coef(frac, interp); - sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); -#endif - - out[out_stride * out_sample++] = PSHR32(sum,15); - last_sample += int_advance; - samp_frac_num += frac_advance; - if (samp_frac_num >= den_rate) - { - samp_frac_num -= den_rate; - last_sample++; - } - } - - st->last_sample[channel_index] = last_sample; - st->samp_frac_num[channel_index] = samp_frac_num; - return out_sample; -} -#endif - -static void update_filter(SpeexResamplerState *st) -{ - spx_uint32_t old_length; - - old_length = st->filt_len; - st->oversample = quality_map[st->quality].oversample; - st->filt_len = quality_map[st->quality].base_length; - - if (st->num_rate > st->den_rate) - { - /* down-sampling */ - st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate; - /* FIXME: divide the numerator and denominator by a certain amount if they're too large */ - st->filt_len = st->filt_len*st->num_rate / st->den_rate; - /* Round down to make sure we have a multiple of 4 */ - st->filt_len &= (~0x3); - if (2*st->den_rate < st->num_rate) - st->oversample >>= 1; - if (4*st->den_rate < st->num_rate) - st->oversample >>= 1; - if (8*st->den_rate < st->num_rate) - st->oversample >>= 1; - if (16*st->den_rate < st->num_rate) - st->oversample >>= 1; - if (st->oversample < 1) - st->oversample = 1; - } else { - /* up-sampling */ - st->cutoff = quality_map[st->quality].upsample_bandwidth; - } - - /* Choose the resampling type that requires the least amount of memory */ - if (st->den_rate <= st->oversample) - { - spx_uint32_t i; - if (!st->sinc_table) - st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t)); - else if (st->sinc_table_length < st->filt_len*st->den_rate) - { - st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t)); - st->sinc_table_length = st->filt_len*st->den_rate; - } - for (i=0;i<st->den_rate;i++) - { - spx_int32_t j; - for (j=0;j<st->filt_len;j++) - { - st->sinc_table[i*st->filt_len+j] = sinc(st->cutoff,((j-(spx_int32_t)st->filt_len/2+1)-((float)i)/st->den_rate), st->filt_len, quality_map[st->quality].window_func); - } - } -#ifdef FIXED_POINT - st->resampler_ptr = resampler_basic_direct_single; -#else - if (st->quality>8) - st->resampler_ptr = resampler_basic_direct_double; - else - st->resampler_ptr = resampler_basic_direct_single; -#endif - /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/ - } else { - spx_int32_t i; - if (!st->sinc_table) - st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); - else if (st->sinc_table_length < st->filt_len*st->oversample+8) - { - st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); - st->sinc_table_length = st->filt_len*st->oversample+8; - } - for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++) - st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len, quality_map[st->quality].window_func); -#ifdef FIXED_POINT - st->resampler_ptr = resampler_basic_interpolate_single; -#else - if (st->quality>8) - st->resampler_ptr = resampler_basic_interpolate_double; - else - st->resampler_ptr = resampler_basic_interpolate_single; -#endif - /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/ - } - st->int_advance = st->num_rate/st->den_rate; - st->frac_advance = st->num_rate%st->den_rate; - - - /* Here's the place where we update the filter memory to take into account - the change in filter length. It's probably the messiest part of the code - due to handling of lots of corner cases. */ - if (!st->mem) - { - spx_uint32_t i; - st->mem_alloc_size = st->filt_len-1 + st->buffer_size; - st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); - for (i=0;i<st->nb_channels*st->mem_alloc_size;i++) - st->mem[i] = 0; - /*speex_warning("init filter");*/ - } else if (!st->started) - { - spx_uint32_t i; - st->mem_alloc_size = st->filt_len-1 + st->buffer_size; - st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); - for (i=0;i<st->nb_channels*st->mem_alloc_size;i++) - st->mem[i] = 0; - /*speex_warning("reinit filter");*/ - } else if (st->filt_len > old_length) - { - spx_int32_t i; - /* Increase the filter length */ - /*speex_warning("increase filter size");*/ - int old_alloc_size = st->mem_alloc_size; - if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size) - { - st->mem_alloc_size = st->filt_len-1 + st->buffer_size; - st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); - } - for (i=st->nb_channels-1;i>=0;i--) - { - spx_int32_t j; - spx_uint32_t olen = old_length; - /*if (st->magic_samples[i])*/ - { - /* Try and remove the magic samples as if nothing had happened */ - - /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */ - olen = old_length + 2*st->magic_samples[i]; - for (j=old_length-2+st->magic_samples[i];j>=0;j--) - st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j]; - for (j=0;j<st->magic_samples[i];j++) - st->mem[i*st->mem_alloc_size+j] = 0; - st->magic_samples[i] = 0; - } - if (st->filt_len > olen) - { - /* If the new filter length is still bigger than the "augmented" length */ - /* Copy data going backward */ - for (j=0;j<olen-1;j++) - st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)]; - /* Then put zeros for lack of anything better */ - for (;j<st->filt_len-1;j++) - st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0; - /* Adjust last_sample */ - st->last_sample[i] += (st->filt_len - olen)/2; - } else { - /* Put back some of the magic! */ - st->magic_samples[i] = (olen - st->filt_len)/2; - for (j=0;j<st->filt_len-1+st->magic_samples[i];j++) - st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; - } - } - } else if (st->filt_len < old_length) - { - spx_uint32_t i; - /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic" - samples so they can be used directly as input the next time(s) */ - for (i=0;i<st->nb_channels;i++) - { - spx_uint32_t j; - spx_uint32_t old_magic = st->magic_samples[i]; - st->magic_samples[i] = (old_length - st->filt_len)/2; - /* We must copy some of the memory that's no longer used */ - /* Copy data going backward */ - for (j=0;j<st->filt_len-1+st->magic_samples[i]+old_magic;j++) - st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; - st->magic_samples[i] += old_magic; - } - } - -} - -EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) -{ - return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err); -} - -EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) -{ - spx_uint32_t i; - SpeexResamplerState *st; - if (quality > 10 || quality < 0) - { - if (err) - *err = RESAMPLER_ERR_INVALID_ARG; - return NULL; - } - st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState)); - st->initialised = 0; - st->started = 0; - st->in_rate = 0; - st->out_rate = 0; - st->num_rate = 0; - st->den_rate = 0; - st->quality = -1; - st->sinc_table_length = 0; - st->mem_alloc_size = 0; - st->filt_len = 0; - st->mem = 0; - st->resampler_ptr = 0; - - st->cutoff = 1.f; - st->nb_channels = nb_channels; - st->in_stride = 1; - st->out_stride = 1; - -#ifdef FIXED_POINT - st->buffer_size = 160; -#else - st->buffer_size = 160; -#endif - - /* Per channel data */ - st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int)); - st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); - st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); - for (i=0;i<nb_channels;i++) - { - st->last_sample[i] = 0; - st->magic_samples[i] = 0; - st->samp_frac_num[i] = 0; - } - - speex_resampler_set_quality(st, quality); - speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate); - - - update_filter(st); - - st->initialised = 1; - if (err) - *err = RESAMPLER_ERR_SUCCESS; - - return st; -} - -EXPORT void speex_resampler_destroy(SpeexResamplerState *st) -{ - speex_free(st->mem); - speex_free(st->sinc_table); - speex_free(st->last_sample); - speex_free(st->magic_samples); - speex_free(st->samp_frac_num); - speex_free(st); -} - -static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) -{ - int j=0; - const int N = st->filt_len; - int out_sample = 0; - spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; - spx_uint32_t ilen; - - st->started = 1; - - /* Call the right resampler through the function ptr */ - out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len); - - if (st->last_sample[channel_index] < (spx_int32_t)*in_len) - *in_len = st->last_sample[channel_index]; - *out_len = out_sample; - st->last_sample[channel_index] -= *in_len; - - ilen = *in_len; - - for(j=0;j<N-1;++j) - mem[j] = mem[j+ilen]; - - return RESAMPLER_ERR_SUCCESS; -} - -static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_index, spx_word16_t **out, spx_uint32_t out_len) { - spx_uint32_t tmp_in_len = st->magic_samples[channel_index]; - spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; - const int N = st->filt_len; - - speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len); - - st->magic_samples[channel_index] -= tmp_in_len; - - /* If we couldn't process all "magic" input samples, save the rest for next time */ - if (st->magic_samples[channel_index]) - { - spx_uint32_t i; - for (i=0;i<st->magic_samples[channel_index];i++) - mem[N-1+i]=mem[N-1+i+tmp_in_len]; - } - *out += out_len*st->out_stride; - return out_len; -} - -#ifdef FIXED_POINT -EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) -#else -EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) -#endif -{ - int j; - spx_uint32_t ilen = *in_len; - spx_uint32_t olen = *out_len; - spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; - const int filt_offs = st->filt_len - 1; - const spx_uint32_t xlen = st->mem_alloc_size - filt_offs; - const int istride = st->in_stride; - - if (st->magic_samples[channel_index]) - olen -= speex_resampler_magic(st, channel_index, &out, olen); - if (! st->magic_samples[channel_index]) { - while (ilen && olen) { - spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; - spx_uint32_t ochunk = olen; - - if (in) { - for(j=0;j<ichunk;++j) - x[j+filt_offs]=in[j*istride]; - } else { - for(j=0;j<ichunk;++j) - x[j+filt_offs]=0; - } - speex_resampler_process_native(st, channel_index, &ichunk, out, &ochunk); - ilen -= ichunk; - olen -= ochunk; - out += ochunk * st->out_stride; - if (in) - in += ichunk * istride; - } - } - *in_len -= ilen; - *out_len -= olen; - return RESAMPLER_ERR_SUCCESS; -} - -#ifdef FIXED_POINT -EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) -#else -EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) -#endif -{ - int j; - const int istride_save = st->in_stride; - const int ostride_save = st->out_stride; - spx_uint32_t ilen = *in_len; - spx_uint32_t olen = *out_len; - spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; - const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1); -#ifdef VAR_ARRAYS - const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC; - VARDECL(spx_word16_t *ystack); - ALLOC(ystack, ylen, spx_word16_t); -#else - const unsigned int ylen = FIXED_STACK_ALLOC; - spx_word16_t ystack[FIXED_STACK_ALLOC]; -#endif - - st->out_stride = 1; - - while (ilen && olen) { - spx_word16_t *y = ystack; - spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; - spx_uint32_t ochunk = (olen > ylen) ? ylen : olen; - spx_uint32_t omagic = 0; - - if (st->magic_samples[channel_index]) { - omagic = speex_resampler_magic(st, channel_index, &y, ochunk); - ochunk -= omagic; - olen -= omagic; - } - if (! st->magic_samples[channel_index]) { - if (in) { - for(j=0;j<ichunk;++j) -#ifdef FIXED_POINT - x[j+st->filt_len-1]=WORD2INT(in[j*istride_save]); -#else - x[j+st->filt_len-1]=in[j*istride_save]; -#endif - } else { - for(j=0;j<ichunk;++j) - x[j+st->filt_len-1]=0; - } - - speex_resampler_process_native(st, channel_index, &ichunk, y, &ochunk); - } else { - ichunk = 0; - ochunk = 0; - } - - for (j=0;j<ochunk+omagic;++j) -#ifdef FIXED_POINT - out[j*ostride_save] = ystack[j]; -#else - out[j*ostride_save] = WORD2INT(ystack[j]); -#endif - - ilen -= ichunk; - olen -= ochunk; - out += (ochunk+omagic) * ostride_save; - if (in) - in += ichunk * istride_save; - } - st->out_stride = ostride_save; - *in_len -= ilen; - *out_len -= olen; - - return RESAMPLER_ERR_SUCCESS; -} - -EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) -{ - spx_uint32_t i; - int istride_save, ostride_save; - spx_uint32_t bak_len = *out_len; - istride_save = st->in_stride; - ostride_save = st->out_stride; - st->in_stride = st->out_stride = st->nb_channels; - for (i=0;i<st->nb_channels;i++) - { - *out_len = bak_len; - if (in != NULL) - speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len); - else - speex_resampler_process_float(st, i, NULL, in_len, out+i, out_len); - } - st->in_stride = istride_save; - st->out_stride = ostride_save; - return RESAMPLER_ERR_SUCCESS; -} - -EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) -{ - spx_uint32_t i; - int istride_save, ostride_save; - spx_uint32_t bak_len = *out_len; - istride_save = st->in_stride; - ostride_save = st->out_stride; - st->in_stride = st->out_stride = st->nb_channels; - for (i=0;i<st->nb_channels;i++) - { - *out_len = bak_len; - if (in != NULL) - speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len); - else - speex_resampler_process_int(st, i, NULL, in_len, out+i, out_len); - } - st->in_stride = istride_save; - st->out_stride = ostride_save; - return RESAMPLER_ERR_SUCCESS; -} - -EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate) -{ - return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate); -} - -EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate) -{ - *in_rate = st->in_rate; - *out_rate = st->out_rate; -} - -EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate) -{ - spx_uint32_t fact; - spx_uint32_t old_den; - spx_uint32_t i; - if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) - return RESAMPLER_ERR_SUCCESS; - - old_den = st->den_rate; - st->in_rate = in_rate; - st->out_rate = out_rate; - st->num_rate = ratio_num; - st->den_rate = ratio_den; - /* FIXME: This is terribly inefficient, but who cares (at least for now)? */ - for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++) - { - while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) - { - st->num_rate /= fact; - st->den_rate /= fact; - } - } - - if (old_den > 0) - { - for (i=0;i<st->nb_channels;i++) - { - st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den; - /* Safety net */ - if (st->samp_frac_num[i] >= st->den_rate) - st->samp_frac_num[i] = st->den_rate-1; - } - } - - if (st->initialised) - update_filter(st); - return RESAMPLER_ERR_SUCCESS; -} - -EXPORT void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den) -{ - *ratio_num = st->num_rate; - *ratio_den = st->den_rate; -} - -EXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int quality) -{ - if (quality > 10 || quality < 0) - return RESAMPLER_ERR_INVALID_ARG; - if (st->quality == quality) - return RESAMPLER_ERR_SUCCESS; - st->quality = quality; - if (st->initialised) - update_filter(st); - return RESAMPLER_ERR_SUCCESS; -} - -EXPORT void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) -{ - *quality = st->quality; -} - -EXPORT void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride) -{ - st->in_stride = stride; -} - -EXPORT void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride) -{ - *stride = st->in_stride; -} - -EXPORT void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride) -{ - st->out_stride = stride; -} - -EXPORT void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride) -{ - *stride = st->out_stride; -} - -EXPORT int speex_resampler_get_input_latency(SpeexResamplerState *st) -{ - return st->filt_len / 2; -} - -EXPORT int speex_resampler_get_output_latency(SpeexResamplerState *st) -{ - return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate; -} - -EXPORT int speex_resampler_skip_zeros(SpeexResamplerState *st) -{ - spx_uint32_t i; - for (i=0;i<st->nb_channels;i++) - st->last_sample[i] = st->filt_len/2; - return RESAMPLER_ERR_SUCCESS; -} - -EXPORT int speex_resampler_reset_mem(SpeexResamplerState *st) -{ - spx_uint32_t i; - for (i=0;i<st->nb_channels*(st->filt_len-1);i++) - st->mem[i] = 0; - return RESAMPLER_ERR_SUCCESS; -} - -EXPORT const char *speex_resampler_strerror(int err) -{ - switch (err) - { - case RESAMPLER_ERR_SUCCESS: - return "Success."; - case RESAMPLER_ERR_ALLOC_FAILED: - return "Memory allocation failed."; - case RESAMPLER_ERR_BAD_STATE: - return "Bad resampler state."; - case RESAMPLER_ERR_INVALID_ARG: - return "Invalid argument."; - case RESAMPLER_ERR_PTR_OVERLAP: - return "Input and output buffers overlap."; - default: - return "Unknown error. Bad error code or strange version mismatch."; - } -} diff --git a/drivers/speex/resample_sse.h b/drivers/speex/resample_sse.h deleted file mode 100644 index 4bd35a2d03..0000000000 --- a/drivers/speex/resample_sse.h +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (C) 2007-2008 Jean-Marc Valin - * Copyright (C) 2008 Thorvald Natvig - */ -/** - @file resample_sse.h - @brief Resampler functions (SSE version) -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#include <xmmintrin.h> - -#define OVERRIDE_INNER_PRODUCT_SINGLE -static inline float inner_product_single(const float *a, const float *b, unsigned int len) -{ - int i; - float ret; - __m128 sum = _mm_setzero_ps(); - for (i=0;i<len;i+=8) - { - sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i))); - sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4))); - } - sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum)); - sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55)); - _mm_store_ss(&ret, sum); - return ret; -} - -#define OVERRIDE_INTERPOLATE_PRODUCT_SINGLE -static inline float interpolate_product_single(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) { - int i; - float ret; - __m128 sum = _mm_setzero_ps(); - __m128 f = _mm_loadu_ps(frac); - for(i=0;i<len;i+=2) - { - sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample))); - sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample))); - } - sum = _mm_mul_ps(f, 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(&ret, sum); - return ret; -} - -#ifdef _USE_SSE2 -#include <emmintrin.h> -#define OVERRIDE_INNER_PRODUCT_DOUBLE - -static inline double inner_product_double(const float *a, const float *b, unsigned int len) -{ - int i; - double ret; - __m128d sum = _mm_setzero_pd(); - __m128 t; - for (i=0;i<len;i+=8) - { - t = _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i)); - sum = _mm_add_pd(sum, _mm_cvtps_pd(t)); - sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t))); - - t = _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4)); - sum = _mm_add_pd(sum, _mm_cvtps_pd(t)); - sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t))); - } - sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum)); - _mm_store_sd(&ret, sum); - return ret; -} - -#define OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE -static inline double interpolate_product_double(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) { - int i; - double ret; - __m128d sum; - __m128d sum1 = _mm_setzero_pd(); - __m128d sum2 = _mm_setzero_pd(); - __m128 f = _mm_loadu_ps(frac); - __m128d f1 = _mm_cvtps_pd(f); - __m128d f2 = _mm_cvtps_pd(_mm_movehl_ps(f,f)); - __m128 t; - for(i=0;i<len;i+=2) - { - t = _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample)); - sum1 = _mm_add_pd(sum1, _mm_cvtps_pd(t)); - sum2 = _mm_add_pd(sum2, _mm_cvtps_pd(_mm_movehl_ps(t, t))); - - t = _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample)); - sum1 = _mm_add_pd(sum1, _mm_cvtps_pd(t)); - sum2 = _mm_add_pd(sum2, _mm_cvtps_pd(_mm_movehl_ps(t, t))); - } - sum1 = _mm_mul_pd(f1, sum1); - sum2 = _mm_mul_pd(f2, sum2); - sum = _mm_add_pd(sum1, sum2); - sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum)); - _mm_store_sd(&ret, sum); - return ret; -} - -#endif diff --git a/drivers/speex/sb_celp.c b/drivers/speex/sb_celp.c deleted file mode 100644 index fe8bfca72a..0000000000 --- a/drivers/speex/sb_celp.c +++ /dev/null @@ -1,1488 +0,0 @@ -/* Copyright (C) 2002-2006 Jean-Marc Valin - File: sb_celp.c - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -#include "config.h" - - -#include <math.h> -#include "sb_celp.h" -#include "filters.h" -#include "lpc.h" -#include "lsp.h" -#include "stack_alloc.h" -#include "cb_search.h" -#include "quant_lsp.h" -#include "vq.h" -#include "ltp.h" -#include "arch.h" -#include "math_approx.h" -#include "os_support.h" - -#ifndef NULL -#define NULL 0 -#endif - -/* Default size for the encoder and decoder stack (can be changed at compile time). - This does not apply when using variable-size arrays or alloca. */ -#ifndef SB_ENC_STACK -#define SB_ENC_STACK (10000*sizeof(spx_sig_t)) -#endif - -#ifndef SB_DEC_STACK -#define SB_DEC_STACK (6000*sizeof(spx_sig_t)) -#endif - - -#ifdef DISABLE_WIDEBAND -void *sb_encoder_init(const SpeexMode *m) -{ - speex_fatal("Wideband and Ultra-wideband are disabled"); - return NULL; -} -void sb_encoder_destroy(void *state) -{ - speex_fatal("Wideband and Ultra-wideband are disabled"); -} -int sb_encode(void *state, void *vin, SpeexBits *bits) -{ - speex_fatal("Wideband and Ultra-wideband are disabled"); - return -2; -} -void *sb_decoder_init(const SpeexMode *m) -{ - speex_fatal("Wideband and Ultra-wideband are disabled"); - return NULL; -} -void sb_decoder_destroy(void *state) -{ - speex_fatal("Wideband and Ultra-wideband are disabled"); -} -int sb_decode(void *state, SpeexBits *bits, void *vout) -{ - speex_fatal("Wideband and Ultra-wideband are disabled"); - return -2; -} -int sb_encoder_ctl(void *state, int request, void *ptr) -{ - speex_fatal("Wideband and Ultra-wideband are disabled"); - return -2; -} -int sb_decoder_ctl(void *state, int request, void *ptr) -{ - speex_fatal("Wideband and Ultra-wideband are disabled"); - return -2; -} -#else - - -#ifndef M_PI -#define M_PI 3.14159265358979323846 /* pi */ -#endif - -#define sqr(x) ((x)*(x)) - -#define SUBMODE(x) st->submodes[st->submodeID]->x - -#ifdef FIXED_POINT -static const spx_word16_t gc_quant_bound[16] = {125, 164, 215, 282, 370, 484, 635, 832, 1090, 1428, 1871, 2452, 3213, 4210, 5516, 7228}; -static const spx_word16_t fold_quant_bound[32] = { - 39, 44, 50, 57, 64, 73, 83, 94, - 106, 120, 136, 154, 175, 198, 225, 255, - 288, 327, 370, 420, 476, 539, 611, 692, - 784, 889, 1007, 1141, 1293, 1465, 1660, 1881}; -#define LSP_MARGIN 410 -#define LSP_DELTA1 6553 -#define LSP_DELTA2 1638 - -#else - -static const spx_word16_t gc_quant_bound[16] = { - 0.97979, 1.28384, 1.68223, 2.20426, 2.88829, 3.78458, 4.95900, 6.49787, - 8.51428, 11.15642, 14.61846, 19.15484, 25.09895, 32.88761, 43.09325, 56.46588}; -static const spx_word16_t fold_quant_bound[32] = { - 0.30498, 0.34559, 0.39161, 0.44375, 0.50283, 0.56979, 0.64565, 0.73162, - 0.82903, 0.93942, 1.06450, 1.20624, 1.36685, 1.54884, 1.75506, 1.98875, - 2.25355, 2.55360, 2.89361, 3.27889, 3.71547, 4.21018, 4.77076, 5.40598, - 6.12577, 6.94141, 7.86565, 8.91295, 10.09969, 11.44445, 12.96826, 14.69497}; - -#define LSP_MARGIN .05 -#define LSP_DELTA1 .2 -#define LSP_DELTA2 .05 - -#endif - -#define QMF_ORDER 64 - -#ifdef FIXED_POINT -static const spx_word16_t h0[64] = {2, -7, -7, 18, 15, -39, -25, 75, 35, -130, -41, 212, 38, -327, -17, 483, -32, -689, 124, 956, -283, -1307, 543, 1780, -973, -2467, 1733, 3633, -3339, -6409, 9059, 30153, 30153, 9059, -6409, -3339, 3633, 1733, -2467, -973, 1780, 543, -1307, -283, 956, 124, -689, -32, 483, -17, -327, 38, 212, -41, -130, 35, 75, -25, -39, 15, 18, -7, -7, 2}; - -#else -static const float h0[64] = { - 3.596189e-05f, -0.0001123515f, - -0.0001104587f, 0.0002790277f, - 0.0002298438f, -0.0005953563f, - -0.0003823631f, 0.00113826f, - 0.0005308539f, -0.001986177f, - -0.0006243724f, 0.003235877f, - 0.0005743159f, -0.004989147f, - -0.0002584767f, 0.007367171f, - -0.0004857935f, -0.01050689f, - 0.001894714f, 0.01459396f, - -0.004313674f, -0.01994365f, - 0.00828756f, 0.02716055f, - -0.01485397f, -0.03764973f, - 0.026447f, 0.05543245f, - -0.05095487f, -0.09779096f, - 0.1382363f, 0.4600981f, - 0.4600981f, 0.1382363f, - -0.09779096f, -0.05095487f, - 0.05543245f, 0.026447f, - -0.03764973f, -0.01485397f, - 0.02716055f, 0.00828756f, - -0.01994365f, -0.004313674f, - 0.01459396f, 0.001894714f, - -0.01050689f, -0.0004857935f, - 0.007367171f, -0.0002584767f, - -0.004989147f, 0.0005743159f, - 0.003235877f, -0.0006243724f, - -0.001986177f, 0.0005308539f, - 0.00113826f, -0.0003823631f, - -0.0005953563f, 0.0002298438f, - 0.0002790277f, -0.0001104587f, - -0.0001123515f, 3.596189e-05f -}; - -#endif - -extern const spx_word16_t lag_window[]; -extern const spx_word16_t lpc_window[]; - - -void *sb_encoder_init(const SpeexMode *m) -{ - int i; - spx_int32_t tmp; - SBEncState *st; - const SpeexSBMode *mode; - - st = (SBEncState*)speex_alloc(sizeof(SBEncState)); - if (!st) - return NULL; - st->mode = m; - mode = (const SpeexSBMode*)m->mode; - - - st->st_low = speex_encoder_init(mode->nb_mode); -#if defined(VAR_ARRAYS) || defined (USE_ALLOCA) - st->stack = NULL; -#else - /*st->stack = (char*)speex_alloc_scratch(SB_ENC_STACK);*/ - speex_encoder_ctl(st->st_low, SPEEX_GET_STACK, &st->stack); -#endif - - st->full_frame_size = 2*mode->frameSize; - st->frame_size = mode->frameSize; - st->subframeSize = mode->subframeSize; - st->nbSubframes = mode->frameSize/mode->subframeSize; - st->windowSize = st->frame_size+st->subframeSize; - st->lpcSize=mode->lpcSize; - - st->encode_submode = 1; - st->submodes=mode->submodes; - st->submodeSelect = st->submodeID=mode->defaultSubmode; - - tmp=9; - speex_encoder_ctl(st->st_low, SPEEX_SET_QUALITY, &tmp); - tmp=1; - speex_encoder_ctl(st->st_low, SPEEX_SET_WIDEBAND, &tmp); - - st->lpc_floor = mode->lpc_floor; - st->gamma1=mode->gamma1; - st->gamma2=mode->gamma2; - st->first=1; - - st->high=(spx_word16_t*)speex_alloc((st->windowSize-st->frame_size)*sizeof(spx_word16_t)); - - st->h0_mem=(spx_word16_t*)speex_alloc((QMF_ORDER)*sizeof(spx_word16_t)); - st->h1_mem=(spx_word16_t*)speex_alloc((QMF_ORDER)*sizeof(spx_word16_t)); - - st->window= lpc_window; - - st->lagWindow = lag_window; - - st->old_lsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t)); - st->old_qlsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t)); - st->interp_qlpc = (spx_coef_t*)speex_alloc(st->lpcSize*sizeof(spx_coef_t)); - st->pi_gain = (spx_word32_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word32_t)); - st->exc_rms = (spx_word16_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word16_t)); - st->innov_rms_save = NULL; - - st->mem_sp = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); - st->mem_sp2 = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); - st->mem_sw = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); - - for (i=0;i<st->lpcSize;i++) - st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), st->lpcSize+1); - -#ifndef DISABLE_VBR - st->vbr_quality = 8; - st->vbr_enabled = 0; - st->vbr_max = 0; - st->vbr_max_high = 20000; /* We just need a big value here */ - st->vad_enabled = 0; - st->abr_enabled = 0; - st->relative_quality=0; -#endif /* #ifndef DISABLE_VBR */ - - st->complexity=2; - speex_encoder_ctl(st->st_low, SPEEX_GET_SAMPLING_RATE, &st->sampling_rate); - st->sampling_rate*=2; -#ifdef ENABLE_VALGRIND - VALGRIND_MAKE_READABLE(st, (st->stack-(char*)st)); -#endif - return st; -} - -void sb_encoder_destroy(void *state) -{ - SBEncState *st=(SBEncState*)state; - - speex_encoder_destroy(st->st_low); -#if !(defined(VAR_ARRAYS) || defined (USE_ALLOCA)) - /*speex_free_scratch(st->stack);*/ -#endif - - speex_free(st->high); - - speex_free(st->h0_mem); - speex_free(st->h1_mem); - - speex_free(st->old_lsp); - speex_free(st->old_qlsp); - speex_free(st->interp_qlpc); - speex_free(st->pi_gain); - speex_free(st->exc_rms); - - speex_free(st->mem_sp); - speex_free(st->mem_sp2); - speex_free(st->mem_sw); - - - speex_free(st); -} - - -int sb_encode(void *state, void *vin, SpeexBits *bits) -{ - SBEncState *st; - int i, roots, sub; - char *stack; - VARDECL(spx_mem_t *mem); - VARDECL(spx_sig_t *innov); - VARDECL(spx_word16_t *target); - VARDECL(spx_word16_t *syn_resp); - VARDECL(spx_word32_t *low_pi_gain); - spx_word16_t *low; - spx_word16_t *high; - VARDECL(spx_word16_t *low_exc_rms); - VARDECL(spx_word16_t *low_innov_rms); - const SpeexSBMode *mode; - spx_int32_t dtx; - spx_word16_t *in = (spx_word16_t*)vin; - spx_word16_t e_low=0, e_high=0; - VARDECL(spx_coef_t *lpc); - VARDECL(spx_coef_t *interp_lpc); - VARDECL(spx_coef_t *bw_lpc1); - VARDECL(spx_coef_t *bw_lpc2); - VARDECL(spx_lsp_t *lsp); - VARDECL(spx_lsp_t *qlsp); - VARDECL(spx_lsp_t *interp_lsp); - VARDECL(spx_lsp_t *interp_qlsp); - - st = (SBEncState*)state; - stack=st->stack; - mode = (const SpeexSBMode*)(st->mode->mode); - low = in; - high = in+st->frame_size; - - /* High-band buffering / sync with low band */ - /* Compute the two sub-bands by filtering with QMF h0*/ - qmf_decomp(in, h0, low, high, st->full_frame_size, QMF_ORDER, st->h0_mem, stack); - -#ifndef DISABLE_VBR - if (st->vbr_enabled || st->vad_enabled) - { - /* Need to compute things here before the signal is trashed by the encoder */ - /*FIXME: Are the two signals (low, high) in sync? */ - e_low = compute_rms16(low, st->frame_size); - e_high = compute_rms16(high, st->frame_size); - } -#endif /* #ifndef DISABLE_VBR */ - - ALLOC(low_innov_rms, st->nbSubframes, spx_word16_t); - speex_encoder_ctl(st->st_low, SPEEX_SET_INNOVATION_SAVE, low_innov_rms); - /* Encode the narrowband part*/ - speex_encode_native(st->st_low, low, bits); - - high = high - (st->windowSize-st->frame_size); - SPEEX_COPY(high, st->high, st->windowSize-st->frame_size); - SPEEX_COPY(st->high, &high[st->frame_size], st->windowSize-st->frame_size); - - - ALLOC(low_pi_gain, st->nbSubframes, spx_word32_t); - ALLOC(low_exc_rms, st->nbSubframes, spx_word16_t); - speex_encoder_ctl(st->st_low, SPEEX_GET_PI_GAIN, low_pi_gain); - speex_encoder_ctl(st->st_low, SPEEX_GET_EXC, low_exc_rms); - - speex_encoder_ctl(st->st_low, SPEEX_GET_LOW_MODE, &dtx); - - if (dtx==0) - dtx=1; - else - dtx=0; - - ALLOC(lpc, st->lpcSize, spx_coef_t); - ALLOC(interp_lpc, st->lpcSize, spx_coef_t); - ALLOC(bw_lpc1, st->lpcSize, spx_coef_t); - ALLOC(bw_lpc2, st->lpcSize, spx_coef_t); - - ALLOC(lsp, st->lpcSize, spx_lsp_t); - ALLOC(qlsp, st->lpcSize, spx_lsp_t); - ALLOC(interp_lsp, st->lpcSize, spx_lsp_t); - ALLOC(interp_qlsp, st->lpcSize, spx_lsp_t); - - { - VARDECL(spx_word16_t *autocorr); - VARDECL(spx_word16_t *w_sig); - ALLOC(autocorr, st->lpcSize+1, spx_word16_t); - ALLOC(w_sig, st->windowSize, spx_word16_t); - /* Window for analysis */ - /* FIXME: This is a kludge */ - if (st->subframeSize==80) - { - for (i=0;i<st->windowSize;i++) - w_sig[i] = EXTRACT16(SHR32(MULT16_16(high[i],st->window[i>>1]),SIG_SHIFT)); - } else { - for (i=0;i<st->windowSize;i++) - w_sig[i] = EXTRACT16(SHR32(MULT16_16(high[i],st->window[i]),SIG_SHIFT)); - } - /* Compute auto-correlation */ - _spx_autocorr(w_sig, autocorr, st->lpcSize+1, st->windowSize); - autocorr[0] = ADD16(autocorr[0],MULT16_16_Q15(autocorr[0],st->lpc_floor)); /* Noise floor in auto-correlation domain */ - - /* Lag windowing: equivalent to filtering in the power-spectrum domain */ - for (i=0;i<st->lpcSize+1;i++) - autocorr[i] = MULT16_16_Q14(autocorr[i],st->lagWindow[i]); - - /* Levinson-Durbin */ - _spx_lpc(lpc, autocorr, st->lpcSize); - } - - /* LPC to LSPs (x-domain) transform */ - roots=lpc_to_lsp (lpc, st->lpcSize, lsp, 10, LSP_DELTA1, stack); - if (roots!=st->lpcSize) - { - roots = lpc_to_lsp (lpc, st->lpcSize, lsp, 10, LSP_DELTA2, stack); - if (roots!=st->lpcSize) { - /*If we can't find all LSP's, do some damage control and use a flat filter*/ - for (i=0;i<st->lpcSize;i++) - { - lsp[i]=st->old_lsp[i]; - } - } - } - -#ifndef DISABLE_VBR - /* VBR code */ - if ((st->vbr_enabled || st->vad_enabled) && !dtx) - { - float ratio; - if (st->abr_enabled) - { - float qual_change=0; - if (st->abr_drift2 * st->abr_drift > 0) - { - /* Only adapt if long-term and short-term drift are the same sign */ - qual_change = -.00001*st->abr_drift/(1+st->abr_count); - if (qual_change>.1) - qual_change=.1; - if (qual_change<-.1) - qual_change=-.1; - } - st->vbr_quality += qual_change; - if (st->vbr_quality>10) - st->vbr_quality=10; - if (st->vbr_quality<0) - st->vbr_quality=0; - } - - - ratio = 2*log((1.f+e_high)/(1.f+e_low)); - - speex_encoder_ctl(st->st_low, SPEEX_GET_RELATIVE_QUALITY, &st->relative_quality); - if (ratio<-4) - ratio=-4; - if (ratio>2) - ratio=2; - /*if (ratio>-2)*/ - if (st->vbr_enabled) - { - spx_int32_t modeid; - modeid = mode->nb_modes-1; - st->relative_quality+=1.0*(ratio+2); - if (st->relative_quality<-1) - st->relative_quality=-1; - while (modeid) - { - int v1; - float thresh; - v1=(int)floor(st->vbr_quality); - if (v1==10) - thresh = mode->vbr_thresh[modeid][v1]; - else - thresh = (st->vbr_quality-v1) * mode->vbr_thresh[modeid][v1+1] + - (1+v1-st->vbr_quality) * mode->vbr_thresh[modeid][v1]; - if (st->relative_quality >= thresh && st->sampling_rate*st->submodes[modeid]->bits_per_frame/st->full_frame_size <= st->vbr_max_high) - break; - modeid--; - } - speex_encoder_ctl(state, SPEEX_SET_HIGH_MODE, &modeid); - if (st->abr_enabled) - { - spx_int32_t bitrate; - speex_encoder_ctl(state, SPEEX_GET_BITRATE, &bitrate); - st->abr_drift+=(bitrate-st->abr_enabled); - st->abr_drift2 = .95*st->abr_drift2 + .05*(bitrate-st->abr_enabled); - st->abr_count += 1.0; - } - - } else { - /* VAD only */ - int modeid; - if (st->relative_quality<2.0) - modeid=1; - else - modeid=st->submodeSelect; - /*speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);*/ - st->submodeID=modeid; - - } - /*fprintf (stderr, "%f %f\n", ratio, low_qual);*/ - } -#endif /* #ifndef DISABLE_VBR */ - - if (st->encode_submode) - { - speex_bits_pack(bits, 1, 1); - if (dtx) - speex_bits_pack(bits, 0, SB_SUBMODE_BITS); - else - speex_bits_pack(bits, st->submodeID, SB_SUBMODE_BITS); - } - - /* If null mode (no transmission), just set a couple things to zero*/ - if (dtx || st->submodes[st->submodeID] == NULL) - { - for (i=0;i<st->frame_size;i++) - high[i]=VERY_SMALL; - - for (i=0;i<st->lpcSize;i++) - st->mem_sw[i]=0; - st->first=1; - - /* Final signal synthesis from excitation */ - iir_mem16(high, st->interp_qlpc, high, st->frame_size, st->lpcSize, st->mem_sp, stack); - - if (dtx) - return 0; - else - return 1; - } - - - /* LSP quantization */ - SUBMODE(lsp_quant)(lsp, qlsp, st->lpcSize, bits); - - if (st->first) - { - for (i=0;i<st->lpcSize;i++) - st->old_lsp[i] = lsp[i]; - for (i=0;i<st->lpcSize;i++) - st->old_qlsp[i] = qlsp[i]; - } - - ALLOC(mem, st->lpcSize, spx_mem_t); - ALLOC(syn_resp, st->subframeSize, spx_word16_t); - ALLOC(innov, st->subframeSize, spx_sig_t); - ALLOC(target, st->subframeSize, spx_word16_t); - - for (sub=0;sub<st->nbSubframes;sub++) - { - VARDECL(spx_word16_t *exc); - VARDECL(spx_word16_t *res); - VARDECL(spx_word16_t *sw); - spx_word16_t *sp; - spx_word16_t filter_ratio; /*Q7*/ - int offset; - spx_word32_t rl, rh; /*Q13*/ - spx_word16_t eh=0; - - offset = st->subframeSize*sub; - sp=high+offset; - ALLOC(exc, st->subframeSize, spx_word16_t); - ALLOC(res, st->subframeSize, spx_word16_t); - ALLOC(sw, st->subframeSize, spx_word16_t); - - /* LSP interpolation (quantized and unquantized) */ - lsp_interpolate(st->old_lsp, lsp, interp_lsp, st->lpcSize, sub, st->nbSubframes); - lsp_interpolate(st->old_qlsp, qlsp, interp_qlsp, st->lpcSize, sub, st->nbSubframes); - - lsp_enforce_margin(interp_lsp, st->lpcSize, LSP_MARGIN); - lsp_enforce_margin(interp_qlsp, st->lpcSize, LSP_MARGIN); - - lsp_to_lpc(interp_lsp, interp_lpc, st->lpcSize,stack); - lsp_to_lpc(interp_qlsp, st->interp_qlpc, st->lpcSize, stack); - - bw_lpc(st->gamma1, interp_lpc, bw_lpc1, st->lpcSize); - bw_lpc(st->gamma2, interp_lpc, bw_lpc2, st->lpcSize); - - /* Compute mid-band (4000 Hz for wideband) response of low-band and high-band - filters */ - st->pi_gain[sub]=LPC_SCALING; - rh = LPC_SCALING; - for (i=0;i<st->lpcSize;i+=2) - { - rh += st->interp_qlpc[i+1] - st->interp_qlpc[i]; - st->pi_gain[sub] += st->interp_qlpc[i] + st->interp_qlpc[i+1]; - } - - rl = low_pi_gain[sub]; -#ifdef FIXED_POINT - filter_ratio=EXTRACT16(SATURATE(PDIV32(SHL32(ADD32(rl,82),7),ADD32(82,rh)),32767)); -#else - filter_ratio=(rl+.01)/(rh+.01); -#endif - - /* Compute "real excitation" */ - fir_mem16(sp, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, st->mem_sp2, stack); - /* Compute energy of low-band and high-band excitation */ - - eh = compute_rms16(exc, st->subframeSize); - - if (!SUBMODE(innovation_quant)) {/* 1 for spectral folding excitation, 0 for stochastic */ - spx_word32_t g; /*Q7*/ - spx_word16_t el; /*Q0*/ - el = low_innov_rms[sub]; - - /* Gain to use if we want to use the low-band excitation for high-band */ - g=PDIV32(MULT16_16(filter_ratio,eh),EXTEND32(ADD16(1,el))); - -#if 0 - { - char *tmp_stack=stack; - float *tmp_sig; - float g2; - ALLOC(tmp_sig, st->subframeSize, spx_sig_t); - for (i=0;i<st->lpcSize;i++) - mem[i]=st->mem_sp[i]; - iir_mem2(st->low_innov+offset, st->interp_qlpc, tmp_sig, st->subframeSize, st->lpcSize, mem); - g2 = compute_rms(sp, st->subframeSize)/(.01+compute_rms(tmp_sig, st->subframeSize)); - /*fprintf (stderr, "gains: %f %f\n", g, g2);*/ - g = g2; - stack = tmp_stack; - } -#endif - - /*print_vec(&g, 1, "gain factor");*/ - /* Gain quantization */ - { - int quant = scal_quant(g, fold_quant_bound, 32); - /*speex_warning_int("tata", quant);*/ - if (quant<0) - quant=0; - if (quant>31) - quant=31; - speex_bits_pack(bits, quant, 5); - } - if (st->innov_rms_save) - { - st->innov_rms_save[sub] = eh; - } - st->exc_rms[sub] = eh; - } else { - spx_word16_t gc; /*Q7*/ - spx_word32_t scale; /*Q14*/ - spx_word16_t el; /*Q0*/ - el = low_exc_rms[sub]; /*Q0*/ - - gc = PDIV32_16(MULT16_16(filter_ratio,1+eh),1+el); - - /* This is a kludge that cleans up a historical bug */ - if (st->subframeSize==80) - gc = MULT16_16_P15(QCONST16(0.70711f,15),gc); - /*printf ("%f %f %f %f\n", el, eh, filter_ratio, gc);*/ - { - int qgc = scal_quant(gc, gc_quant_bound, 16); - speex_bits_pack(bits, qgc, 4); - gc = MULT16_16_Q15(QCONST16(0.87360,15),gc_quant_bound[qgc]); - } - if (st->subframeSize==80) - gc = MULT16_16_P14(QCONST16(1.4142f,14), gc); - - scale = SHL32(MULT16_16(PDIV32_16(SHL32(EXTEND32(gc),SIG_SHIFT-6),filter_ratio),(1+el)),6); - - compute_impulse_response(st->interp_qlpc, bw_lpc1, bw_lpc2, syn_resp, st->subframeSize, st->lpcSize, stack); - - - /* Reset excitation */ - for (i=0;i<st->subframeSize;i++) - res[i]=VERY_SMALL; - - /* Compute zero response (ringing) of A(z/g1) / ( A(z/g2) * Aq(z) ) */ - for (i=0;i<st->lpcSize;i++) - mem[i]=st->mem_sp[i]; - iir_mem16(res, st->interp_qlpc, res, st->subframeSize, st->lpcSize, mem, stack); - - for (i=0;i<st->lpcSize;i++) - mem[i]=st->mem_sw[i]; - filter_mem16(res, bw_lpc1, bw_lpc2, res, st->subframeSize, st->lpcSize, mem, stack); - - /* Compute weighted signal */ - for (i=0;i<st->lpcSize;i++) - mem[i]=st->mem_sw[i]; - filter_mem16(sp, bw_lpc1, bw_lpc2, sw, st->subframeSize, st->lpcSize, mem, stack); - - /* Compute target signal */ - for (i=0;i<st->subframeSize;i++) - target[i]=SUB16(sw[i],res[i]); - - signal_div(target, target, scale, st->subframeSize); - - /* Reset excitation */ - SPEEX_MEMSET(innov, 0, st->subframeSize); - - /*print_vec(target, st->subframeSize, "\ntarget");*/ - SUBMODE(innovation_quant)(target, st->interp_qlpc, bw_lpc1, bw_lpc2, - SUBMODE(innovation_params), st->lpcSize, st->subframeSize, - innov, syn_resp, bits, stack, st->complexity, SUBMODE(double_codebook)); - /*print_vec(target, st->subframeSize, "after");*/ - - signal_mul(innov, innov, scale, st->subframeSize); - - if (SUBMODE(double_codebook)) { - char *tmp_stack=stack; - VARDECL(spx_sig_t *innov2); - ALLOC(innov2, st->subframeSize, spx_sig_t); - SPEEX_MEMSET(innov2, 0, st->subframeSize); - for (i=0;i<st->subframeSize;i++) - target[i]=MULT16_16_P13(QCONST16(2.5f,13), target[i]); - - SUBMODE(innovation_quant)(target, st->interp_qlpc, bw_lpc1, bw_lpc2, - SUBMODE(innovation_params), st->lpcSize, st->subframeSize, - innov2, syn_resp, bits, stack, st->complexity, 0); - signal_mul(innov2, innov2, MULT16_32_P15(QCONST16(0.4f,15),scale), st->subframeSize); - - for (i=0;i<st->subframeSize;i++) - innov[i] = ADD32(innov[i],innov2[i]); - stack = tmp_stack; - } - for (i=0;i<st->subframeSize;i++) - exc[i] = PSHR32(innov[i],SIG_SHIFT); - - if (st->innov_rms_save) - { - st->innov_rms_save[sub] = MULT16_16_Q15(QCONST16(.70711f, 15), compute_rms(innov, st->subframeSize)); - } - st->exc_rms[sub] = compute_rms16(exc, st->subframeSize); - - - } - - - /*Keep the previous memory*/ - for (i=0;i<st->lpcSize;i++) - mem[i]=st->mem_sp[i]; - /* Final signal synthesis from excitation */ - iir_mem16(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp, stack); - - /* Compute weighted signal again, from synthesized speech (not sure it's the right thing) */ - filter_mem16(sp, bw_lpc1, bw_lpc2, sw, st->subframeSize, st->lpcSize, st->mem_sw, stack); - } - - for (i=0;i<st->lpcSize;i++) - st->old_lsp[i] = lsp[i]; - for (i=0;i<st->lpcSize;i++) - st->old_qlsp[i] = qlsp[i]; - - st->first=0; - - return 1; -} - - - - - -void *sb_decoder_init(const SpeexMode *m) -{ - spx_int32_t tmp; - SBDecState *st; - const SpeexSBMode *mode; - st = (SBDecState*)speex_alloc(sizeof(SBDecState)); - if (!st) - return NULL; - st->mode = m; - mode=(const SpeexSBMode*)m->mode; - st->encode_submode = 1; - - st->st_low = speex_decoder_init(mode->nb_mode); -#if defined(VAR_ARRAYS) || defined (USE_ALLOCA) - st->stack = NULL; -#else - /*st->stack = (char*)speex_alloc_scratch(SB_DEC_STACK);*/ - speex_decoder_ctl(st->st_low, SPEEX_GET_STACK, &st->stack); -#endif - - st->full_frame_size = 2*mode->frameSize; - st->frame_size = mode->frameSize; - st->subframeSize = mode->subframeSize; - st->nbSubframes = mode->frameSize/mode->subframeSize; - st->lpcSize=mode->lpcSize; - speex_decoder_ctl(st->st_low, SPEEX_GET_SAMPLING_RATE, &st->sampling_rate); - st->sampling_rate*=2; - tmp=1; - speex_decoder_ctl(st->st_low, SPEEX_SET_WIDEBAND, &tmp); - - st->submodes=mode->submodes; - st->submodeID=mode->defaultSubmode; - - st->first=1; - - st->g0_mem = (spx_word16_t*)speex_alloc((QMF_ORDER)*sizeof(spx_word16_t)); - st->g1_mem = (spx_word16_t*)speex_alloc((QMF_ORDER)*sizeof(spx_word16_t)); - - st->excBuf = (spx_word16_t*)speex_alloc((st->subframeSize)*sizeof(spx_word16_t)); - - st->old_qlsp = (spx_lsp_t*)speex_alloc((st->lpcSize)*sizeof(spx_lsp_t)); - st->interp_qlpc = (spx_coef_t*)speex_alloc(st->lpcSize*sizeof(spx_coef_t)); - - st->pi_gain = (spx_word32_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word32_t)); - st->exc_rms = (spx_word16_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word16_t)); - st->mem_sp = (spx_mem_t*)speex_alloc((2*st->lpcSize)*sizeof(spx_mem_t)); - - st->innov_save = NULL; - - - st->lpc_enh_enabled=0; - st->seed = 1000; - -#ifdef ENABLE_VALGRIND - VALGRIND_MAKE_READABLE(st, (st->stack-(char*)st)); -#endif - return st; -} - -void sb_decoder_destroy(void *state) -{ - SBDecState *st; - st = (SBDecState*)state; - speex_decoder_destroy(st->st_low); -#if !(defined(VAR_ARRAYS) || defined (USE_ALLOCA)) - /*speex_free_scratch(st->stack);*/ -#endif - - speex_free(st->g0_mem); - speex_free(st->g1_mem); - speex_free(st->excBuf); - speex_free(st->old_qlsp); - speex_free(st->interp_qlpc); - speex_free(st->pi_gain); - speex_free(st->exc_rms); - speex_free(st->mem_sp); - - speex_free(state); -} - -static void sb_decode_lost(SBDecState *st, spx_word16_t *out, int dtx, char *stack) -{ - int i; - int saved_modeid=0; - - if (dtx) - { - saved_modeid=st->submodeID; - st->submodeID=1; - } else { - bw_lpc(QCONST16(0.99f,15), st->interp_qlpc, st->interp_qlpc, st->lpcSize); - } - - st->first=1; - - - /* Final signal synthesis from excitation */ - if (!dtx) - { - st->last_ener = MULT16_16_Q15(QCONST16(.9f,15),st->last_ener); - } - for (i=0;i<st->frame_size;i++) - out[i+st->frame_size] = speex_rand(st->last_ener, &st->seed); - - iir_mem16(out+st->frame_size, st->interp_qlpc, out+st->frame_size, st->frame_size, st->lpcSize, - st->mem_sp, stack); - - - /* Reconstruct the original */ - qmf_synth(out, out+st->frame_size, h0, out, st->full_frame_size, QMF_ORDER, st->g0_mem, st->g1_mem, stack); - if (dtx) - { - st->submodeID=saved_modeid; - } - - return; -} - -int sb_decode(void *state, SpeexBits *bits, void *vout) -{ - int i, sub; - SBDecState *st; - int wideband; - int ret; - char *stack; - VARDECL(spx_word32_t *low_pi_gain); - VARDECL(spx_word16_t *low_exc_rms); - VARDECL(spx_coef_t *ak); - VARDECL(spx_lsp_t *qlsp); - VARDECL(spx_lsp_t *interp_qlsp); - spx_int32_t dtx; - const SpeexSBMode *mode; - spx_word16_t *out = (spx_word16_t*)vout; - spx_word16_t *low_innov_alias; - spx_word32_t exc_ener_sum = 0; - - st = (SBDecState*)state; - stack=st->stack; - mode = (const SpeexSBMode*)(st->mode->mode); - - low_innov_alias = out+st->frame_size; - speex_decoder_ctl(st->st_low, SPEEX_SET_INNOVATION_SAVE, low_innov_alias); - /* Decode the low-band */ - ret = speex_decode_native(st->st_low, bits, out); - - speex_decoder_ctl(st->st_low, SPEEX_GET_DTX_STATUS, &dtx); - - /* If error decoding the narrowband part, propagate error */ - if (ret!=0) - { - return ret; - } - - if (!bits) - { - sb_decode_lost(st, out, dtx, stack); - return 0; - } - - if (st->encode_submode) - { - - /*Check "wideband bit"*/ - if (speex_bits_remaining(bits)>0) - wideband = speex_bits_peek(bits); - else - wideband = 0; - if (wideband) - { - /*Regular wideband frame, read the submode*/ - wideband = speex_bits_unpack_unsigned(bits, 1); - st->submodeID = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS); - } else - { - /*Was a narrowband frame, set "null submode"*/ - st->submodeID = 0; - } - if (st->submodeID != 0 && st->submodes[st->submodeID] == NULL) - { - speex_notify("Invalid mode encountered. The stream is corrupted."); - return -2; - } - } - - /* If null mode (no transmission), just set a couple things to zero*/ - if (st->submodes[st->submodeID] == NULL) - { - if (dtx) - { - sb_decode_lost(st, out, 1, stack); - return 0; - } - - for (i=0;i<st->frame_size;i++) - out[st->frame_size+i]=VERY_SMALL; - - st->first=1; - - /* Final signal synthesis from excitation */ - iir_mem16(out+st->frame_size, st->interp_qlpc, out+st->frame_size, st->frame_size, st->lpcSize, st->mem_sp, stack); - - qmf_synth(out, out+st->frame_size, h0, out, st->full_frame_size, QMF_ORDER, st->g0_mem, st->g1_mem, stack); - - return 0; - - } - - ALLOC(low_pi_gain, st->nbSubframes, spx_word32_t); - ALLOC(low_exc_rms, st->nbSubframes, spx_word16_t); - speex_decoder_ctl(st->st_low, SPEEX_GET_PI_GAIN, low_pi_gain); - speex_decoder_ctl(st->st_low, SPEEX_GET_EXC, low_exc_rms); - - ALLOC(qlsp, st->lpcSize, spx_lsp_t); - ALLOC(interp_qlsp, st->lpcSize, spx_lsp_t); - SUBMODE(lsp_unquant)(qlsp, st->lpcSize, bits); - - if (st->first) - { - for (i=0;i<st->lpcSize;i++) - st->old_qlsp[i] = qlsp[i]; - } - - ALLOC(ak, st->lpcSize, spx_coef_t); - - for (sub=0;sub<st->nbSubframes;sub++) - { - VARDECL(spx_word32_t *exc); - spx_word16_t *innov_save=NULL; - spx_word16_t *sp; - spx_word16_t filter_ratio; - spx_word16_t el=0; - int offset; - spx_word32_t rl=0,rh=0; - - offset = st->subframeSize*sub; - sp=out+st->frame_size+offset; - ALLOC(exc, st->subframeSize, spx_word32_t); - /* Pointer for saving innovation */ - if (st->innov_save) - { - innov_save = st->innov_save+2*offset; - SPEEX_MEMSET(innov_save, 0, 2*st->subframeSize); - } - - /* LSP interpolation */ - lsp_interpolate(st->old_qlsp, qlsp, interp_qlsp, st->lpcSize, sub, st->nbSubframes); - - lsp_enforce_margin(interp_qlsp, st->lpcSize, LSP_MARGIN); - - /* LSP to LPC */ - lsp_to_lpc(interp_qlsp, ak, st->lpcSize, stack); - - /* Calculate reponse ratio between the low and high filter in the middle - of the band (4000 Hz) */ - - st->pi_gain[sub]=LPC_SCALING; - rh = LPC_SCALING; - for (i=0;i<st->lpcSize;i+=2) - { - rh += ak[i+1] - ak[i]; - st->pi_gain[sub] += ak[i] + ak[i+1]; - } - - rl = low_pi_gain[sub]; -#ifdef FIXED_POINT - filter_ratio=EXTRACT16(SATURATE(PDIV32(SHL32(ADD32(rl,82),7),ADD32(82,rh)),32767)); -#else - filter_ratio=(rl+.01)/(rh+.01); -#endif - - SPEEX_MEMSET(exc, 0, st->subframeSize); - if (!SUBMODE(innovation_unquant)) - { - spx_word32_t g; - int quant; - - quant = speex_bits_unpack_unsigned(bits, 5); - g= spx_exp(MULT16_16(QCONST16(.125f,11),(quant-10))); - - g = PDIV32(g, filter_ratio); - - for (i=0;i<st->subframeSize;i+=2) - { - exc[i]=SHL32(MULT16_32_P15(MULT16_16_Q15(mode->folding_gain,low_innov_alias[offset+i]),SHL32(g,6)),SIG_SHIFT); - exc[i+1]=NEG32(SHL32(MULT16_32_P15(MULT16_16_Q15(mode->folding_gain,low_innov_alias[offset+i+1]),SHL32(g,6)),SIG_SHIFT)); - } - - } else { - spx_word16_t gc; - spx_word32_t scale; - int qgc = speex_bits_unpack_unsigned(bits, 4); - - el = low_exc_rms[sub]; - gc = MULT16_16_Q15(QCONST16(0.87360,15),gc_quant_bound[qgc]); - - if (st->subframeSize==80) - gc = MULT16_16_P14(QCONST16(1.4142f,14),gc); - - scale = SHL32(PDIV32(SHL32(MULT16_16(gc, el),3), filter_ratio),SIG_SHIFT-3); - SUBMODE(innovation_unquant)(exc, SUBMODE(innovation_params), st->subframeSize, - bits, stack, &st->seed); - - signal_mul(exc,exc,scale,st->subframeSize); - - if (SUBMODE(double_codebook)) { - char *tmp_stack=stack; - VARDECL(spx_sig_t *innov2); - ALLOC(innov2, st->subframeSize, spx_sig_t); - SPEEX_MEMSET(innov2, 0, st->subframeSize); - SUBMODE(innovation_unquant)(innov2, SUBMODE(innovation_params), st->subframeSize, - bits, stack, &st->seed); - signal_mul(innov2, innov2, MULT16_32_P15(QCONST16(0.4f,15),scale), st->subframeSize); - for (i=0;i<st->subframeSize;i++) - exc[i] = ADD32(exc[i],innov2[i]); - stack = tmp_stack; - } - - } - - if (st->innov_save) - { - for (i=0;i<st->subframeSize;i++) - innov_save[2*i]=EXTRACT16(PSHR32(exc[i],SIG_SHIFT)); - } - - iir_mem16(st->excBuf, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, - st->mem_sp, stack); - for (i=0;i<st->subframeSize;i++) - st->excBuf[i]=EXTRACT16(PSHR32(exc[i],SIG_SHIFT)); - for (i=0;i<st->lpcSize;i++) - st->interp_qlpc[i] = ak[i]; - st->exc_rms[sub] = compute_rms16(st->excBuf, st->subframeSize); - exc_ener_sum = ADD32(exc_ener_sum, DIV32(MULT16_16(st->exc_rms[sub],st->exc_rms[sub]), st->nbSubframes)); - } - st->last_ener = spx_sqrt(exc_ener_sum); - - qmf_synth(out, out+st->frame_size, h0, out, st->full_frame_size, QMF_ORDER, st->g0_mem, st->g1_mem, stack); - for (i=0;i<st->lpcSize;i++) - st->old_qlsp[i] = qlsp[i]; - - st->first=0; - - return 0; -} - - -int sb_encoder_ctl(void *state, int request, void *ptr) -{ - SBEncState *st; - st=(SBEncState*)state; - switch(request) - { - case SPEEX_GET_FRAME_SIZE: - (*(spx_int32_t*)ptr) = st->full_frame_size; - break; - case SPEEX_SET_HIGH_MODE: - st->submodeSelect = st->submodeID = (*(spx_int32_t*)ptr); - break; - case SPEEX_SET_LOW_MODE: - speex_encoder_ctl(st->st_low, SPEEX_SET_LOW_MODE, ptr); - break; - case SPEEX_SET_DTX: - speex_encoder_ctl(st->st_low, SPEEX_SET_DTX, ptr); - break; - case SPEEX_GET_DTX: - speex_encoder_ctl(st->st_low, SPEEX_GET_DTX, ptr); - break; - case SPEEX_GET_LOW_MODE: - speex_encoder_ctl(st->st_low, SPEEX_GET_LOW_MODE, ptr); - break; - case SPEEX_SET_MODE: - speex_encoder_ctl(st, SPEEX_SET_QUALITY, ptr); - break; -#ifndef DISABLE_VBR - case SPEEX_SET_VBR: - st->vbr_enabled = (*(spx_int32_t*)ptr); - speex_encoder_ctl(st->st_low, SPEEX_SET_VBR, ptr); - break; - case SPEEX_GET_VBR: - (*(spx_int32_t*)ptr) = st->vbr_enabled; - break; - case SPEEX_SET_VAD: - st->vad_enabled = (*(spx_int32_t*)ptr); - speex_encoder_ctl(st->st_low, SPEEX_SET_VAD, ptr); - break; - case SPEEX_GET_VAD: - (*(spx_int32_t*)ptr) = st->vad_enabled; - break; -#endif /* #ifndef DISABLE_VBR */ -#if !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API) - case SPEEX_SET_VBR_QUALITY: - { - spx_int32_t q; - float qual = (*(float*)ptr)+.6; - st->vbr_quality = (*(float*)ptr); - if (qual>10) - qual=10; - q=(int)floor(.5+*(float*)ptr); - if (q>10) - q=10; - speex_encoder_ctl(st->st_low, SPEEX_SET_VBR_QUALITY, &qual); - speex_encoder_ctl(state, SPEEX_SET_QUALITY, &q); - break; - } - case SPEEX_GET_VBR_QUALITY: - (*(float*)ptr) = st->vbr_quality; - break; -#endif /* #if !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API) */ -#ifndef DISABLE_VBR - case SPEEX_SET_ABR: - st->abr_enabled = (*(spx_int32_t*)ptr); - st->vbr_enabled = st->abr_enabled!=0; - speex_encoder_ctl(st->st_low, SPEEX_SET_VBR, &st->vbr_enabled); - if (st->vbr_enabled) - { - spx_int32_t i=10, rate, target; - float vbr_qual; - target = (*(spx_int32_t*)ptr); - while (i>=0) - { - speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i); - speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate); - if (rate <= target) - break; - i--; - } - vbr_qual=i; - if (vbr_qual<0) - vbr_qual=0; - speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_qual); - st->abr_count=0; - st->abr_drift=0; - st->abr_drift2=0; - } - - break; - case SPEEX_GET_ABR: - (*(spx_int32_t*)ptr) = st->abr_enabled; - break; -#endif /* #ifndef DISABLE_VBR */ - - case SPEEX_SET_QUALITY: - { - spx_int32_t nb_qual; - int quality = (*(spx_int32_t*)ptr); - if (quality < 0) - quality = 0; - if (quality > 10) - quality = 10; - st->submodeSelect = st->submodeID = ((const SpeexSBMode*)(st->mode->mode))->quality_map[quality]; - nb_qual = ((const SpeexSBMode*)(st->mode->mode))->low_quality_map[quality]; - speex_encoder_ctl(st->st_low, SPEEX_SET_MODE, &nb_qual); - } - break; - case SPEEX_SET_COMPLEXITY: - speex_encoder_ctl(st->st_low, SPEEX_SET_COMPLEXITY, ptr); - st->complexity = (*(spx_int32_t*)ptr); - if (st->complexity<1) - st->complexity=1; - break; - case SPEEX_GET_COMPLEXITY: - (*(spx_int32_t*)ptr) = st->complexity; - break; - case SPEEX_SET_BITRATE: - { - spx_int32_t i=10; - spx_int32_t rate, target; - target = (*(spx_int32_t*)ptr); - while (i>=0) - { - speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i); - speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate); - if (rate <= target) - break; - i--; - } - } - break; - case SPEEX_GET_BITRATE: - speex_encoder_ctl(st->st_low, request, ptr); - /*fprintf (stderr, "before: %d\n", (*(int*)ptr));*/ - if (st->submodes[st->submodeID]) - (*(spx_int32_t*)ptr) += st->sampling_rate*SUBMODE(bits_per_frame)/st->full_frame_size; - else - (*(spx_int32_t*)ptr) += st->sampling_rate*(SB_SUBMODE_BITS+1)/st->full_frame_size; - /*fprintf (stderr, "after: %d\n", (*(int*)ptr));*/ - break; - case SPEEX_SET_SAMPLING_RATE: - { - spx_int32_t tmp=(*(spx_int32_t*)ptr); - st->sampling_rate = tmp; - tmp>>=1; - speex_encoder_ctl(st->st_low, SPEEX_SET_SAMPLING_RATE, &tmp); - } - break; - case SPEEX_GET_SAMPLING_RATE: - (*(spx_int32_t*)ptr)=st->sampling_rate; - break; - case SPEEX_RESET_STATE: - { - int i; - st->first = 1; - for (i=0;i<st->lpcSize;i++) - st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), st->lpcSize+1); - for (i=0;i<st->lpcSize;i++) - st->mem_sw[i]=st->mem_sp[i]=st->mem_sp2[i]=0; - for (i=0;i<QMF_ORDER;i++) - st->h0_mem[i]=st->h1_mem[i]=0; - } - break; - case SPEEX_SET_SUBMODE_ENCODING: - st->encode_submode = (*(spx_int32_t*)ptr); - speex_encoder_ctl(st->st_low, SPEEX_SET_SUBMODE_ENCODING, ptr); - break; - case SPEEX_GET_SUBMODE_ENCODING: - (*(spx_int32_t*)ptr) = st->encode_submode; - break; - case SPEEX_GET_LOOKAHEAD: - speex_encoder_ctl(st->st_low, SPEEX_GET_LOOKAHEAD, ptr); - (*(spx_int32_t*)ptr) = 2*(*(spx_int32_t*)ptr) + QMF_ORDER - 1; - break; - case SPEEX_SET_PLC_TUNING: - speex_encoder_ctl(st->st_low, SPEEX_SET_PLC_TUNING, ptr); - break; - case SPEEX_GET_PLC_TUNING: - speex_encoder_ctl(st->st_low, SPEEX_GET_PLC_TUNING, ptr); - break; -#ifndef DISABLE_VBR - case SPEEX_SET_VBR_MAX_BITRATE: - { - st->vbr_max = (*(spx_int32_t*)ptr); - if (SPEEX_SET_VBR_MAX_BITRATE<1) - { - speex_encoder_ctl(st->st_low, SPEEX_SET_VBR_MAX_BITRATE, &st->vbr_max); - st->vbr_max_high = 17600; - } else { - spx_int32_t low_rate; - if (st->vbr_max >= 42200) - { - st->vbr_max_high = 17600; - } else if (st->vbr_max >= 27800) - { - st->vbr_max_high = 9600; - } else if (st->vbr_max > 20600) - { - st->vbr_max_high = 5600; - } else { - st->vbr_max_high = 1800; - } - if (st->subframeSize==80) - st->vbr_max_high = 1800; - low_rate = st->vbr_max - st->vbr_max_high; - speex_encoder_ctl(st->st_low, SPEEX_SET_VBR_MAX_BITRATE, &low_rate); - } - } - break; - case SPEEX_GET_VBR_MAX_BITRATE: - (*(spx_int32_t*)ptr) = st->vbr_max; - break; -#endif /* #ifndef DISABLE_VBR */ - case SPEEX_SET_HIGHPASS: - speex_encoder_ctl(st->st_low, SPEEX_SET_HIGHPASS, ptr); - break; - case SPEEX_GET_HIGHPASS: - speex_encoder_ctl(st->st_low, SPEEX_GET_HIGHPASS, ptr); - break; - - - /* This is all internal stuff past this point */ - case SPEEX_GET_PI_GAIN: - { - int i; - spx_word32_t *g = (spx_word32_t*)ptr; - for (i=0;i<st->nbSubframes;i++) - g[i]=st->pi_gain[i]; - } - break; - case SPEEX_GET_EXC: - { - int i; - for (i=0;i<st->nbSubframes;i++) - ((spx_word16_t*)ptr)[i] = st->exc_rms[i]; - } - break; -#ifndef DISABLE_VBR - case SPEEX_GET_RELATIVE_QUALITY: - (*(float*)ptr)=st->relative_quality; - break; -#endif /* #ifndef DISABLE_VBR */ - case SPEEX_SET_INNOVATION_SAVE: - st->innov_rms_save = (spx_word16_t*)ptr; - break; - case SPEEX_SET_WIDEBAND: - speex_encoder_ctl(st->st_low, SPEEX_SET_WIDEBAND, ptr); - break; - case SPEEX_GET_STACK: - *((char**)ptr) = st->stack; - break; - default: - speex_warning_int("Unknown nb_ctl request: ", request); - return -1; - } - return 0; -} - -int sb_decoder_ctl(void *state, int request, void *ptr) -{ - SBDecState *st; - st=(SBDecState*)state; - switch(request) - { - case SPEEX_SET_HIGH_MODE: - st->submodeID = (*(spx_int32_t*)ptr); - break; - case SPEEX_SET_LOW_MODE: - speex_decoder_ctl(st->st_low, SPEEX_SET_LOW_MODE, ptr); - break; - case SPEEX_GET_LOW_MODE: - speex_decoder_ctl(st->st_low, SPEEX_GET_LOW_MODE, ptr); - break; - case SPEEX_GET_FRAME_SIZE: - (*(spx_int32_t*)ptr) = st->full_frame_size; - break; - case SPEEX_SET_ENH: - speex_decoder_ctl(st->st_low, request, ptr); - st->lpc_enh_enabled = *((spx_int32_t*)ptr); - break; - case SPEEX_GET_ENH: - *((spx_int32_t*)ptr) = st->lpc_enh_enabled; - break; - case SPEEX_SET_MODE: - case SPEEX_SET_QUALITY: - { - spx_int32_t nb_qual; - int quality = (*(spx_int32_t*)ptr); - if (quality < 0) - quality = 0; - if (quality > 10) - quality = 10; - st->submodeID = ((const SpeexSBMode*)(st->mode->mode))->quality_map[quality]; - nb_qual = ((const SpeexSBMode*)(st->mode->mode))->low_quality_map[quality]; - speex_decoder_ctl(st->st_low, SPEEX_SET_MODE, &nb_qual); - } - break; - case SPEEX_GET_BITRATE: - speex_decoder_ctl(st->st_low, request, ptr); - if (st->submodes[st->submodeID]) - (*(spx_int32_t*)ptr) += st->sampling_rate*SUBMODE(bits_per_frame)/st->full_frame_size; - else - (*(spx_int32_t*)ptr) += st->sampling_rate*(SB_SUBMODE_BITS+1)/st->full_frame_size; - break; - case SPEEX_SET_SAMPLING_RATE: - { - spx_int32_t tmp=(*(spx_int32_t*)ptr); - st->sampling_rate = tmp; - tmp>>=1; - speex_decoder_ctl(st->st_low, SPEEX_SET_SAMPLING_RATE, &tmp); - } - break; - case SPEEX_GET_SAMPLING_RATE: - (*(spx_int32_t*)ptr)=st->sampling_rate; - break; - case SPEEX_SET_HANDLER: - speex_decoder_ctl(st->st_low, SPEEX_SET_HANDLER, ptr); - break; - case SPEEX_SET_USER_HANDLER: - speex_decoder_ctl(st->st_low, SPEEX_SET_USER_HANDLER, ptr); - break; - case SPEEX_RESET_STATE: - { - int i; - for (i=0;i<2*st->lpcSize;i++) - st->mem_sp[i]=0; - for (i=0;i<QMF_ORDER;i++) - st->g0_mem[i]=st->g1_mem[i]=0; - st->last_ener=0; - } - break; - case SPEEX_SET_SUBMODE_ENCODING: - st->encode_submode = (*(spx_int32_t*)ptr); - speex_decoder_ctl(st->st_low, SPEEX_SET_SUBMODE_ENCODING, ptr); - break; - case SPEEX_GET_SUBMODE_ENCODING: - (*(spx_int32_t*)ptr) = st->encode_submode; - break; - case SPEEX_GET_LOOKAHEAD: - speex_decoder_ctl(st->st_low, SPEEX_GET_LOOKAHEAD, ptr); - (*(spx_int32_t*)ptr) = 2*(*(spx_int32_t*)ptr); - break; - case SPEEX_SET_HIGHPASS: - speex_decoder_ctl(st->st_low, SPEEX_SET_HIGHPASS, ptr); - break; - case SPEEX_GET_HIGHPASS: - speex_decoder_ctl(st->st_low, SPEEX_GET_HIGHPASS, ptr); - break; - case SPEEX_GET_ACTIVITY: - speex_decoder_ctl(st->st_low, SPEEX_GET_ACTIVITY, ptr); - break; - case SPEEX_GET_PI_GAIN: - { - int i; - spx_word32_t *g = (spx_word32_t*)ptr; - for (i=0;i<st->nbSubframes;i++) - g[i]=st->pi_gain[i]; - } - break; - case SPEEX_GET_EXC: - { - int i; - for (i=0;i<st->nbSubframes;i++) - ((spx_word16_t*)ptr)[i] = st->exc_rms[i]; - } - break; - case SPEEX_GET_DTX_STATUS: - speex_decoder_ctl(st->st_low, SPEEX_GET_DTX_STATUS, ptr); - break; - case SPEEX_SET_INNOVATION_SAVE: - st->innov_save = (spx_word16_t*)ptr; - break; - case SPEEX_SET_WIDEBAND: - speex_decoder_ctl(st->st_low, SPEEX_SET_WIDEBAND, ptr); - break; - case SPEEX_GET_STACK: - *((char**)ptr) = st->stack; - break; - default: - speex_warning_int("Unknown nb_ctl request: ", request); - return -1; - } - return 0; -} - -#endif - diff --git a/drivers/speex/sb_celp.h b/drivers/speex/sb_celp.h deleted file mode 100644 index e8c3761237..0000000000 --- a/drivers/speex/sb_celp.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright (C) 2002-2006 Jean-Marc Valin */ -/** - @file sb_celp.h - @brief Sub-band CELP mode used for wideband encoding -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 SB_CELP_H -#define SB_CELP_H - -#include "modes.h" -#include <speex/speex_bits.h> -#include "nb_celp.h" - -/**Structure representing the full state of the sub-band encoder*/ -typedef struct SBEncState { - const SpeexMode *mode; /**< Pointer to the mode (containing for vtable info) */ - void *st_low; /**< State of the low-band (narrowband) encoder */ - int full_frame_size; /**< Length of full-band frames*/ - int frame_size; /**< Length of high-band frames*/ - int subframeSize; /**< Length of high-band sub-frames*/ - int nbSubframes; /**< Number of high-band sub-frames*/ - int windowSize; /**< Length of high-band LPC window*/ - int lpcSize; /**< Order of high-band LPC analysis */ - int first; /**< First frame? */ - spx_word16_t lpc_floor; /**< Controls LPC analysis noise floor */ - spx_word16_t gamma1; /**< Perceptual weighting coef 1 */ - spx_word16_t gamma2; /**< Perceptual weighting coef 2 */ - - char *stack; /**< Temporary allocation stack */ - spx_word16_t *high; /**< High-band signal (buffer) */ - spx_word16_t *h0_mem, *h1_mem; - - const spx_word16_t *window; /**< LPC analysis window */ - const spx_word16_t *lagWindow; /**< Auto-correlation window */ - spx_lsp_t *old_lsp; /**< LSPs of previous frame */ - spx_lsp_t *old_qlsp; /**< Quantized LSPs of previous frame */ - spx_coef_t *interp_qlpc; /**< Interpolated quantized LPCs for current sub-frame */ - - spx_mem_t *mem_sp; /**< Synthesis signal memory */ - spx_mem_t *mem_sp2; - spx_mem_t *mem_sw; /**< Perceptual signal memory */ - spx_word32_t *pi_gain; - spx_word16_t *exc_rms; - spx_word16_t *innov_rms_save; /**< If non-NULL, innovation is copied here */ - -#ifndef DISABLE_VBR - float vbr_quality; /**< Quality setting for VBR encoding */ - int vbr_enabled; /**< 1 for enabling VBR, 0 otherwise */ - spx_int32_t vbr_max; /**< Max bit-rate allowed in VBR mode (total) */ - spx_int32_t vbr_max_high; /**< Max bit-rate allowed in VBR mode for the high-band */ - spx_int32_t abr_enabled; /**< ABR setting (in bps), 0 if off */ - float abr_drift; - float abr_drift2; - float abr_count; - int vad_enabled; /**< 1 for enabling VAD, 0 otherwise */ - float relative_quality; -#endif /* #ifndef DISABLE_VBR */ - - int encode_submode; - const SpeexSubmode * const *submodes; - int submodeID; - int submodeSelect; - int complexity; - spx_int32_t sampling_rate; - -} SBEncState; - - -/**Structure representing the full state of the sub-band decoder*/ -typedef struct SBDecState { - const SpeexMode *mode; /**< Pointer to the mode (containing for vtable info) */ - void *st_low; /**< State of the low-band (narrowband) encoder */ - int full_frame_size; - int frame_size; - int subframeSize; - int nbSubframes; - int lpcSize; - int first; - spx_int32_t sampling_rate; - int lpc_enh_enabled; - - char *stack; - spx_word16_t *g0_mem, *g1_mem; - - spx_word16_t *excBuf; - spx_lsp_t *old_qlsp; - spx_coef_t *interp_qlpc; - - spx_mem_t *mem_sp; - spx_word32_t *pi_gain; - spx_word16_t *exc_rms; - spx_word16_t *innov_save; /** If non-NULL, innovation is copied here */ - - spx_word16_t last_ener; - spx_int32_t seed; - - int encode_submode; - const SpeexSubmode * const *submodes; - int submodeID; -} SBDecState; - - -/**Initializes encoder state*/ -void *sb_encoder_init(const SpeexMode *m); - -/**De-allocates encoder state resources*/ -void sb_encoder_destroy(void *state); - -/**Encodes one frame*/ -int sb_encode(void *state, void *in, SpeexBits *bits); - - -/**Initializes decoder state*/ -void *sb_decoder_init(const SpeexMode *m); - -/**De-allocates decoder state resources*/ -void sb_decoder_destroy(void *state); - -/**Decodes one frame*/ -int sb_decode(void *state, SpeexBits *bits, void *out); - -int sb_encoder_ctl(void *state, int request, void *ptr); - -int sb_decoder_ctl(void *state, int request, void *ptr); - -#endif diff --git a/drivers/speex/scal.c b/drivers/speex/scal.c deleted file mode 100644 index 056aa62b56..0000000000 --- a/drivers/speex/scal.c +++ /dev/null @@ -1,289 +0,0 @@ -/* Copyright (C) 2006-2008 CSIRO, Jean-Marc Valin, Xiph.Org Foundation - - File: scal.c - Shaped comb-allpass filter for channel decorrelation - - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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. -*/ - -/* -The algorithm implemented here is described in: - -* J.-M. Valin, Perceptually-Motivated Nonlinear Channel Decorrelation For - Stereo Acoustic Echo Cancellation, Accepted for Joint Workshop on - Handsfree Speech Communication and Microphone Arrays (HSCMA), 2008. - http://people.xiph.org/~jm/papers/valin_hscma2008.pdf - -*/ - - -#include "config.h" - - -#include "speex/speex_echo.h" -#include "vorbis_psy.h" -#include "arch.h" -#include "os_support.h" -#include "smallft.h" -#include <math.h> -#include <stdlib.h> - -#define ALLPASS_ORDER 20 - -struct SpeexDecorrState_ { - int rate; - int channels; - int frame_size; -#ifdef VORBIS_PSYCHO - VorbisPsy *psy; - struct drft_lookup lookup; - float *wola_mem; - float *curve; -#endif - float *vorbis_win; - int seed; - float *y; - - /* Per-channel stuff */ - float *buff; - float (*ring)[ALLPASS_ORDER]; - int *ringID; - int *order; - float *alpha; -}; - - - -EXPORT SpeexDecorrState *speex_decorrelate_new(int rate, int channels, int frame_size) -{ - int i, ch; - SpeexDecorrState *st = speex_alloc(sizeof(SpeexDecorrState)); - st->rate = rate; - st->channels = channels; - st->frame_size = frame_size; -#ifdef VORBIS_PSYCHO - st->psy = vorbis_psy_init(rate, 2*frame_size); - spx_drft_init(&st->lookup, 2*frame_size); - st->wola_mem = speex_alloc(frame_size*sizeof(float)); - st->curve = speex_alloc(frame_size*sizeof(float)); -#endif - st->y = speex_alloc(frame_size*sizeof(float)); - - st->buff = speex_alloc(channels*2*frame_size*sizeof(float)); - st->ringID = speex_alloc(channels*sizeof(int)); - st->order = speex_alloc(channels*sizeof(int)); - st->alpha = speex_alloc(channels*sizeof(float)); - st->ring = speex_alloc(channels*ALLPASS_ORDER*sizeof(float)); - - /*FIXME: The +20 is there only as a kludge for ALL_PASS_OLA*/ - st->vorbis_win = speex_alloc((2*frame_size+20)*sizeof(float)); - for (i=0;i<2*frame_size;i++) - st->vorbis_win[i] = sin(.5*SPEEX_PI* sin(SPEEX_PI*i/(2*frame_size))*sin(SPEEX_PI*i/(2*frame_size)) ); - st->seed = rand(); - - for (ch=0;ch<channels;ch++) - { - for (i=0;i<ALLPASS_ORDER;i++) - st->ring[ch][i] = 0; - st->ringID[ch] = 0; - st->alpha[ch] = 0; - st->order[ch] = 10; - } - return st; -} - -static float uni_rand(int *seed) -{ - const unsigned int jflone = 0x3f800000; - const unsigned int jflmsk = 0x007fffff; - union {int i; float f;} ran; - *seed = 1664525 * *seed + 1013904223; - ran.i = jflone | (jflmsk & *seed); - ran.f -= 1.5; - return 2*ran.f; -} - -static unsigned int irand(int *seed) -{ - *seed = 1664525 * *seed + 1013904223; - return ((unsigned int)*seed)>>16; -} - - -EXPORT void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_int16_t *out, int strength) -{ - int ch; - float amount; - - if (strength<0) - strength = 0; - if (strength>100) - strength = 100; - - amount = .01*strength; - for (ch=0;ch<st->channels;ch++) - { - int i; - int N=2*st->frame_size; - float beta, beta2; - float *x; - float max_alpha = 0; - - float *buff; - float *ring; - int ringID; - int order; - float alpha; - - buff = st->buff+ch*2*st->frame_size; - ring = st->ring[ch]; - ringID = st->ringID[ch]; - order = st->order[ch]; - alpha = st->alpha[ch]; - - for (i=0;i<st->frame_size;i++) - buff[i] = buff[i+st->frame_size]; - for (i=0;i<st->frame_size;i++) - buff[i+st->frame_size] = in[i*st->channels+ch]; - - x = buff+st->frame_size; - beta = 1.-.3*amount*amount; - if (amount>1) - beta = 1-sqrt(.4*amount); - else - beta = 1-0.63246*amount; - if (beta<0) - beta = 0; - - beta2 = beta; - for (i=0;i<st->frame_size;i++) - { - st->y[i] = alpha*(x[i-ALLPASS_ORDER+order]-beta*x[i-ALLPASS_ORDER+order-1])*st->vorbis_win[st->frame_size+i+order] - + x[i-ALLPASS_ORDER]*st->vorbis_win[st->frame_size+i] - - alpha*(ring[ringID] - - beta*ring[ringID+1>=order?0:ringID+1]); - ring[ringID++]=st->y[i]; - st->y[i] *= st->vorbis_win[st->frame_size+i]; - if (ringID>=order) - ringID=0; - } - order = order+(irand(&st->seed)%3)-1; - if (order < 5) - order = 5; - if (order > 10) - order = 10; - /*order = 5+(irand(&st->seed)%6);*/ - max_alpha = pow(.96+.04*(amount-1),order); - if (max_alpha > .98/(1.+beta2)) - max_alpha = .98/(1.+beta2); - - alpha = alpha + .4*uni_rand(&st->seed); - if (alpha > max_alpha) - alpha = max_alpha; - if (alpha < -max_alpha) - alpha = -max_alpha; - for (i=0;i<ALLPASS_ORDER;i++) - ring[i] = 0; - ringID = 0; - for (i=0;i<st->frame_size;i++) - { - float tmp = alpha*(x[i-ALLPASS_ORDER+order]-beta*x[i-ALLPASS_ORDER+order-1])*st->vorbis_win[i+order] - + x[i-ALLPASS_ORDER]*st->vorbis_win[i] - - alpha*(ring[ringID] - - beta*ring[ringID+1>=order?0:ringID+1]); - ring[ringID++]=tmp; - tmp *= st->vorbis_win[i]; - if (ringID>=order) - ringID=0; - st->y[i] += tmp; - } - -#ifdef VORBIS_PSYCHO - float frame[N]; - float scale = 1./N; - for (i=0;i<2*st->frame_size;i++) - frame[i] = buff[i]; - //float coef = .5*0.78130; - float coef = SPEEX_PI*0.075063 * 0.93763 * amount * .8 * 0.707; - compute_curve(st->psy, buff, st->curve); - for (i=1;i<st->frame_size;i++) - { - float x1,x2; - float gain; - do { - x1 = uni_rand(&st->seed); - x2 = uni_rand(&st->seed); - } while (x1*x1+x2*x2 > 1.); - gain = coef*sqrt(.1+st->curve[i]); - frame[2*i-1] = gain*x1; - frame[2*i] = gain*x2; - } - frame[0] = coef*uni_rand(&st->seed)*sqrt(.1+st->curve[0]); - frame[2*st->frame_size-1] = coef*uni_rand(&st->seed)*sqrt(.1+st->curve[st->frame_size-1]); - spx_drft_backward(&st->lookup,frame); - for (i=0;i<2*st->frame_size;i++) - frame[i] *= st->vorbis_win[i]; -#endif - - for (i=0;i<st->frame_size;i++) - { -#ifdef VORBIS_PSYCHO - float tmp = st->y[i] + frame[i] + st->wola_mem[i]; - st->wola_mem[i] = frame[i+st->frame_size]; -#else - float tmp = st->y[i]; -#endif - if (tmp>32767) - tmp = 32767; - if (tmp < -32767) - tmp = -32767; - out[i*st->channels+ch] = tmp; - } - - st->ringID[ch] = ringID; - st->order[ch] = order; - st->alpha[ch] = alpha; - - } -} - -EXPORT void speex_decorrelate_destroy(SpeexDecorrState *st) -{ -#ifdef VORBIS_PSYCHO - vorbis_psy_destroy(st->psy); - speex_free(st->wola_mem); - speex_free(st->curve); -#endif - speex_free(st->buff); - speex_free(st->ring); - speex_free(st->ringID); - speex_free(st->alpha); - speex_free(st->vorbis_win); - speex_free(st->order); - speex_free(st->y); - speex_free(st); -} diff --git a/drivers/speex/smallft.c b/drivers/speex/smallft.c deleted file mode 100644 index bf87ec4d01..0000000000 --- a/drivers/speex/smallft.c +++ /dev/null @@ -1,1261 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * - * by the XIPHOPHORUS Company http://www.xiph.org/ * - * * - ******************************************************************** - - function: *unnormalized* fft transform - last mod: $Id: smallft.c,v 1.19 2003/10/08 05:12:37 jm Exp $ - - ********************************************************************/ - -/* FFT implementation from OggSquish, minus cosine transforms, - * minus all but radix 2/4 case. In Vorbis we only need this - * cut-down version. - * - * To do more than just power-of-two sized vectors, see the full - * version I wrote for NetLib. - * - * Note that the packing is a little strange; rather than the FFT r/i - * packing following R_0, I_n, R_1, I_1, R_2, I_2 ... R_n-1, I_n-1, - * it follows R_0, R_1, I_1, R_2, I_2 ... R_n-1, I_n-1, I_n like the - * FORTRAN version - */ - - -#include "config.h" - - -#include <math.h> -#include "smallft.h" -#include "arch.h" -#include "os_support.h" - -static void drfti1(int n, float *wa, int *ifac){ - static int ntryh[4] = { 4,2,3,5 }; - static float tpi = 6.28318530717958648f; - float arg,argh,argld,fi; - int ntry=0,i,j=-1; - int k1, l1, l2, ib; - int ld, ii, ip, is, nq, nr; - int ido, ipm, nfm1; - int nl=n; - int nf=0; - - L101: - j++; - if (j < 4) - ntry=ntryh[j]; - else - ntry+=2; - - L104: - nq=nl/ntry; - nr=nl-ntry*nq; - if (nr!=0) goto L101; - - nf++; - ifac[nf+1]=ntry; - nl=nq; - if(ntry!=2)goto L107; - if(nf==1)goto L107; - - for (i=1;i<nf;i++){ - ib=nf-i+1; - ifac[ib+1]=ifac[ib]; - } - ifac[2] = 2; - - L107: - if(nl!=1)goto L104; - ifac[0]=n; - ifac[1]=nf; - argh=tpi/n; - is=0; - nfm1=nf-1; - l1=1; - - if(nfm1==0)return; - - for (k1=0;k1<nfm1;k1++){ - ip=ifac[k1+2]; - ld=0; - l2=l1*ip; - ido=n/l2; - ipm=ip-1; - - for (j=0;j<ipm;j++){ - ld+=l1; - i=is; - argld=(float)ld*argh; - fi=0.f; - for (ii=2;ii<ido;ii+=2){ - fi+=1.f; - arg=fi*argld; - wa[i++]=cos(arg); - wa[i++]=sin(arg); - } - is+=ido; - } - l1=l2; - } -} - -static void fdrffti(int n, float *wsave, int *ifac){ - - if (n == 1) return; - drfti1(n, wsave+n, ifac); -} - -static void dradf2(int ido,int l1,float *cc,float *ch,float *wa1){ - int i,k; - float ti2,tr2; - int t0,t1,t2,t3,t4,t5,t6; - - t1=0; - t0=(t2=l1*ido); - t3=ido<<1; - for(k=0;k<l1;k++){ - ch[t1<<1]=cc[t1]+cc[t2]; - ch[(t1<<1)+t3-1]=cc[t1]-cc[t2]; - t1+=ido; - t2+=ido; - } - - if(ido<2)return; - if(ido==2)goto L105; - - t1=0; - t2=t0; - for(k=0;k<l1;k++){ - t3=t2; - t4=(t1<<1)+(ido<<1); - t5=t1; - t6=t1+t1; - for(i=2;i<ido;i+=2){ - t3+=2; - t4-=2; - t5+=2; - t6+=2; - tr2=wa1[i-2]*cc[t3-1]+wa1[i-1]*cc[t3]; - ti2=wa1[i-2]*cc[t3]-wa1[i-1]*cc[t3-1]; - ch[t6]=cc[t5]+ti2; - ch[t4]=ti2-cc[t5]; - ch[t6-1]=cc[t5-1]+tr2; - ch[t4-1]=cc[t5-1]-tr2; - } - t1+=ido; - t2+=ido; - } - - if(ido%2==1)return; - - L105: - t3=(t2=(t1=ido)-1); - t2+=t0; - for(k=0;k<l1;k++){ - ch[t1]=-cc[t2]; - ch[t1-1]=cc[t3]; - t1+=ido<<1; - t2+=ido; - t3+=ido; - } -} - -static void dradf4(int ido,int l1,float *cc,float *ch,float *wa1, - float *wa2,float *wa3){ - static float hsqt2 = .70710678118654752f; - int i,k,t0,t1,t2,t3,t4,t5,t6; - float ci2,ci3,ci4,cr2,cr3,cr4,ti1,ti2,ti3,ti4,tr1,tr2,tr3,tr4; - t0=l1*ido; - - t1=t0; - t4=t1<<1; - t2=t1+(t1<<1); - t3=0; - - for(k=0;k<l1;k++){ - tr1=cc[t1]+cc[t2]; - tr2=cc[t3]+cc[t4]; - - ch[t5=t3<<2]=tr1+tr2; - ch[(ido<<2)+t5-1]=tr2-tr1; - ch[(t5+=(ido<<1))-1]=cc[t3]-cc[t4]; - ch[t5]=cc[t2]-cc[t1]; - - t1+=ido; - t2+=ido; - t3+=ido; - t4+=ido; - } - - if(ido<2)return; - if(ido==2)goto L105; - - - t1=0; - for(k=0;k<l1;k++){ - t2=t1; - t4=t1<<2; - t5=(t6=ido<<1)+t4; - for(i=2;i<ido;i+=2){ - t3=(t2+=2); - t4+=2; - t5-=2; - - t3+=t0; - cr2=wa1[i-2]*cc[t3-1]+wa1[i-1]*cc[t3]; - ci2=wa1[i-2]*cc[t3]-wa1[i-1]*cc[t3-1]; - t3+=t0; - cr3=wa2[i-2]*cc[t3-1]+wa2[i-1]*cc[t3]; - ci3=wa2[i-2]*cc[t3]-wa2[i-1]*cc[t3-1]; - t3+=t0; - cr4=wa3[i-2]*cc[t3-1]+wa3[i-1]*cc[t3]; - ci4=wa3[i-2]*cc[t3]-wa3[i-1]*cc[t3-1]; - - tr1=cr2+cr4; - tr4=cr4-cr2; - ti1=ci2+ci4; - ti4=ci2-ci4; - - ti2=cc[t2]+ci3; - ti3=cc[t2]-ci3; - tr2=cc[t2-1]+cr3; - tr3=cc[t2-1]-cr3; - - ch[t4-1]=tr1+tr2; - ch[t4]=ti1+ti2; - - ch[t5-1]=tr3-ti4; - ch[t5]=tr4-ti3; - - ch[t4+t6-1]=ti4+tr3; - ch[t4+t6]=tr4+ti3; - - ch[t5+t6-1]=tr2-tr1; - ch[t5+t6]=ti1-ti2; - } - t1+=ido; - } - if(ido&1)return; - - L105: - - t2=(t1=t0+ido-1)+(t0<<1); - t3=ido<<2; - t4=ido; - t5=ido<<1; - t6=ido; - - for(k=0;k<l1;k++){ - ti1=-hsqt2*(cc[t1]+cc[t2]); - tr1=hsqt2*(cc[t1]-cc[t2]); - - ch[t4-1]=tr1+cc[t6-1]; - ch[t4+t5-1]=cc[t6-1]-tr1; - - ch[t4]=ti1-cc[t1+t0]; - ch[t4+t5]=ti1+cc[t1+t0]; - - t1+=ido; - t2+=ido; - t4+=t3; - t6+=ido; - } -} - -static void dradfg(int ido,int ip,int l1,int idl1,float *cc,float *c1, - float *c2,float *ch,float *ch2,float *wa){ - - static float tpi=6.283185307179586f; - int idij,ipph,i,j,k,l,ic,ik,is; - int t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10; - float dc2,ai1,ai2,ar1,ar2,ds2; - int nbd; - float dcp,arg,dsp,ar1h,ar2h; - int idp2,ipp2; - - arg=tpi/(float)ip; - dcp=cos(arg); - dsp=sin(arg); - ipph=(ip+1)>>1; - ipp2=ip; - idp2=ido; - nbd=(ido-1)>>1; - t0=l1*ido; - t10=ip*ido; - - if(ido==1)goto L119; - for(ik=0;ik<idl1;ik++)ch2[ik]=c2[ik]; - - t1=0; - for(j=1;j<ip;j++){ - t1+=t0; - t2=t1; - for(k=0;k<l1;k++){ - ch[t2]=c1[t2]; - t2+=ido; - } - } - - is=-ido; - t1=0; - if(nbd>l1){ - for(j=1;j<ip;j++){ - t1+=t0; - is+=ido; - t2= -ido+t1; - for(k=0;k<l1;k++){ - idij=is-1; - t2+=ido; - t3=t2; - for(i=2;i<ido;i+=2){ - idij+=2; - t3+=2; - ch[t3-1]=wa[idij-1]*c1[t3-1]+wa[idij]*c1[t3]; - ch[t3]=wa[idij-1]*c1[t3]-wa[idij]*c1[t3-1]; - } - } - } - }else{ - - for(j=1;j<ip;j++){ - is+=ido; - idij=is-1; - t1+=t0; - t2=t1; - for(i=2;i<ido;i+=2){ - idij+=2; - t2+=2; - t3=t2; - for(k=0;k<l1;k++){ - ch[t3-1]=wa[idij-1]*c1[t3-1]+wa[idij]*c1[t3]; - ch[t3]=wa[idij-1]*c1[t3]-wa[idij]*c1[t3-1]; - t3+=ido; - } - } - } - } - - t1=0; - t2=ipp2*t0; - if(nbd<l1){ - for(j=1;j<ipph;j++){ - t1+=t0; - t2-=t0; - t3=t1; - t4=t2; - for(i=2;i<ido;i+=2){ - t3+=2; - t4+=2; - t5=t3-ido; - t6=t4-ido; - for(k=0;k<l1;k++){ - t5+=ido; - t6+=ido; - c1[t5-1]=ch[t5-1]+ch[t6-1]; - c1[t6-1]=ch[t5]-ch[t6]; - c1[t5]=ch[t5]+ch[t6]; - c1[t6]=ch[t6-1]-ch[t5-1]; - } - } - } - }else{ - for(j=1;j<ipph;j++){ - t1+=t0; - t2-=t0; - t3=t1; - t4=t2; - for(k=0;k<l1;k++){ - t5=t3; - t6=t4; - for(i=2;i<ido;i+=2){ - t5+=2; - t6+=2; - c1[t5-1]=ch[t5-1]+ch[t6-1]; - c1[t6-1]=ch[t5]-ch[t6]; - c1[t5]=ch[t5]+ch[t6]; - c1[t6]=ch[t6-1]-ch[t5-1]; - } - t3+=ido; - t4+=ido; - } - } - } - -L119: - for(ik=0;ik<idl1;ik++)c2[ik]=ch2[ik]; - - t1=0; - t2=ipp2*idl1; - for(j=1;j<ipph;j++){ - t1+=t0; - t2-=t0; - t3=t1-ido; - t4=t2-ido; - for(k=0;k<l1;k++){ - t3+=ido; - t4+=ido; - c1[t3]=ch[t3]+ch[t4]; - c1[t4]=ch[t4]-ch[t3]; - } - } - - ar1=1.f; - ai1=0.f; - t1=0; - t2=ipp2*idl1; - t3=(ip-1)*idl1; - for(l=1;l<ipph;l++){ - t1+=idl1; - t2-=idl1; - ar1h=dcp*ar1-dsp*ai1; - ai1=dcp*ai1+dsp*ar1; - ar1=ar1h; - t4=t1; - t5=t2; - t6=t3; - t7=idl1; - - for(ik=0;ik<idl1;ik++){ - ch2[t4++]=c2[ik]+ar1*c2[t7++]; - ch2[t5++]=ai1*c2[t6++]; - } - - dc2=ar1; - ds2=ai1; - ar2=ar1; - ai2=ai1; - - t4=idl1; - t5=(ipp2-1)*idl1; - for(j=2;j<ipph;j++){ - t4+=idl1; - t5-=idl1; - - ar2h=dc2*ar2-ds2*ai2; - ai2=dc2*ai2+ds2*ar2; - ar2=ar2h; - - t6=t1; - t7=t2; - t8=t4; - t9=t5; - for(ik=0;ik<idl1;ik++){ - ch2[t6++]+=ar2*c2[t8++]; - ch2[t7++]+=ai2*c2[t9++]; - } - } - } - - t1=0; - for(j=1;j<ipph;j++){ - t1+=idl1; - t2=t1; - for(ik=0;ik<idl1;ik++)ch2[ik]+=c2[t2++]; - } - - if(ido<l1)goto L132; - - t1=0; - t2=0; - for(k=0;k<l1;k++){ - t3=t1; - t4=t2; - for(i=0;i<ido;i++)cc[t4++]=ch[t3++]; - t1+=ido; - t2+=t10; - } - - goto L135; - - L132: - for(i=0;i<ido;i++){ - t1=i; - t2=i; - for(k=0;k<l1;k++){ - cc[t2]=ch[t1]; - t1+=ido; - t2+=t10; - } - } - - L135: - t1=0; - t2=ido<<1; - t3=0; - t4=ipp2*t0; - for(j=1;j<ipph;j++){ - - t1+=t2; - t3+=t0; - t4-=t0; - - t5=t1; - t6=t3; - t7=t4; - - for(k=0;k<l1;k++){ - cc[t5-1]=ch[t6]; - cc[t5]=ch[t7]; - t5+=t10; - t6+=ido; - t7+=ido; - } - } - - if(ido==1)return; - if(nbd<l1)goto L141; - - t1=-ido; - t3=0; - t4=0; - t5=ipp2*t0; - for(j=1;j<ipph;j++){ - t1+=t2; - t3+=t2; - t4+=t0; - t5-=t0; - t6=t1; - t7=t3; - t8=t4; - t9=t5; - for(k=0;k<l1;k++){ - for(i=2;i<ido;i+=2){ - ic=idp2-i; - cc[i+t7-1]=ch[i+t8-1]+ch[i+t9-1]; - cc[ic+t6-1]=ch[i+t8-1]-ch[i+t9-1]; - cc[i+t7]=ch[i+t8]+ch[i+t9]; - cc[ic+t6]=ch[i+t9]-ch[i+t8]; - } - t6+=t10; - t7+=t10; - t8+=ido; - t9+=ido; - } - } - return; - - L141: - - t1=-ido; - t3=0; - t4=0; - t5=ipp2*t0; - for(j=1;j<ipph;j++){ - t1+=t2; - t3+=t2; - t4+=t0; - t5-=t0; - for(i=2;i<ido;i+=2){ - t6=idp2+t1-i; - t7=i+t3; - t8=i+t4; - t9=i+t5; - for(k=0;k<l1;k++){ - cc[t7-1]=ch[t8-1]+ch[t9-1]; - cc[t6-1]=ch[t8-1]-ch[t9-1]; - cc[t7]=ch[t8]+ch[t9]; - cc[t6]=ch[t9]-ch[t8]; - t6+=t10; - t7+=t10; - t8+=ido; - t9+=ido; - } - } - } -} - -static void drftf1(int n,float *c,float *ch,float *wa,int *ifac){ - int i,k1,l1,l2; - int na,kh,nf; - int ip,iw,ido,idl1,ix2,ix3; - - nf=ifac[1]; - na=1; - l2=n; - iw=n; - - for(k1=0;k1<nf;k1++){ - kh=nf-k1; - ip=ifac[kh+1]; - l1=l2/ip; - ido=n/l2; - idl1=ido*l1; - iw-=(ip-1)*ido; - na=1-na; - - if(ip!=4)goto L102; - - ix2=iw+ido; - ix3=ix2+ido; - if(na!=0) - dradf4(ido,l1,ch,c,wa+iw-1,wa+ix2-1,wa+ix3-1); - else - dradf4(ido,l1,c,ch,wa+iw-1,wa+ix2-1,wa+ix3-1); - goto L110; - - L102: - if(ip!=2)goto L104; - if(na!=0)goto L103; - - dradf2(ido,l1,c,ch,wa+iw-1); - goto L110; - - L103: - dradf2(ido,l1,ch,c,wa+iw-1); - goto L110; - - L104: - if(ido==1)na=1-na; - if(na!=0)goto L109; - - dradfg(ido,ip,l1,idl1,c,c,c,ch,ch,wa+iw-1); - na=1; - goto L110; - - L109: - dradfg(ido,ip,l1,idl1,ch,ch,ch,c,c,wa+iw-1); - na=0; - - L110: - l2=l1; - } - - if(na==1)return; - - for(i=0;i<n;i++)c[i]=ch[i]; -} - -static void dradb2(int ido,int l1,float *cc,float *ch,float *wa1){ - int i,k,t0,t1,t2,t3,t4,t5,t6; - float ti2,tr2; - - t0=l1*ido; - - t1=0; - t2=0; - t3=(ido<<1)-1; - for(k=0;k<l1;k++){ - ch[t1]=cc[t2]+cc[t3+t2]; - ch[t1+t0]=cc[t2]-cc[t3+t2]; - t2=(t1+=ido)<<1; - } - - if(ido<2)return; - if(ido==2)goto L105; - - t1=0; - t2=0; - for(k=0;k<l1;k++){ - t3=t1; - t5=(t4=t2)+(ido<<1); - t6=t0+t1; - for(i=2;i<ido;i+=2){ - t3+=2; - t4+=2; - t5-=2; - t6+=2; - ch[t3-1]=cc[t4-1]+cc[t5-1]; - tr2=cc[t4-1]-cc[t5-1]; - ch[t3]=cc[t4]-cc[t5]; - ti2=cc[t4]+cc[t5]; - ch[t6-1]=wa1[i-2]*tr2-wa1[i-1]*ti2; - ch[t6]=wa1[i-2]*ti2+wa1[i-1]*tr2; - } - t2=(t1+=ido)<<1; - } - - if(ido%2==1)return; - -L105: - t1=ido-1; - t2=ido-1; - for(k=0;k<l1;k++){ - ch[t1]=cc[t2]+cc[t2]; - ch[t1+t0]=-(cc[t2+1]+cc[t2+1]); - t1+=ido; - t2+=ido<<1; - } -} - -static void dradb3(int ido,int l1,float *cc,float *ch,float *wa1, - float *wa2){ - static float taur = -.5f; - static float taui = .8660254037844386f; - int i,k,t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10; - float ci2,ci3,di2,di3,cr2,cr3,dr2,dr3,ti2,tr2; - t0=l1*ido; - - t1=0; - t2=t0<<1; - t3=ido<<1; - t4=ido+(ido<<1); - t5=0; - for(k=0;k<l1;k++){ - tr2=cc[t3-1]+cc[t3-1]; - cr2=cc[t5]+(taur*tr2); - ch[t1]=cc[t5]+tr2; - ci3=taui*(cc[t3]+cc[t3]); - ch[t1+t0]=cr2-ci3; - ch[t1+t2]=cr2+ci3; - t1+=ido; - t3+=t4; - t5+=t4; - } - - if(ido==1)return; - - t1=0; - t3=ido<<1; - for(k=0;k<l1;k++){ - t7=t1+(t1<<1); - t6=(t5=t7+t3); - t8=t1; - t10=(t9=t1+t0)+t0; - - for(i=2;i<ido;i+=2){ - t5+=2; - t6-=2; - t7+=2; - t8+=2; - t9+=2; - t10+=2; - tr2=cc[t5-1]+cc[t6-1]; - cr2=cc[t7-1]+(taur*tr2); - ch[t8-1]=cc[t7-1]+tr2; - ti2=cc[t5]-cc[t6]; - ci2=cc[t7]+(taur*ti2); - ch[t8]=cc[t7]+ti2; - cr3=taui*(cc[t5-1]-cc[t6-1]); - ci3=taui*(cc[t5]+cc[t6]); - dr2=cr2-ci3; - dr3=cr2+ci3; - di2=ci2+cr3; - di3=ci2-cr3; - ch[t9-1]=wa1[i-2]*dr2-wa1[i-1]*di2; - ch[t9]=wa1[i-2]*di2+wa1[i-1]*dr2; - ch[t10-1]=wa2[i-2]*dr3-wa2[i-1]*di3; - ch[t10]=wa2[i-2]*di3+wa2[i-1]*dr3; - } - t1+=ido; - } -} - -static void dradb4(int ido,int l1,float *cc,float *ch,float *wa1, - float *wa2,float *wa3){ - static float sqrt2=1.414213562373095f; - int i,k,t0,t1,t2,t3,t4,t5,t6,t7,t8; - float ci2,ci3,ci4,cr2,cr3,cr4,ti1,ti2,ti3,ti4,tr1,tr2,tr3,tr4; - t0=l1*ido; - - t1=0; - t2=ido<<2; - t3=0; - t6=ido<<1; - for(k=0;k<l1;k++){ - t4=t3+t6; - t5=t1; - tr3=cc[t4-1]+cc[t4-1]; - tr4=cc[t4]+cc[t4]; - tr1=cc[t3]-cc[(t4+=t6)-1]; - tr2=cc[t3]+cc[t4-1]; - ch[t5]=tr2+tr3; - ch[t5+=t0]=tr1-tr4; - ch[t5+=t0]=tr2-tr3; - ch[t5+=t0]=tr1+tr4; - t1+=ido; - t3+=t2; - } - - if(ido<2)return; - if(ido==2)goto L105; - - t1=0; - for(k=0;k<l1;k++){ - t5=(t4=(t3=(t2=t1<<2)+t6))+t6; - t7=t1; - for(i=2;i<ido;i+=2){ - t2+=2; - t3+=2; - t4-=2; - t5-=2; - t7+=2; - ti1=cc[t2]+cc[t5]; - ti2=cc[t2]-cc[t5]; - ti3=cc[t3]-cc[t4]; - tr4=cc[t3]+cc[t4]; - tr1=cc[t2-1]-cc[t5-1]; - tr2=cc[t2-1]+cc[t5-1]; - ti4=cc[t3-1]-cc[t4-1]; - tr3=cc[t3-1]+cc[t4-1]; - ch[t7-1]=tr2+tr3; - cr3=tr2-tr3; - ch[t7]=ti2+ti3; - ci3=ti2-ti3; - cr2=tr1-tr4; - cr4=tr1+tr4; - ci2=ti1+ti4; - ci4=ti1-ti4; - - ch[(t8=t7+t0)-1]=wa1[i-2]*cr2-wa1[i-1]*ci2; - ch[t8]=wa1[i-2]*ci2+wa1[i-1]*cr2; - ch[(t8+=t0)-1]=wa2[i-2]*cr3-wa2[i-1]*ci3; - ch[t8]=wa2[i-2]*ci3+wa2[i-1]*cr3; - ch[(t8+=t0)-1]=wa3[i-2]*cr4-wa3[i-1]*ci4; - ch[t8]=wa3[i-2]*ci4+wa3[i-1]*cr4; - } - t1+=ido; - } - - if(ido%2 == 1)return; - - L105: - - t1=ido; - t2=ido<<2; - t3=ido-1; - t4=ido+(ido<<1); - for(k=0;k<l1;k++){ - t5=t3; - ti1=cc[t1]+cc[t4]; - ti2=cc[t4]-cc[t1]; - tr1=cc[t1-1]-cc[t4-1]; - tr2=cc[t1-1]+cc[t4-1]; - ch[t5]=tr2+tr2; - ch[t5+=t0]=sqrt2*(tr1-ti1); - ch[t5+=t0]=ti2+ti2; - ch[t5+=t0]=-sqrt2*(tr1+ti1); - - t3+=ido; - t1+=t2; - t4+=t2; - } -} - -static void dradbg(int ido,int ip,int l1,int idl1,float *cc,float *c1, - float *c2,float *ch,float *ch2,float *wa){ - static float tpi=6.283185307179586f; - int idij,ipph,i,j,k,l,ik,is,t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10, - t11,t12; - float dc2,ai1,ai2,ar1,ar2,ds2; - int nbd; - float dcp,arg,dsp,ar1h,ar2h; - int ipp2; - - t10=ip*ido; - t0=l1*ido; - arg=tpi/(float)ip; - dcp=cos(arg); - dsp=sin(arg); - nbd=(ido-1)>>1; - ipp2=ip; - ipph=(ip+1)>>1; - if(ido<l1)goto L103; - - t1=0; - t2=0; - for(k=0;k<l1;k++){ - t3=t1; - t4=t2; - for(i=0;i<ido;i++){ - ch[t3]=cc[t4]; - t3++; - t4++; - } - t1+=ido; - t2+=t10; - } - goto L106; - - L103: - t1=0; - for(i=0;i<ido;i++){ - t2=t1; - t3=t1; - for(k=0;k<l1;k++){ - ch[t2]=cc[t3]; - t2+=ido; - t3+=t10; - } - t1++; - } - - L106: - t1=0; - t2=ipp2*t0; - t7=(t5=ido<<1); - for(j=1;j<ipph;j++){ - t1+=t0; - t2-=t0; - t3=t1; - t4=t2; - t6=t5; - for(k=0;k<l1;k++){ - ch[t3]=cc[t6-1]+cc[t6-1]; - ch[t4]=cc[t6]+cc[t6]; - t3+=ido; - t4+=ido; - t6+=t10; - } - t5+=t7; - } - - if (ido == 1)goto L116; - if(nbd<l1)goto L112; - - t1=0; - t2=ipp2*t0; - t7=0; - for(j=1;j<ipph;j++){ - t1+=t0; - t2-=t0; - t3=t1; - t4=t2; - - t7+=(ido<<1); - t8=t7; - for(k=0;k<l1;k++){ - t5=t3; - t6=t4; - t9=t8; - t11=t8; - for(i=2;i<ido;i+=2){ - t5+=2; - t6+=2; - t9+=2; - t11-=2; - ch[t5-1]=cc[t9-1]+cc[t11-1]; - ch[t6-1]=cc[t9-1]-cc[t11-1]; - ch[t5]=cc[t9]-cc[t11]; - ch[t6]=cc[t9]+cc[t11]; - } - t3+=ido; - t4+=ido; - t8+=t10; - } - } - goto L116; - - L112: - t1=0; - t2=ipp2*t0; - t7=0; - for(j=1;j<ipph;j++){ - t1+=t0; - t2-=t0; - t3=t1; - t4=t2; - t7+=(ido<<1); - t8=t7; - t9=t7; - for(i=2;i<ido;i+=2){ - t3+=2; - t4+=2; - t8+=2; - t9-=2; - t5=t3; - t6=t4; - t11=t8; - t12=t9; - for(k=0;k<l1;k++){ - ch[t5-1]=cc[t11-1]+cc[t12-1]; - ch[t6-1]=cc[t11-1]-cc[t12-1]; - ch[t5]=cc[t11]-cc[t12]; - ch[t6]=cc[t11]+cc[t12]; - t5+=ido; - t6+=ido; - t11+=t10; - t12+=t10; - } - } - } - -L116: - ar1=1.f; - ai1=0.f; - t1=0; - t9=(t2=ipp2*idl1); - t3=(ip-1)*idl1; - for(l=1;l<ipph;l++){ - t1+=idl1; - t2-=idl1; - - ar1h=dcp*ar1-dsp*ai1; - ai1=dcp*ai1+dsp*ar1; - ar1=ar1h; - t4=t1; - t5=t2; - t6=0; - t7=idl1; - t8=t3; - for(ik=0;ik<idl1;ik++){ - c2[t4++]=ch2[t6++]+ar1*ch2[t7++]; - c2[t5++]=ai1*ch2[t8++]; - } - dc2=ar1; - ds2=ai1; - ar2=ar1; - ai2=ai1; - - t6=idl1; - t7=t9-idl1; - for(j=2;j<ipph;j++){ - t6+=idl1; - t7-=idl1; - ar2h=dc2*ar2-ds2*ai2; - ai2=dc2*ai2+ds2*ar2; - ar2=ar2h; - t4=t1; - t5=t2; - t11=t6; - t12=t7; - for(ik=0;ik<idl1;ik++){ - c2[t4++]+=ar2*ch2[t11++]; - c2[t5++]+=ai2*ch2[t12++]; - } - } - } - - t1=0; - for(j=1;j<ipph;j++){ - t1+=idl1; - t2=t1; - for(ik=0;ik<idl1;ik++)ch2[ik]+=ch2[t2++]; - } - - t1=0; - t2=ipp2*t0; - for(j=1;j<ipph;j++){ - t1+=t0; - t2-=t0; - t3=t1; - t4=t2; - for(k=0;k<l1;k++){ - ch[t3]=c1[t3]-c1[t4]; - ch[t4]=c1[t3]+c1[t4]; - t3+=ido; - t4+=ido; - } - } - - if(ido==1)goto L132; - if(nbd<l1)goto L128; - - t1=0; - t2=ipp2*t0; - for(j=1;j<ipph;j++){ - t1+=t0; - t2-=t0; - t3=t1; - t4=t2; - for(k=0;k<l1;k++){ - t5=t3; - t6=t4; - for(i=2;i<ido;i+=2){ - t5+=2; - t6+=2; - ch[t5-1]=c1[t5-1]-c1[t6]; - ch[t6-1]=c1[t5-1]+c1[t6]; - ch[t5]=c1[t5]+c1[t6-1]; - ch[t6]=c1[t5]-c1[t6-1]; - } - t3+=ido; - t4+=ido; - } - } - goto L132; - - L128: - t1=0; - t2=ipp2*t0; - for(j=1;j<ipph;j++){ - t1+=t0; - t2-=t0; - t3=t1; - t4=t2; - for(i=2;i<ido;i+=2){ - t3+=2; - t4+=2; - t5=t3; - t6=t4; - for(k=0;k<l1;k++){ - ch[t5-1]=c1[t5-1]-c1[t6]; - ch[t6-1]=c1[t5-1]+c1[t6]; - ch[t5]=c1[t5]+c1[t6-1]; - ch[t6]=c1[t5]-c1[t6-1]; - t5+=ido; - t6+=ido; - } - } - } - -L132: - if(ido==1)return; - - for(ik=0;ik<idl1;ik++)c2[ik]=ch2[ik]; - - t1=0; - for(j=1;j<ip;j++){ - t2=(t1+=t0); - for(k=0;k<l1;k++){ - c1[t2]=ch[t2]; - t2+=ido; - } - } - - if(nbd>l1)goto L139; - - is= -ido-1; - t1=0; - for(j=1;j<ip;j++){ - is+=ido; - t1+=t0; - idij=is; - t2=t1; - for(i=2;i<ido;i+=2){ - t2+=2; - idij+=2; - t3=t2; - for(k=0;k<l1;k++){ - c1[t3-1]=wa[idij-1]*ch[t3-1]-wa[idij]*ch[t3]; - c1[t3]=wa[idij-1]*ch[t3]+wa[idij]*ch[t3-1]; - t3+=ido; - } - } - } - return; - - L139: - is= -ido-1; - t1=0; - for(j=1;j<ip;j++){ - is+=ido; - t1+=t0; - t2=t1; - for(k=0;k<l1;k++){ - idij=is; - t3=t2; - for(i=2;i<ido;i+=2){ - idij+=2; - t3+=2; - c1[t3-1]=wa[idij-1]*ch[t3-1]-wa[idij]*ch[t3]; - c1[t3]=wa[idij-1]*ch[t3]+wa[idij]*ch[t3-1]; - } - t2+=ido; - } - } -} - -static void drftb1(int n, float *c, float *ch, float *wa, int *ifac){ - int i,k1,l1,l2; - int na; - int nf,ip,iw,ix2,ix3,ido,idl1; - - nf=ifac[1]; - na=0; - l1=1; - iw=1; - - for(k1=0;k1<nf;k1++){ - ip=ifac[k1 + 2]; - l2=ip*l1; - ido=n/l2; - idl1=ido*l1; - if(ip!=4)goto L103; - ix2=iw+ido; - ix3=ix2+ido; - - if(na!=0) - dradb4(ido,l1,ch,c,wa+iw-1,wa+ix2-1,wa+ix3-1); - else - dradb4(ido,l1,c,ch,wa+iw-1,wa+ix2-1,wa+ix3-1); - na=1-na; - goto L115; - - L103: - if(ip!=2)goto L106; - - if(na!=0) - dradb2(ido,l1,ch,c,wa+iw-1); - else - dradb2(ido,l1,c,ch,wa+iw-1); - na=1-na; - goto L115; - - L106: - if(ip!=3)goto L109; - - ix2=iw+ido; - if(na!=0) - dradb3(ido,l1,ch,c,wa+iw-1,wa+ix2-1); - else - dradb3(ido,l1,c,ch,wa+iw-1,wa+ix2-1); - na=1-na; - goto L115; - - L109: -/* The radix five case can be translated later..... */ -/* if(ip!=5)goto L112; - - ix2=iw+ido; - ix3=ix2+ido; - ix4=ix3+ido; - if(na!=0) - dradb5(ido,l1,ch,c,wa+iw-1,wa+ix2-1,wa+ix3-1,wa+ix4-1); - else - dradb5(ido,l1,c,ch,wa+iw-1,wa+ix2-1,wa+ix3-1,wa+ix4-1); - na=1-na; - goto L115; - - L112:*/ - if(na!=0) - dradbg(ido,ip,l1,idl1,ch,ch,ch,c,c,wa+iw-1); - else - dradbg(ido,ip,l1,idl1,c,c,c,ch,ch,wa+iw-1); - if(ido==1)na=1-na; - - L115: - l1=l2; - iw+=(ip-1)*ido; - } - - if(na==0)return; - - for(i=0;i<n;i++)c[i]=ch[i]; -} - -void spx_drft_forward(struct drft_lookup *l,float *data){ - if(l->n==1)return; - drftf1(l->n,data,l->trigcache,l->trigcache+l->n,l->splitcache); -} - -void spx_drft_backward(struct drft_lookup *l,float *data){ - if (l->n==1)return; - drftb1(l->n,data,l->trigcache,l->trigcache+l->n,l->splitcache); -} - -void spx_drft_init(struct drft_lookup *l,int n) -{ - l->n=n; - l->trigcache=(float*)speex_alloc(3*n*sizeof(*l->trigcache)); - l->splitcache=(int*)speex_alloc(32*sizeof(*l->splitcache)); - fdrffti(n, l->trigcache, l->splitcache); -} - -void spx_drft_clear(struct drft_lookup *l) -{ - if(l) - { - if(l->trigcache) - speex_free(l->trigcache); - if(l->splitcache) - speex_free(l->splitcache); - } -} diff --git a/drivers/speex/smallft.h b/drivers/speex/smallft.h deleted file mode 100644 index 446e2f65b1..0000000000 --- a/drivers/speex/smallft.h +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * - * by the XIPHOPHORUS Company http://www.xiph.org/ * - * * - ******************************************************************** - - function: fft transform - last mod: $Id: smallft.h,v 1.3 2003/09/16 18:35:45 jm Exp $ - - ********************************************************************/ -/** - @file smallft.h - @brief Discrete Rotational Fourier Transform (DRFT) -*/ - -#ifndef _V_SMFT_H_ -#define _V_SMFT_H_ - - -#ifdef __cplusplus -extern "C" { -#endif - -/** Discrete Rotational Fourier Transform lookup */ -struct drft_lookup{ - int n; - float *trigcache; - int *splitcache; -}; - -extern void spx_drft_forward(struct drft_lookup *l,float *data); -extern void spx_drft_backward(struct drft_lookup *l,float *data); -extern void spx_drft_init(struct drft_lookup *l,int n); -extern void spx_drft_clear(struct drft_lookup *l); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/speex/speex.c b/drivers/speex/speex.c deleted file mode 100644 index a695728c89..0000000000 --- a/drivers/speex/speex.c +++ /dev/null @@ -1,250 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: speex.c - - Basic Speex 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. - - - Neither the name of the Xiph.org Foundation nor the names of its - 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 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. - -*/ - - -#include "config.h" - - -#include "modes.h" -#include <math.h> -#include "os_support.h" - -#ifndef NULL -#define NULL 0 -#endif - -#define MAX_IN_SAMPLES 640 - - - -EXPORT void *speex_encoder_init(const SpeexMode *mode) -{ - return mode->enc_init(mode); -} - -EXPORT void *speex_decoder_init(const SpeexMode *mode) -{ - return mode->dec_init(mode); -} - -EXPORT void speex_encoder_destroy(void *state) -{ - (*((SpeexMode**)state))->enc_destroy(state); -} - -EXPORT void speex_decoder_destroy(void *state) -{ - (*((SpeexMode**)state))->dec_destroy(state); -} - - - -int speex_encode_native(void *state, spx_word16_t *in, SpeexBits *bits) -{ - return (*((SpeexMode**)state))->enc(state, in, bits); -} - -int speex_decode_native(void *state, SpeexBits *bits, spx_word16_t *out) -{ - return (*((SpeexMode**)state))->dec(state, bits, out); -} - - - -#ifdef FIXED_POINT - -#ifndef DISABLE_FLOAT_API -EXPORT int speex_encode(void *state, float *in, SpeexBits *bits) -{ - int i; - spx_int32_t N; - spx_int16_t short_in[MAX_IN_SAMPLES]; - speex_encoder_ctl(state, SPEEX_GET_FRAME_SIZE, &N); - for (i=0;i<N;i++) - { - if (in[i]>32767.f) - short_in[i] = 32767; - else if (in[i]<-32768.f) - short_in[i] = -32768; - else - short_in[i] = (spx_int16_t)floor(.5+in[i]); - } - return (*((SpeexMode**)state))->enc(state, short_in, bits); -} -#endif /* #ifndef DISABLE_FLOAT_API */ - -EXPORT int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits) -{ - SpeexMode *mode; - mode = *(SpeexMode**)state; - return (mode)->enc(state, in, bits); -} - -#ifndef DISABLE_FLOAT_API -EXPORT int speex_decode(void *state, SpeexBits *bits, float *out) -{ - int i, ret; - spx_int32_t N; - spx_int16_t short_out[MAX_IN_SAMPLES]; - speex_decoder_ctl(state, SPEEX_GET_FRAME_SIZE, &N); - ret = (*((SpeexMode**)state))->dec(state, bits, short_out); - for (i=0;i<N;i++) - out[i] = short_out[i]; - return ret; -} -#endif /* #ifndef DISABLE_FLOAT_API */ - -EXPORT int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out) -{ - SpeexMode *mode = *(SpeexMode**)state; - return (mode)->dec(state, bits, out); -} - -#else - -EXPORT int speex_encode(void *state, float *in, SpeexBits *bits) -{ - return (*((SpeexMode**)state))->enc(state, in, bits); -} - -EXPORT int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits) -{ - int i; - spx_int32_t N; - float float_in[MAX_IN_SAMPLES]; - speex_encoder_ctl(state, SPEEX_GET_FRAME_SIZE, &N); - for (i=0;i<N;i++) - float_in[i] = in[i]; - return (*((SpeexMode**)state))->enc(state, float_in, bits); -} - -EXPORT int speex_decode(void *state, SpeexBits *bits, float *out) -{ - return (*((SpeexMode**)state))->dec(state, bits, out); -} - -EXPORT int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out) -{ - int i; - spx_int32_t N; - float float_out[MAX_IN_SAMPLES]; - int ret; - speex_decoder_ctl(state, SPEEX_GET_FRAME_SIZE, &N); - ret = (*((SpeexMode**)state))->dec(state, bits, float_out); - for (i=0;i<N;i++) - { - if (float_out[i]>32767.f) - out[i] = 32767; - else if (float_out[i]<-32768.f) - out[i] = -32768; - else - out[i] = (spx_int16_t)floor(.5+float_out[i]); - } - return ret; -} -#endif - - - -EXPORT int speex_encoder_ctl(void *state, int request, void *ptr) -{ - return (*((SpeexMode**)state))->enc_ctl(state, request, ptr); -} - -EXPORT int speex_decoder_ctl(void *state, int request, void *ptr) -{ - return (*((SpeexMode**)state))->dec_ctl(state, request, ptr); -} - - - -int nb_mode_query(const void *mode, int request, void *ptr) -{ - const SpeexNBMode *m = (const SpeexNBMode*)mode; - - switch (request) - { - case SPEEX_MODE_FRAME_SIZE: - *((int*)ptr)=m->frameSize; - break; - case SPEEX_SUBMODE_BITS_PER_FRAME: - if (*((int*)ptr)==0) - *((int*)ptr) = NB_SUBMODE_BITS+1; - else if (m->submodes[*((int*)ptr)]==NULL) - *((int*)ptr) = -1; - else - *((int*)ptr) = m->submodes[*((int*)ptr)]->bits_per_frame; - break; - default: - speex_warning_int("Unknown nb_mode_query request: ", request); - return -1; - } - return 0; -} - - - -EXPORT int speex_lib_ctl(int request, void *ptr) -{ - switch (request) - { - case SPEEX_LIB_GET_MAJOR_VERSION: - *((int*)ptr) = SPEEX_MAJOR_VERSION; - break; - case SPEEX_LIB_GET_MINOR_VERSION: - *((int*)ptr) = SPEEX_MINOR_VERSION; - break; - case SPEEX_LIB_GET_MICRO_VERSION: - *((int*)ptr) = SPEEX_MICRO_VERSION; - break; - case SPEEX_LIB_GET_EXTRA_VERSION: - *((const char**)ptr) = SPEEX_EXTRA_VERSION; - break; - case SPEEX_LIB_GET_VERSION_STRING: - *((const char**)ptr) = SPEEX_VERSION; - break; - /*case SPEEX_LIB_SET_ALLOC_FUNC: - break; - case SPEEX_LIB_GET_ALLOC_FUNC: - break; - case SPEEX_LIB_SET_FREE_FUNC: - break; - case SPEEX_LIB_GET_FREE_FUNC: - break;*/ - default: - speex_warning_int("Unknown wb_mode_query request: ", request); - return -1; - } - return 0; -} diff --git a/drivers/speex/speex.h b/drivers/speex/speex.h deleted file mode 100644 index 82ba016237..0000000000 --- a/drivers/speex/speex.h +++ /dev/null @@ -1,424 +0,0 @@ -/* Copyright (C) 2002-2006 Jean-Marc Valin*/ -/** - @file speex.h - @brief Describes the different modes of the codec -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 SPEEX_H -#define SPEEX_H -/** @defgroup Codec Speex encoder and decoder - * This is the Speex codec itself. - * @{ - */ - -#include "speex/speex_bits.h" -#include "speex/speex_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Values allowed for *ctl() requests */ - -/** Set enhancement on/off (decoder only) */ -#define SPEEX_SET_ENH 0 -/** Get enhancement state (decoder only) */ -#define SPEEX_GET_ENH 1 - -/*Would be SPEEX_SET_FRAME_SIZE, but it's (currently) invalid*/ -/** Obtain frame size used by encoder/decoder */ -#define SPEEX_GET_FRAME_SIZE 3 - -/** Set quality value */ -#define SPEEX_SET_QUALITY 4 -/** Get current quality setting */ -/* #define SPEEX_GET_QUALITY 5 -- Doesn't make much sense, does it? */ - -/** Set sub-mode to use */ -#define SPEEX_SET_MODE 6 -/** Get current sub-mode in use */ -#define SPEEX_GET_MODE 7 - -/** Set low-band sub-mode to use (wideband only)*/ -#define SPEEX_SET_LOW_MODE 8 -/** Get current low-band mode in use (wideband only)*/ -#define SPEEX_GET_LOW_MODE 9 - -/** Set high-band sub-mode to use (wideband only)*/ -#define SPEEX_SET_HIGH_MODE 10 -/** Get current high-band mode in use (wideband only)*/ -#define SPEEX_GET_HIGH_MODE 11 - -/** Set VBR on (1) or off (0) */ -#define SPEEX_SET_VBR 12 -/** Get VBR status (1 for on, 0 for off) */ -#define SPEEX_GET_VBR 13 - -/** Set quality value for VBR encoding (0-10) */ -#define SPEEX_SET_VBR_QUALITY 14 -/** Get current quality value for VBR encoding (0-10) */ -#define SPEEX_GET_VBR_QUALITY 15 - -/** Set complexity of the encoder (0-10) */ -#define SPEEX_SET_COMPLEXITY 16 -/** Get current complexity of the encoder (0-10) */ -#define SPEEX_GET_COMPLEXITY 17 - -/** Set bit-rate used by the encoder (or lower) */ -#define SPEEX_SET_BITRATE 18 -/** Get current bit-rate used by the encoder or decoder */ -#define SPEEX_GET_BITRATE 19 - -/** Define a handler function for in-band Speex request*/ -#define SPEEX_SET_HANDLER 20 - -/** Define a handler function for in-band user-defined request*/ -#define SPEEX_SET_USER_HANDLER 22 - -/** Set sampling rate used in bit-rate computation */ -#define SPEEX_SET_SAMPLING_RATE 24 -/** Get sampling rate used in bit-rate computation */ -#define SPEEX_GET_SAMPLING_RATE 25 - -/** Reset the encoder/decoder memories to zero*/ -#define SPEEX_RESET_STATE 26 - -/** Get VBR info (mostly used internally) */ -#define SPEEX_GET_RELATIVE_QUALITY 29 - -/** Set VAD status (1 for on, 0 for off) */ -#define SPEEX_SET_VAD 30 - -/** Get VAD status (1 for on, 0 for off) */ -#define SPEEX_GET_VAD 31 - -/** Set Average Bit-Rate (ABR) to n bits per seconds */ -#define SPEEX_SET_ABR 32 -/** Get Average Bit-Rate (ABR) setting (in bps) */ -#define SPEEX_GET_ABR 33 - -/** Set DTX status (1 for on, 0 for off) */ -#define SPEEX_SET_DTX 34 -/** Get DTX status (1 for on, 0 for off) */ -#define SPEEX_GET_DTX 35 - -/** Set submode encoding in each frame (1 for yes, 0 for no, setting to no breaks the standard) */ -#define SPEEX_SET_SUBMODE_ENCODING 36 -/** Get submode encoding in each frame */ -#define SPEEX_GET_SUBMODE_ENCODING 37 - -/*#define SPEEX_SET_LOOKAHEAD 38*/ -/** Returns the lookahead used by Speex */ -#define SPEEX_GET_LOOKAHEAD 39 - -/** Sets tuning for packet-loss concealment (expected loss rate) */ -#define SPEEX_SET_PLC_TUNING 40 -/** Gets tuning for PLC */ -#define SPEEX_GET_PLC_TUNING 41 - -/** Sets the max bit-rate allowed in VBR mode */ -#define SPEEX_SET_VBR_MAX_BITRATE 42 -/** Gets the max bit-rate allowed in VBR mode */ -#define SPEEX_GET_VBR_MAX_BITRATE 43 - -/** Turn on/off input/output high-pass filtering */ -#define SPEEX_SET_HIGHPASS 44 -/** Get status of input/output high-pass filtering */ -#define SPEEX_GET_HIGHPASS 45 - -/** Get "activity level" of the last decoded frame, i.e. - how much damage we cause if we remove the frame */ -#define SPEEX_GET_ACTIVITY 47 - - -/* Preserving compatibility:*/ -/** Equivalent to SPEEX_SET_ENH */ -#define SPEEX_SET_PF 0 -/** Equivalent to SPEEX_GET_ENH */ -#define SPEEX_GET_PF 1 - - - - -/* Values allowed for mode queries */ -/** Query the frame size of a mode */ -#define SPEEX_MODE_FRAME_SIZE 0 - -/** Query the size of an encoded frame for a particular sub-mode */ -#define SPEEX_SUBMODE_BITS_PER_FRAME 1 - - - -/** Get major Speex version */ -#define SPEEX_LIB_GET_MAJOR_VERSION 1 -/** Get minor Speex version */ -#define SPEEX_LIB_GET_MINOR_VERSION 3 -/** Get micro Speex version */ -#define SPEEX_LIB_GET_MICRO_VERSION 5 -/** Get extra Speex version */ -#define SPEEX_LIB_GET_EXTRA_VERSION 7 -/** Get Speex version string */ -#define SPEEX_LIB_GET_VERSION_STRING 9 - -/*#define SPEEX_LIB_SET_ALLOC_FUNC 10 -#define SPEEX_LIB_GET_ALLOC_FUNC 11 -#define SPEEX_LIB_SET_FREE_FUNC 12 -#define SPEEX_LIB_GET_FREE_FUNC 13 - -#define SPEEX_LIB_SET_WARNING_FUNC 14 -#define SPEEX_LIB_GET_WARNING_FUNC 15 -#define SPEEX_LIB_SET_ERROR_FUNC 16 -#define SPEEX_LIB_GET_ERROR_FUNC 17 -*/ - -/** Number of defined modes in Speex */ -#define SPEEX_NB_MODES 3 - -/** modeID for the defined narrowband mode */ -#define SPEEX_MODEID_NB 0 - -/** modeID for the defined wideband mode */ -#define SPEEX_MODEID_WB 1 - -/** modeID for the defined ultra-wideband mode */ -#define SPEEX_MODEID_UWB 2 - -struct SpeexMode; - - -/* Prototypes for mode function pointers */ - -/** Encoder state initialization function */ -typedef void *(*encoder_init_func)(const struct SpeexMode *mode); - -/** Encoder state destruction function */ -typedef void (*encoder_destroy_func)(void *st); - -/** Main encoding function */ -typedef int (*encode_func)(void *state, void *in, SpeexBits *bits); - -/** Function for controlling the encoder options */ -typedef int (*encoder_ctl_func)(void *state, int request, void *ptr); - -/** Decoder state initialization function */ -typedef void *(*decoder_init_func)(const struct SpeexMode *mode); - -/** Decoder state destruction function */ -typedef void (*decoder_destroy_func)(void *st); - -/** Main decoding function */ -typedef int (*decode_func)(void *state, SpeexBits *bits, void *out); - -/** Function for controlling the decoder options */ -typedef int (*decoder_ctl_func)(void *state, int request, void *ptr); - - -/** Query function for a mode */ -typedef int (*mode_query_func)(const void *mode, int request, void *ptr); - -/** Struct defining a Speex mode */ -typedef struct SpeexMode { - /** Pointer to the low-level mode data */ - const void *mode; - - /** Pointer to the mode query function */ - mode_query_func query; - - /** The name of the mode (you should not rely on this to identify the mode)*/ - const char *modeName; - - /**ID of the mode*/ - int modeID; - - /**Version number of the bitstream (incremented every time we break - bitstream compatibility*/ - int bitstream_version; - - /** Pointer to encoder initialization function */ - encoder_init_func enc_init; - - /** Pointer to encoder destruction function */ - encoder_destroy_func enc_destroy; - - /** Pointer to frame encoding function */ - encode_func enc; - - /** Pointer to decoder initialization function */ - decoder_init_func dec_init; - - /** Pointer to decoder destruction function */ - decoder_destroy_func dec_destroy; - - /** Pointer to frame decoding function */ - decode_func dec; - - /** ioctl-like requests for encoder */ - encoder_ctl_func enc_ctl; - - /** ioctl-like requests for decoder */ - decoder_ctl_func dec_ctl; - -} SpeexMode; - -/** - * Returns a handle to a newly created Speex encoder state structure. For now, - * the "mode" argument can be &nb_mode or &wb_mode . In the future, more modes - * may be added. Note that for now if you have more than one channels to - * encode, you need one state per channel. - * - * @param mode The mode to use (either speex_nb_mode or speex_wb.mode) - * @return A newly created encoder state or NULL if state allocation fails - */ -void *speex_encoder_init(const SpeexMode *mode); - -/** Frees all resources associated to an existing Speex encoder state. - * @param state Encoder state to be destroyed */ -void speex_encoder_destroy(void *state); - -/** Uses an existing encoder state to encode one frame of speech pointed to by - "in". The encoded bit-stream is saved in "bits". - @param state Encoder state - @param in Frame that will be encoded with a +-2^15 range. This data MAY be - overwritten by the encoder and should be considered uninitialised - after the call. - @param bits Bit-stream where the data will be written - @return 0 if frame needs not be transmitted (DTX only), 1 otherwise - */ -int speex_encode(void *state, float *in, SpeexBits *bits); - -/** Uses an existing encoder state to encode one frame of speech pointed to by - "in". The encoded bit-stream is saved in "bits". - @param state Encoder state - @param in Frame that will be encoded with a +-2^15 range - @param bits Bit-stream where the data will be written - @return 0 if frame needs not be transmitted (DTX only), 1 otherwise - */ -int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits); - -/** Used like the ioctl function to control the encoder parameters - * - * @param state Encoder state - * @param request ioctl-type request (one of the SPEEX_* macros) - * @param ptr Data exchanged to-from function - * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter - */ -int speex_encoder_ctl(void *state, int request, void *ptr); - - -/** Returns a handle to a newly created decoder state structure. For now, - * the mode argument can be &nb_mode or &wb_mode . In the future, more modes - * may be added. Note that for now if you have more than one channels to - * decode, you need one state per channel. - * - * @param mode Speex mode (one of speex_nb_mode or speex_wb_mode) - * @return A newly created decoder state or NULL if state allocation fails - */ -void *speex_decoder_init(const SpeexMode *mode); - -/** Frees all resources associated to an existing decoder state. - * - * @param state State to be destroyed - */ -void speex_decoder_destroy(void *state); - -/** Uses an existing decoder state to decode one frame of speech from - * bit-stream bits. The output speech is saved written to out. - * - * @param state Decoder state - * @param bits Bit-stream from which to decode the frame (NULL if the packet was lost) - * @param out Where to write the decoded frame - * @return return status (0 for no error, -1 for end of stream, -2 corrupt stream) - */ -int speex_decode(void *state, SpeexBits *bits, float *out); - -/** Uses an existing decoder state to decode one frame of speech from - * bit-stream bits. The output speech is saved written to out. - * - * @param state Decoder state - * @param bits Bit-stream from which to decode the frame (NULL if the packet was lost) - * @param out Where to write the decoded frame - * @return return status (0 for no error, -1 for end of stream, -2 corrupt stream) - */ -int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out); - -/** Used like the ioctl function to control the encoder parameters - * - * @param state Decoder state - * @param request ioctl-type request (one of the SPEEX_* macros) - * @param ptr Data exchanged to-from function - * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter - */ -int speex_decoder_ctl(void *state, int request, void *ptr); - - -/** Query function for mode information - * - * @param mode Speex mode - * @param request ioctl-type request (one of the SPEEX_* macros) - * @param ptr Data exchanged to-from function - * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter - */ -int speex_mode_query(const SpeexMode *mode, int request, void *ptr); - -/** Functions for controlling the behavior of libspeex - * @param request ioctl-type request (one of the SPEEX_LIB_* macros) - * @param ptr Data exchanged to-from function - * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter - */ -int speex_lib_ctl(int request, void *ptr); - -/** Default narrowband mode */ -extern const SpeexMode speex_nb_mode; - -/** Default wideband mode */ -extern const SpeexMode speex_wb_mode; - -/** Default "ultra-wideband" mode */ -extern const SpeexMode speex_uwb_mode; - -/** List of all modes available */ -extern const SpeexMode * const speex_mode_list[SPEEX_NB_MODES]; - -/** Obtain one of the modes available */ -const SpeexMode * speex_lib_get_mode (int mode); - -#ifndef WIN32 -/* We actually override the function in the narrowband case so that we can avoid linking in the wideband stuff */ -#define speex_lib_get_mode(mode) ((mode)==SPEEX_MODEID_NB ? &speex_nb_mode : speex_lib_get_mode (mode)) -#endif - -#ifdef __cplusplus -} -#endif - -/** @}*/ -#endif diff --git a/drivers/speex/speex_bind.cpp b/drivers/speex/speex_bind.cpp deleted file mode 100644 index d15bb3da8c..0000000000 --- a/drivers/speex/speex_bind.cpp +++ /dev/null @@ -1,64 +0,0 @@ - -#include "memory.h" -#include "speex_bind.h" -#include -#ifdef __cplusplus -extern "C" { -#endif - -void *speex_alloc (int size) { - - uint8_t * mem = (uint8_t*)memalloc(size); - for(int i=0;i<size;i++) - mem[i]=0; - return mem; -} - -void *speex_alloc_scratch (int size) { - - return memalloc(size); -} - -void *speex_realloc (void *ptr, int size) { - - return memrealloc(ptr,size); -} - -void speex_free (void *ptr) { - - memfree(ptr); -} - -void speex_free_scratch (void *ptr) { - - memfree(ptr); -} - -void _speex_fatal(const char *str, const char *file, int line) { - - _err_print_error("SPEEX ERROR",p_file,p_line,str); -} - -void speex_warning(const char *str) { - - _err_print_error("SPEEX WARNING","",0,str); -} - -void speex_warning_int(const char *str, int val) { - - _err_print_error("SPEEX WARNING INT","Value",val,str); -} - -void speex_notify(const char *str) { - - print_line(str); -} - -void _speex_putc(int ch, void *file) { - - // will not putc, no. -} - -#ifdef __cplusplus -} -#endif diff --git a/drivers/speex/speex_bind.h b/drivers/speex/speex_bind.h deleted file mode 100644 index c928430a33..0000000000 --- a/drivers/speex/speex_bind.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef SPEEX_BIND_H -#define SPEEX_BIND_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* -#define OVERRIDE_SPEEX_ALLOC -#define OVERRIDE_SPEEX_ALLOC_SCRATCH -#define OVERRIDE_SPEEX_REALLOC -#define OVERRIDE_SPEEX_FREE -#define OVERRIDE_SPEEX_FREE_SCRATCH -#define OVERRIDE_SPEEX_FATAL -#define OVERRIDE_SPEEX_WARNING -#define OVERRIDE_SPEEX_WARNING_INT -#define OVERRIDE_SPEEX_NOTIFY -#define OVERRIDE_SPEEX_PUTC - -void *speex_alloc (int size); -void *speex_alloc_scratch (int size); -void *speex_realloc (void *ptr, int size); -void speex_free (void *ptr); -void speex_free_scratch (void *ptr); -void _speex_fatal(const char *str, const char *file, int line); -void speex_warning(const char *str); -void speex_warning_int(const char *str, int val); -void speex_notify(const char *str); -void _speex_putc(int ch, void *file); - - -*/ -#define RELEASE -#define SPEEX_PI 3.14159265358979323846 - -#ifdef _MSC_VER -#define SPEEX_INLINE __inline -#else -#define SPEEX_INLINE inline -#endif - - - -#ifdef __cplusplus -} -#endif - -#endif // SPEEX_BIND_H diff --git a/drivers/speex/speex_bits.h b/drivers/speex/speex_bits.h deleted file mode 100644 index a26fb4ce0c..0000000000 --- a/drivers/speex/speex_bits.h +++ /dev/null @@ -1,174 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @file speex_bits.h - @brief Handles bit packing/unpacking -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 BITS_H -#define BITS_H -/** @defgroup SpeexBits SpeexBits: Bit-stream manipulations - * This is the structure that holds the bit-stream when encoding or decoding - * with Speex. It allows some manipulations as well. - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** Bit-packing data structure representing (part of) a bit-stream. */ -typedef struct SpeexBits { - char *chars; /**< "raw" data */ - int nbBits; /**< Total number of bits stored in the stream*/ - int charPtr; /**< Position of the byte "cursor" */ - int bitPtr; /**< Position of the bit "cursor" within the current char */ - int owner; /**< Does the struct "own" the "raw" buffer (member "chars") */ - int overflow;/**< Set to one if we try to read past the valid data */ - int buf_size;/**< Allocated size for buffer */ - int reserved1; /**< Reserved for future use */ - void *reserved2; /**< Reserved for future use */ -} SpeexBits; - -/** Initializes and allocates resources for a SpeexBits struct */ -void speex_bits_init(SpeexBits *bits); - -/** Initializes SpeexBits struct using a pre-allocated buffer*/ -void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size); - -/** Sets the bits in a SpeexBits struct to use data from an existing buffer (for decoding without copying data) */ -void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size); - -/** Frees all resources associated to a SpeexBits struct. Right now this does nothing since no resources are allocated, but this could change in the future.*/ -void speex_bits_destroy(SpeexBits *bits); - -/** Resets bits to initial value (just after initialization, erasing content)*/ -void speex_bits_reset(SpeexBits *bits); - -/** Rewind the bit-stream to the beginning (ready for read) without erasing the content */ -void speex_bits_rewind(SpeexBits *bits); - -/** Initializes the bit-stream from the data in an area of memory */ -void speex_bits_read_from(SpeexBits *bits, char *bytes, int len); - -/** Append bytes to the bit-stream - * - * @param bits Bit-stream to operate on - * @param bytes pointer to the bytes what will be appended - * @param len Number of bytes of append - */ -void speex_bits_read_whole_bytes(SpeexBits *bits, char *bytes, int len); - -/** Write the content of a bit-stream to an area of memory - * - * @param bits Bit-stream to operate on - * @param bytes Memory location where to write the bits - * @param max_len Maximum number of bytes to write (i.e. size of the "bytes" buffer) - * @return Number of bytes written to the "bytes" buffer -*/ -int speex_bits_write(SpeexBits *bits, char *bytes, int max_len); - -/** Like speex_bits_write, but writes only the complete bytes in the stream. Also removes the written bytes from the stream */ -int speex_bits_write_whole_bytes(SpeexBits *bits, char *bytes, int max_len); - -/** Append bits to the bit-stream - * @param bits Bit-stream to operate on - * @param data Value to append as integer - * @param nbBits number of bits to consider in "data" - */ -void speex_bits_pack(SpeexBits *bits, int data, int nbBits); - -/** Interpret the next bits in the bit-stream as a signed integer - * - * @param bits Bit-stream to operate on - * @param nbBits Number of bits to interpret - * @return A signed integer represented by the bits read - */ -int speex_bits_unpack_signed(SpeexBits *bits, int nbBits); - -/** Interpret the next bits in the bit-stream as an unsigned integer - * - * @param bits Bit-stream to operate on - * @param nbBits Number of bits to interpret - * @return An unsigned integer represented by the bits read - */ -unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits); - -/** Returns the number of bytes in the bit-stream, including the last one even if it is not "full" - * - * @param bits Bit-stream to operate on - * @return Number of bytes in the stream - */ -int speex_bits_nbytes(SpeexBits *bits); - -/** Same as speex_bits_unpack_unsigned, but without modifying the cursor position - * - * @param bits Bit-stream to operate on - * @param nbBits Number of bits to look for - * @return Value of the bits peeked, interpreted as unsigned - */ -unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits); - -/** Get the value of the next bit in the stream, without modifying the - * "cursor" position - * - * @param bits Bit-stream to operate on - * @return Value of the bit peeked (one bit only) - */ -int speex_bits_peek(SpeexBits *bits); - -/** Advances the position of the "bit cursor" in the stream - * - * @param bits Bit-stream to operate on - * @param n Number of bits to advance - */ -void speex_bits_advance(SpeexBits *bits, int n); - -/** Returns the number of bits remaining to be read in a stream - * - * @param bits Bit-stream to operate on - * @return Number of bits that can still be read from the stream - */ -int speex_bits_remaining(SpeexBits *bits); - -/** Insert a terminator so that the data can be sent as a packet while auto-detecting - * the number of frames in each packet - * - * @param bits Bit-stream to operate on - */ -void speex_bits_insert_terminator(SpeexBits *bits); - -#ifdef __cplusplus -} -#endif - -/* @} */ -#endif diff --git a/drivers/speex/speex_buffer.h b/drivers/speex/speex_buffer.h deleted file mode 100644 index df56f5f18b..0000000000 --- a/drivers/speex/speex_buffer.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (C) 2007 Jean-Marc Valin - - File: speex_buffer.h - This is a very simple ring buffer implementation. It is not thread-safe - so you need to do your own locking. - - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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 SPEEX_BUFFER_H -#define SPEEX_BUFFER_H - -#include "speex/speex_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct SpeexBuffer_; -typedef struct SpeexBuffer_ SpeexBuffer; - -SpeexBuffer *speex_buffer_init(int size); - -void speex_buffer_destroy(SpeexBuffer *st); - -int speex_buffer_write(SpeexBuffer *st, void *data, int len); - -int speex_buffer_writezeros(SpeexBuffer *st, int len); - -int speex_buffer_read(SpeexBuffer *st, void *data, int len); - -int speex_buffer_get_available(SpeexBuffer *st); - -int speex_buffer_resize(SpeexBuffer *st, int len); - -#ifdef __cplusplus -} -#endif - -#endif - - - - diff --git a/drivers/speex/speex_callbacks.c b/drivers/speex/speex_callbacks.c deleted file mode 100644 index 0b5eaaae68..0000000000 --- a/drivers/speex/speex_callbacks.c +++ /dev/null @@ -1,144 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File speex_callbacks.c - Callback handling and in-band signalling - - - 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 the Xiph.org Foundation nor the names of its - 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 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. - -*/ - - -#include "config.h" - - -#include <speex/speex_callbacks.h> -#include "arch.h" -#include "os_support.h" - -EXPORT int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state) -{ - int id; - SpeexCallback *callback; - /*speex_bits_advance(bits, 5);*/ - id=speex_bits_unpack_unsigned(bits, 4); - callback = callback_list+id; - - if (callback->func) - { - return callback->func(bits, state, callback->data); - } else - /*If callback is not registered, skip the right number of bits*/ - { - int adv; - if (id<2) - adv = 1; - else if (id<8) - adv = 4; - else if (id<10) - adv = 8; - else if (id<12) - adv = 16; - else if (id<14) - adv = 32; - else - adv = 64; - speex_bits_advance(bits, adv); - } - return 0; -} - -EXPORT int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data) -{ - spx_int32_t m; - m = speex_bits_unpack_unsigned(bits, 4); - speex_encoder_ctl(data, SPEEX_SET_MODE, &m); - return 0; -} - -EXPORT int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data) -{ - spx_int32_t m; - m = speex_bits_unpack_unsigned(bits, 4); - speex_encoder_ctl(data, SPEEX_SET_LOW_MODE, &m); - return 0; -} - -EXPORT int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data) -{ - spx_int32_t m; - m = speex_bits_unpack_unsigned(bits, 4); - speex_encoder_ctl(data, SPEEX_SET_HIGH_MODE, &m); - return 0; -} - -#ifndef DISABLE_VBR -EXPORT int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data) -{ - spx_int32_t vbr; - vbr = speex_bits_unpack_unsigned(bits, 1); - speex_encoder_ctl(data, SPEEX_SET_VBR, &vbr); - return 0; -} -#endif /* #ifndef DISABLE_VBR */ - -EXPORT int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data) -{ - spx_int32_t enh; - enh = speex_bits_unpack_unsigned(bits, 1); - speex_decoder_ctl(data, SPEEX_SET_ENH, &enh); - return 0; -} - -#ifndef DISABLE_VBR -EXPORT int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data) -{ - float qual; - qual = speex_bits_unpack_unsigned(bits, 4); - speex_encoder_ctl(data, SPEEX_SET_VBR_QUALITY, &qual); - return 0; -} -#endif /* #ifndef DISABLE_VBR */ - -EXPORT int speex_std_char_handler(SpeexBits *bits, void *state, void *data) -{ - unsigned char ch; - ch = speex_bits_unpack_unsigned(bits, 8); - _speex_putc(ch, data); - /*printf("speex_std_char_handler ch=%x\n", ch);*/ - return 0; -} - - - -/* Default handler for user callbacks: skip it */ -EXPORT int speex_default_user_handler(SpeexBits *bits, void *state, void *data) -{ - int req_size = speex_bits_unpack_unsigned(bits, 4); - speex_bits_advance(bits, 5+8*req_size); - return 0; -} diff --git a/drivers/speex/speex_callbacks.h b/drivers/speex/speex_callbacks.h deleted file mode 100644 index 6f450b3a3a..0000000000 --- a/drivers/speex/speex_callbacks.h +++ /dev/null @@ -1,134 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin*/ -/** - @file speex_callbacks.h - @brief Describes callback handling and in-band signalling -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 SPEEX_CALLBACKS_H -#define SPEEX_CALLBACKS_H -/** @defgroup SpeexCallbacks Various definitions for Speex callbacks supported by the decoder. - * @{ - */ - -#include "speex.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Total number of callbacks */ -#define SPEEX_MAX_CALLBACKS 16 - -/* Describes all the in-band requests */ - -/*These are 1-bit requests*/ -/** Request for perceptual enhancement (1 for on, 0 for off) */ -#define SPEEX_INBAND_ENH_REQUEST 0 -/** Reserved */ -#define SPEEX_INBAND_RESERVED1 1 - -/*These are 4-bit requests*/ -/** Request for a mode change */ -#define SPEEX_INBAND_MODE_REQUEST 2 -/** Request for a low mode change */ -#define SPEEX_INBAND_LOW_MODE_REQUEST 3 -/** Request for a high mode change */ -#define SPEEX_INBAND_HIGH_MODE_REQUEST 4 -/** Request for VBR (1 on, 0 off) */ -#define SPEEX_INBAND_VBR_QUALITY_REQUEST 5 -/** Request to be sent acknowledge */ -#define SPEEX_INBAND_ACKNOWLEDGE_REQUEST 6 -/** Request for VBR (1 for on, 0 for off) */ -#define SPEEX_INBAND_VBR_REQUEST 7 - -/*These are 8-bit requests*/ -/** Send a character in-band */ -#define SPEEX_INBAND_CHAR 8 -/** Intensity stereo information */ -#define SPEEX_INBAND_STEREO 9 - -/*These are 16-bit requests*/ -/** Transmit max bit-rate allowed */ -#define SPEEX_INBAND_MAX_BITRATE 10 - -/*These are 32-bit requests*/ -/** Acknowledge packet reception */ -#define SPEEX_INBAND_ACKNOWLEDGE 12 - -/** Callback function type */ -typedef int (*speex_callback_func)(SpeexBits *bits, void *state, void *data); - -/** Callback information */ -typedef struct SpeexCallback { - int callback_id; /**< ID associated to the callback */ - speex_callback_func func; /**< Callback handler function */ - void *data; /**< Data that will be sent to the handler */ - void *reserved1; /**< Reserved for future use */ - int reserved2; /**< Reserved for future use */ -} SpeexCallback; - -/** Handle in-band request */ -int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state); - -/** Standard handler for mode request (change mode, no questions asked) */ -int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data); - -/** Standard handler for high mode request (change high mode, no questions asked) */ -int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data); - -/** Standard handler for in-band characters (write to stderr) */ -int speex_std_char_handler(SpeexBits *bits, void *state, void *data); - -/** Default handler for user-defined requests: in this case, just ignore */ -int speex_default_user_handler(SpeexBits *bits, void *state, void *data); - - - -/** Standard handler for low mode request (change low mode, no questions asked) */ -int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data); - -/** Standard handler for VBR request (Set VBR, no questions asked) */ -int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data); - -/** Standard handler for enhancer request (Turn enhancer on/off, no questions asked) */ -int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data); - -/** Standard handler for VBR quality request (Set VBR quality, no questions asked) */ -int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data); - - -#ifdef __cplusplus -} -#endif - -/** @} */ -#endif diff --git a/drivers/speex/speex_config_types.h b/drivers/speex/speex_config_types.h deleted file mode 100644 index bd548546b0..0000000000 --- a/drivers/speex/speex_config_types.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __SPEEX_TYPES_H__ -#define __SPEEX_TYPES_H__ - -/* these are filled in by configure */ -typedef short spx_int16_t; -typedef unsigned short spx_uint16_t; -typedef int spx_int32_t; -typedef unsigned int spx_uint32_t; - -#endif - diff --git a/drivers/speex/speex_echo.h b/drivers/speex/speex_echo.h deleted file mode 100644 index 53bcd28a1a..0000000000 --- a/drivers/speex/speex_echo.h +++ /dev/null @@ -1,170 +0,0 @@ -/* Copyright (C) Jean-Marc Valin */ -/** - @file speex_echo.h - @brief Echo cancellation -*/ -/* - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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 SPEEX_ECHO_H -#define SPEEX_ECHO_H -/** @defgroup SpeexEchoState SpeexEchoState: Acoustic echo canceller - * This is the acoustic echo canceller module. - * @{ - */ -#include "speex/speex_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Obtain frame size used by the AEC */ -#define SPEEX_ECHO_GET_FRAME_SIZE 3 - -/** Set sampling rate */ -#define SPEEX_ECHO_SET_SAMPLING_RATE 24 -/** Get sampling rate */ -#define SPEEX_ECHO_GET_SAMPLING_RATE 25 - -/* Can't set window sizes */ -/** Get size of impulse response (int32) */ -#define SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE 27 - -/* Can't set window content */ -/** Get impulse response (int32[]) */ -#define SPEEX_ECHO_GET_IMPULSE_RESPONSE 29 - -/** Internal echo canceller state. Should never be accessed directly. */ -struct SpeexEchoState_; - -/** @class SpeexEchoState - * This holds the state of the echo canceller. You need one per channel. -*/ - -/** Internal echo canceller state. Should never be accessed directly. */ -typedef struct SpeexEchoState_ SpeexEchoState; - -/** Creates a new echo canceller state - * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms) - * @param filter_length Number of samples of echo to cancel (should generally correspond to 100-500 ms) - * @return Newly-created echo canceller state - */ -SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length); - -/** Creates a new multi-channel echo canceller state - * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms) - * @param filter_length Number of samples of echo to cancel (should generally correspond to 100-500 ms) - * @param nb_mic Number of microphone channels - * @param nb_speakers Number of speaker channels - * @return Newly-created echo canceller state - */ -SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_length, int nb_mic, int nb_speakers); - -/** Destroys an echo canceller state - * @param st Echo canceller state -*/ -void speex_echo_state_destroy(SpeexEchoState *st); - -/** Performs echo cancellation a frame, based on the audio sent to the speaker (no delay is added - * to playback in this form) - * - * @param st Echo canceller state - * @param rec Signal from the microphone (near end + far end echo) - * @param play Signal played to the speaker (received from far end) - * @param out Returns near-end signal with echo removed - */ -void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out); - -/** Performs echo cancellation a frame (deprecated) */ -void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out, spx_int32_t *Yout); - -/** Perform echo cancellation using internal playback buffer, which is delayed by two frames - * to account for the delay introduced by most soundcards (but it could be off!) - * @param st Echo canceller state - * @param rec Signal from the microphone (near end + far end echo) - * @param out Returns near-end signal with echo removed -*/ -void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out); - -/** Let the echo canceller know that a frame was just queued to the soundcard - * @param st Echo canceller state - * @param play Signal played to the speaker (received from far end) -*/ -void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play); - -/** Reset the echo canceller to its original state - * @param st Echo canceller state - */ -void speex_echo_state_reset(SpeexEchoState *st); - -/** Used like the ioctl function to control the echo canceller parameters - * - * @param st Echo canceller state - * @param request ioctl-type request (one of the SPEEX_ECHO_* macros) - * @param ptr Data exchanged to-from function - * @return 0 if no error, -1 if request in unknown - */ -int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr); - - - -struct SpeexDecorrState_; - -typedef struct SpeexDecorrState_ SpeexDecorrState; - - -/** Create a state for the channel decorrelation algorithm - This is useful for multi-channel echo cancellation only - * @param rate Sampling rate - * @param channels Number of channels (it's a bit pointless if you don't have at least 2) - * @param frame_size Size of the frame to process at ones (counting samples *per* channel) -*/ -SpeexDecorrState *speex_decorrelate_new(int rate, int channels, int frame_size); - -/** Remove correlation between the channels by modifying the phase and possibly - adding noise in a way that is not (or little) perceptible. - * @param st Decorrelator state - * @param in Input audio in interleaved format - * @param out Result of the decorrelation (out *may* alias in) - * @param strength How much alteration of the audio to apply from 0 to 100. -*/ -void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_int16_t *out, int strength); - -/** Destroy a Decorrelation state - * @param st State to destroy -*/ -void speex_decorrelate_destroy(SpeexDecorrState *st); - - -#ifdef __cplusplus -} -#endif - - -/** @}*/ -#endif diff --git a/drivers/speex/speex_header.c b/drivers/speex/speex_header.c deleted file mode 100644 index 2792623983..0000000000 --- a/drivers/speex/speex_header.c +++ /dev/null @@ -1,200 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: speex_header.c - Describes the Speex header - - 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 the Xiph.org Foundation nor the names of its - 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 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. - -*/ - - -#include "config.h" - - -#include "arch.h" -#include <speex/speex_header.h> -#include <speex/speex.h> -#include "os_support.h" - -#ifndef NULL -#define NULL 0 -#endif - -/** Convert little endian */ -static SPEEX_INLINE spx_int32_t le_int(spx_int32_t i) -{ -#if !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) /* || defined(BIG_ENDIAN_ENABLED) */ ) - spx_uint32_t ui, ret; - ui = i; - ret = ui>>24; - ret |= (ui>>8)&0x0000ff00; - ret |= (ui<<8)&0x00ff0000; - ret |= (ui<<24); - return ret; -#else - return i; -#endif -} - -#define ENDIAN_SWITCH(x) {x=le_int(x);} - - -/* -typedef struct SpeexHeader { - char speex_string[8]; - char speex_version[SPEEX_HEADER_VERSION_LENGTH]; - int speex_version_id; - int header_size; - int rate; - int mode; - int mode_bitstream_version; - int nb_channels; - int bitrate; - int frame_size; - int vbr; - int frames_per_packet; - int extra_headers; - int reserved1; - int reserved2; -} SpeexHeader; -*/ - -EXPORT void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const SpeexMode *m) -{ - int i; - const char *h="Speex "; - /* - strncpy(header->speex_string, "Speex ", 8); - strncpy(header->speex_version, SPEEX_VERSION, SPEEX_HEADER_VERSION_LENGTH-1); - header->speex_version[SPEEX_HEADER_VERSION_LENGTH-1]=0; - */ - for (i=0;i<8;i++) - header->speex_string[i]=h[i]; - for (i=0;i<SPEEX_HEADER_VERSION_LENGTH-1 && SPEEX_VERSION[i];i++) - header->speex_version[i]=SPEEX_VERSION[i]; - for (;i<SPEEX_HEADER_VERSION_LENGTH;i++) - header->speex_version[i]=0; - - header->speex_version_id = 1; - header->header_size = sizeof(SpeexHeader); - - header->rate = rate; - header->mode = m->modeID; - header->mode_bitstream_version = m->bitstream_version; - if (m->modeID<0) - speex_warning("This mode is meant to be used alone"); - header->nb_channels = nb_channels; - header->bitrate = -1; - speex_mode_query(m, SPEEX_MODE_FRAME_SIZE, &header->frame_size); - header->vbr = 0; - - header->frames_per_packet = 0; - header->extra_headers = 0; - header->reserved1 = 0; - header->reserved2 = 0; -} - -EXPORT char *speex_header_to_packet(SpeexHeader *header, int *size) -{ - SpeexHeader *le_header; - le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader)); - - SPEEX_COPY(le_header, header, 1); - - /*Make sure everything is now little-endian*/ - ENDIAN_SWITCH(le_header->speex_version_id); - ENDIAN_SWITCH(le_header->header_size); - ENDIAN_SWITCH(le_header->rate); - ENDIAN_SWITCH(le_header->mode); - ENDIAN_SWITCH(le_header->mode_bitstream_version); - ENDIAN_SWITCH(le_header->nb_channels); - ENDIAN_SWITCH(le_header->bitrate); - ENDIAN_SWITCH(le_header->frame_size); - ENDIAN_SWITCH(le_header->vbr); - ENDIAN_SWITCH(le_header->frames_per_packet); - ENDIAN_SWITCH(le_header->extra_headers); - - *size = sizeof(SpeexHeader); - return (char *)le_header; -} - -EXPORT SpeexHeader *speex_packet_to_header(char *packet, int size) -{ - int i; - SpeexHeader *le_header; - const char *h = "Speex "; - for (i=0;i<8;i++) - if (packet[i]!=h[i]) - { - speex_notify("This doesn't look like a Speex file"); - return NULL; - } - - /*FIXME: Do we allow larger headers?*/ - if (size < (int)sizeof(SpeexHeader)) - { - speex_notify("Speex header too small"); - return NULL; - } - - le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader)); - - SPEEX_COPY(le_header, (SpeexHeader*)packet, 1); - - /*Make sure everything is converted correctly from little-endian*/ - ENDIAN_SWITCH(le_header->speex_version_id); - ENDIAN_SWITCH(le_header->header_size); - ENDIAN_SWITCH(le_header->rate); - ENDIAN_SWITCH(le_header->mode); - ENDIAN_SWITCH(le_header->mode_bitstream_version); - ENDIAN_SWITCH(le_header->nb_channels); - ENDIAN_SWITCH(le_header->bitrate); - ENDIAN_SWITCH(le_header->frame_size); - ENDIAN_SWITCH(le_header->vbr); - ENDIAN_SWITCH(le_header->frames_per_packet); - ENDIAN_SWITCH(le_header->extra_headers); - - if (le_header->mode >= SPEEX_NB_MODES || le_header->mode < 0) - { - speex_notify("Invalid mode specified in Speex header"); - speex_free (le_header); - return NULL; - } - - if (le_header->nb_channels>2) - le_header->nb_channels = 2; - if (le_header->nb_channels<1) - le_header->nb_channels = 1; - - return le_header; - -} - -EXPORT void speex_header_free(void *ptr) -{ - speex_free(ptr); -} diff --git a/drivers/speex/speex_header.h b/drivers/speex/speex_header.h deleted file mode 100644 index f85b2496ae..0000000000 --- a/drivers/speex/speex_header.h +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @file speex_header.h - @brief Describes the Speex header -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 SPEEX_HEADER_H -#define SPEEX_HEADER_H -/** @defgroup SpeexHeader SpeexHeader: Makes it easy to write/parse an Ogg/Speex header - * This is the Speex header for the Ogg encapsulation. You don't need that if you just use RTP. - * @{ - */ - -#include "speex/speex_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct SpeexMode; - -/** Length of the Speex header identifier */ -#define SPEEX_HEADER_STRING_LENGTH 8 - -/** Maximum number of characters for encoding the Speex version number in the header */ -#define SPEEX_HEADER_VERSION_LENGTH 20 - -/** Speex header info for file-based formats */ -typedef struct SpeexHeader { - char speex_string[SPEEX_HEADER_STRING_LENGTH]; /**< Identifies a Speex bit-stream, always set to "Speex " */ - char speex_version[SPEEX_HEADER_VERSION_LENGTH]; /**< Speex version */ - spx_int32_t speex_version_id; /**< Version for Speex (for checking compatibility) */ - spx_int32_t header_size; /**< Total size of the header ( sizeof(SpeexHeader) ) */ - spx_int32_t rate; /**< Sampling rate used */ - spx_int32_t mode; /**< Mode used (0 for narrowband, 1 for wideband) */ - spx_int32_t mode_bitstream_version; /**< Version ID of the bit-stream */ - spx_int32_t nb_channels; /**< Number of channels encoded */ - spx_int32_t bitrate; /**< Bit-rate used */ - spx_int32_t frame_size; /**< Size of frames */ - spx_int32_t vbr; /**< 1 for a VBR encoding, 0 otherwise */ - spx_int32_t frames_per_packet; /**< Number of frames stored per Ogg packet */ - spx_int32_t extra_headers; /**< Number of additional headers after the comments */ - spx_int32_t reserved1; /**< Reserved for future use, must be zero */ - spx_int32_t reserved2; /**< Reserved for future use, must be zero */ -} SpeexHeader; - -/** Initializes a SpeexHeader using basic information */ -void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const struct SpeexMode *m); - -/** Creates the header packet from the header itself (mostly involves endianness conversion) */ -char *speex_header_to_packet(SpeexHeader *header, int *size); - -/** Creates a SpeexHeader from a packet */ -SpeexHeader *speex_packet_to_header(char *packet, int size); - -/** Frees the memory allocated by either speex_header_to_packet() or speex_packet_to_header() */ -void speex_header_free(void *ptr); - -#ifdef __cplusplus -} -#endif - -/** @} */ -#endif diff --git a/drivers/speex/speex_jitter.h b/drivers/speex/speex_jitter.h deleted file mode 100644 index d68674b13a..0000000000 --- a/drivers/speex/speex_jitter.h +++ /dev/null @@ -1,197 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @file speex_jitter.h - @brief Adaptive jitter buffer for Speex -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 SPEEX_JITTER_H -#define SPEEX_JITTER_H -/** @defgroup JitterBuffer JitterBuffer: Adaptive jitter buffer - * This is the jitter buffer that reorders UDP/RTP packets and adjusts the buffer size - * to maintain good quality and low latency. - * @{ - */ - -#include "speex/speex_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Generic adaptive jitter buffer state */ -struct JitterBuffer_; - -/** Generic adaptive jitter buffer state */ -typedef struct JitterBuffer_ JitterBuffer; - -/** Definition of an incoming packet */ -typedef struct _JitterBufferPacket JitterBufferPacket; - -/** Definition of an incoming packet */ -struct _JitterBufferPacket { - char *data; /**< Data bytes contained in the packet */ - spx_uint32_t len; /**< Length of the packet in bytes */ - spx_uint32_t timestamp; /**< Timestamp for the packet */ - spx_uint32_t span; /**< Time covered by the packet (same units as timestamp) */ - spx_uint16_t sequence; /**< RTP Sequence number if available (0 otherwise) */ - spx_uint32_t user_data; /**< Put whatever data you like here (it's ignored by the jitter buffer) */ -}; - -/** Packet has been retrieved */ -#define JITTER_BUFFER_OK 0 -/** Packet is lost or is late */ -#define JITTER_BUFFER_MISSING 1 -/** A "fake" packet is meant to be inserted here to increase buffering */ -#define JITTER_BUFFER_INSERTION 2 -/** There was an error in the jitter buffer */ -#define JITTER_BUFFER_INTERNAL_ERROR -1 -/** Invalid argument */ -#define JITTER_BUFFER_BAD_ARGUMENT -2 - - -/** Set minimum amount of extra buffering required (margin) */ -#define JITTER_BUFFER_SET_MARGIN 0 -/** Get minimum amount of extra buffering required (margin) */ -#define JITTER_BUFFER_GET_MARGIN 1 -/* JITTER_BUFFER_SET_AVAILABLE_COUNT wouldn't make sense */ - -/** Get the amount of available packets currently buffered */ -#define JITTER_BUFFER_GET_AVAILABLE_COUNT 3 -/** Included because of an early misspelling (will remove in next release) */ -#define JITTER_BUFFER_GET_AVALIABLE_COUNT 3 - -/** Assign a function to destroy unused packet. When setting that, the jitter - buffer no longer copies packet data. */ -#define JITTER_BUFFER_SET_DESTROY_CALLBACK 4 -/** */ -#define JITTER_BUFFER_GET_DESTROY_CALLBACK 5 - -/** Tell the jitter buffer to only adjust the delay in multiples of the step parameter provided */ -#define JITTER_BUFFER_SET_DELAY_STEP 6 -/** */ -#define JITTER_BUFFER_GET_DELAY_STEP 7 - -/** Tell the jitter buffer to only do concealment in multiples of the size parameter provided */ -#define JITTER_BUFFER_SET_CONCEALMENT_SIZE 8 -#define JITTER_BUFFER_GET_CONCEALMENT_SIZE 9 - -/** Absolute max amount of loss that can be tolerated regardless of the delay. Typical loss - should be half of that or less. */ -#define JITTER_BUFFER_SET_MAX_LATE_RATE 10 -#define JITTER_BUFFER_GET_MAX_LATE_RATE 11 - -/** Equivalent cost of one percent late packet in timestamp units */ -#define JITTER_BUFFER_SET_LATE_COST 12 -#define JITTER_BUFFER_GET_LATE_COST 13 - - -/** Initialises jitter buffer - * - * @param step_size Starting value for the size of concleanment packets and delay - adjustment steps. Can be changed at any time using JITTER_BUFFER_SET_DELAY_STEP - and JITTER_BUFFER_GET_CONCEALMENT_SIZE. - * @return Newly created jitter buffer state - */ -JitterBuffer *jitter_buffer_init(int step_size); - -/** Restores jitter buffer to its original state - * - * @param jitter Jitter buffer state - */ -void jitter_buffer_reset(JitterBuffer *jitter); - -/** Destroys jitter buffer - * - * @param jitter Jitter buffer state - */ -void jitter_buffer_destroy(JitterBuffer *jitter); - -/** Put one packet into the jitter buffer - * - * @param jitter Jitter buffer state - * @param packet Incoming packet -*/ -void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet); - -/** Get one packet from the jitter buffer - * - * @param jitter Jitter buffer state - * @param packet Returned packet - * @param desired_span Number of samples (or units) we wish to get from the buffer (no guarantee) - * @param current_timestamp Timestamp for the returned packet -*/ -int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset); - -/** Used right after jitter_buffer_get() to obtain another packet that would have the same timestamp. - * This is mainly useful for media where a single "frame" can be split into several packets. - * - * @param jitter Jitter buffer state - * @param packet Returned packet - */ -int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet); - -/** Get pointer timestamp of jitter buffer - * - * @param jitter Jitter buffer state -*/ -int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter); - -/** Advance by one tick - * - * @param jitter Jitter buffer state -*/ -void jitter_buffer_tick(JitterBuffer *jitter); - -/** Telling the jitter buffer about the remaining data in the application buffer - * @param jitter Jitter buffer state - * @param rem Amount of data buffered by the application (timestamp units) - */ -void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem); - -/** Used like the ioctl function to control the jitter buffer parameters - * - * @param jitter Jitter buffer state - * @param request ioctl-type request (one of the JITTER_BUFFER_* macros) - * @param ptr Data exchanged to-from function - * @return 0 if no error, -1 if request in unknown -*/ -int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr); - -int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset); - -/* @} */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/speex/speex_preprocess.h b/drivers/speex/speex_preprocess.h deleted file mode 100644 index f8eef2cd91..0000000000 --- a/drivers/speex/speex_preprocess.h +++ /dev/null @@ -1,219 +0,0 @@ -/* Copyright (C) 2003 Epic Games - Written by Jean-Marc Valin */ -/** - * @file speex_preprocess.h - * @brief Speex preprocessor. The preprocess can do noise suppression, - * residual echo suppression (after using the echo canceller), automatic - * gain control (AGC) and voice activity detection (VAD). -*/ -/* - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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 SPEEX_PREPROCESS_H -#define SPEEX_PREPROCESS_H -/** @defgroup SpeexPreprocessState SpeexPreprocessState: The Speex preprocessor - * This is the Speex preprocessor. The preprocess can do noise suppression, - * residual echo suppression (after using the echo canceller), automatic - * gain control (AGC) and voice activity detection (VAD). - * @{ - */ - -#include "speex/speex_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** State of the preprocessor (one per channel). Should never be accessed directly. */ -struct SpeexPreprocessState_; - -/** State of the preprocessor (one per channel). Should never be accessed directly. */ -typedef struct SpeexPreprocessState_ SpeexPreprocessState; - - -/** Creates a new preprocessing state. You MUST create one state per channel processed. - * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms). Must be - * the same value as that used for the echo canceller for residual echo cancellation to work. - * @param sampling_rate Sampling rate used for the input. - * @return Newly created preprocessor state -*/ -SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate); - -/** Destroys a preprocessor state - * @param st Preprocessor state to destroy -*/ -void speex_preprocess_state_destroy(SpeexPreprocessState *st); - -/** Preprocess a frame - * @param st Preprocessor state - * @param x Audio sample vector (in and out). Must be same size as specified in speex_preprocess_state_init(). - * @return Bool value for voice activity (1 for speech, 0 for noise/silence), ONLY if VAD turned on. -*/ -int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x); - -/** Preprocess a frame (deprecated, use speex_preprocess_run() instead)*/ -int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo); - -/** Update preprocessor state, but do not compute the output - * @param st Preprocessor state - * @param x Audio sample vector (in only). Must be same size as specified in speex_preprocess_state_init(). -*/ -void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x); - -/** Used like the ioctl function to control the preprocessor parameters - * @param st Preprocessor state - * @param request ioctl-type request (one of the SPEEX_PREPROCESS_* macros) - * @param ptr Data exchanged to-from function - * @return 0 if no error, -1 if request in unknown -*/ -int speex_preprocess_ctl(SpeexPreprocessState *st, int request, void *ptr); - - - -/** Set preprocessor denoiser state */ -#define SPEEX_PREPROCESS_SET_DENOISE 0 -/** Get preprocessor denoiser state */ -#define SPEEX_PREPROCESS_GET_DENOISE 1 - -/** Set preprocessor Automatic Gain Control state */ -#define SPEEX_PREPROCESS_SET_AGC 2 -/** Get preprocessor Automatic Gain Control state */ -#define SPEEX_PREPROCESS_GET_AGC 3 - -/** Set preprocessor Voice Activity Detection state */ -#define SPEEX_PREPROCESS_SET_VAD 4 -/** Get preprocessor Voice Activity Detection state */ -#define SPEEX_PREPROCESS_GET_VAD 5 - -/** Set preprocessor Automatic Gain Control level (float) */ -#define SPEEX_PREPROCESS_SET_AGC_LEVEL 6 -/** Get preprocessor Automatic Gain Control level (float) */ -#define SPEEX_PREPROCESS_GET_AGC_LEVEL 7 - -/** Set preprocessor dereverb state */ -#define SPEEX_PREPROCESS_SET_DEREVERB 8 -/** Get preprocessor dereverb state */ -#define SPEEX_PREPROCESS_GET_DEREVERB 9 - -/** Set preprocessor dereverb level */ -#define SPEEX_PREPROCESS_SET_DEREVERB_LEVEL 10 -/** Get preprocessor dereverb level */ -#define SPEEX_PREPROCESS_GET_DEREVERB_LEVEL 11 - -/** Set preprocessor dereverb decay */ -#define SPEEX_PREPROCESS_SET_DEREVERB_DECAY 12 -/** Get preprocessor dereverb decay */ -#define SPEEX_PREPROCESS_GET_DEREVERB_DECAY 13 - -/** Set probability required for the VAD to go from silence to voice */ -#define SPEEX_PREPROCESS_SET_PROB_START 14 -/** Get probability required for the VAD to go from silence to voice */ -#define SPEEX_PREPROCESS_GET_PROB_START 15 - -/** Set probability required for the VAD to stay in the voice state (integer percent) */ -#define SPEEX_PREPROCESS_SET_PROB_CONTINUE 16 -/** Get probability required for the VAD to stay in the voice state (integer percent) */ -#define SPEEX_PREPROCESS_GET_PROB_CONTINUE 17 - -/** Set maximum attenuation of the noise in dB (negative number) */ -#define SPEEX_PREPROCESS_SET_NOISE_SUPPRESS 18 -/** Get maximum attenuation of the noise in dB (negative number) */ -#define SPEEX_PREPROCESS_GET_NOISE_SUPPRESS 19 - -/** Set maximum attenuation of the residual echo in dB (negative number) */ -#define SPEEX_PREPROCESS_SET_ECHO_SUPPRESS 20 -/** Get maximum attenuation of the residual echo in dB (negative number) */ -#define SPEEX_PREPROCESS_GET_ECHO_SUPPRESS 21 - -/** Set maximum attenuation of the residual echo in dB when near end is active (negative number) */ -#define SPEEX_PREPROCESS_SET_ECHO_SUPPRESS_ACTIVE 22 -/** Get maximum attenuation of the residual echo in dB when near end is active (negative number) */ -#define SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE 23 - -/** Set the corresponding echo canceller state so that residual echo suppression can be performed (NULL for no residual echo suppression) */ -#define SPEEX_PREPROCESS_SET_ECHO_STATE 24 -/** Get the corresponding echo canceller state */ -#define SPEEX_PREPROCESS_GET_ECHO_STATE 25 - -/** Set maximal gain increase in dB/second (int32) */ -#define SPEEX_PREPROCESS_SET_AGC_INCREMENT 26 - -/** Get maximal gain increase in dB/second (int32) */ -#define SPEEX_PREPROCESS_GET_AGC_INCREMENT 27 - -/** Set maximal gain decrease in dB/second (int32) */ -#define SPEEX_PREPROCESS_SET_AGC_DECREMENT 28 - -/** Get maximal gain decrease in dB/second (int32) */ -#define SPEEX_PREPROCESS_GET_AGC_DECREMENT 29 - -/** Set maximal gain in dB (int32) */ -#define SPEEX_PREPROCESS_SET_AGC_MAX_GAIN 30 - -/** Get maximal gain in dB (int32) */ -#define SPEEX_PREPROCESS_GET_AGC_MAX_GAIN 31 - -/* Can't set loudness */ -/** Get loudness */ -#define SPEEX_PREPROCESS_GET_AGC_LOUDNESS 33 - -/* Can't set gain */ -/** Get current gain (int32 percent) */ -#define SPEEX_PREPROCESS_GET_AGC_GAIN 35 - -/* Can't set spectrum size */ -/** Get spectrum size for power spectrum (int32) */ -#define SPEEX_PREPROCESS_GET_PSD_SIZE 37 - -/* Can't set power spectrum */ -/** Get power spectrum (int32[] of squared values) */ -#define SPEEX_PREPROCESS_GET_PSD 39 - -/* Can't set noise size */ -/** Get spectrum size for noise estimate (int32) */ -#define SPEEX_PREPROCESS_GET_NOISE_PSD_SIZE 41 - -/* Can't set noise estimate */ -/** Get noise estimate (int32[] of squared values) */ -#define SPEEX_PREPROCESS_GET_NOISE_PSD 43 - -/* Can't set speech probability */ -/** Get speech probability in last frame (int32). */ -#define SPEEX_PREPROCESS_GET_PROB 45 - -/** Set preprocessor Automatic Gain Control level (int32) */ -#define SPEEX_PREPROCESS_SET_AGC_TARGET 46 -/** Get preprocessor Automatic Gain Control level (int32) */ -#define SPEEX_PREPROCESS_GET_AGC_TARGET 47 - -#ifdef __cplusplus -} -#endif - -/** @}*/ -#endif diff --git a/drivers/speex/speex_resampler.h b/drivers/speex/speex_resampler.h deleted file mode 100644 index 54eef8d7b8..0000000000 --- a/drivers/speex/speex_resampler.h +++ /dev/null @@ -1,340 +0,0 @@ -/* Copyright (C) 2007 Jean-Marc Valin - - File: speex_resampler.h - Resampling code - - The design goals of this code are: - - Very fast algorithm - - Low memory requirement - - Good *perceptual* quality (and not best SNR) - - 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. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - 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 SPEEX_RESAMPLER_H -#define SPEEX_RESAMPLER_H - -#ifdef OUTSIDE_SPEEX - -/********* WARNING: MENTAL SANITY ENDS HERE *************/ - -/* If the resampler is defined outside of Speex, we change the symbol names so that - there won't be any clash if linking with Speex later on. */ - -/* #define RANDOM_PREFIX your software name here */ -#ifndef RANDOM_PREFIX -#error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes" -#endif - -#define CAT_PREFIX2(a,b) a ## b -#define CAT_PREFIX(a,b) CAT_PREFIX2(a, b) - -#define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init) -#define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac) -#define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy) -#define speex_resampler_process_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_float) -#define speex_resampler_process_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_int) -#define speex_resampler_process_interleaved_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_float) -#define speex_resampler_process_interleaved_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_int) -#define speex_resampler_set_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate) -#define speex_resampler_get_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_get_rate) -#define speex_resampler_set_rate_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate_frac) -#define speex_resampler_get_ratio CAT_PREFIX(RANDOM_PREFIX,_resampler_get_ratio) -#define speex_resampler_set_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_set_quality) -#define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality) -#define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride) -#define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride) -#define speex_resampler_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_output_stride) -#define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride) -#define speex_resampler_get_input_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_latency) -#define speex_resampler_get_output_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_latency) -#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros) -#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem) -#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror) - -#define spx_int16_t short -#define spx_int32_t int -#define spx_uint16_t unsigned short -#define spx_uint32_t unsigned int - -#else /* OUTSIDE_SPEEX */ - -#include "speex/speex_types.h" - -#endif /* OUTSIDE_SPEEX */ - -#ifdef __cplusplus -extern "C" { -#endif - -#define SPEEX_RESAMPLER_QUALITY_MAX 10 -#define SPEEX_RESAMPLER_QUALITY_MIN 0 -#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4 -#define SPEEX_RESAMPLER_QUALITY_VOIP 3 -#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5 - -enum { - RESAMPLER_ERR_SUCCESS = 0, - RESAMPLER_ERR_ALLOC_FAILED = 1, - RESAMPLER_ERR_BAD_STATE = 2, - RESAMPLER_ERR_INVALID_ARG = 3, - RESAMPLER_ERR_PTR_OVERLAP = 4, - - RESAMPLER_ERR_MAX_ERROR -}; - -struct SpeexResamplerState_; -typedef struct SpeexResamplerState_ SpeexResamplerState; - -/** Create a new resampler with integer input and output rates. - * @param nb_channels Number of channels to be processed - * @param in_rate Input sampling rate (integer number of Hz). - * @param out_rate Output sampling rate (integer number of Hz). - * @param quality Resampling quality between 0 and 10, where 0 has poor quality - * and 10 has very high quality. - * @return Newly created resampler state - * @retval NULL Error: not enough memory - */ -SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, - spx_uint32_t in_rate, - spx_uint32_t out_rate, - int quality, - int *err); - -/** Create a new resampler with fractional input/output rates. The sampling - * rate ratio is an arbitrary rational number with both the numerator and - * denominator being 32-bit integers. - * @param nb_channels Number of channels to be processed - * @param ratio_num Numerator of the sampling rate ratio - * @param ratio_den Denominator of the sampling rate ratio - * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). - * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). - * @param quality Resampling quality between 0 and 10, where 0 has poor quality - * and 10 has very high quality. - * @return Newly created resampler state - * @retval NULL Error: not enough memory - */ -SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, - spx_uint32_t ratio_num, - spx_uint32_t ratio_den, - spx_uint32_t in_rate, - spx_uint32_t out_rate, - int quality, - int *err); - -/** Destroy a resampler state. - * @param st Resampler state - */ -void speex_resampler_destroy(SpeexResamplerState *st); - -/** Resample a float array. The input and output buffers must *not* overlap. - * @param st Resampler state - * @param channel_index Index of the channel to process for the multi-channel - * base (0 otherwise) - * @param in Input buffer - * @param in_len Number of input samples in the input buffer. Returns the - * number of samples processed - * @param out Output buffer - * @param out_len Size of the output buffer. Returns the number of samples written - */ -int speex_resampler_process_float(SpeexResamplerState *st, - spx_uint32_t channel_index, - const float *in, - spx_uint32_t *in_len, - float *out, - spx_uint32_t *out_len); - -/** Resample an int array. The input and output buffers must *not* overlap. - * @param st Resampler state - * @param channel_index Index of the channel to process for the multi-channel - * base (0 otherwise) - * @param in Input buffer - * @param in_len Number of input samples in the input buffer. Returns the number - * of samples processed - * @param out Output buffer - * @param out_len Size of the output buffer. Returns the number of samples written - */ -int speex_resampler_process_int(SpeexResamplerState *st, - spx_uint32_t channel_index, - const spx_int16_t *in, - spx_uint32_t *in_len, - spx_int16_t *out, - spx_uint32_t *out_len); - -/** Resample an interleaved float array. The input and output buffers must *not* overlap. - * @param st Resampler state - * @param in Input buffer - * @param in_len Number of input samples in the input buffer. Returns the number - * of samples processed. This is all per-channel. - * @param out Output buffer - * @param out_len Size of the output buffer. Returns the number of samples written. - * This is all per-channel. - */ -int speex_resampler_process_interleaved_float(SpeexResamplerState *st, - const float *in, - spx_uint32_t *in_len, - float *out, - spx_uint32_t *out_len); - -/** Resample an interleaved int array. The input and output buffers must *not* overlap. - * @param st Resampler state - * @param in Input buffer - * @param in_len Number of input samples in the input buffer. Returns the number - * of samples processed. This is all per-channel. - * @param out Output buffer - * @param out_len Size of the output buffer. Returns the number of samples written. - * This is all per-channel. - */ -int speex_resampler_process_interleaved_int(SpeexResamplerState *st, - const spx_int16_t *in, - spx_uint32_t *in_len, - spx_int16_t *out, - spx_uint32_t *out_len); - -/** Set (change) the input/output sampling rates (integer value). - * @param st Resampler state - * @param in_rate Input sampling rate (integer number of Hz). - * @param out_rate Output sampling rate (integer number of Hz). - */ -int speex_resampler_set_rate(SpeexResamplerState *st, - spx_uint32_t in_rate, - spx_uint32_t out_rate); - -/** Get the current input/output sampling rates (integer value). - * @param st Resampler state - * @param in_rate Input sampling rate (integer number of Hz) copied. - * @param out_rate Output sampling rate (integer number of Hz) copied. - */ -void speex_resampler_get_rate(SpeexResamplerState *st, - spx_uint32_t *in_rate, - spx_uint32_t *out_rate); - -/** Set (change) the input/output sampling rates and resampling ratio - * (fractional values in Hz supported). - * @param st Resampler state - * @param ratio_num Numerator of the sampling rate ratio - * @param ratio_den Denominator of the sampling rate ratio - * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). - * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). - */ -int speex_resampler_set_rate_frac(SpeexResamplerState *st, - spx_uint32_t ratio_num, - spx_uint32_t ratio_den, - spx_uint32_t in_rate, - spx_uint32_t out_rate); - -/** Get the current resampling ratio. This will be reduced to the least - * common denominator. - * @param st Resampler state - * @param ratio_num Numerator of the sampling rate ratio copied - * @param ratio_den Denominator of the sampling rate ratio copied - */ -void speex_resampler_get_ratio(SpeexResamplerState *st, - spx_uint32_t *ratio_num, - spx_uint32_t *ratio_den); - -/** Set (change) the conversion quality. - * @param st Resampler state - * @param quality Resampling quality between 0 and 10, where 0 has poor - * quality and 10 has very high quality. - */ -int speex_resampler_set_quality(SpeexResamplerState *st, - int quality); - -/** Get the conversion quality. - * @param st Resampler state - * @param quality Resampling quality between 0 and 10, where 0 has poor - * quality and 10 has very high quality. - */ -void speex_resampler_get_quality(SpeexResamplerState *st, - int *quality); - -/** Set (change) the input stride. - * @param st Resampler state - * @param stride Input stride - */ -void speex_resampler_set_input_stride(SpeexResamplerState *st, - spx_uint32_t stride); - -/** Get the input stride. - * @param st Resampler state - * @param stride Input stride copied - */ -void speex_resampler_get_input_stride(SpeexResamplerState *st, - spx_uint32_t *stride); - -/** Set (change) the output stride. - * @param st Resampler state - * @param stride Output stride - */ -void speex_resampler_set_output_stride(SpeexResamplerState *st, - spx_uint32_t stride); - -/** Get the output stride. - * @param st Resampler state copied - * @param stride Output stride - */ -void speex_resampler_get_output_stride(SpeexResamplerState *st, - spx_uint32_t *stride); - -/** Get the latency in input samples introduced by the resampler. - * @param st Resampler state - */ -int speex_resampler_get_input_latency(SpeexResamplerState *st); - -/** Get the latency in output samples introduced by the resampler. - * @param st Resampler state - */ -int speex_resampler_get_output_latency(SpeexResamplerState *st); - -/** Make sure that the first samples to go out of the resamplers don't have - * leading zeros. This is only useful before starting to use a newly created - * resampler. It is recommended to use that when resampling an audio file, as - * it will generate a file with the same length. For real-time processing, - * it is probably easier not to use this call (so that the output duration - * is the same for the first frame). - * @param st Resampler state - */ -int speex_resampler_skip_zeros(SpeexResamplerState *st); - -/** Reset a resampler so a new (unrelated) stream can be processed. - * @param st Resampler state - */ -int speex_resampler_reset_mem(SpeexResamplerState *st); - -/** Returns the English meaning for an error code - * @param err Error code - * @return English string - */ -const char *speex_resampler_strerror(int err); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/drivers/speex/speex_stereo.h b/drivers/speex/speex_stereo.h deleted file mode 100644 index a259713b82..0000000000 --- a/drivers/speex/speex_stereo.h +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin*/ -/** - @file speex_stereo.h - @brief Describes the handling for intensity stereo -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 STEREO_H -#define STEREO_H -/** @defgroup SpeexStereoState SpeexStereoState: Handling Speex stereo files - * This describes the Speex intensity stereo encoding/decoding - * @{ - */ - -#include "speex/speex_types.h" -#include "speex/speex_bits.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** If you access any of these fields directly, I'll personally come and bite you */ -typedef struct SpeexStereoState { - float balance; /**< Left/right balance info */ - float e_ratio; /**< Ratio of energies: E(left+right)/[E(left)+E(right)] */ - float smooth_left; /**< Smoothed left channel gain */ - float smooth_right; /**< Smoothed right channel gain */ - float reserved1; /**< Reserved for future use */ - float reserved2; /**< Reserved for future use */ -} SpeexStereoState; - -/** Deprecated. Use speex_stereo_state_init() instead. */ -#define SPEEX_STEREO_STATE_INIT {1,.5,1,1,0,0} - -/** Initialise/create a stereo stereo state */ -SpeexStereoState *speex_stereo_state_init(); - -/** Reset/re-initialise an already allocated stereo state */ -void speex_stereo_state_reset(SpeexStereoState *stereo); - -/** Destroy a stereo stereo state */ -void speex_stereo_state_destroy(SpeexStereoState *stereo); - -/** Transforms a stereo frame into a mono frame and stores intensity stereo info in 'bits' */ -void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits); - -/** Transforms a stereo frame into a mono frame and stores intensity stereo info in 'bits' */ -void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits); - -/** Transforms a mono frame into a stereo frame using intensity stereo info */ -void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *stereo); - -/** Transforms a mono frame into a stereo frame using intensity stereo info */ -void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *stereo); - -/** Callback handler for intensity stereo info */ -int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data); - -#ifdef __cplusplus -} -#endif - -/** @} */ -#endif diff --git a/drivers/speex/speex_types.h b/drivers/speex/speex_types.h deleted file mode 100644 index 852fed801d..0000000000 --- a/drivers/speex/speex_types.h +++ /dev/null @@ -1,126 +0,0 @@ -/* speex_types.h taken from libogg */ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: #ifdef jail to whip a few platforms into the UNIX ideal. - last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $ - - ********************************************************************/ -/** - @file speex_types.h - @brief Speex types -*/ -#ifndef _SPEEX_TYPES_H -#define _SPEEX_TYPES_H - -#if defined(_WIN32) - -# if defined(__CYGWIN__) -# include <_G_config.h> - typedef _G_int32_t spx_int32_t; - typedef _G_uint32_t spx_uint32_t; - typedef _G_int16_t spx_int16_t; - typedef _G_uint16_t spx_uint16_t; -# elif defined(__MINGW32__) - typedef short spx_int16_t; - typedef unsigned short spx_uint16_t; - typedef int spx_int32_t; - typedef unsigned int spx_uint32_t; -# elif defined(__MWERKS__) - typedef int spx_int32_t; - typedef unsigned int spx_uint32_t; - typedef short spx_int16_t; - typedef unsigned short spx_uint16_t; -# else - /* MSVC/Borland */ - typedef __int32 spx_int32_t; - typedef unsigned __int32 spx_uint32_t; - typedef __int16 spx_int16_t; - typedef unsigned __int16 spx_uint16_t; -# endif - -#elif defined(__MACOS__) - -# include <sys/types.h> - typedef SInt16 spx_int16_t; - typedef UInt16 spx_uint16_t; - typedef SInt32 spx_int32_t; - typedef UInt32 spx_uint32_t; - -#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ - -# include <sys/types.h> - typedef int16_t spx_int16_t; - typedef u_int16_t spx_uint16_t; - typedef int32_t spx_int32_t; - typedef u_int32_t spx_uint32_t; - -#elif defined(__BEOS__) - - /* Be */ -# include <inttypes.h> - typedef int16_t spx_int16_t; - typedef u_int16_t spx_uint16_t; - typedef int32_t spx_int32_t; - typedef u_int32_t spx_uint32_t; - -#elif defined (__EMX__) - - /* OS/2 GCC */ - typedef short spx_int16_t; - typedef unsigned short spx_uint16_t; - typedef int spx_int32_t; - typedef unsigned int spx_uint32_t; - -#elif defined (DJGPP) - - /* DJGPP */ - typedef short spx_int16_t; - typedef int spx_int32_t; - typedef unsigned int spx_uint32_t; - -#elif defined(R5900) - - /* PS2 EE */ - typedef int spx_int32_t; - typedef unsigned spx_uint32_t; - typedef short spx_int16_t; - -#elif defined(__SYMBIAN32__) - - /* Symbian GCC */ - typedef signed short spx_int16_t; - typedef unsigned short spx_uint16_t; - typedef signed int spx_int32_t; - typedef unsigned int spx_uint32_t; - -#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) - - typedef short spx_int16_t; - typedef unsigned short spx_uint16_t; - typedef long spx_int32_t; - typedef unsigned long spx_uint32_t; - -#elif defined(CONFIG_TI_C6X) - - typedef short spx_int16_t; - typedef unsigned short spx_uint16_t; - typedef int spx_int32_t; - typedef unsigned int spx_uint32_t; - -#else - -# include <speex/speex_config_types.h> - -#endif - -#endif /* _SPEEX_TYPES_H */ diff --git a/drivers/speex/stack_alloc.h b/drivers/speex/stack_alloc.h deleted file mode 100644 index 5264e666b0..0000000000 --- a/drivers/speex/stack_alloc.h +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @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. - - - Neither the name of the Xiph.org Foundation nor the names of its - 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 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 STACK_ALLOC_H -#define STACK_ALLOC_H - -#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 - */ - -#ifdef ENABLE_VALGRIND - -#include <valgrind/memcheck.h> - -#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1)) - -#define PUSH(stack, size, type) (VALGRIND_MAKE_NOACCESS(stack, 1000),ALIGN((stack),sizeof(type)),VALGRIND_MAKE_WRITABLE(stack, ((size)*sizeof(type))),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type)))) - -#else - -#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1)) - -#define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type)))) - -#endif - -#if defined(VAR_ARRAYS) -#define VARDECL(var) -#define ALLOC(var, size, type) type var[size] -#elif defined(USE_ALLOCA) -#define VARDECL(var) var -#define ALLOC(var, size, type) var = alloca(sizeof(type)*(size)) -#else -#define VARDECL(var) var -#define ALLOC(var, size, type) var = PUSH(stack, size, type) -#endif - - -#endif diff --git a/drivers/speex/stereo.c b/drivers/speex/stereo.c deleted file mode 100644 index 50eab222fe..0000000000 --- a/drivers/speex/stereo.c +++ /dev/null @@ -1,296 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: stereo.c - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -#include "config.h" - - -#include <speex/speex_stereo.h> -#include <speex/speex_callbacks.h> -#include "math_approx.h" -#include "vq.h" -#include <math.h> -#include "os_support.h" - -typedef struct RealSpeexStereoState { - spx_word32_t balance; /**< Left/right balance info */ - spx_word32_t e_ratio; /**< Ratio of energies: E(left+right)/[E(left)+E(right)] */ - spx_word32_t smooth_left; /**< Smoothed left channel gain */ - spx_word32_t smooth_right; /**< Smoothed right channel gain */ - spx_uint32_t reserved1; /**< Reserved for future use */ - spx_int32_t reserved2; /**< Reserved for future use */ -} RealSpeexStereoState; - - -/*float e_ratio_quant[4] = {1, 1.26, 1.587, 2};*/ -#ifndef FIXED_POINT -static const float e_ratio_quant[4] = {.25f, .315f, .397f, .5f}; -static const float e_ratio_quant_bounds[3] = {0.2825f, 0.356f, 0.4485f}; -#else -static const spx_word16_t e_ratio_quant[4] = {8192, 10332, 13009, 16384}; -static const spx_word16_t e_ratio_quant_bounds[3] = {9257, 11665, 14696}; -static const spx_word16_t balance_bounds[31] = {18, 23, 30, 38, 49, 63, 81, 104, - 134, 172, 221, 284, 364, 468, 600, 771, - 990, 1271, 1632, 2096, 2691, 3455, 4436, 5696, - 7314, 9392, 12059, 15484, 19882, 25529, 32766}; -#endif - -/* This is an ugly compatibility hack that properly resets the stereo state - In case it it compiled in fixed-point, but initialised with the deprecated - floating point static initialiser */ -#ifdef FIXED_POINT -#define COMPATIBILITY_HACK(s) do {if ((s)->reserved1 != 0xdeadbeef) speex_stereo_state_reset((SpeexStereoState*)s); } while (0); -#else -#define COMPATIBILITY_HACK(s) -#endif - -EXPORT SpeexStereoState *speex_stereo_state_init() -{ - SpeexStereoState *stereo = speex_alloc(sizeof(SpeexStereoState)); - speex_stereo_state_reset(stereo); - return stereo; -} - -EXPORT void speex_stereo_state_reset(SpeexStereoState *_stereo) -{ - RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; -#ifdef FIXED_POINT - stereo->balance = 65536; - stereo->e_ratio = 16384; - stereo->smooth_left = 16384; - stereo->smooth_right = 16384; - stereo->reserved1 = 0xdeadbeef; - stereo->reserved2 = 0; -#else - stereo->balance = 1.0f; - stereo->e_ratio = .5f; - stereo->smooth_left = 1.f; - stereo->smooth_right = 1.f; - stereo->reserved1 = 0; - stereo->reserved2 = 0; -#endif -} - -EXPORT void speex_stereo_state_destroy(SpeexStereoState *stereo) -{ - speex_free(stereo); -} - -#ifndef DISABLE_FLOAT_API -EXPORT void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits) -{ - int i, tmp; - float e_left=0, e_right=0, e_tot=0; - float balance, e_ratio; - for (i=0;i<frame_size;i++) - { - e_left += ((float)data[2*i])*data[2*i]; - e_right += ((float)data[2*i+1])*data[2*i+1]; - data[i] = .5*(((float)data[2*i])+data[2*i+1]); - e_tot += ((float)data[i])*data[i]; - } - balance=(e_left+1)/(e_right+1); - e_ratio = e_tot/(1+e_left+e_right); - - /*Quantization*/ - speex_bits_pack(bits, 14, 5); - speex_bits_pack(bits, SPEEX_INBAND_STEREO, 4); - - balance=4*log(balance); - - /*Pack sign*/ - if (balance>0) - speex_bits_pack(bits, 0, 1); - else - speex_bits_pack(bits, 1, 1); - balance=floor(.5+fabs(balance)); - if (balance>30) - balance=31; - - speex_bits_pack(bits, (int)balance, 5); - - /* FIXME: this is a hack */ - tmp=scal_quant(e_ratio*Q15_ONE, e_ratio_quant_bounds, 4); - speex_bits_pack(bits, tmp, 2); -} -#endif /* #ifndef DISABLE_FLOAT_API */ - -EXPORT void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits) -{ - int i, tmp; - spx_word32_t e_left=0, e_right=0, e_tot=0; - spx_word32_t balance, e_ratio; - spx_word32_t largest, smallest; - int balance_id; -#ifdef FIXED_POINT - int shift; -#endif - - /* In band marker */ - speex_bits_pack(bits, 14, 5); - /* Stereo marker */ - speex_bits_pack(bits, SPEEX_INBAND_STEREO, 4); - - for (i=0;i<frame_size;i++) - { - e_left += SHR32(MULT16_16(data[2*i],data[2*i]),8); - e_right += SHR32(MULT16_16(data[2*i+1],data[2*i+1]),8); -#ifdef FIXED_POINT - /* I think this is actually unbiased */ - data[i] = SHR16(data[2*i],1)+PSHR16(data[2*i+1],1); -#else - data[i] = .5*(((float)data[2*i])+data[2*i+1]); -#endif - e_tot += SHR32(MULT16_16(data[i],data[i]),8); - } - if (e_left > e_right) - { - speex_bits_pack(bits, 0, 1); - largest = e_left; - smallest = e_right; - } else { - speex_bits_pack(bits, 1, 1); - largest = e_right; - smallest = e_left; - } - - /* Balance quantization */ -#ifdef FIXED_POINT - shift = spx_ilog2(largest)-15; - largest = VSHR32(largest, shift-4); - smallest = VSHR32(smallest, shift); - balance = DIV32(largest, ADD32(smallest, 1)); - if (balance > 32767) - balance = 32767; - balance_id = scal_quant(EXTRACT16(balance), balance_bounds, 32); -#else - balance=(largest+1.)/(smallest+1.); - balance=4*log(balance); - balance_id=floor(.5+fabs(balance)); - if (balance_id>30) - balance_id=31; -#endif - - speex_bits_pack(bits, balance_id, 5); - - /* "coherence" quantisation */ -#ifdef FIXED_POINT - shift = spx_ilog2(e_tot); - e_tot = VSHR32(e_tot, shift-25); - e_left = VSHR32(e_left, shift-10); - e_right = VSHR32(e_right, shift-10); - e_ratio = DIV32(e_tot, e_left+e_right+1); -#else - e_ratio = e_tot/(1.+e_left+e_right); -#endif - - tmp=scal_quant(EXTRACT16(e_ratio), e_ratio_quant_bounds, 4); - /*fprintf (stderr, "%d %d %d %d\n", largest, smallest, balance_id, e_ratio);*/ - speex_bits_pack(bits, tmp, 2); -} - -#ifndef DISABLE_FLOAT_API -EXPORT void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *_stereo) -{ - int i; - spx_word32_t balance; - spx_word16_t e_left, e_right, e_ratio; - RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; - - COMPATIBILITY_HACK(stereo); - - balance=stereo->balance; - e_ratio=stereo->e_ratio; - - /* These two are Q14, with max value just below 2. */ - e_right = DIV32(QCONST32(1., 22), spx_sqrt(MULT16_32_Q15(e_ratio, ADD32(QCONST32(1., 16), balance)))); - e_left = SHR32(MULT16_16(spx_sqrt(balance), e_right), 8); - - for (i=frame_size-1;i>=0;i--) - { - spx_word16_t tmp=data[i]; - stereo->smooth_left = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_left, QCONST16(0.98, 15)), e_left, QCONST16(0.02, 15)), 15)); - stereo->smooth_right = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_right, QCONST16(0.98, 15)), e_right, QCONST16(0.02, 15)), 15)); - data[2*i] = (float)MULT16_16_P14(stereo->smooth_left, tmp); - data[2*i+1] = (float)MULT16_16_P14(stereo->smooth_right, tmp); - } -} -#endif /* #ifndef DISABLE_FLOAT_API */ - -EXPORT void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *_stereo) -{ - int i; - spx_word32_t balance; - spx_word16_t e_left, e_right, e_ratio; - RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; - - COMPATIBILITY_HACK(stereo); - - balance=stereo->balance; - e_ratio=stereo->e_ratio; - - /* These two are Q14, with max value just below 2. */ - e_right = DIV32(QCONST32(1., 22), spx_sqrt(MULT16_32_Q15(e_ratio, ADD32(QCONST32(1., 16), balance)))); - e_left = SHR32(MULT16_16(spx_sqrt(balance), e_right), 8); - - for (i=frame_size-1;i>=0;i--) - { - spx_int16_t tmp=data[i]; - stereo->smooth_left = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_left, QCONST16(0.98, 15)), e_left, QCONST16(0.02, 15)), 15)); - stereo->smooth_right = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_right, QCONST16(0.98, 15)), e_right, QCONST16(0.02, 15)), 15)); - data[2*i] = (spx_int16_t)MULT16_16_P14(stereo->smooth_left, tmp); - data[2*i+1] = (spx_int16_t)MULT16_16_P14(stereo->smooth_right, tmp); - } -} - -EXPORT int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data) -{ - RealSpeexStereoState *stereo; - spx_word16_t sign=1, dexp; - int tmp; - - stereo = (RealSpeexStereoState*)data; - - COMPATIBILITY_HACK(stereo); - - if (speex_bits_unpack_unsigned(bits, 1)) - sign=-1; - dexp = speex_bits_unpack_unsigned(bits, 5); -#ifndef FIXED_POINT - stereo->balance = exp(sign*.25*dexp); -#else - stereo->balance = spx_exp(MULT16_16(sign, SHL16(dexp, 9))); -#endif - tmp = speex_bits_unpack_unsigned(bits, 2); - stereo->e_ratio = e_ratio_quant[tmp]; - - return 0; -} diff --git a/drivers/speex/vbr.c b/drivers/speex/vbr.c deleted file mode 100644 index 16100e3d41..0000000000 --- a/drivers/speex/vbr.c +++ /dev/null @@ -1,275 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: vbr.c - - VBR-related routines - - 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 the Xiph.org Foundation nor the names of its - 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 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. - -*/ - - -#include "config.h" - - -#include "vbr.h" -#include <math.h> - - -#define sqr(x) ((x)*(x)) - -#define MIN_ENERGY 6000 -#define NOISE_POW .3 - -#ifndef DISABLE_VBR - -const float vbr_nb_thresh[9][11]={ - {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}, /* CNG */ - { 4.0f, 2.5f, 2.0f, 1.2f, 0.5f, 0.0f, -0.5f, -0.7f, -0.8f, -0.9f, -1.0f}, /* 2 kbps */ - {10.0f, 6.5f, 5.2f, 4.5f, 3.9f, 3.5f, 3.0f, 2.5f, 2.3f, 1.8f, 1.0f}, /* 6 kbps */ - {11.0f, 8.8f, 7.5f, 6.5f, 5.0f, 3.9f, 3.9f, 3.9f, 3.5f, 3.0f, 1.0f}, /* 8 kbps */ - {11.0f, 11.0f, 9.9f, 8.5f, 7.0f, 6.0f, 4.5f, 4.0f, 4.0f, 4.0f, 2.0f}, /* 11 kbps */ - {11.0f, 11.0f, 11.0f, 11.0f, 9.5f, 8.5f, 8.0f, 7.0f, 6.0f, 5.0f, 3.0f}, /* 15 kbps */ - {11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 9.5f, 8.5f, 7.0f, 6.0f, 5.0f}, /* 18 kbps */ - {11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 9.8f, 9.5f, 7.5f}, /* 24 kbps */ - { 7.0f, 4.5f, 3.7f, 3.0f, 2.5f, 2.0f, 1.8f, 1.5f, 1.0f, 0.0f, 0.0f} /* 4 kbps */ -}; - - -const float vbr_hb_thresh[5][11]={ - {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}, /* silence */ - {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}, /* 2 kbps */ - {11.0f, 11.0f, 9.5f, 8.5f, 7.5f, 6.0f, 5.0f, 3.9f, 3.0f, 2.0f, 1.0f}, /* 6 kbps */ - {11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 9.5f, 8.7f, 7.8f, 7.0f, 6.5f, 4.0f}, /* 10 kbps */ - {11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 9.8f, 7.5f, 5.5f} /* 18 kbps */ -}; - -const float vbr_uhb_thresh[2][11]={ - {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}, /* silence */ - { 3.9f, 2.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f} /* 2 kbps */ -}; - -void vbr_init(VBRState *vbr) -{ - int i; - - vbr->average_energy=0; - vbr->last_energy=1; - vbr->accum_sum=0; - vbr->energy_alpha=.1; - vbr->soft_pitch=0; - vbr->last_pitch_coef=0; - vbr->last_quality=0; - - vbr->noise_accum = .05*pow(MIN_ENERGY, NOISE_POW); - vbr->noise_accum_count=.05; - vbr->noise_level=vbr->noise_accum/vbr->noise_accum_count; - vbr->consec_noise=0; - - - for (i=0;i<VBR_MEMORY_SIZE;i++) - vbr->last_log_energy[i] = log(MIN_ENERGY); -} - - -/* - This function should analyse the signal and decide how critical the - coding error will be perceptually. The following factors should be - taken into account: - - -Attacks (positive energy derivative) should be coded with more bits - - -Stationary voiced segments should receive more bits - - -Segments with (very) low absolute energy should receive less bits (maybe - only shaped noise?) - - -DTX for near-zero energy? - - -Stationary fricative segments should have less bits - - -Temporal masking: when energy slope is decreasing, decrease the bit-rate - - -Decrease bit-rate for males (low pitch)? - - -(wideband only) less bits in the high-band when signal is very - non-stationary (harder to notice high-frequency noise)??? - -*/ - -float vbr_analysis(VBRState *vbr, spx_word16_t *sig, int len, int pitch, float pitch_coef) -{ - int i; - float ener=0, ener1=0, ener2=0; - float qual=7; - int va; - float log_energy; - float non_st=0; - float voicing; - float pow_ener; - - for (i=0;i<len>>1;i++) - ener1 += ((float)sig[i])*sig[i]; - - for (i=len>>1;i<len;i++) - ener2 += ((float)sig[i])*sig[i]; - ener=ener1+ener2; - - log_energy = log(ener+MIN_ENERGY); - for (i=0;i<VBR_MEMORY_SIZE;i++) - non_st += sqr(log_energy-vbr->last_log_energy[i]); - non_st = non_st/(30*VBR_MEMORY_SIZE); - if (non_st>1) - non_st=1; - - voicing = 3*(pitch_coef-.4)*fabs(pitch_coef-.4); - vbr->average_energy = (1-vbr->energy_alpha)*vbr->average_energy + vbr->energy_alpha*ener; - vbr->noise_level=vbr->noise_accum/vbr->noise_accum_count; - pow_ener = pow(ener,NOISE_POW); - if (vbr->noise_accum_count<.06 && ener>MIN_ENERGY) - vbr->noise_accum = .05*pow_ener; - - if ((voicing<.3 && non_st < .2 && pow_ener < 1.2*vbr->noise_level) - || (voicing<.3 && non_st < .05 && pow_ener < 1.5*vbr->noise_level) - || (voicing<.4 && non_st < .05 && pow_ener < 1.2*vbr->noise_level) - || (voicing<0 && non_st < .05)) - { - float tmp; - va = 0; - vbr->consec_noise++; - if (pow_ener > 3*vbr->noise_level) - tmp = 3*vbr->noise_level; - else - tmp = pow_ener; - if (vbr->consec_noise>=4) - { - vbr->noise_accum = .95*vbr->noise_accum + .05*tmp; - vbr->noise_accum_count = .95*vbr->noise_accum_count + .05; - } - } else { - va = 1; - vbr->consec_noise=0; - } - - if (pow_ener < vbr->noise_level && ener>MIN_ENERGY) - { - vbr->noise_accum = .95*vbr->noise_accum + .05*pow_ener; - vbr->noise_accum_count = .95*vbr->noise_accum_count + .05; - } - - /* Checking for very low absolute energy */ - if (ener < 30000) - { - qual -= .7; - if (ener < 10000) - qual-=.7; - if (ener < 3000) - qual-=.7; - } else { - float short_diff, long_diff; - short_diff = log((ener+1)/(1+vbr->last_energy)); - long_diff = log((ener+1)/(1+vbr->average_energy)); - /*fprintf (stderr, "%f %f\n", short_diff, long_diff);*/ - - if (long_diff<-5) - long_diff=-5; - if (long_diff>2) - long_diff=2; - - if (long_diff>0) - qual += .6*long_diff; - if (long_diff<0) - qual += .5*long_diff; - if (short_diff>0) - { - if (short_diff>5) - short_diff=5; - qual += .5*short_diff; - } - /* Checking for energy increases */ - if (ener2 > 1.6*ener1) - qual += .5; - } - vbr->last_energy = ener; - vbr->soft_pitch = .6*vbr->soft_pitch + .4*pitch_coef; - qual += 2.2*((pitch_coef-.4) + (vbr->soft_pitch-.4)); - - if (qual < vbr->last_quality) - qual = .5*qual + .5*vbr->last_quality; - if (qual<4) - qual=4; - if (qual>10) - qual=10; - - /* - if (vbr->consec_noise>=2) - qual-=1.3; - if (vbr->consec_noise>=5) - qual-=1.3; - if (vbr->consec_noise>=12) - qual-=1.3; - */ - if (vbr->consec_noise>=3) - qual=4; - - if (vbr->consec_noise) - qual -= 1.0 * (log(3.0 + vbr->consec_noise)-log(3)); - if (qual<0) - qual=0; - - if (ener<60000) - { - if (vbr->consec_noise>2) - qual-=0.5*(log(3.0 + vbr->consec_noise)-log(3)); - if (ener<10000&&vbr->consec_noise>2) - qual-=0.5*(log(3.0 + vbr->consec_noise)-log(3)); - if (qual<0) - qual=0; - qual += .3*log(.0001+ener/60000.0); - } - if (qual<-1) - qual=-1; - - /*printf ("%f %f %f %f %d\n", qual, voicing, non_st, pow_ener/(.01+vbr->noise_level), va);*/ - - vbr->last_pitch_coef = pitch_coef; - vbr->last_quality = qual; - - for (i=VBR_MEMORY_SIZE-1;i>0;i--) - vbr->last_log_energy[i] = vbr->last_log_energy[i-1]; - vbr->last_log_energy[0] = log_energy; - - /*printf ("VBR: %f %f %f %d %f\n", (float)(log_energy-log(vbr->average_energy+MIN_ENERGY)), non_st, voicing, va, vbr->noise_level);*/ - - return qual; -} - -void vbr_destroy(VBRState *vbr) -{ -} - -#endif /* #ifndef DISABLE_VBR */ diff --git a/drivers/speex/vbr.h b/drivers/speex/vbr.h deleted file mode 100644 index ff1e3e46f2..0000000000 --- a/drivers/speex/vbr.h +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @file vbr.h - @brief Variable Bit-Rate (VBR) related routines -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 VBR_H -#define VBR_H - -#include "arch.h" - -#define VBR_MEMORY_SIZE 5 - -extern const float vbr_nb_thresh[9][11]; -extern const float vbr_hb_thresh[5][11]; -extern const float vbr_uhb_thresh[2][11]; - -/** VBR state. */ -typedef struct VBRState { - float energy_alpha; - float average_energy; - float last_energy; - float last_log_energy[VBR_MEMORY_SIZE]; - float accum_sum; - float last_pitch_coef; - float soft_pitch; - float last_quality; - float noise_level; - float noise_accum; - float noise_accum_count; - int consec_noise; -} VBRState; - -void vbr_init(VBRState *vbr); - -float vbr_analysis(VBRState *vbr, spx_word16_t *sig, int len, int pitch, float pitch_coef); - -void vbr_destroy(VBRState *vbr); - -#endif diff --git a/drivers/speex/vorbis_psy.h b/drivers/speex/vorbis_psy.h deleted file mode 100644 index 6871057753..0000000000 --- a/drivers/speex/vorbis_psy.h +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright (C) 2005 Jean-Marc Valin, CSIRO, Christopher Montgomery - File: vorbis_psy.h - - 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 the Xiph.org Foundation nor the names of its - 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 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 VORBIS_PSY_H -#define VORBIS_PSY_H - -#ifdef VORBIS_PSYCHO - -#include "smallft.h" -#define P_BANDS 17 /* 62Hz to 16kHz */ -#define NOISE_COMPAND_LEVELS 40 - - -#define todB(x) ((x)>1e-13?log((x)*(x))*4.34294480f:-30) -#define fromdB(x) (exp((x)*.11512925f)) - -/* The bark scale equations are approximations, since the original - table was somewhat hand rolled. The below are chosen to have the - best possible fit to the rolled tables, thus their somewhat odd - appearance (these are more accurate and over a longer range than - the oft-quoted bark equations found in the texts I have). The - approximations are valid from 0 - 30kHz (nyquist) or so. - - all f in Hz, z in Bark */ - -#define toBARK(n) (13.1f*atan(.00074f*(n))+2.24f*atan((n)*(n)*1.85e-8f)+1e-4f*(n)) -#define fromBARK(z) (102.f*(z)-2.f*pow(z,2.f)+.4f*pow(z,3.f)+pow(1.46f,z)-1.f) - -/* Frequency to octave. We arbitrarily declare 63.5 Hz to be octave - 0.0 */ - -#define toOC(n) (log(n)*1.442695f-5.965784f) -#define fromOC(o) (exp(((o)+5.965784f)*.693147f)) - - -typedef struct { - - float noisewindowlo; - float noisewindowhi; - int noisewindowlomin; - int noisewindowhimin; - int noisewindowfixed; - float noiseoff[P_BANDS]; - float noisecompand[NOISE_COMPAND_LEVELS]; - -} VorbisPsyInfo; - - - -typedef struct { - int n; - int rate; - struct drft_lookup lookup; - VorbisPsyInfo *vi; - - float *window; - float *noiseoffset; - long *bark; - -} VorbisPsy; - - -VorbisPsy *vorbis_psy_init(int rate, int size); -void vorbis_psy_destroy(VorbisPsy *psy); -void compute_curve(VorbisPsy *psy, float *audio, float *curve); -void curve_to_lpc(VorbisPsy *psy, float *curve, float *awk1, float *awk2, int ord); - -#endif -#endif diff --git a/drivers/speex/vq.c b/drivers/speex/vq.c deleted file mode 100644 index 049e68169b..0000000000 --- a/drivers/speex/vq.c +++ /dev/null @@ -1,147 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: vq.c - Vector quantization - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -#include "config.h" - - -#include "vq.h" -#include "stack_alloc.h" -#include "arch.h" - -#ifdef _USE_SSE -#include <xmmintrin.h> -#include "vq_sse.h" -#elif defined(SHORTCUTS) && (defined(ARM4_ASM) || defined(ARM5E_ASM)) -#include "vq_arm4.h" -#elif defined(BFIN_ASM) -#include "vq_bfin.h" -#endif - - -int scal_quant(spx_word16_t in, const spx_word16_t *boundary, int entries) -{ - int i=0; - while (i<entries-1 && in>boundary[0]) - { - boundary++; - i++; - } - return i; -} - -int scal_quant32(spx_word32_t in, const spx_word32_t *boundary, int entries) -{ - int i=0; - while (i<entries-1 && in>boundary[0]) - { - boundary++; - i++; - } - return i; -} - - -#ifndef OVERRIDE_VQ_NBEST -/*Finds the indices of the n-best entries in a codebook*/ -void vq_nbest(spx_word16_t *in, const spx_word16_t *codebook, int len, int entries, spx_word32_t *E, int N, int *nbest, spx_word32_t *best_dist, char *stack) -{ - int i,j,k,used; - used = 0; - for (i=0;i<entries;i++) - { - spx_word32_t dist=0; - for (j=0;j<len;j++) - dist = MAC16_16(dist,in[j],*codebook++); -#ifdef FIXED_POINT - dist=SUB32(SHR32(E[i],1),dist); -#else - dist=.5f*E[i]-dist; -#endif - if (i<N || dist<best_dist[N-1]) - { - for (k=N-1; (k >= 1) && (k > used || dist < best_dist[k-1]); k--) - { - best_dist[k]=best_dist[k-1]; - nbest[k] = nbest[k-1]; - } - best_dist[k]=dist; - nbest[k]=i; - used++; - } - } -} -#endif - - - - -#ifndef OVERRIDE_VQ_NBEST_SIGN -/*Finds the indices of the n-best entries in a codebook with sign*/ -void vq_nbest_sign(spx_word16_t *in, const spx_word16_t *codebook, int len, int entries, spx_word32_t *E, int N, int *nbest, spx_word32_t *best_dist, char *stack) -{ - int i,j,k, sign, used; - used=0; - for (i=0;i<entries;i++) - { - spx_word32_t dist=0; - for (j=0;j<len;j++) - dist = MAC16_16(dist,in[j],*codebook++); - if (dist>0) - { - sign=0; - dist=-dist; - } else - { - sign=1; - } -#ifdef FIXED_POINT - dist = ADD32(dist,SHR32(E[i],1)); -#else - dist = ADD32(dist,.5f*E[i]); -#endif - if (i<N || dist<best_dist[N-1]) - { - for (k=N-1; (k >= 1) && (k > used || dist < best_dist[k-1]); k--) - { - best_dist[k]=best_dist[k-1]; - nbest[k] = nbest[k-1]; - } - best_dist[k]=dist; - nbest[k]=i; - used++; - if (sign) - nbest[k]+=entries; - } - } -} -#endif diff --git a/drivers/speex/vq.h b/drivers/speex/vq.h deleted file mode 100644 index 5a4ced249c..0000000000 --- a/drivers/speex/vq.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @file vq.h - @brief Vector quantization -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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 VQ_H -#define VQ_H - -#include "arch.h" - -int scal_quant(spx_word16_t in, const spx_word16_t *boundary, int entries); -int scal_quant32(spx_word32_t in, const spx_word32_t *boundary, int entries); - -#ifdef _USE_SSE -#include <xmmintrin.h> -void vq_nbest(spx_word16_t *in, const __m128 *codebook, int len, int entries, __m128 *E, int N, int *nbest, spx_word32_t *best_dist, char *stack); - -void vq_nbest_sign(spx_word16_t *in, const __m128 *codebook, int len, int entries, __m128 *E, int N, int *nbest, spx_word32_t *best_dist, char *stack); -#else -void vq_nbest(spx_word16_t *in, const spx_word16_t *codebook, int len, int entries, spx_word32_t *E, int N, int *nbest, spx_word32_t *best_dist, char *stack); - -void vq_nbest_sign(spx_word16_t *in, const spx_word16_t *codebook, int len, int entries, spx_word32_t *E, int N, int *nbest, spx_word32_t *best_dist, char *stack); -#endif - -#endif diff --git a/drivers/speex/vq_arm4.h b/drivers/speex/vq_arm4.h deleted file mode 100644 index 585b8613c5..0000000000 --- a/drivers/speex/vq_arm4.h +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (C) 2004 Jean-Marc Valin */ -/** - @file vq_arm4.h - @brief ARM4-optimized vq routine -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#define OVERRIDE_VQ_NBEST -void vq_nbest(spx_word16_t *in, const spx_word16_t *codebook, int len, int entries, spx_word32_t *E, int N, int *nbest, spx_word32_t *best_dist, char *stack) -{ - int i,j; - for (i=0;i<entries;i+=4) - { -#if 1 - spx_word32_t dist1, dist2, dist3, dist4; - int dead1, dead2, dead3, dead4, dead5, dead6, dead7, dead8; - __asm__ __volatile__ ( - "mov %0, #0 \n\t" - "mov %1, #0 \n\t" - "mov %2, #0 \n\t" - "mov %3, #0 \n\t" - "mov %10, %4 \n\t" - "add %4, %4, %4\n\t" - ".vqloop%=:\n\t" - "ldrsh %7, [%5], #2 \n\t" - "ldrsh %8, [%6] \n\t" - "mov %9, %6 \n\t" - "mla %0, %7, %8, %0 \n\t" - "ldrsh %8, [%9, %4]! \n\t" - "mla %1, %7, %8, %1 \n\t" - "ldrsh %8, [%9, %4]!\n\t" - "mla %2, %7, %8, %2 \n\t" - "ldrsh %8, [%9, %4]! \n\t" - "mla %3, %7, %8, %3 \n\t" - "subs %10, %10, #1 \n\t" - "add %6, %6, #2 \n\t" - "bne .vqloop%=" - : "=r" (dist1), "=r" (dist2), "=r" (dist3), "=r" (dist4), - "=r" (dead1), "=r" (dead2), "=r" (codebook), "=r" (dead4), - "=r" (dead5), "=r" (dead6), "=r" (dead7) - : "4" (len), "5" (in), "6" (codebook) - : "cc"); -#else -dist1=dist2=dist3=dist4=0; - /* spx_word32_t dist1=0; - spx_word32_t dist2=0; - spx_word32_t dist3=0; - spx_word32_t dist4=0;*/ - for (j=0;j<2;j++) - { - const spx_word16_t *code = codebook; - dist1 = MAC16_16(dist1,in[j],*code); - code += len; - dist2 = MAC16_16(dist2,in[j],*code); - code += len; - dist3 = MAC16_16(dist3,in[j],*code); - code += len; - dist4 = MAC16_16(dist4,in[j],*code); - codebook++; - } -#endif - dist1=SUB32(SHR(*E++,1),dist1); - if (dist1<*best_dist || i==0) - { - *best_dist=dist1; - *nbest=i; - } - dist2=SUB32(SHR(*E++,1),dist2); - if (dist2<*best_dist) - { - *best_dist=dist2; - *nbest=i+1; - } - dist3=SUB32(SHR(*E++,1),dist3); - if (dist3<*best_dist) - { - *best_dist=dist3; - *nbest=i+2; - } - dist4=SUB32(SHR(*E++,1),dist4); - if (dist4<*best_dist) - { - *best_dist=dist4; - *nbest=i+3; - } - codebook += 3*len; - } -} diff --git a/drivers/speex/vq_bfin.h b/drivers/speex/vq_bfin.h deleted file mode 100644 index 2cc9ea5f17..0000000000 --- a/drivers/speex/vq_bfin.h +++ /dev/null @@ -1,107 +0,0 @@ -/* Copyright (C) 2005 Analog Devices */ -/** - @file vq_bfin.h - @author Jean-Marc Valin - @brief Blackfin-optimized vq routine -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#define OVERRIDE_VQ_NBEST -void vq_nbest(spx_word16_t *in, const spx_word16_t *codebook, int len, int entries, spx_word32_t *E, int N, int *nbest, spx_word32_t *best_dist, char *stack) -{ - if (N==1) - { - best_dist[0] = 2147483647; - { - spx_word32_t dist; - __asm__ __volatile__ - ( - "LC0 = %8;\n\t" - "R2 = 0;\n\t" - "I0 = %6;\n\t" - "B0 = %6;\n\t" - "L0 = %9;\n\t" - "LOOP entries_loop%= LC0;\n\t" - "LOOP_BEGIN entries_loop%=;\n\t" - "%0 = [%4++];\n\t" - "%0 >>= 1;\n\t" - "A0 = %0;\n\t" - "R0.L = W[%1++%7] || R1.L = W[I0++];\n\t" - "LOOP vq_loop%= LC1 = %5;\n\t" - "LOOP_BEGIN vq_loop%=;\n\t" - "%0 = (A0 -= R0.L*R1.L) (IS) || R0.L = W[%1++%7] || R1.L = W[I0++];\n\t" - "LOOP_END vq_loop%=;\n\t" - "%0 = (A0 -= R0.L*R1.L) (IS);\n\t" - "cc = %0 < %2;\n\t" - "if cc %2 = %0;\n\t" - "if cc %3 = R2;\n\t" - "R2 += 1;\n\t" - "LOOP_END entries_loop%=;\n\t" - : "=&D" (dist), "=&a" (codebook), "=&d" (best_dist[0]), "=&d" (nbest[0]), "=&a" (E) - : "a" (len-1), "a" (in), "a" (2), "d" (entries), "d" (len<<1), "1" (codebook), "4" (E), "2" (best_dist[0]), "3" (nbest[0]) - : "R0", "R1", "R2", "I0", "L0", "B0", "A0", "cc", "memory" - ); - } - } else { - int i,k,used; - used = 0; - for (i=0;i<entries;i++) - { - spx_word32_t dist; - __asm__ - ( - "%0 >>= 1;\n\t" - "A0 = %0;\n\t" - "I0 = %3;\n\t" - "L0 = 0;\n\t" - "R0.L = W[%1++%4] || R1.L = W[I0++];\n\t" - "LOOP vq_loop%= LC0 = %2;\n\t" - "LOOP_BEGIN vq_loop%=;\n\t" - "%0 = (A0 -= R0.L*R1.L) (IS) || R0.L = W[%1++%4] || R1.L = W[I0++];\n\t" - "LOOP_END vq_loop%=;\n\t" - "%0 = (A0 -= R0.L*R1.L) (IS);\n\t" - : "=D" (dist), "=a" (codebook) - : "a" (len-1), "a" (in), "a" (2), "1" (codebook), "0" (E[i]) - : "R0", "R1", "I0", "L0", "A0" - ); - if (i<N || dist<best_dist[N-1]) - { - for (k=N-1; (k >= 1) && (k > used || dist < best_dist[k-1]); k--) - { - best_dist[k]=best_dist[k-1]; - nbest[k] = nbest[k-1]; - } - best_dist[k]=dist; - nbest[k]=i; - used++; - } - } - } -} diff --git a/drivers/speex/vq_sse.h b/drivers/speex/vq_sse.h deleted file mode 100644 index 00a42ce354..0000000000 --- a/drivers/speex/vq_sse.h +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright (C) 2004 Jean-Marc Valin */ -/** - @file vq_sse.h - @brief SSE-optimized vq routine -*/ -/* - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - -#define OVERRIDE_VQ_NBEST -void vq_nbest(spx_word16_t *_in, const __m128 *codebook, int len, int entries, __m128 *E, int N, int *nbest, spx_word32_t *best_dist, char *stack) -{ - int i,j,k,used; - VARDECL(float *dist); - VARDECL(__m128 *in); - __m128 half; - used = 0; - ALLOC(dist, entries, float); - half = _mm_set_ps1(.5f); - ALLOC(in, len, __m128); - for (i=0;i<len;i++) - in[i] = _mm_set_ps1(_in[i]); - for (i=0;i<entries>>2;i++) - { - __m128 d = _mm_mul_ps(E[i], half); - for (j=0;j<len;j++) - d = _mm_sub_ps(d, _mm_mul_ps(in[j], *codebook++)); - _mm_storeu_ps(dist+4*i, d); - } - for (i=0;i<entries;i++) - { - if (i<N || dist[i]<best_dist[N-1]) - { - for (k=N-1; (k >= 1) && (k > used || dist[i] < best_dist[k-1]); k--) - { - best_dist[k]=best_dist[k-1]; - nbest[k] = nbest[k-1]; - } - best_dist[k]=dist[i]; - nbest[k]=i; - used++; - } - } -} - - - - -#define OVERRIDE_VQ_NBEST_SIGN -void vq_nbest_sign(spx_word16_t *_in, const __m128 *codebook, int len, int entries, __m128 *E, int N, int *nbest, spx_word32_t *best_dist, char *stack) -{ - int i,j,k,used; - VARDECL(float *dist); - VARDECL(__m128 *in); - __m128 half; - used = 0; - ALLOC(dist, entries, float); - half = _mm_set_ps1(.5f); - ALLOC(in, len, __m128); - for (i=0;i<len;i++) - in[i] = _mm_set_ps1(_in[i]); - for (i=0;i<entries>>2;i++) - { - __m128 d = _mm_setzero_ps(); - for (j=0;j<len;j++) - d = _mm_add_ps(d, _mm_mul_ps(in[j], *codebook++)); - _mm_storeu_ps(dist+4*i, d); - } - for (i=0;i<entries;i++) - { - int sign; - if (dist[i]>0) - { - sign=0; - dist[i]=-dist[i]; - } else - { - sign=1; - } - dist[i] += .5f*((float*)E)[i]; - if (i<N || dist[i]<best_dist[N-1]) - { - for (k=N-1; (k >= 1) && (k > used || dist[i] < best_dist[k-1]); k--) - { - best_dist[k]=best_dist[k-1]; - nbest[k] = nbest[k-1]; - } - best_dist[k]=dist[i]; - nbest[k]=i; - used++; - if (sign) - nbest[k]+=entries; - } - } -} diff --git a/drivers/speex/window.c b/drivers/speex/window.c deleted file mode 100644 index 3376415fff..0000000000 --- a/drivers/speex/window.c +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (C) 2006 Jean-Marc Valin - File: window.c - - 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 the Xiph.org Foundation nor the names of its - 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 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. -*/ - - -#include "config.h" - - -#include "arch.h" - -#ifdef FIXED_POINT -const spx_word16_t lag_window[11] = { - 16384, 16337, 16199, 15970, 15656, 15260, 14790, 14254, 13659, 13015, 12330 -}; - -const spx_word16_t lpc_window[200] = { -1310, 1313, 1321, 1333, 1352, 1375, 1403, 1436, -1475, 1518, 1567, 1621, 1679, 1743, 1811, 1884, -1962, 2044, 2132, 2224, 2320, 2421, 2526, 2636, -2750, 2868, 2990, 3116, 3246, 3380, 3518, 3659, -3804, 3952, 4104, 4259, 4417, 4578, 4742, 4909, -5079, 5251, 5425, 5602, 5781, 5963, 6146, 6331, -6518, 6706, 6896, 7087, 7280, 7473, 7668, 7863, -8059, 8256, 8452, 8650, 8847, 9044, 9241, 9438, -9635, 9831, 10026, 10220, 10414, 10606, 10797, 10987, -11176, 11363, 11548, 11731, 11912, 12091, 12268, 12443, -12615, 12785, 12952, 13116, 13277, 13435, 13590, 13742, -13890, 14035, 14176, 14314, 14448, 14578, 14704, 14826, -14944, 15058, 15168, 15273, 15374, 15470, 15562, 15649, -15732, 15810, 15883, 15951, 16015, 16073, 16127, 16175, -16219, 16257, 16291, 16319, 16342, 16360, 16373, 16381, -16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, -16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, -16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, -16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, -16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, -16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, -16384, 16384, 16384, 16361, 16294, 16183, 16028, 15830, -15588, 15304, 14979, 14613, 14207, 13763, 13282, 12766, -12215, 11631, 11016, 10373, 9702, 9007, 8289, 7551, -6797, 6028, 5251, 4470, 3695, 2943, 2248, 1696 -}; -#else -const spx_word16_t lag_window[11] = { - 1.00000, 0.99716, 0.98869, 0.97474, 0.95554, 0.93140, 0.90273, 0.86998, 0.83367, 0.79434, 0.75258 -}; - -const spx_word16_t lpc_window[200] = { - 0.080000f, 0.080158f, 0.080630f, 0.081418f, 0.082520f, 0.083935f, 0.085663f, 0.087703f, - 0.090052f, 0.092710f, 0.095674f, 0.098943f, 0.102514f, 0.106385f, 0.110553f, 0.115015f, - 0.119769f, 0.124811f, 0.130137f, 0.135744f, 0.141628f, 0.147786f, 0.154212f, 0.160902f, - 0.167852f, 0.175057f, 0.182513f, 0.190213f, 0.198153f, 0.206328f, 0.214731f, 0.223357f, - 0.232200f, 0.241254f, 0.250513f, 0.259970f, 0.269619f, 0.279453f, 0.289466f, 0.299651f, - 0.310000f, 0.320507f, 0.331164f, 0.341965f, 0.352901f, 0.363966f, 0.375151f, 0.386449f, - 0.397852f, 0.409353f, 0.420943f, 0.432615f, 0.444361f, 0.456172f, 0.468040f, 0.479958f, - 0.491917f, 0.503909f, 0.515925f, 0.527959f, 0.540000f, 0.552041f, 0.564075f, 0.576091f, - 0.588083f, 0.600042f, 0.611960f, 0.623828f, 0.635639f, 0.647385f, 0.659057f, 0.670647f, - 0.682148f, 0.693551f, 0.704849f, 0.716034f, 0.727099f, 0.738035f, 0.748836f, 0.759493f, - 0.770000f, 0.780349f, 0.790534f, 0.800547f, 0.810381f, 0.820030f, 0.829487f, 0.838746f, - 0.847800f, 0.856643f, 0.865269f, 0.873672f, 0.881847f, 0.889787f, 0.897487f, 0.904943f, - 0.912148f, 0.919098f, 0.925788f, 0.932214f, 0.938372f, 0.944256f, 0.949863f, 0.955189f, - 0.960231f, 0.964985f, 0.969447f, 0.973615f, 0.977486f, 0.981057f, 0.984326f, 0.987290f, - 0.989948f, 0.992297f, 0.994337f, 0.996065f, 0.997480f, 0.998582f, 0.999370f, 0.999842f, - 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, - 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, - 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, - 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, - 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, - 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, - 1.000000f, 1.000000f, 1.000000f, 0.998640f, 0.994566f, 0.987787f, 0.978324f, 0.966203f, - 0.951458f, 0.934131f, 0.914270f, 0.891931f, 0.867179f, 0.840084f, 0.810723f, 0.779182f, - 0.745551f, 0.709930f, 0.672424f, 0.633148f, 0.592223f, 0.549781f, 0.505964f, 0.460932f, - 0.414863f, 0.367968f, 0.320511f, 0.272858f, 0.225569f, 0.179655f, 0.137254f, 0.103524f -}; -#endif diff --git a/drivers/squish/SCsub b/drivers/squish/SCsub deleted file mode 100644 index da39dc1ebc..0000000000 --- a/drivers/squish/SCsub +++ /dev/null @@ -1,23 +0,0 @@ -Import('env') - - -squish_sources=[ -'squish/alpha.cpp', -'squish/clusterfit.cpp', -'squish/colourblock.cpp', -'squish/colourfit.cpp', -'squish/colourset.cpp', -'squish/maths.cpp', -'squish/rangefit.cpp', -'squish/singlecolourfit.cpp', -'squish/squish.cpp', -'squish/image_compress_squish.cpp', -] - - -if (env["tools"]=="yes"): - env.drivers_sources+=squish_sources - -#env.add_source_files(env.drivers_sources, squish_sources) - -Export('env') diff --git a/drivers/squish/alpha.cpp b/drivers/squish/alpha.cpp deleted file mode 100644 index 2ddb7dc28b..0000000000 --- a/drivers/squish/alpha.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "alpha.h" -#include <algorithm> - -namespace squish { - -static int FloatToInt( float a, int limit ) -{ - // use ANSI round-to-zero behaviour to get round-to-nearest - int i = ( int )( a + 0.5f ); - - // clamp to the limit - if( i < 0 ) - i = 0; - else if( i > limit ) - i = limit; - - // done - return i; -} - -void CompressAlphaDxt3( u8 const* rgba, int mask, void* block ) -{ - u8* bytes = reinterpret_cast< u8* >( block ); - - // quantise and pack the alpha values pairwise - for( int i = 0; i < 8; ++i ) - { - // quantise down to 4 bits - float alpha1 = ( float )rgba[8*i + 3] * ( 15.0f/255.0f ); - float alpha2 = ( float )rgba[8*i + 7] * ( 15.0f/255.0f ); - int quant1 = FloatToInt( alpha1, 15 ); - int quant2 = FloatToInt( alpha2, 15 ); - - // set alpha to zero where masked - int bit1 = 1 << ( 2*i ); - int bit2 = 1 << ( 2*i + 1 ); - if( ( mask & bit1 ) == 0 ) - quant1 = 0; - if( ( mask & bit2 ) == 0 ) - quant2 = 0; - - // pack into the byte - bytes[i] = ( u8 )( quant1 | ( quant2 << 4 ) ); - } -} - -void DecompressAlphaDxt3( u8* rgba, void const* block ) -{ - u8 const* bytes = reinterpret_cast< u8 const* >( block ); - - // unpack the alpha values pairwise - for( int i = 0; i < 8; ++i ) - { - // quantise down to 4 bits - u8 quant = bytes[i]; - - // unpack the values - u8 lo = quant & 0x0f; - u8 hi = quant & 0xf0; - - // convert back up to bytes - rgba[8*i + 3] = lo | ( lo << 4 ); - rgba[8*i + 7] = hi | ( hi >> 4 ); - } -} - -static void FixRange( int& min, int& max, int steps ) -{ - if( max - min < steps ) - max = std::min( min + steps, 255 ); - if( max - min < steps ) - min = std::max( 0, max - steps ); -} - -static int FitCodes( u8 const* rgba, int mask, u8 const* codes, u8* indices ) -{ - // fit each alpha value to the codebook - int err = 0; - for( int i = 0; i < 16; ++i ) - { - // check this pixel is valid - int bit = 1 << i; - if( ( mask & bit ) == 0 ) - { - // use the first code - indices[i] = 0; - continue; - } - - // find the least error and corresponding index - int value = rgba[4*i + 3]; - int least = 2147483647; //INT_MAX - int index = 0; - for( int j = 0; j < 8; ++j ) - { - // get the squared error from this code - int dist = ( int )value - ( int )codes[j]; - dist *= dist; - - // compare with the best so far - if( dist < least ) - { - least = dist; - index = j; - } - } - - // save this index and accumulate the error - indices[i] = ( u8 )index; - err += least; - } - - // return the total error - return err; -} - -static void WriteAlphaBlock( int alpha0, int alpha1, u8 const* indices, void* block ) -{ - u8* bytes = reinterpret_cast< u8* >( block ); - - // write the first two bytes - bytes[0] = ( u8 )alpha0; - bytes[1] = ( u8 )alpha1; - - // pack the indices with 3 bits each - u8* dest = bytes + 2; - u8 const* src = indices; - for( int i = 0; i < 2; ++i ) - { - // pack 8 3-bit values - int value = 0; - for( int j = 0; j < 8; ++j ) - { - int index = *src++; - value |= ( index << 3*j ); - } - - // store in 3 bytes - for( int j = 0; j < 3; ++j ) - { - int byte = ( value >> 8*j ) & 0xff; - *dest++ = ( u8 )byte; - } - } -} - -static void WriteAlphaBlock5( int alpha0, int alpha1, u8 const* indices, void* block ) -{ - // check the relative values of the endpoints - if( alpha0 > alpha1 ) - { - // swap the indices - u8 swapped[16]; - for( int i = 0; i < 16; ++i ) - { - u8 index = indices[i]; - if( index == 0 ) - swapped[i] = 1; - else if( index == 1 ) - swapped[i] = 0; - else if( index <= 5 ) - swapped[i] = 7 - index; - else - swapped[i] = index; - } - - // write the block - WriteAlphaBlock( alpha1, alpha0, swapped, block ); - } - else - { - // write the block - WriteAlphaBlock( alpha0, alpha1, indices, block ); - } -} - -static void WriteAlphaBlock7( int alpha0, int alpha1, u8 const* indices, void* block ) -{ - // check the relative values of the endpoints - if( alpha0 < alpha1 ) - { - // swap the indices - u8 swapped[16]; - for( int i = 0; i < 16; ++i ) - { - u8 index = indices[i]; - if( index == 0 ) - swapped[i] = 1; - else if( index == 1 ) - swapped[i] = 0; - else - swapped[i] = 9 - index; - } - - // write the block - WriteAlphaBlock( alpha1, alpha0, swapped, block ); - } - else - { - // write the block - WriteAlphaBlock( alpha0, alpha1, indices, block ); - } -} - -void CompressAlphaDxt5( u8 const* rgba, int mask, void* block ) -{ - // get the range for 5-alpha and 7-alpha interpolation - int min5 = 255; - int max5 = 0; - int min7 = 255; - int max7 = 0; - for( int i = 0; i < 16; ++i ) - { - // check this pixel is valid - int bit = 1 << i; - if( ( mask & bit ) == 0 ) - continue; - - // incorporate into the min/max - int value = rgba[4*i + 3]; - if( value < min7 ) - min7 = value; - if( value > max7 ) - max7 = value; - if( value != 0 && value < min5 ) - min5 = value; - if( value != 255 && value > max5 ) - max5 = value; - } - - // handle the case that no valid range was found - if( min5 > max5 ) - min5 = max5; - if( min7 > max7 ) - min7 = max7; - - // fix the range to be the minimum in each case - FixRange( min5, max5, 5 ); - FixRange( min7, max7, 7 ); - - // set up the 5-alpha code book - u8 codes5[8]; - codes5[0] = ( u8 )min5; - codes5[1] = ( u8 )max5; - for( int i = 1; i < 5; ++i ) - codes5[1 + i] = ( u8 )( ( ( 5 - i )*min5 + i*max5 )/5 ); - codes5[6] = 0; - codes5[7] = 255; - - // set up the 7-alpha code book - u8 codes7[8]; - codes7[0] = ( u8 )min7; - codes7[1] = ( u8 )max7; - for( int i = 1; i < 7; ++i ) - codes7[1 + i] = ( u8 )( ( ( 7 - i )*min7 + i*max7 )/7 ); - - // fit the data to both code books - u8 indices5[16]; - u8 indices7[16]; - int err5 = FitCodes( rgba, mask, codes5, indices5 ); - int err7 = FitCodes( rgba, mask, codes7, indices7 ); - - // save the block with least error - if( err5 <= err7 ) - WriteAlphaBlock5( min5, max5, indices5, block ); - else - WriteAlphaBlock7( min7, max7, indices7, block ); -} - -void DecompressAlphaDxt5( u8* rgba, void const* block ) -{ - // get the two alpha values - u8 const* bytes = reinterpret_cast< u8 const* >( block ); - int alpha0 = bytes[0]; - int alpha1 = bytes[1]; - - // compare the values to build the codebook - u8 codes[8]; - codes[0] = ( u8 )alpha0; - codes[1] = ( u8 )alpha1; - if( alpha0 <= alpha1 ) - { - // use 5-alpha codebook - for( int i = 1; i < 5; ++i ) - codes[1 + i] = ( u8 )( ( ( 5 - i )*alpha0 + i*alpha1 )/5 ); - codes[6] = 0; - codes[7] = 255; - } - else - { - // use 7-alpha codebook - for( int i = 1; i < 7; ++i ) - codes[1 + i] = ( u8 )( ( ( 7 - i )*alpha0 + i*alpha1 )/7 ); - } - - // decode the indices - u8 indices[16]; - u8 const* src = bytes + 2; - u8* dest = indices; - for( int i = 0; i < 2; ++i ) - { - // grab 3 bytes - int value = 0; - for( int j = 0; j < 3; ++j ) - { - int byte = *src++; - value |= ( byte << 8*j ); - } - - // unpack 8 3-bit values from it - for( int j = 0; j < 8; ++j ) - { - int index = ( value >> 3*j ) & 0x7; - *dest++ = ( u8 )index; - } - } - - // write out the indexed codebook values - for( int i = 0; i < 16; ++i ) - rgba[4*i + 3] = codes[indices[i]]; -} - -} // namespace squish diff --git a/drivers/squish/alpha.h b/drivers/squish/alpha.h deleted file mode 100644 index d56fe4d2c6..0000000000 --- a/drivers/squish/alpha.h +++ /dev/null @@ -1,41 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_ALPHA_H -#define SQUISH_ALPHA_H - -#include "squish/squish.h" - -namespace squish { - -void CompressAlphaDxt3( u8 const* rgba, int mask, void* block ); -void CompressAlphaDxt5( u8 const* rgba, int mask, void* block ); - -void DecompressAlphaDxt3( u8* rgba, void const* block ); -void DecompressAlphaDxt5( u8* rgba, void const* block ); - -} // namespace squish - -#endif // ndef SQUISH_ALPHA_H diff --git a/drivers/squish/clusterfit.cpp b/drivers/squish/clusterfit.cpp deleted file mode 100644 index afea84880c..0000000000 --- a/drivers/squish/clusterfit.cpp +++ /dev/null @@ -1,393 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - Copyright (c) 2007 Ignacio Castano icastano@nvidia.com - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "clusterfit.h" -#include "colourset.h" -#include "colourblock.h" -#include <cfloat> - -namespace squish { - -ClusterFit::ClusterFit( ColourSet const* colours, int flags ) - : ColourFit( colours, flags ) -{ - // set the iteration count - m_iterationCount = ( m_flags & kColourIterativeClusterFit ) ? kMaxIterations : 1; - - // initialise the best error - m_besterror = VEC4_CONST( FLT_MAX ); - - // initialise the metric - bool perceptual = ( ( m_flags & kColourMetricPerceptual ) != 0 ); - if( perceptual ) - m_metric = Vec4( 0.2126f, 0.7152f, 0.0722f, 0.0f ); - else - m_metric = VEC4_CONST( 1.0f ); - - // cache some values - int const count = m_colours->GetCount(); - Vec3 const* values = m_colours->GetPoints(); - - // get the covariance matrix - Sym3x3 covariance = ComputeWeightedCovariance( count, values, m_colours->GetWeights() ); - - // compute the principle component - m_principle = ComputePrincipleComponent( covariance ); -} - -bool ClusterFit::ConstructOrdering( Vec3 const& axis, int iteration ) -{ - // cache some values - int const count = m_colours->GetCount(); - Vec3 const* values = m_colours->GetPoints(); - - // build the list of dot products - float dps[16]; - u8* order = ( u8* )m_order + 16*iteration; - for( int i = 0; i < count; ++i ) - { - dps[i] = Dot( values[i], axis ); - order[i] = ( u8 )i; - } - - // stable sort using them - for( int i = 0; i < count; ++i ) - { - for( int j = i; j > 0 && dps[j] < dps[j - 1]; --j ) - { - std::swap( dps[j], dps[j - 1] ); - std::swap( order[j], order[j - 1] ); - } - } - - // check this ordering is unique - for( int it = 0; it < iteration; ++it ) - { - u8 const* prev = ( u8* )m_order + 16*it; - bool same = true; - for( int i = 0; i < count; ++i ) - { - if( order[i] != prev[i] ) - { - same = false; - break; - } - } - if( same ) - return false; - } - - // copy the ordering and weight all the points - Vec3 const* unweighted = m_colours->GetPoints(); - float const* weights = m_colours->GetWeights(); - m_xsum_wsum = VEC4_CONST( 0.0f ); - for( int i = 0; i < count; ++i ) - { - int j = order[i]; - Vec4 p( unweighted[j].X(), unweighted[j].Y(), unweighted[j].Z(), 1.0f ); - Vec4 w( weights[j] ); - Vec4 x = p*w; - m_points_weights[i] = x; - m_xsum_wsum += x; - } - return true; -} - -void ClusterFit::Compress3( void* block ) -{ - // declare variables - int const count = m_colours->GetCount(); - Vec4 const two = VEC4_CONST( 2.0 ); - Vec4 const one = VEC4_CONST( 1.0f ); - Vec4 const half_half2( 0.5f, 0.5f, 0.5f, 0.25f ); - Vec4 const zero = VEC4_CONST( 0.0f ); - Vec4 const half = VEC4_CONST( 0.5f ); - Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f ); - Vec4 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f, 0.0f ); - - // prepare an ordering using the principle axis - ConstructOrdering( m_principle, 0 ); - - // check all possible clusters and iterate on the total order - Vec4 beststart = VEC4_CONST( 0.0f ); - Vec4 bestend = VEC4_CONST( 0.0f ); - Vec4 besterror = m_besterror; - u8 bestindices[16]; - int bestiteration = 0; - int besti = 0, bestj = 0; - - // loop over iterations (we avoid the case that all points in first or last cluster) - for( int iterationIndex = 0;; ) - { - // first cluster [0,i) is at the start - Vec4 part0 = VEC4_CONST( 0.0f ); - for( int i = 0; i < count; ++i ) - { - // second cluster [i,j) is half along - Vec4 part1 = ( i == 0 ) ? m_points_weights[0] : VEC4_CONST( 0.0f ); - int jmin = ( i == 0 ) ? 1 : i; - for( int j = jmin;; ) - { - // last cluster [j,count) is at the end - Vec4 part2 = m_xsum_wsum - part1 - part0; - - // compute least squares terms directly - Vec4 alphax_sum = MultiplyAdd( part1, half_half2, part0 ); - Vec4 alpha2_sum = alphax_sum.SplatW(); - - Vec4 betax_sum = MultiplyAdd( part1, half_half2, part2 ); - Vec4 beta2_sum = betax_sum.SplatW(); - - Vec4 alphabeta_sum = ( part1*half_half2 ).SplatW(); - - // compute the least-squares optimal points - Vec4 factor = Reciprocal( NegativeMultiplySubtract( alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum ) ); - Vec4 a = NegativeMultiplySubtract( betax_sum, alphabeta_sum, alphax_sum*beta2_sum )*factor; - Vec4 b = NegativeMultiplySubtract( alphax_sum, alphabeta_sum, betax_sum*alpha2_sum )*factor; - - // clamp to the grid - a = Min( one, Max( zero, a ) ); - b = Min( one, Max( zero, b ) ); - a = Truncate( MultiplyAdd( grid, a, half ) )*gridrcp; - b = Truncate( MultiplyAdd( grid, b, half ) )*gridrcp; - - // compute the error (we skip the constant xxsum) - Vec4 e1 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum ); - Vec4 e2 = NegativeMultiplySubtract( a, alphax_sum, a*b*alphabeta_sum ); - Vec4 e3 = NegativeMultiplySubtract( b, betax_sum, e2 ); - Vec4 e4 = MultiplyAdd( two, e3, e1 ); - - // apply the metric to the error term - Vec4 e5 = e4*m_metric; - Vec4 error = e5.SplatX() + e5.SplatY() + e5.SplatZ(); - - // keep the solution if it wins - if( CompareAnyLessThan( error, besterror ) ) - { - beststart = a; - bestend = b; - besti = i; - bestj = j; - besterror = error; - bestiteration = iterationIndex; - } - - // advance - if( j == count ) - break; - part1 += m_points_weights[j]; - ++j; - } - - // advance - part0 += m_points_weights[i]; - } - - // stop if we didn't improve in this iteration - if( bestiteration != iterationIndex ) - break; - - // advance if possible - ++iterationIndex; - if( iterationIndex == m_iterationCount ) - break; - - // stop if a new iteration is an ordering that has already been tried - Vec3 axis = ( bestend - beststart ).GetVec3(); - if( !ConstructOrdering( axis, iterationIndex ) ) - break; - } - - // save the block if necessary - if( CompareAnyLessThan( besterror, m_besterror ) ) - { - // remap the indices - u8 const* order = ( u8* )m_order + 16*bestiteration; - - u8 unordered[16]; - for( int m = 0; m < besti; ++m ) - unordered[order[m]] = 0; - for( int m = besti; m < bestj; ++m ) - unordered[order[m]] = 2; - for( int m = bestj; m < count; ++m ) - unordered[order[m]] = 1; - - m_colours->RemapIndices( unordered, bestindices ); - - // save the block - WriteColourBlock3( beststart.GetVec3(), bestend.GetVec3(), bestindices, block ); - - // save the error - m_besterror = besterror; - } -} - -void ClusterFit::Compress4( void* block ) -{ - // declare variables - int const count = m_colours->GetCount(); - Vec4 const two = VEC4_CONST( 2.0f ); - Vec4 const one = VEC4_CONST( 1.0f ); - Vec4 const onethird_onethird2( 1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f, 1.0f/9.0f ); - Vec4 const twothirds_twothirds2( 2.0f/3.0f, 2.0f/3.0f, 2.0f/3.0f, 4.0f/9.0f ); - Vec4 const twonineths = VEC4_CONST( 2.0f/9.0f ); - Vec4 const zero = VEC4_CONST( 0.0f ); - Vec4 const half = VEC4_CONST( 0.5f ); - Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f ); - Vec4 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f, 0.0f ); - - // prepare an ordering using the principle axis - ConstructOrdering( m_principle, 0 ); - - // check all possible clusters and iterate on the total order - Vec4 beststart = VEC4_CONST( 0.0f ); - Vec4 bestend = VEC4_CONST( 0.0f ); - Vec4 besterror = m_besterror; - u8 bestindices[16]; - int bestiteration = 0; - int besti = 0, bestj = 0, bestk = 0; - - // loop over iterations (we avoid the case that all points in first or last cluster) - for( int iterationIndex = 0;; ) - { - // first cluster [0,i) is at the start - Vec4 part0 = VEC4_CONST( 0.0f ); - for( int i = 0; i < count; ++i ) - { - // second cluster [i,j) is one third along - Vec4 part1 = VEC4_CONST( 0.0f ); - for( int j = i;; ) - { - // third cluster [j,k) is two thirds along - Vec4 part2 = ( j == 0 ) ? m_points_weights[0] : VEC4_CONST( 0.0f ); - int kmin = ( j == 0 ) ? 1 : j; - for( int k = kmin;; ) - { - // last cluster [k,count) is at the end - Vec4 part3 = m_xsum_wsum - part2 - part1 - part0; - - // compute least squares terms directly - Vec4 const alphax_sum = MultiplyAdd( part2, onethird_onethird2, MultiplyAdd( part1, twothirds_twothirds2, part0 ) ); - Vec4 const alpha2_sum = alphax_sum.SplatW(); - - Vec4 const betax_sum = MultiplyAdd( part1, onethird_onethird2, MultiplyAdd( part2, twothirds_twothirds2, part3 ) ); - Vec4 const beta2_sum = betax_sum.SplatW(); - - Vec4 const alphabeta_sum = twonineths*( part1 + part2 ).SplatW(); - - // compute the least-squares optimal points - Vec4 factor = Reciprocal( NegativeMultiplySubtract( alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum ) ); - Vec4 a = NegativeMultiplySubtract( betax_sum, alphabeta_sum, alphax_sum*beta2_sum )*factor; - Vec4 b = NegativeMultiplySubtract( alphax_sum, alphabeta_sum, betax_sum*alpha2_sum )*factor; - - // clamp to the grid - a = Min( one, Max( zero, a ) ); - b = Min( one, Max( zero, b ) ); - a = Truncate( MultiplyAdd( grid, a, half ) )*gridrcp; - b = Truncate( MultiplyAdd( grid, b, half ) )*gridrcp; - - // compute the error (we skip the constant xxsum) - Vec4 e1 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum ); - Vec4 e2 = NegativeMultiplySubtract( a, alphax_sum, a*b*alphabeta_sum ); - Vec4 e3 = NegativeMultiplySubtract( b, betax_sum, e2 ); - Vec4 e4 = MultiplyAdd( two, e3, e1 ); - - // apply the metric to the error term - Vec4 e5 = e4*m_metric; - Vec4 error = e5.SplatX() + e5.SplatY() + e5.SplatZ(); - - // keep the solution if it wins - if( CompareAnyLessThan( error, besterror ) ) - { - beststart = a; - bestend = b; - besterror = error; - besti = i; - bestj = j; - bestk = k; - bestiteration = iterationIndex; - } - - // advance - if( k == count ) - break; - part2 += m_points_weights[k]; - ++k; - } - - // advance - if( j == count ) - break; - part1 += m_points_weights[j]; - ++j; - } - - // advance - part0 += m_points_weights[i]; - } - - // stop if we didn't improve in this iteration - if( bestiteration != iterationIndex ) - break; - - // advance if possible - ++iterationIndex; - if( iterationIndex == m_iterationCount ) - break; - - // stop if a new iteration is an ordering that has already been tried - Vec3 axis = ( bestend - beststart ).GetVec3(); - if( !ConstructOrdering( axis, iterationIndex ) ) - break; - } - - // save the block if necessary - if( CompareAnyLessThan( besterror, m_besterror ) ) - { - // remap the indices - u8 const* order = ( u8* )m_order + 16*bestiteration; - - u8 unordered[16]; - for( int m = 0; m < besti; ++m ) - unordered[order[m]] = 0; - for( int m = besti; m < bestj; ++m ) - unordered[order[m]] = 2; - for( int m = bestj; m < bestk; ++m ) - unordered[order[m]] = 3; - for( int m = bestk; m < count; ++m ) - unordered[order[m]] = 1; - - m_colours->RemapIndices( unordered, bestindices ); - - // save the block - WriteColourBlock4( beststart.GetVec3(), bestend.GetVec3(), bestindices, block ); - - // save the error - m_besterror = besterror; - } -} - -} // namespace squish diff --git a/drivers/squish/clusterfit.h b/drivers/squish/clusterfit.h deleted file mode 100644 index 2d2b67103b..0000000000 --- a/drivers/squish/clusterfit.h +++ /dev/null @@ -1,61 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - Copyright (c) 2007 Ignacio Castano icastano@nvidia.com - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_CLUSTERFIT_H -#define SQUISH_CLUSTERFIT_H - -#include "squish/squish.h" -#include "maths.h" -#include "simd.h" -#include "colourfit.h" - -namespace squish { - -class ClusterFit : public ColourFit -{ -public: - ClusterFit( ColourSet const* colours, int flags ); - -private: - bool ConstructOrdering( Vec3 const& axis, int iteration ); - - virtual void Compress3( void* block ); - virtual void Compress4( void* block ); - - enum { kMaxIterations = 8 }; - - int m_iterationCount; - Vec3 m_principle; - u8 m_order[16*kMaxIterations]; - Vec4 m_points_weights[16]; - Vec4 m_xsum_wsum; - Vec4 m_metric; - Vec4 m_besterror; -}; - -} // namespace squish - -#endif // ndef SQUISH_CLUSTERFIT_H diff --git a/drivers/squish/colourblock.cpp b/drivers/squish/colourblock.cpp deleted file mode 100644 index e6a5788b74..0000000000 --- a/drivers/squish/colourblock.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "colourblock.h" - -namespace squish { - -static int FloatToInt( float a, int limit ) -{ - // use ANSI round-to-zero behaviour to get round-to-nearest - int i = ( int )( a + 0.5f ); - - // clamp to the limit - if( i < 0 ) - i = 0; - else if( i > limit ) - i = limit; - - // done - return i; -} - -static int FloatTo565( Vec3::Arg colour ) -{ - // get the components in the correct range - int r = FloatToInt( 31.0f*colour.X(), 31 ); - int g = FloatToInt( 63.0f*colour.Y(), 63 ); - int b = FloatToInt( 31.0f*colour.Z(), 31 ); - - // pack into a single value - return ( r << 11 ) | ( g << 5 ) | b; -} - -static void WriteColourBlock( int a, int b, u8* indices, void* block ) -{ - // get the block as bytes - u8* bytes = ( u8* )block; - - // write the endpoints - bytes[0] = ( u8 )( a & 0xff ); - bytes[1] = ( u8 )( a >> 8 ); - bytes[2] = ( u8 )( b & 0xff ); - bytes[3] = ( u8 )( b >> 8 ); - - // write the indices - for( int i = 0; i < 4; ++i ) - { - u8 const* ind = indices + 4*i; - bytes[4 + i] = ind[0] | ( ind[1] << 2 ) | ( ind[2] << 4 ) | ( ind[3] << 6 ); - } -} - -void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ) -{ - // get the packed values - int a = FloatTo565( start ); - int b = FloatTo565( end ); - - // remap the indices - u8 remapped[16]; - if( a <= b ) - { - // use the indices directly - for( int i = 0; i < 16; ++i ) - remapped[i] = indices[i]; - } - else - { - // swap a and b - std::swap( a, b ); - for( int i = 0; i < 16; ++i ) - { - if( indices[i] == 0 ) - remapped[i] = 1; - else if( indices[i] == 1 ) - remapped[i] = 0; - else - remapped[i] = indices[i]; - } - } - - // write the block - WriteColourBlock( a, b, remapped, block ); -} - -void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ) -{ - // get the packed values - int a = FloatTo565( start ); - int b = FloatTo565( end ); - - // remap the indices - u8 remapped[16]; - if( a < b ) - { - // swap a and b - std::swap( a, b ); - for( int i = 0; i < 16; ++i ) - remapped[i] = ( indices[i] ^ 0x1 ) & 0x3; - } - else if( a == b ) - { - // use index 0 - for( int i = 0; i < 16; ++i ) - remapped[i] = 0; - } - else - { - // use the indices directly - for( int i = 0; i < 16; ++i ) - remapped[i] = indices[i]; - } - - // write the block - WriteColourBlock( a, b, remapped, block ); -} - -static int Unpack565( u8 const* packed, u8* colour ) -{ - // build the packed value - int value = ( int )packed[0] | ( ( int )packed[1] << 8 ); - - // get the components in the stored range - u8 red = ( u8 )( ( value >> 11 ) & 0x1f ); - u8 green = ( u8 )( ( value >> 5 ) & 0x3f ); - u8 blue = ( u8 )( value & 0x1f ); - - // scale up to 8 bits - colour[0] = ( red << 3 ) | ( red >> 2 ); - colour[1] = ( green << 2 ) | ( green >> 4 ); - colour[2] = ( blue << 3 ) | ( blue >> 2 ); - colour[3] = 255; - - // return the value - return value; -} - -void DecompressColour( u8* rgba, void const* block, bool isDxt1 ) -{ - // get the block bytes - u8 const* bytes = reinterpret_cast< u8 const* >( block ); - - // unpack the endpoints - u8 codes[16]; - int a = Unpack565( bytes, codes ); - int b = Unpack565( bytes + 2, codes + 4 ); - - // generate the midpoints - for( int i = 0; i < 3; ++i ) - { - int c = codes[i]; - int d = codes[4 + i]; - - if( isDxt1 && a <= b ) - { - codes[8 + i] = ( u8 )( ( c + d )/2 ); - codes[12 + i] = 0; - } - else - { - codes[8 + i] = ( u8 )( ( 2*c + d )/3 ); - codes[12 + i] = ( u8 )( ( c + 2*d )/3 ); - } - } - - // fill in alpha for the intermediate values - codes[8 + 3] = 255; - codes[12 + 3] = ( isDxt1 && a <= b ) ? 0 : 255; - - // unpack the indices - u8 indices[16]; - for( int i = 0; i < 4; ++i ) - { - u8* ind = indices + 4*i; - u8 packed = bytes[4 + i]; - - ind[0] = packed & 0x3; - ind[1] = ( packed >> 2 ) & 0x3; - ind[2] = ( packed >> 4 ) & 0x3; - ind[3] = ( packed >> 6 ) & 0x3; - } - - // store out the colours - for( int i = 0; i < 16; ++i ) - { - u8 offset = 4*indices[i]; - for( int j = 0; j < 4; ++j ) - rgba[4*i + j] = codes[offset + j]; - } -} - -} // namespace squish diff --git a/drivers/squish/colourblock.h b/drivers/squish/colourblock.h deleted file mode 100644 index 8a25b42a63..0000000000 --- a/drivers/squish/colourblock.h +++ /dev/null @@ -1,41 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_COLOURBLOCK_H -#define SQUISH_COLOURBLOCK_H - -#include "squish/squish.h" -#include "maths.h" - -namespace squish { - -void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ); -void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ); - -void DecompressColour( u8* rgba, void const* block, bool isDxt1 ); - -} // namespace squish - -#endif // ndef SQUISH_COLOURBLOCK_H diff --git a/drivers/squish/colourfit.cpp b/drivers/squish/colourfit.cpp deleted file mode 100644 index dba2b87e81..0000000000 --- a/drivers/squish/colourfit.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "colourfit.h" -#include "colourset.h" - -namespace squish { - -ColourFit::ColourFit( ColourSet const* colours, int flags ) - : m_colours( colours ), - m_flags( flags ) -{ -} - -void ColourFit::Compress( void* block ) -{ - bool isDxt1 = ( ( m_flags & kDxt1 ) != 0 ); - if( isDxt1 ) - { - Compress3( block ); - if( !m_colours->IsTransparent() ) - Compress4( block ); - } - else - Compress4( block ); -} - -} // namespace squish diff --git a/drivers/squish/colourfit.h b/drivers/squish/colourfit.h deleted file mode 100644 index d048b48709..0000000000 --- a/drivers/squish/colourfit.h +++ /dev/null @@ -1,53 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_COLOURFIT_H -#define SQUISH_COLOURFIT_H - -#include "squish/squish.h" -#include "maths.h" - -namespace squish { - -class ColourSet; - -class ColourFit -{ -public: - ColourFit( ColourSet const* colours, int flags ); - - void Compress( void* block ); - -protected: - virtual void Compress3( void* block ) = 0; - virtual void Compress4( void* block ) = 0; - - ColourSet const* m_colours; - int m_flags; -}; - -} // namespace squish - -#endif // ndef SQUISH_COLOURFIT_H diff --git a/drivers/squish/colourset.cpp b/drivers/squish/colourset.cpp deleted file mode 100644 index 97d29d9873..0000000000 --- a/drivers/squish/colourset.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "colourset.h" - -namespace squish { - -ColourSet::ColourSet( u8 const* rgba, int mask, int flags ) - : m_count( 0 ), - m_transparent( false ) -{ - // check the compression mode for dxt1 - bool isDxt1 = ( ( flags & kDxt1 ) != 0 ); - bool weightByAlpha = ( ( flags & kWeightColourByAlpha ) != 0 ); - - // create the minimal set - for( int i = 0; i < 16; ++i ) - { - // check this pixel is enabled - int bit = 1 << i; - if( ( mask & bit ) == 0 ) - { - m_remap[i] = -1; - continue; - } - - // check for transparent pixels when using dxt1 - if( isDxt1 && rgba[4*i + 3] < 128 ) - { - m_remap[i] = -1; - m_transparent = true; - continue; - } - - // loop over previous points for a match - for( int j = 0;; ++j ) - { - // allocate a new point - if( j == i ) - { - // normalise coordinates to [0,1] - float x = ( float )rgba[4*i] / 255.0f; - float y = ( float )rgba[4*i + 1] / 255.0f; - float z = ( float )rgba[4*i + 2] / 255.0f; - - // ensure there is always non-zero weight even for zero alpha - float w = ( float )( rgba[4*i + 3] + 1 ) / 256.0f; - - // add the point - m_points[m_count] = Vec3( x, y, z ); - m_weights[m_count] = ( weightByAlpha ? w : 1.0f ); - m_remap[i] = m_count; - - // advance - ++m_count; - break; - } - - // check for a match - int oldbit = 1 << j; - bool match = ( ( mask & oldbit ) != 0 ) - && ( rgba[4*i] == rgba[4*j] ) - && ( rgba[4*i + 1] == rgba[4*j + 1] ) - && ( rgba[4*i + 2] == rgba[4*j + 2] ) - && ( rgba[4*j + 3] >= 128 || !isDxt1 ); - if( match ) - { - // get the index of the match - int index = m_remap[j]; - - // ensure there is always non-zero weight even for zero alpha - float w = ( float )( rgba[4*i + 3] + 1 ) / 256.0f; - - // map to this point and increase the weight - m_weights[index] += ( weightByAlpha ? w : 1.0f ); - m_remap[i] = index; - break; - } - } - } - - // square root the weights - for( int i = 0; i < m_count; ++i ) - m_weights[i] = std::sqrt( m_weights[i] ); -} - -void ColourSet::RemapIndices( u8 const* source, u8* target ) const -{ - for( int i = 0; i < 16; ++i ) - { - int j = m_remap[i]; - if( j == -1 ) - target[i] = 3; - else - target[i] = source[j]; - } -} - -} // namespace squish diff --git a/drivers/squish/colourset.h b/drivers/squish/colourset.h deleted file mode 100644 index 803e787f5b..0000000000 --- a/drivers/squish/colourset.h +++ /dev/null @@ -1,58 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_COLOURSET_H -#define SQUISH_COLOURSET_H - -#include "squish/squish.h" -#include "maths.h" - -namespace squish { - -/*! @brief Represents a set of block colours -*/ -class ColourSet -{ -public: - ColourSet( u8 const* rgba, int mask, int flags ); - - int GetCount() const { return m_count; } - Vec3 const* GetPoints() const { return m_points; } - float const* GetWeights() const { return m_weights; } - bool IsTransparent() const { return m_transparent; } - - void RemapIndices( u8 const* source, u8* target ) const; - -private: - int m_count; - Vec3 m_points[16]; - float m_weights[16]; - int m_remap[16]; - bool m_transparent; -}; - -} // namespace sqish - -#endif // ndef SQUISH_COLOURSET_H diff --git a/drivers/squish/config.h b/drivers/squish/config.h deleted file mode 100644 index 7bf3760c26..0000000000 --- a/drivers/squish/config.h +++ /dev/null @@ -1,49 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_CONFIG_H -#define SQUISH_CONFIG_H - -// Set to 1 when building squish to use Altivec instructions. -#ifndef SQUISH_USE_ALTIVEC -#define SQUISH_USE_ALTIVEC 0 -#endif - -// Set to 1 or 2 when building squish to use SSE or SSE2 instructions. -#ifndef SQUISH_USE_SSE -#define SQUISH_USE_SSE 0 -#endif - -// Internally et SQUISH_USE_SIMD when either Altivec or SSE is available. -#if SQUISH_USE_ALTIVEC && SQUISH_USE_SSE -#error "Cannot enable both Altivec and SSE!" -#endif -#if SQUISH_USE_ALTIVEC || SQUISH_USE_SSE -#define SQUISH_USE_SIMD 1 -#else -#define SQUISH_USE_SIMD 0 -#endif - -#endif // ndef SQUISH_CONFIG_H diff --git a/drivers/squish/image_compress_squish.cpp b/drivers/squish/image_compress_squish.cpp deleted file mode 100644 index 95de83d5a5..0000000000 --- a/drivers/squish/image_compress_squish.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/*************************************************************************/ -/* image_compress_squish.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "image_compress_squish.h" -#include "squish/squish.h" -#include "print_string.h" - -void image_compress_squish(Image *p_image) { - - int w=p_image->get_width(); - int h=p_image->get_height(); - - if (p_image->get_mipmaps() == 0) { - ERR_FAIL_COND( !w || w % 4 != 0); - ERR_FAIL_COND( !h || h % 4 != 0); - } else { - ERR_FAIL_COND( !w || w !=nearest_power_of_2(w) ); - ERR_FAIL_COND( !h || h !=nearest_power_of_2(h) ); - }; - - if (p_image->get_format()>=Image::FORMAT_BC1) - return; //do not compress, already compressed - - int shift=0; - int squish_comp=squish::kColourRangeFit; - Image::Format target_format; - - if (p_image->get_format()==Image::FORMAT_GRAYSCALE_ALPHA) { - //compressed normalmap - target_format = Image::FORMAT_BC3; squish_comp|=squish::kDxt5;; - } else if (p_image->detect_alpha()!=Image::ALPHA_NONE) { - - target_format = Image::FORMAT_BC2; squish_comp|=squish::kDxt3;; - } else { - target_format = Image::FORMAT_BC1; shift=1; squish_comp|=squish::kDxt1;; - } - - p_image->convert(Image::FORMAT_RGBA); //always expects rgba - - int mm_count = p_image->get_mipmaps(); - - DVector<uint8_t> data; - int target_size = Image::get_image_data_size(w,h,target_format,mm_count); - data.resize(target_size); - - DVector<uint8_t>::Read rb = p_image->get_data().read(); - DVector<uint8_t>::Write wb = data.write(); - - int dst_ofs=0; - - for(int i=0;i<=mm_count;i++) { - - int src_ofs = p_image->get_mipmap_offset(i); - squish::CompressImage( &rb[src_ofs],w,h,&wb[dst_ofs],squish_comp); - dst_ofs+=(MAX(4,w)*MAX(4,h))>>shift; - w>>=1; - h>>=1; - } - - rb = DVector<uint8_t>::Read(); - wb = DVector<uint8_t>::Write(); - - p_image->create(p_image->get_width(),p_image->get_height(),p_image->get_mipmaps(),target_format,data); - -} - diff --git a/drivers/squish/image_compress_squish.h b/drivers/squish/image_compress_squish.h deleted file mode 100644 index 8c37ac2caa..0000000000 --- a/drivers/squish/image_compress_squish.h +++ /dev/null @@ -1,39 +0,0 @@ -/*************************************************************************/ -/* image_compress_squish.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef IMAGE_COMPRESS_SQUISH_H -#define IMAGE_COMPRESS_SQUISH_H - - -#include "image.h" - - -void image_compress_squish(Image *p_image); - - -#endif // IMAGE_COMPRESS_SQUISH_H diff --git a/drivers/squish/maths.cpp b/drivers/squish/maths.cpp deleted file mode 100644 index 59818a4d2b..0000000000 --- a/drivers/squish/maths.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -/*! @file - - The symmetric eigensystem solver algorithm is from - http://www.geometrictools.com/Documentation/EigenSymmetric3x3.pdf -*/ - -#include "maths.h" -#include <cfloat> - -namespace squish { - -Sym3x3 ComputeWeightedCovariance( int n, Vec3 const* points, float const* weights ) -{ - // compute the centroid - float total = 0.0f; - Vec3 centroid( 0.0f ); - for( int i = 0; i < n; ++i ) - { - total += weights[i]; - centroid += weights[i]*points[i]; - } - centroid /= total; - - // accumulate the covariance matrix - Sym3x3 covariance( 0.0f ); - for( int i = 0; i < n; ++i ) - { - Vec3 a = points[i] - centroid; - Vec3 b = weights[i]*a; - - covariance[0] += a.X()*b.X(); - covariance[1] += a.X()*b.Y(); - covariance[2] += a.X()*b.Z(); - covariance[3] += a.Y()*b.Y(); - covariance[4] += a.Y()*b.Z(); - covariance[5] += a.Z()*b.Z(); - } - - // return it - return covariance; -} - -static Vec3 GetMultiplicity1Evector( Sym3x3 const& matrix, float evalue ) -{ - // compute M - Sym3x3 m; - m[0] = matrix[0] - evalue; - m[1] = matrix[1]; - m[2] = matrix[2]; - m[3] = matrix[3] - evalue; - m[4] = matrix[4]; - m[5] = matrix[5] - evalue; - - // compute U - Sym3x3 u; - u[0] = m[3]*m[5] - m[4]*m[4]; - u[1] = m[2]*m[4] - m[1]*m[5]; - u[2] = m[1]*m[4] - m[2]*m[3]; - u[3] = m[0]*m[5] - m[2]*m[2]; - u[4] = m[1]*m[2] - m[4]*m[0]; - u[5] = m[0]*m[3] - m[1]*m[1]; - - // find the largest component - float mc = std::fabs( u[0] ); - int mi = 0; - for( int i = 1; i < 6; ++i ) - { - float c = std::fabs( u[i] ); - if( c > mc ) - { - mc = c; - mi = i; - } - } - - // pick the column with this component - switch( mi ) - { - case 0: - return Vec3( u[0], u[1], u[2] ); - - case 1: - case 3: - return Vec3( u[1], u[3], u[4] ); - - default: - return Vec3( u[2], u[4], u[5] ); - } -} - -static Vec3 GetMultiplicity2Evector( Sym3x3 const& matrix, float evalue ) -{ - // compute M - Sym3x3 m; - m[0] = matrix[0] - evalue; - m[1] = matrix[1]; - m[2] = matrix[2]; - m[3] = matrix[3] - evalue; - m[4] = matrix[4]; - m[5] = matrix[5] - evalue; - - // find the largest component - float mc = std::fabs( m[0] ); - int mi = 0; - for( int i = 1; i < 6; ++i ) - { - float c = std::fabs( m[i] ); - if( c > mc ) - { - mc = c; - mi = i; - } - } - - // pick the first eigenvector based on this index - switch( mi ) - { - case 0: - case 1: - return Vec3( -m[1], m[0], 0.0f ); - - case 2: - return Vec3( m[2], 0.0f, -m[0] ); - - case 3: - case 4: - return Vec3( 0.0f, -m[4], m[3] ); - - default: - return Vec3( 0.0f, -m[5], m[4] ); - } -} - -Vec3 ComputePrincipleComponent( Sym3x3 const& matrix ) -{ - // compute the cubic coefficients - float c0 = matrix[0]*matrix[3]*matrix[5] - + 2.0f*matrix[1]*matrix[2]*matrix[4] - - matrix[0]*matrix[4]*matrix[4] - - matrix[3]*matrix[2]*matrix[2] - - matrix[5]*matrix[1]*matrix[1]; - float c1 = matrix[0]*matrix[3] + matrix[0]*matrix[5] + matrix[3]*matrix[5] - - matrix[1]*matrix[1] - matrix[2]*matrix[2] - matrix[4]*matrix[4]; - float c2 = matrix[0] + matrix[3] + matrix[5]; - - // compute the quadratic coefficients - float a = c1 - ( 1.0f/3.0f )*c2*c2; - float b = ( -2.0f/27.0f )*c2*c2*c2 + ( 1.0f/3.0f )*c1*c2 - c0; - - // compute the root count check - float Q = 0.25f*b*b + ( 1.0f/27.0f )*a*a*a; - - // test the multiplicity - if( FLT_EPSILON < Q ) - { - // only one root, which implies we have a multiple of the identity - return Vec3( 1.0f ); - } - else if( Q < -FLT_EPSILON ) - { - // three distinct roots - float theta = std::atan2( std::sqrt( -Q ), -0.5f*b ); - float rho = std::sqrt( 0.25f*b*b - Q ); - - float rt = std::pow( rho, 1.0f/3.0f ); - float ct = std::cos( theta/3.0f ); - float st = std::sin( theta/3.0f ); - - float l1 = ( 1.0f/3.0f )*c2 + 2.0f*rt*ct; - float l2 = ( 1.0f/3.0f )*c2 - rt*( ct + ( float )sqrt( 3.0f )*st ); - float l3 = ( 1.0f/3.0f )*c2 - rt*( ct - ( float )sqrt( 3.0f )*st ); - - // pick the larger - if( std::fabs( l2 ) > std::fabs( l1 ) ) - l1 = l2; - if( std::fabs( l3 ) > std::fabs( l1 ) ) - l1 = l3; - - // get the eigenvector - return GetMultiplicity1Evector( matrix, l1 ); - } - else // if( -FLT_EPSILON <= Q && Q <= FLT_EPSILON ) - { - // two roots - float rt; - if( b < 0.0f ) - rt = -std::pow( -0.5f*b, 1.0f/3.0f ); - else - rt = std::pow( 0.5f*b, 1.0f/3.0f ); - - float l1 = ( 1.0f/3.0f )*c2 + rt; // repeated - float l2 = ( 1.0f/3.0f )*c2 - 2.0f*rt; - - // get the eigenvector - if( std::fabs( l1 ) > std::fabs( l2 ) ) - return GetMultiplicity2Evector( matrix, l1 ); - else - return GetMultiplicity1Evector( matrix, l2 ); - } -} - -} // namespace squish diff --git a/drivers/squish/maths.h b/drivers/squish/maths.h deleted file mode 100644 index 769ae463f7..0000000000 --- a/drivers/squish/maths.h +++ /dev/null @@ -1,233 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_MATHS_H -#define SQUISH_MATHS_H - -#include <cmath> -#include <algorithm> -#include "config.h" - -namespace squish { - -class Vec3 -{ -public: - typedef Vec3 const& Arg; - - Vec3() - { - } - - explicit Vec3( float s ) - { - m_x = s; - m_y = s; - m_z = s; - } - - Vec3( float x, float y, float z ) - { - m_x = x; - m_y = y; - m_z = z; - } - - float X() const { return m_x; } - float Y() const { return m_y; } - float Z() const { return m_z; } - - Vec3 operator-() const - { - return Vec3( -m_x, -m_y, -m_z ); - } - - Vec3& operator+=( Arg v ) - { - m_x += v.m_x; - m_y += v.m_y; - m_z += v.m_z; - return *this; - } - - Vec3& operator-=( Arg v ) - { - m_x -= v.m_x; - m_y -= v.m_y; - m_z -= v.m_z; - return *this; - } - - Vec3& operator*=( Arg v ) - { - m_x *= v.m_x; - m_y *= v.m_y; - m_z *= v.m_z; - return *this; - } - - Vec3& operator*=( float s ) - { - m_x *= s; - m_y *= s; - m_z *= s; - return *this; - } - - Vec3& operator/=( Arg v ) - { - m_x /= v.m_x; - m_y /= v.m_y; - m_z /= v.m_z; - return *this; - } - - Vec3& operator/=( float s ) - { - float t = 1.0f/s; - m_x *= t; - m_y *= t; - m_z *= t; - return *this; - } - - friend Vec3 operator+( Arg left, Arg right ) - { - Vec3 copy( left ); - return copy += right; - } - - friend Vec3 operator-( Arg left, Arg right ) - { - Vec3 copy( left ); - return copy -= right; - } - - friend Vec3 operator*( Arg left, Arg right ) - { - Vec3 copy( left ); - return copy *= right; - } - - friend Vec3 operator*( Arg left, float right ) - { - Vec3 copy( left ); - return copy *= right; - } - - friend Vec3 operator*( float left, Arg right ) - { - Vec3 copy( right ); - return copy *= left; - } - - friend Vec3 operator/( Arg left, Arg right ) - { - Vec3 copy( left ); - return copy /= right; - } - - friend Vec3 operator/( Arg left, float right ) - { - Vec3 copy( left ); - return copy /= right; - } - - friend float Dot( Arg left, Arg right ) - { - return left.m_x*right.m_x + left.m_y*right.m_y + left.m_z*right.m_z; - } - - friend Vec3 Min( Arg left, Arg right ) - { - return Vec3( - std::min( left.m_x, right.m_x ), - std::min( left.m_y, right.m_y ), - std::min( left.m_z, right.m_z ) - ); - } - - friend Vec3 Max( Arg left, Arg right ) - { - return Vec3( - std::max( left.m_x, right.m_x ), - std::max( left.m_y, right.m_y ), - std::max( left.m_z, right.m_z ) - ); - } - - friend Vec3 Truncate( Arg v ) - { - return Vec3( - v.m_x > 0.0f ? std::floor( v.m_x ) : std::ceil( v.m_x ), - v.m_y > 0.0f ? std::floor( v.m_y ) : std::ceil( v.m_y ), - v.m_z > 0.0f ? std::floor( v.m_z ) : std::ceil( v.m_z ) - ); - } - -private: - float m_x; - float m_y; - float m_z; -}; - -inline float LengthSquared( Vec3::Arg v ) -{ - return Dot( v, v ); -} - -class Sym3x3 -{ -public: - Sym3x3() - { - } - - Sym3x3( float s ) - { - for( int i = 0; i < 6; ++i ) - m_x[i] = s; - } - - float operator[]( int index ) const - { - return m_x[index]; - } - - float& operator[]( int index ) - { - return m_x[index]; - } - -private: - float m_x[6]; -}; - -Sym3x3 ComputeWeightedCovariance( int n, Vec3 const* points, float const* weights ); -Vec3 ComputePrincipleComponent( Sym3x3 const& matrix ); - -} // namespace squish - -#endif // ndef SQUISH_MATHS_H diff --git a/drivers/squish/rangefit.cpp b/drivers/squish/rangefit.cpp deleted file mode 100644 index 5a66436056..0000000000 --- a/drivers/squish/rangefit.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "rangefit.h" -#include "colourset.h" -#include "colourblock.h" -#include <cfloat> - -namespace squish { - -RangeFit::RangeFit( ColourSet const* colours, int flags ) - : ColourFit( colours, flags ) -{ - // initialise the metric - bool perceptual = ( ( m_flags & kColourMetricPerceptual ) != 0 ); - if( perceptual ) - m_metric = Vec3( 0.2126f, 0.7152f, 0.0722f ); - else - m_metric = Vec3( 1.0f ); - - // initialise the best error - m_besterror = FLT_MAX; - - // cache some values - int const count = m_colours->GetCount(); - Vec3 const* values = m_colours->GetPoints(); - float const* weights = m_colours->GetWeights(); - - // get the covariance matrix - Sym3x3 covariance = ComputeWeightedCovariance( count, values, weights ); - - // compute the principle component - Vec3 principle = ComputePrincipleComponent( covariance ); - - // get the min and max range as the codebook endpoints - Vec3 start( 0.0f ); - Vec3 end( 0.0f ); - if( count > 0 ) - { - float min, max; - - // compute the range - start = end = values[0]; - min = max = Dot( values[0], principle ); - for( int i = 1; i < count; ++i ) - { - float val = Dot( values[i], principle ); - if( val < min ) - { - start = values[i]; - min = val; - } - else if( val > max ) - { - end = values[i]; - max = val; - } - } - } - - // clamp the output to [0, 1] - Vec3 const one( 1.0f ); - Vec3 const zero( 0.0f ); - start = Min( one, Max( zero, start ) ); - end = Min( one, Max( zero, end ) ); - - // clamp to the grid and save - Vec3 const grid( 31.0f, 63.0f, 31.0f ); - Vec3 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f ); - Vec3 const half( 0.5f ); - m_start = Truncate( grid*start + half )*gridrcp; - m_end = Truncate( grid*end + half )*gridrcp; -} - -void RangeFit::Compress3( void* block ) -{ - // cache some values - int const count = m_colours->GetCount(); - Vec3 const* values = m_colours->GetPoints(); - - // create a codebook - Vec3 codes[3]; - codes[0] = m_start; - codes[1] = m_end; - codes[2] = 0.5f*m_start + 0.5f*m_end; - - // match each point to the closest code - u8 closest[16]; - float error = 0.0f; - for( int i = 0; i < count; ++i ) - { - // find the closest code - float dist = FLT_MAX; - int idx = 0; - for( int j = 0; j < 3; ++j ) - { - float d = LengthSquared( m_metric*( values[i] - codes[j] ) ); - if( d < dist ) - { - dist = d; - idx = j; - } - } - - // save the index - closest[i] = ( u8 )idx; - - // accumulate the error - error += dist; - } - - // save this scheme if it wins - if( error < m_besterror ) - { - // remap the indices - u8 indices[16]; - m_colours->RemapIndices( closest, indices ); - - // save the block - WriteColourBlock3( m_start, m_end, indices, block ); - - // save the error - m_besterror = error; - } -} - -void RangeFit::Compress4( void* block ) -{ - // cache some values - int const count = m_colours->GetCount(); - Vec3 const* values = m_colours->GetPoints(); - - // create a codebook - Vec3 codes[4]; - codes[0] = m_start; - codes[1] = m_end; - codes[2] = ( 2.0f/3.0f )*m_start + ( 1.0f/3.0f )*m_end; - codes[3] = ( 1.0f/3.0f )*m_start + ( 2.0f/3.0f )*m_end; - - // match each point to the closest code - u8 closest[16]; - float error = 0.0f; - for( int i = 0; i < count; ++i ) - { - // find the closest code - float dist = FLT_MAX; - int idx = 0; - for( int j = 0; j < 4; ++j ) - { - float d = LengthSquared( m_metric*( values[i] - codes[j] ) ); - if( d < dist ) - { - dist = d; - idx = j; - } - } - - // save the index - closest[i] = ( u8 )idx; - - // accumulate the error - error += dist; - } - - // save this scheme if it wins - if( error < m_besterror ) - { - // remap the indices - u8 indices[16]; - m_colours->RemapIndices( closest, indices ); - - // save the block - WriteColourBlock4( m_start, m_end, indices, block ); - - // save the error - m_besterror = error; - } -} - -} // namespace squish diff --git a/drivers/squish/rangefit.h b/drivers/squish/rangefit.h deleted file mode 100644 index 9d74f9c128..0000000000 --- a/drivers/squish/rangefit.h +++ /dev/null @@ -1,54 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_RANGEFIT_H -#define SQUISH_RANGEFIT_H - -#include "squish/squish.h" -#include "colourfit.h" -#include "maths.h" - -namespace squish { - -class ColourSet; - -class RangeFit : public ColourFit -{ -public: - RangeFit( ColourSet const* colours, int flags ); - -private: - virtual void Compress3( void* block ); - virtual void Compress4( void* block ); - - Vec3 m_metric; - Vec3 m_start; - Vec3 m_end; - float m_besterror; -}; - -} // squish - -#endif // ndef SQUISH_RANGEFIT_H diff --git a/drivers/squish/simd.h b/drivers/squish/simd.h deleted file mode 100644 index 22bd10a460..0000000000 --- a/drivers/squish/simd.h +++ /dev/null @@ -1,40 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_SIMD_H -#define SQUISH_SIMD_H - -#include "maths.h" - -#if SQUISH_USE_ALTIVEC -#include "simd_ve.h" -#elif SQUISH_USE_SSE -#include "simd_sse.h" -#else -#include "simd_float.h" -#endif - - -#endif // ndef SQUISH_SIMD_H diff --git a/drivers/squish/simd_float.h b/drivers/squish/simd_float.h deleted file mode 100644 index e6351b80eb..0000000000 --- a/drivers/squish/simd_float.h +++ /dev/null @@ -1,183 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_SIMD_FLOAT_H -#define SQUISH_SIMD_FLOAT_H - -#include <algorithm> - -namespace squish { - -#define VEC4_CONST( X ) Vec4( X ) - -class Vec4 -{ -public: - typedef Vec4 const& Arg; - - Vec4() {} - - explicit Vec4( float s ) - : m_x( s ), - m_y( s ), - m_z( s ), - m_w( s ) - { - } - - Vec4( float x, float y, float z, float w ) - : m_x( x ), - m_y( y ), - m_z( z ), - m_w( w ) - { - } - - Vec3 GetVec3() const - { - return Vec3( m_x, m_y, m_z ); - } - - Vec4 SplatX() const { return Vec4( m_x ); } - Vec4 SplatY() const { return Vec4( m_y ); } - Vec4 SplatZ() const { return Vec4( m_z ); } - Vec4 SplatW() const { return Vec4( m_w ); } - - Vec4& operator+=( Arg v ) - { - m_x += v.m_x; - m_y += v.m_y; - m_z += v.m_z; - m_w += v.m_w; - return *this; - } - - Vec4& operator-=( Arg v ) - { - m_x -= v.m_x; - m_y -= v.m_y; - m_z -= v.m_z; - m_w -= v.m_w; - return *this; - } - - Vec4& operator*=( Arg v ) - { - m_x *= v.m_x; - m_y *= v.m_y; - m_z *= v.m_z; - m_w *= v.m_w; - return *this; - } - - friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right ) - { - Vec4 copy( left ); - return copy += right; - } - - friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right ) - { - Vec4 copy( left ); - return copy -= right; - } - - friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right ) - { - Vec4 copy( left ); - return copy *= right; - } - - //! Returns a*b + c - friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) - { - return a*b + c; - } - - //! Returns -( a*b - c ) - friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) - { - return c - a*b; - } - - friend Vec4 Reciprocal( Vec4::Arg v ) - { - return Vec4( - 1.0f/v.m_x, - 1.0f/v.m_y, - 1.0f/v.m_z, - 1.0f/v.m_w - ); - } - - friend Vec4 Min( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( - std::min( left.m_x, right.m_x ), - std::min( left.m_y, right.m_y ), - std::min( left.m_z, right.m_z ), - std::min( left.m_w, right.m_w ) - ); - } - - friend Vec4 Max( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( - std::max( left.m_x, right.m_x ), - std::max( left.m_y, right.m_y ), - std::max( left.m_z, right.m_z ), - std::max( left.m_w, right.m_w ) - ); - } - - friend Vec4 Truncate( Vec4::Arg v ) - { - return Vec4( - v.m_x > 0.0f ? std::floor( v.m_x ) : std::ceil( v.m_x ), - v.m_y > 0.0f ? std::floor( v.m_y ) : std::ceil( v.m_y ), - v.m_z > 0.0f ? std::floor( v.m_z ) : std::ceil( v.m_z ), - v.m_w > 0.0f ? std::floor( v.m_w ) : std::ceil( v.m_w ) - ); - } - - friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right ) - { - return left.m_x < right.m_x - || left.m_y < right.m_y - || left.m_z < right.m_z - || left.m_w < right.m_w; - } - -private: - float m_x; - float m_y; - float m_z; - float m_w; -}; - -} // namespace squish - -#endif // ndef SQUISH_SIMD_FLOAT_H - diff --git a/drivers/squish/simd_sse.h b/drivers/squish/simd_sse.h deleted file mode 100644 index e584f2a0e5..0000000000 --- a/drivers/squish/simd_sse.h +++ /dev/null @@ -1,180 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_SIMD_SSE_H -#define SQUISH_SIMD_SSE_H - -#include <xmmintrin.h> -#if ( SQUISH_USE_SSE > 1 ) -#include <emmintrin.h> -#endif - -#define SQUISH_SSE_SPLAT( a ) \ - ( ( a ) | ( ( a ) << 2 ) | ( ( a ) << 4 ) | ( ( a ) << 6 ) ) - -#define SQUISH_SSE_SHUF( x, y, z, w ) \ - ( ( x ) | ( ( y ) << 2 ) | ( ( z ) << 4 ) | ( ( w ) << 6 ) ) - -namespace squish { - -#define VEC4_CONST( X ) Vec4( X ) - -class Vec4 -{ -public: - typedef Vec4 const& Arg; - - Vec4() {} - - explicit Vec4( __m128 v ) : m_v( v ) {} - - Vec4( Vec4 const& arg ) : m_v( arg.m_v ) {} - - Vec4& operator=( Vec4 const& arg ) - { - m_v = arg.m_v; - return *this; - } - - explicit Vec4( float s ) : m_v( _mm_set1_ps( s ) ) {} - - Vec4( float x, float y, float z, float w ) : m_v( _mm_setr_ps( x, y, z, w ) ) {} - - Vec3 GetVec3() const - { -#ifdef __GNUC__ - __attribute__ ((__aligned__ (16))) float c[4]; -#else - __declspec(align(16)) float c[4]; -#endif - _mm_store_ps( c, m_v ); - return Vec3( c[0], c[1], c[2] ); - } - - Vec4 SplatX() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 0 ) ) ); } - Vec4 SplatY() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 1 ) ) ); } - Vec4 SplatZ() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 2 ) ) ); } - Vec4 SplatW() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 3 ) ) ); } - - Vec4& operator+=( Arg v ) - { - m_v = _mm_add_ps( m_v, v.m_v ); - return *this; - } - - Vec4& operator-=( Arg v ) - { - m_v = _mm_sub_ps( m_v, v.m_v ); - return *this; - } - - Vec4& operator*=( Arg v ) - { - m_v = _mm_mul_ps( m_v, v.m_v ); - return *this; - } - - friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( _mm_add_ps( left.m_v, right.m_v ) ); - } - - friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( _mm_sub_ps( left.m_v, right.m_v ) ); - } - - friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( _mm_mul_ps( left.m_v, right.m_v ) ); - } - - //! Returns a*b + c - friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) - { - return Vec4( _mm_add_ps( _mm_mul_ps( a.m_v, b.m_v ), c.m_v ) ); - } - - //! Returns -( a*b - c ) - friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) - { - return Vec4( _mm_sub_ps( c.m_v, _mm_mul_ps( a.m_v, b.m_v ) ) ); - } - - friend Vec4 Reciprocal( Vec4::Arg v ) - { - // get the reciprocal estimate - __m128 estimate = _mm_rcp_ps( v.m_v ); - - // one round of Newton-Rhaphson refinement - __m128 diff = _mm_sub_ps( _mm_set1_ps( 1.0f ), _mm_mul_ps( estimate, v.m_v ) ); - return Vec4( _mm_add_ps( _mm_mul_ps( diff, estimate ), estimate ) ); - } - - friend Vec4 Min( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( _mm_min_ps( left.m_v, right.m_v ) ); - } - - friend Vec4 Max( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( _mm_max_ps( left.m_v, right.m_v ) ); - } - - friend Vec4 Truncate( Vec4::Arg v ) - { -#if ( SQUISH_USE_SSE == 1 ) - // convert to ints - __m128 input = v.m_v; - __m64 lo = _mm_cvttps_pi32( input ); - __m64 hi = _mm_cvttps_pi32( _mm_movehl_ps( input, input ) ); - - // convert to floats - __m128 part = _mm_movelh_ps( input, _mm_cvtpi32_ps( input, hi ) ); - __m128 truncated = _mm_cvtpi32_ps( part, lo ); - - // clear out the MMX multimedia state to allow FP calls later - _mm_empty(); - return Vec4( truncated ); -#else - // use SSE2 instructions - return Vec4( _mm_cvtepi32_ps( _mm_cvttps_epi32( v.m_v ) ) ); -#endif - } - - friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right ) - { - __m128 bits = _mm_cmplt_ps( left.m_v, right.m_v ); - int value = _mm_movemask_ps( bits ); - return value != 0; - } - -private: - __m128 m_v; -}; - -} // namespace squish - -#endif // ndef SQUISH_SIMD_SSE_H diff --git a/drivers/squish/simd_ve.h b/drivers/squish/simd_ve.h deleted file mode 100644 index 9a33955ffc..0000000000 --- a/drivers/squish/simd_ve.h +++ /dev/null @@ -1,166 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_SIMD_VE_H -#define SQUISH_SIMD_VE_H - -#include <altivec.h> -#undef bool - -namespace squish { - -#define VEC4_CONST( X ) Vec4( ( vector float )( X ) ) - -class Vec4 -{ -public: - typedef Vec4 Arg; - - Vec4() {} - - explicit Vec4( vector float v ) : m_v( v ) {} - - Vec4( Vec4 const& arg ) : m_v( arg.m_v ) {} - - Vec4& operator=( Vec4 const& arg ) - { - m_v = arg.m_v; - return *this; - } - - explicit Vec4( float s ) - { - union { vector float v; float c[4]; } u; - u.c[0] = s; - u.c[1] = s; - u.c[2] = s; - u.c[3] = s; - m_v = u.v; - } - - Vec4( float x, float y, float z, float w ) - { - union { vector float v; float c[4]; } u; - u.c[0] = x; - u.c[1] = y; - u.c[2] = z; - u.c[3] = w; - m_v = u.v; - } - - Vec3 GetVec3() const - { - union { vector float v; float c[4]; } u; - u.v = m_v; - return Vec3( u.c[0], u.c[1], u.c[2] ); - } - - Vec4 SplatX() const { return Vec4( vec_splat( m_v, 0 ) ); } - Vec4 SplatY() const { return Vec4( vec_splat( m_v, 1 ) ); } - Vec4 SplatZ() const { return Vec4( vec_splat( m_v, 2 ) ); } - Vec4 SplatW() const { return Vec4( vec_splat( m_v, 3 ) ); } - - Vec4& operator+=( Arg v ) - { - m_v = vec_add( m_v, v.m_v ); - return *this; - } - - Vec4& operator-=( Arg v ) - { - m_v = vec_sub( m_v, v.m_v ); - return *this; - } - - Vec4& operator*=( Arg v ) - { - m_v = vec_madd( m_v, v.m_v, ( vector float )( -0.0f ) ); - return *this; - } - - friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( vec_add( left.m_v, right.m_v ) ); - } - - friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( vec_sub( left.m_v, right.m_v ) ); - } - - friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( vec_madd( left.m_v, right.m_v, ( vector float )( -0.0f ) ) ); - } - - //! Returns a*b + c - friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) - { - return Vec4( vec_madd( a.m_v, b.m_v, c.m_v ) ); - } - - //! Returns -( a*b - c ) - friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) - { - return Vec4( vec_nmsub( a.m_v, b.m_v, c.m_v ) ); - } - - friend Vec4 Reciprocal( Vec4::Arg v ) - { - // get the reciprocal estimate - vector float estimate = vec_re( v.m_v ); - - // one round of Newton-Rhaphson refinement - vector float diff = vec_nmsub( estimate, v.m_v, ( vector float )( 1.0f ) ); - return Vec4( vec_madd( diff, estimate, estimate ) ); - } - - friend Vec4 Min( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( vec_min( left.m_v, right.m_v ) ); - } - - friend Vec4 Max( Vec4::Arg left, Vec4::Arg right ) - { - return Vec4( vec_max( left.m_v, right.m_v ) ); - } - - friend Vec4 Truncate( Vec4::Arg v ) - { - return Vec4( vec_trunc( v.m_v ) ); - } - - friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right ) - { - return vec_any_lt( left.m_v, right.m_v ) != 0; - } - -private: - vector float m_v; -}; - -} // namespace squish - -#endif // ndef SQUISH_SIMD_VE_H diff --git a/drivers/squish/singlecolourfit.cpp b/drivers/squish/singlecolourfit.cpp deleted file mode 100644 index ac8be1ad72..0000000000 --- a/drivers/squish/singlecolourfit.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "singlecolourfit.h" -#include "colourset.h" -#include "colourblock.h" - -namespace squish { - -struct SourceBlock -{ - u8 start; - u8 end; - u8 error; -}; - -struct SingleColourLookup -{ - SourceBlock sources[2]; -}; - -#include "singlecolourlookup.inl" - -static int FloatToInt( float a, int limit ) -{ - // use ANSI round-to-zero behaviour to get round-to-nearest - int i = ( int )( a + 0.5f ); - - // clamp to the limit - if( i < 0 ) - i = 0; - else if( i > limit ) - i = limit; - - // done - return i; -} - -SingleColourFit::SingleColourFit( ColourSet const* colours, int flags ) - : ColourFit( colours, flags ) -{ - // grab the single colour - Vec3 const* values = m_colours->GetPoints(); - m_colour[0] = ( u8 )FloatToInt( 255.0f*values->X(), 255 ); - m_colour[1] = ( u8 )FloatToInt( 255.0f*values->Y(), 255 ); - m_colour[2] = ( u8 )FloatToInt( 255.0f*values->Z(), 255 ); - - // initialise the best error - m_besterror = 2147483647; //INT_MAX -} - -void SingleColourFit::Compress3( void* block ) -{ - // build the table of lookups - SingleColourLookup const* const lookups[] = - { - lookup_5_3, - lookup_6_3, - lookup_5_3 - }; - - // find the best end-points and index - ComputeEndPoints( lookups ); - - // build the block if we win - if( m_error < m_besterror ) - { - // remap the indices - u8 indices[16]; - m_colours->RemapIndices( &m_index, indices ); - - // save the block - WriteColourBlock3( m_start, m_end, indices, block ); - - // save the error - m_besterror = m_error; - } -} - -void SingleColourFit::Compress4( void* block ) -{ - // build the table of lookups - SingleColourLookup const* const lookups[] = - { - lookup_5_4, - lookup_6_4, - lookup_5_4 - }; - - // find the best end-points and index - ComputeEndPoints( lookups ); - - // build the block if we win - if( m_error < m_besterror ) - { - // remap the indices - u8 indices[16]; - m_colours->RemapIndices( &m_index, indices ); - - // save the block - WriteColourBlock4( m_start, m_end, indices, block ); - - // save the error - m_besterror = m_error; - } -} - -void SingleColourFit::ComputeEndPoints( SingleColourLookup const* const* lookups ) -{ - // check each index combination (endpoint or intermediate) - m_error = 2147483647; //INT_MAX - for( int index = 0; index < 2; ++index ) - { - // check the error for this codebook index - SourceBlock const* sources[3]; - int error = 0; - for( int channel = 0; channel < 3; ++channel ) - { - // grab the lookup table and index for this channel - SingleColourLookup const* lookup = lookups[channel]; - int target = m_colour[channel]; - - // store a pointer to the source for this channel - sources[channel] = lookup[target].sources + index; - - // accumulate the error - int diff = sources[channel]->error; - error += diff*diff; - } - - // keep it if the error is lower - if( error < m_error ) - { - m_start = Vec3( - ( float )sources[0]->start/31.0f, - ( float )sources[1]->start/63.0f, - ( float )sources[2]->start/31.0f - ); - m_end = Vec3( - ( float )sources[0]->end/31.0f, - ( float )sources[1]->end/63.0f, - ( float )sources[2]->end/31.0f - ); - m_index = ( u8 )( 2*index ); - m_error = error; - } - } -} - -} // namespace squish diff --git a/drivers/squish/singlecolourfit.h b/drivers/squish/singlecolourfit.h deleted file mode 100644 index c8dce2a5a0..0000000000 --- a/drivers/squish/singlecolourfit.h +++ /dev/null @@ -1,58 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_SINGLECOLOURFIT_H -#define SQUISH_SINGLECOLOURFIT_H - -#include "squish/squish.h" -#include "colourfit.h" - -namespace squish { - -class ColourSet; -struct SingleColourLookup; - -class SingleColourFit : public ColourFit -{ -public: - SingleColourFit( ColourSet const* colours, int flags ); - -private: - virtual void Compress3( void* block ); - virtual void Compress4( void* block ); - - void ComputeEndPoints( SingleColourLookup const* const* lookups ); - - u8 m_colour[3]; - Vec3 m_start; - Vec3 m_end; - u8 m_index; - int m_error; - int m_besterror; -}; - -} // namespace squish - -#endif // ndef SQUISH_SINGLECOLOURFIT_H diff --git a/drivers/squish/singlecolourlookup.inl b/drivers/squish/singlecolourlookup.inl deleted file mode 100644 index f1c95a1028..0000000000 --- a/drivers/squish/singlecolourlookup.inl +++ /dev/null @@ -1,1040 +0,0 @@ - -static SingleColourLookup const lookup_5_3[] = -{ - { { { 0, 0, 0 }, { 0, 0, 0 } } }, - { { { 0, 0, 1 }, { 0, 0, 1 } } }, - { { { 0, 0, 2 }, { 0, 0, 2 } } }, - { { { 0, 0, 3 }, { 0, 1, 1 } } }, - { { { 0, 0, 4 }, { 0, 1, 0 } } }, - { { { 1, 0, 3 }, { 0, 1, 1 } } }, - { { { 1, 0, 2 }, { 0, 1, 2 } } }, - { { { 1, 0, 1 }, { 0, 2, 1 } } }, - { { { 1, 0, 0 }, { 0, 2, 0 } } }, - { { { 1, 0, 1 }, { 0, 2, 1 } } }, - { { { 1, 0, 2 }, { 0, 2, 2 } } }, - { { { 1, 0, 3 }, { 0, 3, 1 } } }, - { { { 1, 0, 4 }, { 0, 3, 0 } } }, - { { { 2, 0, 3 }, { 0, 3, 1 } } }, - { { { 2, 0, 2 }, { 0, 3, 2 } } }, - { { { 2, 0, 1 }, { 0, 4, 1 } } }, - { { { 2, 0, 0 }, { 0, 4, 0 } } }, - { { { 2, 0, 1 }, { 0, 4, 1 } } }, - { { { 2, 0, 2 }, { 0, 4, 2 } } }, - { { { 2, 0, 3 }, { 0, 5, 1 } } }, - { { { 2, 0, 4 }, { 0, 5, 0 } } }, - { { { 3, 0, 3 }, { 0, 5, 1 } } }, - { { { 3, 0, 2 }, { 0, 5, 2 } } }, - { { { 3, 0, 1 }, { 0, 6, 1 } } }, - { { { 3, 0, 0 }, { 0, 6, 0 } } }, - { { { 3, 0, 1 }, { 0, 6, 1 } } }, - { { { 3, 0, 2 }, { 0, 6, 2 } } }, - { { { 3, 0, 3 }, { 0, 7, 1 } } }, - { { { 3, 0, 4 }, { 0, 7, 0 } } }, - { { { 4, 0, 4 }, { 0, 7, 1 } } }, - { { { 4, 0, 3 }, { 0, 7, 2 } } }, - { { { 4, 0, 2 }, { 1, 7, 1 } } }, - { { { 4, 0, 1 }, { 1, 7, 0 } } }, - { { { 4, 0, 0 }, { 0, 8, 0 } } }, - { { { 4, 0, 1 }, { 0, 8, 1 } } }, - { { { 4, 0, 2 }, { 2, 7, 1 } } }, - { { { 4, 0, 3 }, { 2, 7, 0 } } }, - { { { 4, 0, 4 }, { 0, 9, 0 } } }, - { { { 5, 0, 3 }, { 0, 9, 1 } } }, - { { { 5, 0, 2 }, { 3, 7, 1 } } }, - { { { 5, 0, 1 }, { 3, 7, 0 } } }, - { { { 5, 0, 0 }, { 0, 10, 0 } } }, - { { { 5, 0, 1 }, { 0, 10, 1 } } }, - { { { 5, 0, 2 }, { 0, 10, 2 } } }, - { { { 5, 0, 3 }, { 0, 11, 1 } } }, - { { { 5, 0, 4 }, { 0, 11, 0 } } }, - { { { 6, 0, 3 }, { 0, 11, 1 } } }, - { { { 6, 0, 2 }, { 0, 11, 2 } } }, - { { { 6, 0, 1 }, { 0, 12, 1 } } }, - { { { 6, 0, 0 }, { 0, 12, 0 } } }, - { { { 6, 0, 1 }, { 0, 12, 1 } } }, - { { { 6, 0, 2 }, { 0, 12, 2 } } }, - { { { 6, 0, 3 }, { 0, 13, 1 } } }, - { { { 6, 0, 4 }, { 0, 13, 0 } } }, - { { { 7, 0, 3 }, { 0, 13, 1 } } }, - { { { 7, 0, 2 }, { 0, 13, 2 } } }, - { { { 7, 0, 1 }, { 0, 14, 1 } } }, - { { { 7, 0, 0 }, { 0, 14, 0 } } }, - { { { 7, 0, 1 }, { 0, 14, 1 } } }, - { { { 7, 0, 2 }, { 0, 14, 2 } } }, - { { { 7, 0, 3 }, { 0, 15, 1 } } }, - { { { 7, 0, 4 }, { 0, 15, 0 } } }, - { { { 8, 0, 4 }, { 0, 15, 1 } } }, - { { { 8, 0, 3 }, { 0, 15, 2 } } }, - { { { 8, 0, 2 }, { 1, 15, 1 } } }, - { { { 8, 0, 1 }, { 1, 15, 0 } } }, - { { { 8, 0, 0 }, { 0, 16, 0 } } }, - { { { 8, 0, 1 }, { 0, 16, 1 } } }, - { { { 8, 0, 2 }, { 2, 15, 1 } } }, - { { { 8, 0, 3 }, { 2, 15, 0 } } }, - { { { 8, 0, 4 }, { 0, 17, 0 } } }, - { { { 9, 0, 3 }, { 0, 17, 1 } } }, - { { { 9, 0, 2 }, { 3, 15, 1 } } }, - { { { 9, 0, 1 }, { 3, 15, 0 } } }, - { { { 9, 0, 0 }, { 0, 18, 0 } } }, - { { { 9, 0, 1 }, { 0, 18, 1 } } }, - { { { 9, 0, 2 }, { 0, 18, 2 } } }, - { { { 9, 0, 3 }, { 0, 19, 1 } } }, - { { { 9, 0, 4 }, { 0, 19, 0 } } }, - { { { 10, 0, 3 }, { 0, 19, 1 } } }, - { { { 10, 0, 2 }, { 0, 19, 2 } } }, - { { { 10, 0, 1 }, { 0, 20, 1 } } }, - { { { 10, 0, 0 }, { 0, 20, 0 } } }, - { { { 10, 0, 1 }, { 0, 20, 1 } } }, - { { { 10, 0, 2 }, { 0, 20, 2 } } }, - { { { 10, 0, 3 }, { 0, 21, 1 } } }, - { { { 10, 0, 4 }, { 0, 21, 0 } } }, - { { { 11, 0, 3 }, { 0, 21, 1 } } }, - { { { 11, 0, 2 }, { 0, 21, 2 } } }, - { { { 11, 0, 1 }, { 0, 22, 1 } } }, - { { { 11, 0, 0 }, { 0, 22, 0 } } }, - { { { 11, 0, 1 }, { 0, 22, 1 } } }, - { { { 11, 0, 2 }, { 0, 22, 2 } } }, - { { { 11, 0, 3 }, { 0, 23, 1 } } }, - { { { 11, 0, 4 }, { 0, 23, 0 } } }, - { { { 12, 0, 4 }, { 0, 23, 1 } } }, - { { { 12, 0, 3 }, { 0, 23, 2 } } }, - { { { 12, 0, 2 }, { 1, 23, 1 } } }, - { { { 12, 0, 1 }, { 1, 23, 0 } } }, - { { { 12, 0, 0 }, { 0, 24, 0 } } }, - { { { 12, 0, 1 }, { 0, 24, 1 } } }, - { { { 12, 0, 2 }, { 2, 23, 1 } } }, - { { { 12, 0, 3 }, { 2, 23, 0 } } }, - { { { 12, 0, 4 }, { 0, 25, 0 } } }, - { { { 13, 0, 3 }, { 0, 25, 1 } } }, - { { { 13, 0, 2 }, { 3, 23, 1 } } }, - { { { 13, 0, 1 }, { 3, 23, 0 } } }, - { { { 13, 0, 0 }, { 0, 26, 0 } } }, - { { { 13, 0, 1 }, { 0, 26, 1 } } }, - { { { 13, 0, 2 }, { 0, 26, 2 } } }, - { { { 13, 0, 3 }, { 0, 27, 1 } } }, - { { { 13, 0, 4 }, { 0, 27, 0 } } }, - { { { 14, 0, 3 }, { 0, 27, 1 } } }, - { { { 14, 0, 2 }, { 0, 27, 2 } } }, - { { { 14, 0, 1 }, { 0, 28, 1 } } }, - { { { 14, 0, 0 }, { 0, 28, 0 } } }, - { { { 14, 0, 1 }, { 0, 28, 1 } } }, - { { { 14, 0, 2 }, { 0, 28, 2 } } }, - { { { 14, 0, 3 }, { 0, 29, 1 } } }, - { { { 14, 0, 4 }, { 0, 29, 0 } } }, - { { { 15, 0, 3 }, { 0, 29, 1 } } }, - { { { 15, 0, 2 }, { 0, 29, 2 } } }, - { { { 15, 0, 1 }, { 0, 30, 1 } } }, - { { { 15, 0, 0 }, { 0, 30, 0 } } }, - { { { 15, 0, 1 }, { 0, 30, 1 } } }, - { { { 15, 0, 2 }, { 0, 30, 2 } } }, - { { { 15, 0, 3 }, { 0, 31, 1 } } }, - { { { 15, 0, 4 }, { 0, 31, 0 } } }, - { { { 16, 0, 4 }, { 0, 31, 1 } } }, - { { { 16, 0, 3 }, { 0, 31, 2 } } }, - { { { 16, 0, 2 }, { 1, 31, 1 } } }, - { { { 16, 0, 1 }, { 1, 31, 0 } } }, - { { { 16, 0, 0 }, { 4, 28, 0 } } }, - { { { 16, 0, 1 }, { 4, 28, 1 } } }, - { { { 16, 0, 2 }, { 2, 31, 1 } } }, - { { { 16, 0, 3 }, { 2, 31, 0 } } }, - { { { 16, 0, 4 }, { 4, 29, 0 } } }, - { { { 17, 0, 3 }, { 4, 29, 1 } } }, - { { { 17, 0, 2 }, { 3, 31, 1 } } }, - { { { 17, 0, 1 }, { 3, 31, 0 } } }, - { { { 17, 0, 0 }, { 4, 30, 0 } } }, - { { { 17, 0, 1 }, { 4, 30, 1 } } }, - { { { 17, 0, 2 }, { 4, 30, 2 } } }, - { { { 17, 0, 3 }, { 4, 31, 1 } } }, - { { { 17, 0, 4 }, { 4, 31, 0 } } }, - { { { 18, 0, 3 }, { 4, 31, 1 } } }, - { { { 18, 0, 2 }, { 4, 31, 2 } } }, - { { { 18, 0, 1 }, { 5, 31, 1 } } }, - { { { 18, 0, 0 }, { 5, 31, 0 } } }, - { { { 18, 0, 1 }, { 5, 31, 1 } } }, - { { { 18, 0, 2 }, { 5, 31, 2 } } }, - { { { 18, 0, 3 }, { 6, 31, 1 } } }, - { { { 18, 0, 4 }, { 6, 31, 0 } } }, - { { { 19, 0, 3 }, { 6, 31, 1 } } }, - { { { 19, 0, 2 }, { 6, 31, 2 } } }, - { { { 19, 0, 1 }, { 7, 31, 1 } } }, - { { { 19, 0, 0 }, { 7, 31, 0 } } }, - { { { 19, 0, 1 }, { 7, 31, 1 } } }, - { { { 19, 0, 2 }, { 7, 31, 2 } } }, - { { { 19, 0, 3 }, { 8, 31, 1 } } }, - { { { 19, 0, 4 }, { 8, 31, 0 } } }, - { { { 20, 0, 4 }, { 8, 31, 1 } } }, - { { { 20, 0, 3 }, { 8, 31, 2 } } }, - { { { 20, 0, 2 }, { 9, 31, 1 } } }, - { { { 20, 0, 1 }, { 9, 31, 0 } } }, - { { { 20, 0, 0 }, { 12, 28, 0 } } }, - { { { 20, 0, 1 }, { 12, 28, 1 } } }, - { { { 20, 0, 2 }, { 10, 31, 1 } } }, - { { { 20, 0, 3 }, { 10, 31, 0 } } }, - { { { 20, 0, 4 }, { 12, 29, 0 } } }, - { { { 21, 0, 3 }, { 12, 29, 1 } } }, - { { { 21, 0, 2 }, { 11, 31, 1 } } }, - { { { 21, 0, 1 }, { 11, 31, 0 } } }, - { { { 21, 0, 0 }, { 12, 30, 0 } } }, - { { { 21, 0, 1 }, { 12, 30, 1 } } }, - { { { 21, 0, 2 }, { 12, 30, 2 } } }, - { { { 21, 0, 3 }, { 12, 31, 1 } } }, - { { { 21, 0, 4 }, { 12, 31, 0 } } }, - { { { 22, 0, 3 }, { 12, 31, 1 } } }, - { { { 22, 0, 2 }, { 12, 31, 2 } } }, - { { { 22, 0, 1 }, { 13, 31, 1 } } }, - { { { 22, 0, 0 }, { 13, 31, 0 } } }, - { { { 22, 0, 1 }, { 13, 31, 1 } } }, - { { { 22, 0, 2 }, { 13, 31, 2 } } }, - { { { 22, 0, 3 }, { 14, 31, 1 } } }, - { { { 22, 0, 4 }, { 14, 31, 0 } } }, - { { { 23, 0, 3 }, { 14, 31, 1 } } }, - { { { 23, 0, 2 }, { 14, 31, 2 } } }, - { { { 23, 0, 1 }, { 15, 31, 1 } } }, - { { { 23, 0, 0 }, { 15, 31, 0 } } }, - { { { 23, 0, 1 }, { 15, 31, 1 } } }, - { { { 23, 0, 2 }, { 15, 31, 2 } } }, - { { { 23, 0, 3 }, { 16, 31, 1 } } }, - { { { 23, 0, 4 }, { 16, 31, 0 } } }, - { { { 24, 0, 4 }, { 16, 31, 1 } } }, - { { { 24, 0, 3 }, { 16, 31, 2 } } }, - { { { 24, 0, 2 }, { 17, 31, 1 } } }, - { { { 24, 0, 1 }, { 17, 31, 0 } } }, - { { { 24, 0, 0 }, { 20, 28, 0 } } }, - { { { 24, 0, 1 }, { 20, 28, 1 } } }, - { { { 24, 0, 2 }, { 18, 31, 1 } } }, - { { { 24, 0, 3 }, { 18, 31, 0 } } }, - { { { 24, 0, 4 }, { 20, 29, 0 } } }, - { { { 25, 0, 3 }, { 20, 29, 1 } } }, - { { { 25, 0, 2 }, { 19, 31, 1 } } }, - { { { 25, 0, 1 }, { 19, 31, 0 } } }, - { { { 25, 0, 0 }, { 20, 30, 0 } } }, - { { { 25, 0, 1 }, { 20, 30, 1 } } }, - { { { 25, 0, 2 }, { 20, 30, 2 } } }, - { { { 25, 0, 3 }, { 20, 31, 1 } } }, - { { { 25, 0, 4 }, { 20, 31, 0 } } }, - { { { 26, 0, 3 }, { 20, 31, 1 } } }, - { { { 26, 0, 2 }, { 20, 31, 2 } } }, - { { { 26, 0, 1 }, { 21, 31, 1 } } }, - { { { 26, 0, 0 }, { 21, 31, 0 } } }, - { { { 26, 0, 1 }, { 21, 31, 1 } } }, - { { { 26, 0, 2 }, { 21, 31, 2 } } }, - { { { 26, 0, 3 }, { 22, 31, 1 } } }, - { { { 26, 0, 4 }, { 22, 31, 0 } } }, - { { { 27, 0, 3 }, { 22, 31, 1 } } }, - { { { 27, 0, 2 }, { 22, 31, 2 } } }, - { { { 27, 0, 1 }, { 23, 31, 1 } } }, - { { { 27, 0, 0 }, { 23, 31, 0 } } }, - { { { 27, 0, 1 }, { 23, 31, 1 } } }, - { { { 27, 0, 2 }, { 23, 31, 2 } } }, - { { { 27, 0, 3 }, { 24, 31, 1 } } }, - { { { 27, 0, 4 }, { 24, 31, 0 } } }, - { { { 28, 0, 4 }, { 24, 31, 1 } } }, - { { { 28, 0, 3 }, { 24, 31, 2 } } }, - { { { 28, 0, 2 }, { 25, 31, 1 } } }, - { { { 28, 0, 1 }, { 25, 31, 0 } } }, - { { { 28, 0, 0 }, { 28, 28, 0 } } }, - { { { 28, 0, 1 }, { 28, 28, 1 } } }, - { { { 28, 0, 2 }, { 26, 31, 1 } } }, - { { { 28, 0, 3 }, { 26, 31, 0 } } }, - { { { 28, 0, 4 }, { 28, 29, 0 } } }, - { { { 29, 0, 3 }, { 28, 29, 1 } } }, - { { { 29, 0, 2 }, { 27, 31, 1 } } }, - { { { 29, 0, 1 }, { 27, 31, 0 } } }, - { { { 29, 0, 0 }, { 28, 30, 0 } } }, - { { { 29, 0, 1 }, { 28, 30, 1 } } }, - { { { 29, 0, 2 }, { 28, 30, 2 } } }, - { { { 29, 0, 3 }, { 28, 31, 1 } } }, - { { { 29, 0, 4 }, { 28, 31, 0 } } }, - { { { 30, 0, 3 }, { 28, 31, 1 } } }, - { { { 30, 0, 2 }, { 28, 31, 2 } } }, - { { { 30, 0, 1 }, { 29, 31, 1 } } }, - { { { 30, 0, 0 }, { 29, 31, 0 } } }, - { { { 30, 0, 1 }, { 29, 31, 1 } } }, - { { { 30, 0, 2 }, { 29, 31, 2 } } }, - { { { 30, 0, 3 }, { 30, 31, 1 } } }, - { { { 30, 0, 4 }, { 30, 31, 0 } } }, - { { { 31, 0, 3 }, { 30, 31, 1 } } }, - { { { 31, 0, 2 }, { 30, 31, 2 } } }, - { { { 31, 0, 1 }, { 31, 31, 1 } } }, - { { { 31, 0, 0 }, { 31, 31, 0 } } } -}; - -static SingleColourLookup const lookup_6_3[] = -{ - { { { 0, 0, 0 }, { 0, 0, 0 } } }, - { { { 0, 0, 1 }, { 0, 1, 1 } } }, - { { { 0, 0, 2 }, { 0, 1, 0 } } }, - { { { 1, 0, 1 }, { 0, 2, 1 } } }, - { { { 1, 0, 0 }, { 0, 2, 0 } } }, - { { { 1, 0, 1 }, { 0, 3, 1 } } }, - { { { 1, 0, 2 }, { 0, 3, 0 } } }, - { { { 2, 0, 1 }, { 0, 4, 1 } } }, - { { { 2, 0, 0 }, { 0, 4, 0 } } }, - { { { 2, 0, 1 }, { 0, 5, 1 } } }, - { { { 2, 0, 2 }, { 0, 5, 0 } } }, - { { { 3, 0, 1 }, { 0, 6, 1 } } }, - { { { 3, 0, 0 }, { 0, 6, 0 } } }, - { { { 3, 0, 1 }, { 0, 7, 1 } } }, - { { { 3, 0, 2 }, { 0, 7, 0 } } }, - { { { 4, 0, 1 }, { 0, 8, 1 } } }, - { { { 4, 0, 0 }, { 0, 8, 0 } } }, - { { { 4, 0, 1 }, { 0, 9, 1 } } }, - { { { 4, 0, 2 }, { 0, 9, 0 } } }, - { { { 5, 0, 1 }, { 0, 10, 1 } } }, - { { { 5, 0, 0 }, { 0, 10, 0 } } }, - { { { 5, 0, 1 }, { 0, 11, 1 } } }, - { { { 5, 0, 2 }, { 0, 11, 0 } } }, - { { { 6, 0, 1 }, { 0, 12, 1 } } }, - { { { 6, 0, 0 }, { 0, 12, 0 } } }, - { { { 6, 0, 1 }, { 0, 13, 1 } } }, - { { { 6, 0, 2 }, { 0, 13, 0 } } }, - { { { 7, 0, 1 }, { 0, 14, 1 } } }, - { { { 7, 0, 0 }, { 0, 14, 0 } } }, - { { { 7, 0, 1 }, { 0, 15, 1 } } }, - { { { 7, 0, 2 }, { 0, 15, 0 } } }, - { { { 8, 0, 1 }, { 0, 16, 1 } } }, - { { { 8, 0, 0 }, { 0, 16, 0 } } }, - { { { 8, 0, 1 }, { 0, 17, 1 } } }, - { { { 8, 0, 2 }, { 0, 17, 0 } } }, - { { { 9, 0, 1 }, { 0, 18, 1 } } }, - { { { 9, 0, 0 }, { 0, 18, 0 } } }, - { { { 9, 0, 1 }, { 0, 19, 1 } } }, - { { { 9, 0, 2 }, { 0, 19, 0 } } }, - { { { 10, 0, 1 }, { 0, 20, 1 } } }, - { { { 10, 0, 0 }, { 0, 20, 0 } } }, - { { { 10, 0, 1 }, { 0, 21, 1 } } }, - { { { 10, 0, 2 }, { 0, 21, 0 } } }, - { { { 11, 0, 1 }, { 0, 22, 1 } } }, - { { { 11, 0, 0 }, { 0, 22, 0 } } }, - { { { 11, 0, 1 }, { 0, 23, 1 } } }, - { { { 11, 0, 2 }, { 0, 23, 0 } } }, - { { { 12, 0, 1 }, { 0, 24, 1 } } }, - { { { 12, 0, 0 }, { 0, 24, 0 } } }, - { { { 12, 0, 1 }, { 0, 25, 1 } } }, - { { { 12, 0, 2 }, { 0, 25, 0 } } }, - { { { 13, 0, 1 }, { 0, 26, 1 } } }, - { { { 13, 0, 0 }, { 0, 26, 0 } } }, - { { { 13, 0, 1 }, { 0, 27, 1 } } }, - { { { 13, 0, 2 }, { 0, 27, 0 } } }, - { { { 14, 0, 1 }, { 0, 28, 1 } } }, - { { { 14, 0, 0 }, { 0, 28, 0 } } }, - { { { 14, 0, 1 }, { 0, 29, 1 } } }, - { { { 14, 0, 2 }, { 0, 29, 0 } } }, - { { { 15, 0, 1 }, { 0, 30, 1 } } }, - { { { 15, 0, 0 }, { 0, 30, 0 } } }, - { { { 15, 0, 1 }, { 0, 31, 1 } } }, - { { { 15, 0, 2 }, { 0, 31, 0 } } }, - { { { 16, 0, 2 }, { 1, 31, 1 } } }, - { { { 16, 0, 1 }, { 1, 31, 0 } } }, - { { { 16, 0, 0 }, { 0, 32, 0 } } }, - { { { 16, 0, 1 }, { 2, 31, 0 } } }, - { { { 16, 0, 2 }, { 0, 33, 0 } } }, - { { { 17, 0, 1 }, { 3, 31, 0 } } }, - { { { 17, 0, 0 }, { 0, 34, 0 } } }, - { { { 17, 0, 1 }, { 4, 31, 0 } } }, - { { { 17, 0, 2 }, { 0, 35, 0 } } }, - { { { 18, 0, 1 }, { 5, 31, 0 } } }, - { { { 18, 0, 0 }, { 0, 36, 0 } } }, - { { { 18, 0, 1 }, { 6, 31, 0 } } }, - { { { 18, 0, 2 }, { 0, 37, 0 } } }, - { { { 19, 0, 1 }, { 7, 31, 0 } } }, - { { { 19, 0, 0 }, { 0, 38, 0 } } }, - { { { 19, 0, 1 }, { 8, 31, 0 } } }, - { { { 19, 0, 2 }, { 0, 39, 0 } } }, - { { { 20, 0, 1 }, { 9, 31, 0 } } }, - { { { 20, 0, 0 }, { 0, 40, 0 } } }, - { { { 20, 0, 1 }, { 10, 31, 0 } } }, - { { { 20, 0, 2 }, { 0, 41, 0 } } }, - { { { 21, 0, 1 }, { 11, 31, 0 } } }, - { { { 21, 0, 0 }, { 0, 42, 0 } } }, - { { { 21, 0, 1 }, { 12, 31, 0 } } }, - { { { 21, 0, 2 }, { 0, 43, 0 } } }, - { { { 22, 0, 1 }, { 13, 31, 0 } } }, - { { { 22, 0, 0 }, { 0, 44, 0 } } }, - { { { 22, 0, 1 }, { 14, 31, 0 } } }, - { { { 22, 0, 2 }, { 0, 45, 0 } } }, - { { { 23, 0, 1 }, { 15, 31, 0 } } }, - { { { 23, 0, 0 }, { 0, 46, 0 } } }, - { { { 23, 0, 1 }, { 0, 47, 1 } } }, - { { { 23, 0, 2 }, { 0, 47, 0 } } }, - { { { 24, 0, 1 }, { 0, 48, 1 } } }, - { { { 24, 0, 0 }, { 0, 48, 0 } } }, - { { { 24, 0, 1 }, { 0, 49, 1 } } }, - { { { 24, 0, 2 }, { 0, 49, 0 } } }, - { { { 25, 0, 1 }, { 0, 50, 1 } } }, - { { { 25, 0, 0 }, { 0, 50, 0 } } }, - { { { 25, 0, 1 }, { 0, 51, 1 } } }, - { { { 25, 0, 2 }, { 0, 51, 0 } } }, - { { { 26, 0, 1 }, { 0, 52, 1 } } }, - { { { 26, 0, 0 }, { 0, 52, 0 } } }, - { { { 26, 0, 1 }, { 0, 53, 1 } } }, - { { { 26, 0, 2 }, { 0, 53, 0 } } }, - { { { 27, 0, 1 }, { 0, 54, 1 } } }, - { { { 27, 0, 0 }, { 0, 54, 0 } } }, - { { { 27, 0, 1 }, { 0, 55, 1 } } }, - { { { 27, 0, 2 }, { 0, 55, 0 } } }, - { { { 28, 0, 1 }, { 0, 56, 1 } } }, - { { { 28, 0, 0 }, { 0, 56, 0 } } }, - { { { 28, 0, 1 }, { 0, 57, 1 } } }, - { { { 28, 0, 2 }, { 0, 57, 0 } } }, - { { { 29, 0, 1 }, { 0, 58, 1 } } }, - { { { 29, 0, 0 }, { 0, 58, 0 } } }, - { { { 29, 0, 1 }, { 0, 59, 1 } } }, - { { { 29, 0, 2 }, { 0, 59, 0 } } }, - { { { 30, 0, 1 }, { 0, 60, 1 } } }, - { { { 30, 0, 0 }, { 0, 60, 0 } } }, - { { { 30, 0, 1 }, { 0, 61, 1 } } }, - { { { 30, 0, 2 }, { 0, 61, 0 } } }, - { { { 31, 0, 1 }, { 0, 62, 1 } } }, - { { { 31, 0, 0 }, { 0, 62, 0 } } }, - { { { 31, 0, 1 }, { 0, 63, 1 } } }, - { { { 31, 0, 2 }, { 0, 63, 0 } } }, - { { { 32, 0, 2 }, { 1, 63, 1 } } }, - { { { 32, 0, 1 }, { 1, 63, 0 } } }, - { { { 32, 0, 0 }, { 16, 48, 0 } } }, - { { { 32, 0, 1 }, { 2, 63, 0 } } }, - { { { 32, 0, 2 }, { 16, 49, 0 } } }, - { { { 33, 0, 1 }, { 3, 63, 0 } } }, - { { { 33, 0, 0 }, { 16, 50, 0 } } }, - { { { 33, 0, 1 }, { 4, 63, 0 } } }, - { { { 33, 0, 2 }, { 16, 51, 0 } } }, - { { { 34, 0, 1 }, { 5, 63, 0 } } }, - { { { 34, 0, 0 }, { 16, 52, 0 } } }, - { { { 34, 0, 1 }, { 6, 63, 0 } } }, - { { { 34, 0, 2 }, { 16, 53, 0 } } }, - { { { 35, 0, 1 }, { 7, 63, 0 } } }, - { { { 35, 0, 0 }, { 16, 54, 0 } } }, - { { { 35, 0, 1 }, { 8, 63, 0 } } }, - { { { 35, 0, 2 }, { 16, 55, 0 } } }, - { { { 36, 0, 1 }, { 9, 63, 0 } } }, - { { { 36, 0, 0 }, { 16, 56, 0 } } }, - { { { 36, 0, 1 }, { 10, 63, 0 } } }, - { { { 36, 0, 2 }, { 16, 57, 0 } } }, - { { { 37, 0, 1 }, { 11, 63, 0 } } }, - { { { 37, 0, 0 }, { 16, 58, 0 } } }, - { { { 37, 0, 1 }, { 12, 63, 0 } } }, - { { { 37, 0, 2 }, { 16, 59, 0 } } }, - { { { 38, 0, 1 }, { 13, 63, 0 } } }, - { { { 38, 0, 0 }, { 16, 60, 0 } } }, - { { { 38, 0, 1 }, { 14, 63, 0 } } }, - { { { 38, 0, 2 }, { 16, 61, 0 } } }, - { { { 39, 0, 1 }, { 15, 63, 0 } } }, - { { { 39, 0, 0 }, { 16, 62, 0 } } }, - { { { 39, 0, 1 }, { 16, 63, 1 } } }, - { { { 39, 0, 2 }, { 16, 63, 0 } } }, - { { { 40, 0, 1 }, { 17, 63, 1 } } }, - { { { 40, 0, 0 }, { 17, 63, 0 } } }, - { { { 40, 0, 1 }, { 18, 63, 1 } } }, - { { { 40, 0, 2 }, { 18, 63, 0 } } }, - { { { 41, 0, 1 }, { 19, 63, 1 } } }, - { { { 41, 0, 0 }, { 19, 63, 0 } } }, - { { { 41, 0, 1 }, { 20, 63, 1 } } }, - { { { 41, 0, 2 }, { 20, 63, 0 } } }, - { { { 42, 0, 1 }, { 21, 63, 1 } } }, - { { { 42, 0, 0 }, { 21, 63, 0 } } }, - { { { 42, 0, 1 }, { 22, 63, 1 } } }, - { { { 42, 0, 2 }, { 22, 63, 0 } } }, - { { { 43, 0, 1 }, { 23, 63, 1 } } }, - { { { 43, 0, 0 }, { 23, 63, 0 } } }, - { { { 43, 0, 1 }, { 24, 63, 1 } } }, - { { { 43, 0, 2 }, { 24, 63, 0 } } }, - { { { 44, 0, 1 }, { 25, 63, 1 } } }, - { { { 44, 0, 0 }, { 25, 63, 0 } } }, - { { { 44, 0, 1 }, { 26, 63, 1 } } }, - { { { 44, 0, 2 }, { 26, 63, 0 } } }, - { { { 45, 0, 1 }, { 27, 63, 1 } } }, - { { { 45, 0, 0 }, { 27, 63, 0 } } }, - { { { 45, 0, 1 }, { 28, 63, 1 } } }, - { { { 45, 0, 2 }, { 28, 63, 0 } } }, - { { { 46, 0, 1 }, { 29, 63, 1 } } }, - { { { 46, 0, 0 }, { 29, 63, 0 } } }, - { { { 46, 0, 1 }, { 30, 63, 1 } } }, - { { { 46, 0, 2 }, { 30, 63, 0 } } }, - { { { 47, 0, 1 }, { 31, 63, 1 } } }, - { { { 47, 0, 0 }, { 31, 63, 0 } } }, - { { { 47, 0, 1 }, { 32, 63, 1 } } }, - { { { 47, 0, 2 }, { 32, 63, 0 } } }, - { { { 48, 0, 2 }, { 33, 63, 1 } } }, - { { { 48, 0, 1 }, { 33, 63, 0 } } }, - { { { 48, 0, 0 }, { 48, 48, 0 } } }, - { { { 48, 0, 1 }, { 34, 63, 0 } } }, - { { { 48, 0, 2 }, { 48, 49, 0 } } }, - { { { 49, 0, 1 }, { 35, 63, 0 } } }, - { { { 49, 0, 0 }, { 48, 50, 0 } } }, - { { { 49, 0, 1 }, { 36, 63, 0 } } }, - { { { 49, 0, 2 }, { 48, 51, 0 } } }, - { { { 50, 0, 1 }, { 37, 63, 0 } } }, - { { { 50, 0, 0 }, { 48, 52, 0 } } }, - { { { 50, 0, 1 }, { 38, 63, 0 } } }, - { { { 50, 0, 2 }, { 48, 53, 0 } } }, - { { { 51, 0, 1 }, { 39, 63, 0 } } }, - { { { 51, 0, 0 }, { 48, 54, 0 } } }, - { { { 51, 0, 1 }, { 40, 63, 0 } } }, - { { { 51, 0, 2 }, { 48, 55, 0 } } }, - { { { 52, 0, 1 }, { 41, 63, 0 } } }, - { { { 52, 0, 0 }, { 48, 56, 0 } } }, - { { { 52, 0, 1 }, { 42, 63, 0 } } }, - { { { 52, 0, 2 }, { 48, 57, 0 } } }, - { { { 53, 0, 1 }, { 43, 63, 0 } } }, - { { { 53, 0, 0 }, { 48, 58, 0 } } }, - { { { 53, 0, 1 }, { 44, 63, 0 } } }, - { { { 53, 0, 2 }, { 48, 59, 0 } } }, - { { { 54, 0, 1 }, { 45, 63, 0 } } }, - { { { 54, 0, 0 }, { 48, 60, 0 } } }, - { { { 54, 0, 1 }, { 46, 63, 0 } } }, - { { { 54, 0, 2 }, { 48, 61, 0 } } }, - { { { 55, 0, 1 }, { 47, 63, 0 } } }, - { { { 55, 0, 0 }, { 48, 62, 0 } } }, - { { { 55, 0, 1 }, { 48, 63, 1 } } }, - { { { 55, 0, 2 }, { 48, 63, 0 } } }, - { { { 56, 0, 1 }, { 49, 63, 1 } } }, - { { { 56, 0, 0 }, { 49, 63, 0 } } }, - { { { 56, 0, 1 }, { 50, 63, 1 } } }, - { { { 56, 0, 2 }, { 50, 63, 0 } } }, - { { { 57, 0, 1 }, { 51, 63, 1 } } }, - { { { 57, 0, 0 }, { 51, 63, 0 } } }, - { { { 57, 0, 1 }, { 52, 63, 1 } } }, - { { { 57, 0, 2 }, { 52, 63, 0 } } }, - { { { 58, 0, 1 }, { 53, 63, 1 } } }, - { { { 58, 0, 0 }, { 53, 63, 0 } } }, - { { { 58, 0, 1 }, { 54, 63, 1 } } }, - { { { 58, 0, 2 }, { 54, 63, 0 } } }, - { { { 59, 0, 1 }, { 55, 63, 1 } } }, - { { { 59, 0, 0 }, { 55, 63, 0 } } }, - { { { 59, 0, 1 }, { 56, 63, 1 } } }, - { { { 59, 0, 2 }, { 56, 63, 0 } } }, - { { { 60, 0, 1 }, { 57, 63, 1 } } }, - { { { 60, 0, 0 }, { 57, 63, 0 } } }, - { { { 60, 0, 1 }, { 58, 63, 1 } } }, - { { { 60, 0, 2 }, { 58, 63, 0 } } }, - { { { 61, 0, 1 }, { 59, 63, 1 } } }, - { { { 61, 0, 0 }, { 59, 63, 0 } } }, - { { { 61, 0, 1 }, { 60, 63, 1 } } }, - { { { 61, 0, 2 }, { 60, 63, 0 } } }, - { { { 62, 0, 1 }, { 61, 63, 1 } } }, - { { { 62, 0, 0 }, { 61, 63, 0 } } }, - { { { 62, 0, 1 }, { 62, 63, 1 } } }, - { { { 62, 0, 2 }, { 62, 63, 0 } } }, - { { { 63, 0, 1 }, { 63, 63, 1 } } }, - { { { 63, 0, 0 }, { 63, 63, 0 } } } -}; - -static SingleColourLookup const lookup_5_4[] = -{ - { { { 0, 0, 0 }, { 0, 0, 0 } } }, - { { { 0, 0, 1 }, { 0, 1, 1 } } }, - { { { 0, 0, 2 }, { 0, 1, 0 } } }, - { { { 0, 0, 3 }, { 0, 1, 1 } } }, - { { { 0, 0, 4 }, { 0, 2, 1 } } }, - { { { 1, 0, 3 }, { 0, 2, 0 } } }, - { { { 1, 0, 2 }, { 0, 2, 1 } } }, - { { { 1, 0, 1 }, { 0, 3, 1 } } }, - { { { 1, 0, 0 }, { 0, 3, 0 } } }, - { { { 1, 0, 1 }, { 1, 2, 1 } } }, - { { { 1, 0, 2 }, { 1, 2, 0 } } }, - { { { 1, 0, 3 }, { 0, 4, 0 } } }, - { { { 1, 0, 4 }, { 0, 5, 1 } } }, - { { { 2, 0, 3 }, { 0, 5, 0 } } }, - { { { 2, 0, 2 }, { 0, 5, 1 } } }, - { { { 2, 0, 1 }, { 0, 6, 1 } } }, - { { { 2, 0, 0 }, { 0, 6, 0 } } }, - { { { 2, 0, 1 }, { 2, 3, 1 } } }, - { { { 2, 0, 2 }, { 2, 3, 0 } } }, - { { { 2, 0, 3 }, { 0, 7, 0 } } }, - { { { 2, 0, 4 }, { 1, 6, 1 } } }, - { { { 3, 0, 3 }, { 1, 6, 0 } } }, - { { { 3, 0, 2 }, { 0, 8, 0 } } }, - { { { 3, 0, 1 }, { 0, 9, 1 } } }, - { { { 3, 0, 0 }, { 0, 9, 0 } } }, - { { { 3, 0, 1 }, { 0, 9, 1 } } }, - { { { 3, 0, 2 }, { 0, 10, 1 } } }, - { { { 3, 0, 3 }, { 0, 10, 0 } } }, - { { { 3, 0, 4 }, { 2, 7, 1 } } }, - { { { 4, 0, 4 }, { 2, 7, 0 } } }, - { { { 4, 0, 3 }, { 0, 11, 0 } } }, - { { { 4, 0, 2 }, { 1, 10, 1 } } }, - { { { 4, 0, 1 }, { 1, 10, 0 } } }, - { { { 4, 0, 0 }, { 0, 12, 0 } } }, - { { { 4, 0, 1 }, { 0, 13, 1 } } }, - { { { 4, 0, 2 }, { 0, 13, 0 } } }, - { { { 4, 0, 3 }, { 0, 13, 1 } } }, - { { { 4, 0, 4 }, { 0, 14, 1 } } }, - { { { 5, 0, 3 }, { 0, 14, 0 } } }, - { { { 5, 0, 2 }, { 2, 11, 1 } } }, - { { { 5, 0, 1 }, { 2, 11, 0 } } }, - { { { 5, 0, 0 }, { 0, 15, 0 } } }, - { { { 5, 0, 1 }, { 1, 14, 1 } } }, - { { { 5, 0, 2 }, { 1, 14, 0 } } }, - { { { 5, 0, 3 }, { 0, 16, 0 } } }, - { { { 5, 0, 4 }, { 0, 17, 1 } } }, - { { { 6, 0, 3 }, { 0, 17, 0 } } }, - { { { 6, 0, 2 }, { 0, 17, 1 } } }, - { { { 6, 0, 1 }, { 0, 18, 1 } } }, - { { { 6, 0, 0 }, { 0, 18, 0 } } }, - { { { 6, 0, 1 }, { 2, 15, 1 } } }, - { { { 6, 0, 2 }, { 2, 15, 0 } } }, - { { { 6, 0, 3 }, { 0, 19, 0 } } }, - { { { 6, 0, 4 }, { 1, 18, 1 } } }, - { { { 7, 0, 3 }, { 1, 18, 0 } } }, - { { { 7, 0, 2 }, { 0, 20, 0 } } }, - { { { 7, 0, 1 }, { 0, 21, 1 } } }, - { { { 7, 0, 0 }, { 0, 21, 0 } } }, - { { { 7, 0, 1 }, { 0, 21, 1 } } }, - { { { 7, 0, 2 }, { 0, 22, 1 } } }, - { { { 7, 0, 3 }, { 0, 22, 0 } } }, - { { { 7, 0, 4 }, { 2, 19, 1 } } }, - { { { 8, 0, 4 }, { 2, 19, 0 } } }, - { { { 8, 0, 3 }, { 0, 23, 0 } } }, - { { { 8, 0, 2 }, { 1, 22, 1 } } }, - { { { 8, 0, 1 }, { 1, 22, 0 } } }, - { { { 8, 0, 0 }, { 0, 24, 0 } } }, - { { { 8, 0, 1 }, { 0, 25, 1 } } }, - { { { 8, 0, 2 }, { 0, 25, 0 } } }, - { { { 8, 0, 3 }, { 0, 25, 1 } } }, - { { { 8, 0, 4 }, { 0, 26, 1 } } }, - { { { 9, 0, 3 }, { 0, 26, 0 } } }, - { { { 9, 0, 2 }, { 2, 23, 1 } } }, - { { { 9, 0, 1 }, { 2, 23, 0 } } }, - { { { 9, 0, 0 }, { 0, 27, 0 } } }, - { { { 9, 0, 1 }, { 1, 26, 1 } } }, - { { { 9, 0, 2 }, { 1, 26, 0 } } }, - { { { 9, 0, 3 }, { 0, 28, 0 } } }, - { { { 9, 0, 4 }, { 0, 29, 1 } } }, - { { { 10, 0, 3 }, { 0, 29, 0 } } }, - { { { 10, 0, 2 }, { 0, 29, 1 } } }, - { { { 10, 0, 1 }, { 0, 30, 1 } } }, - { { { 10, 0, 0 }, { 0, 30, 0 } } }, - { { { 10, 0, 1 }, { 2, 27, 1 } } }, - { { { 10, 0, 2 }, { 2, 27, 0 } } }, - { { { 10, 0, 3 }, { 0, 31, 0 } } }, - { { { 10, 0, 4 }, { 1, 30, 1 } } }, - { { { 11, 0, 3 }, { 1, 30, 0 } } }, - { { { 11, 0, 2 }, { 4, 24, 0 } } }, - { { { 11, 0, 1 }, { 1, 31, 1 } } }, - { { { 11, 0, 0 }, { 1, 31, 0 } } }, - { { { 11, 0, 1 }, { 1, 31, 1 } } }, - { { { 11, 0, 2 }, { 2, 30, 1 } } }, - { { { 11, 0, 3 }, { 2, 30, 0 } } }, - { { { 11, 0, 4 }, { 2, 31, 1 } } }, - { { { 12, 0, 4 }, { 2, 31, 0 } } }, - { { { 12, 0, 3 }, { 4, 27, 0 } } }, - { { { 12, 0, 2 }, { 3, 30, 1 } } }, - { { { 12, 0, 1 }, { 3, 30, 0 } } }, - { { { 12, 0, 0 }, { 4, 28, 0 } } }, - { { { 12, 0, 1 }, { 3, 31, 1 } } }, - { { { 12, 0, 2 }, { 3, 31, 0 } } }, - { { { 12, 0, 3 }, { 3, 31, 1 } } }, - { { { 12, 0, 4 }, { 4, 30, 1 } } }, - { { { 13, 0, 3 }, { 4, 30, 0 } } }, - { { { 13, 0, 2 }, { 6, 27, 1 } } }, - { { { 13, 0, 1 }, { 6, 27, 0 } } }, - { { { 13, 0, 0 }, { 4, 31, 0 } } }, - { { { 13, 0, 1 }, { 5, 30, 1 } } }, - { { { 13, 0, 2 }, { 5, 30, 0 } } }, - { { { 13, 0, 3 }, { 8, 24, 0 } } }, - { { { 13, 0, 4 }, { 5, 31, 1 } } }, - { { { 14, 0, 3 }, { 5, 31, 0 } } }, - { { { 14, 0, 2 }, { 5, 31, 1 } } }, - { { { 14, 0, 1 }, { 6, 30, 1 } } }, - { { { 14, 0, 0 }, { 6, 30, 0 } } }, - { { { 14, 0, 1 }, { 6, 31, 1 } } }, - { { { 14, 0, 2 }, { 6, 31, 0 } } }, - { { { 14, 0, 3 }, { 8, 27, 0 } } }, - { { { 14, 0, 4 }, { 7, 30, 1 } } }, - { { { 15, 0, 3 }, { 7, 30, 0 } } }, - { { { 15, 0, 2 }, { 8, 28, 0 } } }, - { { { 15, 0, 1 }, { 7, 31, 1 } } }, - { { { 15, 0, 0 }, { 7, 31, 0 } } }, - { { { 15, 0, 1 }, { 7, 31, 1 } } }, - { { { 15, 0, 2 }, { 8, 30, 1 } } }, - { { { 15, 0, 3 }, { 8, 30, 0 } } }, - { { { 15, 0, 4 }, { 10, 27, 1 } } }, - { { { 16, 0, 4 }, { 10, 27, 0 } } }, - { { { 16, 0, 3 }, { 8, 31, 0 } } }, - { { { 16, 0, 2 }, { 9, 30, 1 } } }, - { { { 16, 0, 1 }, { 9, 30, 0 } } }, - { { { 16, 0, 0 }, { 12, 24, 0 } } }, - { { { 16, 0, 1 }, { 9, 31, 1 } } }, - { { { 16, 0, 2 }, { 9, 31, 0 } } }, - { { { 16, 0, 3 }, { 9, 31, 1 } } }, - { { { 16, 0, 4 }, { 10, 30, 1 } } }, - { { { 17, 0, 3 }, { 10, 30, 0 } } }, - { { { 17, 0, 2 }, { 10, 31, 1 } } }, - { { { 17, 0, 1 }, { 10, 31, 0 } } }, - { { { 17, 0, 0 }, { 12, 27, 0 } } }, - { { { 17, 0, 1 }, { 11, 30, 1 } } }, - { { { 17, 0, 2 }, { 11, 30, 0 } } }, - { { { 17, 0, 3 }, { 12, 28, 0 } } }, - { { { 17, 0, 4 }, { 11, 31, 1 } } }, - { { { 18, 0, 3 }, { 11, 31, 0 } } }, - { { { 18, 0, 2 }, { 11, 31, 1 } } }, - { { { 18, 0, 1 }, { 12, 30, 1 } } }, - { { { 18, 0, 0 }, { 12, 30, 0 } } }, - { { { 18, 0, 1 }, { 14, 27, 1 } } }, - { { { 18, 0, 2 }, { 14, 27, 0 } } }, - { { { 18, 0, 3 }, { 12, 31, 0 } } }, - { { { 18, 0, 4 }, { 13, 30, 1 } } }, - { { { 19, 0, 3 }, { 13, 30, 0 } } }, - { { { 19, 0, 2 }, { 16, 24, 0 } } }, - { { { 19, 0, 1 }, { 13, 31, 1 } } }, - { { { 19, 0, 0 }, { 13, 31, 0 } } }, - { { { 19, 0, 1 }, { 13, 31, 1 } } }, - { { { 19, 0, 2 }, { 14, 30, 1 } } }, - { { { 19, 0, 3 }, { 14, 30, 0 } } }, - { { { 19, 0, 4 }, { 14, 31, 1 } } }, - { { { 20, 0, 4 }, { 14, 31, 0 } } }, - { { { 20, 0, 3 }, { 16, 27, 0 } } }, - { { { 20, 0, 2 }, { 15, 30, 1 } } }, - { { { 20, 0, 1 }, { 15, 30, 0 } } }, - { { { 20, 0, 0 }, { 16, 28, 0 } } }, - { { { 20, 0, 1 }, { 15, 31, 1 } } }, - { { { 20, 0, 2 }, { 15, 31, 0 } } }, - { { { 20, 0, 3 }, { 15, 31, 1 } } }, - { { { 20, 0, 4 }, { 16, 30, 1 } } }, - { { { 21, 0, 3 }, { 16, 30, 0 } } }, - { { { 21, 0, 2 }, { 18, 27, 1 } } }, - { { { 21, 0, 1 }, { 18, 27, 0 } } }, - { { { 21, 0, 0 }, { 16, 31, 0 } } }, - { { { 21, 0, 1 }, { 17, 30, 1 } } }, - { { { 21, 0, 2 }, { 17, 30, 0 } } }, - { { { 21, 0, 3 }, { 20, 24, 0 } } }, - { { { 21, 0, 4 }, { 17, 31, 1 } } }, - { { { 22, 0, 3 }, { 17, 31, 0 } } }, - { { { 22, 0, 2 }, { 17, 31, 1 } } }, - { { { 22, 0, 1 }, { 18, 30, 1 } } }, - { { { 22, 0, 0 }, { 18, 30, 0 } } }, - { { { 22, 0, 1 }, { 18, 31, 1 } } }, - { { { 22, 0, 2 }, { 18, 31, 0 } } }, - { { { 22, 0, 3 }, { 20, 27, 0 } } }, - { { { 22, 0, 4 }, { 19, 30, 1 } } }, - { { { 23, 0, 3 }, { 19, 30, 0 } } }, - { { { 23, 0, 2 }, { 20, 28, 0 } } }, - { { { 23, 0, 1 }, { 19, 31, 1 } } }, - { { { 23, 0, 0 }, { 19, 31, 0 } } }, - { { { 23, 0, 1 }, { 19, 31, 1 } } }, - { { { 23, 0, 2 }, { 20, 30, 1 } } }, - { { { 23, 0, 3 }, { 20, 30, 0 } } }, - { { { 23, 0, 4 }, { 22, 27, 1 } } }, - { { { 24, 0, 4 }, { 22, 27, 0 } } }, - { { { 24, 0, 3 }, { 20, 31, 0 } } }, - { { { 24, 0, 2 }, { 21, 30, 1 } } }, - { { { 24, 0, 1 }, { 21, 30, 0 } } }, - { { { 24, 0, 0 }, { 24, 24, 0 } } }, - { { { 24, 0, 1 }, { 21, 31, 1 } } }, - { { { 24, 0, 2 }, { 21, 31, 0 } } }, - { { { 24, 0, 3 }, { 21, 31, 1 } } }, - { { { 24, 0, 4 }, { 22, 30, 1 } } }, - { { { 25, 0, 3 }, { 22, 30, 0 } } }, - { { { 25, 0, 2 }, { 22, 31, 1 } } }, - { { { 25, 0, 1 }, { 22, 31, 0 } } }, - { { { 25, 0, 0 }, { 24, 27, 0 } } }, - { { { 25, 0, 1 }, { 23, 30, 1 } } }, - { { { 25, 0, 2 }, { 23, 30, 0 } } }, - { { { 25, 0, 3 }, { 24, 28, 0 } } }, - { { { 25, 0, 4 }, { 23, 31, 1 } } }, - { { { 26, 0, 3 }, { 23, 31, 0 } } }, - { { { 26, 0, 2 }, { 23, 31, 1 } } }, - { { { 26, 0, 1 }, { 24, 30, 1 } } }, - { { { 26, 0, 0 }, { 24, 30, 0 } } }, - { { { 26, 0, 1 }, { 26, 27, 1 } } }, - { { { 26, 0, 2 }, { 26, 27, 0 } } }, - { { { 26, 0, 3 }, { 24, 31, 0 } } }, - { { { 26, 0, 4 }, { 25, 30, 1 } } }, - { { { 27, 0, 3 }, { 25, 30, 0 } } }, - { { { 27, 0, 2 }, { 28, 24, 0 } } }, - { { { 27, 0, 1 }, { 25, 31, 1 } } }, - { { { 27, 0, 0 }, { 25, 31, 0 } } }, - { { { 27, 0, 1 }, { 25, 31, 1 } } }, - { { { 27, 0, 2 }, { 26, 30, 1 } } }, - { { { 27, 0, 3 }, { 26, 30, 0 } } }, - { { { 27, 0, 4 }, { 26, 31, 1 } } }, - { { { 28, 0, 4 }, { 26, 31, 0 } } }, - { { { 28, 0, 3 }, { 28, 27, 0 } } }, - { { { 28, 0, 2 }, { 27, 30, 1 } } }, - { { { 28, 0, 1 }, { 27, 30, 0 } } }, - { { { 28, 0, 0 }, { 28, 28, 0 } } }, - { { { 28, 0, 1 }, { 27, 31, 1 } } }, - { { { 28, 0, 2 }, { 27, 31, 0 } } }, - { { { 28, 0, 3 }, { 27, 31, 1 } } }, - { { { 28, 0, 4 }, { 28, 30, 1 } } }, - { { { 29, 0, 3 }, { 28, 30, 0 } } }, - { { { 29, 0, 2 }, { 30, 27, 1 } } }, - { { { 29, 0, 1 }, { 30, 27, 0 } } }, - { { { 29, 0, 0 }, { 28, 31, 0 } } }, - { { { 29, 0, 1 }, { 29, 30, 1 } } }, - { { { 29, 0, 2 }, { 29, 30, 0 } } }, - { { { 29, 0, 3 }, { 29, 30, 1 } } }, - { { { 29, 0, 4 }, { 29, 31, 1 } } }, - { { { 30, 0, 3 }, { 29, 31, 0 } } }, - { { { 30, 0, 2 }, { 29, 31, 1 } } }, - { { { 30, 0, 1 }, { 30, 30, 1 } } }, - { { { 30, 0, 0 }, { 30, 30, 0 } } }, - { { { 30, 0, 1 }, { 30, 31, 1 } } }, - { { { 30, 0, 2 }, { 30, 31, 0 } } }, - { { { 30, 0, 3 }, { 30, 31, 1 } } }, - { { { 30, 0, 4 }, { 31, 30, 1 } } }, - { { { 31, 0, 3 }, { 31, 30, 0 } } }, - { { { 31, 0, 2 }, { 31, 30, 1 } } }, - { { { 31, 0, 1 }, { 31, 31, 1 } } }, - { { { 31, 0, 0 }, { 31, 31, 0 } } } -}; - -static SingleColourLookup const lookup_6_4[] = -{ - { { { 0, 0, 0 }, { 0, 0, 0 } } }, - { { { 0, 0, 1 }, { 0, 1, 0 } } }, - { { { 0, 0, 2 }, { 0, 2, 0 } } }, - { { { 1, 0, 1 }, { 0, 3, 1 } } }, - { { { 1, 0, 0 }, { 0, 3, 0 } } }, - { { { 1, 0, 1 }, { 0, 4, 0 } } }, - { { { 1, 0, 2 }, { 0, 5, 0 } } }, - { { { 2, 0, 1 }, { 0, 6, 1 } } }, - { { { 2, 0, 0 }, { 0, 6, 0 } } }, - { { { 2, 0, 1 }, { 0, 7, 0 } } }, - { { { 2, 0, 2 }, { 0, 8, 0 } } }, - { { { 3, 0, 1 }, { 0, 9, 1 } } }, - { { { 3, 0, 0 }, { 0, 9, 0 } } }, - { { { 3, 0, 1 }, { 0, 10, 0 } } }, - { { { 3, 0, 2 }, { 0, 11, 0 } } }, - { { { 4, 0, 1 }, { 0, 12, 1 } } }, - { { { 4, 0, 0 }, { 0, 12, 0 } } }, - { { { 4, 0, 1 }, { 0, 13, 0 } } }, - { { { 4, 0, 2 }, { 0, 14, 0 } } }, - { { { 5, 0, 1 }, { 0, 15, 1 } } }, - { { { 5, 0, 0 }, { 0, 15, 0 } } }, - { { { 5, 0, 1 }, { 0, 16, 0 } } }, - { { { 5, 0, 2 }, { 1, 15, 0 } } }, - { { { 6, 0, 1 }, { 0, 17, 0 } } }, - { { { 6, 0, 0 }, { 0, 18, 0 } } }, - { { { 6, 0, 1 }, { 0, 19, 0 } } }, - { { { 6, 0, 2 }, { 3, 14, 0 } } }, - { { { 7, 0, 1 }, { 0, 20, 0 } } }, - { { { 7, 0, 0 }, { 0, 21, 0 } } }, - { { { 7, 0, 1 }, { 0, 22, 0 } } }, - { { { 7, 0, 2 }, { 4, 15, 0 } } }, - { { { 8, 0, 1 }, { 0, 23, 0 } } }, - { { { 8, 0, 0 }, { 0, 24, 0 } } }, - { { { 8, 0, 1 }, { 0, 25, 0 } } }, - { { { 8, 0, 2 }, { 6, 14, 0 } } }, - { { { 9, 0, 1 }, { 0, 26, 0 } } }, - { { { 9, 0, 0 }, { 0, 27, 0 } } }, - { { { 9, 0, 1 }, { 0, 28, 0 } } }, - { { { 9, 0, 2 }, { 7, 15, 0 } } }, - { { { 10, 0, 1 }, { 0, 29, 0 } } }, - { { { 10, 0, 0 }, { 0, 30, 0 } } }, - { { { 10, 0, 1 }, { 0, 31, 0 } } }, - { { { 10, 0, 2 }, { 9, 14, 0 } } }, - { { { 11, 0, 1 }, { 0, 32, 0 } } }, - { { { 11, 0, 0 }, { 0, 33, 0 } } }, - { { { 11, 0, 1 }, { 2, 30, 0 } } }, - { { { 11, 0, 2 }, { 0, 34, 0 } } }, - { { { 12, 0, 1 }, { 0, 35, 0 } } }, - { { { 12, 0, 0 }, { 0, 36, 0 } } }, - { { { 12, 0, 1 }, { 3, 31, 0 } } }, - { { { 12, 0, 2 }, { 0, 37, 0 } } }, - { { { 13, 0, 1 }, { 0, 38, 0 } } }, - { { { 13, 0, 0 }, { 0, 39, 0 } } }, - { { { 13, 0, 1 }, { 5, 30, 0 } } }, - { { { 13, 0, 2 }, { 0, 40, 0 } } }, - { { { 14, 0, 1 }, { 0, 41, 0 } } }, - { { { 14, 0, 0 }, { 0, 42, 0 } } }, - { { { 14, 0, 1 }, { 6, 31, 0 } } }, - { { { 14, 0, 2 }, { 0, 43, 0 } } }, - { { { 15, 0, 1 }, { 0, 44, 0 } } }, - { { { 15, 0, 0 }, { 0, 45, 0 } } }, - { { { 15, 0, 1 }, { 8, 30, 0 } } }, - { { { 15, 0, 2 }, { 0, 46, 0 } } }, - { { { 16, 0, 2 }, { 0, 47, 0 } } }, - { { { 16, 0, 1 }, { 1, 46, 0 } } }, - { { { 16, 0, 0 }, { 0, 48, 0 } } }, - { { { 16, 0, 1 }, { 0, 49, 0 } } }, - { { { 16, 0, 2 }, { 0, 50, 0 } } }, - { { { 17, 0, 1 }, { 2, 47, 0 } } }, - { { { 17, 0, 0 }, { 0, 51, 0 } } }, - { { { 17, 0, 1 }, { 0, 52, 0 } } }, - { { { 17, 0, 2 }, { 0, 53, 0 } } }, - { { { 18, 0, 1 }, { 4, 46, 0 } } }, - { { { 18, 0, 0 }, { 0, 54, 0 } } }, - { { { 18, 0, 1 }, { 0, 55, 0 } } }, - { { { 18, 0, 2 }, { 0, 56, 0 } } }, - { { { 19, 0, 1 }, { 5, 47, 0 } } }, - { { { 19, 0, 0 }, { 0, 57, 0 } } }, - { { { 19, 0, 1 }, { 0, 58, 0 } } }, - { { { 19, 0, 2 }, { 0, 59, 0 } } }, - { { { 20, 0, 1 }, { 7, 46, 0 } } }, - { { { 20, 0, 0 }, { 0, 60, 0 } } }, - { { { 20, 0, 1 }, { 0, 61, 0 } } }, - { { { 20, 0, 2 }, { 0, 62, 0 } } }, - { { { 21, 0, 1 }, { 8, 47, 0 } } }, - { { { 21, 0, 0 }, { 0, 63, 0 } } }, - { { { 21, 0, 1 }, { 1, 62, 0 } } }, - { { { 21, 0, 2 }, { 1, 63, 0 } } }, - { { { 22, 0, 1 }, { 10, 46, 0 } } }, - { { { 22, 0, 0 }, { 2, 62, 0 } } }, - { { { 22, 0, 1 }, { 2, 63, 0 } } }, - { { { 22, 0, 2 }, { 3, 62, 0 } } }, - { { { 23, 0, 1 }, { 11, 47, 0 } } }, - { { { 23, 0, 0 }, { 3, 63, 0 } } }, - { { { 23, 0, 1 }, { 4, 62, 0 } } }, - { { { 23, 0, 2 }, { 4, 63, 0 } } }, - { { { 24, 0, 1 }, { 13, 46, 0 } } }, - { { { 24, 0, 0 }, { 5, 62, 0 } } }, - { { { 24, 0, 1 }, { 5, 63, 0 } } }, - { { { 24, 0, 2 }, { 6, 62, 0 } } }, - { { { 25, 0, 1 }, { 14, 47, 0 } } }, - { { { 25, 0, 0 }, { 6, 63, 0 } } }, - { { { 25, 0, 1 }, { 7, 62, 0 } } }, - { { { 25, 0, 2 }, { 7, 63, 0 } } }, - { { { 26, 0, 1 }, { 16, 45, 0 } } }, - { { { 26, 0, 0 }, { 8, 62, 0 } } }, - { { { 26, 0, 1 }, { 8, 63, 0 } } }, - { { { 26, 0, 2 }, { 9, 62, 0 } } }, - { { { 27, 0, 1 }, { 16, 48, 0 } } }, - { { { 27, 0, 0 }, { 9, 63, 0 } } }, - { { { 27, 0, 1 }, { 10, 62, 0 } } }, - { { { 27, 0, 2 }, { 10, 63, 0 } } }, - { { { 28, 0, 1 }, { 16, 51, 0 } } }, - { { { 28, 0, 0 }, { 11, 62, 0 } } }, - { { { 28, 0, 1 }, { 11, 63, 0 } } }, - { { { 28, 0, 2 }, { 12, 62, 0 } } }, - { { { 29, 0, 1 }, { 16, 54, 0 } } }, - { { { 29, 0, 0 }, { 12, 63, 0 } } }, - { { { 29, 0, 1 }, { 13, 62, 0 } } }, - { { { 29, 0, 2 }, { 13, 63, 0 } } }, - { { { 30, 0, 1 }, { 16, 57, 0 } } }, - { { { 30, 0, 0 }, { 14, 62, 0 } } }, - { { { 30, 0, 1 }, { 14, 63, 0 } } }, - { { { 30, 0, 2 }, { 15, 62, 0 } } }, - { { { 31, 0, 1 }, { 16, 60, 0 } } }, - { { { 31, 0, 0 }, { 15, 63, 0 } } }, - { { { 31, 0, 1 }, { 24, 46, 0 } } }, - { { { 31, 0, 2 }, { 16, 62, 0 } } }, - { { { 32, 0, 2 }, { 16, 63, 0 } } }, - { { { 32, 0, 1 }, { 17, 62, 0 } } }, - { { { 32, 0, 0 }, { 25, 47, 0 } } }, - { { { 32, 0, 1 }, { 17, 63, 0 } } }, - { { { 32, 0, 2 }, { 18, 62, 0 } } }, - { { { 33, 0, 1 }, { 18, 63, 0 } } }, - { { { 33, 0, 0 }, { 27, 46, 0 } } }, - { { { 33, 0, 1 }, { 19, 62, 0 } } }, - { { { 33, 0, 2 }, { 19, 63, 0 } } }, - { { { 34, 0, 1 }, { 20, 62, 0 } } }, - { { { 34, 0, 0 }, { 28, 47, 0 } } }, - { { { 34, 0, 1 }, { 20, 63, 0 } } }, - { { { 34, 0, 2 }, { 21, 62, 0 } } }, - { { { 35, 0, 1 }, { 21, 63, 0 } } }, - { { { 35, 0, 0 }, { 30, 46, 0 } } }, - { { { 35, 0, 1 }, { 22, 62, 0 } } }, - { { { 35, 0, 2 }, { 22, 63, 0 } } }, - { { { 36, 0, 1 }, { 23, 62, 0 } } }, - { { { 36, 0, 0 }, { 31, 47, 0 } } }, - { { { 36, 0, 1 }, { 23, 63, 0 } } }, - { { { 36, 0, 2 }, { 24, 62, 0 } } }, - { { { 37, 0, 1 }, { 24, 63, 0 } } }, - { { { 37, 0, 0 }, { 32, 47, 0 } } }, - { { { 37, 0, 1 }, { 25, 62, 0 } } }, - { { { 37, 0, 2 }, { 25, 63, 0 } } }, - { { { 38, 0, 1 }, { 26, 62, 0 } } }, - { { { 38, 0, 0 }, { 32, 50, 0 } } }, - { { { 38, 0, 1 }, { 26, 63, 0 } } }, - { { { 38, 0, 2 }, { 27, 62, 0 } } }, - { { { 39, 0, 1 }, { 27, 63, 0 } } }, - { { { 39, 0, 0 }, { 32, 53, 0 } } }, - { { { 39, 0, 1 }, { 28, 62, 0 } } }, - { { { 39, 0, 2 }, { 28, 63, 0 } } }, - { { { 40, 0, 1 }, { 29, 62, 0 } } }, - { { { 40, 0, 0 }, { 32, 56, 0 } } }, - { { { 40, 0, 1 }, { 29, 63, 0 } } }, - { { { 40, 0, 2 }, { 30, 62, 0 } } }, - { { { 41, 0, 1 }, { 30, 63, 0 } } }, - { { { 41, 0, 0 }, { 32, 59, 0 } } }, - { { { 41, 0, 1 }, { 31, 62, 0 } } }, - { { { 41, 0, 2 }, { 31, 63, 0 } } }, - { { { 42, 0, 1 }, { 32, 61, 0 } } }, - { { { 42, 0, 0 }, { 32, 62, 0 } } }, - { { { 42, 0, 1 }, { 32, 63, 0 } } }, - { { { 42, 0, 2 }, { 41, 46, 0 } } }, - { { { 43, 0, 1 }, { 33, 62, 0 } } }, - { { { 43, 0, 0 }, { 33, 63, 0 } } }, - { { { 43, 0, 1 }, { 34, 62, 0 } } }, - { { { 43, 0, 2 }, { 42, 47, 0 } } }, - { { { 44, 0, 1 }, { 34, 63, 0 } } }, - { { { 44, 0, 0 }, { 35, 62, 0 } } }, - { { { 44, 0, 1 }, { 35, 63, 0 } } }, - { { { 44, 0, 2 }, { 44, 46, 0 } } }, - { { { 45, 0, 1 }, { 36, 62, 0 } } }, - { { { 45, 0, 0 }, { 36, 63, 0 } } }, - { { { 45, 0, 1 }, { 37, 62, 0 } } }, - { { { 45, 0, 2 }, { 45, 47, 0 } } }, - { { { 46, 0, 1 }, { 37, 63, 0 } } }, - { { { 46, 0, 0 }, { 38, 62, 0 } } }, - { { { 46, 0, 1 }, { 38, 63, 0 } } }, - { { { 46, 0, 2 }, { 47, 46, 0 } } }, - { { { 47, 0, 1 }, { 39, 62, 0 } } }, - { { { 47, 0, 0 }, { 39, 63, 0 } } }, - { { { 47, 0, 1 }, { 40, 62, 0 } } }, - { { { 47, 0, 2 }, { 48, 46, 0 } } }, - { { { 48, 0, 2 }, { 40, 63, 0 } } }, - { { { 48, 0, 1 }, { 41, 62, 0 } } }, - { { { 48, 0, 0 }, { 41, 63, 0 } } }, - { { { 48, 0, 1 }, { 48, 49, 0 } } }, - { { { 48, 0, 2 }, { 42, 62, 0 } } }, - { { { 49, 0, 1 }, { 42, 63, 0 } } }, - { { { 49, 0, 0 }, { 43, 62, 0 } } }, - { { { 49, 0, 1 }, { 48, 52, 0 } } }, - { { { 49, 0, 2 }, { 43, 63, 0 } } }, - { { { 50, 0, 1 }, { 44, 62, 0 } } }, - { { { 50, 0, 0 }, { 44, 63, 0 } } }, - { { { 50, 0, 1 }, { 48, 55, 0 } } }, - { { { 50, 0, 2 }, { 45, 62, 0 } } }, - { { { 51, 0, 1 }, { 45, 63, 0 } } }, - { { { 51, 0, 0 }, { 46, 62, 0 } } }, - { { { 51, 0, 1 }, { 48, 58, 0 } } }, - { { { 51, 0, 2 }, { 46, 63, 0 } } }, - { { { 52, 0, 1 }, { 47, 62, 0 } } }, - { { { 52, 0, 0 }, { 47, 63, 0 } } }, - { { { 52, 0, 1 }, { 48, 61, 0 } } }, - { { { 52, 0, 2 }, { 48, 62, 0 } } }, - { { { 53, 0, 1 }, { 56, 47, 0 } } }, - { { { 53, 0, 0 }, { 48, 63, 0 } } }, - { { { 53, 0, 1 }, { 49, 62, 0 } } }, - { { { 53, 0, 2 }, { 49, 63, 0 } } }, - { { { 54, 0, 1 }, { 58, 46, 0 } } }, - { { { 54, 0, 0 }, { 50, 62, 0 } } }, - { { { 54, 0, 1 }, { 50, 63, 0 } } }, - { { { 54, 0, 2 }, { 51, 62, 0 } } }, - { { { 55, 0, 1 }, { 59, 47, 0 } } }, - { { { 55, 0, 0 }, { 51, 63, 0 } } }, - { { { 55, 0, 1 }, { 52, 62, 0 } } }, - { { { 55, 0, 2 }, { 52, 63, 0 } } }, - { { { 56, 0, 1 }, { 61, 46, 0 } } }, - { { { 56, 0, 0 }, { 53, 62, 0 } } }, - { { { 56, 0, 1 }, { 53, 63, 0 } } }, - { { { 56, 0, 2 }, { 54, 62, 0 } } }, - { { { 57, 0, 1 }, { 62, 47, 0 } } }, - { { { 57, 0, 0 }, { 54, 63, 0 } } }, - { { { 57, 0, 1 }, { 55, 62, 0 } } }, - { { { 57, 0, 2 }, { 55, 63, 0 } } }, - { { { 58, 0, 1 }, { 56, 62, 1 } } }, - { { { 58, 0, 0 }, { 56, 62, 0 } } }, - { { { 58, 0, 1 }, { 56, 63, 0 } } }, - { { { 58, 0, 2 }, { 57, 62, 0 } } }, - { { { 59, 0, 1 }, { 57, 63, 1 } } }, - { { { 59, 0, 0 }, { 57, 63, 0 } } }, - { { { 59, 0, 1 }, { 58, 62, 0 } } }, - { { { 59, 0, 2 }, { 58, 63, 0 } } }, - { { { 60, 0, 1 }, { 59, 62, 1 } } }, - { { { 60, 0, 0 }, { 59, 62, 0 } } }, - { { { 60, 0, 1 }, { 59, 63, 0 } } }, - { { { 60, 0, 2 }, { 60, 62, 0 } } }, - { { { 61, 0, 1 }, { 60, 63, 1 } } }, - { { { 61, 0, 0 }, { 60, 63, 0 } } }, - { { { 61, 0, 1 }, { 61, 62, 0 } } }, - { { { 61, 0, 2 }, { 61, 63, 0 } } }, - { { { 62, 0, 1 }, { 62, 62, 1 } } }, - { { { 62, 0, 0 }, { 62, 62, 0 } } }, - { { { 62, 0, 1 }, { 62, 63, 0 } } }, - { { { 62, 0, 2 }, { 63, 62, 0 } } }, - { { { 63, 0, 1 }, { 63, 63, 1 } } }, - { { { 63, 0, 0 }, { 63, 63, 0 } } } -}; diff --git a/drivers/squish/squish.cpp b/drivers/squish/squish.cpp deleted file mode 100644 index 400a3b0c46..0000000000 --- a/drivers/squish/squish.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#include "squish/squish.h" -#include "colourset.h" -#include "maths.h" -#include "rangefit.h" -#include "clusterfit.h" -#include "colourblock.h" -#include "alpha.h" -#include "singlecolourfit.h" - -namespace squish { - -static int FixFlags( int flags ) -{ - // grab the flag bits - int method = flags & ( kDxt1 | kDxt3 | kDxt5 ); - int fit = flags & ( kColourIterativeClusterFit | kColourClusterFit | kColourRangeFit ); - int metric = flags & ( kColourMetricPerceptual | kColourMetricUniform ); - int extra = flags & kWeightColourByAlpha; - - // set defaults - if( method != kDxt3 && method != kDxt5 ) - method = kDxt1; - if( fit != kColourRangeFit ) - fit = kColourClusterFit; - if( metric != kColourMetricUniform ) - metric = kColourMetricPerceptual; - - // done - return method | fit | metric | extra; -} - -void Compress( u8 const* rgba, void* block, int flags ) -{ - // compress with full mask - CompressMasked( rgba, 0xffff, block, flags ); -} - -void CompressMasked( u8 const* rgba, int mask, void* block, int flags ) -{ - // fix any bad flags - flags = FixFlags( flags ); - - // get the block locations - void* colourBlock = block; - void* alphaBock = block; - if( ( flags & ( kDxt3 | kDxt5 ) ) != 0 ) - colourBlock = reinterpret_cast< u8* >( block ) + 8; - - // create the minimal point set - ColourSet colours( rgba, mask, flags ); - - // check the compression type and compress colour - if( colours.GetCount() == 1 ) - { - // always do a single colour fit - SingleColourFit fit( &colours, flags ); - fit.Compress( colourBlock ); - } - else if( ( flags & kColourRangeFit ) != 0 || colours.GetCount() == 0 ) - { - // do a range fit - RangeFit fit( &colours, flags ); - fit.Compress( colourBlock ); - } - else - { - // default to a cluster fit (could be iterative or not) - ClusterFit fit( &colours, flags ); - fit.Compress( colourBlock ); - } - - // compress alpha separately if necessary - if( ( flags & kDxt3 ) != 0 ) - CompressAlphaDxt3( rgba, mask, alphaBock ); - else if( ( flags & kDxt5 ) != 0 ) - CompressAlphaDxt5( rgba, mask, alphaBock ); -} - -void Decompress( u8* rgba, void const* block, int flags ) -{ - // fix any bad flags - flags = FixFlags( flags ); - - // get the block locations - void const* colourBlock = block; - void const* alphaBock = block; - if( ( flags & ( kDxt3 | kDxt5 ) ) != 0 ) - colourBlock = reinterpret_cast< u8 const* >( block ) + 8; - - // decompress colour - DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); - - // decompress alpha separately if necessary - if( ( flags & kDxt3 ) != 0 ) - DecompressAlphaDxt3( rgba, alphaBock ); - else if( ( flags & kDxt5 ) != 0 ) - DecompressAlphaDxt5( rgba, alphaBock ); -} - -int GetStorageRequirements( int width, int height, int flags ) -{ - // fix any bad flags - flags = FixFlags( flags ); - - // compute the storage requirements - int blockcount = ( ( width + 3 )/4 ) * ( ( height + 3 )/4 ); - int blocksize = ( ( flags & kDxt1 ) != 0 ) ? 8 : 16; - return blockcount*blocksize; -} - -void CompressImage( u8 const* rgba, int width, int height, void* blocks, int flags ) -{ - // fix any bad flags - flags = FixFlags( flags ); - - // initialise the block output - u8* targetBlock = reinterpret_cast< u8* >( blocks ); - int bytesPerBlock = ( ( flags & kDxt1 ) != 0 ) ? 8 : 16; - - // loop over blocks - for( int y = 0; y < height; y += 4 ) - { - for( int x = 0; x < width; x += 4 ) - { - // build the 4x4 block of pixels - u8 sourceRgba[16*4]; - u8* targetPixel = sourceRgba; - int mask = 0; - for( int py = 0; py < 4; ++py ) - { - for( int px = 0; px < 4; ++px ) - { - // get the source pixel in the image - int sx = x + px; - int sy = y + py; - - // enable if we're in the image - if( sx < width && sy < height ) - { - // copy the rgba value - u8 const* sourcePixel = rgba + 4*( width*sy + sx ); - for( int i = 0; i < 4; ++i ) - *targetPixel++ = *sourcePixel++; - - // enable this pixel - mask |= ( 1 << ( 4*py + px ) ); - } - else - { - // skip this pixel as its outside the image - targetPixel += 4; - } - } - } - - // compress it into the output - CompressMasked( sourceRgba, mask, targetBlock, flags ); - - // advance - targetBlock += bytesPerBlock; - } - } -} - -void DecompressImage( u8* rgba, int width, int height, void const* blocks, int flags ) -{ - // fix any bad flags - flags = FixFlags( flags ); - - // initialise the block input - u8 const* sourceBlock = reinterpret_cast< u8 const* >( blocks ); - int bytesPerBlock = ( ( flags & kDxt1 ) != 0 ) ? 8 : 16; - - // loop over blocks - for( int y = 0; y < height; y += 4 ) - { - for( int x = 0; x < width; x += 4 ) - { - // decompress the block - u8 targetRgba[4*16]; - Decompress( targetRgba, sourceBlock, flags ); - - // write the decompressed pixels to the correct image locations - u8 const* sourcePixel = targetRgba; - for( int py = 0; py < 4; ++py ) - { - for( int px = 0; px < 4; ++px ) - { - // get the target location - int sx = x + px; - int sy = y + py; - if( sx < width && sy < height ) - { - u8* targetPixel = rgba + 4*( width*sy + sx ); - - // copy the rgba value - for( int i = 0; i < 4; ++i ) - *targetPixel++ = *sourcePixel++; - } - else - { - // skip this pixel as its outside the image - sourcePixel += 4; - } - } - } - - // advance - sourceBlock += bytesPerBlock; - } - } -} - -} // namespace squish diff --git a/drivers/squish/squish.h b/drivers/squish/squish.h deleted file mode 100644 index 5f5ac149d7..0000000000 --- a/drivers/squish/squish.h +++ /dev/null @@ -1,247 +0,0 @@ -/* ----------------------------------------------------------------------------- - - Copyright (c) 2006 Simon Brown si@sjbrown.co.uk - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------------- */ - -#ifndef SQUISH_H -#define SQUISH_H - -//! All squish API functions live in this namespace. -namespace squish { - -// ----------------------------------------------------------------------------- - -//! Typedef a quantity that is a single unsigned byte. -typedef unsigned char u8; - -// ----------------------------------------------------------------------------- - -enum -{ - //! Use DXT1 compression. - kDxt1 = ( 1 << 0 ), - - //! Use DXT3 compression. - kDxt3 = ( 1 << 1 ), - - //! Use DXT5 compression. - kDxt5 = ( 1 << 2 ), - - //! Use a very slow but very high quality colour compressor. - kColourIterativeClusterFit = ( 1 << 8 ), - - //! Use a slow but high quality colour compressor (the default). - kColourClusterFit = ( 1 << 3 ), - - //! Use a fast but low quality colour compressor. - kColourRangeFit = ( 1 << 4 ), - - //! Use a perceptual metric for colour error (the default). - kColourMetricPerceptual = ( 1 << 5 ), - - //! Use a uniform metric for colour error. - kColourMetricUniform = ( 1 << 6 ), - - //! Weight the colour by alpha during cluster fit (disabled by default). - kWeightColourByAlpha = ( 1 << 7 ) -}; - -// ----------------------------------------------------------------------------- - -/*! @brief Compresses a 4x4 block of pixels. - - @param rgba The rgba values of the 16 source pixels. - @param block Storage for the compressed DXT block. - @param flags Compression flags. - - The source pixels should be presented as a contiguous array of 16 rgba - values, with each component as 1 byte each. In memory this should be: - - { r1, g1, b1, a1, .... , r16, g16, b16, a16 } - - The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression, - however, DXT1 will be used by default if none is specified. When using DXT1 - compression, 8 bytes of storage are required for the compressed DXT block. - DXT3 and DXT5 compression require 16 bytes of storage per block. - - The flags parameter can also specify a preferred colour compressor and - colour error metric to use when fitting the RGB components of the data. - Possible colour compressors are: kColourClusterFit (the default), - kColourRangeFit or kColourIterativeClusterFit. Possible colour error metrics - are: kColourMetricPerceptual (the default) or kColourMetricUniform. If no - flags are specified in any particular category then the default will be - used. Unknown flags are ignored. - - When using kColourClusterFit, an additional flag can be specified to - weight the colour of each pixel by its alpha value. For images that are - rendered using alpha blending, this can significantly increase the - perceived quality. -*/ -void Compress( u8 const* rgba, void* block, int flags ); - -// ----------------------------------------------------------------------------- - -/*! @brief Compresses a 4x4 block of pixels. - - @param rgba The rgba values of the 16 source pixels. - @param mask The valid pixel mask. - @param block Storage for the compressed DXT block. - @param flags Compression flags. - - The source pixels should be presented as a contiguous array of 16 rgba - values, with each component as 1 byte each. In memory this should be: - - { r1, g1, b1, a1, .... , r16, g16, b16, a16 } - - The mask parameter enables only certain pixels within the block. The lowest - bit enables the first pixel and so on up to the 16th bit. Bits beyond the - 16th bit are ignored. Pixels that are not enabled are allowed to take - arbitrary colours in the output block. An example of how this can be used - is in the CompressImage function to disable pixels outside the bounds of - the image when the width or height is not divisible by 4. - - The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression, - however, DXT1 will be used by default if none is specified. When using DXT1 - compression, 8 bytes of storage are required for the compressed DXT block. - DXT3 and DXT5 compression require 16 bytes of storage per block. - - The flags parameter can also specify a preferred colour compressor and - colour error metric to use when fitting the RGB components of the data. - Possible colour compressors are: kColourClusterFit (the default), - kColourRangeFit or kColourIterativeClusterFit. Possible colour error metrics - are: kColourMetricPerceptual (the default) or kColourMetricUniform. If no - flags are specified in any particular category then the default will be - used. Unknown flags are ignored. - - When using kColourClusterFit, an additional flag can be specified to - weight the colour of each pixel by its alpha value. For images that are - rendered using alpha blending, this can significantly increase the - perceived quality. -*/ -void CompressMasked( u8 const* rgba, int mask, void* block, int flags ); - -// ----------------------------------------------------------------------------- - -/*! @brief Decompresses a 4x4 block of pixels. - - @param rgba Storage for the 16 decompressed pixels. - @param block The compressed DXT block. - @param flags Compression flags. - - The decompressed pixels will be written as a contiguous array of 16 rgba - values, with each component as 1 byte each. In memory this is: - - { r1, g1, b1, a1, .... , r16, g16, b16, a16 } - - The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression, - however, DXT1 will be used by default if none is specified. All other flags - are ignored. -*/ -void Decompress( u8* rgba, void const* block, int flags ); - -// ----------------------------------------------------------------------------- - -/*! @brief Computes the amount of compressed storage required. - - @param width The width of the image. - @param height The height of the image. - @param flags Compression flags. - - The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression, - however, DXT1 will be used by default if none is specified. All other flags - are ignored. - - Most DXT images will be a multiple of 4 in each dimension, but this - function supports arbitrary size images by allowing the outer blocks to - be only partially used. -*/ -int GetStorageRequirements( int width, int height, int flags ); - -// ----------------------------------------------------------------------------- - -/*! @brief Compresses an image in memory. - - @param rgba The pixels of the source. - @param width The width of the source image. - @param height The height of the source image. - @param blocks Storage for the compressed output. - @param flags Compression flags. - - The source pixels should be presented as a contiguous array of width*height - rgba values, with each component as 1 byte each. In memory this should be: - - { r1, g1, b1, a1, .... , rn, gn, bn, an } for n = width*height - - The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression, - however, DXT1 will be used by default if none is specified. When using DXT1 - compression, 8 bytes of storage are required for each compressed DXT block. - DXT3 and DXT5 compression require 16 bytes of storage per block. - - The flags parameter can also specify a preferred colour compressor and - colour error metric to use when fitting the RGB components of the data. - Possible colour compressors are: kColourClusterFit (the default), - kColourRangeFit or kColourIterativeClusterFit. Possible colour error metrics - are: kColourMetricPerceptual (the default) or kColourMetricUniform. If no - flags are specified in any particular category then the default will be - used. Unknown flags are ignored. - - When using kColourClusterFit, an additional flag can be specified to - weight the colour of each pixel by its alpha value. For images that are - rendered using alpha blending, this can significantly increase the - perceived quality. - - Internally this function calls squish::Compress for each block. To see how - much memory is required in the compressed image, use - squish::GetStorageRequirements. -*/ -void CompressImage( u8 const* rgba, int width, int height, void* blocks, int flags ); - -// ----------------------------------------------------------------------------- - -/*! @brief Decompresses an image in memory. - - @param rgba Storage for the decompressed pixels. - @param width The width of the source image. - @param height The height of the source image. - @param blocks The compressed DXT blocks. - @param flags Compression flags. - - The decompressed pixels will be written as a contiguous array of width*height - 16 rgba values, with each component as 1 byte each. In memory this is: - - { r1, g1, b1, a1, .... , rn, gn, bn, an } for n = width*height - - The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression, - however, DXT1 will be used by default if none is specified. All other flags - are ignored. - - Internally this function calls squish::Decompress for each block. -*/ -void DecompressImage( u8* rgba, int width, int height, void const* blocks, int flags ); - -// ----------------------------------------------------------------------------- - -} // namespace squish - -#endif // ndef SQUISH_H - diff --git a/drivers/theora/SCsub b/drivers/theora/SCsub deleted file mode 100644 index fa85b49804..0000000000 --- a/drivers/theora/SCsub +++ /dev/null @@ -1,67 +0,0 @@ -Import('env') - -sources = [ - "theora/analyze.c", - "theora/apiwrapper.c", - "theora/bitpack.c", - "theora/cpu.c", - "theora/decapiwrapper.c", - "theora/decinfo.c", - "theora/decode.c", - "theora/dequant.c", - #"theora/encapiwrapper.c", - #"theora/encfrag.c", - #"theora/encinfo.c", - #"theora/encode.c", - "theora/encoder_disabled.c", - "theora/enquant.c", - "theora/fdct.c", - "theora/fragment.c", - "theora/huffdec.c", - "theora/huffenc.c", - "theora/idct.c", - "theora/info.c", - "theora/internal.c", - "theora/mathops.c", - "theora/mcenc.c", - "theora/quant.c", - "theora/rate.c", - "theora/state.c", - "theora/tokenize.c", - "theora/video_stream_theora.cpp", -] - -sources_x86 = [ - "theora/x86/mmxencfrag.c", - "theora/x86/mmxfdct.c", - "theora/x86/mmxfrag.c", - "theora/x86/mmxidct.c", - "theora/x86/mmxstate.c", - "theora/x86/sse2fdct.c", - "theora/x86/x86enc.c", - "theora/x86/x86state.c", -] - -sources_x86_vc = [ - "theora/x86_vc/mmxencfrag.c", - "theora/x86_vc/mmxfdct.c", - "theora/x86_vc/mmxfrag.c", - "theora/x86_vc/mmxidct.c", - "theora/x86_vc/mmxstate.c", - "theora/x86_vc/x86enc.c", - "theora/x86_vc/x86state.c", -] - -env.drivers_sources += sources - -if (env["x86_opt_gcc"]): - env.Append(CCFLAGS=["-DOC_X86_ASM"]) - env.drivers_sources += sources_x86 - -if (env["x86_opt_vc"]): - env.Append(CCFLAGS=["-DOC_X86_ASM"]) - env.drivers_sources += sources_x86_vc - - - - diff --git a/drivers/theora/theora.exp b/drivers/theora/theora.exp deleted file mode 100644 index b4e0225f1e..0000000000 --- a/drivers/theora/theora.exp +++ /dev/null @@ -1,55 +0,0 @@ -# export list for libtheora
-_theora_version_string
-_theora_version_number
-_theora_encode_init
-_theora_encode_YUVin
-_theora_encode_packetout
-_theora_encode_header
-_theora_encode_comment
-_theora_encode_tables
-_theora_decode_header
-_theora_decode_init
-_theora_decode_packetin
-_theora_decode_YUVout
-_theora_control
-_theora_packet_isheader
-_theora_packet_iskeyframe
-_theora_granule_shift
-_theora_granule_frame
-_theora_granule_time
-_theora_info_init
-_theora_info_clear
-_theora_clear
-_theora_comment_init
-_theora_comment_add
-_theora_comment_add_tag
-_theora_comment_query
-_theora_comment_query_count
-_theora_comment_clear
-_th_version_string
-_th_version_number
-_th_decode_headerin
-_th_decode_alloc
-_th_setup_free
-_th_decode_ctl
-_th_decode_packetin
-_th_decode_ycbcr_out
-_th_decode_free
-_th_packet_isheader
-_th_packet_iskeyframe
-_th_granule_frame
-_th_granule_time
-_th_info_init
-_th_info_clear
-_th_comment_init
-_th_comment_add
-_th_comment_add_tag
-_th_comment_query
-_th_comment_query_count
-_th_comment_clear
-_th_encode_alloc
-_th_encode_ctl
-_th_encode_flushheader
-_th_encode_packetout
-_th_encode_ycbcr_in
-_th_encode_free
diff --git a/drivers/theora/video_stream_theora.cpp b/drivers/theora/video_stream_theora.cpp deleted file mode 100644 index 1f3832ec16..0000000000 --- a/drivers/theora/video_stream_theora.cpp +++ /dev/null @@ -1,945 +0,0 @@ -/*************************************************************************/ -/* video_stream_theora.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifdef THEORA_ENABLED - -#include "video_stream_theora.h" -#include "os/os.h" -#include "yuv2rgb.h" -#include "globals.h" - - -int VideoStreamPlaybackTheora:: buffer_data() { - - char *buffer=ogg_sync_buffer(&oy,4096); - -#ifdef THEORA_USE_THREAD_STREAMING - - int read; - - do { - thread_sem->post(); - read = MIN(ring_buffer.data_left(),4096); - if (read) { - ring_buffer.read((uint8_t*)buffer,read); - ogg_sync_wrote(&oy,read); - } else { - OS::get_singleton()->delay_usec(100); - } - - } while(read==0); - - return read; - -#else - - int bytes=file->get_buffer((uint8_t*)buffer, 4096); - ogg_sync_wrote(&oy,bytes); - return(bytes); - -#endif -} - -int VideoStreamPlaybackTheora::queue_page(ogg_page *page){ - if(theora_p) { - ogg_stream_pagein(&to,page); - if (to.e_o_s) - theora_eos=true; - } - if(vorbis_p) { - ogg_stream_pagein(&vo,page); - if (vo.e_o_s) - vorbis_eos=true; - } - return 0; -} - -void VideoStreamPlaybackTheora::video_write(void){ - th_ycbcr_buffer yuv; - th_decode_ycbcr_out(td,yuv); - - /* - int y_offset, uv_offset; - y_offset=(ti.pic_x&~1)+yuv[0].stride*(ti.pic_y&~1); - - { - int pixels = size.x * size.y; - frame_data.resize(pixels * 4); - DVector<uint8_t>::Write w = frame_data.write(); - char* dst = (char*)w.ptr(); - int p = 0; - for (int i=0; i<size.y; i++) { - - char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; - char *out = dst + (int)size.x * 4 * i; - for (int j=0;j<size.x;j++) { - - dst[p++] = in_y[j]; - dst[p++] = in_y[j]; - dst[p++] = in_y[j]; - dst[p++] = 255; - }; - } - format = Image::FORMAT_RGBA; - } - // */ - - //* - - int pitch = 4; - frame_data.resize(size.x * size.y * pitch); - { - DVector<uint8_t>::Write w = frame_data.write(); - char* dst = (char*)w.ptr(); - - //uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y/2); - - if (px_fmt == TH_PF_444) { - - yuv444_2_rgb8888((uint8_t*)dst, (uint8_t*)yuv[0].data, (uint8_t*)yuv[1].data, (uint8_t*)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x<<2, 0); - - } else if (px_fmt == TH_PF_422) { - - yuv422_2_rgb8888((uint8_t*)dst, (uint8_t*)yuv[0].data, (uint8_t*)yuv[1].data, (uint8_t*)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x<<2, 0); - - } else if (px_fmt == TH_PF_420) { - - yuv420_2_rgb8888((uint8_t*)dst, (uint8_t*)yuv[0].data, (uint8_t*)yuv[2].data, (uint8_t*)yuv[1].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x<<2, 0); - }; - - format = Image::FORMAT_RGBA; - } - - Image img(size.x,size.y,0,Image::FORMAT_RGBA,frame_data); //zero copy image creation - - texture->set_data(img); //zero copy send to visual server - - /* - - if (px_fmt == TH_PF_444) { - - int pitch = 3; - frame_data.resize(size.x * size.y * pitch); - DVector<uint8_t>::Write w = frame_data.write(); - char* dst = (char*)w.ptr(); - - for(int i=0;i<size.y;i++) { - - char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; - char *out = dst + (int)size.x * pitch * i; - char *in_u = (char *)yuv[1].data+uv_offset+yuv[1].stride*i; - char *in_v = (char *)yuv[2].data+uv_offset+yuv[2].stride*i; - for (int j=0;j<size.x;j++) { - - out[j*3+0] = in_y[j]; - out[j*3+1] = in_u[j]; - out[j*3+2] = in_v[j]; - }; - } - - format = Image::FORMAT_YUV_444; - - } else { - - int div; - if (px_fmt!=TH_PF_422) { - div = 2; - } - - bool rgba = true; - if (rgba) { - - int pitch = 4; - frame_data.resize(size.x * size.y * pitch); - DVector<uint8_t>::Write w = frame_data.write(); - char* dst = (char*)w.ptr(); - - uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y / div); - for(int i=0;i<size.y;i++) { - char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; - char *in_u = (char *)yuv[1].data+uv_offset+yuv[1].stride*(i/div); - char *in_v = (char *)yuv[2].data+uv_offset+yuv[2].stride*(i/div); - uint8_t *out = (uint8_t*)dst + (int)size.x * pitch * i; - int ofs = 0; - for (int j=0;j<size.x;j++) { - - uint8_t y, u, v; - y = in_y[j]; - u = in_u[j/2]; - v = in_v[j/2]; - - int32_t r = Math::fast_ftoi(1.164 * (y - 16) + 1.596 * (v - 128)); - int32_t g = Math::fast_ftoi(1.164 * (y - 16) - 0.813 * (v - 128) - 0.391 * (u - 128)); - int32_t b = Math::fast_ftoi(1.164 * (y - 16) + 2.018 * (u - 128)); - - out[ofs++] = CLAMP(r, 0, 255); - out[ofs++] = CLAMP(g, 0, 255); - out[ofs++] = CLAMP(b, 0, 255); - out[ofs++] = 255; - } - } - - format = Image::FORMAT_RGBA; - - } else { - - int pitch = 2; - frame_data.resize(size.x * size.y * pitch); - DVector<uint8_t>::Write w = frame_data.write(); - char* dst = (char*)w.ptr(); - - uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y / div); - for(int i=0;i<size.y;i++) { - char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; - char *out = dst + (int)size.x * pitch * i; - for (int j=0;j<size.x;j++) - out[j*2] = in_y[j]; - char *in_u = (char *)yuv[1].data+uv_offset+yuv[1].stride*(i/div); - char *in_v = (char *)yuv[2].data+uv_offset+yuv[2].stride*(i/div); - for (int j=0;j<(int)size.x>>1;j++) { - out[j*4+1] = in_u[j]; - out[j*4+3] = in_v[j]; - } - } - - format = Image::FORMAT_YUV_422; - }; - }; - // */ - - frames_pending = 1; -} - -void VideoStreamPlaybackTheora::clear() { - - if (!file) - return; - - if(vorbis_p){ - ogg_stream_clear(&vo); - if (vorbis_p >= 3) { - vorbis_block_clear(&vb); - vorbis_dsp_clear(&vd); - }; - vorbis_comment_clear(&vc); - vorbis_info_clear(&vi); - vorbis_p = 0; - } - if(theora_p){ - ogg_stream_clear(&to); - th_decode_free(td); - th_comment_clear(&tc); - th_info_clear(&ti); - theora_p = 0; - } - ogg_sync_clear(&oy); - -#ifdef THEORA_USE_THREAD_STREAMING - thread_exit=true; - thread_sem->post(); //just in case - Thread::wait_to_finish(thread); - memdelete(thread); - thread=NULL; - ring_buffer.clear(); -#endif - //file_name = ""; - - theora_p = 0; - vorbis_p = 0; - videobuf_ready = 0; - frames_pending = 0; - videobuf_time = 0; - theora_eos=false; - vorbis_eos=false; - - if (file) { - memdelete(file); - } - file=NULL; - playing = false; -}; - -void VideoStreamPlaybackTheora::set_file(const String& p_file) { - - ERR_FAIL_COND(playing); - ogg_packet op; - th_setup_info *ts = NULL; - - file_name = p_file; - if (file) { - memdelete(file); - } - file = FileAccess::open(p_file, FileAccess::READ); - ERR_FAIL_COND(!file); - -#ifdef THEORA_USE_THREAD_STREAMING - thread_exit=false; - thread_eof=false; - //pre-fill buffer - int to_read = ring_buffer.space_left(); - int read = file->get_buffer(read_buffer.ptr(),to_read); - ring_buffer.write(read_buffer.ptr(),read); - - thread=Thread::create(_streaming_thread,this); - -#endif - - ogg_sync_init(&oy); - - /* init supporting Vorbis structures needed in header parsing */ - vorbis_info_init(&vi); - vorbis_comment_init(&vc); - - /* init supporting Theora structures needed in header parsing */ - th_comment_init(&tc); - th_info_init(&ti); - - theora_eos=false; - vorbis_eos=false; - - /* Ogg file open; parse the headers */ - /* Only interested in Vorbis/Theora streams */ - int stateflag = 0; - - int audio_track_skip=audio_track; - - - while(!stateflag){ - int ret=buffer_data(); - if(ret==0)break; - while(ogg_sync_pageout(&oy,&og)>0){ - ogg_stream_state test; - - /* is this a mandated initial header? If not, stop parsing */ - if(!ogg_page_bos(&og)){ - /* don't leak the page; get it into the appropriate stream */ - queue_page(&og); - stateflag=1; - break; - } - - ogg_stream_init(&test,ogg_page_serialno(&og)); - ogg_stream_pagein(&test,&og); - ogg_stream_packetout(&test,&op); - - - /* identify the codec: try theora */ - if(!theora_p && th_decode_headerin(&ti,&tc,&ts,&op)>=0){ - /* it is theora */ - copymem(&to,&test,sizeof(test)); - theora_p=1; - }else if(!vorbis_p && vorbis_synthesis_headerin(&vi,&vc,&op)>=0){ - - - /* it is vorbis */ - if (audio_track_skip) { - vorbis_info_clear(&vi); - vorbis_comment_clear(&vc); - ogg_stream_clear(&test); - vorbis_info_init(&vi); - vorbis_comment_init(&vc); - - audio_track_skip--; - } else { - copymem(&vo,&test,sizeof(test)); - vorbis_p=1; - } - }else{ - /* whatever it is, we don't care about it */ - ogg_stream_clear(&test); - } - } - /* fall through to non-bos page parsing */ - } - - /* we're expecting more header packets. */ - while((theora_p && theora_p<3) || (vorbis_p && vorbis_p<3)){ - int ret; - - /* look for further theora headers */ - while(theora_p && (theora_p<3) && (ret=ogg_stream_packetout(&to,&op))){ - if(ret<0){ - fprintf(stderr,"Error parsing Theora stream headers; " - "corrupt stream?\n"); - clear(); - return; - } - if(!th_decode_headerin(&ti,&tc,&ts,&op)){ - fprintf(stderr,"Error parsing Theora stream headers; " - "corrupt stream?\n"); - clear(); - return; - } - theora_p++; - } - - /* look for more vorbis header packets */ - while(vorbis_p && (vorbis_p<3) && (ret=ogg_stream_packetout(&vo,&op))){ - if(ret<0){ - fprintf(stderr,"Error parsing Vorbis stream headers; corrupt stream?\n"); - clear(); - return; - } - ret = vorbis_synthesis_headerin(&vi,&vc,&op); - if(ret){ - fprintf(stderr,"Error parsing Vorbis stream headers; corrupt stream?\n"); - clear(); - return; - } - vorbis_p++; - if(vorbis_p==3)break; - } - - /* The header pages/packets will arrive before anything else we - care about, or the stream is not obeying spec */ - - if(ogg_sync_pageout(&oy,&og)>0){ - queue_page(&og); /* demux into the appropriate stream */ - }else{ - int ret=buffer_data(); /* someone needs more data */ - if(ret==0){ - fprintf(stderr,"End of file while searching for codec headers.\n"); - clear(); - return; - } - } - } - - /* and now we have it all. initialize decoders */ - if(theora_p){ - td=th_decode_alloc(&ti,ts); - printf("Ogg logical stream %lx is Theora %dx%d %.02f fps", - to.serialno,ti.pic_width,ti.pic_height, - (double)ti.fps_numerator/ti.fps_denominator); - px_fmt=ti.pixel_fmt; - switch(ti.pixel_fmt){ - case TH_PF_420: printf(" 4:2:0 video\n"); break; - case TH_PF_422: printf(" 4:2:2 video\n"); break; - case TH_PF_444: printf(" 4:4:4 video\n"); break; - case TH_PF_RSVD: - default: - printf(" video\n (UNKNOWN Chroma sampling!)\n"); - break; - } - if(ti.pic_width!=ti.frame_width || ti.pic_height!=ti.frame_height) - printf(" Frame content is %dx%d with offset (%d,%d).\n", - ti.frame_width, ti.frame_height, ti.pic_x, ti.pic_y); - th_decode_ctl(td,TH_DECCTL_GET_PPLEVEL_MAX,&pp_level_max, - sizeof(pp_level_max)); - pp_level=pp_level_max; - pp_level=0; - th_decode_ctl(td,TH_DECCTL_SET_PPLEVEL,&pp_level,sizeof(pp_level)); - pp_inc=0; - - /*{ - int arg = 0xffff; - th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_MBMODE,&arg,sizeof(arg)); - th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_MV,&arg,sizeof(arg)); - th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_QI,&arg,sizeof(arg)); - arg=10; - th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_BITS,&arg,sizeof(arg)); - }*/ - - int w; - int h; - w=(ti.pic_x+ti.frame_width+1&~1)-(ti.pic_x&~1); - h=(ti.pic_y+ti.frame_height+1&~1)-(ti.pic_y&~1); - size.x = w; - size.y = h; - - texture->create(w,h,Image::FORMAT_RGBA,Texture::FLAG_FILTER|Texture::FLAG_VIDEO_SURFACE); - - }else{ - /* tear down the partial theora setup */ - th_info_clear(&ti); - th_comment_clear(&tc); - } - - th_setup_free(ts); - - if(vorbis_p){ - vorbis_synthesis_init(&vd,&vi); - vorbis_block_init(&vd,&vb); - fprintf(stderr,"Ogg logical stream %lx is Vorbis %d channel %ld Hz audio.\n", - vo.serialno,vi.channels,vi.rate); - //_setup(vi.channels, vi.rate); - - }else{ - /* tear down the partial vorbis setup */ - vorbis_info_clear(&vi); - vorbis_comment_clear(&vc); - } - - playing = false; - buffering=true; - time=0; - audio_frames_wrote=0; - - -}; - -float VideoStreamPlaybackTheora::get_time() const { - - //print_line("total: "+itos(get_total())+" todo: "+itos(get_todo())); - //return MAX(0,time-((get_total())/(float)vi.rate)); - return time-AudioServer::get_singleton()->get_output_delay()-delay_compensation;//-((get_total())/(float)vi.rate); -}; - -Ref<Texture> VideoStreamPlaybackTheora::get_texture() { - - return texture; -} - -void VideoStreamPlaybackTheora::update(float p_delta) { - - if (!file) - return; - - if (!playing || paused) { - //printf("not playing\n"); - return; - }; - - - -#ifdef THEORA_USE_THREAD_STREAMING - thread_sem->post(); -#endif - - //double ctime =AudioServer::get_singleton()->get_mix_time(); - - //print_line("play "+rtos(p_delta)); - time+=p_delta; - - if (videobuf_time>get_time()) { - return; //no new frames need to be produced - } - - bool frame_done=false; - bool audio_done=!vorbis_p; - - while (!frame_done || (!audio_done && !vorbis_eos)) { - //a frame needs to be produced - - ogg_packet op; - bool no_theora=false; - - - while (vorbis_p) { - int ret; - float **pcm; - - bool buffer_full=false; - - /* if there's pending, decoded audio, grab it */ - if ((ret=vorbis_synthesis_pcmout(&vd,&pcm))>0) { - - - - const int AUXBUF_LEN=4096; - int to_read = ret; - int16_t aux_buffer[AUXBUF_LEN]; - - while(to_read) { - - int m = MIN(AUXBUF_LEN/vi.channels,to_read); - - int count = 0; - - for(int j=0;j<m;j++){ - for(int i=0;i<vi.channels;i++){ - - int val=Math::fast_ftoi(pcm[i][j]*32767.f); - if(val>32767)val=32767; - if(val<-32768)val=-32768; - aux_buffer[count++] = val; - } - } - - if (mix_callback) { - int mixed = mix_callback(mix_udata,aux_buffer,m); - to_read-=mixed; - if (mixed!=m) { //could mix no more - buffer_full=true; - break; - } - } else { - to_read-=m; //just pretend we sent the audio - } - - - } - - - int tr = vorbis_synthesis_read(&vd, ret-to_read); - - - if (vd.granulepos>=0) { - // print_line("wrote: "+itos(audio_frames_wrote)+" gpos: "+itos(vd.granulepos)); - } - - //print_line("mix audio!"); - - audio_frames_wrote+=ret-to_read; - - //print_line("AGP: "+itos(vd.granulepos)+" added "+itos(ret-to_read)); - - - } else { - - /* no pending audio; is there a pending packet to decode? */ - if (ogg_stream_packetout(&vo,&op)>0){ - if(vorbis_synthesis(&vb,&op)==0) { /* test for success! */ - vorbis_synthesis_blockin(&vd,&vb); - } - } else { /* we need more data; break out to suck in another page */ - //printf("need moar data\n"); - break; - }; - } - - - audio_done = videobuf_time < (audio_frames_wrote/float(vi.rate)); - - if (buffer_full) - break; - } - - while(theora_p && !frame_done){ - /* theora is one in, one out... */ - if(ogg_stream_packetout(&to,&op)>0){ - - - if(false && pp_inc){ - pp_level+=pp_inc; - th_decode_ctl(td,TH_DECCTL_SET_PPLEVEL,&pp_level, - sizeof(pp_level)); - pp_inc=0; - } - /*HACK: This should be set after a seek or a gap, but we might not have - a granulepos for the first packet (we only have them for the last - packet on a page), so we just set it as often as we get it. - To do this right, we should back-track from the last packet on the - page and compute the correct granulepos for the first packet after - a seek or a gap.*/ - if(op.granulepos>=0){ - th_decode_ctl(td,TH_DECCTL_SET_GRANPOS,&op.granulepos, - sizeof(op.granulepos)); - } - ogg_int64_t videobuf_granulepos; - if(th_decode_packetin(td,&op,&videobuf_granulepos)==0){ - videobuf_time=th_granule_time(td,videobuf_granulepos); - - //printf("frame time %f, play time %f, ready %i\n", (float)videobuf_time, get_time(), videobuf_ready); - - /* is it already too old to be useful? This is only actually - useful cosmetically after a SIGSTOP. Note that we have to - decode the frame even if we don't show it (for now) due to - keyframing. Soon enough libtheora will be able to deal - with non-keyframe seeks. */ - - if(videobuf_time>=get_time()) { - frame_done=true; - } else{ - /*If we are too slow, reduce the pp level.*/ - pp_inc=pp_level>0?-1:0; - } - } else { - - } - - } else { - no_theora=true; - break; - } - } - - - //print_line("no theora: "+itos(no_theora)+" theora eos: "+itos(theora_eos)+" frame done "+itos(frame_done)); - -#ifdef THEORA_USE_THREAD_STREAMING - if (file && thread_eof && no_theora && theora_eos && ring_buffer.data_left()==0) { -#else - if (file && /*!videobuf_ready && */ no_theora && theora_eos) { -#endif - printf("video done, stopping\n"); - stop(); - return; - }; - #if 0 - if (!videobuf_ready || audio_todo > 0){ - /* no data yet for somebody. Grab another page */ - - buffer_data(); - while(ogg_sync_pageout(&oy,&og)>0){ - queue_page(&og); - } - } - #else - - - if (!frame_done || !audio_done){ - //what's the point of waiting for audio to grab a page? - - buffer_data(); - while(ogg_sync_pageout(&oy,&og)>0){ - queue_page(&og); - } - } - #endif - /* If playback has begun, top audio buffer off immediately. */ - //if(stateflag) audio_write_nonblocking(); - - /* are we at or past time for this video frame? */ - if(videobuf_ready && videobuf_time<=get_time()){ - - //video_write(); - //videobuf_ready=0; - } else { - //printf("frame at %f not ready (time %f), ready %i\n", (float)videobuf_time, get_time(), videobuf_ready); - } - - float tdiff=videobuf_time-get_time(); - /*If we have lots of extra time, increase the post-processing level.*/ - if(tdiff>ti.fps_denominator*0.25/ti.fps_numerator){ - pp_inc=pp_level<pp_level_max?1:0; - } - else if(tdiff<ti.fps_denominator*0.05/ti.fps_numerator){ - pp_inc=pp_level>0?-1:0; - } - - } - - video_write(); - -}; - - -void VideoStreamPlaybackTheora::play() { - - if (!playing) - time=0; - else { - stop(); - } - - playing = true; - delay_compensation=Globals::get_singleton()->get("audio/video_delay_compensation_ms"); - delay_compensation/=1000.0; - - -}; - -void VideoStreamPlaybackTheora::stop() { - - if (playing) { - - clear(); - set_file(file_name); //reset - } - playing = false; - time=0; -}; - -bool VideoStreamPlaybackTheora::is_playing() const { - - return playing; -}; - -void VideoStreamPlaybackTheora::set_paused(bool p_paused) { - - paused=p_paused; - //pau = !p_paused; -}; - -bool VideoStreamPlaybackTheora::is_paused(bool p_paused) const { - - return paused; -}; - -void VideoStreamPlaybackTheora::set_loop(bool p_enable) { - -}; - -bool VideoStreamPlaybackTheora::has_loop() const { - - return false; -}; - -float VideoStreamPlaybackTheora::get_length() const { - - return 0; -}; - -String VideoStreamPlaybackTheora::get_stream_name() const { - - return ""; -}; - -int VideoStreamPlaybackTheora::get_loop_count() const { - - return 0; -}; - -float VideoStreamPlaybackTheora::get_pos() const { - - return get_time(); -}; - -void VideoStreamPlaybackTheora::seek_pos(float p_time) { - - // no -}; - -void VideoStreamPlaybackTheora::set_mix_callback(AudioMixCallback p_callback,void *p_userdata) { - - mix_callback=p_callback; - mix_udata=p_userdata; -} - -int VideoStreamPlaybackTheora::get_channels() const{ - - return vi.channels; -} - -void VideoStreamPlaybackTheora::set_audio_track(int p_idx) { - - audio_track=p_idx; -} - -int VideoStreamPlaybackTheora::get_mix_rate() const{ - - return vi.rate; -} - -#ifdef THEORA_USE_THREAD_STREAMING - - -void VideoStreamPlaybackTheora::_streaming_thread(void *ud) { - - VideoStreamPlaybackTheora *vs=(VideoStreamPlaybackTheora*)ud; - - while(!vs->thread_exit) { - - //just fill back the buffer - if (!vs->thread_eof) { - - int to_read = vs->ring_buffer.space_left(); - if (to_read) { - int read = vs->file->get_buffer(vs->read_buffer.ptr(),to_read); - vs->ring_buffer.write(vs->read_buffer.ptr(),read); - vs->thread_eof=vs->file->eof_reached(); - } - - - } - - vs->thread_sem->wait(); - } -} - -#endif - -VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() { - - file = NULL; - theora_p = 0; - vorbis_p = 0; - videobuf_ready = 0; - playing = false; - frames_pending = 0; - videobuf_time = 0; - paused=false; - - buffering=false; - texture = Ref<ImageTexture>( memnew(ImageTexture )); - mix_callback=NULL; - mix_udata=NULL; - audio_track=0; - delay_compensation=0; - audio_frames_wrote=0; - -#ifdef THEORA_USE_THREAD_STREAMING - int rb_power = nearest_shift(RB_SIZE_KB*1024); - ring_buffer.resize(rb_power); - read_buffer.resize(RB_SIZE_KB*1024); - thread_sem=Semaphore::create(); - thread=NULL; - thread_exit=false; - thread_eof=false; - -#endif -}; - -VideoStreamPlaybackTheora::~VideoStreamPlaybackTheora() { - -#ifdef THEORA_USE_THREAD_STREAMING - - memdelete(thread_sem); -#endif - clear(); - - if (file) - memdelete(file); - - -}; - - -RES ResourceFormatLoaderVideoStreamTheora::load(const String &p_path,const String& p_original_path, Error *r_error) { - if (r_error) - *r_error=ERR_FILE_CANT_OPEN; - - VideoStreamTheora *stream = memnew(VideoStreamTheora); - stream->set_file(p_path); - - if (r_error) - *r_error=OK; - - return Ref<VideoStreamTheora>(stream); -} - -void ResourceFormatLoaderVideoStreamTheora::get_recognized_extensions(List<String> *p_extensions) const { - - p_extensions->push_back("ogm"); - p_extensions->push_back("ogv"); -} -bool ResourceFormatLoaderVideoStreamTheora::handles_type(const String& p_type) const { - return (p_type=="VideoStream" || p_type=="VideoStreamTheora"); -} - -String ResourceFormatLoaderVideoStreamTheora::get_resource_type(const String &p_path) const { - - String exl=p_path.extension().to_lower(); - if (exl=="ogm" || exl=="ogv") - return "VideoStreamTheora"; - return ""; -} - -#endif - diff --git a/drivers/theora/video_stream_theora.h b/drivers/theora/video_stream_theora.h deleted file mode 100644 index 5484815844..0000000000 --- a/drivers/theora/video_stream_theora.h +++ /dev/null @@ -1,204 +0,0 @@ -/*************************************************************************/ -/* video_stream_theora.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef VIDEO_STREAM_THEORA_H -#define VIDEO_STREAM_THEORA_H - -#ifdef THEORA_ENABLED - -#include "theora/theoradec.h" -#include "vorbis/codec.h" -#include "os/file_access.h" -#include "ring_buffer.h" -#include "io/resource_loader.h" -#include "scene/resources/video_stream.h" -#include "os/thread.h" -#include "os/semaphore.h" - -//#define THEORA_USE_THREAD_STREAMING - -class VideoStreamPlaybackTheora : public VideoStreamPlayback { - - OBJ_TYPE(VideoStreamPlaybackTheora, VideoStreamPlayback); - - enum { - MAX_FRAMES = 4, - }; - - //Image frames[MAX_FRAMES]; - Image::Format format; - DVector<uint8_t> frame_data; - int frames_pending; - FileAccess* file; - String file_name; - int audio_frames_wrote; - Point2i size; - - int buffer_data(); - int queue_page(ogg_page *page); - void video_write(void); - float get_time() const; - - bool theora_eos; - bool vorbis_eos; - - ogg_sync_state oy; - ogg_page og; - ogg_stream_state vo; - ogg_stream_state to; - th_info ti; - th_comment tc; - th_dec_ctx *td; - vorbis_info vi; - vorbis_dsp_state vd; - vorbis_block vb; - vorbis_comment vc; - th_pixel_fmt px_fmt; - double videobuf_time; - int pp_inc; - - int theora_p; - int vorbis_p; - int pp_level_max; - int pp_level; - int videobuf_ready; - - bool playing; - bool buffering; - - double last_update_time; - double time; - double delay_compensation; - - Ref<ImageTexture> texture; - - AudioMixCallback mix_callback; - void* mix_udata; - bool paused; - -#ifdef THEORA_USE_THREAD_STREAMING - - enum { - RB_SIZE_KB=1024 - }; - - RingBuffer<uint8_t> ring_buffer; - Vector<uint8_t> read_buffer; - bool thread_eof; - Semaphore *thread_sem; - Thread *thread; - volatile bool thread_exit; - - static void _streaming_thread(void *ud); - -#endif - - - int audio_track; - -protected: - - void clear(); - -public: - - virtual void play(); - virtual void stop(); - virtual bool is_playing() const; - - virtual void set_paused(bool p_paused); - virtual bool is_paused(bool p_paused) const; - - virtual void set_loop(bool p_enable); - virtual bool has_loop() const; - - virtual float get_length() const; - - virtual String get_stream_name() const; - - virtual int get_loop_count() const; - - virtual float get_pos() const; - virtual void seek_pos(float p_time); - - - void set_file(const String& p_file); - - virtual Ref<Texture> get_texture(); - virtual void update(float p_delta); - - virtual void set_mix_callback(AudioMixCallback p_callback,void *p_userdata); - virtual int get_channels() const; - virtual int get_mix_rate() const; - - virtual void set_audio_track(int p_idx); - - VideoStreamPlaybackTheora(); - ~VideoStreamPlaybackTheora(); -}; - - - -class VideoStreamTheora : public VideoStream { - - OBJ_TYPE(VideoStreamTheora,VideoStream); - - String file; - int audio_track; - - -public: - - Ref<VideoStreamPlayback> instance_playback() { - Ref<VideoStreamPlaybackTheora> pb = memnew( VideoStreamPlaybackTheora ); - pb->set_audio_track(audio_track); - pb->set_file(file); - return pb; - } - - void set_file(const String& p_file) { file=p_file; } - void set_audio_track(int p_track) { audio_track=p_track; } - - VideoStreamTheora() { audio_track=0; } - -}; - -class ResourceFormatLoaderVideoStreamTheora : public ResourceFormatLoader { -public: - virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); - virtual void get_recognized_extensions(List<String> *p_extensions) const; - virtual bool handles_type(const String& p_type) const; - virtual String get_resource_type(const String &p_path) const; - -}; - - - -#endif - -#endif diff --git a/drivers/unix/SCsub b/drivers/unix/SCsub index 3d46a85cdf..fe427e747f 100644 --- a/drivers/unix/SCsub +++ b/drivers/unix/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') g_set_p='#ifdef UNIX_ENABLED\n' @@ -10,6 +12,6 @@ f = open("os_unix_global_settings_path.cpp","wb") f.write(g_set_p) f.close() -env.add_source_files(env.drivers_sources,"*.cpp") +env.add_source_files(env.drivers_sources, "*.cpp") Export('env') diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index 535a425302..d6d1be3395 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -28,8 +28,9 @@ /*************************************************************************/ #include "ip_unix.h" -#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) && !defined(WINRT_ENABLED) +#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) +#include <string.h> #ifdef WINDOWS_ENABLED #ifdef WINRT_ENABLED @@ -62,16 +63,51 @@ #endif #endif -IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) { +static IP_Address _sockaddr2ip(struct sockaddr* p_addr) { - struct hostent *he; - if ((he=gethostbyname(p_hostname.utf8().get_data())) == NULL) { // get the host info - ERR_PRINT("gethostbyname failed!"); - return IP_Address(); - } IP_Address ip; + if (p_addr->sa_family == AF_INET) { + struct sockaddr_in* addr = (struct sockaddr_in*)p_addr; + ip.field32[0] = *((unsigned long*)&addr->sin_addr); + ip.type = IP_Address::TYPE_IPV4; + } else { + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; + for (int i=0; i<16; i++) + ip.field8[i] = addr6->sin6_addr.s6_addr[i]; + ip.type = IP_Address::TYPE_IPV6; + }; + + return ip; +}; + +IP_Address IP_Unix::_resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type) { + + struct addrinfo hints; + struct addrinfo* result; - ip.host= *((unsigned long*)he->h_addr); + memset(&hints, 0, sizeof(struct addrinfo)); + if (p_type == IP_Address::TYPE_IPV4) { + hints.ai_family = AF_INET; + } else if (p_type == IP_Address::TYPE_IPV6) { + hints.ai_family = AF_INET6; + } else { + hints.ai_family = AF_UNSPEC; + }; + + int s = getaddrinfo(p_hostname.utf8().get_data(), NULL, &hints, &result); + if (s != 0) { + ERR_PRINT("getaddrinfo failed!"); + return IP_Address(); + }; + + if (result == NULL || result->ai_addr == NULL) { + ERR_PRINT("Invalid response from getaddrinfo"); + return IP_Address(); + }; + + IP_Address ip = _sockaddr2ip(result->ai_addr); + + freeaddrinfo(result); return ip; @@ -83,6 +119,18 @@ IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) { void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { + using namespace Windows::Networking; + using namespace Windows::Networking::Connectivity; + + auto hostnames = NetworkInformation::GetHostNames(); + + for (int i = 0; i < hostnames->Size; i++) { + + if (hostnames->GetAt(i)->Type == HostNameType::Ipv4 || hostnames->GetAt(i)->Type == HostNameType::Ipv6 && hostnames->GetAt(i)->IPInformation != nullptr) { + + r_addresses->push_back(IP_Address(String(hostnames->GetAt(i)->CanonicalName->Data()))); + } + } }; #else @@ -95,7 +143,7 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { while (true) { addrs = (IP_ADAPTER_ADDRESSES*)memalloc(buf_size); - int err = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST | + int err = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, @@ -121,14 +169,23 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress; while (address != NULL) { - char addr_chr[INET_ADDRSTRLEN]; - SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr); - IP_Address ip; - ip.host= *((unsigned long*)&ipv4->sin_addr); + if (address->Address.lpSockaddr->sa_family == AF_INET) { + + SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr); + + ip.field32[0] = *((unsigned long*)&ipv4->sin_addr); + ip.type = IP_Address::TYPE_IPV4; + } else { // ipv6 + + SOCKADDR_IN6* ipv6 = reinterpret_cast<SOCKADDR_IN6*>(address->Address.lpSockaddr); + for (int i=0; i<16; i++) { + ip.field8[i] = ipv6->sin6_addr.s6_addr[i]; + }; + ip.type = IP_Address::TYPE_IPV6; + }; - //inet_ntop(AF_INET, &ipv4->sin_addr, addr_chr, INET_ADDRSTRLEN); r_addresses->push_back(ip); @@ -154,20 +211,9 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { if (!ifa->ifa_addr) continue; - if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4 - // is a valid IP4 Address - IP_Address ip; - ip.host= *((unsigned long*)&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr); - - r_addresses->push_back(ip); - }/* else if (ifa->ifa_addr->sa_family==AF_INET6) { // check it is IP6 - // is a valid IP6 Address - tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; - char addressBuffer[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN); - printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer); - } */ + IP_Address ip = _sockaddr2ip(ifa->ifa_addr); + r_addresses->push_back(ip); } if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct); diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h index c0034c9a3a..d198a330e7 100644 --- a/drivers/unix/ip_unix.h +++ b/drivers/unix/ip_unix.h @@ -36,7 +36,7 @@ class IP_Unix : public IP { OBJ_TYPE(IP_Unix, IP); - virtual IP_Address _resolve_hostname(const String& p_hostname); + virtual IP_Address _resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type); static IP* _create_unix(); public: diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index fd515d6dd3..271cf302ef 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -390,7 +390,7 @@ Error OS_Unix::execute(const String& p_path, const List<String>& p_arguments,boo if (p_blocking) { int status; - pid_t rpid = waitpid(pid,&status,0); + waitpid(pid,&status,0); if (r_exitcode) *r_exitcode=WEXITSTATUS(status); } else { diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index 0201a85651..0b172b6a51 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -54,6 +54,7 @@ #include <arpa/inet.h> #endif +#include "drivers/unix/socket_helpers.h" int PacketPeerUDPPosix::get_available_packet_count() const { @@ -73,7 +74,15 @@ Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size return ERR_UNAVAILABLE; uint32_t size; - rb.read((uint8_t*)&packet_ip.host,4,true); + uint8_t type; + rb.read(&type, 1, true); + if (type == IP_Address::TYPE_IPV4) { + rb.read((uint8_t*)&packet_ip.field8,4,true); + packet_ip.type = IP_Address::TYPE_IPV4; + } else { + rb.read((uint8_t*)&packet_ip.field8,16,true); + packet_ip.type = IP_Address::TYPE_IPV6; + }; rb.read((uint8_t*)&packet_port,4,true); rb.read((uint8_t*)&size,4,true); rb.read(packet_buffer,size,true); @@ -85,17 +94,17 @@ Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size } Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){ - int sock = _get_socket(); + ERR_FAIL_COND_V(peer_addr.type == IP_Address::TYPE_NONE, ERR_UNCONFIGURED); + + int sock = _get_socket(peer_addr.type); ERR_FAIL_COND_V( sock == -1, FAILED ); - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(peer_port); - addr.sin_addr = *((struct in_addr*)&peer_addr.host); + struct sockaddr_storage addr; + size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port); errno = 0; int err; - while ( (err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, sizeof(addr))) != p_buffer_size) { + while ( (err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, addr_size)) != p_buffer_size) { if (errno != EAGAIN) { return FAILED; @@ -110,17 +119,19 @@ int PacketPeerUDPPosix::get_max_packet_size() const{ return 512; // uhm maybe not } -Error PacketPeerUDPPosix::listen(int p_port, int p_recv_buffer_size){ +Error PacketPeerUDPPosix::listen(int p_port, IP_Address::AddrType p_address_type, int p_recv_buffer_size) { + + ERR_FAIL_COND_V(p_address_type != IP_Address::TYPE_IPV4 && p_address_type != IP_Address::TYPE_IPV6, ERR_INVALID_PARAMETER); close(); - int sock = _get_socket(); + int sock = _get_socket(p_address_type); if (sock == -1 ) return ERR_CANT_CREATE; - sockaddr_in addr = {0}; - addr.sin_family = AF_INET; - addr.sin_port = htons(p_port); - addr.sin_addr.s_addr = INADDR_ANY; - if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_in)) == -1 ) { + + sockaddr_storage addr = {0}; + size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_address_type, NULL); + + if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) { close(); return ERR_UNAVAILABLE; } @@ -145,16 +156,41 @@ Error PacketPeerUDPPosix::wait() { Error PacketPeerUDPPosix::_poll(bool p_wait) { - struct sockaddr_in from = {0}; - socklen_t len = sizeof(struct sockaddr_in); + struct sockaddr_storage from = {0}; + socklen_t len = sizeof(struct sockaddr_storage); int ret; while ( (ret = recvfrom(sockfd, recv_buffer, MIN((int)sizeof(recv_buffer),MAX(rb.space_left()-12, 0)), p_wait?0:MSG_DONTWAIT, (struct sockaddr*)&from, &len)) > 0) { - rb.write((uint8_t*)&from.sin_addr, 4); - uint32_t port = ntohs(from.sin_port); + + uint32_t port = 0; + + if (from.ss_family == AF_INET) { + uint8_t type = (uint8_t)IP_Address::TYPE_IPV4; + rb.write(&type, 1); + struct sockaddr_in* sin_from = (struct sockaddr_in*)&from; + rb.write((uint8_t*)&sin_from->sin_addr, 4); + port = ntohs(sin_from->sin_port); + + } else if (from.ss_family == AF_INET6) { + + uint8_t type = (uint8_t)IP_Address::TYPE_IPV6; + rb.write(&type, 1); + + struct sockaddr_in6* s6_from = (struct sockaddr_in6*)&from; + rb.write((uint8_t*)&s6_from->sin6_addr, 16); + + port = ntohs(s6_from->sin6_port); + + } else { + // WARN_PRINT("Ignoring packet with unknown address family"); + uint8_t type = (uint8_t)IP_Address::TYPE_NONE; + rb.write(&type, 1); + }; + rb.write((uint8_t*)&port, 4); rb.write((uint8_t*)&ret, 4); rb.write(recv_buffer, ret); - len = sizeof(struct sockaddr_in); + + len = sizeof(struct sockaddr_storage); ++queue_count; }; @@ -182,12 +218,14 @@ int PacketPeerUDPPosix::get_packet_port() const{ return packet_port; } -int PacketPeerUDPPosix::_get_socket() { +int PacketPeerUDPPosix::_get_socket(IP_Address::AddrType p_type) { if (sockfd != -1) return sockfd; - sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + int family = p_type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; + + sockfd = socket(family, SOCK_DGRAM, IPPROTO_UDP); ERR_FAIL_COND_V( sockfd == -1, -1 ); //fcntl(sockfd, F_SETFL, O_NONBLOCK); diff --git a/drivers/unix/packet_peer_udp_posix.h b/drivers/unix/packet_peer_udp_posix.h index a11282e5d6..13b6969e53 100644 --- a/drivers/unix/packet_peer_udp_posix.h +++ b/drivers/unix/packet_peer_udp_posix.h @@ -44,15 +44,15 @@ class PacketPeerUDPPosix : public PacketPeerUDP { mutable RingBuffer<uint8_t> rb; uint8_t recv_buffer[PACKET_BUFFER_SIZE]; mutable uint8_t packet_buffer[PACKET_BUFFER_SIZE]; - IP_Address packet_ip; - int packet_port; + mutable IP_Address packet_ip; + mutable int packet_port; mutable int queue_count; int sockfd; IP_Address peer_addr; int peer_port; - _FORCE_INLINE_ int _get_socket(); + _FORCE_INLINE_ int _get_socket(IP_Address::AddrType p_type); static PacketPeerUDP* _create(); virtual Error _poll(bool p_block); @@ -65,7 +65,7 @@ public: virtual int get_max_packet_size() const; - virtual Error listen(int p_port,int p_recv_buffer_size=65536); + virtual Error listen(int p_port, IP_Address::AddrType p_address_type, int p_recv_buffer_size=65536); virtual void close(); virtual Error wait(); virtual bool is_listening() const; diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h new file mode 100644 index 0000000000..4ee40e3d3d --- /dev/null +++ b/drivers/unix/socket_helpers.h @@ -0,0 +1,70 @@ +#ifndef SOCKET_HELPERS_H +#define SOCKET_HELPERS_H + +#include <string.h> + +// helpers for sockaddr -> IP_Address and back, should work for posix and winsock. All implementations should use this + +static size_t _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p_ip, int p_port) { + + memset(p_addr, 0, sizeof(struct sockaddr_storage)); + if (p_ip.type == IP_Address::TYPE_IPV6) { + + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; + addr6->sin6_family = AF_INET6; + addr6->sin6_port = htons(p_port); + copymem(&addr6->sin6_addr.s6_addr, p_ip.field8, 16); + return sizeof(sockaddr_in6); + + } else { + + struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr; + addr4->sin_family = AF_INET; // host byte order + addr4->sin_port = htons(p_port); // short, network byte order + addr4->sin_addr = *((struct in_addr*)&p_ip.field32[0]); + return sizeof(sockaddr_in); + }; +}; + +static size_t _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port, IP_Address::AddrType p_address_type, const List<String> *p_accepted_hosts) { + + memset(p_addr, 0, sizeof(struct sockaddr_storage)); + if (p_address_type == IP_Address::TYPE_IPV4) { + struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr; + addr4->sin_family = AF_INET; + addr4->sin_port = htons(p_port); + addr4->sin_addr.s_addr = INADDR_ANY; // TODO: use accepted hosts list + return sizeof(sockaddr_in); + } else { + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; + + addr6->sin6_family = AF_INET6; + addr6->sin6_port = htons(p_port); + addr6->sin6_addr = in6addr_any; // TODO: use accepted hosts list + return sizeof(sockaddr_in6); + }; +}; + +static void _set_ip_addr_port(IP_Address& r_ip, int& r_port, struct sockaddr_storage* p_addr) { + + if (p_addr->ss_family == AF_INET) { + r_ip.type = IP_Address::TYPE_IPV4; + + struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr; + r_ip.field32[0] = (uint32_t)addr4->sin_addr.s_addr; + + r_port = ntohs(addr4->sin_port); + + } else if (p_addr->ss_family == AF_INET6) { + + r_ip.type = IP_Address::TYPE_IPV6; + + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; + copymem(&addr6->sin6_addr.s6_addr, r_ip.field8, 16); + + r_port = ntohs(addr6->sin6_port); + }; +}; + + +#endif diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index 45a4b934c1..f2915b0a16 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -61,13 +61,7 @@ #define MSG_NOSIGNAL SO_NOSIGPIPE #endif -static void set_addr_in(struct sockaddr_in& their_addr, const IP_Address& p_host, uint16_t p_port) { - - their_addr.sin_family = AF_INET; // host byte order - their_addr.sin_port = htons(p_port); // short, network byte order - their_addr.sin_addr = *((struct in_addr*)&p_host.host); - memset(&(their_addr.sin_zero), '\0', 8); -}; +#include "drivers/unix/socket_helpers.h" StreamPeerTCP* StreamPeerTCPPosix::_create() { @@ -103,9 +97,10 @@ Error StreamPeerTCPPosix::_poll_connection(bool p_block) const { _block(sockfd, false, true); }; - struct sockaddr_in their_addr; - set_addr_in(their_addr, peer_host, peer_port); - if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1) { + struct sockaddr_storage their_addr; + size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port); + + if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == -1) { if (errno == EISCONN) { status = STATUS_CONNECTED; @@ -140,9 +135,10 @@ void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port) Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) { - ERR_FAIL_COND_V( p_host.host == 0, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V( p_host.type == IP_Address::TYPE_NONE, ERR_INVALID_PARAMETER); - if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + int family = p_host.type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; + if ((sockfd = socket(family, SOCK_STREAM, 0)) == -1) { ERR_PRINT("Socket creation failed!"); disconnect(); //perror("socket"); @@ -156,11 +152,11 @@ Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) { ioctl(sockfd, FIONBIO, &bval); #endif - struct sockaddr_in their_addr; - set_addr_in(their_addr, p_host, p_port); + struct sockaddr_storage their_addr; + size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port); errno = 0; - if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1 && errno != EINPROGRESS) { + if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == -1 && errno != EINPROGRESS) { ERR_PRINT("Connection to remote host failed!"); disconnect(); diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp index c67bb51334..05b739804c 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -55,6 +55,9 @@ #include <netinet/in.h> #include <sys/socket.h> #include <assert.h> + +#include "drivers/unix/socket_helpers.h" + TCP_Server* TCPServerPosix::_create() { return memnew(TCPServerPosix); @@ -65,10 +68,11 @@ void TCPServerPosix::make_default() { TCP_Server::_create = TCPServerPosix::_create; }; -Error TCPServerPosix::listen(uint16_t p_port,const List<String> *p_accepted_hosts) { +Error TCPServerPosix::listen(uint16_t p_port, IP_Address::AddrType p_type, const List<String> *p_accepted_hosts) { int sockfd; - sockfd = socket(AF_INET, SOCK_STREAM, 0); + int family = p_type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; + sockfd = socket(family, SOCK_STREAM, 0); ERR_FAIL_COND_V(sockfd == -1, FAILED); #ifndef NO_FCNTL fcntl(sockfd, F_SETFL, O_NONBLOCK); @@ -82,13 +86,12 @@ Error TCPServerPosix::listen(uint16_t p_port,const List<String> *p_accepted_host WARN_PRINT("REUSEADDR failed!") } - struct sockaddr_in my_addr; - my_addr.sin_family = AF_INET; // host byte order - my_addr.sin_port = htons(p_port); // short, network byte order - my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP TODO: use p_accepted_hosts - memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero); + struct sockaddr_storage addr; + size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_type, p_accepted_hosts); + + // automatically fill with my IP TODO: use p_accepted_hosts - if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) != -1) { + if (bind(sockfd, (struct sockaddr *)&addr, addr_size) != -1) { if (::listen(sockfd, 1) == -1) { @@ -136,9 +139,9 @@ Ref<StreamPeerTCP> TCPServerPosix::take_connection() { return Ref<StreamPeerTCP>(); }; - struct sockaddr_in their_addr; - socklen_t sin_size = sizeof(their_addr); - int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &sin_size); + struct sockaddr_storage their_addr; + socklen_t size = sizeof(their_addr); + int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &size); ERR_FAIL_COND_V(fd == -1, Ref<StreamPeerTCP>()); #ifndef NO_FCNTL fcntl(fd, F_SETFL, O_NONBLOCK); @@ -149,8 +152,11 @@ Ref<StreamPeerTCP> TCPServerPosix::take_connection() { Ref<StreamPeerTCPPosix> conn = memnew(StreamPeerTCPPosix); IP_Address ip; - ip.host = (uint32_t)their_addr.sin_addr.s_addr; - conn->set_socket(fd, ip, ntohs(their_addr.sin_port)); + + int port; + _set_ip_addr_port(ip, port, &their_addr); + + conn->set_socket(fd, ip, port); return conn; }; diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h index 570bcaab12..134ec494cb 100644 --- a/drivers/unix/tcp_server_posix.h +++ b/drivers/unix/tcp_server_posix.h @@ -40,7 +40,7 @@ class TCPServerPosix : public TCP_Server { public: - virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL); + virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_IPV4, const List<String> *p_accepted_hosts=NULL); virtual bool is_connection_available() const; virtual Ref<StreamPeerTCP> take_connection(); diff --git a/drivers/vorbis/SCsub b/drivers/vorbis/SCsub deleted file mode 100644 index 87805cc2d8..0000000000 --- a/drivers/vorbis/SCsub +++ /dev/null @@ -1,36 +0,0 @@ -Import('env') - -sources = [ - "vorbis/audio_stream_ogg_vorbis.cpp", -] - -sources_lib = [ - "vorbis/analysis.c", - #"vorbis/barkmel.c", - "vorbis/bitrate.c", - "vorbis/block.c", - "vorbis/codebook.c", - "vorbis/envelope.c", - "vorbis/floor0.c", - "vorbis/floor1.c", - "vorbis/info.c", - "vorbis/lookup.c", - "vorbis/lpc.c", - "vorbis/lsp.c", - "vorbis/mapping0.c", - "vorbis/mdct.c", - "vorbis/psy.c", - #"vorbis/psytune.c", - "vorbis/registry.c", - "vorbis/res0.c", - "vorbis/sharedbook.c", - "vorbis/smallft.c", - "vorbis/synthesis.c", - #"vorbis/tone.c", - "vorbis/vorbisenc.c", - "vorbis/vorbisfile.c", - "vorbis/window.c", -] - -env.drivers_sources += sources -env.drivers_sources += sources_lib diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.h b/drivers/vorbis/audio_stream_ogg_vorbis.h deleted file mode 100644 index bb4d521c1e..0000000000 --- a/drivers/vorbis/audio_stream_ogg_vorbis.h +++ /dev/null @@ -1,142 +0,0 @@ -/*************************************************************************/ -/* audio_stream_ogg_vorbis.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef AUDIO_STREAM_OGG_VORBIS_H -#define AUDIO_STREAM_OGG_VORBIS_H - -#include "scene/resources/audio_stream.h" -#include "vorbis/vorbisfile.h" -#include "os/file_access.h" -#include "io/resource_loader.h" -#include "os/thread_safe.h" - - -class AudioStreamPlaybackOGGVorbis : public AudioStreamPlayback { - - OBJ_TYPE(AudioStreamPlaybackOGGVorbis,AudioStreamPlayback); - - enum { - MIN_MIX=1024 - }; - - FileAccess *f; - - ov_callbacks _ov_callbacks; - float length; - static size_t _ov_read_func(void *p_dst,size_t p_data, size_t p_count, void *_f); - static int _ov_seek_func(void *_f,ogg_int64_t offs, int whence); - static int _ov_close_func(void *_f); - static long _ov_tell_func(void *_f); - - String file; - int64_t frames_mixed; - - bool stream_loaded; - volatile bool playing; - OggVorbis_File vf; - int stream_channels; - int stream_srate; - int current_section; - - - bool paused; - bool loops; - int repeats; - - Error _load_stream(); - void _clear_stream(); - void _close_file(); - - bool stream_valid; - float loop_restart_time; - - -public: - - - Error set_file(const String& p_file); - - virtual void play(float p_from=0); - virtual void stop(); - virtual bool is_playing() const; - - virtual void set_loop_restart_time(float p_time) { loop_restart_time=p_time; } - - virtual void set_paused(bool p_paused); - virtual bool is_paused(bool p_paused) const; - - virtual void set_loop(bool p_enable); - virtual bool has_loop() const; - - virtual float get_length() const; - - virtual String get_stream_name() const; - - virtual int get_loop_count() const; - - virtual float get_pos() const; - virtual void seek_pos(float p_time); - - virtual int get_channels() const { return stream_channels; } - virtual int get_mix_rate() const { return stream_srate; } - - virtual int get_minimum_buffer_size() const { return 0; } - virtual int mix(int16_t* p_bufer,int p_frames); - - AudioStreamPlaybackOGGVorbis(); - ~AudioStreamPlaybackOGGVorbis(); -}; - - -class AudioStreamOGGVorbis : public AudioStream { - - OBJ_TYPE(AudioStreamOGGVorbis,AudioStream); - - String file; -public: - - Ref<AudioStreamPlayback> instance_playback() { - Ref<AudioStreamPlaybackOGGVorbis> pb = memnew( AudioStreamPlaybackOGGVorbis ); - pb->set_file(file); - return pb; - } - - void set_file(const String& p_file) { file=p_file; } - -}; - -class ResourceFormatLoaderAudioStreamOGGVorbis : public ResourceFormatLoader { -public: - virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); - virtual void get_recognized_extensions(List<String> *p_extensions) const; - virtual bool handles_type(const String& p_type) const; - virtual String get_resource_type(const String &p_path) const; -}; - - -#endif // AUDIO_STREAM_OGG_H diff --git a/drivers/webp/SCsub b/drivers/webp/SCsub deleted file mode 100644 index f65bd13dba..0000000000 --- a/drivers/webp/SCsub +++ /dev/null @@ -1,115 +0,0 @@ -Import('env') - -webp_sources = [ -"webp/enc/webpenc.c",\ -"webp/enc/near_lossless.c",\ -"webp/enc/frame.c",\ -"webp/enc/alpha.c",\ -"webp/enc/picture_csp.c",\ -"webp/enc/vp8l.c",\ -"webp/enc/picture_psnr.c",\ -"webp/enc/delta_palettization.c",\ -"webp/enc/syntax.c",\ -"webp/enc/backward_references.c",\ -"webp/enc/token.c",\ -"webp/enc/analysis.c",\ -"webp/enc/iterator.c",\ -"webp/enc/picture_tools.c",\ -"webp/enc/picture_rescale.c",\ -"webp/enc/config.c",\ -"webp/enc/tree.c",\ -"webp/enc/cost.c",\ -"webp/enc/picture.c",\ -"webp/enc/quant.c",\ -"webp/enc/filter.c",\ -"webp/enc/histogram.c",\ -"webp/image_loader_webp.cpp",\ -"webp/utils/rescaler.c",\ -"webp/utils/filters.c",\ -"webp/utils/quant_levels_dec.c",\ -"webp/utils/huffman.c",\ -"webp/utils/thread.c",\ -"webp/utils/quant_levels.c",\ -"webp/utils/bit_writer.c",\ -"webp/utils/bit_reader.c",\ -"webp/utils/random.c",\ -"webp/utils/utils.c",\ -"webp/utils/huffman_encode.c",\ -"webp/utils/color_cache.c",\ -"webp/mux/muxinternal.c",\ -"webp/mux/muxread.c",\ -"webp/mux/anim_encode.c",\ -"webp/mux/muxedit.c",\ -"webp/dec/webp.c",\ -"webp/dec/frame.c",\ -"webp/dec/alpha.c",\ -"webp/dec/vp8l.c",\ -"webp/dec/io.c",\ -"webp/dec/vp8.c",\ -"webp/dec/idec.c",\ -"webp/dec/tree.c",\ -"webp/dec/buffer.c",\ -"webp/dec/quant.c",\ -"webp/demux/demux.c",\ -"webp/demux/anim_decode.c",\ -"webp/dsp/yuv.c",\ -"webp/dsp/filters_sse2.c",\ -"webp/dsp/dec_sse41.c",\ -"webp/dsp/rescaler.c",\ -"webp/dsp/lossless_sse2.c",\ -"webp/dsp/alpha_processing_sse41.c",\ -"webp/dsp/alpha_processing_sse2.c",\ -"webp/dsp/filters.c",\ -"webp/dsp/upsampling_mips_dsp_r2.c",\ -"webp/dsp/dec_neon.c",\ -"webp/dsp/enc_neon.c",\ -"webp/dsp/lossless_enc_mips32.c",\ -"webp/dsp/lossless_enc_sse2.c",\ -"webp/dsp/upsampling.c",\ -"webp/dsp/lossless_enc_neon.c",\ -"webp/dsp/alpha_processing.c",\ -"webp/dsp/cost_sse2.c",\ -"webp/dsp/dec_mips32.c",\ -"webp/dsp/enc_avx2.c",\ -"webp/dsp/rescaler_mips32.c",\ -"webp/dsp/enc.c",\ -"webp/dsp/lossless_enc_sse41.c",\ -"webp/dsp/cost_mips32.c",\ -"webp/dsp/lossless_mips_dsp_r2.c",\ -"webp/dsp/filters_mips_dsp_r2.c",\ -"webp/dsp/upsampling_neon.c",\ -"webp/dsp/alpha_processing_mips_dsp_r2.c",\ -"webp/dsp/enc_mips_dsp_r2.c",\ -"webp/dsp/lossless.c",\ -"webp/dsp/yuv_mips_dsp_r2.c",\ -"webp/dsp/cost_mips_dsp_r2.c",\ -"webp/dsp/argb.c",\ -"webp/dsp/dec_sse2.c",\ -"webp/dsp/rescaler_sse2.c",\ -"webp/dsp/enc_sse41.c",\ -"webp/dsp/argb_mips_dsp_r2.c",\ -"webp/dsp/lossless_enc_mips_dsp_r2.c",\ -"webp/dsp/dec_clip_tables.c",\ -"webp/dsp/yuv_mips32.c",\ -"webp/dsp/cpu.c",\ -"webp/dsp/dec.c",\ -"webp/dsp/argb_sse2.c",\ -"webp/dsp/lossless_neon.c",\ -"webp/dsp/lossless_enc.c",\ -"webp/dsp/enc_mips32.c",\ -"webp/dsp/cost.c",\ -"webp/dsp/rescaler_mips_dsp_r2.c",\ -"webp/dsp/dec_mips_dsp_r2.c",\ -"webp/dsp/rescaler_neon.c",\ -"webp/dsp/yuv_sse2.c",\ -"webp/dsp/enc_sse2.c",\ -"webp/dsp/upsampling_sse2.c" -] - -env.drivers_sources+=webp_sources - -#env.add_source_files(env.drivers_sources, webp_sources) - - -Export('env') - diff --git a/drivers/webp/dec/alpha.c b/drivers/webp/dec/alpha.c deleted file mode 100644 index 19ce548e96..0000000000 --- a/drivers/webp/dec/alpha.c +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Alpha-plane decompression. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include <stdlib.h> -#include "./alphai.h" -#include "./vp8i.h" -#include "./vp8li.h" -#include "../dsp/dsp.h" -#include "../utils/quant_levels_dec.h" -#include "../utils/utils.h" -#include "webp/format_constants.h" - -//------------------------------------------------------------------------------ -// ALPHDecoder object. - -// Allocates a new alpha decoder instance. -static ALPHDecoder* ALPHNew(void) { - ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); - return dec; -} - -// Clears and deallocates an alpha decoder instance. -static void ALPHDelete(ALPHDecoder* const dec) { - if (dec != NULL) { - VP8LDelete(dec->vp8l_dec_); - dec->vp8l_dec_ = NULL; - WebPSafeFree(dec); - } -} - -//------------------------------------------------------------------------------ -// Decoding. - -// Initialize alpha decoding by parsing the alpha header and decoding the image -// header for alpha data stored using lossless compression. -// Returns false in case of error in alpha header (data too short, invalid -// compression method or filter, error in lossless header data etc). -static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, - size_t data_size, const VP8Io* const src_io, - uint8_t* output) { - int ok = 0; - const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; - const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; - int rsrv; - VP8Io* const io = &dec->io_; - - assert(data != NULL && output != NULL && src_io != NULL); - - VP8FiltersInit(); - dec->output_ = output; - dec->width_ = src_io->width; - dec->height_ = src_io->height; - assert(dec->width_ > 0 && dec->height_ > 0); - - if (data_size <= ALPHA_HEADER_LEN) { - return 0; - } - - dec->method_ = (data[0] >> 0) & 0x03; - dec->filter_ = (data[0] >> 2) & 0x03; - dec->pre_processing_ = (data[0] >> 4) & 0x03; - rsrv = (data[0] >> 6) & 0x03; - if (dec->method_ < ALPHA_NO_COMPRESSION || - dec->method_ > ALPHA_LOSSLESS_COMPRESSION || - dec->filter_ >= WEBP_FILTER_LAST || - dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS || - rsrv != 0) { - return 0; - } - - // Copy the necessary parameters from src_io to io - VP8InitIo(io); - WebPInitCustomIo(NULL, io); - io->opaque = dec; - io->width = src_io->width; - io->height = src_io->height; - - io->use_cropping = src_io->use_cropping; - io->crop_left = src_io->crop_left; - io->crop_right = src_io->crop_right; - io->crop_top = src_io->crop_top; - io->crop_bottom = src_io->crop_bottom; - // No need to copy the scaling parameters. - - if (dec->method_ == ALPHA_NO_COMPRESSION) { - const size_t alpha_decoded_size = dec->width_ * dec->height_; - ok = (alpha_data_size >= alpha_decoded_size); - } else { - assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION); - ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size); - } - - return ok; -} - -// Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha -// starting from row number 'row'. It assumes that rows up to (row - 1) have -// already been decoded. -// Returns false in case of bitstream error. -static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) { - ALPHDecoder* const alph_dec = dec->alph_dec_; - const int width = alph_dec->width_; - const int height = alph_dec->io_.crop_bottom; - if (alph_dec->method_ == ALPHA_NO_COMPRESSION) { - int y; - const uint8_t* prev_line = dec->alpha_prev_line_; - const uint8_t* deltas = dec->alpha_data_ + ALPHA_HEADER_LEN + row * width; - uint8_t* dst = dec->alpha_plane_ + row * width; - assert(deltas <= &dec->alpha_data_[dec->alpha_data_size_]); - if (alph_dec->filter_ != WEBP_FILTER_NONE) { - assert(WebPUnfilters[alph_dec->filter_] != NULL); - for (y = 0; y < num_rows; ++y) { - WebPUnfilters[alph_dec->filter_](prev_line, deltas, dst, width); - prev_line = dst; - dst += width; - deltas += width; - } - } else { - for (y = 0; y < num_rows; ++y) { - memcpy(dst, deltas, width * sizeof(*dst)); - prev_line = dst; - dst += width; - deltas += width; - } - } - dec->alpha_prev_line_ = prev_line; - } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION - assert(alph_dec->vp8l_dec_ != NULL); - if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) { - return 0; - } - } - - if (row + num_rows >= height) { - dec->is_alpha_decoded_ = 1; - } - return 1; -} - -static int AllocateAlphaPlane(VP8Decoder* const dec, const VP8Io* const io) { - const int stride = io->width; - const int height = io->crop_bottom; - const uint64_t alpha_size = (uint64_t)stride * height; - assert(dec->alpha_plane_mem_ == NULL); - dec->alpha_plane_mem_ = - (uint8_t*)WebPSafeMalloc(alpha_size, sizeof(*dec->alpha_plane_)); - if (dec->alpha_plane_mem_ == NULL) { - return 0; - } - dec->alpha_plane_ = dec->alpha_plane_mem_; - dec->alpha_prev_line_ = NULL; - return 1; -} - -void WebPDeallocateAlphaMemory(VP8Decoder* const dec) { - assert(dec != NULL); - WebPSafeFree(dec->alpha_plane_mem_); - dec->alpha_plane_mem_ = NULL; - dec->alpha_plane_ = NULL; - ALPHDelete(dec->alph_dec_); - dec->alph_dec_ = NULL; -} - -//------------------------------------------------------------------------------ -// Main entry point. - -const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, - const VP8Io* const io, - int row, int num_rows) { - const int width = io->width; - const int height = io->crop_bottom; - - assert(dec != NULL && io != NULL); - - if (row < 0 || num_rows <= 0 || row + num_rows > height) { - return NULL; // sanity check. - } - - if (!dec->is_alpha_decoded_) { - if (dec->alph_dec_ == NULL) { // Initialize decoder. - dec->alph_dec_ = ALPHNew(); - if (dec->alph_dec_ == NULL) return NULL; - if (!AllocateAlphaPlane(dec, io)) goto Error; - if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_, - io, dec->alpha_plane_)) { - goto Error; - } - // if we allowed use of alpha dithering, check whether it's needed at all - if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) { - dec->alpha_dithering_ = 0; // disable dithering - } else { - num_rows = height - row; // decode everything in one pass - } - } - - assert(dec->alph_dec_ != NULL); - assert(row + num_rows <= height); - if (!ALPHDecode(dec, row, num_rows)) goto Error; - - if (dec->is_alpha_decoded_) { // finished? - ALPHDelete(dec->alph_dec_); - dec->alph_dec_ = NULL; - if (dec->alpha_dithering_ > 0) { - uint8_t* const alpha = dec->alpha_plane_ + io->crop_top * width - + io->crop_left; - if (!WebPDequantizeLevels(alpha, - io->crop_right - io->crop_left, - io->crop_bottom - io->crop_top, - width, dec->alpha_dithering_)) { - goto Error; - } - } - } - } - - // Return a pointer to the current decoded row. - return dec->alpha_plane_ + row * width; - - Error: - WebPDeallocateAlphaMemory(dec); - return NULL; -} diff --git a/drivers/webp/dec/decode_vp8.h b/drivers/webp/dec/decode_vp8.h deleted file mode 100644 index 2bf1bdbbf5..0000000000 --- a/drivers/webp/dec/decode_vp8.h +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Low-level API for VP8 decoder -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_WEBP_DECODE_VP8_H_ -#define WEBP_WEBP_DECODE_VP8_H_ - -#include "webp/decode.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Lower-level API -// -// These functions provide fine-grained control of the decoding process. -// The call flow should resemble: -// -// VP8Io io; -// VP8InitIo(&io); -// io.data = data; -// io.data_size = size; -// /* customize io's functions (setup()/put()/teardown()) if needed. */ -// -// VP8Decoder* dec = VP8New(); -// bool ok = VP8Decode(dec); -// if (!ok) printf("Error: %s\n", VP8StatusMessage(dec)); -// VP8Delete(dec); -// return ok; - -// Input / Output -typedef struct VP8Io VP8Io; -typedef int (*VP8IoPutHook)(const VP8Io* io); -typedef int (*VP8IoSetupHook)(VP8Io* io); -typedef void (*VP8IoTeardownHook)(const VP8Io* io); - -struct VP8Io { - // set by VP8GetHeaders() - int width, height; // picture dimensions, in pixels (invariable). - // These are the original, uncropped dimensions. - // The actual area passed to put() is stored - // in mb_w / mb_h fields. - - // set before calling put() - int mb_y; // position of the current rows (in pixels) - int mb_w; // number of columns in the sample - int mb_h; // number of rows in the sample - const uint8_t* y, *u, *v; // rows to copy (in yuv420 format) - int y_stride; // row stride for luma - int uv_stride; // row stride for chroma - - void* opaque; // user data - - // called when fresh samples are available. Currently, samples are in - // YUV420 format, and can be up to width x 24 in size (depending on the - // in-loop filtering level, e.g.). Should return false in case of error - // or abort request. The actual size of the area to update is mb_w x mb_h - // in size, taking cropping into account. - VP8IoPutHook put; - - // called just before starting to decode the blocks. - // Must return false in case of setup error, true otherwise. If false is - // returned, teardown() will NOT be called. But if the setup succeeded - // and true is returned, then teardown() will always be called afterward. - VP8IoSetupHook setup; - - // Called just after block decoding is finished (or when an error occurred - // during put()). Is NOT called if setup() failed. - VP8IoTeardownHook teardown; - - // this is a recommendation for the user-side yuv->rgb converter. This flag - // is set when calling setup() hook and can be overwritten by it. It then - // can be taken into consideration during the put() method. - int fancy_upsampling; - - // Input buffer. - size_t data_size; - const uint8_t* data; - - // If true, in-loop filtering will not be performed even if present in the - // bitstream. Switching off filtering may speed up decoding at the expense - // of more visible blocking. Note that output will also be non-compliant - // with the VP8 specifications. - int bypass_filtering; - - // Cropping parameters. - int use_cropping; - int crop_left, crop_right, crop_top, crop_bottom; - - // Scaling parameters. - int use_scaling; - int scaled_width, scaled_height; - - // If non NULL, pointer to the alpha data (if present) corresponding to the - // start of the current row (That is: it is pre-offset by mb_y and takes - // cropping into account). - const uint8_t* a; -}; - -// Internal, version-checked, entry point -int VP8InitIoInternal(VP8Io* const, int); - -// Set the custom IO function pointers and user-data. The setter for IO hooks -// should be called before initiating incremental decoding. Returns true if -// WebPIDecoder object is successfully modified, false otherwise. -int WebPISetIOHooks(WebPIDecoder* const idec, - VP8IoPutHook put, - VP8IoSetupHook setup, - VP8IoTeardownHook teardown, - void* user_data); - -// Main decoding object. This is an opaque structure. -typedef struct VP8Decoder VP8Decoder; - -// Create a new decoder object. -VP8Decoder* VP8New(void); - -// Must be called to make sure 'io' is initialized properly. -// Returns false in case of version mismatch. Upon such failure, no other -// decoding function should be called (VP8Decode, VP8GetHeaders, ...) -static WEBP_INLINE int VP8InitIo(VP8Io* const io) { - return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION); -} - -// Decode the VP8 frame header. Returns true if ok. -// Note: 'io->data' must be pointing to the start of the VP8 frame header. -int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io); - -// Decode a picture. Will call VP8GetHeaders() if it wasn't done already. -// Returns false in case of error. -int VP8Decode(VP8Decoder* const dec, VP8Io* const io); - -// Return current status of the decoder: -VP8StatusCode VP8Status(VP8Decoder* const dec); - -// return readable string corresponding to the last status. -const char* VP8StatusMessage(VP8Decoder* const dec); - -// Resets the decoder in its initial state, reclaiming memory. -// Not a mandatory call between calls to VP8Decode(). -void VP8Clear(VP8Decoder* const dec); - -// Destroy the decoder object. -void VP8Delete(VP8Decoder* const dec); - -//------------------------------------------------------------------------------ -// Miscellaneous VP8/VP8L bitstream probing functions. - -// Returns true if the next 3 bytes in data contain the VP8 signature. -WEBP_EXTERN(int) VP8CheckSignature(const uint8_t* const data, size_t data_size); - -// Validates the VP8 data-header and retrieves basic header information viz -// width and height. Returns 0 in case of formatting error. *width/*height -// can be passed NULL. -WEBP_EXTERN(int) VP8GetInfo( - const uint8_t* data, - size_t data_size, // data available so far - size_t chunk_size, // total data size expected in the chunk - int* const width, int* const height); - -// Returns true if the next byte(s) in data is a VP8L signature. -WEBP_EXTERN(int) VP8LCheckSignature(const uint8_t* const data, size_t size); - -// Validates the VP8L data-header and retrieves basic header information viz -// width, height and alpha. Returns 0 in case of formatting error. -// width/height/has_alpha can be passed NULL. -WEBP_EXTERN(int) VP8LGetInfo( - const uint8_t* data, size_t data_size, // data available so far - int* const width, int* const height, int* const has_alpha); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_DECODE_VP8_H_ */ diff --git a/drivers/webp/dec/webp.c b/drivers/webp/dec/webp.c deleted file mode 100644 index dd6c090f00..0000000000 --- a/drivers/webp/dec/webp.c +++ /dev/null @@ -1,846 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Main decoding functions for WEBP images. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include <stdlib.h> - -#include "./vp8i.h" -#include "./vp8li.h" -#include "./webpi.h" -#include "../utils/utils.h" -#include "webp/mux_types.h" // ALPHA_FLAG - -//------------------------------------------------------------------------------ -// RIFF layout is: -// Offset tag -// 0...3 "RIFF" 4-byte tag -// 4...7 size of image data (including metadata) starting at offset 8 -// 8...11 "WEBP" our form-type signature -// The RIFF container (12 bytes) is followed by appropriate chunks: -// 12..15 "VP8 ": 4-bytes tags, signaling the use of VP8 video format -// 16..19 size of the raw VP8 image data, starting at offset 20 -// 20.... the VP8 bytes -// Or, -// 12..15 "VP8L": 4-bytes tags, signaling the use of VP8L lossless format -// 16..19 size of the raw VP8L image data, starting at offset 20 -// 20.... the VP8L bytes -// Or, -// 12..15 "VP8X": 4-bytes tags, describing the extended-VP8 chunk. -// 16..19 size of the VP8X chunk starting at offset 20. -// 20..23 VP8X flags bit-map corresponding to the chunk-types present. -// 24..26 Width of the Canvas Image. -// 27..29 Height of the Canvas Image. -// There can be extra chunks after the "VP8X" chunk (ICCP, FRGM, ANMF, VP8, -// VP8L, XMP, EXIF ...) -// All sizes are in little-endian order. -// Note: chunk data size must be padded to multiple of 2 when written. - -// Validates the RIFF container (if detected) and skips over it. -// If a RIFF container is detected, returns: -// VP8_STATUS_BITSTREAM_ERROR for invalid header, -// VP8_STATUS_NOT_ENOUGH_DATA for truncated data if have_all_data is true, -// and VP8_STATUS_OK otherwise. -// In case there are not enough bytes (partial RIFF container), return 0 for -// *riff_size. Else return the RIFF size extracted from the header. -static VP8StatusCode ParseRIFF(const uint8_t** const data, - size_t* const data_size, int have_all_data, - size_t* const riff_size) { - assert(data != NULL); - assert(data_size != NULL); - assert(riff_size != NULL); - - *riff_size = 0; // Default: no RIFF present. - if (*data_size >= RIFF_HEADER_SIZE && !memcmp(*data, "RIFF", TAG_SIZE)) { - if (memcmp(*data + 8, "WEBP", TAG_SIZE)) { - return VP8_STATUS_BITSTREAM_ERROR; // Wrong image file signature. - } else { - const uint32_t size = GetLE32(*data + TAG_SIZE); - // Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn"). - if (size < TAG_SIZE + CHUNK_HEADER_SIZE) { - return VP8_STATUS_BITSTREAM_ERROR; - } - if (size > MAX_CHUNK_PAYLOAD) { - return VP8_STATUS_BITSTREAM_ERROR; - } - if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. - } - // We have a RIFF container. Skip it. - *riff_size = size; - *data += RIFF_HEADER_SIZE; - *data_size -= RIFF_HEADER_SIZE; - } - } - return VP8_STATUS_OK; -} - -// Validates the VP8X header and skips over it. -// Returns VP8_STATUS_BITSTREAM_ERROR for invalid VP8X header, -// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and -// VP8_STATUS_OK otherwise. -// If a VP8X chunk is found, found_vp8x is set to true and *width_ptr, -// *height_ptr and *flags_ptr are set to the corresponding values extracted -// from the VP8X chunk. -static VP8StatusCode ParseVP8X(const uint8_t** const data, - size_t* const data_size, - int* const found_vp8x, - int* const width_ptr, int* const height_ptr, - uint32_t* const flags_ptr) { - const uint32_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; - assert(data != NULL); - assert(data_size != NULL); - assert(found_vp8x != NULL); - - *found_vp8x = 0; - - if (*data_size < CHUNK_HEADER_SIZE) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. - } - - if (!memcmp(*data, "VP8X", TAG_SIZE)) { - int width, height; - uint32_t flags; - const uint32_t chunk_size = GetLE32(*data + TAG_SIZE); - if (chunk_size != VP8X_CHUNK_SIZE) { - return VP8_STATUS_BITSTREAM_ERROR; // Wrong chunk size. - } - - // Verify if enough data is available to validate the VP8X chunk. - if (*data_size < vp8x_size) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. - } - flags = GetLE32(*data + 8); - width = 1 + GetLE24(*data + 12); - height = 1 + GetLE24(*data + 15); - if (width * (uint64_t)height >= MAX_IMAGE_AREA) { - return VP8_STATUS_BITSTREAM_ERROR; // image is too large - } - - if (flags_ptr != NULL) *flags_ptr = flags; - if (width_ptr != NULL) *width_ptr = width; - if (height_ptr != NULL) *height_ptr = height; - // Skip over VP8X header bytes. - *data += vp8x_size; - *data_size -= vp8x_size; - *found_vp8x = 1; - } - return VP8_STATUS_OK; -} - -// Skips to the next VP8/VP8L chunk header in the data given the size of the -// RIFF chunk 'riff_size'. -// Returns VP8_STATUS_BITSTREAM_ERROR if any invalid chunk size is encountered, -// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and -// VP8_STATUS_OK otherwise. -// If an alpha chunk is found, *alpha_data and *alpha_size are set -// appropriately. -static VP8StatusCode ParseOptionalChunks(const uint8_t** const data, - size_t* const data_size, - size_t const riff_size, - const uint8_t** const alpha_data, - size_t* const alpha_size) { - const uint8_t* buf; - size_t buf_size; - uint32_t total_size = TAG_SIZE + // "WEBP". - CHUNK_HEADER_SIZE + // "VP8Xnnnn". - VP8X_CHUNK_SIZE; // data. - assert(data != NULL); - assert(data_size != NULL); - buf = *data; - buf_size = *data_size; - - assert(alpha_data != NULL); - assert(alpha_size != NULL); - *alpha_data = NULL; - *alpha_size = 0; - - while (1) { - uint32_t chunk_size; - uint32_t disk_chunk_size; // chunk_size with padding - - *data = buf; - *data_size = buf_size; - - if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data. - return VP8_STATUS_NOT_ENOUGH_DATA; - } - - chunk_size = GetLE32(buf + TAG_SIZE); - if (chunk_size > MAX_CHUNK_PAYLOAD) { - return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. - } - // For odd-sized chunk-payload, there's one byte padding at the end. - disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1; - total_size += disk_chunk_size; - - // Check that total bytes skipped so far does not exceed riff_size. - if (riff_size > 0 && (total_size > riff_size)) { - return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. - } - - // Start of a (possibly incomplete) VP8/VP8L chunk implies that we have - // parsed all the optional chunks. - // Note: This check must occur before the check 'buf_size < disk_chunk_size' - // below to allow incomplete VP8/VP8L chunks. - if (!memcmp(buf, "VP8 ", TAG_SIZE) || - !memcmp(buf, "VP8L", TAG_SIZE)) { - return VP8_STATUS_OK; - } - - if (buf_size < disk_chunk_size) { // Insufficient data. - return VP8_STATUS_NOT_ENOUGH_DATA; - } - - if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header. - *alpha_data = buf + CHUNK_HEADER_SIZE; - *alpha_size = chunk_size; - } - - // We have a full and valid chunk; skip it. - buf += disk_chunk_size; - buf_size -= disk_chunk_size; - } -} - -// Validates the VP8/VP8L Header ("VP8 nnnn" or "VP8L nnnn") and skips over it. -// Returns VP8_STATUS_BITSTREAM_ERROR for invalid (chunk larger than -// riff_size) VP8/VP8L header, -// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and -// VP8_STATUS_OK otherwise. -// If a VP8/VP8L chunk is found, *chunk_size is set to the total number of bytes -// extracted from the VP8/VP8L chunk header. -// The flag '*is_lossless' is set to 1 in case of VP8L chunk / raw VP8L data. -static VP8StatusCode ParseVP8Header(const uint8_t** const data_ptr, - size_t* const data_size, int have_all_data, - size_t riff_size, size_t* const chunk_size, - int* const is_lossless) { - const uint8_t* const data = *data_ptr; - const int is_vp8 = !memcmp(data, "VP8 ", TAG_SIZE); - const int is_vp8l = !memcmp(data, "VP8L", TAG_SIZE); - const uint32_t minimal_size = - TAG_SIZE + CHUNK_HEADER_SIZE; // "WEBP" + "VP8 nnnn" OR - // "WEBP" + "VP8Lnnnn" - assert(data != NULL); - assert(data_size != NULL); - assert(chunk_size != NULL); - assert(is_lossless != NULL); - - if (*data_size < CHUNK_HEADER_SIZE) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. - } - - if (is_vp8 || is_vp8l) { - // Bitstream contains VP8/VP8L header. - const uint32_t size = GetLE32(data + TAG_SIZE); - if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) { - return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information. - } - if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. - } - // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header. - *chunk_size = size; - *data_ptr += CHUNK_HEADER_SIZE; - *data_size -= CHUNK_HEADER_SIZE; - *is_lossless = is_vp8l; - } else { - // Raw VP8/VP8L bitstream (no header). - *is_lossless = VP8LCheckSignature(data, *data_size); - *chunk_size = *data_size; - } - - return VP8_STATUS_OK; -} - -//------------------------------------------------------------------------------ - -// Fetch '*width', '*height', '*has_alpha' and fill out 'headers' based on -// 'data'. All the output parameters may be NULL. If 'headers' is NULL only the -// minimal amount will be read to fetch the remaining parameters. -// If 'headers' is non-NULL this function will attempt to locate both alpha -// data (with or without a VP8X chunk) and the bitstream chunk (VP8/VP8L). -// Note: The following chunk sequences (before the raw VP8/VP8L data) are -// considered valid by this function: -// RIFF + VP8(L) -// RIFF + VP8X + (optional chunks) + VP8(L) -// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. -// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. -static VP8StatusCode ParseHeadersInternal(const uint8_t* data, - size_t data_size, - int* const width, - int* const height, - int* const has_alpha, - int* const has_animation, - int* const format, - WebPHeaderStructure* const headers) { - int canvas_width = 0; - int canvas_height = 0; - int image_width = 0; - int image_height = 0; - int found_riff = 0; - int found_vp8x = 0; - int animation_present = 0; - int fragments_present = 0; - const int have_all_data = (headers != NULL) ? headers->have_all_data : 0; - - VP8StatusCode status; - WebPHeaderStructure hdrs; - - if (data == NULL || data_size < RIFF_HEADER_SIZE) { - return VP8_STATUS_NOT_ENOUGH_DATA; - } - memset(&hdrs, 0, sizeof(hdrs)); - hdrs.data = data; - hdrs.data_size = data_size; - - // Skip over RIFF header. - status = ParseRIFF(&data, &data_size, have_all_data, &hdrs.riff_size); - if (status != VP8_STATUS_OK) { - return status; // Wrong RIFF header / insufficient data. - } - found_riff = (hdrs.riff_size > 0); - - // Skip over VP8X. - { - uint32_t flags = 0; - status = ParseVP8X(&data, &data_size, &found_vp8x, - &canvas_width, &canvas_height, &flags); - if (status != VP8_STATUS_OK) { - return status; // Wrong VP8X / insufficient data. - } - animation_present = !!(flags & ANIMATION_FLAG); - fragments_present = !!(flags & FRAGMENTS_FLAG); - if (!found_riff && found_vp8x) { - // Note: This restriction may be removed in the future, if it becomes - // necessary to send VP8X chunk to the decoder. - return VP8_STATUS_BITSTREAM_ERROR; - } - if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG); - if (has_animation != NULL) *has_animation = animation_present; - if (format != NULL) *format = 0; // default = undefined - - image_width = canvas_width; - image_height = canvas_height; - if (found_vp8x && (animation_present || fragments_present) && - headers == NULL) { - status = VP8_STATUS_OK; - goto ReturnWidthHeight; // Just return features from VP8X header. - } - } - - if (data_size < TAG_SIZE) { - status = VP8_STATUS_NOT_ENOUGH_DATA; - goto ReturnWidthHeight; - } - - // Skip over optional chunks if data started with "RIFF + VP8X" or "ALPH". - if ((found_riff && found_vp8x) || - (!found_riff && !found_vp8x && !memcmp(data, "ALPH", TAG_SIZE))) { - status = ParseOptionalChunks(&data, &data_size, hdrs.riff_size, - &hdrs.alpha_data, &hdrs.alpha_data_size); - if (status != VP8_STATUS_OK) { - goto ReturnWidthHeight; // Invalid chunk size / insufficient data. - } - } - - // Skip over VP8/VP8L header. - status = ParseVP8Header(&data, &data_size, have_all_data, hdrs.riff_size, - &hdrs.compressed_size, &hdrs.is_lossless); - if (status != VP8_STATUS_OK) { - goto ReturnWidthHeight; // Wrong VP8/VP8L chunk-header / insufficient data. - } - if (hdrs.compressed_size > MAX_CHUNK_PAYLOAD) { - return VP8_STATUS_BITSTREAM_ERROR; - } - - if (format != NULL && !(animation_present || fragments_present)) { - *format = hdrs.is_lossless ? 2 : 1; - } - - if (!hdrs.is_lossless) { - if (data_size < VP8_FRAME_HEADER_SIZE) { - status = VP8_STATUS_NOT_ENOUGH_DATA; - goto ReturnWidthHeight; - } - // Validates raw VP8 data. - if (!VP8GetInfo(data, data_size, (uint32_t)hdrs.compressed_size, - &image_width, &image_height)) { - return VP8_STATUS_BITSTREAM_ERROR; - } - } else { - if (data_size < VP8L_FRAME_HEADER_SIZE) { - status = VP8_STATUS_NOT_ENOUGH_DATA; - goto ReturnWidthHeight; - } - // Validates raw VP8L data. - if (!VP8LGetInfo(data, data_size, &image_width, &image_height, has_alpha)) { - return VP8_STATUS_BITSTREAM_ERROR; - } - } - // Validates image size coherency. - if (found_vp8x) { - if (canvas_width != image_width || canvas_height != image_height) { - return VP8_STATUS_BITSTREAM_ERROR; - } - } - if (headers != NULL) { - *headers = hdrs; - headers->offset = data - headers->data; - assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD); - assert(headers->offset == headers->data_size - data_size); - } - ReturnWidthHeight: - if (status == VP8_STATUS_OK || - (status == VP8_STATUS_NOT_ENOUGH_DATA && found_vp8x && headers == NULL)) { - if (has_alpha != NULL) { - // If the data did not contain a VP8X/VP8L chunk the only definitive way - // to set this is by looking for alpha data (from an ALPH chunk). - *has_alpha |= (hdrs.alpha_data != NULL); - } - if (width != NULL) *width = image_width; - if (height != NULL) *height = image_height; - return VP8_STATUS_OK; - } else { - return status; - } -} - -VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) { - // status is marked volatile as a workaround for a clang-3.8 (aarch64) bug - volatile VP8StatusCode status; - int has_animation = 0; - assert(headers != NULL); - // fill out headers, ignore width/height/has_alpha. - status = ParseHeadersInternal(headers->data, headers->data_size, - NULL, NULL, NULL, &has_animation, - NULL, headers); - if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) { - // TODO(jzern): full support of animation frames will require API additions. - if (has_animation) { - status = VP8_STATUS_UNSUPPORTED_FEATURE; - } - } - return status; -} - -//------------------------------------------------------------------------------ -// WebPDecParams - -void WebPResetDecParams(WebPDecParams* const params) { - if (params != NULL) { - memset(params, 0, sizeof(*params)); - } -} - -//------------------------------------------------------------------------------ -// "Into" decoding variants - -// Main flow -static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size, - WebPDecParams* const params) { - VP8StatusCode status; - VP8Io io; - WebPHeaderStructure headers; - - headers.data = data; - headers.data_size = data_size; - headers.have_all_data = 1; - status = WebPParseHeaders(&headers); // Process Pre-VP8 chunks. - if (status != VP8_STATUS_OK) { - return status; - } - - assert(params != NULL); - VP8InitIo(&io); - io.data = headers.data + headers.offset; - io.data_size = headers.data_size - headers.offset; - WebPInitCustomIo(params, &io); // Plug the I/O functions. - - if (!headers.is_lossless) { - VP8Decoder* const dec = VP8New(); - if (dec == NULL) { - return VP8_STATUS_OUT_OF_MEMORY; - } - dec->alpha_data_ = headers.alpha_data; - dec->alpha_data_size_ = headers.alpha_data_size; - - // Decode bitstream header, update io->width/io->height. - if (!VP8GetHeaders(dec, &io)) { - status = dec->status_; // An error occurred. Grab error status. - } else { - // Allocate/check output buffers. - status = WebPAllocateDecBuffer(io.width, io.height, params->options, - params->output); - if (status == VP8_STATUS_OK) { // Decode - // This change must be done before calling VP8Decode() - dec->mt_method_ = VP8GetThreadMethod(params->options, &headers, - io.width, io.height); - VP8InitDithering(params->options, dec); - if (!VP8Decode(dec, &io)) { - status = dec->status_; - } - } - } - VP8Delete(dec); - } else { - VP8LDecoder* const dec = VP8LNew(); - if (dec == NULL) { - return VP8_STATUS_OUT_OF_MEMORY; - } - if (!VP8LDecodeHeader(dec, &io)) { - status = dec->status_; // An error occurred. Grab error status. - } else { - // Allocate/check output buffers. - status = WebPAllocateDecBuffer(io.width, io.height, params->options, - params->output); - if (status == VP8_STATUS_OK) { // Decode - if (!VP8LDecodeImage(dec)) { - status = dec->status_; - } - } - } - VP8LDelete(dec); - } - - if (status != VP8_STATUS_OK) { - WebPFreeDecBuffer(params->output); - } else { - if (params->options != NULL && params->options->flip) { - // This restores the original stride values if options->flip was used - // during the call to WebPAllocateDecBuffer above. - status = WebPFlipBuffer(params->output); - } - } - return status; -} - -// Helpers -static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace, - const uint8_t* const data, - size_t data_size, - uint8_t* const rgba, - int stride, size_t size) { - WebPDecParams params; - WebPDecBuffer buf; - if (rgba == NULL) { - return NULL; - } - WebPInitDecBuffer(&buf); - WebPResetDecParams(¶ms); - params.output = &buf; - buf.colorspace = colorspace; - buf.u.RGBA.rgba = rgba; - buf.u.RGBA.stride = stride; - buf.u.RGBA.size = size; - buf.is_external_memory = 1; - if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { - return NULL; - } - return rgba; -} - -uint8_t* WebPDecodeRGBInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_RGB, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeRGBAInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_RGBA, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeARGBInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_ARGB, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeBGRInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_BGR, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeBGRAInto(const uint8_t* data, size_t data_size, - uint8_t* output, size_t size, int stride) { - return DecodeIntoRGBABuffer(MODE_BGRA, data, data_size, output, stride, size); -} - -uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size, - uint8_t* luma, size_t luma_size, int luma_stride, - uint8_t* u, size_t u_size, int u_stride, - uint8_t* v, size_t v_size, int v_stride) { - WebPDecParams params; - WebPDecBuffer output; - if (luma == NULL) return NULL; - WebPInitDecBuffer(&output); - WebPResetDecParams(¶ms); - params.output = &output; - output.colorspace = MODE_YUV; - output.u.YUVA.y = luma; - output.u.YUVA.y_stride = luma_stride; - output.u.YUVA.y_size = luma_size; - output.u.YUVA.u = u; - output.u.YUVA.u_stride = u_stride; - output.u.YUVA.u_size = u_size; - output.u.YUVA.v = v; - output.u.YUVA.v_stride = v_stride; - output.u.YUVA.v_size = v_size; - output.is_external_memory = 1; - if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { - return NULL; - } - return luma; -} - -//------------------------------------------------------------------------------ - -static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data, - size_t data_size, int* const width, int* const height, - WebPDecBuffer* const keep_info) { - WebPDecParams params; - WebPDecBuffer output; - - WebPInitDecBuffer(&output); - WebPResetDecParams(¶ms); - params.output = &output; - output.colorspace = mode; - - // Retrieve (and report back) the required dimensions from bitstream. - if (!WebPGetInfo(data, data_size, &output.width, &output.height)) { - return NULL; - } - if (width != NULL) *width = output.width; - if (height != NULL) *height = output.height; - - // Decode - if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { - return NULL; - } - if (keep_info != NULL) { // keep track of the side-info - WebPCopyDecBuffer(&output, keep_info); - } - // return decoded samples (don't clear 'output'!) - return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y; -} - -uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_RGB, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_RGBA, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_ARGB, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_BGR, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, - int* width, int* height) { - return Decode(MODE_BGRA, data, data_size, width, height, NULL); -} - -uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, - int* width, int* height, uint8_t** u, uint8_t** v, - int* stride, int* uv_stride) { - WebPDecBuffer output; // only to preserve the side-infos - uint8_t* const out = Decode(MODE_YUV, data, data_size, - width, height, &output); - - if (out != NULL) { - const WebPYUVABuffer* const buf = &output.u.YUVA; - *u = buf->u; - *v = buf->v; - *stride = buf->y_stride; - *uv_stride = buf->u_stride; - assert(buf->u_stride == buf->v_stride); - } - return out; -} - -static void DefaultFeatures(WebPBitstreamFeatures* const features) { - assert(features != NULL); - memset(features, 0, sizeof(*features)); -} - -static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size, - WebPBitstreamFeatures* const features) { - if (features == NULL || data == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - DefaultFeatures(features); - - // Only parse enough of the data to retrieve the features. - return ParseHeadersInternal(data, data_size, - &features->width, &features->height, - &features->has_alpha, &features->has_animation, - &features->format, NULL); -} - -//------------------------------------------------------------------------------ -// WebPGetInfo() - -int WebPGetInfo(const uint8_t* data, size_t data_size, - int* width, int* height) { - WebPBitstreamFeatures features; - - if (GetFeatures(data, data_size, &features) != VP8_STATUS_OK) { - return 0; - } - - if (width != NULL) { - *width = features.width; - } - if (height != NULL) { - *height = features.height; - } - - return 1; -} - -//------------------------------------------------------------------------------ -// Advance decoding API - -int WebPInitDecoderConfigInternal(WebPDecoderConfig* config, - int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { - return 0; // version mismatch - } - if (config == NULL) { - return 0; - } - memset(config, 0, sizeof(*config)); - DefaultFeatures(&config->input); - WebPInitDecBuffer(&config->output); - return 1; -} - -VP8StatusCode WebPGetFeaturesInternal(const uint8_t* data, size_t data_size, - WebPBitstreamFeatures* features, - int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { - return VP8_STATUS_INVALID_PARAM; // version mismatch - } - if (features == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - return GetFeatures(data, data_size, features); -} - -VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, - WebPDecoderConfig* config) { - WebPDecParams params; - VP8StatusCode status; - - if (config == NULL) { - return VP8_STATUS_INVALID_PARAM; - } - - status = GetFeatures(data, data_size, &config->input); - if (status != VP8_STATUS_OK) { - if (status == VP8_STATUS_NOT_ENOUGH_DATA) { - return VP8_STATUS_BITSTREAM_ERROR; // Not-enough-data treated as error. - } - return status; - } - - WebPResetDecParams(¶ms); - params.options = &config->options; - params.output = &config->output; - if (WebPAvoidSlowMemory(params.output, &config->input)) { - // decoding to slow memory: use a temporary in-mem buffer to decode into. - WebPDecBuffer in_mem_buffer; - WebPInitDecBuffer(&in_mem_buffer); - in_mem_buffer.colorspace = config->output.colorspace; - in_mem_buffer.width = config->input.width; - in_mem_buffer.height = config->input.height; - params.output = &in_mem_buffer; - status = DecodeInto(data, data_size, ¶ms); - if (status == VP8_STATUS_OK) { // do the slow-copy - status = WebPCopyDecBufferPixels(&in_mem_buffer, &config->output); - } - WebPFreeDecBuffer(&in_mem_buffer); - } else { - status = DecodeInto(data, data_size, ¶ms); - } - - return status; -} - -//------------------------------------------------------------------------------ -// Cropping and rescaling. - -int WebPIoInitFromOptions(const WebPDecoderOptions* const options, - VP8Io* const io, WEBP_CSP_MODE src_colorspace) { - const int W = io->width; - const int H = io->height; - int x = 0, y = 0, w = W, h = H; - - // Cropping - io->use_cropping = (options != NULL) && (options->use_cropping > 0); - if (io->use_cropping) { - w = options->crop_width; - h = options->crop_height; - x = options->crop_left; - y = options->crop_top; - if (!WebPIsRGBMode(src_colorspace)) { // only snap for YUV420 - x &= ~1; - y &= ~1; - } - if (x < 0 || y < 0 || w <= 0 || h <= 0 || x + w > W || y + h > H) { - return 0; // out of frame boundary error - } - } - io->crop_left = x; - io->crop_top = y; - io->crop_right = x + w; - io->crop_bottom = y + h; - io->mb_w = w; - io->mb_h = h; - - // Scaling - io->use_scaling = (options != NULL) && (options->use_scaling > 0); - if (io->use_scaling) { - int scaled_width = options->scaled_width; - int scaled_height = options->scaled_height; - if (!WebPRescalerGetScaledDimensions(w, h, &scaled_width, &scaled_height)) { - return 0; - } - io->scaled_width = scaled_width; - io->scaled_height = scaled_height; - } - - // Filter - io->bypass_filtering = (options != NULL) && options->bypass_filtering; - - // Fancy upsampler -#ifdef FANCY_UPSAMPLING - io->fancy_upsampling = (options == NULL) || (!options->no_fancy_upsampling); -#endif - - if (io->use_scaling) { - // disable filter (only for large downscaling ratio). - io->bypass_filtering = (io->scaled_width < W * 3 / 4) && - (io->scaled_height < H * 3 / 4); - io->fancy_upsampling = 0; - } - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/drivers/webp/demux/anim_decode.c b/drivers/webp/demux/anim_decode.c deleted file mode 100644 index 39cf3de197..0000000000 --- a/drivers/webp/demux/anim_decode.c +++ /dev/null @@ -1,442 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// AnimDecoder implementation. -// - -#ifdef HAVE_CONFIG_H -#include "webp/config.h" -#endif - -#include <assert.h> -#include <string.h> - -#include "../utils/utils.h" -#include "webp/decode.h" -#include "webp/demux.h" - -#define NUM_CHANNELS 4 - -typedef void (*BlendRowFunc)(uint32_t* const, const uint32_t* const, int); -static void BlendPixelRowNonPremult(uint32_t* const src, - const uint32_t* const dst, int num_pixels); -static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst, - int num_pixels); - -struct WebPAnimDecoder { - WebPDemuxer* demux_; // Demuxer created from given WebP bitstream. - WebPDecoderConfig config_; // Decoder config. - // Note: we use a pointer to a function blending multiple pixels at a time to - // allow possible inlining of per-pixel blending function. - BlendRowFunc blend_func_; // Pointer to the chose blend row function. - WebPAnimInfo info_; // Global info about the animation. - uint8_t* curr_frame_; // Current canvas (not disposed). - uint8_t* prev_frame_disposed_; // Previous canvas (properly disposed). - int prev_frame_timestamp_; // Previous frame timestamp (milliseconds). - WebPIterator prev_iter_; // Iterator object for previous frame. - int prev_frame_was_keyframe_; // True if previous frame was a keyframe. - int next_frame_; // Index of the next frame to be decoded - // (starting from 1). -}; - -static void DefaultDecoderOptions(WebPAnimDecoderOptions* const dec_options) { - dec_options->color_mode = MODE_RGBA; - dec_options->use_threads = 0; -} - -int WebPAnimDecoderOptionsInitInternal(WebPAnimDecoderOptions* dec_options, - int abi_version) { - if (dec_options == NULL || - WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) { - return 0; - } - DefaultDecoderOptions(dec_options); - return 1; -} - -static int ApplyDecoderOptions(const WebPAnimDecoderOptions* const dec_options, - WebPAnimDecoder* const dec) { - WEBP_CSP_MODE mode; - WebPDecoderConfig* config = &dec->config_; - assert(dec_options != NULL); - - mode = dec_options->color_mode; - if (mode != MODE_RGBA && mode != MODE_BGRA && - mode != MODE_rgbA && mode != MODE_bgrA) { - return 0; - } - dec->blend_func_ = (mode == MODE_RGBA || mode == MODE_BGRA) - ? &BlendPixelRowNonPremult - : &BlendPixelRowPremult; - WebPInitDecoderConfig(config); - config->output.colorspace = mode; - config->output.is_external_memory = 1; - config->options.use_threads = dec_options->use_threads; - // Note: config->output.u.RGBA is set at the time of decoding each frame. - return 1; -} - -WebPAnimDecoder* WebPAnimDecoderNewInternal( - const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options, - int abi_version) { - WebPAnimDecoderOptions options; - WebPAnimDecoder* dec = NULL; - if (webp_data == NULL || - WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) { - return NULL; - } - - // Note: calloc() so that the pointer members are initialized to NULL. - dec = (WebPAnimDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); - if (dec == NULL) goto Error; - - if (dec_options != NULL) { - options = *dec_options; - } else { - DefaultDecoderOptions(&options); - } - if (!ApplyDecoderOptions(&options, dec)) goto Error; - - dec->demux_ = WebPDemux(webp_data); - if (dec->demux_ == NULL) goto Error; - - dec->info_.canvas_width = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_WIDTH); - dec->info_.canvas_height = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_HEIGHT); - dec->info_.loop_count = WebPDemuxGetI(dec->demux_, WEBP_FF_LOOP_COUNT); - dec->info_.bgcolor = WebPDemuxGetI(dec->demux_, WEBP_FF_BACKGROUND_COLOR); - dec->info_.frame_count = WebPDemuxGetI(dec->demux_, WEBP_FF_FRAME_COUNT); - - { - const int canvas_bytes = - dec->info_.canvas_width * NUM_CHANNELS * dec->info_.canvas_height; - // Note: calloc() because we fill frame with zeroes as well. - dec->curr_frame_ = WebPSafeCalloc(1ULL, canvas_bytes); - if (dec->curr_frame_ == NULL) goto Error; - dec->prev_frame_disposed_ = WebPSafeCalloc(1ULL, canvas_bytes); - if (dec->prev_frame_disposed_ == NULL) goto Error; - } - - WebPAnimDecoderReset(dec); - - return dec; - - Error: - WebPAnimDecoderDelete(dec); - return NULL; -} - -int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, WebPAnimInfo* info) { - if (dec == NULL || info == NULL) return 0; - *info = dec->info_; - return 1; -} - -// Returns true if the frame covers the full canvas. -static int IsFullFrame(int width, int height, int canvas_width, - int canvas_height) { - return (width == canvas_width && height == canvas_height); -} - -// Clear the canvas to transparent. -static void ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width, - uint32_t canvas_height) { - memset(buf, 0, canvas_width * NUM_CHANNELS * canvas_height); -} - -// Clear given frame rectangle to transparent. -static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset, - int y_offset, int width, int height) { - int j; - assert(width * NUM_CHANNELS <= buf_stride); - buf += y_offset * buf_stride + x_offset * NUM_CHANNELS; - for (j = 0; j < height; ++j) { - memset(buf, 0, width * NUM_CHANNELS); - buf += buf_stride; - } -} - -// Copy width * height pixels from 'src' to 'dst'. -static void CopyCanvas(const uint8_t* src, uint8_t* dst, - uint32_t width, uint32_t height) { - assert(src != NULL && dst != NULL); - memcpy(dst, src, width * NUM_CHANNELS * height); -} - -// Returns true if the current frame is a key-frame. -static int IsKeyFrame(const WebPIterator* const curr, - const WebPIterator* const prev, - int prev_frame_was_key_frame, - int canvas_width, int canvas_height) { - if (curr->frame_num == 1) { - return 1; - } else if ((!curr->has_alpha || curr->blend_method == WEBP_MUX_NO_BLEND) && - IsFullFrame(curr->width, curr->height, - canvas_width, canvas_height)) { - return 1; - } else { - return (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) && - (IsFullFrame(prev->width, prev->height, canvas_width, - canvas_height) || - prev_frame_was_key_frame); - } -} - - -// Blend a single channel of 'src' over 'dst', given their alpha channel values. -// 'src' and 'dst' are assumed to be NOT pre-multiplied by alpha. -static uint8_t BlendChannelNonPremult(uint32_t src, uint8_t src_a, - uint32_t dst, uint8_t dst_a, - uint32_t scale, int shift) { - const uint8_t src_channel = (src >> shift) & 0xff; - const uint8_t dst_channel = (dst >> shift) & 0xff; - const uint32_t blend_unscaled = src_channel * src_a + dst_channel * dst_a; - assert(blend_unscaled < (1ULL << 32) / scale); - return (blend_unscaled * scale) >> 24; -} - -// Blend 'src' over 'dst' assuming they are NOT pre-multiplied by alpha. -static uint32_t BlendPixelNonPremult(uint32_t src, uint32_t dst) { - const uint8_t src_a = (src >> 24) & 0xff; - - if (src_a == 0) { - return dst; - } else { - const uint8_t dst_a = (dst >> 24) & 0xff; - // This is the approximate integer arithmetic for the actual formula: - // dst_factor_a = (dst_a * (255 - src_a)) / 255. - const uint8_t dst_factor_a = (dst_a * (256 - src_a)) >> 8; - const uint8_t blend_a = src_a + dst_factor_a; - const uint32_t scale = (1UL << 24) / blend_a; - - const uint8_t blend_r = - BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 0); - const uint8_t blend_g = - BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 8); - const uint8_t blend_b = - BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 16); - assert(src_a + dst_factor_a < 256); - - return (blend_r << 0) | - (blend_g << 8) | - (blend_b << 16) | - ((uint32_t)blend_a << 24); - } -} - -// Blend 'num_pixels' in 'src' over 'dst' assuming they are NOT pre-multiplied -// by alpha. -static void BlendPixelRowNonPremult(uint32_t* const src, - const uint32_t* const dst, int num_pixels) { - int i; - for (i = 0; i < num_pixels; ++i) { - const uint8_t src_alpha = (src[i] >> 24) & 0xff; - if (src_alpha != 0xff) { - src[i] = BlendPixelNonPremult(src[i], dst[i]); - } - } -} - -// Individually multiply each channel in 'pix' by 'scale'. -static WEBP_INLINE uint32_t ChannelwiseMultiply(uint32_t pix, uint32_t scale) { - uint32_t mask = 0x00FF00FF; - uint32_t rb = ((pix & mask) * scale) >> 8; - uint32_t ag = ((pix >> 8) & mask) * scale; - return (rb & mask) | (ag & ~mask); -} - -// Blend 'src' over 'dst' assuming they are pre-multiplied by alpha. -static uint32_t BlendPixelPremult(uint32_t src, uint32_t dst) { - const uint8_t src_a = (src >> 24) & 0xff; - return src + ChannelwiseMultiply(dst, 256 - src_a); -} - -// Blend 'num_pixels' in 'src' over 'dst' assuming they are pre-multiplied by -// alpha. -static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst, - int num_pixels) { - int i; - for (i = 0; i < num_pixels; ++i) { - const uint8_t src_alpha = (src[i] >> 24) & 0xff; - if (src_alpha != 0xff) { - src[i] = BlendPixelPremult(src[i], dst[i]); - } - } -} - -// Returns two ranges (<left, width> pairs) at row 'canvas_y', that belong to -// 'src' but not 'dst'. A point range is empty if the corresponding width is 0. -static void FindBlendRangeAtRow(const WebPIterator* const src, - const WebPIterator* const dst, int canvas_y, - int* const left1, int* const width1, - int* const left2, int* const width2) { - const int src_max_x = src->x_offset + src->width; - const int dst_max_x = dst->x_offset + dst->width; - const int dst_max_y = dst->y_offset + dst->height; - assert(canvas_y >= src->y_offset && canvas_y < (src->y_offset + src->height)); - *left1 = -1; - *width1 = 0; - *left2 = -1; - *width2 = 0; - - if (canvas_y < dst->y_offset || canvas_y >= dst_max_y || - src->x_offset >= dst_max_x || src_max_x <= dst->x_offset) { - *left1 = src->x_offset; - *width1 = src->width; - return; - } - - if (src->x_offset < dst->x_offset) { - *left1 = src->x_offset; - *width1 = dst->x_offset - src->x_offset; - } - - if (src_max_x > dst_max_x) { - *left2 = dst_max_x; - *width2 = src_max_x - dst_max_x; - } -} - -int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, - uint8_t** buf_ptr, int* timestamp_ptr) { - WebPIterator iter; - uint32_t width; - uint32_t height; - int is_key_frame; - int timestamp; - BlendRowFunc blend_row; - - if (dec == NULL || buf_ptr == NULL || timestamp_ptr == NULL) return 0; - if (!WebPAnimDecoderHasMoreFrames(dec)) return 0; - - width = dec->info_.canvas_width; - height = dec->info_.canvas_height; - blend_row = dec->blend_func_; - - // Get compressed frame. - if (!WebPDemuxGetFrame(dec->demux_, dec->next_frame_, &iter)) { - return 0; - } - timestamp = dec->prev_frame_timestamp_ + iter.duration; - - // Initialize. - is_key_frame = IsKeyFrame(&iter, &dec->prev_iter_, - dec->prev_frame_was_keyframe_, width, height); - if (is_key_frame) { - ZeroFillCanvas(dec->curr_frame_, width, height); - } else { - CopyCanvas(dec->prev_frame_disposed_, dec->curr_frame_, width, height); - } - - // Decode. - { - const uint8_t* in = iter.fragment.bytes; - const size_t in_size = iter.fragment.size; - const size_t out_offset = - (iter.y_offset * width + iter.x_offset) * NUM_CHANNELS; - WebPDecoderConfig* const config = &dec->config_; - WebPRGBABuffer* const buf = &config->output.u.RGBA; - buf->stride = NUM_CHANNELS * width; - buf->size = buf->stride * iter.height; - buf->rgba = dec->curr_frame_ + out_offset; - - if (WebPDecode(in, in_size, config) != VP8_STATUS_OK) { - goto Error; - } - } - - // During the decoding of current frame, we may have set some pixels to be - // transparent (i.e. alpha < 255). However, the value of each of these - // pixels should have been determined by blending it against the value of - // that pixel in the previous frame if blending method of is WEBP_MUX_BLEND. - if (iter.frame_num > 1 && iter.blend_method == WEBP_MUX_BLEND && - !is_key_frame) { - if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_NONE) { - int y; - // Blend transparent pixels with pixels in previous canvas. - for (y = 0; y < iter.height; ++y) { - const size_t offset = - (iter.y_offset + y) * width + iter.x_offset; - blend_row((uint32_t*)dec->curr_frame_ + offset, - (uint32_t*)dec->prev_frame_disposed_ + offset, iter.width); - } - } else { - int y; - assert(dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND); - // We need to blend a transparent pixel with its value just after - // initialization. That is, blend it with: - // * Fully transparent pixel if it belongs to prevRect <-- No-op. - // * The pixel in the previous canvas otherwise <-- Need alpha-blending. - for (y = 0; y < iter.height; ++y) { - const int canvas_y = iter.y_offset + y; - int left1, width1, left2, width2; - FindBlendRangeAtRow(&iter, &dec->prev_iter_, canvas_y, &left1, &width1, - &left2, &width2); - if (width1 > 0) { - const size_t offset1 = canvas_y * width + left1; - blend_row((uint32_t*)dec->curr_frame_ + offset1, - (uint32_t*)dec->prev_frame_disposed_ + offset1, width1); - } - if (width2 > 0) { - const size_t offset2 = canvas_y * width + left2; - blend_row((uint32_t*)dec->curr_frame_ + offset2, - (uint32_t*)dec->prev_frame_disposed_ + offset2, width2); - } - } - } - } - - // Update info of the previous frame and dispose it for the next iteration. - dec->prev_frame_timestamp_ = timestamp; - dec->prev_iter_ = iter; - dec->prev_frame_was_keyframe_ = is_key_frame; - CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height); - if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { - ZeroFillFrameRect(dec->prev_frame_disposed_, width * NUM_CHANNELS, - dec->prev_iter_.x_offset, dec->prev_iter_.y_offset, - dec->prev_iter_.width, dec->prev_iter_.height); - } - ++dec->next_frame_; - - // All OK, fill in the values. - *buf_ptr = dec->curr_frame_; - *timestamp_ptr = timestamp; - return 1; - - Error: - WebPDemuxReleaseIterator(&iter); - return 0; -} - -int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec) { - if (dec == NULL) return 0; - return (dec->next_frame_ <= (int)dec->info_.frame_count); -} - -void WebPAnimDecoderReset(WebPAnimDecoder* dec) { - if (dec != NULL) { - dec->prev_frame_timestamp_ = 0; - memset(&dec->prev_iter_, 0, sizeof(dec->prev_iter_)); - dec->prev_frame_was_keyframe_ = 0; - dec->next_frame_ = 1; - } -} - -const WebPDemuxer* WebPAnimDecoderGetDemuxer(const WebPAnimDecoder* dec) { - if (dec == NULL) return NULL; - return dec->demux_; -} - -void WebPAnimDecoderDelete(WebPAnimDecoder* dec) { - if (dec != NULL) { - WebPDemuxDelete(dec->demux_); - WebPSafeFree(dec->curr_frame_); - WebPSafeFree(dec->prev_frame_disposed_); - WebPSafeFree(dec); - } -} diff --git a/drivers/webp/demux/demux.c b/drivers/webp/demux/demux.c deleted file mode 100644 index df93c5b379..0000000000 --- a/drivers/webp/demux/demux.c +++ /dev/null @@ -1,966 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebP container demux. -// - -#ifdef HAVE_CONFIG_H -#include "webp/config.h" -#endif - -#include <assert.h> -#include <stdlib.h> -#include <string.h> - -#include "../utils/utils.h" -#include "webp/decode.h" // WebPGetFeatures -#include "webp/demux.h" -#include "webp/format_constants.h" - -#define DMUX_MAJ_VERSION 0 -#define DMUX_MIN_VERSION 3 -#define DMUX_REV_VERSION 0 - -typedef struct { - size_t start_; // start location of the data - size_t end_; // end location - size_t riff_end_; // riff chunk end location, can be > end_. - size_t buf_size_; // size of the buffer - const uint8_t* buf_; -} MemBuffer; - -typedef struct { - size_t offset_; - size_t size_; -} ChunkData; - -typedef struct Frame { - int x_offset_, y_offset_; - int width_, height_; - int has_alpha_; - int duration_; - WebPMuxAnimDispose dispose_method_; - WebPMuxAnimBlend blend_method_; - int frame_num_; - int complete_; // img_components_ contains a full image. - ChunkData img_components_[2]; // 0=VP8{,L} 1=ALPH - struct Frame* next_; -} Frame; - -typedef struct Chunk { - ChunkData data_; - struct Chunk* next_; -} Chunk; - -struct WebPDemuxer { - MemBuffer mem_; - WebPDemuxState state_; - int is_ext_format_; - uint32_t feature_flags_; - int canvas_width_, canvas_height_; - int loop_count_; - uint32_t bgcolor_; - int num_frames_; - Frame* frames_; - Frame** frames_tail_; - Chunk* chunks_; // non-image chunks - Chunk** chunks_tail_; -}; - -typedef enum { - PARSE_OK, - PARSE_NEED_MORE_DATA, - PARSE_ERROR -} ParseStatus; - -typedef struct ChunkParser { - uint8_t id[4]; - ParseStatus (*parse)(WebPDemuxer* const dmux); - int (*valid)(const WebPDemuxer* const dmux); -} ChunkParser; - -static ParseStatus ParseSingleImage(WebPDemuxer* const dmux); -static ParseStatus ParseVP8X(WebPDemuxer* const dmux); -static int IsValidSimpleFormat(const WebPDemuxer* const dmux); -static int IsValidExtendedFormat(const WebPDemuxer* const dmux); - -static const ChunkParser kMasterChunks[] = { - { { 'V', 'P', '8', ' ' }, ParseSingleImage, IsValidSimpleFormat }, - { { 'V', 'P', '8', 'L' }, ParseSingleImage, IsValidSimpleFormat }, - { { 'V', 'P', '8', 'X' }, ParseVP8X, IsValidExtendedFormat }, - { { '0', '0', '0', '0' }, NULL, NULL }, -}; - -//------------------------------------------------------------------------------ - -int WebPGetDemuxVersion(void) { - return (DMUX_MAJ_VERSION << 16) | (DMUX_MIN_VERSION << 8) | DMUX_REV_VERSION; -} - -// ----------------------------------------------------------------------------- -// MemBuffer - -static int RemapMemBuffer(MemBuffer* const mem, - const uint8_t* data, size_t size) { - if (size < mem->buf_size_) return 0; // can't remap to a shorter buffer! - - mem->buf_ = data; - mem->end_ = mem->buf_size_ = size; - return 1; -} - -static int InitMemBuffer(MemBuffer* const mem, - const uint8_t* data, size_t size) { - memset(mem, 0, sizeof(*mem)); - return RemapMemBuffer(mem, data, size); -} - -// Return the remaining data size available in 'mem'. -static WEBP_INLINE size_t MemDataSize(const MemBuffer* const mem) { - return (mem->end_ - mem->start_); -} - -// Return true if 'size' exceeds the end of the RIFF chunk. -static WEBP_INLINE int SizeIsInvalid(const MemBuffer* const mem, size_t size) { - return (size > mem->riff_end_ - mem->start_); -} - -static WEBP_INLINE void Skip(MemBuffer* const mem, size_t size) { - mem->start_ += size; -} - -static WEBP_INLINE void Rewind(MemBuffer* const mem, size_t size) { - mem->start_ -= size; -} - -static WEBP_INLINE const uint8_t* GetBuffer(MemBuffer* const mem) { - return mem->buf_ + mem->start_; -} - -// Read from 'mem' and skip the read bytes. -static WEBP_INLINE uint8_t ReadByte(MemBuffer* const mem) { - const uint8_t byte = mem->buf_[mem->start_]; - Skip(mem, 1); - return byte; -} - -static WEBP_INLINE int ReadLE16s(MemBuffer* const mem) { - const uint8_t* const data = mem->buf_ + mem->start_; - const int val = GetLE16(data); - Skip(mem, 2); - return val; -} - -static WEBP_INLINE int ReadLE24s(MemBuffer* const mem) { - const uint8_t* const data = mem->buf_ + mem->start_; - const int val = GetLE24(data); - Skip(mem, 3); - return val; -} - -static WEBP_INLINE uint32_t ReadLE32(MemBuffer* const mem) { - const uint8_t* const data = mem->buf_ + mem->start_; - const uint32_t val = GetLE32(data); - Skip(mem, 4); - return val; -} - -// ----------------------------------------------------------------------------- -// Secondary chunk parsing - -static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) { - *dmux->chunks_tail_ = chunk; - chunk->next_ = NULL; - dmux->chunks_tail_ = &chunk->next_; -} - -// Add a frame to the end of the list, ensuring the last frame is complete. -// Returns true on success, false otherwise. -static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) { - const Frame* const last_frame = *dmux->frames_tail_; - if (last_frame != NULL && !last_frame->complete_) return 0; - - *dmux->frames_tail_ = frame; - frame->next_ = NULL; - dmux->frames_tail_ = &frame->next_; - return 1; -} - -static void SetFrameInfo(size_t start_offset, size_t size, - int frame_num, int complete, - const WebPBitstreamFeatures* const features, - Frame* const frame) { - frame->img_components_[0].offset_ = start_offset; - frame->img_components_[0].size_ = size; - frame->width_ = features->width; - frame->height_ = features->height; - frame->has_alpha_ |= features->has_alpha; - frame->frame_num_ = frame_num; - frame->complete_ = complete; -} - -// Store image bearing chunks to 'frame'. -static ParseStatus StoreFrame(int frame_num, uint32_t min_size, - MemBuffer* const mem, Frame* const frame) { - int alpha_chunks = 0; - int image_chunks = 0; - int done = (MemDataSize(mem) < min_size); - ParseStatus status = PARSE_OK; - - if (done) return PARSE_NEED_MORE_DATA; - - do { - const size_t chunk_start_offset = mem->start_; - const uint32_t fourcc = ReadLE32(mem); - const uint32_t payload_size = ReadLE32(mem); - const uint32_t payload_size_padded = payload_size + (payload_size & 1); - const size_t payload_available = (payload_size_padded > MemDataSize(mem)) - ? MemDataSize(mem) : payload_size_padded; - const size_t chunk_size = CHUNK_HEADER_SIZE + payload_available; - - if (payload_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; - if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR; - if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA; - - switch (fourcc) { - case MKFOURCC('A', 'L', 'P', 'H'): - if (alpha_chunks == 0) { - ++alpha_chunks; - frame->img_components_[1].offset_ = chunk_start_offset; - frame->img_components_[1].size_ = chunk_size; - frame->has_alpha_ = 1; - frame->frame_num_ = frame_num; - Skip(mem, payload_available); - } else { - goto Done; - } - break; - case MKFOURCC('V', 'P', '8', 'L'): - if (alpha_chunks > 0) return PARSE_ERROR; // VP8L has its own alpha - // fall through - case MKFOURCC('V', 'P', '8', ' '): - if (image_chunks == 0) { - // Extract the bitstream features, tolerating failures when the data - // is incomplete. - WebPBitstreamFeatures features; - const VP8StatusCode vp8_status = - WebPGetFeatures(mem->buf_ + chunk_start_offset, chunk_size, - &features); - if (status == PARSE_NEED_MORE_DATA && - vp8_status == VP8_STATUS_NOT_ENOUGH_DATA) { - return PARSE_NEED_MORE_DATA; - } else if (vp8_status != VP8_STATUS_OK) { - // We have enough data, and yet WebPGetFeatures() failed. - return PARSE_ERROR; - } - ++image_chunks; - SetFrameInfo(chunk_start_offset, chunk_size, frame_num, - status == PARSE_OK, &features, frame); - Skip(mem, payload_available); - } else { - goto Done; - } - break; - Done: - default: - // Restore fourcc/size when moving up one level in parsing. - Rewind(mem, CHUNK_HEADER_SIZE); - done = 1; - break; - } - - if (mem->start_ == mem->riff_end_) { - done = 1; - } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) { - status = PARSE_NEED_MORE_DATA; - } - } while (!done && status == PARSE_OK); - - return status; -} - -// Creates a new Frame if 'actual_size' is within bounds and 'mem' contains -// enough data ('min_size') to parse the payload. -// Returns PARSE_OK on success with *frame pointing to the new Frame. -// Returns PARSE_NEED_MORE_DATA with insufficient data, PARSE_ERROR otherwise. -static ParseStatus NewFrame(const MemBuffer* const mem, - uint32_t min_size, uint32_t actual_size, - Frame** frame) { - if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR; - if (actual_size < min_size) return PARSE_ERROR; - if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; - - *frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(**frame)); - return (*frame == NULL) ? PARSE_ERROR : PARSE_OK; -} - -// Parse a 'ANMF' chunk and any image bearing chunks that immediately follow. -// 'frame_chunk_size' is the previously validated, padded chunk size. -static ParseStatus ParseAnimationFrame( - WebPDemuxer* const dmux, uint32_t frame_chunk_size) { - const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); - const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE; - int added_frame = 0; - int bits; - MemBuffer* const mem = &dmux->mem_; - Frame* frame; - ParseStatus status = - NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame); - if (status != PARSE_OK) return status; - - frame->x_offset_ = 2 * ReadLE24s(mem); - frame->y_offset_ = 2 * ReadLE24s(mem); - frame->width_ = 1 + ReadLE24s(mem); - frame->height_ = 1 + ReadLE24s(mem); - frame->duration_ = ReadLE24s(mem); - bits = ReadByte(mem); - frame->dispose_method_ = - (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE; - frame->blend_method_ = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND; - if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) { - WebPSafeFree(frame); - return PARSE_ERROR; - } - - // Store a frame only if the animation flag is set there is some data for - // this frame is available. - status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame); - if (status != PARSE_ERROR && is_animation && frame->frame_num_ > 0) { - added_frame = AddFrame(dmux, frame); - if (added_frame) { - ++dmux->num_frames_; - } else { - status = PARSE_ERROR; - } - } - - if (!added_frame) WebPSafeFree(frame); - return status; -} - -// General chunk storage, starting with the header at 'start_offset', allowing -// the user to request the payload via a fourcc string. 'size' includes the -// header and the unpadded payload size. -// Returns true on success, false otherwise. -static int StoreChunk(WebPDemuxer* const dmux, - size_t start_offset, uint32_t size) { - Chunk* const chunk = (Chunk*)WebPSafeCalloc(1ULL, sizeof(*chunk)); - if (chunk == NULL) return 0; - - chunk->data_.offset_ = start_offset; - chunk->data_.size_ = size; - AddChunk(dmux, chunk); - return 1; -} - -// ----------------------------------------------------------------------------- -// Primary chunk parsing - -static ParseStatus ReadHeader(MemBuffer* const mem) { - const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE; - uint32_t riff_size; - - // Basic file level validation. - if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; - if (memcmp(GetBuffer(mem), "RIFF", CHUNK_SIZE_BYTES) || - memcmp(GetBuffer(mem) + CHUNK_HEADER_SIZE, "WEBP", CHUNK_SIZE_BYTES)) { - return PARSE_ERROR; - } - - riff_size = GetLE32(GetBuffer(mem) + TAG_SIZE); - if (riff_size < CHUNK_HEADER_SIZE) return PARSE_ERROR; - if (riff_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; - - // There's no point in reading past the end of the RIFF chunk - mem->riff_end_ = riff_size + CHUNK_HEADER_SIZE; - if (mem->buf_size_ > mem->riff_end_) { - mem->buf_size_ = mem->end_ = mem->riff_end_; - } - - Skip(mem, RIFF_HEADER_SIZE); - return PARSE_OK; -} - -static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) { - const size_t min_size = CHUNK_HEADER_SIZE; - MemBuffer* const mem = &dmux->mem_; - Frame* frame; - ParseStatus status; - int image_added = 0; - - if (dmux->frames_ != NULL) return PARSE_ERROR; - if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR; - if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; - - frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); - if (frame == NULL) return PARSE_ERROR; - - // For the single image case we allow parsing of a partial frame, but we need - // at least CHUNK_HEADER_SIZE for parsing. - status = StoreFrame(1, CHUNK_HEADER_SIZE, &dmux->mem_, frame); - if (status != PARSE_ERROR) { - const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG); - // Clear any alpha when the alpha flag is missing. - if (!has_alpha && frame->img_components_[1].size_ > 0) { - frame->img_components_[1].offset_ = 0; - frame->img_components_[1].size_ = 0; - frame->has_alpha_ = 0; - } - - // Use the frame width/height as the canvas values for non-vp8x files. - // Also, set ALPHA_FLAG if this is a lossless image with alpha. - if (!dmux->is_ext_format_ && frame->width_ > 0 && frame->height_ > 0) { - dmux->state_ = WEBP_DEMUX_PARSED_HEADER; - dmux->canvas_width_ = frame->width_; - dmux->canvas_height_ = frame->height_; - dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0; - } - if (!AddFrame(dmux, frame)) { - status = PARSE_ERROR; // last frame was left incomplete - } else { - image_added = 1; - dmux->num_frames_ = 1; - } - } - - if (!image_added) WebPSafeFree(frame); - return status; -} - -static ParseStatus ParseVP8XChunks(WebPDemuxer* const dmux) { - const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); - MemBuffer* const mem = &dmux->mem_; - int anim_chunks = 0; - ParseStatus status = PARSE_OK; - - do { - int store_chunk = 1; - const size_t chunk_start_offset = mem->start_; - const uint32_t fourcc = ReadLE32(mem); - const uint32_t chunk_size = ReadLE32(mem); - const uint32_t chunk_size_padded = chunk_size + (chunk_size & 1); - - if (chunk_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; - if (SizeIsInvalid(mem, chunk_size_padded)) return PARSE_ERROR; - - switch (fourcc) { - case MKFOURCC('V', 'P', '8', 'X'): { - return PARSE_ERROR; - } - case MKFOURCC('A', 'L', 'P', 'H'): - case MKFOURCC('V', 'P', '8', ' '): - case MKFOURCC('V', 'P', '8', 'L'): { - // check that this isn't an animation (all frames should be in an ANMF). - if (anim_chunks > 0 || is_animation) return PARSE_ERROR; - - Rewind(mem, CHUNK_HEADER_SIZE); - status = ParseSingleImage(dmux); - break; - } - case MKFOURCC('A', 'N', 'I', 'M'): { - if (chunk_size_padded < ANIM_CHUNK_SIZE) return PARSE_ERROR; - - if (MemDataSize(mem) < chunk_size_padded) { - status = PARSE_NEED_MORE_DATA; - } else if (anim_chunks == 0) { - ++anim_chunks; - dmux->bgcolor_ = ReadLE32(mem); - dmux->loop_count_ = ReadLE16s(mem); - Skip(mem, chunk_size_padded - ANIM_CHUNK_SIZE); - } else { - store_chunk = 0; - goto Skip; - } - break; - } - case MKFOURCC('A', 'N', 'M', 'F'): { - if (anim_chunks == 0) return PARSE_ERROR; // 'ANIM' precedes frames. - status = ParseAnimationFrame(dmux, chunk_size_padded); - break; - } - case MKFOURCC('I', 'C', 'C', 'P'): { - store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG); - goto Skip; - } - case MKFOURCC('E', 'X', 'I', 'F'): { - store_chunk = !!(dmux->feature_flags_ & EXIF_FLAG); - goto Skip; - } - case MKFOURCC('X', 'M', 'P', ' '): { - store_chunk = !!(dmux->feature_flags_ & XMP_FLAG); - goto Skip; - } - Skip: - default: { - if (chunk_size_padded <= MemDataSize(mem)) { - if (store_chunk) { - // Store only the chunk header and unpadded size as only the payload - // will be returned to the user. - if (!StoreChunk(dmux, chunk_start_offset, - CHUNK_HEADER_SIZE + chunk_size)) { - return PARSE_ERROR; - } - } - Skip(mem, chunk_size_padded); - } else { - status = PARSE_NEED_MORE_DATA; - } - } - } - - if (mem->start_ == mem->riff_end_) { - break; - } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) { - status = PARSE_NEED_MORE_DATA; - } - } while (status == PARSE_OK); - - return status; -} - -static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { - MemBuffer* const mem = &dmux->mem_; - uint32_t vp8x_size; - - if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; - - dmux->is_ext_format_ = 1; - Skip(mem, TAG_SIZE); // VP8X - vp8x_size = ReadLE32(mem); - if (vp8x_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; - if (vp8x_size < VP8X_CHUNK_SIZE) return PARSE_ERROR; - vp8x_size += vp8x_size & 1; - if (SizeIsInvalid(mem, vp8x_size)) return PARSE_ERROR; - if (MemDataSize(mem) < vp8x_size) return PARSE_NEED_MORE_DATA; - - dmux->feature_flags_ = ReadByte(mem); - Skip(mem, 3); // Reserved. - dmux->canvas_width_ = 1 + ReadLE24s(mem); - dmux->canvas_height_ = 1 + ReadLE24s(mem); - if (dmux->canvas_width_ * (uint64_t)dmux->canvas_height_ >= MAX_IMAGE_AREA) { - return PARSE_ERROR; // image final dimension is too large - } - Skip(mem, vp8x_size - VP8X_CHUNK_SIZE); // skip any trailing data. - dmux->state_ = WEBP_DEMUX_PARSED_HEADER; - - if (SizeIsInvalid(mem, CHUNK_HEADER_SIZE)) return PARSE_ERROR; - if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; - - return ParseVP8XChunks(dmux); -} - -// ----------------------------------------------------------------------------- -// Format validation - -static int IsValidSimpleFormat(const WebPDemuxer* const dmux) { - const Frame* const frame = dmux->frames_; - if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1; - - if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0; - if (dmux->state_ == WEBP_DEMUX_DONE && frame == NULL) return 0; - - if (frame->width_ <= 0 || frame->height_ <= 0) return 0; - return 1; -} - -// If 'exact' is true, check that the image resolution matches the canvas. -// If 'exact' is false, check that the x/y offsets do not exceed the canvas. -static int CheckFrameBounds(const Frame* const frame, int exact, - int canvas_width, int canvas_height) { - if (exact) { - if (frame->x_offset_ != 0 || frame->y_offset_ != 0) { - return 0; - } - if (frame->width_ != canvas_width || frame->height_ != canvas_height) { - return 0; - } - } else { - if (frame->x_offset_ < 0 || frame->y_offset_ < 0) return 0; - if (frame->width_ + frame->x_offset_ > canvas_width) return 0; - if (frame->height_ + frame->y_offset_ > canvas_height) return 0; - } - return 1; -} - -static int IsValidExtendedFormat(const WebPDemuxer* const dmux) { - const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); - const int is_fragmented = !!(dmux->feature_flags_ & FRAGMENTS_FLAG); - const Frame* f = dmux->frames_; - - if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1; - - if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0; - if (dmux->loop_count_ < 0) return 0; - if (dmux->state_ == WEBP_DEMUX_DONE && dmux->frames_ == NULL) return 0; - if (is_fragmented) return 0; - - while (f != NULL) { - const int cur_frame_set = f->frame_num_; - int frame_count = 0; - - // Check frame properties. - for (; f != NULL && f->frame_num_ == cur_frame_set; f = f->next_) { - const ChunkData* const image = f->img_components_; - const ChunkData* const alpha = f->img_components_ + 1; - - if (!is_animation && f->frame_num_ > 1) return 0; - - if (f->complete_) { - if (alpha->size_ == 0 && image->size_ == 0) return 0; - // Ensure alpha precedes image bitstream. - if (alpha->size_ > 0 && alpha->offset_ > image->offset_) { - return 0; - } - - if (f->width_ <= 0 || f->height_ <= 0) return 0; - } else { - // There shouldn't be a partial frame in a complete file. - if (dmux->state_ == WEBP_DEMUX_DONE) return 0; - - // Ensure alpha precedes image bitstream. - if (alpha->size_ > 0 && image->size_ > 0 && - alpha->offset_ > image->offset_) { - return 0; - } - // There shouldn't be any frames after an incomplete one. - if (f->next_ != NULL) return 0; - } - - if (f->width_ > 0 && f->height_ > 0 && - !CheckFrameBounds(f, !is_animation, - dmux->canvas_width_, dmux->canvas_height_)) { - return 0; - } - - ++frame_count; - } - } - return 1; -} - -// ----------------------------------------------------------------------------- -// WebPDemuxer object - -static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) { - dmux->state_ = WEBP_DEMUX_PARSING_HEADER; - dmux->loop_count_ = 1; - dmux->bgcolor_ = 0xFFFFFFFF; // White background by default. - dmux->canvas_width_ = -1; - dmux->canvas_height_ = -1; - dmux->frames_tail_ = &dmux->frames_; - dmux->chunks_tail_ = &dmux->chunks_; - dmux->mem_ = *mem; -} - -static ParseStatus CreateRawImageDemuxer(MemBuffer* const mem, - WebPDemuxer** demuxer) { - WebPBitstreamFeatures features; - const VP8StatusCode status = - WebPGetFeatures(mem->buf_, mem->buf_size_, &features); - *demuxer = NULL; - if (status != VP8_STATUS_OK) { - return (status == VP8_STATUS_NOT_ENOUGH_DATA) ? PARSE_NEED_MORE_DATA - : PARSE_ERROR; - } - - { - WebPDemuxer* const dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux)); - Frame* const frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); - if (dmux == NULL || frame == NULL) goto Error; - InitDemux(dmux, mem); - SetFrameInfo(0, mem->buf_size_, 1 /*frame_num*/, 1 /*complete*/, &features, - frame); - if (!AddFrame(dmux, frame)) goto Error; - dmux->state_ = WEBP_DEMUX_DONE; - dmux->canvas_width_ = frame->width_; - dmux->canvas_height_ = frame->height_; - dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0; - dmux->num_frames_ = 1; - assert(IsValidSimpleFormat(dmux)); - *demuxer = dmux; - return PARSE_OK; - - Error: - WebPSafeFree(dmux); - WebPSafeFree(frame); - return PARSE_ERROR; - } -} - -WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial, - WebPDemuxState* state, int version) { - const ChunkParser* parser; - int partial; - ParseStatus status = PARSE_ERROR; - MemBuffer mem; - WebPDemuxer* dmux; - - if (state != NULL) *state = WEBP_DEMUX_PARSE_ERROR; - - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DEMUX_ABI_VERSION)) return NULL; - if (data == NULL || data->bytes == NULL || data->size == 0) return NULL; - - if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL; - status = ReadHeader(&mem); - if (status != PARSE_OK) { - // If parsing of the webp file header fails attempt to handle a raw - // VP8/VP8L frame. Note 'allow_partial' is ignored in this case. - if (status == PARSE_ERROR) { - status = CreateRawImageDemuxer(&mem, &dmux); - if (status == PARSE_OK) { - if (state != NULL) *state = WEBP_DEMUX_DONE; - return dmux; - } - } - if (state != NULL) { - *state = (status == PARSE_NEED_MORE_DATA) ? WEBP_DEMUX_PARSING_HEADER - : WEBP_DEMUX_PARSE_ERROR; - } - return NULL; - } - - partial = (mem.buf_size_ < mem.riff_end_); - if (!allow_partial && partial) return NULL; - - dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux)); - if (dmux == NULL) return NULL; - InitDemux(dmux, &mem); - - status = PARSE_ERROR; - for (parser = kMasterChunks; parser->parse != NULL; ++parser) { - if (!memcmp(parser->id, GetBuffer(&dmux->mem_), TAG_SIZE)) { - status = parser->parse(dmux); - if (status == PARSE_OK) dmux->state_ = WEBP_DEMUX_DONE; - if (status == PARSE_NEED_MORE_DATA && !partial) status = PARSE_ERROR; - if (status != PARSE_ERROR && !parser->valid(dmux)) status = PARSE_ERROR; - if (status == PARSE_ERROR) dmux->state_ = WEBP_DEMUX_PARSE_ERROR; - break; - } - } - if (state != NULL) *state = dmux->state_; - - if (status == PARSE_ERROR) { - WebPDemuxDelete(dmux); - return NULL; - } - return dmux; -} - -void WebPDemuxDelete(WebPDemuxer* dmux) { - Chunk* c; - Frame* f; - if (dmux == NULL) return; - - for (f = dmux->frames_; f != NULL;) { - Frame* const cur_frame = f; - f = f->next_; - WebPSafeFree(cur_frame); - } - for (c = dmux->chunks_; c != NULL;) { - Chunk* const cur_chunk = c; - c = c->next_; - WebPSafeFree(cur_chunk); - } - WebPSafeFree(dmux); -} - -// ----------------------------------------------------------------------------- - -uint32_t WebPDemuxGetI(const WebPDemuxer* dmux, WebPFormatFeature feature) { - if (dmux == NULL) return 0; - - switch (feature) { - case WEBP_FF_FORMAT_FLAGS: return dmux->feature_flags_; - case WEBP_FF_CANVAS_WIDTH: return (uint32_t)dmux->canvas_width_; - case WEBP_FF_CANVAS_HEIGHT: return (uint32_t)dmux->canvas_height_; - case WEBP_FF_LOOP_COUNT: return (uint32_t)dmux->loop_count_; - case WEBP_FF_BACKGROUND_COLOR: return dmux->bgcolor_; - case WEBP_FF_FRAME_COUNT: return (uint32_t)dmux->num_frames_; - } - return 0; -} - -// ----------------------------------------------------------------------------- -// Frame iteration - -static const Frame* GetFrame(const WebPDemuxer* const dmux, int frame_num) { - const Frame* f; - for (f = dmux->frames_; f != NULL; f = f->next_) { - if (frame_num == f->frame_num_) break; - } - return f; -} - -static const uint8_t* GetFramePayload(const uint8_t* const mem_buf, - const Frame* const frame, - size_t* const data_size) { - *data_size = 0; - if (frame != NULL) { - const ChunkData* const image = frame->img_components_; - const ChunkData* const alpha = frame->img_components_ + 1; - size_t start_offset = image->offset_; - *data_size = image->size_; - - // if alpha exists it precedes image, update the size allowing for - // intervening chunks. - if (alpha->size_ > 0) { - const size_t inter_size = (image->offset_ > 0) - ? image->offset_ - (alpha->offset_ + alpha->size_) - : 0; - start_offset = alpha->offset_; - *data_size += alpha->size_ + inter_size; - } - return mem_buf + start_offset; - } - return NULL; -} - -// Create a whole 'frame' from VP8 (+ alpha) or lossless. -static int SynthesizeFrame(const WebPDemuxer* const dmux, - const Frame* const frame, - WebPIterator* const iter) { - const uint8_t* const mem_buf = dmux->mem_.buf_; - size_t payload_size = 0; - const uint8_t* const payload = GetFramePayload(mem_buf, frame, &payload_size); - if (payload == NULL) return 0; - assert(frame != NULL); - - iter->frame_num = frame->frame_num_; - iter->num_frames = dmux->num_frames_; - iter->x_offset = frame->x_offset_; - iter->y_offset = frame->y_offset_; - iter->width = frame->width_; - iter->height = frame->height_; - iter->has_alpha = frame->has_alpha_; - iter->duration = frame->duration_; - iter->dispose_method = frame->dispose_method_; - iter->blend_method = frame->blend_method_; - iter->complete = frame->complete_; - iter->fragment.bytes = payload; - iter->fragment.size = payload_size; - return 1; -} - -static int SetFrame(int frame_num, WebPIterator* const iter) { - const Frame* frame; - const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_; - if (dmux == NULL || frame_num < 0) return 0; - if (frame_num > dmux->num_frames_) return 0; - if (frame_num == 0) frame_num = dmux->num_frames_; - - frame = GetFrame(dmux, frame_num); - if (frame == NULL) return 0; - - return SynthesizeFrame(dmux, frame, iter); -} - -int WebPDemuxGetFrame(const WebPDemuxer* dmux, int frame, WebPIterator* iter) { - if (iter == NULL) return 0; - - memset(iter, 0, sizeof(*iter)); - iter->private_ = (void*)dmux; - return SetFrame(frame, iter); -} - -int WebPDemuxNextFrame(WebPIterator* iter) { - if (iter == NULL) return 0; - return SetFrame(iter->frame_num + 1, iter); -} - -int WebPDemuxPrevFrame(WebPIterator* iter) { - if (iter == NULL) return 0; - if (iter->frame_num <= 1) return 0; - return SetFrame(iter->frame_num - 1, iter); -} - -void WebPDemuxReleaseIterator(WebPIterator* iter) { - (void)iter; -} - -// ----------------------------------------------------------------------------- -// Chunk iteration - -static int ChunkCount(const WebPDemuxer* const dmux, const char fourcc[4]) { - const uint8_t* const mem_buf = dmux->mem_.buf_; - const Chunk* c; - int count = 0; - for (c = dmux->chunks_; c != NULL; c = c->next_) { - const uint8_t* const header = mem_buf + c->data_.offset_; - if (!memcmp(header, fourcc, TAG_SIZE)) ++count; - } - return count; -} - -static const Chunk* GetChunk(const WebPDemuxer* const dmux, - const char fourcc[4], int chunk_num) { - const uint8_t* const mem_buf = dmux->mem_.buf_; - const Chunk* c; - int count = 0; - for (c = dmux->chunks_; c != NULL; c = c->next_) { - const uint8_t* const header = mem_buf + c->data_.offset_; - if (!memcmp(header, fourcc, TAG_SIZE)) ++count; - if (count == chunk_num) break; - } - return c; -} - -static int SetChunk(const char fourcc[4], int chunk_num, - WebPChunkIterator* const iter) { - const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_; - int count; - - if (dmux == NULL || fourcc == NULL || chunk_num < 0) return 0; - count = ChunkCount(dmux, fourcc); - if (count == 0) return 0; - if (chunk_num == 0) chunk_num = count; - - if (chunk_num <= count) { - const uint8_t* const mem_buf = dmux->mem_.buf_; - const Chunk* const chunk = GetChunk(dmux, fourcc, chunk_num); - iter->chunk.bytes = mem_buf + chunk->data_.offset_ + CHUNK_HEADER_SIZE; - iter->chunk.size = chunk->data_.size_ - CHUNK_HEADER_SIZE; - iter->num_chunks = count; - iter->chunk_num = chunk_num; - return 1; - } - return 0; -} - -int WebPDemuxGetChunk(const WebPDemuxer* dmux, - const char fourcc[4], int chunk_num, - WebPChunkIterator* iter) { - if (iter == NULL) return 0; - - memset(iter, 0, sizeof(*iter)); - iter->private_ = (void*)dmux; - return SetChunk(fourcc, chunk_num, iter); -} - -int WebPDemuxNextChunk(WebPChunkIterator* iter) { - if (iter != NULL) { - const char* const fourcc = - (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE; - return SetChunk(fourcc, iter->chunk_num + 1, iter); - } - return 0; -} - -int WebPDemuxPrevChunk(WebPChunkIterator* iter) { - if (iter != NULL && iter->chunk_num > 1) { - const char* const fourcc = - (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE; - return SetChunk(fourcc, iter->chunk_num - 1, iter); - } - return 0; -} - -void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter) { - (void)iter; -} - diff --git a/drivers/webp/dsp/dsp.h b/drivers/webp/dsp/dsp.h deleted file mode 100644 index 2469f7d3ac..0000000000 --- a/drivers/webp/dsp/dsp.h +++ /dev/null @@ -1,569 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Speed-critical functions. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_DSP_DSP_H_ -#define WEBP_DSP_DSP_H_ - -#ifdef HAVE_CONFIG_H -#include "webp/config.h" -#endif - -#include "webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define BPS 32 // this is the common stride for enc/dec - -//------------------------------------------------------------------------------ -// CPU detection - -#if defined(__GNUC__) -# define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__) -# define LOCAL_GCC_PREREQ(maj, min) \ - (LOCAL_GCC_VERSION >= (((maj) << 8) | (min))) -#else -# define LOCAL_GCC_VERSION 0 -# define LOCAL_GCC_PREREQ(maj, min) 0 -#endif - -#ifndef __has_builtin -# define __has_builtin(x) 0 -#endif - -#if defined(_MSC_VER) && _MSC_VER > 1310 && \ - (defined(_M_X64) || defined(_M_IX86)) -#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets -#endif - -#if defined(_MSC_VER) && _MSC_VER >= 1500 && \ - (defined(_M_X64) || defined(_M_IX86)) -#define WEBP_MSC_SSE41 // Visual C++ SSE4.1 targets -#endif - -// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp -// files without intrinsics, allowing the corresponding Init() to be called. -// Files containing intrinsics will need to be built targeting the instruction -// set so should succeed on one of the earlier tests. -#if defined(__SSE2__) || defined(WEBP_MSC_SSE2) || defined(WEBP_HAVE_SSE2) -#define WEBP_USE_SSE2 -#endif - -#if defined(__SSE4_1__) || defined(WEBP_MSC_SSE41) || defined(WEBP_HAVE_SSE41) -#define WEBP_USE_SSE41 -#endif - -#if defined(__AVX2__) || defined(WEBP_HAVE_AVX2) -#define WEBP_USE_AVX2 -#endif - -#if defined(__ANDROID__) && defined(__ARM_ARCH_7A__) -#define WEBP_ANDROID_NEON // Android targets that might support NEON -#endif - -// The intrinsics currently cause compiler errors with arm-nacl-gcc and the -// inline assembly would need to be modified for use with Native Client. -#if (defined(__ARM_NEON__) || defined(WEBP_ANDROID_NEON) || \ - defined(__aarch64__) || defined(WEBP_HAVE_NEON)) && \ - !defined(__native_client__) -#define WEBP_USE_NEON -#endif - -#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM) -#define WEBP_USE_NEON -#define WEBP_USE_INTRINSICS -#endif - -#if defined(__mips__) && !defined(__mips64) && \ - defined(__mips_isa_rev) && (__mips_isa_rev >= 1) && (__mips_isa_rev < 6) -#define WEBP_USE_MIPS32 -#if (__mips_isa_rev >= 2) -#define WEBP_USE_MIPS32_R2 -#if defined(__mips_dspr2) || (__mips_dsp_rev >= 2) -#define WEBP_USE_MIPS_DSP_R2 -#endif -#endif -#endif - -#if defined(__mips_msa) && defined(__mips_isa_rev) && (__mips_isa_rev >= 5) -#define WEBP_USE_MSA -#endif - -// This macro prevents thread_sanitizer from reporting known concurrent writes. -#define WEBP_TSAN_IGNORE_FUNCTION -#if defined(__has_feature) -#if __has_feature(thread_sanitizer) -#undef WEBP_TSAN_IGNORE_FUNCTION -#define WEBP_TSAN_IGNORE_FUNCTION __attribute__((no_sanitize_thread)) -#endif -#endif - -#define WEBP_UBSAN_IGNORE_UNDEF -#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW -#if !defined(WEBP_FORCE_ALIGNED) && defined(__clang__) && \ - defined(__has_attribute) -#if __has_attribute(no_sanitize) -// This macro prevents the undefined behavior sanitizer from reporting -// failures. This is only meant to silence unaligned loads on platforms that -// are known to support them. -#undef WEBP_UBSAN_IGNORE_UNDEF -#define WEBP_UBSAN_IGNORE_UNDEF \ - __attribute__((no_sanitize("undefined"))) - -// This macro prevents the undefined behavior sanitizer from reporting -// failures related to unsigned integer overflows. This is only meant to -// silence cases where this well defined behavior is expected. -#undef WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW -#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW \ - __attribute__((no_sanitize("unsigned-integer-overflow"))) -#endif -#endif - -typedef enum { - kSSE2, - kSSE3, - kSSE4_1, - kAVX, - kAVX2, - kNEON, - kMIPS32, - kMIPSdspR2, - kMSA -} CPUFeature; -// returns true if the CPU supports the feature. -typedef int (*VP8CPUInfo)(CPUFeature feature); -WEBP_EXTERN(VP8CPUInfo) VP8GetCPUInfo; - -//------------------------------------------------------------------------------ -// Init stub generator - -// Defines an init function stub to ensure each module exposes a symbol, -// avoiding a compiler warning. -#define WEBP_DSP_INIT_STUB(func) \ - extern void func(void); \ - WEBP_TSAN_IGNORE_FUNCTION void func(void) {} - -//------------------------------------------------------------------------------ -// Encoding - -// Transforms -// VP8Idct: Does one of two inverse transforms. If do_two is set, the transforms -// will be done for (ref, in, dst) and (ref + 4, in + 16, dst + 4). -typedef void (*VP8Idct)(const uint8_t* ref, const int16_t* in, uint8_t* dst, - int do_two); -typedef void (*VP8Fdct)(const uint8_t* src, const uint8_t* ref, int16_t* out); -typedef void (*VP8WHT)(const int16_t* in, int16_t* out); -extern VP8Idct VP8ITransform; -extern VP8Fdct VP8FTransform; -extern VP8Fdct VP8FTransform2; // performs two transforms at a time -extern VP8WHT VP8FTransformWHT; -// Predictions -// *dst is the destination block. *top and *left can be NULL. -typedef void (*VP8IntraPreds)(uint8_t *dst, const uint8_t* left, - const uint8_t* top); -typedef void (*VP8Intra4Preds)(uint8_t *dst, const uint8_t* top); -extern VP8Intra4Preds VP8EncPredLuma4; -extern VP8IntraPreds VP8EncPredLuma16; -extern VP8IntraPreds VP8EncPredChroma8; - -typedef int (*VP8Metric)(const uint8_t* pix, const uint8_t* ref); -extern VP8Metric VP8SSE16x16, VP8SSE16x8, VP8SSE8x8, VP8SSE4x4; -typedef int (*VP8WMetric)(const uint8_t* pix, const uint8_t* ref, - const uint16_t* const weights); -// The weights for VP8TDisto4x4 and VP8TDisto16x16 contain a row-major -// 4 by 4 symmetric matrix. -extern VP8WMetric VP8TDisto4x4, VP8TDisto16x16; - -typedef void (*VP8BlockCopy)(const uint8_t* src, uint8_t* dst); -extern VP8BlockCopy VP8Copy4x4; -extern VP8BlockCopy VP8Copy16x8; -// Quantization -struct VP8Matrix; // forward declaration -typedef int (*VP8QuantizeBlock)(int16_t in[16], int16_t out[16], - const struct VP8Matrix* const mtx); -// Same as VP8QuantizeBlock, but quantizes two consecutive blocks. -typedef int (*VP8Quantize2Blocks)(int16_t in[32], int16_t out[32], - const struct VP8Matrix* const mtx); - -extern VP8QuantizeBlock VP8EncQuantizeBlock; -extern VP8Quantize2Blocks VP8EncQuantize2Blocks; - -// specific to 2nd transform: -typedef int (*VP8QuantizeBlockWHT)(int16_t in[16], int16_t out[16], - const struct VP8Matrix* const mtx); -extern VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT; - -extern const int VP8DspScan[16 + 4 + 4]; - -// Collect histogram for susceptibility calculation. -#define MAX_COEFF_THRESH 31 // size of histogram used by CollectHistogram. -typedef struct { - // We only need to store max_value and last_non_zero, not the distribution. - int max_value; - int last_non_zero; -} VP8Histogram; -typedef void (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo); -extern VP8CHisto VP8CollectHistogram; -// General-purpose util function to help VP8CollectHistogram(). -void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1], - VP8Histogram* const histo); - -// must be called before using any of the above -void VP8EncDspInit(void); - -//------------------------------------------------------------------------------ -// cost functions (encoding) - -extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p) -// approximate cost per level: -extern const uint16_t VP8LevelFixedCosts[2047 /*MAX_LEVEL*/ + 1]; -extern const uint8_t VP8EncBands[16 + 1]; - -struct VP8Residual; -typedef void (*VP8SetResidualCoeffsFunc)(const int16_t* const coeffs, - struct VP8Residual* const res); -extern VP8SetResidualCoeffsFunc VP8SetResidualCoeffs; - -// Cost calculation function. -typedef int (*VP8GetResidualCostFunc)(int ctx0, - const struct VP8Residual* const res); -extern VP8GetResidualCostFunc VP8GetResidualCost; - -// must be called before anything using the above -void VP8EncDspCostInit(void); - -//------------------------------------------------------------------------------ -// SSIM utils - -// struct for accumulating statistical moments -typedef struct { - double w; // sum(w_i) : sum of weights - double xm, ym; // sum(w_i * x_i), sum(w_i * y_i) - double xxm, xym, yym; // sum(w_i * x_i * x_i), etc. -} VP8DistoStats; - -#define VP8_SSIM_KERNEL 3 // total size of the kernel: 2 * VP8_SSIM_KERNEL + 1 -typedef void (*VP8SSIMAccumulateClippedFunc)(const uint8_t* src1, int stride1, - const uint8_t* src2, int stride2, - int xo, int yo, // center position - int W, int H, // plane dimension - VP8DistoStats* const stats); - -// This version is called with the guarantee that you can load 8 bytes and -// 8 rows at offset src1 and src2 -typedef void (*VP8SSIMAccumulateFunc)(const uint8_t* src1, int stride1, - const uint8_t* src2, int stride2, - VP8DistoStats* const stats); - -extern VP8SSIMAccumulateFunc VP8SSIMAccumulate; // unclipped / unchecked -extern VP8SSIMAccumulateClippedFunc VP8SSIMAccumulateClipped; // with clipping - -// must be called before using any of the above directly -void VP8SSIMDspInit(void); - -//------------------------------------------------------------------------------ -// Decoding - -typedef void (*VP8DecIdct)(const int16_t* coeffs, uint8_t* dst); -// when doing two transforms, coeffs is actually int16_t[2][16]. -typedef void (*VP8DecIdct2)(const int16_t* coeffs, uint8_t* dst, int do_two); -extern VP8DecIdct2 VP8Transform; -extern VP8DecIdct VP8TransformAC3; -extern VP8DecIdct VP8TransformUV; -extern VP8DecIdct VP8TransformDC; -extern VP8DecIdct VP8TransformDCUV; -extern VP8WHT VP8TransformWHT; - -// *dst is the destination block, with stride BPS. Boundary samples are -// assumed accessible when needed. -typedef void (*VP8PredFunc)(uint8_t* dst); -extern VP8PredFunc VP8PredLuma16[/* NUM_B_DC_MODES */]; -extern VP8PredFunc VP8PredChroma8[/* NUM_B_DC_MODES */]; -extern VP8PredFunc VP8PredLuma4[/* NUM_BMODES */]; - -// clipping tables (for filtering) -extern const int8_t* const VP8ksclip1; // clips [-1020, 1020] to [-128, 127] -extern const int8_t* const VP8ksclip2; // clips [-112, 112] to [-16, 15] -extern const uint8_t* const VP8kclip1; // clips [-255,511] to [0,255] -extern const uint8_t* const VP8kabs0; // abs(x) for x in [-255,255] -// must be called first -void VP8InitClipTables(void); - -// simple filter (only for luma) -typedef void (*VP8SimpleFilterFunc)(uint8_t* p, int stride, int thresh); -extern VP8SimpleFilterFunc VP8SimpleVFilter16; -extern VP8SimpleFilterFunc VP8SimpleHFilter16; -extern VP8SimpleFilterFunc VP8SimpleVFilter16i; // filter 3 inner edges -extern VP8SimpleFilterFunc VP8SimpleHFilter16i; - -// regular filter (on both macroblock edges and inner edges) -typedef void (*VP8LumaFilterFunc)(uint8_t* luma, int stride, - int thresh, int ithresh, int hev_t); -typedef void (*VP8ChromaFilterFunc)(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_t); -// on outer edge -extern VP8LumaFilterFunc VP8VFilter16; -extern VP8LumaFilterFunc VP8HFilter16; -extern VP8ChromaFilterFunc VP8VFilter8; -extern VP8ChromaFilterFunc VP8HFilter8; - -// on inner edge -extern VP8LumaFilterFunc VP8VFilter16i; // filtering 3 inner edges altogether -extern VP8LumaFilterFunc VP8HFilter16i; -extern VP8ChromaFilterFunc VP8VFilter8i; // filtering u and v altogether -extern VP8ChromaFilterFunc VP8HFilter8i; - -// Dithering. Combines dithering values (centered around 128) with dst[], -// according to: dst[] = clip(dst[] + (((dither[]-128) + 8) >> 4) -#define VP8_DITHER_DESCALE 4 -#define VP8_DITHER_DESCALE_ROUNDER (1 << (VP8_DITHER_DESCALE - 1)) -#define VP8_DITHER_AMP_BITS 7 -#define VP8_DITHER_AMP_CENTER (1 << VP8_DITHER_AMP_BITS) -extern void (*VP8DitherCombine8x8)(const uint8_t* dither, uint8_t* dst, - int dst_stride); - -// must be called before anything using the above -void VP8DspInit(void); - -//------------------------------------------------------------------------------ -// WebP I/O - -#define FANCY_UPSAMPLING // undefined to remove fancy upsampling support - -// Convert a pair of y/u/v lines together to the output rgb/a colorspace. -// bottom_y can be NULL if only one line of output is needed (at top/bottom). -typedef void (*WebPUpsampleLinePairFunc)( - const uint8_t* top_y, const uint8_t* bottom_y, - const uint8_t* top_u, const uint8_t* top_v, - const uint8_t* cur_u, const uint8_t* cur_v, - uint8_t* top_dst, uint8_t* bottom_dst, int len); - -#ifdef FANCY_UPSAMPLING - -// Fancy upsampling functions to convert YUV to RGB(A) modes -extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; - -#endif // FANCY_UPSAMPLING - -// Per-row point-sampling methods. -typedef void (*WebPSamplerRowFunc)(const uint8_t* y, - const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len); -// Generic function to apply 'WebPSamplerRowFunc' to the whole plane: -void WebPSamplerProcessPlane(const uint8_t* y, int y_stride, - const uint8_t* u, const uint8_t* v, int uv_stride, - uint8_t* dst, int dst_stride, - int width, int height, WebPSamplerRowFunc func); - -// Sampling functions to convert rows of YUV to RGB(A) -extern WebPSamplerRowFunc WebPSamplers[/* MODE_LAST */]; - -// General function for converting two lines of ARGB or RGBA. -// 'alpha_is_last' should be true if 0xff000000 is stored in memory as -// as 0x00, 0x00, 0x00, 0xff (little endian). -WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last); - -// YUV444->RGB converters -typedef void (*WebPYUV444Converter)(const uint8_t* y, - const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len); - -extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */]; - -// Must be called before using the WebPUpsamplers[] (and for premultiplied -// colorspaces like rgbA, rgbA4444, etc) -void WebPInitUpsamplers(void); -// Must be called before using WebPSamplers[] -void WebPInitSamplers(void); -// Must be called before using WebPYUV444Converters[] -void WebPInitYUV444Converters(void); - -//------------------------------------------------------------------------------ -// ARGB -> YUV converters - -// Convert ARGB samples to luma Y. -extern void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width); -// Convert ARGB samples to U/V with downsampling. do_store should be '1' for -// even lines and '0' for odd ones. 'src_width' is the original width, not -// the U/V one. -extern void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v, - int src_width, int do_store); - -// Convert a row of accumulated (four-values) of rgba32 toward U/V -extern void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb, - uint8_t* u, uint8_t* v, int width); - -// Convert RGB or BGR to Y -extern void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width); -extern void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width); - -// used for plain-C fallback. -extern void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v, - int src_width, int do_store); -extern void WebPConvertRGBA32ToUV_C(const uint16_t* rgb, - uint8_t* u, uint8_t* v, int width); - -// Must be called before using the above. -void WebPInitConvertARGBToYUV(void); - -//------------------------------------------------------------------------------ -// Rescaler - -struct WebPRescaler; - -// Import a row of data and save its contribution in the rescaler. -// 'channel' denotes the channel number to be imported. 'Expand' corresponds to -// the wrk->x_expand case. Otherwise, 'Shrink' is to be used. -typedef void (*WebPRescalerImportRowFunc)(struct WebPRescaler* const wrk, - const uint8_t* src); - -extern WebPRescalerImportRowFunc WebPRescalerImportRowExpand; -extern WebPRescalerImportRowFunc WebPRescalerImportRowShrink; - -// Export one row (starting at x_out position) from rescaler. -// 'Expand' corresponds to the wrk->y_expand case. -// Otherwise 'Shrink' is to be used -typedef void (*WebPRescalerExportRowFunc)(struct WebPRescaler* const wrk); -extern WebPRescalerExportRowFunc WebPRescalerExportRowExpand; -extern WebPRescalerExportRowFunc WebPRescalerExportRowShrink; - -// Plain-C implementation, as fall-back. -extern void WebPRescalerImportRowExpandC(struct WebPRescaler* const wrk, - const uint8_t* src); -extern void WebPRescalerImportRowShrinkC(struct WebPRescaler* const wrk, - const uint8_t* src); -extern void WebPRescalerExportRowExpandC(struct WebPRescaler* const wrk); -extern void WebPRescalerExportRowShrinkC(struct WebPRescaler* const wrk); - -// Main entry calls: -extern void WebPRescalerImportRow(struct WebPRescaler* const wrk, - const uint8_t* src); -// Export one row (starting at x_out position) from rescaler. -extern void WebPRescalerExportRow(struct WebPRescaler* const wrk); - -// Must be called first before using the above. -void WebPRescalerDspInit(void); - -//------------------------------------------------------------------------------ -// Utilities for processing transparent channel. - -// Apply alpha pre-multiply on an rgba, bgra or argb plane of size w * h. -// alpha_first should be 0 for argb, 1 for rgba or bgra (where alpha is last). -extern void (*WebPApplyAlphaMultiply)( - uint8_t* rgba, int alpha_first, int w, int h, int stride); - -// Same, buf specifically for RGBA4444 format -extern void (*WebPApplyAlphaMultiply4444)( - uint8_t* rgba4444, int w, int h, int stride); - -// Dispatch the values from alpha[] plane to the ARGB destination 'dst'. -// Returns true if alpha[] plane has non-trivial values different from 0xff. -extern int (*WebPDispatchAlpha)(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint8_t* dst, int dst_stride); - -// Transfer packed 8b alpha[] values to green channel in dst[], zero'ing the -// A/R/B values. 'dst_stride' is the stride for dst[] in uint32_t units. -extern void (*WebPDispatchAlphaToGreen)(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint32_t* dst, int dst_stride); - -// Extract the alpha values from 32b values in argb[] and pack them into alpha[] -// (this is the opposite of WebPDispatchAlpha). -// Returns true if there's only trivial 0xff alpha values. -extern int (*WebPExtractAlpha)(const uint8_t* argb, int argb_stride, - int width, int height, - uint8_t* alpha, int alpha_stride); - -// Pre-Multiply operation transforms x into x * A / 255 (where x=Y,R,G or B). -// Un-Multiply operation transforms x into x * 255 / A. - -// Pre-Multiply or Un-Multiply (if 'inverse' is true) argb values in a row. -extern void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse); - -// Same a WebPMultARGBRow(), but for several rows. -void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, - int inverse); - -// Same for a row of single values, with side alpha values. -extern void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse); - -// Same a WebPMultRow(), but for several 'num_rows' rows. -void WebPMultRows(uint8_t* ptr, int stride, - const uint8_t* alpha, int alpha_stride, - int width, int num_rows, int inverse); - -// Plain-C versions, used as fallback by some implementations. -void WebPMultRowC(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse); -void WebPMultARGBRowC(uint32_t* const ptr, int width, int inverse); - -// To be called first before using the above. -void WebPInitAlphaProcessing(void); - -// ARGB packing function: a/r/g/b input is rgba or bgra order. -extern void (*VP8PackARGB)(const uint8_t* a, const uint8_t* r, - const uint8_t* g, const uint8_t* b, int len, - uint32_t* out); - -// RGB packing function. 'step' can be 3 or 4. r/g/b input is rgb or bgr order. -extern void (*VP8PackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b, - int len, int step, uint32_t* out); - -// To be called first before using the above. -void VP8EncDspARGBInit(void); - -//------------------------------------------------------------------------------ -// Filter functions - -typedef enum { // Filter types. - WEBP_FILTER_NONE = 0, - WEBP_FILTER_HORIZONTAL, - WEBP_FILTER_VERTICAL, - WEBP_FILTER_GRADIENT, - WEBP_FILTER_LAST = WEBP_FILTER_GRADIENT + 1, // end marker - WEBP_FILTER_BEST, // meta-types - WEBP_FILTER_FAST -} WEBP_FILTER_TYPE; - -typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height, - int stride, uint8_t* out); -// In-place un-filtering. -// Warning! 'prev_line' pointer can be equal to 'cur_line' or 'preds'. -typedef void (*WebPUnfilterFunc)(const uint8_t* prev_line, const uint8_t* preds, - uint8_t* cur_line, int width); - -// Filter the given data using the given predictor. -// 'in' corresponds to a 2-dimensional pixel array of size (stride * height) -// in raster order. -// 'stride' is number of bytes per scan line (with possible padding). -// 'out' should be pre-allocated. -extern WebPFilterFunc WebPFilters[WEBP_FILTER_LAST]; - -// In-place reconstruct the original data from the given filtered data. -// The reconstruction will be done for 'num_rows' rows starting from 'row' -// (assuming rows upto 'row - 1' are already reconstructed). -extern WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST]; - -// To be called first before using the above. -void VP8FiltersInit(void); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_DSP_DSP_H_ */ diff --git a/drivers/webp/dsp/lossless.h b/drivers/webp/dsp/lossless.h deleted file mode 100644 index 7709b4fe85..0000000000 --- a/drivers/webp/dsp/lossless.h +++ /dev/null @@ -1,372 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Image transforms and color space conversion methods for lossless decoder. -// -// Authors: Vikas Arora (vikaas.arora@gmail.com) -// Jyrki Alakuijala (jyrki@google.com) - -#ifndef WEBP_DSP_LOSSLESS_H_ -#define WEBP_DSP_LOSSLESS_H_ - -#include "webp/types.h" -#include "webp/decode.h" - -#include "../enc/histogram.h" -#include "../utils/utils.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef WEBP_EXPERIMENTAL_FEATURES -#include "../enc/delta_palettization.h" -#endif // WEBP_EXPERIMENTAL_FEATURES - -//------------------------------------------------------------------------------ -// Decoding - -typedef uint32_t (*VP8LPredictorFunc)(uint32_t left, const uint32_t* const top); -extern VP8LPredictorFunc VP8LPredictors[16]; - -typedef void (*VP8LProcessBlueAndRedFunc)(uint32_t* argb_data, int num_pixels); -extern VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed; - -typedef struct { - // Note: the members are uint8_t, so that any negative values are - // automatically converted to "mod 256" values. - uint8_t green_to_red_; - uint8_t green_to_blue_; - uint8_t red_to_blue_; -} VP8LMultipliers; -typedef void (*VP8LTransformColorFunc)(const VP8LMultipliers* const m, - uint32_t* argb_data, int num_pixels); -extern VP8LTransformColorFunc VP8LTransformColorInverse; - -struct VP8LTransform; // Defined in dec/vp8li.h. - -// Performs inverse transform of data given transform information, start and end -// rows. Transform will be applied to rows [row_start, row_end[. -// The *in and *out pointers refer to source and destination data respectively -// corresponding to the intermediate row (row_start). -void VP8LInverseTransform(const struct VP8LTransform* const transform, - int row_start, int row_end, - const uint32_t* const in, uint32_t* const out); - -// Color space conversion. -typedef void (*VP8LConvertFunc)(const uint32_t* src, int num_pixels, - uint8_t* dst); -extern VP8LConvertFunc VP8LConvertBGRAToRGB; -extern VP8LConvertFunc VP8LConvertBGRAToRGBA; -extern VP8LConvertFunc VP8LConvertBGRAToRGBA4444; -extern VP8LConvertFunc VP8LConvertBGRAToRGB565; -extern VP8LConvertFunc VP8LConvertBGRAToBGR; - -// Converts from BGRA to other color spaces. -void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels, - WEBP_CSP_MODE out_colorspace, uint8_t* const rgba); - -// color mapping related functions. -static WEBP_INLINE uint32_t VP8GetARGBIndex(uint32_t idx) { - return (idx >> 8) & 0xff; -} - -static WEBP_INLINE uint8_t VP8GetAlphaIndex(uint8_t idx) { - return idx; -} - -static WEBP_INLINE uint32_t VP8GetARGBValue(uint32_t val) { - return val; -} - -static WEBP_INLINE uint8_t VP8GetAlphaValue(uint32_t val) { - return (val >> 8) & 0xff; -} - -typedef void (*VP8LMapARGBFunc)(const uint32_t* src, - const uint32_t* const color_map, - uint32_t* dst, int y_start, - int y_end, int width); -typedef void (*VP8LMapAlphaFunc)(const uint8_t* src, - const uint32_t* const color_map, - uint8_t* dst, int y_start, - int y_end, int width); - -extern VP8LMapARGBFunc VP8LMapColor32b; -extern VP8LMapAlphaFunc VP8LMapColor8b; - -// Similar to the static method ColorIndexInverseTransform() that is part of -// lossless.c, but used only for alpha decoding. It takes uint8_t (rather than -// uint32_t) arguments for 'src' and 'dst'. -void VP8LColorIndexInverseTransformAlpha( - const struct VP8LTransform* const transform, int y_start, int y_end, - const uint8_t* src, uint8_t* dst); - -// Expose some C-only fallback functions -void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, - uint32_t* data, int num_pixels); - -void VP8LConvertBGRAToRGB_C(const uint32_t* src, int num_pixels, uint8_t* dst); -void VP8LConvertBGRAToRGBA_C(const uint32_t* src, int num_pixels, uint8_t* dst); -void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src, - int num_pixels, uint8_t* dst); -void VP8LConvertBGRAToRGB565_C(const uint32_t* src, - int num_pixels, uint8_t* dst); -void VP8LConvertBGRAToBGR_C(const uint32_t* src, int num_pixels, uint8_t* dst); -void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels); - -// Must be called before calling any of the above methods. -void VP8LDspInit(void); - -//------------------------------------------------------------------------------ -// Encoding - -extern VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed; -extern VP8LTransformColorFunc VP8LTransformColor; -typedef void (*VP8LCollectColorBlueTransformsFunc)( - const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_blue, int red_to_blue, int histo[]); -extern VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms; - -typedef void (*VP8LCollectColorRedTransformsFunc)( - const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_red, int histo[]); -extern VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms; - -// Expose some C-only fallback functions -void VP8LTransformColor_C(const VP8LMultipliers* const m, - uint32_t* data, int num_pixels); -void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels); -void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_red, int histo[]); -void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_blue, int red_to_blue, - int histo[]); - -//------------------------------------------------------------------------------ -// Image transforms. - -void VP8LResidualImage(int width, int height, int bits, int low_effort, - uint32_t* const argb, uint32_t* const argb_scratch, - uint32_t* const image, int near_lossless, int exact, - int used_subtract_green); - -void VP8LColorSpaceTransform(int width, int height, int bits, int quality, - uint32_t* const argb, uint32_t* image); - -//------------------------------------------------------------------------------ -// Misc methods. - -// Computes sampled size of 'size' when sampling using 'sampling bits'. -static WEBP_INLINE uint32_t VP8LSubSampleSize(uint32_t size, - uint32_t sampling_bits) { - return (size + (1 << sampling_bits) - 1) >> sampling_bits; -} - -// Converts near lossless quality into max number of bits shaved off. -static WEBP_INLINE int VP8LNearLosslessBits(int near_lossless_quality) { - // 100 -> 0 - // 80..99 -> 1 - // 60..79 -> 2 - // 40..59 -> 3 - // 20..39 -> 4 - // 0..19 -> 5 - return 5 - near_lossless_quality / 20; -} - -// ----------------------------------------------------------------------------- -// Faster logarithm for integers. Small values use a look-up table. - -// The threshold till approximate version of log_2 can be used. -// Practically, we can get rid of the call to log() as the two values match to -// very high degree (the ratio of these two is 0.99999x). -// Keeping a high threshold for now. -#define APPROX_LOG_WITH_CORRECTION_MAX 65536 -#define APPROX_LOG_MAX 4096 -#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086 -#define LOG_LOOKUP_IDX_MAX 256 -extern const float kLog2Table[LOG_LOOKUP_IDX_MAX]; -extern const float kSLog2Table[LOG_LOOKUP_IDX_MAX]; -typedef float (*VP8LFastLog2SlowFunc)(uint32_t v); - -extern VP8LFastLog2SlowFunc VP8LFastLog2Slow; -extern VP8LFastLog2SlowFunc VP8LFastSLog2Slow; - -static WEBP_INLINE float VP8LFastLog2(uint32_t v) { - return (v < LOG_LOOKUP_IDX_MAX) ? kLog2Table[v] : VP8LFastLog2Slow(v); -} -// Fast calculation of v * log2(v) for integer input. -static WEBP_INLINE float VP8LFastSLog2(uint32_t v) { - return (v < LOG_LOOKUP_IDX_MAX) ? kSLog2Table[v] : VP8LFastSLog2Slow(v); -} - -// ----------------------------------------------------------------------------- -// Huffman-cost related functions. - -typedef double (*VP8LCostFunc)(const uint32_t* population, int length); -typedef double (*VP8LCostCombinedFunc)(const uint32_t* X, const uint32_t* Y, - int length); -typedef float (*VP8LCombinedShannonEntropyFunc)(const int X[256], - const int Y[256]); - -extern VP8LCostFunc VP8LExtraCost; -extern VP8LCostCombinedFunc VP8LExtraCostCombined; -extern VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy; - -typedef struct { // small struct to hold counters - int counts[2]; // index: 0=zero steak, 1=non-zero streak - int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3] -} VP8LStreaks; - -typedef VP8LStreaks (*VP8LCostCombinedCountFunc)(const uint32_t* X, - const uint32_t* Y, int length); - -extern VP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount; - -typedef struct { // small struct to hold bit entropy results - double entropy; // entropy - uint32_t sum; // sum of the population - int nonzeros; // number of non-zero elements in the population - uint32_t max_val; // maximum value in the population - uint32_t nonzero_code; // index of the last non-zero in the population -} VP8LBitEntropy; - -void VP8LBitEntropyInit(VP8LBitEntropy* const entropy); - -// Get the combined symbol bit entropy and Huffman cost stats for the -// distributions 'X' and 'Y'. Those results can then be refined according to -// codec specific heuristics. -void VP8LGetCombinedEntropyUnrefined(const uint32_t* const X, - const uint32_t* const Y, int length, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats); -// Get the entropy for the distribution 'X'. -void VP8LGetEntropyUnrefined(const uint32_t* const X, int length, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats); - -void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n, - VP8LBitEntropy* const entropy); - -typedef void (*GetEntropyUnrefinedHelperFunc)(uint32_t val, int i, - uint32_t* const val_prev, - int* const i_prev, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats); -// Internal function used by VP8LGet*EntropyUnrefined. -extern GetEntropyUnrefinedHelperFunc VP8LGetEntropyUnrefinedHelper; - -typedef void (*VP8LHistogramAddFunc)(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out); -extern VP8LHistogramAddFunc VP8LHistogramAdd; - -// ----------------------------------------------------------------------------- -// PrefixEncode() - -typedef int (*VP8LVectorMismatchFunc)(const uint32_t* const array1, - const uint32_t* const array2, int length); -// Returns the first index where array1 and array2 are different. -extern VP8LVectorMismatchFunc VP8LVectorMismatch; - -static WEBP_INLINE int VP8LBitsLog2Ceiling(uint32_t n) { - const int log_floor = BitsLog2Floor(n); - if (n == (n & ~(n - 1))) // zero or a power of two. - return log_floor; - else - return log_floor + 1; -} - -// Splitting of distance and length codes into prefixes and -// extra bits. The prefixes are encoded with an entropy code -// while the extra bits are stored just as normal bits. -static WEBP_INLINE void VP8LPrefixEncodeBitsNoLUT(int distance, int* const code, - int* const extra_bits) { - const int highest_bit = BitsLog2Floor(--distance); - const int second_highest_bit = (distance >> (highest_bit - 1)) & 1; - *extra_bits = highest_bit - 1; - *code = 2 * highest_bit + second_highest_bit; -} - -static WEBP_INLINE void VP8LPrefixEncodeNoLUT(int distance, int* const code, - int* const extra_bits, - int* const extra_bits_value) { - const int highest_bit = BitsLog2Floor(--distance); - const int second_highest_bit = (distance >> (highest_bit - 1)) & 1; - *extra_bits = highest_bit - 1; - *extra_bits_value = distance & ((1 << *extra_bits) - 1); - *code = 2 * highest_bit + second_highest_bit; -} - -#define PREFIX_LOOKUP_IDX_MAX 512 -typedef struct { - int8_t code_; - int8_t extra_bits_; -} VP8LPrefixCode; - -// These tables are derived using VP8LPrefixEncodeNoLUT. -extern const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX]; -extern const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX]; -static WEBP_INLINE void VP8LPrefixEncodeBits(int distance, int* const code, - int* const extra_bits) { - if (distance < PREFIX_LOOKUP_IDX_MAX) { - const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance]; - *code = prefix_code.code_; - *extra_bits = prefix_code.extra_bits_; - } else { - VP8LPrefixEncodeBitsNoLUT(distance, code, extra_bits); - } -} - -static WEBP_INLINE void VP8LPrefixEncode(int distance, int* const code, - int* const extra_bits, - int* const extra_bits_value) { - if (distance < PREFIX_LOOKUP_IDX_MAX) { - const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance]; - *code = prefix_code.code_; - *extra_bits = prefix_code.extra_bits_; - *extra_bits_value = kPrefixEncodeExtraBitsValue[distance]; - } else { - VP8LPrefixEncodeNoLUT(distance, code, extra_bits, extra_bits_value); - } -} - -// Sum of each component, mod 256. -static WEBP_INLINE uint32_t VP8LAddPixels(uint32_t a, uint32_t b) { - const uint32_t alpha_and_green = (a & 0xff00ff00u) + (b & 0xff00ff00u); - const uint32_t red_and_blue = (a & 0x00ff00ffu) + (b & 0x00ff00ffu); - return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); -} - -// Difference of each component, mod 256. -static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) { - const uint32_t alpha_and_green = - 0x00ff00ffu + (a & 0xff00ff00u) - (b & 0xff00ff00u); - const uint32_t red_and_blue = - 0xff00ff00u + (a & 0x00ff00ffu) - (b & 0x00ff00ffu); - return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); -} - -void VP8LBundleColorMap(const uint8_t* const row, int width, - int xbits, uint32_t* const dst); - -// Must be called before calling any of the above methods. -void VP8LEncDspInit(void); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // WEBP_DSP_LOSSLESS_H_ diff --git a/drivers/webp/enc/alpha.c b/drivers/webp/enc/alpha.c deleted file mode 100644 index 464df4db09..0000000000 --- a/drivers/webp/enc/alpha.c +++ /dev/null @@ -1,433 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Alpha-plane compression. -// -// Author: Skal (pascal.massimino@gmail.com) - -#include <assert.h> -#include <stdlib.h> - -#include "./vp8enci.h" -#include "../dsp/dsp.h" -#include "../utils/filters.h" -#include "../utils/quant_levels.h" -#include "../utils/utils.h" -#include "webp/format_constants.h" - -// ----------------------------------------------------------------------------- -// Encodes the given alpha data via specified compression method 'method'. -// The pre-processing (quantization) is performed if 'quality' is less than 100. -// For such cases, the encoding is lossy. The valid range is [0, 100] for -// 'quality' and [0, 1] for 'method': -// 'method = 0' - No compression; -// 'method = 1' - Use lossless coder on the alpha plane only -// 'filter' values [0, 4] correspond to prediction modes none, horizontal, -// vertical & gradient filters. The prediction mode 4 will try all the -// prediction modes 0 to 3 and pick the best one. -// 'effort_level': specifies how much effort must be spent to try and reduce -// the compressed output size. In range 0 (quick) to 6 (slow). -// -// 'output' corresponds to the buffer containing compressed alpha data. -// This buffer is allocated by this method and caller should call -// WebPSafeFree(*output) when done. -// 'output_size' corresponds to size of this compressed alpha buffer. -// -// Returns 1 on successfully encoding the alpha and -// 0 if either: -// invalid quality or method, or -// memory allocation for the compressed data fails. - -#include "../enc/vp8li.h" - -static int EncodeLossless(const uint8_t* const data, int width, int height, - int effort_level, // in [0..6] range - VP8LBitWriter* const bw, - WebPAuxStats* const stats) { - int ok = 0; - WebPConfig config; - WebPPicture picture; - - WebPPictureInit(&picture); - picture.width = width; - picture.height = height; - picture.use_argb = 1; - picture.stats = stats; - if (!WebPPictureAlloc(&picture)) return 0; - - // Transfer the alpha values to the green channel. - WebPDispatchAlphaToGreen(data, width, picture.width, picture.height, - picture.argb, picture.argb_stride); - - WebPConfigInit(&config); - config.lossless = 1; - // Enable exact, or it would alter RGB values of transparent alpha, which is - // normally OK but not here since we are not encoding the input image but an - // internal encoding-related image containing necessary exact information in - // RGB channels. - config.exact = 1; - config.method = effort_level; // impact is very small - // Set a low default quality for encoding alpha. Ensure that Alpha quality at - // lower methods (3 and below) is less than the threshold for triggering - // costly 'BackwardReferencesTraceBackwards'. - config.quality = 8.f * effort_level; - assert(config.quality >= 0 && config.quality <= 100.f); - - // TODO(urvang): Temporary fix to avoid generating images that trigger - // a decoder bug related to alpha with color cache. - // See: https://code.google.com/p/webp/issues/detail?id=239 - // Need to re-enable this later. - ok = (VP8LEncodeStream(&config, &picture, bw, 0 /*use_cache*/) == VP8_ENC_OK); - WebPPictureFree(&picture); - ok = ok && !bw->error_; - if (!ok) { - VP8LBitWriterWipeOut(bw); - return 0; - } - return 1; -} - -// ----------------------------------------------------------------------------- - -// Small struct to hold the result of a filter mode compression attempt. -typedef struct { - size_t score; - VP8BitWriter bw; - WebPAuxStats stats; -} FilterTrial; - -// This function always returns an initialized 'bw' object, even upon error. -static int EncodeAlphaInternal(const uint8_t* const data, int width, int height, - int method, int filter, int reduce_levels, - int effort_level, // in [0..6] range - uint8_t* const tmp_alpha, - FilterTrial* result) { - int ok = 0; - const uint8_t* alpha_src; - WebPFilterFunc filter_func; - uint8_t header; - const size_t data_size = width * height; - const uint8_t* output = NULL; - size_t output_size = 0; - VP8LBitWriter tmp_bw; - - assert((uint64_t)data_size == (uint64_t)width * height); // as per spec - assert(filter >= 0 && filter < WEBP_FILTER_LAST); - assert(method >= ALPHA_NO_COMPRESSION); - assert(method <= ALPHA_LOSSLESS_COMPRESSION); - assert(sizeof(header) == ALPHA_HEADER_LEN); - - filter_func = WebPFilters[filter]; - if (filter_func != NULL) { - filter_func(data, width, height, width, tmp_alpha); - alpha_src = tmp_alpha; - } else { - alpha_src = data; - } - - if (method != ALPHA_NO_COMPRESSION) { - ok = VP8LBitWriterInit(&tmp_bw, data_size >> 3); - ok = ok && EncodeLossless(alpha_src, width, height, effort_level, - &tmp_bw, &result->stats); - if (ok) { - output = VP8LBitWriterFinish(&tmp_bw); - output_size = VP8LBitWriterNumBytes(&tmp_bw); - if (output_size > data_size) { - // compressed size is larger than source! Revert to uncompressed mode. - method = ALPHA_NO_COMPRESSION; - VP8LBitWriterWipeOut(&tmp_bw); - } - } else { - VP8LBitWriterWipeOut(&tmp_bw); - return 0; - } - } - - if (method == ALPHA_NO_COMPRESSION) { - output = alpha_src; - output_size = data_size; - ok = 1; - } - - // Emit final result. - header = method | (filter << 2); - if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4; - - VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size); - ok = ok && VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN); - ok = ok && VP8BitWriterAppend(&result->bw, output, output_size); - - if (method != ALPHA_NO_COMPRESSION) { - VP8LBitWriterWipeOut(&tmp_bw); - } - ok = ok && !result->bw.error_; - result->score = VP8BitWriterSize(&result->bw); - return ok; -} - -// ----------------------------------------------------------------------------- - -static int GetNumColors(const uint8_t* data, int width, int height, - int stride) { - int j; - int colors = 0; - uint8_t color[256] = { 0 }; - - for (j = 0; j < height; ++j) { - int i; - const uint8_t* const p = data + j * stride; - for (i = 0; i < width; ++i) { - color[p[i]] = 1; - } - } - for (j = 0; j < 256; ++j) { - if (color[j] > 0) ++colors; - } - return colors; -} - -#define FILTER_TRY_NONE (1 << WEBP_FILTER_NONE) -#define FILTER_TRY_ALL ((1 << WEBP_FILTER_LAST) - 1) - -// Given the input 'filter' option, return an OR'd bit-set of filters to try. -static uint32_t GetFilterMap(const uint8_t* alpha, int width, int height, - int filter, int effort_level) { - uint32_t bit_map = 0U; - if (filter == WEBP_FILTER_FAST) { - // Quick estimate of the best candidate. - int try_filter_none = (effort_level > 3); - const int kMinColorsForFilterNone = 16; - const int kMaxColorsForFilterNone = 192; - const int num_colors = GetNumColors(alpha, width, height, width); - // For low number of colors, NONE yields better compression. - filter = (num_colors <= kMinColorsForFilterNone) - ? WEBP_FILTER_NONE - : WebPEstimateBestFilter(alpha, width, height, width); - bit_map |= 1 << filter; - // For large number of colors, try FILTER_NONE in addition to the best - // filter as well. - if (try_filter_none || num_colors > kMaxColorsForFilterNone) { - bit_map |= FILTER_TRY_NONE; - } - } else if (filter == WEBP_FILTER_NONE) { - bit_map = FILTER_TRY_NONE; - } else { // WEBP_FILTER_BEST -> try all - bit_map = FILTER_TRY_ALL; - } - return bit_map; -} - -static void InitFilterTrial(FilterTrial* const score) { - score->score = (size_t)~0U; - VP8BitWriterInit(&score->bw, 0); -} - -static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height, - size_t data_size, int method, int filter, - int reduce_levels, int effort_level, - uint8_t** const output, - size_t* const output_size, - WebPAuxStats* const stats) { - int ok = 1; - FilterTrial best; - uint32_t try_map = - GetFilterMap(alpha, width, height, filter, effort_level); - InitFilterTrial(&best); - - if (try_map != FILTER_TRY_NONE) { - uint8_t* filtered_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size); - if (filtered_alpha == NULL) return 0; - - for (filter = WEBP_FILTER_NONE; ok && try_map; ++filter, try_map >>= 1) { - if (try_map & 1) { - FilterTrial trial; - ok = EncodeAlphaInternal(alpha, width, height, method, filter, - reduce_levels, effort_level, filtered_alpha, - &trial); - if (ok && trial.score < best.score) { - VP8BitWriterWipeOut(&best.bw); - best = trial; - } else { - VP8BitWriterWipeOut(&trial.bw); - } - } - } - WebPSafeFree(filtered_alpha); - } else { - ok = EncodeAlphaInternal(alpha, width, height, method, WEBP_FILTER_NONE, - reduce_levels, effort_level, NULL, &best); - } - if (ok) { - if (stats != NULL) { - stats->lossless_features = best.stats.lossless_features; - stats->histogram_bits = best.stats.histogram_bits; - stats->transform_bits = best.stats.transform_bits; - stats->cache_bits = best.stats.cache_bits; - stats->palette_size = best.stats.palette_size; - stats->lossless_size = best.stats.lossless_size; - stats->lossless_hdr_size = best.stats.lossless_hdr_size; - stats->lossless_data_size = best.stats.lossless_data_size; - } - *output_size = VP8BitWriterSize(&best.bw); - *output = VP8BitWriterBuf(&best.bw); - } else { - VP8BitWriterWipeOut(&best.bw); - } - return ok; -} - -static int EncodeAlpha(VP8Encoder* const enc, - int quality, int method, int filter, - int effort_level, - uint8_t** const output, size_t* const output_size) { - const WebPPicture* const pic = enc->pic_; - const int width = pic->width; - const int height = pic->height; - - uint8_t* quant_alpha = NULL; - const size_t data_size = width * height; - uint64_t sse = 0; - int ok = 1; - const int reduce_levels = (quality < 100); - - // quick sanity checks - assert((uint64_t)data_size == (uint64_t)width * height); // as per spec - assert(enc != NULL && pic != NULL && pic->a != NULL); - assert(output != NULL && output_size != NULL); - assert(width > 0 && height > 0); - assert(pic->a_stride >= width); - assert(filter >= WEBP_FILTER_NONE && filter <= WEBP_FILTER_FAST); - - if (quality < 0 || quality > 100) { - return 0; - } - - if (method < ALPHA_NO_COMPRESSION || method > ALPHA_LOSSLESS_COMPRESSION) { - return 0; - } - - if (method == ALPHA_NO_COMPRESSION) { - // Don't filter, as filtering will make no impact on compressed size. - filter = WEBP_FILTER_NONE; - } - - quant_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size); - if (quant_alpha == NULL) { - return 0; - } - - // Extract alpha data (width x height) from raw_data (stride x height). - WebPCopyPlane(pic->a, pic->a_stride, quant_alpha, width, width, height); - - if (reduce_levels) { // No Quantization required for 'quality = 100'. - // 16 alpha levels gives quite a low MSE w.r.t original alpha plane hence - // mapped to moderate quality 70. Hence Quality:[0, 70] -> Levels:[2, 16] - // and Quality:]70, 100] -> Levels:]16, 256]. - const int alpha_levels = (quality <= 70) ? (2 + quality / 5) - : (16 + (quality - 70) * 8); - ok = QuantizeLevels(quant_alpha, width, height, alpha_levels, &sse); - } - - if (ok) { - VP8FiltersInit(); - ok = ApplyFiltersAndEncode(quant_alpha, width, height, data_size, method, - filter, reduce_levels, effort_level, output, - output_size, pic->stats); - if (pic->stats != NULL) { // need stats? - pic->stats->coded_size += (int)(*output_size); - enc->sse_[3] = sse; - } - } - - WebPSafeFree(quant_alpha); - return ok; -} - -//------------------------------------------------------------------------------ -// Main calls - -static int CompressAlphaJob(VP8Encoder* const enc, void* dummy) { - const WebPConfig* config = enc->config_; - uint8_t* alpha_data = NULL; - size_t alpha_size = 0; - const int effort_level = config->method; // maps to [0..6] - const WEBP_FILTER_TYPE filter = - (config->alpha_filtering == 0) ? WEBP_FILTER_NONE : - (config->alpha_filtering == 1) ? WEBP_FILTER_FAST : - WEBP_FILTER_BEST; - if (!EncodeAlpha(enc, config->alpha_quality, config->alpha_compression, - filter, effort_level, &alpha_data, &alpha_size)) { - return 0; - } - if (alpha_size != (uint32_t)alpha_size) { // Sanity check. - WebPSafeFree(alpha_data); - return 0; - } - enc->alpha_data_size_ = (uint32_t)alpha_size; - enc->alpha_data_ = alpha_data; - (void)dummy; - return 1; -} - -void VP8EncInitAlpha(VP8Encoder* const enc) { - WebPInitAlphaProcessing(); - enc->has_alpha_ = WebPPictureHasTransparency(enc->pic_); - enc->alpha_data_ = NULL; - enc->alpha_data_size_ = 0; - if (enc->thread_level_ > 0) { - WebPWorker* const worker = &enc->alpha_worker_; - WebPGetWorkerInterface()->Init(worker); - worker->data1 = enc; - worker->data2 = NULL; - worker->hook = (WebPWorkerHook)CompressAlphaJob; - } -} - -int VP8EncStartAlpha(VP8Encoder* const enc) { - if (enc->has_alpha_) { - if (enc->thread_level_ > 0) { - WebPWorker* const worker = &enc->alpha_worker_; - // Makes sure worker is good to go. - if (!WebPGetWorkerInterface()->Reset(worker)) { - return 0; - } - WebPGetWorkerInterface()->Launch(worker); - return 1; - } else { - return CompressAlphaJob(enc, NULL); // just do the job right away - } - } - return 1; -} - -int VP8EncFinishAlpha(VP8Encoder* const enc) { - if (enc->has_alpha_) { - if (enc->thread_level_ > 0) { - WebPWorker* const worker = &enc->alpha_worker_; - if (!WebPGetWorkerInterface()->Sync(worker)) return 0; // error - } - } - return WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); -} - -int VP8EncDeleteAlpha(VP8Encoder* const enc) { - int ok = 1; - if (enc->thread_level_ > 0) { - WebPWorker* const worker = &enc->alpha_worker_; - // finish anything left in flight - ok = WebPGetWorkerInterface()->Sync(worker); - // still need to end the worker, even if !ok - WebPGetWorkerInterface()->End(worker); - } - WebPSafeFree(enc->alpha_data_); - enc->alpha_data_ = NULL; - enc->alpha_data_size_ = 0; - enc->has_alpha_ = 0; - return ok; -} diff --git a/drivers/webp/enc/backward_references.h b/drivers/webp/enc/backward_references.h deleted file mode 100644 index b72a01fb0e..0000000000 --- a/drivers/webp/enc/backward_references.h +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// - -#ifndef WEBP_ENC_BACKWARD_REFERENCES_H_ -#define WEBP_ENC_BACKWARD_REFERENCES_H_ - -#include <assert.h> -#include <stdlib.h> -#include "webp/types.h" -#include "webp/format_constants.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// The maximum allowed limit is 11. -#define MAX_COLOR_CACHE_BITS 10 - -// ----------------------------------------------------------------------------- -// PixOrCopy - -enum Mode { - kLiteral, - kCacheIdx, - kCopy, - kNone -}; - -typedef struct { - // mode as uint8_t to make the memory layout to be exactly 8 bytes. - uint8_t mode; - uint16_t len; - uint32_t argb_or_distance; -} PixOrCopy; - -static WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance, - uint16_t len) { - PixOrCopy retval; - retval.mode = kCopy; - retval.argb_or_distance = distance; - retval.len = len; - return retval; -} - -static WEBP_INLINE PixOrCopy PixOrCopyCreateCacheIdx(int idx) { - PixOrCopy retval; - assert(idx >= 0); - assert(idx < (1 << MAX_COLOR_CACHE_BITS)); - retval.mode = kCacheIdx; - retval.argb_or_distance = idx; - retval.len = 1; - return retval; -} - -static WEBP_INLINE PixOrCopy PixOrCopyCreateLiteral(uint32_t argb) { - PixOrCopy retval; - retval.mode = kLiteral; - retval.argb_or_distance = argb; - retval.len = 1; - return retval; -} - -static WEBP_INLINE int PixOrCopyIsLiteral(const PixOrCopy* const p) { - return (p->mode == kLiteral); -} - -static WEBP_INLINE int PixOrCopyIsCacheIdx(const PixOrCopy* const p) { - return (p->mode == kCacheIdx); -} - -static WEBP_INLINE int PixOrCopyIsCopy(const PixOrCopy* const p) { - return (p->mode == kCopy); -} - -static WEBP_INLINE uint32_t PixOrCopyLiteral(const PixOrCopy* const p, - int component) { - assert(p->mode == kLiteral); - return (p->argb_or_distance >> (component * 8)) & 0xff; -} - -static WEBP_INLINE uint32_t PixOrCopyLength(const PixOrCopy* const p) { - return p->len; -} - -static WEBP_INLINE uint32_t PixOrCopyArgb(const PixOrCopy* const p) { - assert(p->mode == kLiteral); - return p->argb_or_distance; -} - -static WEBP_INLINE uint32_t PixOrCopyCacheIdx(const PixOrCopy* const p) { - assert(p->mode == kCacheIdx); - assert(p->argb_or_distance < (1U << MAX_COLOR_CACHE_BITS)); - return p->argb_or_distance; -} - -static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) { - assert(p->mode == kCopy); - return p->argb_or_distance; -} - -// ----------------------------------------------------------------------------- -// VP8LHashChain - -#define HASH_BITS 18 -#define HASH_SIZE (1 << HASH_BITS) - -typedef struct VP8LHashChain VP8LHashChain; -struct VP8LHashChain { - // The 20 most significant bits contain the offset at which the best match - // is found. These 20 bits are the limit defined by GetWindowSizeForHashChain - // (through WINDOW_SIZE = 1<<20). - // The lower 12 bits contain the length of the match. The 12 bit limit is - // defined in MaxFindCopyLength with MAX_LENGTH=4096. - uint32_t* offset_length_; - // This is the maximum size of the hash_chain that can be constructed. - // Typically this is the pixel count (width x height) for a given image. - int size_; -}; - -// Must be called first, to set size. -int VP8LHashChainInit(VP8LHashChain* const p, int size); -// Pre-compute the best matches for argb. -int VP8LHashChainFill(VP8LHashChain* const p, int quality, - const uint32_t* const argb, int xsize, int ysize); -void VP8LHashChainClear(VP8LHashChain* const p); // release memory - -// ----------------------------------------------------------------------------- -// VP8LBackwardRefs (block-based backward-references storage) - -// maximum number of reference blocks the image will be segmented into -#define MAX_REFS_BLOCK_PER_IMAGE 16 - -typedef struct PixOrCopyBlock PixOrCopyBlock; // forward declaration -typedef struct VP8LBackwardRefs VP8LBackwardRefs; - -// Container for blocks chain -struct VP8LBackwardRefs { - int block_size_; // common block-size - int error_; // set to true if some memory error occurred - PixOrCopyBlock* refs_; // list of currently used blocks - PixOrCopyBlock** tail_; // for list recycling - PixOrCopyBlock* free_blocks_; // free-list - PixOrCopyBlock* last_block_; // used for adding new refs (internal) -}; - -// Initialize the object. 'block_size' is the common block size to store -// references (typically, width * height / MAX_REFS_BLOCK_PER_IMAGE). -void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size); -// Release memory for backward references. -void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs); -// Copies the 'src' backward refs to the 'dst'. Returns 0 in case of error. -int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src, - VP8LBackwardRefs* const dst); - -// Cursor for iterating on references content -typedef struct { - // public: - PixOrCopy* cur_pos; // current position - // private: - PixOrCopyBlock* cur_block_; // current block in the refs list - const PixOrCopy* last_pos_; // sentinel for switching to next block -} VP8LRefsCursor; - -// Returns a cursor positioned at the beginning of the references list. -VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs); -// Returns true if cursor is pointing at a valid position. -static WEBP_INLINE int VP8LRefsCursorOk(const VP8LRefsCursor* const c) { - return (c->cur_pos != NULL); -} -// Move to next block of references. Internal, not to be called directly. -void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c); -// Move to next position, or NULL. Should not be called if !VP8LRefsCursorOk(). -static WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) { - assert(c != NULL); - assert(VP8LRefsCursorOk(c)); - if (++c->cur_pos == c->last_pos_) VP8LRefsCursorNextBlock(c); -} - -// ----------------------------------------------------------------------------- -// Main entry points - -// Evaluates best possible backward references for specified quality. -// The input cache_bits to 'VP8LGetBackwardReferences' sets the maximum cache -// bits to use (passing 0 implies disabling the local color cache). -// The optimal cache bits is evaluated and set for the *cache_bits parameter. -// The return value is the pointer to the best of the two backward refs viz, -// refs[0] or refs[1]. -VP8LBackwardRefs* VP8LGetBackwardReferences( - int width, int height, const uint32_t* const argb, int quality, - int low_effort, int* const cache_bits, - const VP8LHashChain* const hash_chain, VP8LBackwardRefs refs[2]); - -#ifdef __cplusplus -} -#endif - -#endif // WEBP_ENC_BACKWARD_REFERENCES_H_ diff --git a/drivers/webp/enc/config.c b/drivers/webp/enc/config.c deleted file mode 100644 index 8fd2276cb5..0000000000 --- a/drivers/webp/enc/config.c +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Coding tools configuration -// -// Author: Skal (pascal.massimino@gmail.com) - -#include "webp/encode.h" - -//------------------------------------------------------------------------------ -// WebPConfig -//------------------------------------------------------------------------------ - -int WebPConfigInitInternal(WebPConfig* config, - WebPPreset preset, float quality, int version) { - if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) { - return 0; // caller/system version mismatch! - } - if (config == NULL) return 0; - - config->quality = quality; - config->target_size = 0; - config->target_PSNR = 0.; - config->method = 4; - config->sns_strength = 50; - config->filter_strength = 60; // mid-filtering - config->filter_sharpness = 0; - config->filter_type = 1; // default: strong (so U/V is filtered too) - config->partitions = 0; - config->segments = 4; - config->pass = 1; - config->show_compressed = 0; - config->preprocessing = 0; - config->autofilter = 0; - config->partition_limit = 0; - config->alpha_compression = 1; - config->alpha_filtering = 1; - config->alpha_quality = 100; - config->lossless = 0; - config->exact = 0; - config->image_hint = WEBP_HINT_DEFAULT; - config->emulate_jpeg_size = 0; - config->thread_level = 0; - config->low_memory = 0; - config->near_lossless = 100; -#ifdef WEBP_EXPERIMENTAL_FEATURES - config->delta_palettization = 0; -#endif // WEBP_EXPERIMENTAL_FEATURES - - // TODO(skal): tune. - switch (preset) { - case WEBP_PRESET_PICTURE: - config->sns_strength = 80; - config->filter_sharpness = 4; - config->filter_strength = 35; - config->preprocessing &= ~2; // no dithering - break; - case WEBP_PRESET_PHOTO: - config->sns_strength = 80; - config->filter_sharpness = 3; - config->filter_strength = 30; - config->preprocessing |= 2; - break; - case WEBP_PRESET_DRAWING: - config->sns_strength = 25; - config->filter_sharpness = 6; - config->filter_strength = 10; - break; - case WEBP_PRESET_ICON: - config->sns_strength = 0; - config->filter_strength = 0; // disable filtering to retain sharpness - config->preprocessing &= ~2; // no dithering - break; - case WEBP_PRESET_TEXT: - config->sns_strength = 0; - config->filter_strength = 0; // disable filtering to retain sharpness - config->preprocessing &= ~2; // no dithering - config->segments = 2; - break; - case WEBP_PRESET_DEFAULT: - default: - break; - } - return WebPValidateConfig(config); -} - -int WebPValidateConfig(const WebPConfig* config) { - if (config == NULL) return 0; - if (config->quality < 0 || config->quality > 100) - return 0; - if (config->target_size < 0) - return 0; - if (config->target_PSNR < 0) - return 0; - if (config->method < 0 || config->method > 6) - return 0; - if (config->segments < 1 || config->segments > 4) - return 0; - if (config->sns_strength < 0 || config->sns_strength > 100) - return 0; - if (config->filter_strength < 0 || config->filter_strength > 100) - return 0; - if (config->filter_sharpness < 0 || config->filter_sharpness > 7) - return 0; - if (config->filter_type < 0 || config->filter_type > 1) - return 0; - if (config->autofilter < 0 || config->autofilter > 1) - return 0; - if (config->pass < 1 || config->pass > 10) - return 0; - if (config->show_compressed < 0 || config->show_compressed > 1) - return 0; - if (config->preprocessing < 0 || config->preprocessing > 7) - return 0; - if (config->partitions < 0 || config->partitions > 3) - return 0; - if (config->partition_limit < 0 || config->partition_limit > 100) - return 0; - if (config->alpha_compression < 0) - return 0; - if (config->alpha_filtering < 0) - return 0; - if (config->alpha_quality < 0 || config->alpha_quality > 100) - return 0; - if (config->lossless < 0 || config->lossless > 1) - return 0; - if (config->near_lossless < 0 || config->near_lossless > 100) - return 0; - if (config->image_hint >= WEBP_HINT_LAST) - return 0; - if (config->emulate_jpeg_size < 0 || config->emulate_jpeg_size > 1) - return 0; - if (config->thread_level < 0 || config->thread_level > 1) - return 0; - if (config->low_memory < 0 || config->low_memory > 1) - return 0; - if (config->exact < 0 || config->exact > 1) - return 0; -#ifdef WEBP_EXPERIMENTAL_FEATURES - if (config->delta_palettization < 0 || config->delta_palettization > 1) - return 0; -#endif // WEBP_EXPERIMENTAL_FEATURES - return 1; -} - -//------------------------------------------------------------------------------ - -#define MAX_LEVEL 9 - -// Mapping between -z level and -m / -q parameter settings. -static const struct { - uint8_t method_; - uint8_t quality_; -} kLosslessPresets[MAX_LEVEL + 1] = { - { 0, 0 }, { 1, 20 }, { 2, 25 }, { 3, 30 }, { 3, 50 }, - { 4, 50 }, { 4, 75 }, { 4, 90 }, { 5, 90 }, { 6, 100 } -}; - -int WebPConfigLosslessPreset(WebPConfig* config, int level) { - if (config == NULL || level < 0 || level > MAX_LEVEL) return 0; - config->lossless = 1; - config->method = kLosslessPresets[level].method_; - config->quality = kLosslessPresets[level].quality_; - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/drivers/webp/enc/delta_palettization.c b/drivers/webp/enc/delta_palettization.c deleted file mode 100644 index 8bd3a3d233..0000000000 --- a/drivers/webp/enc/delta_palettization.c +++ /dev/null @@ -1,455 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Mislav Bradac (mislavm@google.com) -// - -#include "./delta_palettization.h" - -#ifdef WEBP_EXPERIMENTAL_FEATURES -#include "webp/types.h" -#include "../dsp/lossless.h" - -#define MK_COL(r, g, b) (((r) << 16) + ((g) << 8) + (b)) - -// Format allows palette up to 256 entries, but more palette entries produce -// bigger entropy. In the future it will probably be useful to add more entries -// that are far from the origin of the palette or choose remaining entries -// dynamically. -#define DELTA_PALETTE_SIZE 226 - -// Palette used for delta_palettization. Entries are roughly sorted by distance -// of their signed equivalents from the origin. -static const uint32_t kDeltaPalette[DELTA_PALETTE_SIZE] = { - MK_COL(0u, 0u, 0u), - MK_COL(255u, 255u, 255u), - MK_COL(1u, 1u, 1u), - MK_COL(254u, 254u, 254u), - MK_COL(2u, 2u, 2u), - MK_COL(4u, 4u, 4u), - MK_COL(252u, 252u, 252u), - MK_COL(250u, 0u, 0u), - MK_COL(0u, 250u, 0u), - MK_COL(0u, 0u, 250u), - MK_COL(6u, 0u, 0u), - MK_COL(0u, 6u, 0u), - MK_COL(0u, 0u, 6u), - MK_COL(0u, 0u, 248u), - MK_COL(0u, 0u, 8u), - MK_COL(0u, 248u, 0u), - MK_COL(0u, 248u, 248u), - MK_COL(0u, 248u, 8u), - MK_COL(0u, 8u, 0u), - MK_COL(0u, 8u, 248u), - MK_COL(0u, 8u, 8u), - MK_COL(8u, 8u, 8u), - MK_COL(248u, 0u, 0u), - MK_COL(248u, 0u, 248u), - MK_COL(248u, 0u, 8u), - MK_COL(248u, 248u, 0u), - MK_COL(248u, 8u, 0u), - MK_COL(8u, 0u, 0u), - MK_COL(8u, 0u, 248u), - MK_COL(8u, 0u, 8u), - MK_COL(8u, 248u, 0u), - MK_COL(8u, 8u, 0u), - MK_COL(23u, 23u, 23u), - MK_COL(13u, 13u, 13u), - MK_COL(232u, 232u, 232u), - MK_COL(244u, 244u, 244u), - MK_COL(245u, 245u, 250u), - MK_COL(50u, 50u, 50u), - MK_COL(204u, 204u, 204u), - MK_COL(236u, 236u, 236u), - MK_COL(16u, 16u, 16u), - MK_COL(240u, 16u, 16u), - MK_COL(16u, 240u, 16u), - MK_COL(240u, 240u, 16u), - MK_COL(16u, 16u, 240u), - MK_COL(240u, 16u, 240u), - MK_COL(16u, 240u, 240u), - MK_COL(240u, 240u, 240u), - MK_COL(0u, 0u, 232u), - MK_COL(0u, 232u, 0u), - MK_COL(232u, 0u, 0u), - MK_COL(0u, 0u, 24u), - MK_COL(0u, 24u, 0u), - MK_COL(24u, 0u, 0u), - MK_COL(32u, 32u, 32u), - MK_COL(224u, 32u, 32u), - MK_COL(32u, 224u, 32u), - MK_COL(224u, 224u, 32u), - MK_COL(32u, 32u, 224u), - MK_COL(224u, 32u, 224u), - MK_COL(32u, 224u, 224u), - MK_COL(224u, 224u, 224u), - MK_COL(0u, 0u, 176u), - MK_COL(0u, 0u, 80u), - MK_COL(0u, 176u, 0u), - MK_COL(0u, 176u, 176u), - MK_COL(0u, 176u, 80u), - MK_COL(0u, 80u, 0u), - MK_COL(0u, 80u, 176u), - MK_COL(0u, 80u, 80u), - MK_COL(176u, 0u, 0u), - MK_COL(176u, 0u, 176u), - MK_COL(176u, 0u, 80u), - MK_COL(176u, 176u, 0u), - MK_COL(176u, 80u, 0u), - MK_COL(80u, 0u, 0u), - MK_COL(80u, 0u, 176u), - MK_COL(80u, 0u, 80u), - MK_COL(80u, 176u, 0u), - MK_COL(80u, 80u, 0u), - MK_COL(0u, 0u, 152u), - MK_COL(0u, 0u, 104u), - MK_COL(0u, 152u, 0u), - MK_COL(0u, 152u, 152u), - MK_COL(0u, 152u, 104u), - MK_COL(0u, 104u, 0u), - MK_COL(0u, 104u, 152u), - MK_COL(0u, 104u, 104u), - MK_COL(152u, 0u, 0u), - MK_COL(152u, 0u, 152u), - MK_COL(152u, 0u, 104u), - MK_COL(152u, 152u, 0u), - MK_COL(152u, 104u, 0u), - MK_COL(104u, 0u, 0u), - MK_COL(104u, 0u, 152u), - MK_COL(104u, 0u, 104u), - MK_COL(104u, 152u, 0u), - MK_COL(104u, 104u, 0u), - MK_COL(216u, 216u, 216u), - MK_COL(216u, 216u, 40u), - MK_COL(216u, 216u, 176u), - MK_COL(216u, 216u, 80u), - MK_COL(216u, 40u, 216u), - MK_COL(216u, 40u, 40u), - MK_COL(216u, 40u, 176u), - MK_COL(216u, 40u, 80u), - MK_COL(216u, 176u, 216u), - MK_COL(216u, 176u, 40u), - MK_COL(216u, 176u, 176u), - MK_COL(216u, 176u, 80u), - MK_COL(216u, 80u, 216u), - MK_COL(216u, 80u, 40u), - MK_COL(216u, 80u, 176u), - MK_COL(216u, 80u, 80u), - MK_COL(40u, 216u, 216u), - MK_COL(40u, 216u, 40u), - MK_COL(40u, 216u, 176u), - MK_COL(40u, 216u, 80u), - MK_COL(40u, 40u, 216u), - MK_COL(40u, 40u, 40u), - MK_COL(40u, 40u, 176u), - MK_COL(40u, 40u, 80u), - MK_COL(40u, 176u, 216u), - MK_COL(40u, 176u, 40u), - MK_COL(40u, 176u, 176u), - MK_COL(40u, 176u, 80u), - MK_COL(40u, 80u, 216u), - MK_COL(40u, 80u, 40u), - MK_COL(40u, 80u, 176u), - MK_COL(40u, 80u, 80u), - MK_COL(80u, 216u, 216u), - MK_COL(80u, 216u, 40u), - MK_COL(80u, 216u, 176u), - MK_COL(80u, 216u, 80u), - MK_COL(80u, 40u, 216u), - MK_COL(80u, 40u, 40u), - MK_COL(80u, 40u, 176u), - MK_COL(80u, 40u, 80u), - MK_COL(80u, 176u, 216u), - MK_COL(80u, 176u, 40u), - MK_COL(80u, 176u, 176u), - MK_COL(80u, 176u, 80u), - MK_COL(80u, 80u, 216u), - MK_COL(80u, 80u, 40u), - MK_COL(80u, 80u, 176u), - MK_COL(80u, 80u, 80u), - MK_COL(0u, 0u, 192u), - MK_COL(0u, 0u, 64u), - MK_COL(0u, 0u, 128u), - MK_COL(0u, 192u, 0u), - MK_COL(0u, 192u, 192u), - MK_COL(0u, 192u, 64u), - MK_COL(0u, 192u, 128u), - MK_COL(0u, 64u, 0u), - MK_COL(0u, 64u, 192u), - MK_COL(0u, 64u, 64u), - MK_COL(0u, 64u, 128u), - MK_COL(0u, 128u, 0u), - MK_COL(0u, 128u, 192u), - MK_COL(0u, 128u, 64u), - MK_COL(0u, 128u, 128u), - MK_COL(176u, 216u, 216u), - MK_COL(176u, 216u, 40u), - MK_COL(176u, 216u, 176u), - MK_COL(176u, 216u, 80u), - MK_COL(176u, 40u, 216u), - MK_COL(176u, 40u, 40u), - MK_COL(176u, 40u, 176u), - MK_COL(176u, 40u, 80u), - MK_COL(176u, 176u, 216u), - MK_COL(176u, 176u, 40u), - MK_COL(176u, 176u, 176u), - MK_COL(176u, 176u, 80u), - MK_COL(176u, 80u, 216u), - MK_COL(176u, 80u, 40u), - MK_COL(176u, 80u, 176u), - MK_COL(176u, 80u, 80u), - MK_COL(192u, 0u, 0u), - MK_COL(192u, 0u, 192u), - MK_COL(192u, 0u, 64u), - MK_COL(192u, 0u, 128u), - MK_COL(192u, 192u, 0u), - MK_COL(192u, 192u, 192u), - MK_COL(192u, 192u, 64u), - MK_COL(192u, 192u, 128u), - MK_COL(192u, 64u, 0u), - MK_COL(192u, 64u, 192u), - MK_COL(192u, 64u, 64u), - MK_COL(192u, 64u, 128u), - MK_COL(192u, 128u, 0u), - MK_COL(192u, 128u, 192u), - MK_COL(192u, 128u, 64u), - MK_COL(192u, 128u, 128u), - MK_COL(64u, 0u, 0u), - MK_COL(64u, 0u, 192u), - MK_COL(64u, 0u, 64u), - MK_COL(64u, 0u, 128u), - MK_COL(64u, 192u, 0u), - MK_COL(64u, 192u, 192u), - MK_COL(64u, 192u, 64u), - MK_COL(64u, 192u, 128u), - MK_COL(64u, 64u, 0u), - MK_COL(64u, 64u, 192u), - MK_COL(64u, 64u, 64u), - MK_COL(64u, 64u, 128u), - MK_COL(64u, 128u, 0u), - MK_COL(64u, 128u, 192u), - MK_COL(64u, 128u, 64u), - MK_COL(64u, 128u, 128u), - MK_COL(128u, 0u, 0u), - MK_COL(128u, 0u, 192u), - MK_COL(128u, 0u, 64u), - MK_COL(128u, 0u, 128u), - MK_COL(128u, 192u, 0u), - MK_COL(128u, 192u, 192u), - MK_COL(128u, 192u, 64u), - MK_COL(128u, 192u, 128u), - MK_COL(128u, 64u, 0u), - MK_COL(128u, 64u, 192u), - MK_COL(128u, 64u, 64u), - MK_COL(128u, 64u, 128u), - MK_COL(128u, 128u, 0u), - MK_COL(128u, 128u, 192u), - MK_COL(128u, 128u, 64u), - MK_COL(128u, 128u, 128u), -}; - -#undef MK_COL - -//------------------------------------------------------------------------------ -// TODO(skal): move the functions to dsp/lossless.c when the correct -// granularity is found. For now, we'll just copy-paste some useful bits -// here instead. - -// In-place sum of each component with mod 256. -static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) { - const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u); - const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu); - *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); -} - -static WEBP_INLINE uint32_t Clip255(uint32_t a) { - if (a < 256) { - return a; - } - // return 0, when a is a negative integer. - // return 255, when a is positive. - return ~a >> 24; -} - -// Delta palettization functions. -static WEBP_INLINE int Square(int x) { - return x * x; -} - -static WEBP_INLINE uint32_t Intensity(uint32_t a) { - return - 30 * ((a >> 16) & 0xff) + - 59 * ((a >> 8) & 0xff) + - 11 * ((a >> 0) & 0xff); -} - -static uint32_t CalcDist(uint32_t predicted_value, uint32_t actual_value, - uint32_t palette_entry) { - int i; - uint32_t distance = 0; - AddPixelsEq(&predicted_value, palette_entry); - for (i = 0; i < 32; i += 8) { - const int32_t av = (actual_value >> i) & 0xff; - const int32_t pv = (predicted_value >> i) & 0xff; - distance += Square(pv - av); - } - // We sum square of intensity difference with factor 10, but because Intensity - // returns 100 times real intensity we need to multiply differences of colors - // by 1000. - distance *= 1000u; - distance += Square(Intensity(predicted_value) - - Intensity(actual_value)); - return distance; -} - -static uint32_t Predict(int x, int y, uint32_t* image) { - const uint32_t t = (y == 0) ? ARGB_BLACK : image[x]; - const uint32_t l = (x == 0) ? ARGB_BLACK : image[x - 1]; - const uint32_t p = - (((((t >> 24) & 0xff) + ((l >> 24) & 0xff)) / 2) << 24) + - (((((t >> 16) & 0xff) + ((l >> 16) & 0xff)) / 2) << 16) + - (((((t >> 8) & 0xff) + ((l >> 8) & 0xff)) / 2) << 8) + - (((((t >> 0) & 0xff) + ((l >> 0) & 0xff)) / 2) << 0); - if (x == 0 && y == 0) return ARGB_BLACK; - if (x == 0) return t; - if (y == 0) return l; - return p; -} - -static WEBP_INLINE int AddSubtractComponentFullWithCoefficient( - int a, int b, int c) { - return Clip255(a + ((b - c) >> 2)); -} - -static WEBP_INLINE uint32_t ClampedAddSubtractFullWithCoefficient( - uint32_t c0, uint32_t c1, uint32_t c2) { - const int a = AddSubtractComponentFullWithCoefficient( - c0 >> 24, c1 >> 24, c2 >> 24); - const int r = AddSubtractComponentFullWithCoefficient((c0 >> 16) & 0xff, - (c1 >> 16) & 0xff, - (c2 >> 16) & 0xff); - const int g = AddSubtractComponentFullWithCoefficient((c0 >> 8) & 0xff, - (c1 >> 8) & 0xff, - (c2 >> 8) & 0xff); - const int b = AddSubtractComponentFullWithCoefficient( - c0 & 0xff, c1 & 0xff, c2 & 0xff); - return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; -} - -//------------------------------------------------------------------------------ - -// Find palette entry with minimum error from difference of actual pixel value -// and predicted pixel value. Propagate error of pixel to its top and left pixel -// in src array. Write predicted_value + palette_entry to new_image. Return -// index of best palette entry. -static int FindBestPaletteEntry(uint32_t src, uint32_t predicted_value, - const uint32_t palette[], int palette_size) { - int i; - int idx = 0; - uint32_t best_distance = CalcDist(predicted_value, src, palette[0]); - for (i = 1; i < palette_size; ++i) { - const uint32_t distance = CalcDist(predicted_value, src, palette[i]); - if (distance < best_distance) { - best_distance = distance; - idx = i; - } - } - return idx; -} - -static void ApplyBestPaletteEntry(int x, int y, - uint32_t new_value, uint32_t palette_value, - uint32_t* src, int src_stride, - uint32_t* new_image) { - AddPixelsEq(&new_value, palette_value); - if (x > 0) { - src[x - 1] = ClampedAddSubtractFullWithCoefficient(src[x - 1], - new_value, src[x]); - } - if (y > 0) { - src[x - src_stride] = - ClampedAddSubtractFullWithCoefficient(src[x - src_stride], - new_value, src[x]); - } - new_image[x] = new_value; -} - -//------------------------------------------------------------------------------ -// Main entry point - -static WebPEncodingError ApplyDeltaPalette(uint32_t* src, uint32_t* dst, - uint32_t src_stride, - uint32_t dst_stride, - const uint32_t* palette, - int palette_size, - int width, int height, - int num_passes) { - int x, y; - WebPEncodingError err = VP8_ENC_OK; - uint32_t* new_image = (uint32_t*)WebPSafeMalloc(width, sizeof(*new_image)); - uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row)); - if (new_image == NULL || tmp_row == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - while (num_passes--) { - uint32_t* cur_src = src; - uint32_t* cur_dst = dst; - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - const uint32_t predicted_value = Predict(x, y, new_image); - tmp_row[x] = FindBestPaletteEntry(cur_src[x], predicted_value, - palette, palette_size); - ApplyBestPaletteEntry(x, y, predicted_value, palette[tmp_row[x]], - cur_src, src_stride, new_image); - } - for (x = 0; x < width; ++x) { - cur_dst[x] = palette[tmp_row[x]]; - } - cur_src += src_stride; - cur_dst += dst_stride; - } - } - Error: - WebPSafeFree(new_image); - WebPSafeFree(tmp_row); - return err; -} - -// replaces enc->argb_ by a palettizable approximation of it, -// and generates optimal enc->palette_[] -WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) { - const WebPPicture* const pic = enc->pic_; - uint32_t* src = pic->argb; - uint32_t* dst = enc->argb_; - const int width = pic->width; - const int height = pic->height; - - WebPEncodingError err = VP8_ENC_OK; - memcpy(enc->palette_, kDeltaPalette, sizeof(kDeltaPalette)); - enc->palette_[DELTA_PALETTE_SIZE - 1] = src[0] - 0xff000000u; - enc->palette_size_ = DELTA_PALETTE_SIZE; - err = ApplyDeltaPalette(src, dst, pic->argb_stride, enc->current_width_, - enc->palette_, enc->palette_size_, - width, height, 2); - if (err != VP8_ENC_OK) goto Error; - - Error: - return err; -} - -#else // !WEBP_EXPERIMENTAL_FEATURES - -WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) { - (void)enc; - return VP8_ENC_ERROR_INVALID_CONFIGURATION; -} - -#endif // WEBP_EXPERIMENTAL_FEATURES diff --git a/drivers/webp/enc/delta_palettization.h b/drivers/webp/enc/delta_palettization.h deleted file mode 100644 index 54195d452c..0000000000 --- a/drivers/webp/enc/delta_palettization.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Mislav Bradac (mislavm@google.com) -// - -#ifndef WEBP_ENC_DELTA_PALETTIZATION_H_ -#define WEBP_ENC_DELTA_PALETTIZATION_H_ - -#include "webp/encode.h" -#include "../enc/vp8li.h" - -// Replaces enc->argb_[] input by a palettizable approximation of it, -// and generates optimal enc->palette_[]. -// This function can revert enc->use_palette_ / enc->use_predict_ flag -// if delta-palettization is not producing expected saving. -WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc); - -#endif // WEBP_ENC_DELTA_PALETTIZATION_H_ diff --git a/drivers/webp/enc/frame.c b/drivers/webp/enc/frame.c deleted file mode 100644 index 65a98ada4d..0000000000 --- a/drivers/webp/enc/frame.c +++ /dev/null @@ -1,850 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// frame coding and analysis -// -// Author: Skal (pascal.massimino@gmail.com) - -#include <string.h> -#include <math.h> - -#include "./cost.h" -#include "./vp8enci.h" -#include "../dsp/dsp.h" -#include "webp/format_constants.h" // RIFF constants - -#define SEGMENT_VISU 0 -#define DEBUG_SEARCH 0 // useful to track search convergence - -//------------------------------------------------------------------------------ -// multi-pass convergence - -#define HEADER_SIZE_ESTIMATE (RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + \ - VP8_FRAME_HEADER_SIZE) -#define DQ_LIMIT 0.4 // convergence is considered reached if dq < DQ_LIMIT -// we allow 2k of extra head-room in PARTITION0 limit. -#define PARTITION0_SIZE_LIMIT ((VP8_MAX_PARTITION0_SIZE - 2048ULL) << 11) - -typedef struct { // struct for organizing convergence in either size or PSNR - int is_first; - float dq; - float q, last_q; - double value, last_value; // PSNR or size - double target; - int do_size_search; -} PassStats; - -static int InitPassStats(const VP8Encoder* const enc, PassStats* const s) { - const uint64_t target_size = (uint64_t)enc->config_->target_size; - const int do_size_search = (target_size != 0); - const float target_PSNR = enc->config_->target_PSNR; - - s->is_first = 1; - s->dq = 10.f; - s->q = s->last_q = enc->config_->quality; - s->target = do_size_search ? (double)target_size - : (target_PSNR > 0.) ? target_PSNR - : 40.; // default, just in case - s->value = s->last_value = 0.; - s->do_size_search = do_size_search; - return do_size_search; -} - -static float Clamp(float v, float min, float max) { - return (v < min) ? min : (v > max) ? max : v; -} - -static float ComputeNextQ(PassStats* const s) { - float dq; - if (s->is_first) { - dq = (s->value > s->target) ? -s->dq : s->dq; - s->is_first = 0; - } else if (s->value != s->last_value) { - const double slope = (s->target - s->value) / (s->last_value - s->value); - dq = (float)(slope * (s->last_q - s->q)); - } else { - dq = 0.; // we're done?! - } - // Limit variable to avoid large swings. - s->dq = Clamp(dq, -30.f, 30.f); - s->last_q = s->q; - s->last_value = s->value; - s->q = Clamp(s->q + s->dq, 0.f, 100.f); - return s->q; -} - -//------------------------------------------------------------------------------ -// Tables for level coding - -const uint8_t VP8Cat3[] = { 173, 148, 140 }; -const uint8_t VP8Cat4[] = { 176, 155, 140, 135 }; -const uint8_t VP8Cat5[] = { 180, 157, 141, 134, 130 }; -const uint8_t VP8Cat6[] = - { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 }; - -//------------------------------------------------------------------------------ -// Reset the statistics about: number of skips, token proba, level cost,... - -static void ResetStats(VP8Encoder* const enc) { - VP8EncProba* const proba = &enc->proba_; - VP8CalculateLevelCosts(proba); - proba->nb_skip_ = 0; -} - -//------------------------------------------------------------------------------ -// Skip decision probability - -#define SKIP_PROBA_THRESHOLD 250 // value below which using skip_proba is OK. - -static int CalcSkipProba(uint64_t nb, uint64_t total) { - return (int)(total ? (total - nb) * 255 / total : 255); -} - -// Returns the bit-cost for coding the skip probability. -static int FinalizeSkipProba(VP8Encoder* const enc) { - VP8EncProba* const proba = &enc->proba_; - const int nb_mbs = enc->mb_w_ * enc->mb_h_; - const int nb_events = proba->nb_skip_; - int size; - proba->skip_proba_ = CalcSkipProba(nb_events, nb_mbs); - proba->use_skip_proba_ = (proba->skip_proba_ < SKIP_PROBA_THRESHOLD); - size = 256; // 'use_skip_proba' bit - if (proba->use_skip_proba_) { - size += nb_events * VP8BitCost(1, proba->skip_proba_) - + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba_); - size += 8 * 256; // cost of signaling the skip_proba_ itself. - } - return size; -} - -// Collect statistics and deduce probabilities for next coding pass. -// Return the total bit-cost for coding the probability updates. -static int CalcTokenProba(int nb, int total) { - assert(nb <= total); - return nb ? (255 - nb * 255 / total) : 255; -} - -// Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability. -static int BranchCost(int nb, int total, int proba) { - return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba); -} - -static void ResetTokenStats(VP8Encoder* const enc) { - VP8EncProba* const proba = &enc->proba_; - memset(proba->stats_, 0, sizeof(proba->stats_)); -} - -static int FinalizeTokenProbas(VP8EncProba* const proba) { - int has_changed = 0; - int size = 0; - int t, b, c, p; - for (t = 0; t < NUM_TYPES; ++t) { - for (b = 0; b < NUM_BANDS; ++b) { - for (c = 0; c < NUM_CTX; ++c) { - for (p = 0; p < NUM_PROBAS; ++p) { - const proba_t stats = proba->stats_[t][b][c][p]; - const int nb = (stats >> 0) & 0xffff; - const int total = (stats >> 16) & 0xffff; - const int update_proba = VP8CoeffsUpdateProba[t][b][c][p]; - const int old_p = VP8CoeffsProba0[t][b][c][p]; - const int new_p = CalcTokenProba(nb, total); - const int old_cost = BranchCost(nb, total, old_p) - + VP8BitCost(0, update_proba); - const int new_cost = BranchCost(nb, total, new_p) - + VP8BitCost(1, update_proba) - + 8 * 256; - const int use_new_p = (old_cost > new_cost); - size += VP8BitCost(use_new_p, update_proba); - if (use_new_p) { // only use proba that seem meaningful enough. - proba->coeffs_[t][b][c][p] = new_p; - has_changed |= (new_p != old_p); - size += 8 * 256; - } else { - proba->coeffs_[t][b][c][p] = old_p; - } - } - } - } - } - proba->dirty_ = has_changed; - return size; -} - -//------------------------------------------------------------------------------ -// Finalize Segment probability based on the coding tree - -static int GetProba(int a, int b) { - const int total = a + b; - return (total == 0) ? 255 // that's the default probability. - : (255 * a + total / 2) / total; // rounded proba -} - -static void SetSegmentProbas(VP8Encoder* const enc) { - int p[NUM_MB_SEGMENTS] = { 0 }; - int n; - - for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { - const VP8MBInfo* const mb = &enc->mb_info_[n]; - p[mb->segment_]++; - } - if (enc->pic_->stats != NULL) { - for (n = 0; n < NUM_MB_SEGMENTS; ++n) { - enc->pic_->stats->segment_size[n] = p[n]; - } - } - if (enc->segment_hdr_.num_segments_ > 1) { - uint8_t* const probas = enc->proba_.segments_; - probas[0] = GetProba(p[0] + p[1], p[2] + p[3]); - probas[1] = GetProba(p[0], p[1]); - probas[2] = GetProba(p[2], p[3]); - - enc->segment_hdr_.update_map_ = - (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); - enc->segment_hdr_.size_ = - p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) + - p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) + - p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) + - p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2])); - } else { - enc->segment_hdr_.update_map_ = 0; - enc->segment_hdr_.size_ = 0; - } -} - -//------------------------------------------------------------------------------ -// Coefficient coding - -static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) { - int n = res->first; - // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 - const uint8_t* p = res->prob[n][ctx]; - if (!VP8PutBit(bw, res->last >= 0, p[0])) { - return 0; - } - - while (n < 16) { - const int c = res->coeffs[n++]; - const int sign = c < 0; - int v = sign ? -c : c; - if (!VP8PutBit(bw, v != 0, p[1])) { - p = res->prob[VP8EncBands[n]][0]; - continue; - } - if (!VP8PutBit(bw, v > 1, p[2])) { - p = res->prob[VP8EncBands[n]][1]; - } else { - if (!VP8PutBit(bw, v > 4, p[3])) { - if (VP8PutBit(bw, v != 2, p[4])) - VP8PutBit(bw, v == 4, p[5]); - } else if (!VP8PutBit(bw, v > 10, p[6])) { - if (!VP8PutBit(bw, v > 6, p[7])) { - VP8PutBit(bw, v == 6, 159); - } else { - VP8PutBit(bw, v >= 9, 165); - VP8PutBit(bw, !(v & 1), 145); - } - } else { - int mask; - const uint8_t* tab; - if (v < 3 + (8 << 1)) { // VP8Cat3 (3b) - VP8PutBit(bw, 0, p[8]); - VP8PutBit(bw, 0, p[9]); - v -= 3 + (8 << 0); - mask = 1 << 2; - tab = VP8Cat3; - } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b) - VP8PutBit(bw, 0, p[8]); - VP8PutBit(bw, 1, p[9]); - v -= 3 + (8 << 1); - mask = 1 << 3; - tab = VP8Cat4; - } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b) - VP8PutBit(bw, 1, p[8]); - VP8PutBit(bw, 0, p[10]); - v -= 3 + (8 << 2); - mask = 1 << 4; - tab = VP8Cat5; - } else { // VP8Cat6 (11b) - VP8PutBit(bw, 1, p[8]); - VP8PutBit(bw, 1, p[10]); - v -= 3 + (8 << 3); - mask = 1 << 10; - tab = VP8Cat6; - } - while (mask) { - VP8PutBit(bw, !!(v & mask), *tab++); - mask >>= 1; - } - } - p = res->prob[VP8EncBands[n]][2]; - } - VP8PutBitUniform(bw, sign); - if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) { - return 1; // EOB - } - } - return 1; -} - -static void CodeResiduals(VP8BitWriter* const bw, VP8EncIterator* const it, - const VP8ModeScore* const rd) { - int x, y, ch; - VP8Residual res; - uint64_t pos1, pos2, pos3; - const int i16 = (it->mb_->type_ == 1); - const int segment = it->mb_->segment_; - VP8Encoder* const enc = it->enc_; - - VP8IteratorNzToBytes(it); - - pos1 = VP8BitWriterPos(bw); - if (i16) { - VP8InitResidual(0, 1, enc, &res); - VP8SetResidualCoeffs(rd->y_dc_levels, &res); - it->top_nz_[8] = it->left_nz_[8] = - PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res); - VP8InitResidual(1, 0, enc, &res); - } else { - VP8InitResidual(0, 3, enc, &res); - } - - // luma-AC - for (y = 0; y < 4; ++y) { - for (x = 0; x < 4; ++x) { - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); - it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res); - } - } - pos2 = VP8BitWriterPos(bw); - - // U/V - VP8InitResidual(0, 2, enc, &res); - for (ch = 0; ch <= 2; ch += 2) { - for (y = 0; y < 2; ++y) { - for (x = 0; x < 2; ++x) { - const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; - VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); - it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = - PutCoeffs(bw, ctx, &res); - } - } - } - pos3 = VP8BitWriterPos(bw); - it->luma_bits_ = pos2 - pos1; - it->uv_bits_ = pos3 - pos2; - it->bit_count_[segment][i16] += it->luma_bits_; - it->bit_count_[segment][2] += it->uv_bits_; - VP8IteratorBytesToNz(it); -} - -// Same as CodeResiduals, but doesn't actually write anything. -// Instead, it just records the event distribution. -static void RecordResiduals(VP8EncIterator* const it, - const VP8ModeScore* const rd) { - int x, y, ch; - VP8Residual res; - VP8Encoder* const enc = it->enc_; - - VP8IteratorNzToBytes(it); - - if (it->mb_->type_ == 1) { // i16x16 - VP8InitResidual(0, 1, enc, &res); - VP8SetResidualCoeffs(rd->y_dc_levels, &res); - it->top_nz_[8] = it->left_nz_[8] = - VP8RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res); - VP8InitResidual(1, 0, enc, &res); - } else { - VP8InitResidual(0, 3, enc, &res); - } - - // luma-AC - for (y = 0; y < 4; ++y) { - for (x = 0; x < 4; ++x) { - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); - it->top_nz_[x] = it->left_nz_[y] = VP8RecordCoeffs(ctx, &res); - } - } - - // U/V - VP8InitResidual(0, 2, enc, &res); - for (ch = 0; ch <= 2; ch += 2) { - for (y = 0; y < 2; ++y) { - for (x = 0; x < 2; ++x) { - const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; - VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); - it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = - VP8RecordCoeffs(ctx, &res); - } - } - } - - VP8IteratorBytesToNz(it); -} - -//------------------------------------------------------------------------------ -// Token buffer - -#if !defined(DISABLE_TOKEN_BUFFER) - -static int RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd, - VP8TBuffer* const tokens) { - int x, y, ch; - VP8Residual res; - VP8Encoder* const enc = it->enc_; - - VP8IteratorNzToBytes(it); - if (it->mb_->type_ == 1) { // i16x16 - const int ctx = it->top_nz_[8] + it->left_nz_[8]; - VP8InitResidual(0, 1, enc, &res); - VP8SetResidualCoeffs(rd->y_dc_levels, &res); - it->top_nz_[8] = it->left_nz_[8] = - VP8RecordCoeffTokens(ctx, 1, - res.first, res.last, res.coeffs, tokens); - VP8RecordCoeffs(ctx, &res); - VP8InitResidual(1, 0, enc, &res); - } else { - VP8InitResidual(0, 3, enc, &res); - } - - // luma-AC - for (y = 0; y < 4; ++y) { - for (x = 0; x < 4; ++x) { - const int ctx = it->top_nz_[x] + it->left_nz_[y]; - VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); - it->top_nz_[x] = it->left_nz_[y] = - VP8RecordCoeffTokens(ctx, res.coeff_type, - res.first, res.last, res.coeffs, tokens); - VP8RecordCoeffs(ctx, &res); - } - } - - // U/V - VP8InitResidual(0, 2, enc, &res); - for (ch = 0; ch <= 2; ch += 2) { - for (y = 0; y < 2; ++y) { - for (x = 0; x < 2; ++x) { - const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; - VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); - it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = - VP8RecordCoeffTokens(ctx, 2, - res.first, res.last, res.coeffs, tokens); - VP8RecordCoeffs(ctx, &res); - } - } - } - VP8IteratorBytesToNz(it); - return !tokens->error_; -} - -#endif // !DISABLE_TOKEN_BUFFER - -//------------------------------------------------------------------------------ -// ExtraInfo map / Debug function - -#if SEGMENT_VISU -static void SetBlock(uint8_t* p, int value, int size) { - int y; - for (y = 0; y < size; ++y) { - memset(p, value, size); - p += BPS; - } -} -#endif - -static void ResetSSE(VP8Encoder* const enc) { - enc->sse_[0] = 0; - enc->sse_[1] = 0; - enc->sse_[2] = 0; - // Note: enc->sse_[3] is managed by alpha.c - enc->sse_count_ = 0; -} - -static void StoreSSE(const VP8EncIterator* const it) { - VP8Encoder* const enc = it->enc_; - const uint8_t* const in = it->yuv_in_; - const uint8_t* const out = it->yuv_out_; - // Note: not totally accurate at boundary. And doesn't include in-loop filter. - enc->sse_[0] += VP8SSE16x16(in + Y_OFF_ENC, out + Y_OFF_ENC); - enc->sse_[1] += VP8SSE8x8(in + U_OFF_ENC, out + U_OFF_ENC); - enc->sse_[2] += VP8SSE8x8(in + V_OFF_ENC, out + V_OFF_ENC); - enc->sse_count_ += 16 * 16; -} - -static void StoreSideInfo(const VP8EncIterator* const it) { - VP8Encoder* const enc = it->enc_; - const VP8MBInfo* const mb = it->mb_; - WebPPicture* const pic = enc->pic_; - - if (pic->stats != NULL) { - StoreSSE(it); - enc->block_count_[0] += (mb->type_ == 0); - enc->block_count_[1] += (mb->type_ == 1); - enc->block_count_[2] += (mb->skip_ != 0); - } - - if (pic->extra_info != NULL) { - uint8_t* const info = &pic->extra_info[it->x_ + it->y_ * enc->mb_w_]; - switch (pic->extra_info_type) { - case 1: *info = mb->type_; break; - case 2: *info = mb->segment_; break; - case 3: *info = enc->dqm_[mb->segment_].quant_; break; - case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break; - case 5: *info = mb->uv_mode_; break; - case 6: { - const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3); - *info = (b > 255) ? 255 : b; break; - } - case 7: *info = mb->alpha_; break; - default: *info = 0; break; - } - } -#if SEGMENT_VISU // visualize segments and prediction modes - SetBlock(it->yuv_out_ + Y_OFF_ENC, mb->segment_ * 64, 16); - SetBlock(it->yuv_out_ + U_OFF_ENC, it->preds_[0] * 64, 8); - SetBlock(it->yuv_out_ + V_OFF_ENC, mb->uv_mode_ * 64, 8); -#endif -} - -static double GetPSNR(uint64_t mse, uint64_t size) { - return (mse > 0 && size > 0) ? 10. * log10(255. * 255. * size / mse) : 99; -} - -//------------------------------------------------------------------------------ -// StatLoop(): only collect statistics (number of skips, token usage, ...). -// This is used for deciding optimal probabilities. It also modifies the -// quantizer value if some target (size, PSNR) was specified. - -static void SetLoopParams(VP8Encoder* const enc, float q) { - // Make sure the quality parameter is inside valid bounds - q = Clamp(q, 0.f, 100.f); - - VP8SetSegmentParams(enc, q); // setup segment quantizations and filters - SetSegmentProbas(enc); // compute segment probabilities - - ResetStats(enc); - ResetSSE(enc); -} - -static uint64_t OneStatPass(VP8Encoder* const enc, VP8RDLevel rd_opt, - int nb_mbs, int percent_delta, - PassStats* const s) { - VP8EncIterator it; - uint64_t size = 0; - uint64_t size_p0 = 0; - uint64_t distortion = 0; - const uint64_t pixel_count = nb_mbs * 384; - - VP8IteratorInit(enc, &it); - SetLoopParams(enc, s->q); - do { - VP8ModeScore info; - VP8IteratorImport(&it, NULL); - if (VP8Decimate(&it, &info, rd_opt)) { - // Just record the number of skips and act like skip_proba is not used. - enc->proba_.nb_skip_++; - } - RecordResiduals(&it, &info); - size += info.R + info.H; - size_p0 += info.H; - distortion += info.D; - if (percent_delta && !VP8IteratorProgress(&it, percent_delta)) - return 0; - VP8IteratorSaveBoundary(&it); - } while (VP8IteratorNext(&it) && --nb_mbs > 0); - - size_p0 += enc->segment_hdr_.size_; - if (s->do_size_search) { - size += FinalizeSkipProba(enc); - size += FinalizeTokenProbas(&enc->proba_); - size = ((size + size_p0 + 1024) >> 11) + HEADER_SIZE_ESTIMATE; - s->value = (double)size; - } else { - s->value = GetPSNR(distortion, pixel_count); - } - return size_p0; -} - -static int StatLoop(VP8Encoder* const enc) { - const int method = enc->method_; - const int do_search = enc->do_search_; - const int fast_probe = ((method == 0 || method == 3) && !do_search); - int num_pass_left = enc->config_->pass; - const int task_percent = 20; - const int percent_per_pass = - (task_percent + num_pass_left / 2) / num_pass_left; - const int final_percent = enc->percent_ + task_percent; - const VP8RDLevel rd_opt = - (method >= 3 || do_search) ? RD_OPT_BASIC : RD_OPT_NONE; - int nb_mbs = enc->mb_w_ * enc->mb_h_; - PassStats stats; - - InitPassStats(enc, &stats); - ResetTokenStats(enc); - - // Fast mode: quick analysis pass over few mbs. Better than nothing. - if (fast_probe) { - if (method == 3) { // we need more stats for method 3 to be reliable. - nb_mbs = (nb_mbs > 200) ? nb_mbs >> 1 : 100; - } else { - nb_mbs = (nb_mbs > 200) ? nb_mbs >> 2 : 50; - } - } - - while (num_pass_left-- > 0) { - const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || - (num_pass_left == 0) || - (enc->max_i4_header_bits_ == 0); - const uint64_t size_p0 = - OneStatPass(enc, rd_opt, nb_mbs, percent_per_pass, &stats); - if (size_p0 == 0) return 0; -#if (DEBUG_SEARCH > 0) - printf("#%d value:%.1lf -> %.1lf q:%.2f -> %.2f\n", - num_pass_left, stats.last_value, stats.value, stats.last_q, stats.q); -#endif - if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) { - ++num_pass_left; - enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... - continue; // ...and start over - } - if (is_last_pass) { - break; - } - // If no target size: just do several pass without changing 'q' - if (do_search) { - ComputeNextQ(&stats); - if (fabs(stats.dq) <= DQ_LIMIT) break; - } - } - if (!do_search || !stats.do_size_search) { - // Need to finalize probas now, since it wasn't done during the search. - FinalizeSkipProba(enc); - FinalizeTokenProbas(&enc->proba_); - } - VP8CalculateLevelCosts(&enc->proba_); // finalize costs - return WebPReportProgress(enc->pic_, final_percent, &enc->percent_); -} - -//------------------------------------------------------------------------------ -// Main loops -// - -static const int kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 }; - -static int PreLoopInitialize(VP8Encoder* const enc) { - int p; - int ok = 1; - const int average_bytes_per_MB = kAverageBytesPerMB[enc->base_quant_ >> 4]; - const int bytes_per_parts = - enc->mb_w_ * enc->mb_h_ * average_bytes_per_MB / enc->num_parts_; - // Initialize the bit-writers - for (p = 0; ok && p < enc->num_parts_; ++p) { - ok = VP8BitWriterInit(enc->parts_ + p, bytes_per_parts); - } - if (!ok) { - VP8EncFreeBitWriters(enc); // malloc error occurred - WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - return ok; -} - -static int PostLoopFinalize(VP8EncIterator* const it, int ok) { - VP8Encoder* const enc = it->enc_; - if (ok) { // Finalize the partitions, check for extra errors. - int p; - for (p = 0; p < enc->num_parts_; ++p) { - VP8BitWriterFinish(enc->parts_ + p); - ok &= !enc->parts_[p].error_; - } - } - - if (ok) { // All good. Finish up. - if (enc->pic_->stats != NULL) { // finalize byte counters... - int i, s; - for (i = 0; i <= 2; ++i) { - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - enc->residual_bytes_[i][s] = (int)((it->bit_count_[s][i] + 7) >> 3); - } - } - } - VP8AdjustFilterStrength(it); // ...and store filter stats. - } else { - // Something bad happened -> need to do some memory cleanup. - VP8EncFreeBitWriters(enc); - } - return ok; -} - -//------------------------------------------------------------------------------ -// VP8EncLoop(): does the final bitstream coding. - -static void ResetAfterSkip(VP8EncIterator* const it) { - if (it->mb_->type_ == 1) { - *it->nz_ = 0; // reset all predictors - it->left_nz_[8] = 0; - } else { - *it->nz_ &= (1 << 24); // preserve the dc_nz bit - } -} - -int VP8EncLoop(VP8Encoder* const enc) { - VP8EncIterator it; - int ok = PreLoopInitialize(enc); - if (!ok) return 0; - - StatLoop(enc); // stats-collection loop - - VP8IteratorInit(enc, &it); - VP8InitFilter(&it); - do { - VP8ModeScore info; - const int dont_use_skip = !enc->proba_.use_skip_proba_; - const VP8RDLevel rd_opt = enc->rd_opt_level_; - - VP8IteratorImport(&it, NULL); - // Warning! order is important: first call VP8Decimate() and - // *then* decide how to code the skip decision if there's one. - if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) { - CodeResiduals(it.bw_, &it, &info); - } else { // reset predictors after a skip - ResetAfterSkip(&it); - } - StoreSideInfo(&it); - VP8StoreFilterStats(&it); - VP8IteratorExport(&it); - ok = VP8IteratorProgress(&it, 20); - VP8IteratorSaveBoundary(&it); - } while (ok && VP8IteratorNext(&it)); - - return PostLoopFinalize(&it, ok); -} - -//------------------------------------------------------------------------------ -// Single pass using Token Buffer. - -#if !defined(DISABLE_TOKEN_BUFFER) - -#define MIN_COUNT 96 // minimum number of macroblocks before updating stats - -int VP8EncTokenLoop(VP8Encoder* const enc) { - // Roughly refresh the proba eight times per pass - int max_count = (enc->mb_w_ * enc->mb_h_) >> 3; - int num_pass_left = enc->config_->pass; - const int do_search = enc->do_search_; - VP8EncIterator it; - VP8EncProba* const proba = &enc->proba_; - const VP8RDLevel rd_opt = enc->rd_opt_level_; - const uint64_t pixel_count = enc->mb_w_ * enc->mb_h_ * 384; - PassStats stats; - int ok; - - InitPassStats(enc, &stats); - ok = PreLoopInitialize(enc); - if (!ok) return 0; - - if (max_count < MIN_COUNT) max_count = MIN_COUNT; - - assert(enc->num_parts_ == 1); - assert(enc->use_tokens_); - assert(proba->use_skip_proba_ == 0); - assert(rd_opt >= RD_OPT_BASIC); // otherwise, token-buffer won't be useful - assert(num_pass_left > 0); - - while (ok && num_pass_left-- > 0) { - const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || - (num_pass_left == 0) || - (enc->max_i4_header_bits_ == 0); - uint64_t size_p0 = 0; - uint64_t distortion = 0; - int cnt = max_count; - VP8IteratorInit(enc, &it); - SetLoopParams(enc, stats.q); - if (is_last_pass) { - ResetTokenStats(enc); - VP8InitFilter(&it); // don't collect stats until last pass (too costly) - } - VP8TBufferClear(&enc->tokens_); - do { - VP8ModeScore info; - VP8IteratorImport(&it, NULL); - if (--cnt < 0) { - FinalizeTokenProbas(proba); - VP8CalculateLevelCosts(proba); // refresh cost tables for rd-opt - cnt = max_count; - } - VP8Decimate(&it, &info, rd_opt); - ok = RecordTokens(&it, &info, &enc->tokens_); - if (!ok) { - WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); - break; - } - size_p0 += info.H; - distortion += info.D; - if (is_last_pass) { - StoreSideInfo(&it); - VP8StoreFilterStats(&it); - VP8IteratorExport(&it); - ok = VP8IteratorProgress(&it, 20); - } - VP8IteratorSaveBoundary(&it); - } while (ok && VP8IteratorNext(&it)); - if (!ok) break; - - size_p0 += enc->segment_hdr_.size_; - if (stats.do_size_search) { - uint64_t size = FinalizeTokenProbas(&enc->proba_); - size += VP8EstimateTokenSize(&enc->tokens_, - (const uint8_t*)proba->coeffs_); - size = (size + size_p0 + 1024) >> 11; // -> size in bytes - size += HEADER_SIZE_ESTIMATE; - stats.value = (double)size; - } else { // compute and store PSNR - stats.value = GetPSNR(distortion, pixel_count); - } - -#if (DEBUG_SEARCH > 0) - printf("#%2d metric:%.1lf -> %.1lf last_q=%.2lf q=%.2lf dq=%.2lf\n", - num_pass_left, stats.last_value, stats.value, - stats.last_q, stats.q, stats.dq); -#endif - if (size_p0 > PARTITION0_SIZE_LIMIT) { - ++num_pass_left; - enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... - continue; // ...and start over - } - if (is_last_pass) { - break; // done - } - if (do_search) { - ComputeNextQ(&stats); // Adjust q - } - } - if (ok) { - if (!stats.do_size_search) { - FinalizeTokenProbas(&enc->proba_); - } - ok = VP8EmitTokens(&enc->tokens_, enc->parts_ + 0, - (const uint8_t*)proba->coeffs_, 1); - } - ok = ok && WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); - return PostLoopFinalize(&it, ok); -} - -#else - -int VP8EncTokenLoop(VP8Encoder* const enc) { - (void)enc; - return 0; // we shouldn't be here. -} - -#endif // DISABLE_TOKEN_BUFFER - -//------------------------------------------------------------------------------ - diff --git a/drivers/webp/enc/histogram.c b/drivers/webp/enc/histogram.c deleted file mode 100644 index 61544f4ccd..0000000000 --- a/drivers/webp/enc/histogram.c +++ /dev/null @@ -1,937 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// -#ifdef HAVE_CONFIG_H -#include "webp/config.h" -#endif - -#include <math.h> - -#include "./backward_references.h" -#include "./histogram.h" -#include "../dsp/lossless.h" -#include "../utils/utils.h" - -#define MAX_COST 1.e38 - -// Number of partitions for the three dominant (literal, red and blue) symbol -// costs. -#define NUM_PARTITIONS 4 -// The size of the bin-hash corresponding to the three dominant costs. -#define BIN_SIZE (NUM_PARTITIONS * NUM_PARTITIONS * NUM_PARTITIONS) -// Maximum number of histograms allowed in greedy combining algorithm. -#define MAX_HISTO_GREEDY 100 - -static void HistogramClear(VP8LHistogram* const p) { - uint32_t* const literal = p->literal_; - const int cache_bits = p->palette_code_bits_; - const int histo_size = VP8LGetHistogramSize(cache_bits); - memset(p, 0, histo_size); - p->palette_code_bits_ = cache_bits; - p->literal_ = literal; -} - -// Swap two histogram pointers. -static void HistogramSwap(VP8LHistogram** const A, VP8LHistogram** const B) { - VP8LHistogram* const tmp = *A; - *A = *B; - *B = tmp; -} - -static void HistogramCopy(const VP8LHistogram* const src, - VP8LHistogram* const dst) { - uint32_t* const dst_literal = dst->literal_; - const int dst_cache_bits = dst->palette_code_bits_; - const int histo_size = VP8LGetHistogramSize(dst_cache_bits); - assert(src->palette_code_bits_ == dst_cache_bits); - memcpy(dst, src, histo_size); - dst->literal_ = dst_literal; -} - -int VP8LGetHistogramSize(int cache_bits) { - const int literal_size = VP8LHistogramNumCodes(cache_bits); - const size_t total_size = sizeof(VP8LHistogram) + sizeof(int) * literal_size; - assert(total_size <= (size_t)0x7fffffff); - return (int)total_size; -} - -void VP8LFreeHistogram(VP8LHistogram* const histo) { - WebPSafeFree(histo); -} - -void VP8LFreeHistogramSet(VP8LHistogramSet* const histo) { - WebPSafeFree(histo); -} - -void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs, - VP8LHistogram* const histo) { - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - while (VP8LRefsCursorOk(&c)) { - VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos); - VP8LRefsCursorNext(&c); - } -} - -void VP8LHistogramCreate(VP8LHistogram* const p, - const VP8LBackwardRefs* const refs, - int palette_code_bits) { - if (palette_code_bits >= 0) { - p->palette_code_bits_ = palette_code_bits; - } - HistogramClear(p); - VP8LHistogramStoreRefs(refs, p); -} - -void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits) { - p->palette_code_bits_ = palette_code_bits; - HistogramClear(p); -} - -VP8LHistogram* VP8LAllocateHistogram(int cache_bits) { - VP8LHistogram* histo = NULL; - const int total_size = VP8LGetHistogramSize(cache_bits); - uint8_t* const memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory)); - if (memory == NULL) return NULL; - histo = (VP8LHistogram*)memory; - // literal_ won't necessary be aligned. - histo->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram)); - VP8LHistogramInit(histo, cache_bits); - return histo; -} - -VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) { - int i; - VP8LHistogramSet* set; - const int histo_size = VP8LGetHistogramSize(cache_bits); - const size_t total_size = - sizeof(*set) + size * (sizeof(*set->histograms) + - histo_size + WEBP_ALIGN_CST); - uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory)); - if (memory == NULL) return NULL; - - set = (VP8LHistogramSet*)memory; - memory += sizeof(*set); - set->histograms = (VP8LHistogram**)memory; - memory += size * sizeof(*set->histograms); - set->max_size = size; - set->size = size; - for (i = 0; i < size; ++i) { - memory = (uint8_t*)WEBP_ALIGN(memory); - set->histograms[i] = (VP8LHistogram*)memory; - // literal_ won't necessary be aligned. - set->histograms[i]->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram)); - VP8LHistogramInit(set->histograms[i], cache_bits); - memory += histo_size; - } - return set; -} - -// ----------------------------------------------------------------------------- - -void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, - const PixOrCopy* const v) { - if (PixOrCopyIsLiteral(v)) { - ++histo->alpha_[PixOrCopyLiteral(v, 3)]; - ++histo->red_[PixOrCopyLiteral(v, 2)]; - ++histo->literal_[PixOrCopyLiteral(v, 1)]; - ++histo->blue_[PixOrCopyLiteral(v, 0)]; - } else if (PixOrCopyIsCacheIdx(v)) { - const int literal_ix = - NUM_LITERAL_CODES + NUM_LENGTH_CODES + PixOrCopyCacheIdx(v); - ++histo->literal_[literal_ix]; - } else { - int code, extra_bits; - VP8LPrefixEncodeBits(PixOrCopyLength(v), &code, &extra_bits); - ++histo->literal_[NUM_LITERAL_CODES + code]; - VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits); - ++histo->distance_[code]; - } -} - -// ----------------------------------------------------------------------------- -// Entropy-related functions. - -static WEBP_INLINE double BitsEntropyRefine(const VP8LBitEntropy* entropy) { - double mix; - if (entropy->nonzeros < 5) { - if (entropy->nonzeros <= 1) { - return 0; - } - // Two symbols, they will be 0 and 1 in a Huffman code. - // Let's mix in a bit of entropy to favor good clustering when - // distributions of these are combined. - if (entropy->nonzeros == 2) { - return 0.99 * entropy->sum + 0.01 * entropy->entropy; - } - // No matter what the entropy says, we cannot be better than min_limit - // with Huffman coding. I am mixing a bit of entropy into the - // min_limit since it produces much better (~0.5 %) compression results - // perhaps because of better entropy clustering. - if (entropy->nonzeros == 3) { - mix = 0.95; - } else { - mix = 0.7; // nonzeros == 4. - } - } else { - mix = 0.627; - } - - { - double min_limit = 2 * entropy->sum - entropy->max_val; - min_limit = mix * min_limit + (1.0 - mix) * entropy->entropy; - return (entropy->entropy < min_limit) ? min_limit : entropy->entropy; - } -} - -double VP8LBitsEntropy(const uint32_t* const array, int n, - uint32_t* const trivial_symbol) { - VP8LBitEntropy entropy; - VP8LBitsEntropyUnrefined(array, n, &entropy); - if (trivial_symbol != NULL) { - *trivial_symbol = - (entropy.nonzeros == 1) ? entropy.nonzero_code : VP8L_NON_TRIVIAL_SYM; - } - - return BitsEntropyRefine(&entropy); -} - -static double InitialHuffmanCost(void) { - // Small bias because Huffman code length is typically not stored in - // full length. - static const int kHuffmanCodeOfHuffmanCodeSize = CODE_LENGTH_CODES * 3; - static const double kSmallBias = 9.1; - return kHuffmanCodeOfHuffmanCodeSize - kSmallBias; -} - -// Finalize the Huffman cost based on streak numbers and length type (<3 or >=3) -static double FinalHuffmanCost(const VP8LStreaks* const stats) { - double retval = InitialHuffmanCost(); - retval += stats->counts[0] * 1.5625 + 0.234375 * stats->streaks[0][1]; - retval += stats->counts[1] * 2.578125 + 0.703125 * stats->streaks[1][1]; - retval += 1.796875 * stats->streaks[0][0]; - retval += 3.28125 * stats->streaks[1][0]; - return retval; -} - -// Get the symbol entropy for the distribution 'population'. -// Set 'trivial_sym', if there's only one symbol present in the distribution. -static double PopulationCost(const uint32_t* const population, int length, - uint32_t* const trivial_sym) { - VP8LBitEntropy bit_entropy; - VP8LStreaks stats; - VP8LGetEntropyUnrefined(population, length, &bit_entropy, &stats); - if (trivial_sym != NULL) { - *trivial_sym = (bit_entropy.nonzeros == 1) ? bit_entropy.nonzero_code - : VP8L_NON_TRIVIAL_SYM; - } - - return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats); -} - -static WEBP_INLINE double GetCombinedEntropy(const uint32_t* const X, - const uint32_t* const Y, - int length) { - VP8LBitEntropy bit_entropy; - VP8LStreaks stats; - VP8LGetCombinedEntropyUnrefined(X, Y, length, &bit_entropy, &stats); - - return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats); -} - -// Estimates the Entropy + Huffman + other block overhead size cost. -double VP8LHistogramEstimateBits(const VP8LHistogram* const p) { - return - PopulationCost( - p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_), NULL) - + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL) - + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL) - + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL) - + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL) - + VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES) - + VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES); -} - -// ----------------------------------------------------------------------------- -// Various histogram combine/cost-eval functions - -static int GetCombinedHistogramEntropy(const VP8LHistogram* const a, - const VP8LHistogram* const b, - double cost_threshold, - double* cost) { - const int palette_code_bits = a->palette_code_bits_; - assert(a->palette_code_bits_ == b->palette_code_bits_); - *cost += GetCombinedEntropy(a->literal_, b->literal_, - VP8LHistogramNumCodes(palette_code_bits)); - *cost += VP8LExtraCostCombined(a->literal_ + NUM_LITERAL_CODES, - b->literal_ + NUM_LITERAL_CODES, - NUM_LENGTH_CODES); - if (*cost > cost_threshold) return 0; - - *cost += GetCombinedEntropy(a->red_, b->red_, NUM_LITERAL_CODES); - if (*cost > cost_threshold) return 0; - - *cost += GetCombinedEntropy(a->blue_, b->blue_, NUM_LITERAL_CODES); - if (*cost > cost_threshold) return 0; - - *cost += GetCombinedEntropy(a->alpha_, b->alpha_, NUM_LITERAL_CODES); - if (*cost > cost_threshold) return 0; - - *cost += GetCombinedEntropy(a->distance_, b->distance_, NUM_DISTANCE_CODES); - *cost += - VP8LExtraCostCombined(a->distance_, b->distance_, NUM_DISTANCE_CODES); - if (*cost > cost_threshold) return 0; - - return 1; -} - -// Performs out = a + b, computing the cost C(a+b) - C(a) - C(b) while comparing -// to the threshold value 'cost_threshold'. The score returned is -// Score = C(a+b) - C(a) - C(b), where C(a) + C(b) is known and fixed. -// Since the previous score passed is 'cost_threshold', we only need to compare -// the partial cost against 'cost_threshold + C(a) + C(b)' to possibly bail-out -// early. -static double HistogramAddEval(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out, - double cost_threshold) { - double cost = 0; - const double sum_cost = a->bit_cost_ + b->bit_cost_; - cost_threshold += sum_cost; - - if (GetCombinedHistogramEntropy(a, b, cost_threshold, &cost)) { - VP8LHistogramAdd(a, b, out); - out->bit_cost_ = cost; - out->palette_code_bits_ = a->palette_code_bits_; - out->trivial_symbol_ = (a->trivial_symbol_ == b->trivial_symbol_) ? - a->trivial_symbol_ : VP8L_NON_TRIVIAL_SYM; - } - - return cost - sum_cost; -} - -// Same as HistogramAddEval(), except that the resulting histogram -// is not stored. Only the cost C(a+b) - C(a) is evaluated. We omit -// the term C(b) which is constant over all the evaluations. -static double HistogramAddThresh(const VP8LHistogram* const a, - const VP8LHistogram* const b, - double cost_threshold) { - double cost = -a->bit_cost_; - GetCombinedHistogramEntropy(a, b, cost_threshold, &cost); - return cost; -} - -// ----------------------------------------------------------------------------- - -// The structure to keep track of cost range for the three dominant entropy -// symbols. -// TODO(skal): Evaluate if float can be used here instead of double for -// representing the entropy costs. -typedef struct { - double literal_max_; - double literal_min_; - double red_max_; - double red_min_; - double blue_max_; - double blue_min_; -} DominantCostRange; - -static void DominantCostRangeInit(DominantCostRange* const c) { - c->literal_max_ = 0.; - c->literal_min_ = MAX_COST; - c->red_max_ = 0.; - c->red_min_ = MAX_COST; - c->blue_max_ = 0.; - c->blue_min_ = MAX_COST; -} - -static void UpdateDominantCostRange( - const VP8LHistogram* const h, DominantCostRange* const c) { - if (c->literal_max_ < h->literal_cost_) c->literal_max_ = h->literal_cost_; - if (c->literal_min_ > h->literal_cost_) c->literal_min_ = h->literal_cost_; - if (c->red_max_ < h->red_cost_) c->red_max_ = h->red_cost_; - if (c->red_min_ > h->red_cost_) c->red_min_ = h->red_cost_; - if (c->blue_max_ < h->blue_cost_) c->blue_max_ = h->blue_cost_; - if (c->blue_min_ > h->blue_cost_) c->blue_min_ = h->blue_cost_; -} - -static void UpdateHistogramCost(VP8LHistogram* const h) { - uint32_t alpha_sym, red_sym, blue_sym; - const double alpha_cost = - PopulationCost(h->alpha_, NUM_LITERAL_CODES, &alpha_sym); - const double distance_cost = - PopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL) + - VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES); - const int num_codes = VP8LHistogramNumCodes(h->palette_code_bits_); - h->literal_cost_ = PopulationCost(h->literal_, num_codes, NULL) + - VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES, - NUM_LENGTH_CODES); - h->red_cost_ = PopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym); - h->blue_cost_ = PopulationCost(h->blue_, NUM_LITERAL_CODES, &blue_sym); - h->bit_cost_ = h->literal_cost_ + h->red_cost_ + h->blue_cost_ + - alpha_cost + distance_cost; - if ((alpha_sym | red_sym | blue_sym) == VP8L_NON_TRIVIAL_SYM) { - h->trivial_symbol_ = VP8L_NON_TRIVIAL_SYM; - } else { - h->trivial_symbol_ = - ((uint32_t)alpha_sym << 24) | (red_sym << 16) | (blue_sym << 0); - } -} - -static int GetBinIdForEntropy(double min, double max, double val) { - const double range = max - min; - if (range > 0.) { - const double delta = val - min; - return (int)((NUM_PARTITIONS - 1e-6) * delta / range); - } else { - return 0; - } -} - -static int GetHistoBinIndex(const VP8LHistogram* const h, - const DominantCostRange* const c, int low_effort) { - int bin_id = GetBinIdForEntropy(c->literal_min_, c->literal_max_, - h->literal_cost_); - assert(bin_id < NUM_PARTITIONS); - if (!low_effort) { - bin_id = bin_id * NUM_PARTITIONS - + GetBinIdForEntropy(c->red_min_, c->red_max_, h->red_cost_); - bin_id = bin_id * NUM_PARTITIONS - + GetBinIdForEntropy(c->blue_min_, c->blue_max_, h->blue_cost_); - assert(bin_id < BIN_SIZE); - } - return bin_id; -} - -// Construct the histograms from backward references. -static void HistogramBuild( - int xsize, int histo_bits, const VP8LBackwardRefs* const backward_refs, - VP8LHistogramSet* const image_histo) { - int x = 0, y = 0; - const int histo_xsize = VP8LSubSampleSize(xsize, histo_bits); - VP8LHistogram** const histograms = image_histo->histograms; - VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs); - assert(histo_bits > 0); - while (VP8LRefsCursorOk(&c)) { - const PixOrCopy* const v = c.cur_pos; - const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits); - VP8LHistogramAddSinglePixOrCopy(histograms[ix], v); - x += PixOrCopyLength(v); - while (x >= xsize) { - x -= xsize; - ++y; - } - VP8LRefsCursorNext(&c); - } -} - -// Copies the histograms and computes its bit_cost. -static void HistogramCopyAndAnalyze( - VP8LHistogramSet* const orig_histo, VP8LHistogramSet* const image_histo) { - int i; - const int histo_size = orig_histo->size; - VP8LHistogram** const orig_histograms = orig_histo->histograms; - VP8LHistogram** const histograms = image_histo->histograms; - for (i = 0; i < histo_size; ++i) { - VP8LHistogram* const histo = orig_histograms[i]; - UpdateHistogramCost(histo); - // Copy histograms from orig_histo[] to image_histo[]. - HistogramCopy(histo, histograms[i]); - } -} - -// Partition histograms to different entropy bins for three dominant (literal, -// red and blue) symbol costs and compute the histogram aggregate bit_cost. -static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo, - int16_t* const bin_map, int low_effort) { - int i; - VP8LHistogram** const histograms = image_histo->histograms; - const int histo_size = image_histo->size; - const int bin_depth = histo_size + 1; - DominantCostRange cost_range; - DominantCostRangeInit(&cost_range); - - // Analyze the dominant (literal, red and blue) entropy costs. - for (i = 0; i < histo_size; ++i) { - VP8LHistogram* const histo = histograms[i]; - UpdateDominantCostRange(histo, &cost_range); - } - - // bin-hash histograms on three of the dominant (literal, red and blue) - // symbol costs. - for (i = 0; i < histo_size; ++i) { - const VP8LHistogram* const histo = histograms[i]; - const int bin_id = GetHistoBinIndex(histo, &cost_range, low_effort); - const int bin_offset = bin_id * bin_depth; - // bin_map[n][0] for every bin 'n' maintains the counter for the number of - // histograms in that bin. - // Get and increment the num_histos in that bin. - const int num_histos = ++bin_map[bin_offset]; - assert(bin_offset + num_histos < bin_depth * BIN_SIZE); - // Add histogram i'th index at num_histos (last) position in the bin_map. - bin_map[bin_offset + num_histos] = i; - } -} - -// Compact the histogram set by removing unused entries. -static void HistogramCompactBins(VP8LHistogramSet* const image_histo) { - VP8LHistogram** const histograms = image_histo->histograms; - int i, j; - - for (i = 0, j = 0; i < image_histo->size; ++i) { - if (histograms[i] != NULL && histograms[i]->bit_cost_ != 0.) { - if (j < i) { - histograms[j] = histograms[i]; - histograms[i] = NULL; - } - ++j; - } - } - image_histo->size = j; -} - -static VP8LHistogram* HistogramCombineEntropyBin( - VP8LHistogramSet* const image_histo, - VP8LHistogram* cur_combo, - int16_t* const bin_map, int bin_depth, int num_bins, - double combine_cost_factor, int low_effort) { - int bin_id; - VP8LHistogram** const histograms = image_histo->histograms; - - for (bin_id = 0; bin_id < num_bins; ++bin_id) { - const int bin_offset = bin_id * bin_depth; - const int num_histos = bin_map[bin_offset]; - const int idx1 = bin_map[bin_offset + 1]; - int num_combine_failures = 0; - int n; - for (n = 2; n <= num_histos; ++n) { - const int idx2 = bin_map[bin_offset + n]; - if (low_effort) { - // Merge all histograms with the same bin index, irrespective of cost of - // the merged histograms. - VP8LHistogramAdd(histograms[idx1], histograms[idx2], histograms[idx1]); - histograms[idx2]->bit_cost_ = 0.; - } else { - const double bit_cost_idx2 = histograms[idx2]->bit_cost_; - if (bit_cost_idx2 > 0.) { - const double bit_cost_thresh = -bit_cost_idx2 * combine_cost_factor; - const double curr_cost_diff = - HistogramAddEval(histograms[idx1], histograms[idx2], - cur_combo, bit_cost_thresh); - if (curr_cost_diff < bit_cost_thresh) { - // Try to merge two histograms only if the combo is a trivial one or - // the two candidate histograms are already non-trivial. - // For some images, 'try_combine' turns out to be false for a lot of - // histogram pairs. In that case, we fallback to combining - // histograms as usual to avoid increasing the header size. - const int try_combine = - (cur_combo->trivial_symbol_ != VP8L_NON_TRIVIAL_SYM) || - ((histograms[idx1]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM) && - (histograms[idx2]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM)); - const int max_combine_failures = 32; - if (try_combine || (num_combine_failures >= max_combine_failures)) { - HistogramSwap(&cur_combo, &histograms[idx1]); - histograms[idx2]->bit_cost_ = 0.; - } else { - ++num_combine_failures; - } - } - } - } - } - if (low_effort) { - // Update the bit_cost for the merged histograms (per bin index). - UpdateHistogramCost(histograms[idx1]); - } - } - HistogramCompactBins(image_histo); - return cur_combo; -} - -static uint32_t MyRand(uint32_t *seed) { - *seed *= 16807U; - if (*seed == 0) { - *seed = 1; - } - return *seed; -} - -// ----------------------------------------------------------------------------- -// Histogram pairs priority queue - -// Pair of histograms. Negative idx1 value means that pair is out-of-date. -typedef struct { - int idx1; - int idx2; - double cost_diff; - double cost_combo; -} HistogramPair; - -typedef struct { - HistogramPair* queue; - int size; - int max_size; -} HistoQueue; - -static int HistoQueueInit(HistoQueue* const histo_queue, const int max_index) { - histo_queue->size = 0; - // max_index^2 for the queue size is safe. If you look at - // HistogramCombineGreedy, and imagine that UpdateQueueFront always pushes - // data to the queue, you insert at most: - // - max_index*(max_index-1)/2 (the first two for loops) - // - max_index - 1 in the last for loop at the first iteration of the while - // loop, max_index - 2 at the second iteration ... therefore - // max_index*(max_index-1)/2 overall too - histo_queue->max_size = max_index * max_index; - // We allocate max_size + 1 because the last element at index "size" is - // used as temporary data (and it could be up to max_size). - histo_queue->queue = WebPSafeMalloc(histo_queue->max_size + 1, - sizeof(*histo_queue->queue)); - return histo_queue->queue != NULL; -} - -static void HistoQueueClear(HistoQueue* const histo_queue) { - assert(histo_queue != NULL); - WebPSafeFree(histo_queue->queue); -} - -static void SwapHistogramPairs(HistogramPair *p1, - HistogramPair *p2) { - const HistogramPair tmp = *p1; - *p1 = *p2; - *p2 = tmp; -} - -// Given a valid priority queue in range [0, queue_size) this function checks -// whether histo_queue[queue_size] should be accepted and swaps it with the -// front if it is smaller. Otherwise, it leaves it as is. -static void UpdateQueueFront(HistoQueue* const histo_queue) { - if (histo_queue->queue[histo_queue->size].cost_diff >= 0) return; - - if (histo_queue->queue[histo_queue->size].cost_diff < - histo_queue->queue[0].cost_diff) { - SwapHistogramPairs(histo_queue->queue, - histo_queue->queue + histo_queue->size); - } - ++histo_queue->size; - - // We cannot add more elements than the capacity. - // The allocation adds an extra element to the official capacity so that - // histo_queue->queue[histo_queue->max_size] is read/written within bound. - assert(histo_queue->size <= histo_queue->max_size); -} - -// ----------------------------------------------------------------------------- - -static void PreparePair(VP8LHistogram** histograms, int idx1, int idx2, - HistogramPair* const pair) { - VP8LHistogram* h1; - VP8LHistogram* h2; - double sum_cost; - - if (idx1 > idx2) { - const int tmp = idx2; - idx2 = idx1; - idx1 = tmp; - } - pair->idx1 = idx1; - pair->idx2 = idx2; - h1 = histograms[idx1]; - h2 = histograms[idx2]; - sum_cost = h1->bit_cost_ + h2->bit_cost_; - pair->cost_combo = 0.; - GetCombinedHistogramEntropy(h1, h2, sum_cost, &pair->cost_combo); - pair->cost_diff = pair->cost_combo - sum_cost; -} - -// Combines histograms by continuously choosing the one with the highest cost -// reduction. -static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo) { - int ok = 0; - int image_histo_size = image_histo->size; - int i, j; - VP8LHistogram** const histograms = image_histo->histograms; - // Indexes of remaining histograms. - int* const clusters = WebPSafeMalloc(image_histo_size, sizeof(*clusters)); - // Priority queue of histogram pairs. - HistoQueue histo_queue; - - if (!HistoQueueInit(&histo_queue, image_histo_size) || clusters == NULL) { - goto End; - } - - for (i = 0; i < image_histo_size; ++i) { - // Initialize clusters indexes. - clusters[i] = i; - for (j = i + 1; j < image_histo_size; ++j) { - // Initialize positions array. - PreparePair(histograms, i, j, &histo_queue.queue[histo_queue.size]); - UpdateQueueFront(&histo_queue); - } - } - - while (image_histo_size > 1 && histo_queue.size > 0) { - HistogramPair* copy_to; - const int idx1 = histo_queue.queue[0].idx1; - const int idx2 = histo_queue.queue[0].idx2; - VP8LHistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]); - histograms[idx1]->bit_cost_ = histo_queue.queue[0].cost_combo; - // Remove merged histogram. - for (i = 0; i + 1 < image_histo_size; ++i) { - if (clusters[i] >= idx2) { - clusters[i] = clusters[i + 1]; - } - } - --image_histo_size; - - // Remove pairs intersecting the just combined best pair. This will - // therefore pop the head of the queue. - copy_to = histo_queue.queue; - for (i = 0; i < histo_queue.size; ++i) { - HistogramPair* const p = histo_queue.queue + i; - if (p->idx1 == idx1 || p->idx2 == idx1 || - p->idx1 == idx2 || p->idx2 == idx2) { - // Do not copy the invalid pair. - continue; - } - if (p->cost_diff < histo_queue.queue[0].cost_diff) { - // Replace the top of the queue if we found better. - SwapHistogramPairs(histo_queue.queue, p); - } - SwapHistogramPairs(copy_to, p); - ++copy_to; - } - histo_queue.size = (int)(copy_to - histo_queue.queue); - - // Push new pairs formed with combined histogram to the queue. - for (i = 0; i < image_histo_size; ++i) { - if (clusters[i] != idx1) { - PreparePair(histograms, idx1, clusters[i], - &histo_queue.queue[histo_queue.size]); - UpdateQueueFront(&histo_queue); - } - } - } - // Move remaining histograms to the beginning of the array. - for (i = 0; i < image_histo_size; ++i) { - if (i != clusters[i]) { // swap the two histograms - HistogramSwap(&histograms[i], &histograms[clusters[i]]); - } - } - - image_histo->size = image_histo_size; - ok = 1; - - End: - WebPSafeFree(clusters); - HistoQueueClear(&histo_queue); - return ok; -} - -static void HistogramCombineStochastic(VP8LHistogramSet* const image_histo, - VP8LHistogram* tmp_histo, - VP8LHistogram* best_combo, - int quality, int min_cluster_size) { - int iter; - uint32_t seed = 0; - int tries_with_no_success = 0; - int image_histo_size = image_histo->size; - const int iter_mult = (quality < 25) ? 2 : 2 + (quality - 25) / 8; - const int outer_iters = image_histo_size * iter_mult; - const int num_pairs = image_histo_size / 2; - const int num_tries_no_success = outer_iters / 2; - VP8LHistogram** const histograms = image_histo->histograms; - - // Collapse similar histograms in 'image_histo'. - ++min_cluster_size; - for (iter = 0; - iter < outer_iters && image_histo_size >= min_cluster_size; - ++iter) { - double best_cost_diff = 0.; - int best_idx1 = -1, best_idx2 = 1; - int j; - const int num_tries = - (num_pairs < image_histo_size) ? num_pairs : image_histo_size; - seed += iter; - for (j = 0; j < num_tries; ++j) { - double curr_cost_diff; - // Choose two histograms at random and try to combine them. - const uint32_t idx1 = MyRand(&seed) % image_histo_size; - const uint32_t tmp = (j & 7) + 1; - const uint32_t diff = - (tmp < 3) ? tmp : MyRand(&seed) % (image_histo_size - 1); - const uint32_t idx2 = (idx1 + diff + 1) % image_histo_size; - if (idx1 == idx2) { - continue; - } - - // Calculate cost reduction on combining. - curr_cost_diff = HistogramAddEval(histograms[idx1], histograms[idx2], - tmp_histo, best_cost_diff); - if (curr_cost_diff < best_cost_diff) { // found a better pair? - HistogramSwap(&best_combo, &tmp_histo); - best_cost_diff = curr_cost_diff; - best_idx1 = idx1; - best_idx2 = idx2; - } - } - - if (best_idx1 >= 0) { - HistogramSwap(&best_combo, &histograms[best_idx1]); - // swap best_idx2 slot with last one (which is now unused) - --image_histo_size; - if (best_idx2 != image_histo_size) { - HistogramSwap(&histograms[image_histo_size], &histograms[best_idx2]); - histograms[image_histo_size] = NULL; - } - tries_with_no_success = 0; - } - if (++tries_with_no_success >= num_tries_no_success) { - break; - } - } - image_histo->size = image_histo_size; -} - -// ----------------------------------------------------------------------------- -// Histogram refinement - -// Find the best 'out' histogram for each of the 'in' histograms. -// Note: we assume that out[]->bit_cost_ is already up-to-date. -static void HistogramRemap(const VP8LHistogramSet* const in, - const VP8LHistogramSet* const out, - uint16_t* const symbols) { - int i; - VP8LHistogram** const in_histo = in->histograms; - VP8LHistogram** const out_histo = out->histograms; - const int in_size = in->size; - const int out_size = out->size; - if (out_size > 1) { - for (i = 0; i < in_size; ++i) { - int best_out = 0; - double best_bits = MAX_COST; - int k; - for (k = 0; k < out_size; ++k) { - const double cur_bits = - HistogramAddThresh(out_histo[k], in_histo[i], best_bits); - if (k == 0 || cur_bits < best_bits) { - best_bits = cur_bits; - best_out = k; - } - } - symbols[i] = best_out; - } - } else { - assert(out_size == 1); - for (i = 0; i < in_size; ++i) { - symbols[i] = 0; - } - } - - // Recompute each out based on raw and symbols. - for (i = 0; i < out_size; ++i) { - HistogramClear(out_histo[i]); - } - - for (i = 0; i < in_size; ++i) { - const int idx = symbols[i]; - VP8LHistogramAdd(in_histo[i], out_histo[idx], out_histo[idx]); - } -} - -static double GetCombineCostFactor(int histo_size, int quality) { - double combine_cost_factor = 0.16; - if (quality < 90) { - if (histo_size > 256) combine_cost_factor /= 2.; - if (histo_size > 512) combine_cost_factor /= 2.; - if (histo_size > 1024) combine_cost_factor /= 2.; - if (quality <= 50) combine_cost_factor /= 2.; - } - return combine_cost_factor; -} - -int VP8LGetHistoImageSymbols(int xsize, int ysize, - const VP8LBackwardRefs* const refs, - int quality, int low_effort, - int histo_bits, int cache_bits, - VP8LHistogramSet* const image_histo, - VP8LHistogramSet* const tmp_histos, - uint16_t* const histogram_symbols) { - int ok = 0; - const int histo_xsize = histo_bits ? VP8LSubSampleSize(xsize, histo_bits) : 1; - const int histo_ysize = histo_bits ? VP8LSubSampleSize(ysize, histo_bits) : 1; - const int image_histo_raw_size = histo_xsize * histo_ysize; - const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE; - - // The bin_map for every bin follows following semantics: - // bin_map[n][0] = num_histo; // The number of histograms in that bin. - // bin_map[n][1] = index of first histogram in that bin; - // bin_map[n][num_histo] = index of last histogram in that bin; - // bin_map[n][num_histo + 1] ... bin_map[n][bin_depth - 1] = unused indices. - const int bin_depth = image_histo_raw_size + 1; - int16_t* bin_map = NULL; - VP8LHistogramSet* const orig_histo = - VP8LAllocateHistogramSet(image_histo_raw_size, cache_bits); - VP8LHistogram* cur_combo; - const int entropy_combine = - (orig_histo->size > entropy_combine_num_bins * 2) && (quality < 100); - - if (orig_histo == NULL) goto Error; - - // Don't attempt linear bin-partition heuristic for: - // histograms of small sizes, as bin_map will be very sparse and; - // Maximum quality (q==100), to preserve the compression gains at that level. - if (entropy_combine) { - const int bin_map_size = bin_depth * entropy_combine_num_bins; - bin_map = (int16_t*)WebPSafeCalloc(bin_map_size, sizeof(*bin_map)); - if (bin_map == NULL) goto Error; - } - - // Construct the histograms from backward references. - HistogramBuild(xsize, histo_bits, refs, orig_histo); - // Copies the histograms and computes its bit_cost. - HistogramCopyAndAnalyze(orig_histo, image_histo); - - cur_combo = tmp_histos->histograms[1]; // pick up working slot - if (entropy_combine) { - const double combine_cost_factor = - GetCombineCostFactor(image_histo_raw_size, quality); - HistogramAnalyzeEntropyBin(orig_histo, bin_map, low_effort); - // Collapse histograms with similar entropy. - cur_combo = HistogramCombineEntropyBin(image_histo, cur_combo, bin_map, - bin_depth, entropy_combine_num_bins, - combine_cost_factor, low_effort); - } - - // Don't combine the histograms using stochastic and greedy heuristics for - // low-effort compression mode. - if (!low_effort || !entropy_combine) { - const float x = quality / 100.f; - // cubic ramp between 1 and MAX_HISTO_GREEDY: - const int threshold_size = (int)(1 + (x * x * x) * (MAX_HISTO_GREEDY - 1)); - HistogramCombineStochastic(image_histo, tmp_histos->histograms[0], - cur_combo, quality, threshold_size); - if ((image_histo->size <= threshold_size) && - !HistogramCombineGreedy(image_histo)) { - goto Error; - } - } - - // TODO(vikasa): Optimize HistogramRemap for low-effort compression mode also. - // Find the optimal map from original histograms to the final ones. - HistogramRemap(orig_histo, image_histo, histogram_symbols); - - ok = 1; - - Error: - WebPSafeFree(bin_map); - VP8LFreeHistogramSet(orig_histo); - return ok; -} diff --git a/drivers/webp/enc/histogram.h b/drivers/webp/enc/histogram.h deleted file mode 100644 index 59de42b33e..0000000000 --- a/drivers/webp/enc/histogram.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// -// Models the histograms of literal and distance codes. - -#ifndef WEBP_ENC_HISTOGRAM_H_ -#define WEBP_ENC_HISTOGRAM_H_ - -#include <string.h> - -#include "./backward_references.h" -#include "webp/format_constants.h" -#include "webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Not a trivial literal symbol. -#define VP8L_NON_TRIVIAL_SYM (0xffffffff) - -// A simple container for histograms of data. -typedef struct { - // literal_ contains green literal, palette-code and - // copy-length-prefix histogram - uint32_t* literal_; // Pointer to the allocated buffer for literal. - uint32_t red_[NUM_LITERAL_CODES]; - uint32_t blue_[NUM_LITERAL_CODES]; - uint32_t alpha_[NUM_LITERAL_CODES]; - // Backward reference prefix-code histogram. - uint32_t distance_[NUM_DISTANCE_CODES]; - int palette_code_bits_; - uint32_t trivial_symbol_; // True, if histograms for Red, Blue & Alpha - // literal symbols are single valued. - double bit_cost_; // cached value of bit cost. - double literal_cost_; // Cached values of dominant entropy costs: - double red_cost_; // literal, red & blue. - double blue_cost_; -} VP8LHistogram; - -// Collection of histograms with fixed capacity, allocated as one -// big memory chunk. Can be destroyed by calling WebPSafeFree(). -typedef struct { - int size; // number of slots currently in use - int max_size; // maximum capacity - VP8LHistogram** histograms; -} VP8LHistogramSet; - -// Create the histogram. -// -// The input data is the PixOrCopy data, which models the literals, stop -// codes and backward references (both distances and lengths). Also: if -// palette_code_bits is >= 0, initialize the histogram with this value. -void VP8LHistogramCreate(VP8LHistogram* const p, - const VP8LBackwardRefs* const refs, - int palette_code_bits); - -// Return the size of the histogram for a given palette_code_bits. -int VP8LGetHistogramSize(int palette_code_bits); - -// Set the palette_code_bits and reset the stats. -void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits); - -// Collect all the references into a histogram (without reset) -void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs, - VP8LHistogram* const histo); - -// Free the memory allocated for the histogram. -void VP8LFreeHistogram(VP8LHistogram* const histo); - -// Free the memory allocated for the histogram set. -void VP8LFreeHistogramSet(VP8LHistogramSet* const histo); - -// Allocate an array of pointer to histograms, allocated and initialized -// using 'cache_bits'. Return NULL in case of memory error. -VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits); - -// Allocate and initialize histogram object with specified 'cache_bits'. -// Returns NULL in case of memory error. -// Special case of VP8LAllocateHistogramSet, with size equals 1. -VP8LHistogram* VP8LAllocateHistogram(int cache_bits); - -// Accumulate a token 'v' into a histogram. -void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, - const PixOrCopy* const v); - -static WEBP_INLINE int VP8LHistogramNumCodes(int palette_code_bits) { - return NUM_LITERAL_CODES + NUM_LENGTH_CODES + - ((palette_code_bits > 0) ? (1 << palette_code_bits) : 0); -} - -// Builds the histogram image. -int VP8LGetHistoImageSymbols(int xsize, int ysize, - const VP8LBackwardRefs* const refs, - int quality, int low_effort, - int histogram_bits, int cache_bits, - VP8LHistogramSet* const image_in, - VP8LHistogramSet* const tmp_histos, - uint16_t* const histogram_symbols); - -// Returns the entropy for the symbols in the input array. -// Also sets trivial_symbol to the code value, if the array has only one code -// value. Otherwise, set it to VP8L_NON_TRIVIAL_SYM. -double VP8LBitsEntropy(const uint32_t* const array, int n, - uint32_t* const trivial_symbol); - -// Estimate how many bits the combined entropy of literals and distance -// approximately maps to. -double VP8LHistogramEstimateBits(const VP8LHistogram* const p); - -#ifdef __cplusplus -} -#endif - -#endif // WEBP_ENC_HISTOGRAM_H_ diff --git a/drivers/webp/enc/syntax.c b/drivers/webp/enc/syntax.c deleted file mode 100644 index 2b65f15ca1..0000000000 --- a/drivers/webp/enc/syntax.c +++ /dev/null @@ -1,383 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Header syntax writing -// -// Author: Skal (pascal.massimino@gmail.com) - -#include <assert.h> - -#include "../utils/utils.h" -#include "webp/format_constants.h" // RIFF constants -#include "webp/mux_types.h" // ALPHA_FLAG -#include "./vp8enci.h" - -//------------------------------------------------------------------------------ -// Helper functions - -static int IsVP8XNeeded(const VP8Encoder* const enc) { - return !!enc->has_alpha_; // Currently the only case when VP8X is needed. - // This could change in the future. -} - -static int PutPaddingByte(const WebPPicture* const pic) { - const uint8_t pad_byte[1] = { 0 }; - return !!pic->writer(pad_byte, 1, pic); -} - -//------------------------------------------------------------------------------ -// Writers for header's various pieces (in order of appearance) - -static WebPEncodingError PutRIFFHeader(const VP8Encoder* const enc, - size_t riff_size) { - const WebPPicture* const pic = enc->pic_; - uint8_t riff[RIFF_HEADER_SIZE] = { - 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P' - }; - assert(riff_size == (uint32_t)riff_size); - PutLE32(riff + TAG_SIZE, (uint32_t)riff_size); - if (!pic->writer(riff, sizeof(riff), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static WebPEncodingError PutVP8XHeader(const VP8Encoder* const enc) { - const WebPPicture* const pic = enc->pic_; - uint8_t vp8x[CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE] = { - 'V', 'P', '8', 'X' - }; - uint32_t flags = 0; - - assert(IsVP8XNeeded(enc)); - assert(pic->width >= 1 && pic->height >= 1); - assert(pic->width <= MAX_CANVAS_SIZE && pic->height <= MAX_CANVAS_SIZE); - - if (enc->has_alpha_) { - flags |= ALPHA_FLAG; - } - - PutLE32(vp8x + TAG_SIZE, VP8X_CHUNK_SIZE); - PutLE32(vp8x + CHUNK_HEADER_SIZE, flags); - PutLE24(vp8x + CHUNK_HEADER_SIZE + 4, pic->width - 1); - PutLE24(vp8x + CHUNK_HEADER_SIZE + 7, pic->height - 1); - if (!pic->writer(vp8x, sizeof(vp8x), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static WebPEncodingError PutAlphaChunk(const VP8Encoder* const enc) { - const WebPPicture* const pic = enc->pic_; - uint8_t alpha_chunk_hdr[CHUNK_HEADER_SIZE] = { - 'A', 'L', 'P', 'H' - }; - - assert(enc->has_alpha_); - - // Alpha chunk header. - PutLE32(alpha_chunk_hdr + TAG_SIZE, enc->alpha_data_size_); - if (!pic->writer(alpha_chunk_hdr, sizeof(alpha_chunk_hdr), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - - // Alpha chunk data. - if (!pic->writer(enc->alpha_data_, enc->alpha_data_size_, pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - - // Padding. - if ((enc->alpha_data_size_ & 1) && !PutPaddingByte(pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static WebPEncodingError PutVP8Header(const WebPPicture* const pic, - size_t vp8_size) { - uint8_t vp8_chunk_hdr[CHUNK_HEADER_SIZE] = { - 'V', 'P', '8', ' ' - }; - assert(vp8_size == (uint32_t)vp8_size); - PutLE32(vp8_chunk_hdr + TAG_SIZE, (uint32_t)vp8_size); - if (!pic->writer(vp8_chunk_hdr, sizeof(vp8_chunk_hdr), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static WebPEncodingError PutVP8FrameHeader(const WebPPicture* const pic, - int profile, size_t size0) { - uint8_t vp8_frm_hdr[VP8_FRAME_HEADER_SIZE]; - uint32_t bits; - - if (size0 >= VP8_MAX_PARTITION0_SIZE) { // partition #0 is too big to fit - return VP8_ENC_ERROR_PARTITION0_OVERFLOW; - } - - // Paragraph 9.1. - bits = 0 // keyframe (1b) - | (profile << 1) // profile (3b) - | (1 << 4) // visible (1b) - | ((uint32_t)size0 << 5); // partition length (19b) - vp8_frm_hdr[0] = (bits >> 0) & 0xff; - vp8_frm_hdr[1] = (bits >> 8) & 0xff; - vp8_frm_hdr[2] = (bits >> 16) & 0xff; - // signature - vp8_frm_hdr[3] = (VP8_SIGNATURE >> 16) & 0xff; - vp8_frm_hdr[4] = (VP8_SIGNATURE >> 8) & 0xff; - vp8_frm_hdr[5] = (VP8_SIGNATURE >> 0) & 0xff; - // dimensions - vp8_frm_hdr[6] = pic->width & 0xff; - vp8_frm_hdr[7] = pic->width >> 8; - vp8_frm_hdr[8] = pic->height & 0xff; - vp8_frm_hdr[9] = pic->height >> 8; - - if (!pic->writer(vp8_frm_hdr, sizeof(vp8_frm_hdr), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -// WebP Headers. -static int PutWebPHeaders(const VP8Encoder* const enc, size_t size0, - size_t vp8_size, size_t riff_size) { - WebPPicture* const pic = enc->pic_; - WebPEncodingError err = VP8_ENC_OK; - - // RIFF header. - err = PutRIFFHeader(enc, riff_size); - if (err != VP8_ENC_OK) goto Error; - - // VP8X. - if (IsVP8XNeeded(enc)) { - err = PutVP8XHeader(enc); - if (err != VP8_ENC_OK) goto Error; - } - - // Alpha. - if (enc->has_alpha_) { - err = PutAlphaChunk(enc); - if (err != VP8_ENC_OK) goto Error; - } - - // VP8 header. - err = PutVP8Header(pic, vp8_size); - if (err != VP8_ENC_OK) goto Error; - - // VP8 frame header. - err = PutVP8FrameHeader(pic, enc->profile_, size0); - if (err != VP8_ENC_OK) goto Error; - - // All OK. - return 1; - - // Error. - Error: - return WebPEncodingSetError(pic, err); -} - -// Segmentation header -static void PutSegmentHeader(VP8BitWriter* const bw, - const VP8Encoder* const enc) { - const VP8EncSegmentHeader* const hdr = &enc->segment_hdr_; - const VP8EncProba* const proba = &enc->proba_; - if (VP8PutBitUniform(bw, (hdr->num_segments_ > 1))) { - // We always 'update' the quant and filter strength values - const int update_data = 1; - int s; - VP8PutBitUniform(bw, hdr->update_map_); - if (VP8PutBitUniform(bw, update_data)) { - // we always use absolute values, not relative ones - VP8PutBitUniform(bw, 1); // (segment_feature_mode = 1. Paragraph 9.3.) - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - VP8PutSignedBits(bw, enc->dqm_[s].quant_, 7); - } - for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - VP8PutSignedBits(bw, enc->dqm_[s].fstrength_, 6); - } - } - if (hdr->update_map_) { - for (s = 0; s < 3; ++s) { - if (VP8PutBitUniform(bw, (proba->segments_[s] != 255u))) { - VP8PutBits(bw, proba->segments_[s], 8); - } - } - } - } -} - -// Filtering parameters header -static void PutFilterHeader(VP8BitWriter* const bw, - const VP8EncFilterHeader* const hdr) { - const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0); - VP8PutBitUniform(bw, hdr->simple_); - VP8PutBits(bw, hdr->level_, 6); - VP8PutBits(bw, hdr->sharpness_, 3); - if (VP8PutBitUniform(bw, use_lf_delta)) { - // '0' is the default value for i4x4_lf_delta_ at frame #0. - const int need_update = (hdr->i4x4_lf_delta_ != 0); - if (VP8PutBitUniform(bw, need_update)) { - // we don't use ref_lf_delta => emit four 0 bits - VP8PutBits(bw, 0, 4); - // we use mode_lf_delta for i4x4 - VP8PutSignedBits(bw, hdr->i4x4_lf_delta_, 6); - VP8PutBits(bw, 0, 3); // all others unused - } - } -} - -// Nominal quantization parameters -static void PutQuant(VP8BitWriter* const bw, - const VP8Encoder* const enc) { - VP8PutBits(bw, enc->base_quant_, 7); - VP8PutSignedBits(bw, enc->dq_y1_dc_, 4); - VP8PutSignedBits(bw, enc->dq_y2_dc_, 4); - VP8PutSignedBits(bw, enc->dq_y2_ac_, 4); - VP8PutSignedBits(bw, enc->dq_uv_dc_, 4); - VP8PutSignedBits(bw, enc->dq_uv_ac_, 4); -} - -// Partition sizes -static int EmitPartitionsSize(const VP8Encoder* const enc, - WebPPicture* const pic) { - uint8_t buf[3 * (MAX_NUM_PARTITIONS - 1)]; - int p; - for (p = 0; p < enc->num_parts_ - 1; ++p) { - const size_t part_size = VP8BitWriterSize(enc->parts_ + p); - if (part_size >= VP8_MAX_PARTITION_SIZE) { - return WebPEncodingSetError(pic, VP8_ENC_ERROR_PARTITION_OVERFLOW); - } - buf[3 * p + 0] = (part_size >> 0) & 0xff; - buf[3 * p + 1] = (part_size >> 8) & 0xff; - buf[3 * p + 2] = (part_size >> 16) & 0xff; - } - return p ? pic->writer(buf, 3 * p, pic) : 1; -} - -//------------------------------------------------------------------------------ - -static int GeneratePartition0(VP8Encoder* const enc) { - VP8BitWriter* const bw = &enc->bw_; - const int mb_size = enc->mb_w_ * enc->mb_h_; - uint64_t pos1, pos2, pos3; - - pos1 = VP8BitWriterPos(bw); - if (!VP8BitWriterInit(bw, mb_size * 7 / 8)) { // ~7 bits per macroblock - return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - VP8PutBitUniform(bw, 0); // colorspace - VP8PutBitUniform(bw, 0); // clamp type - - PutSegmentHeader(bw, enc); - PutFilterHeader(bw, &enc->filter_hdr_); - VP8PutBits(bw, enc->num_parts_ == 8 ? 3 : - enc->num_parts_ == 4 ? 2 : - enc->num_parts_ == 2 ? 1 : 0, 2); - PutQuant(bw, enc); - VP8PutBitUniform(bw, 0); // no proba update - VP8WriteProbas(bw, &enc->proba_); - pos2 = VP8BitWriterPos(bw); - VP8CodeIntraModes(enc); - VP8BitWriterFinish(bw); - - pos3 = VP8BitWriterPos(bw); - - if (enc->pic_->stats) { - enc->pic_->stats->header_bytes[0] = (int)((pos2 - pos1 + 7) >> 3); - enc->pic_->stats->header_bytes[1] = (int)((pos3 - pos2 + 7) >> 3); - enc->pic_->stats->alpha_data_size = (int)enc->alpha_data_size_; - } - if (bw->error_) { - return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - return 1; -} - -void VP8EncFreeBitWriters(VP8Encoder* const enc) { - int p; - VP8BitWriterWipeOut(&enc->bw_); - for (p = 0; p < enc->num_parts_; ++p) { - VP8BitWriterWipeOut(enc->parts_ + p); - } -} - -int VP8EncWrite(VP8Encoder* const enc) { - WebPPicture* const pic = enc->pic_; - VP8BitWriter* const bw = &enc->bw_; - const int task_percent = 19; - const int percent_per_part = task_percent / enc->num_parts_; - const int final_percent = enc->percent_ + task_percent; - int ok = 0; - size_t vp8_size, pad, riff_size; - int p; - - // Partition #0 with header and partition sizes - ok = GeneratePartition0(enc); - if (!ok) return 0; - - // Compute VP8 size - vp8_size = VP8_FRAME_HEADER_SIZE + - VP8BitWriterSize(bw) + - 3 * (enc->num_parts_ - 1); - for (p = 0; p < enc->num_parts_; ++p) { - vp8_size += VP8BitWriterSize(enc->parts_ + p); - } - pad = vp8_size & 1; - vp8_size += pad; - - // Compute RIFF size - // At the minimum it is: "WEBPVP8 nnnn" + VP8 data size. - riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8_size; - if (IsVP8XNeeded(enc)) { // Add size for: VP8X header + data. - riff_size += CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; - } - if (enc->has_alpha_) { // Add size for: ALPH header + data. - const uint32_t padded_alpha_size = enc->alpha_data_size_ + - (enc->alpha_data_size_ & 1); - riff_size += CHUNK_HEADER_SIZE + padded_alpha_size; - } - // Sanity check. - if (riff_size > 0xfffffffeU) { - return WebPEncodingSetError(pic, VP8_ENC_ERROR_FILE_TOO_BIG); - } - - // Emit headers and partition #0 - { - const uint8_t* const part0 = VP8BitWriterBuf(bw); - const size_t size0 = VP8BitWriterSize(bw); - ok = ok && PutWebPHeaders(enc, size0, vp8_size, riff_size) - && pic->writer(part0, size0, pic) - && EmitPartitionsSize(enc, pic); - VP8BitWriterWipeOut(bw); // will free the internal buffer. - } - - // Token partitions - for (p = 0; p < enc->num_parts_; ++p) { - const uint8_t* const buf = VP8BitWriterBuf(enc->parts_ + p); - const size_t size = VP8BitWriterSize(enc->parts_ + p); - if (size) - ok = ok && pic->writer(buf, size, pic); - VP8BitWriterWipeOut(enc->parts_ + p); // will free the internal buffer. - ok = ok && WebPReportProgress(pic, enc->percent_ + percent_per_part, - &enc->percent_); - } - - // Padding byte - if (ok && pad) { - ok = PutPaddingByte(pic); - } - - enc->coded_size_ = (int)(CHUNK_HEADER_SIZE + riff_size); - ok = ok && WebPReportProgress(pic, final_percent, &enc->percent_); - return ok; -} - -//------------------------------------------------------------------------------ - diff --git a/drivers/webp/enc/vp8enci.h b/drivers/webp/enc/vp8enci.h deleted file mode 100644 index efd2f19a9b..0000000000 --- a/drivers/webp/enc/vp8enci.h +++ /dev/null @@ -1,531 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// WebP encoder: internal header. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_ENC_VP8ENCI_H_ -#define WEBP_ENC_VP8ENCI_H_ - -#include <string.h> // for memcpy() -#include "../dec/common.h" -#include "../dsp/dsp.h" -#include "../utils/bit_writer.h" -#include "../utils/thread.h" -#include "../utils/utils.h" -#include "webp/encode.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Various defines and enums - -// version numbers -#define ENC_MAJ_VERSION 0 -#define ENC_MIN_VERSION 5 -#define ENC_REV_VERSION 1 - -enum { MAX_LF_LEVELS = 64, // Maximum loop filter level - MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost - MAX_LEVEL = 2047 // max level (note: max codable is 2047 + 67) - }; - -typedef enum { // Rate-distortion optimization levels - RD_OPT_NONE = 0, // no rd-opt - RD_OPT_BASIC = 1, // basic scoring (no trellis) - RD_OPT_TRELLIS = 2, // perform trellis-quant on the final decision only - RD_OPT_TRELLIS_ALL = 3 // trellis-quant for every scoring (much slower) -} VP8RDLevel; - -// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). -// The original or reconstructed samples can be accessed using VP8Scan[]. -// The predicted blocks can be accessed using offsets to yuv_p_ and -// the arrays VP8*ModeOffsets[]. -// * YUV Samples area (yuv_in_/yuv_out_/yuv_out2_) -// (see VP8Scan[] for accessing the blocks, along with -// Y_OFF_ENC/U_OFF_ENC/V_OFF_ENC): -// +----+----+ -// Y_OFF_ENC |YYYY|UUVV| -// U_OFF_ENC |YYYY|UUVV| -// V_OFF_ENC |YYYY|....| <- 25% wasted U/V area -// |YYYY|....| -// +----+----+ -// * Prediction area ('yuv_p_', size = PRED_SIZE_ENC) -// Intra16 predictions (16x16 block each, two per row): -// |I16DC16|I16TM16| -// |I16VE16|I16HE16| -// Chroma U/V predictions (16x8 block each, two per row): -// |C8DC8|C8TM8| -// |C8VE8|C8HE8| -// Intra 4x4 predictions (4x4 block each) -// |I4DC4 I4TM4 I4VE4 I4HE4|I4RD4 I4VR4 I4LD4 I4VL4| -// |I4HD4 I4HU4 I4TMP .....|.......................| <- ~31% wasted -#define YUV_SIZE_ENC (BPS * 16) -#define PRED_SIZE_ENC (32 * BPS + 16 * BPS + 8 * BPS) // I16+Chroma+I4 preds -#define Y_OFF_ENC (0) -#define U_OFF_ENC (16) -#define V_OFF_ENC (16 + 8) - -extern const int VP8Scan[16]; // in quant.c -extern const int VP8UVModeOffsets[4]; // in analyze.c -extern const int VP8I16ModeOffsets[4]; -extern const int VP8I4ModeOffsets[NUM_BMODES]; - -// Layout of prediction blocks -// intra 16x16 -#define I16DC16 (0 * 16 * BPS) -#define I16TM16 (I16DC16 + 16) -#define I16VE16 (1 * 16 * BPS) -#define I16HE16 (I16VE16 + 16) -// chroma 8x8, two U/V blocks side by side (hence: 16x8 each) -#define C8DC8 (2 * 16 * BPS) -#define C8TM8 (C8DC8 + 1 * 16) -#define C8VE8 (2 * 16 * BPS + 8 * BPS) -#define C8HE8 (C8VE8 + 1 * 16) -// intra 4x4 -#define I4DC4 (3 * 16 * BPS + 0) -#define I4TM4 (I4DC4 + 4) -#define I4VE4 (I4DC4 + 8) -#define I4HE4 (I4DC4 + 12) -#define I4RD4 (I4DC4 + 16) -#define I4VR4 (I4DC4 + 20) -#define I4LD4 (I4DC4 + 24) -#define I4VL4 (I4DC4 + 28) -#define I4HD4 (3 * 16 * BPS + 4 * BPS) -#define I4HU4 (I4HD4 + 4) -#define I4TMP (I4HD4 + 8) - -typedef int64_t score_t; // type used for scores, rate, distortion -// Note that MAX_COST is not the maximum allowed by sizeof(score_t), -// in order to allow overflowing computations. -#define MAX_COST ((score_t)0x7fffffffffffffLL) - -#define QFIX 17 -#define BIAS(b) ((b) << (QFIX - 8)) -// Fun fact: this is the _only_ line where we're actually being lossy and -// discarding bits. -static WEBP_INLINE int QUANTDIV(uint32_t n, uint32_t iQ, uint32_t B) { - return (int)((n * iQ + B) >> QFIX); -} - -// Uncomment the following to remove token-buffer code: -// #define DISABLE_TOKEN_BUFFER - -//------------------------------------------------------------------------------ -// Headers - -typedef uint32_t proba_t; // 16b + 16b -typedef uint8_t ProbaArray[NUM_CTX][NUM_PROBAS]; -typedef proba_t StatsArray[NUM_CTX][NUM_PROBAS]; -typedef uint16_t CostArray[NUM_CTX][MAX_VARIABLE_LEVEL + 1]; -typedef const uint16_t* (*CostArrayPtr)[NUM_CTX]; // for easy casting -typedef const uint16_t* CostArrayMap[16][NUM_CTX]; -typedef double LFStats[NUM_MB_SEGMENTS][MAX_LF_LEVELS]; // filter stats - -typedef struct VP8Encoder VP8Encoder; - -// segment features -typedef struct { - int num_segments_; // Actual number of segments. 1 segment only = unused. - int update_map_; // whether to update the segment map or not. - // must be 0 if there's only 1 segment. - int size_; // bit-cost for transmitting the segment map -} VP8EncSegmentHeader; - -// Struct collecting all frame-persistent probabilities. -typedef struct { - uint8_t segments_[3]; // probabilities for segment tree - uint8_t skip_proba_; // final probability of being skipped. - ProbaArray coeffs_[NUM_TYPES][NUM_BANDS]; // 1056 bytes - StatsArray stats_[NUM_TYPES][NUM_BANDS]; // 4224 bytes - CostArray level_cost_[NUM_TYPES][NUM_BANDS]; // 13056 bytes - CostArrayMap remapped_costs_[NUM_TYPES]; // 1536 bytes - int dirty_; // if true, need to call VP8CalculateLevelCosts() - int use_skip_proba_; // Note: we always use skip_proba for now. - int nb_skip_; // number of skipped blocks -} VP8EncProba; - -// Filter parameters. Not actually used in the code (we don't perform -// the in-loop filtering), but filled from user's config -typedef struct { - int simple_; // filtering type: 0=complex, 1=simple - int level_; // base filter level [0..63] - int sharpness_; // [0..7] - int i4x4_lf_delta_; // delta filter level for i4x4 relative to i16x16 -} VP8EncFilterHeader; - -//------------------------------------------------------------------------------ -// Informations about the macroblocks. - -typedef struct { - // block type - unsigned int type_:2; // 0=i4x4, 1=i16x16 - unsigned int uv_mode_:2; - unsigned int skip_:1; - unsigned int segment_:2; - uint8_t alpha_; // quantization-susceptibility -} VP8MBInfo; - -typedef struct VP8Matrix { - uint16_t q_[16]; // quantizer steps - uint16_t iq_[16]; // reciprocals, fixed point. - uint32_t bias_[16]; // rounding bias - uint32_t zthresh_[16]; // value below which a coefficient is zeroed - uint16_t sharpen_[16]; // frequency boosters for slight sharpening -} VP8Matrix; - -typedef struct { - VP8Matrix y1_, y2_, uv_; // quantization matrices - int alpha_; // quant-susceptibility, range [-127,127]. Zero is neutral. - // Lower values indicate a lower risk of blurriness. - int beta_; // filter-susceptibility, range [0,255]. - int quant_; // final segment quantizer. - int fstrength_; // final in-loop filtering strength - int max_edge_; // max edge delta (for filtering strength) - int min_disto_; // minimum distortion required to trigger filtering record - // reactivities - int lambda_i16_, lambda_i4_, lambda_uv_; - int lambda_mode_, lambda_trellis_, tlambda_; - int lambda_trellis_i16_, lambda_trellis_i4_, lambda_trellis_uv_; - - // lambda values for distortion-based evaluation - score_t i4_penalty_; // penalty for using Intra4 -} VP8SegmentInfo; - -// Handy transient struct to accumulate score and info during RD-optimization -// and mode evaluation. -typedef struct { - score_t D, SD; // Distortion, spectral distortion - score_t H, R, score; // header bits, rate, score. - int16_t y_dc_levels[16]; // Quantized levels for luma-DC, luma-AC, chroma. - int16_t y_ac_levels[16][16]; - int16_t uv_levels[4 + 4][16]; - int mode_i16; // mode number for intra16 prediction - uint8_t modes_i4[16]; // mode numbers for intra4 predictions - int mode_uv; // mode number of chroma prediction - uint32_t nz; // non-zero blocks -} VP8ModeScore; - -// Iterator structure to iterate through macroblocks, pointing to the -// right neighbouring data (samples, predictions, contexts, ...) -typedef struct { - int x_, y_; // current macroblock - int y_stride_, uv_stride_; // respective strides - uint8_t* yuv_in_; // input samples - uint8_t* yuv_out_; // output samples - uint8_t* yuv_out2_; // secondary buffer swapped with yuv_out_. - uint8_t* yuv_p_; // scratch buffer for prediction - VP8Encoder* enc_; // back-pointer - VP8MBInfo* mb_; // current macroblock - VP8BitWriter* bw_; // current bit-writer - uint8_t* preds_; // intra mode predictors (4x4 blocks) - uint32_t* nz_; // non-zero pattern - uint8_t i4_boundary_[37]; // 32+5 boundary samples needed by intra4x4 - uint8_t* i4_top_; // pointer to the current top boundary sample - int i4_; // current intra4x4 mode being tested - int top_nz_[9]; // top-non-zero context. - int left_nz_[9]; // left-non-zero. left_nz[8] is independent. - uint64_t bit_count_[4][3]; // bit counters for coded levels. - uint64_t luma_bits_; // macroblock bit-cost for luma - uint64_t uv_bits_; // macroblock bit-cost for chroma - LFStats* lf_stats_; // filter stats (borrowed from enc_) - int do_trellis_; // if true, perform extra level optimisation - int count_down_; // number of mb still to be processed - int count_down0_; // starting counter value (for progress) - int percent0_; // saved initial progress percent - - uint8_t* y_left_; // left luma samples (addressable from index -1 to 15). - uint8_t* u_left_; // left u samples (addressable from index -1 to 7) - uint8_t* v_left_; // left v samples (addressable from index -1 to 7) - - uint8_t* y_top_; // top luma samples at position 'x_' - uint8_t* uv_top_; // top u/v samples at position 'x_', packed as 16 bytes - - // memory for storing y/u/v_left_ - uint8_t yuv_left_mem_[17 + 16 + 16 + 8 + WEBP_ALIGN_CST]; - // memory for yuv_* - uint8_t yuv_mem_[3 * YUV_SIZE_ENC + PRED_SIZE_ENC + WEBP_ALIGN_CST]; -} VP8EncIterator; - - // in iterator.c -// must be called first -void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it); -// restart a scan -void VP8IteratorReset(VP8EncIterator* const it); -// reset iterator position to row 'y' -void VP8IteratorSetRow(VP8EncIterator* const it, int y); -// set count down (=number of iterations to go) -void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down); -// return true if iteration is finished -int VP8IteratorIsDone(const VP8EncIterator* const it); -// Import uncompressed samples from source. -// If tmp_32 is not NULL, import boundary samples too. -// tmp_32 is a 32-bytes scratch buffer that must be aligned in memory. -void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32); -// export decimated samples -void VP8IteratorExport(const VP8EncIterator* const it); -// go to next macroblock. Returns false if not finished. -int VP8IteratorNext(VP8EncIterator* const it); -// save the yuv_out_ boundary values to top_/left_ arrays for next iterations. -void VP8IteratorSaveBoundary(VP8EncIterator* const it); -// Report progression based on macroblock rows. Return 0 for user-abort request. -int VP8IteratorProgress(const VP8EncIterator* const it, - int final_delta_percent); -// Intra4x4 iterations -void VP8IteratorStartI4(VP8EncIterator* const it); -// returns true if not done. -int VP8IteratorRotateI4(VP8EncIterator* const it, - const uint8_t* const yuv_out); - -// Non-zero context setup/teardown -void VP8IteratorNzToBytes(VP8EncIterator* const it); -void VP8IteratorBytesToNz(VP8EncIterator* const it); - -// Helper functions to set mode properties -void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode); -void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes); -void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode); -void VP8SetSkip(const VP8EncIterator* const it, int skip); -void VP8SetSegment(const VP8EncIterator* const it, int segment); - -//------------------------------------------------------------------------------ -// Paginated token buffer - -typedef struct VP8Tokens VP8Tokens; // struct details in token.c - -typedef struct { -#if !defined(DISABLE_TOKEN_BUFFER) - VP8Tokens* pages_; // first page - VP8Tokens** last_page_; // last page - uint16_t* tokens_; // set to (*last_page_)->tokens_ - int left_; // how many free tokens left before the page is full - int page_size_; // number of tokens per page -#endif - int error_; // true in case of malloc error -} VP8TBuffer; - -// initialize an empty buffer -void VP8TBufferInit(VP8TBuffer* const b, int page_size); -void VP8TBufferClear(VP8TBuffer* const b); // de-allocate pages memory - -#if !defined(DISABLE_TOKEN_BUFFER) - -// Finalizes bitstream when probabilities are known. -// Deletes the allocated token memory if final_pass is true. -int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw, - const uint8_t* const probas, int final_pass); - -// record the coding of coefficients without knowing the probabilities yet -int VP8RecordCoeffTokens(const int ctx, const int coeff_type, - int first, int last, - const int16_t* const coeffs, - VP8TBuffer* const tokens); - -// Estimate the final coded size given a set of 'probas'. -size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas); - -// unused for now -void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats); - -#endif // !DISABLE_TOKEN_BUFFER - -//------------------------------------------------------------------------------ -// VP8Encoder - -struct VP8Encoder { - const WebPConfig* config_; // user configuration and parameters - WebPPicture* pic_; // input / output picture - - // headers - VP8EncFilterHeader filter_hdr_; // filtering information - VP8EncSegmentHeader segment_hdr_; // segment information - - int profile_; // VP8's profile, deduced from Config. - - // dimension, in macroblock units. - int mb_w_, mb_h_; - int preds_w_; // stride of the *preds_ prediction plane (=4*mb_w + 1) - - // number of partitions (1, 2, 4 or 8 = MAX_NUM_PARTITIONS) - int num_parts_; - - // per-partition boolean decoders. - VP8BitWriter bw_; // part0 - VP8BitWriter parts_[MAX_NUM_PARTITIONS]; // token partitions - VP8TBuffer tokens_; // token buffer - - int percent_; // for progress - - // transparency blob - int has_alpha_; - uint8_t* alpha_data_; // non-NULL if transparency is present - uint32_t alpha_data_size_; - WebPWorker alpha_worker_; - - // quantization info (one set of DC/AC dequant factor per segment) - VP8SegmentInfo dqm_[NUM_MB_SEGMENTS]; - int base_quant_; // nominal quantizer value. Only used - // for relative coding of segments' quant. - int alpha_; // global susceptibility (<=> complexity) - int uv_alpha_; // U/V quantization susceptibility - // global offset of quantizers, shared by all segments - int dq_y1_dc_; - int dq_y2_dc_, dq_y2_ac_; - int dq_uv_dc_, dq_uv_ac_; - - // probabilities and statistics - VP8EncProba proba_; - uint64_t sse_[4]; // sum of Y/U/V/A squared errors for all macroblocks - uint64_t sse_count_; // pixel count for the sse_[] stats - int coded_size_; - int residual_bytes_[3][4]; - int block_count_[3]; - - // quality/speed settings - int method_; // 0=fastest, 6=best/slowest. - VP8RDLevel rd_opt_level_; // Deduced from method_. - int max_i4_header_bits_; // partition #0 safeness factor - int mb_header_limit_; // rough limit for header bits per MB - int thread_level_; // derived from config->thread_level - int do_search_; // derived from config->target_XXX - int use_tokens_; // if true, use token buffer - - // Memory - VP8MBInfo* mb_info_; // contextual macroblock infos (mb_w_ + 1) - uint8_t* preds_; // predictions modes: (4*mb_w+1) * (4*mb_h+1) - uint32_t* nz_; // non-zero bit context: mb_w+1 - uint8_t* y_top_; // top luma samples. - uint8_t* uv_top_; // top u/v samples. - // U and V are packed into 16 bytes (8 U + 8 V) - LFStats* lf_stats_; // autofilter stats (if NULL, autofilter is off) -}; - -//------------------------------------------------------------------------------ -// internal functions. Not public. - - // in tree.c -extern const uint8_t VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS]; -extern const uint8_t - VP8CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS]; -// Reset the token probabilities to their initial (default) values -void VP8DefaultProbas(VP8Encoder* const enc); -// Write the token probabilities -void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas); -// Writes the partition #0 modes (that is: all intra modes) -void VP8CodeIntraModes(VP8Encoder* const enc); - - // in syntax.c -// Generates the final bitstream by coding the partition0 and headers, -// and appending an assembly of all the pre-coded token partitions. -// Return true if everything is ok. -int VP8EncWrite(VP8Encoder* const enc); -// Release memory allocated for bit-writing in VP8EncLoop & seq. -void VP8EncFreeBitWriters(VP8Encoder* const enc); - - // in frame.c -extern const uint8_t VP8Cat3[]; -extern const uint8_t VP8Cat4[]; -extern const uint8_t VP8Cat5[]; -extern const uint8_t VP8Cat6[]; - -// Form all the four Intra16x16 predictions in the yuv_p_ cache -void VP8MakeLuma16Preds(const VP8EncIterator* const it); -// Form all the four Chroma8x8 predictions in the yuv_p_ cache -void VP8MakeChroma8Preds(const VP8EncIterator* const it); -// Form all the ten Intra4x4 predictions in the yuv_p_ cache -// for the 4x4 block it->i4_ -void VP8MakeIntra4Preds(const VP8EncIterator* const it); -// Rate calculation -int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd); -int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]); -int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd); -// Main coding calls -int VP8EncLoop(VP8Encoder* const enc); -int VP8EncTokenLoop(VP8Encoder* const enc); - - // in webpenc.c -// Assign an error code to a picture. Return false for convenience. -int WebPEncodingSetError(const WebPPicture* const pic, WebPEncodingError error); -int WebPReportProgress(const WebPPicture* const pic, - int percent, int* const percent_store); - - // in analysis.c -// Main analysis loop. Decides the segmentations and complexity. -// Assigns a first guess for Intra16 and uvmode_ prediction modes. -int VP8EncAnalyze(VP8Encoder* const enc); - - // in quant.c -// Sets up segment's quantization values, base_quant_ and filter strengths. -void VP8SetSegmentParams(VP8Encoder* const enc, float quality); -// Pick best modes and fills the levels. Returns true if skipped. -int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, - VP8RDLevel rd_opt); - - // in alpha.c -void VP8EncInitAlpha(VP8Encoder* const enc); // initialize alpha compression -int VP8EncStartAlpha(VP8Encoder* const enc); // start alpha coding process -int VP8EncFinishAlpha(VP8Encoder* const enc); // finalize compressed data -int VP8EncDeleteAlpha(VP8Encoder* const enc); // delete compressed data - - // in filter.c -void VP8SSIMAddStats(const VP8DistoStats* const src, VP8DistoStats* const dst); -void VP8SSIMAccumulatePlane(const uint8_t* src1, int stride1, - const uint8_t* src2, int stride2, - int W, int H, VP8DistoStats* const stats); -double VP8SSIMGet(const VP8DistoStats* const stats); -double VP8SSIMGetSquaredError(const VP8DistoStats* const stats); - -// autofilter -void VP8InitFilter(VP8EncIterator* const it); -void VP8StoreFilterStats(VP8EncIterator* const it); -void VP8AdjustFilterStrength(VP8EncIterator* const it); - -// returns the approximate filtering strength needed to smooth a edge -// step of 'delta', given a sharpness parameter 'sharpness'. -int VP8FilterStrengthFromDelta(int sharpness, int delta); - - // misc utils for picture_*.c: - -// Remove reference to the ARGB/YUVA buffer (doesn't free anything). -void WebPPictureResetBuffers(WebPPicture* const picture); - -// Allocates ARGB buffer of given dimension (previous one is always free'd). -// Preserves the YUV(A) buffer. Returns false in case of error (invalid param, -// out-of-memory). -int WebPPictureAllocARGB(WebPPicture* const picture, int width, int height); - -// Allocates YUVA buffer of given dimension (previous one is always free'd). -// Uses picture->csp to determine whether an alpha buffer is needed. -// Preserves the ARGB buffer. -// Returns false in case of error (invalid param, out-of-memory). -int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height); - -// Clean-up the RGB samples under fully transparent area, to help lossless -// compressibility (no guarantee, though). Assumes that pic->use_argb is true. -void WebPCleanupTransparentAreaLossless(WebPPicture* const pic); - - // in near_lossless.c -// Near lossless preprocessing in RGB color-space. -int VP8ApplyNearLossless(int xsize, int ysize, uint32_t* argb, int quality); -// Near lossless adjustment for predictors. -void VP8ApplyNearLosslessPredict(int xsize, int ysize, int pred_bits, - const uint32_t* argb_orig, - uint32_t* argb, uint32_t* argb_scratch, - const uint32_t* const transform_data, - int quality, int subtract_green); -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_ENC_VP8ENCI_H_ */ diff --git a/drivers/webp/enc/vp8l.c b/drivers/webp/enc/vp8l.c deleted file mode 100644 index 1f2d41ea91..0000000000 --- a/drivers/webp/enc/vp8l.c +++ /dev/null @@ -1,1603 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// main entry for the lossless encoder. -// -// Author: Vikas Arora (vikaas.arora@gmail.com) -// - -#include <assert.h> -#include <stdlib.h> - -#include "./backward_references.h" -#include "./histogram.h" -#include "./vp8enci.h" -#include "./vp8li.h" -#include "../dsp/lossless.h" -#include "../utils/bit_writer.h" -#include "../utils/huffman_encode.h" -#include "../utils/utils.h" -#include "webp/format_constants.h" - -#include "./delta_palettization.h" - -#define PALETTE_KEY_RIGHT_SHIFT 22 // Key for 1K buffer. -// Maximum number of histogram images (sub-blocks). -#define MAX_HUFF_IMAGE_SIZE 2600 - -// Palette reordering for smaller sum of deltas (and for smaller storage). - -static int PaletteCompareColorsForQsort(const void* p1, const void* p2) { - const uint32_t a = WebPMemToUint32(p1); - const uint32_t b = WebPMemToUint32(p2); - assert(a != b); - return (a < b) ? -1 : 1; -} - -static WEBP_INLINE uint32_t PaletteComponentDistance(uint32_t v) { - return (v <= 128) ? v : (256 - v); -} - -// Computes a value that is related to the entropy created by the -// palette entry diff. -// -// Note that the last & 0xff is a no-operation in the next statement, but -// removed by most compilers and is here only for regularity of the code. -static WEBP_INLINE uint32_t PaletteColorDistance(uint32_t col1, uint32_t col2) { - const uint32_t diff = VP8LSubPixels(col1, col2); - const int kMoreWeightForRGBThanForAlpha = 9; - uint32_t score; - score = PaletteComponentDistance((diff >> 0) & 0xff); - score += PaletteComponentDistance((diff >> 8) & 0xff); - score += PaletteComponentDistance((diff >> 16) & 0xff); - score *= kMoreWeightForRGBThanForAlpha; - score += PaletteComponentDistance((diff >> 24) & 0xff); - return score; -} - -static WEBP_INLINE void SwapColor(uint32_t* const col1, uint32_t* const col2) { - const uint32_t tmp = *col1; - *col1 = *col2; - *col2 = tmp; -} - -static void GreedyMinimizeDeltas(uint32_t palette[], int num_colors) { - // Find greedily always the closest color of the predicted color to minimize - // deltas in the palette. This reduces storage needs since the - // palette is stored with delta encoding. - uint32_t predict = 0x00000000; - int i, k; - for (i = 0; i < num_colors; ++i) { - int best_ix = i; - uint32_t best_score = ~0U; - for (k = i; k < num_colors; ++k) { - const uint32_t cur_score = PaletteColorDistance(palette[k], predict); - if (best_score > cur_score) { - best_score = cur_score; - best_ix = k; - } - } - SwapColor(&palette[best_ix], &palette[i]); - predict = palette[i]; - } -} - -// The palette has been sorted by alpha. This function checks if the other -// components of the palette have a monotonic development with regards to -// position in the palette. If all have monotonic development, there is -// no benefit to re-organize them greedily. A monotonic development -// would be spotted in green-only situations (like lossy alpha) or gray-scale -// images. -static int PaletteHasNonMonotonousDeltas(uint32_t palette[], int num_colors) { - uint32_t predict = 0x000000; - int i; - uint8_t sign_found = 0x00; - for (i = 0; i < num_colors; ++i) { - const uint32_t diff = VP8LSubPixels(palette[i], predict); - const uint8_t rd = (diff >> 16) & 0xff; - const uint8_t gd = (diff >> 8) & 0xff; - const uint8_t bd = (diff >> 0) & 0xff; - if (rd != 0x00) { - sign_found |= (rd < 0x80) ? 1 : 2; - } - if (gd != 0x00) { - sign_found |= (gd < 0x80) ? 8 : 16; - } - if (bd != 0x00) { - sign_found |= (bd < 0x80) ? 64 : 128; - } - predict = palette[i]; - } - return (sign_found & (sign_found << 1)) != 0; // two consequent signs. -} - -// ----------------------------------------------------------------------------- -// Palette - -// If number of colors in the image is less than or equal to MAX_PALETTE_SIZE, -// creates a palette and returns true, else returns false. -static int AnalyzeAndCreatePalette(const WebPPicture* const pic, - int low_effort, - uint32_t palette[MAX_PALETTE_SIZE], - int* const palette_size) { - const int num_colors = WebPGetColorPalette(pic, palette); - if (num_colors > MAX_PALETTE_SIZE) return 0; - *palette_size = num_colors; - qsort(palette, num_colors, sizeof(*palette), PaletteCompareColorsForQsort); - if (!low_effort && PaletteHasNonMonotonousDeltas(palette, num_colors)) { - GreedyMinimizeDeltas(palette, num_colors); - } - return 1; -} - -// These five modes are evaluated and their respective entropy is computed. -typedef enum { - kDirect = 0, - kSpatial = 1, - kSubGreen = 2, - kSpatialSubGreen = 3, - kPalette = 4, - kNumEntropyIx = 5 -} EntropyIx; - -typedef enum { - kHistoAlpha = 0, - kHistoAlphaPred, - kHistoGreen, - kHistoGreenPred, - kHistoRed, - kHistoRedPred, - kHistoBlue, - kHistoBluePred, - kHistoRedSubGreen, - kHistoRedPredSubGreen, - kHistoBlueSubGreen, - kHistoBluePredSubGreen, - kHistoPalette, - kHistoTotal // Must be last. -} HistoIx; - -static void AddSingleSubGreen(uint32_t p, uint32_t* r, uint32_t* b) { - const uint32_t green = p >> 8; // The upper bits are masked away later. - ++r[((p >> 16) - green) & 0xff]; - ++b[(p - green) & 0xff]; -} - -static void AddSingle(uint32_t p, - uint32_t* a, uint32_t* r, uint32_t* g, uint32_t* b) { - ++a[p >> 24]; - ++r[(p >> 16) & 0xff]; - ++g[(p >> 8) & 0xff]; - ++b[(p & 0xff)]; -} - -static int AnalyzeEntropy(const uint32_t* argb, - int width, int height, int argb_stride, - int use_palette, - EntropyIx* const min_entropy_ix, - int* const red_and_blue_always_zero) { - // Allocate histogram set with cache_bits = 0. - uint32_t* const histo = - (uint32_t*)WebPSafeCalloc(kHistoTotal, sizeof(*histo) * 256); - if (histo != NULL) { - int i, x, y; - const uint32_t* prev_row = argb; - const uint32_t* curr_row = argb + argb_stride; - for (y = 1; y < height; ++y) { - uint32_t prev_pix = curr_row[0]; - for (x = 1; x < width; ++x) { - const uint32_t pix = curr_row[x]; - const uint32_t pix_diff = VP8LSubPixels(pix, prev_pix); - if ((pix_diff == 0) || (pix == prev_row[x])) continue; - prev_pix = pix; - AddSingle(pix, - &histo[kHistoAlpha * 256], - &histo[kHistoRed * 256], - &histo[kHistoGreen * 256], - &histo[kHistoBlue * 256]); - AddSingle(pix_diff, - &histo[kHistoAlphaPred * 256], - &histo[kHistoRedPred * 256], - &histo[kHistoGreenPred * 256], - &histo[kHistoBluePred * 256]); - AddSingleSubGreen(pix, - &histo[kHistoRedSubGreen * 256], - &histo[kHistoBlueSubGreen * 256]); - AddSingleSubGreen(pix_diff, - &histo[kHistoRedPredSubGreen * 256], - &histo[kHistoBluePredSubGreen * 256]); - { - // Approximate the palette by the entropy of the multiplicative hash. - const int hash = ((pix + (pix >> 19)) * 0x39c5fba7) >> 24; - ++histo[kHistoPalette * 256 + (hash & 0xff)]; - } - } - prev_row = curr_row; - curr_row += argb_stride; - } - { - double entropy_comp[kHistoTotal]; - double entropy[kNumEntropyIx]; - EntropyIx k; - EntropyIx last_mode_to_analyze = - use_palette ? kPalette : kSpatialSubGreen; - int j; - // Let's add one zero to the predicted histograms. The zeros are removed - // too efficiently by the pix_diff == 0 comparison, at least one of the - // zeros is likely to exist. - ++histo[kHistoRedPredSubGreen * 256]; - ++histo[kHistoBluePredSubGreen * 256]; - ++histo[kHistoRedPred * 256]; - ++histo[kHistoGreenPred * 256]; - ++histo[kHistoBluePred * 256]; - ++histo[kHistoAlphaPred * 256]; - - for (j = 0; j < kHistoTotal; ++j) { - entropy_comp[j] = VP8LBitsEntropy(&histo[j * 256], 256, NULL); - } - entropy[kDirect] = entropy_comp[kHistoAlpha] + - entropy_comp[kHistoRed] + - entropy_comp[kHistoGreen] + - entropy_comp[kHistoBlue]; - entropy[kSpatial] = entropy_comp[kHistoAlphaPred] + - entropy_comp[kHistoRedPred] + - entropy_comp[kHistoGreenPred] + - entropy_comp[kHistoBluePred]; - entropy[kSubGreen] = entropy_comp[kHistoAlpha] + - entropy_comp[kHistoRedSubGreen] + - entropy_comp[kHistoGreen] + - entropy_comp[kHistoBlueSubGreen]; - entropy[kSpatialSubGreen] = entropy_comp[kHistoAlphaPred] + - entropy_comp[kHistoRedPredSubGreen] + - entropy_comp[kHistoGreenPred] + - entropy_comp[kHistoBluePredSubGreen]; - // Palette mode seems more efficient in a breakeven case. Bias with 1.0. - entropy[kPalette] = entropy_comp[kHistoPalette] - 1.0; - - *min_entropy_ix = kDirect; - for (k = kDirect + 1; k <= last_mode_to_analyze; ++k) { - if (entropy[*min_entropy_ix] > entropy[k]) { - *min_entropy_ix = k; - } - } - *red_and_blue_always_zero = 1; - // Let's check if the histogram of the chosen entropy mode has - // non-zero red and blue values. If all are zero, we can later skip - // the cross color optimization. - { - static const uint8_t kHistoPairs[5][2] = { - { kHistoRed, kHistoBlue }, - { kHistoRedPred, kHistoBluePred }, - { kHistoRedSubGreen, kHistoBlueSubGreen }, - { kHistoRedPredSubGreen, kHistoBluePredSubGreen }, - { kHistoRed, kHistoBlue } - }; - const uint32_t* const red_histo = - &histo[256 * kHistoPairs[*min_entropy_ix][0]]; - const uint32_t* const blue_histo = - &histo[256 * kHistoPairs[*min_entropy_ix][1]]; - for (i = 1; i < 256; ++i) { - if ((red_histo[i] | blue_histo[i]) != 0) { - *red_and_blue_always_zero = 0; - break; - } - } - } - } - WebPSafeFree(histo); - return 1; - } else { - return 0; - } -} - -static int GetHistoBits(int method, int use_palette, int width, int height) { - // Make tile size a function of encoding method (Range: 0 to 6). - int histo_bits = (use_palette ? 9 : 7) - method; - while (1) { - const int huff_image_size = VP8LSubSampleSize(width, histo_bits) * - VP8LSubSampleSize(height, histo_bits); - if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break; - ++histo_bits; - } - return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS : - (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits; -} - -static int GetTransformBits(int method, int histo_bits) { - const int max_transform_bits = (method < 4) ? 6 : (method > 4) ? 4 : 5; - return (histo_bits > max_transform_bits) ? max_transform_bits : histo_bits; -} - -static int AnalyzeAndInit(VP8LEncoder* const enc) { - const WebPPicture* const pic = enc->pic_; - const int width = pic->width; - const int height = pic->height; - const int pix_cnt = width * height; - const WebPConfig* const config = enc->config_; - const int method = config->method; - const int low_effort = (config->method == 0); - // we round the block size up, so we're guaranteed to have - // at max MAX_REFS_BLOCK_PER_IMAGE blocks used: - int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1; - assert(pic != NULL && pic->argb != NULL); - - enc->use_cross_color_ = 0; - enc->use_predict_ = 0; - enc->use_subtract_green_ = 0; - enc->use_palette_ = - AnalyzeAndCreatePalette(pic, low_effort, - enc->palette_, &enc->palette_size_); - - // TODO(jyrki): replace the decision to be based on an actual estimate - // of entropy, or even spatial variance of entropy. - enc->histo_bits_ = GetHistoBits(method, enc->use_palette_, - pic->width, pic->height); - enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_); - - if (low_effort) { - // AnalyzeEntropy is somewhat slow. - enc->use_predict_ = !enc->use_palette_; - enc->use_subtract_green_ = !enc->use_palette_; - enc->use_cross_color_ = 0; - } else { - int red_and_blue_always_zero; - EntropyIx min_entropy_ix; - if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, - enc->use_palette_, &min_entropy_ix, - &red_and_blue_always_zero)) { - return 0; - } - enc->use_palette_ = (min_entropy_ix == kPalette); - enc->use_subtract_green_ = - (min_entropy_ix == kSubGreen) || (min_entropy_ix == kSpatialSubGreen); - enc->use_predict_ = - (min_entropy_ix == kSpatial) || (min_entropy_ix == kSpatialSubGreen); - enc->use_cross_color_ = red_and_blue_always_zero ? 0 : enc->use_predict_; - } - - if (!VP8LHashChainInit(&enc->hash_chain_, pix_cnt)) return 0; - - // palette-friendly input typically uses less literals - // -> reduce block size a bit - if (enc->use_palette_) refs_block_size /= 2; - VP8LBackwardRefsInit(&enc->refs_[0], refs_block_size); - VP8LBackwardRefsInit(&enc->refs_[1], refs_block_size); - - return 1; -} - -// Returns false in case of memory error. -static int GetHuffBitLengthsAndCodes( - const VP8LHistogramSet* const histogram_image, - HuffmanTreeCode* const huffman_codes) { - int i, k; - int ok = 0; - uint64_t total_length_size = 0; - uint8_t* mem_buf = NULL; - const int histogram_image_size = histogram_image->size; - int max_num_symbols = 0; - uint8_t* buf_rle = NULL; - HuffmanTree* huff_tree = NULL; - - // Iterate over all histograms and get the aggregate number of codes used. - for (i = 0; i < histogram_image_size; ++i) { - const VP8LHistogram* const histo = histogram_image->histograms[i]; - HuffmanTreeCode* const codes = &huffman_codes[5 * i]; - for (k = 0; k < 5; ++k) { - const int num_symbols = - (k == 0) ? VP8LHistogramNumCodes(histo->palette_code_bits_) : - (k == 4) ? NUM_DISTANCE_CODES : 256; - codes[k].num_symbols = num_symbols; - total_length_size += num_symbols; - } - } - - // Allocate and Set Huffman codes. - { - uint16_t* codes; - uint8_t* lengths; - mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size, - sizeof(*lengths) + sizeof(*codes)); - if (mem_buf == NULL) goto End; - - codes = (uint16_t*)mem_buf; - lengths = (uint8_t*)&codes[total_length_size]; - for (i = 0; i < 5 * histogram_image_size; ++i) { - const int bit_length = huffman_codes[i].num_symbols; - huffman_codes[i].codes = codes; - huffman_codes[i].code_lengths = lengths; - codes += bit_length; - lengths += bit_length; - if (max_num_symbols < bit_length) { - max_num_symbols = bit_length; - } - } - } - - buf_rle = (uint8_t*)WebPSafeMalloc(1ULL, max_num_symbols); - huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * max_num_symbols, - sizeof(*huff_tree)); - if (buf_rle == NULL || huff_tree == NULL) goto End; - - // Create Huffman trees. - for (i = 0; i < histogram_image_size; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[5 * i]; - VP8LHistogram* const histo = histogram_image->histograms[i]; - VP8LCreateHuffmanTree(histo->literal_, 15, buf_rle, huff_tree, codes + 0); - VP8LCreateHuffmanTree(histo->red_, 15, buf_rle, huff_tree, codes + 1); - VP8LCreateHuffmanTree(histo->blue_, 15, buf_rle, huff_tree, codes + 2); - VP8LCreateHuffmanTree(histo->alpha_, 15, buf_rle, huff_tree, codes + 3); - VP8LCreateHuffmanTree(histo->distance_, 15, buf_rle, huff_tree, codes + 4); - } - ok = 1; - End: - WebPSafeFree(huff_tree); - WebPSafeFree(buf_rle); - if (!ok) { - WebPSafeFree(mem_buf); - memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes)); - } - return ok; -} - -static void StoreHuffmanTreeOfHuffmanTreeToBitMask( - VP8LBitWriter* const bw, const uint8_t* code_length_bitdepth) { - // RFC 1951 will calm you down if you are worried about this funny sequence. - // This sequence is tuned from that, but more weighted for lower symbol count, - // and more spiking histograms. - static const uint8_t kStorageOrder[CODE_LENGTH_CODES] = { - 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - }; - int i; - // Throw away trailing zeros: - int codes_to_store = CODE_LENGTH_CODES; - for (; codes_to_store > 4; --codes_to_store) { - if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) { - break; - } - } - VP8LPutBits(bw, codes_to_store - 4, 4); - for (i = 0; i < codes_to_store; ++i) { - VP8LPutBits(bw, code_length_bitdepth[kStorageOrder[i]], 3); - } -} - -static void ClearHuffmanTreeIfOnlyOneSymbol( - HuffmanTreeCode* const huffman_code) { - int k; - int count = 0; - for (k = 0; k < huffman_code->num_symbols; ++k) { - if (huffman_code->code_lengths[k] != 0) { - ++count; - if (count > 1) return; - } - } - for (k = 0; k < huffman_code->num_symbols; ++k) { - huffman_code->code_lengths[k] = 0; - huffman_code->codes[k] = 0; - } -} - -static void StoreHuffmanTreeToBitMask( - VP8LBitWriter* const bw, - const HuffmanTreeToken* const tokens, const int num_tokens, - const HuffmanTreeCode* const huffman_code) { - int i; - for (i = 0; i < num_tokens; ++i) { - const int ix = tokens[i].code; - const int extra_bits = tokens[i].extra_bits; - VP8LPutBits(bw, huffman_code->codes[ix], huffman_code->code_lengths[ix]); - switch (ix) { - case 16: - VP8LPutBits(bw, extra_bits, 2); - break; - case 17: - VP8LPutBits(bw, extra_bits, 3); - break; - case 18: - VP8LPutBits(bw, extra_bits, 7); - break; - } - } -} - -// 'huff_tree' and 'tokens' are pre-alloacted buffers. -static void StoreFullHuffmanCode(VP8LBitWriter* const bw, - HuffmanTree* const huff_tree, - HuffmanTreeToken* const tokens, - const HuffmanTreeCode* const tree) { - uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 }; - uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 }; - const int max_tokens = tree->num_symbols; - int num_tokens; - HuffmanTreeCode huffman_code; - huffman_code.num_symbols = CODE_LENGTH_CODES; - huffman_code.code_lengths = code_length_bitdepth; - huffman_code.codes = code_length_bitdepth_symbols; - - VP8LPutBits(bw, 0, 1); - num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens); - { - uint32_t histogram[CODE_LENGTH_CODES] = { 0 }; - uint8_t buf_rle[CODE_LENGTH_CODES] = { 0 }; - int i; - for (i = 0; i < num_tokens; ++i) { - ++histogram[tokens[i].code]; - } - - VP8LCreateHuffmanTree(histogram, 7, buf_rle, huff_tree, &huffman_code); - } - - StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth); - ClearHuffmanTreeIfOnlyOneSymbol(&huffman_code); - { - int trailing_zero_bits = 0; - int trimmed_length = num_tokens; - int write_trimmed_length; - int length; - int i = num_tokens; - while (i-- > 0) { - const int ix = tokens[i].code; - if (ix == 0 || ix == 17 || ix == 18) { - --trimmed_length; // discount trailing zeros - trailing_zero_bits += code_length_bitdepth[ix]; - if (ix == 17) { - trailing_zero_bits += 3; - } else if (ix == 18) { - trailing_zero_bits += 7; - } - } else { - break; - } - } - write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12); - length = write_trimmed_length ? trimmed_length : num_tokens; - VP8LPutBits(bw, write_trimmed_length, 1); - if (write_trimmed_length) { - const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1); - const int nbitpairs = (nbits == 0) ? 1 : (nbits + 1) / 2; - VP8LPutBits(bw, nbitpairs - 1, 3); - assert(trimmed_length >= 2); - VP8LPutBits(bw, trimmed_length - 2, nbitpairs * 2); - } - StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code); - } -} - -// 'huff_tree' and 'tokens' are pre-alloacted buffers. -static void StoreHuffmanCode(VP8LBitWriter* const bw, - HuffmanTree* const huff_tree, - HuffmanTreeToken* const tokens, - const HuffmanTreeCode* const huffman_code) { - int i; - int count = 0; - int symbols[2] = { 0, 0 }; - const int kMaxBits = 8; - const int kMaxSymbol = 1 << kMaxBits; - - // Check whether it's a small tree. - for (i = 0; i < huffman_code->num_symbols && count < 3; ++i) { - if (huffman_code->code_lengths[i] != 0) { - if (count < 2) symbols[count] = i; - ++count; - } - } - - if (count == 0) { // emit minimal tree for empty cases - // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0 - VP8LPutBits(bw, 0x01, 4); - } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) { - VP8LPutBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols. - VP8LPutBits(bw, count - 1, 1); - if (symbols[0] <= 1) { - VP8LPutBits(bw, 0, 1); // Code bit for small (1 bit) symbol value. - VP8LPutBits(bw, symbols[0], 1); - } else { - VP8LPutBits(bw, 1, 1); - VP8LPutBits(bw, symbols[0], 8); - } - if (count == 2) { - VP8LPutBits(bw, symbols[1], 8); - } - } else { - StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code); - } -} - -static WEBP_INLINE void WriteHuffmanCode(VP8LBitWriter* const bw, - const HuffmanTreeCode* const code, - int code_index) { - const int depth = code->code_lengths[code_index]; - const int symbol = code->codes[code_index]; - VP8LPutBits(bw, symbol, depth); -} - -static WEBP_INLINE void WriteHuffmanCodeWithExtraBits( - VP8LBitWriter* const bw, - const HuffmanTreeCode* const code, - int code_index, - int bits, - int n_bits) { - const int depth = code->code_lengths[code_index]; - const int symbol = code->codes[code_index]; - VP8LPutBits(bw, (bits << depth) | symbol, depth + n_bits); -} - -static WebPEncodingError StoreImageToBitMask( - VP8LBitWriter* const bw, int width, int histo_bits, - VP8LBackwardRefs* const refs, - const uint16_t* histogram_symbols, - const HuffmanTreeCode* const huffman_codes) { - const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1; - const int tile_mask = (histo_bits == 0) ? 0 : -(1 << histo_bits); - // x and y trace the position in the image. - int x = 0; - int y = 0; - int tile_x = x & tile_mask; - int tile_y = y & tile_mask; - int histogram_ix = histogram_symbols[0]; - const HuffmanTreeCode* codes = huffman_codes + 5 * histogram_ix; - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - while (VP8LRefsCursorOk(&c)) { - const PixOrCopy* const v = c.cur_pos; - if ((tile_x != (x & tile_mask)) || (tile_y != (y & tile_mask))) { - tile_x = x & tile_mask; - tile_y = y & tile_mask; - histogram_ix = histogram_symbols[(y >> histo_bits) * histo_xsize + - (x >> histo_bits)]; - codes = huffman_codes + 5 * histogram_ix; - } - if (PixOrCopyIsLiteral(v)) { - static const int order[] = { 1, 2, 0, 3 }; - int k; - for (k = 0; k < 4; ++k) { - const int code = PixOrCopyLiteral(v, order[k]); - WriteHuffmanCode(bw, codes + k, code); - } - } else if (PixOrCopyIsCacheIdx(v)) { - const int code = PixOrCopyCacheIdx(v); - const int literal_ix = 256 + NUM_LENGTH_CODES + code; - WriteHuffmanCode(bw, codes, literal_ix); - } else { - int bits, n_bits; - int code; - - const int distance = PixOrCopyDistance(v); - VP8LPrefixEncode(v->len, &code, &n_bits, &bits); - WriteHuffmanCodeWithExtraBits(bw, codes, 256 + code, bits, n_bits); - - // Don't write the distance with the extra bits code since - // the distance can be up to 18 bits of extra bits, and the prefix - // 15 bits, totaling to 33, and our PutBits only supports up to 32 bits. - // TODO(jyrki): optimize this further. - VP8LPrefixEncode(distance, &code, &n_bits, &bits); - WriteHuffmanCode(bw, codes + 4, code); - VP8LPutBits(bw, bits, n_bits); - } - x += PixOrCopyLength(v); - while (x >= width) { - x -= width; - ++y; - } - VP8LRefsCursorNext(&c); - } - return bw->error_ ? VP8_ENC_ERROR_OUT_OF_MEMORY : VP8_ENC_OK; -} - -// Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31 -static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw, - const uint32_t* const argb, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2], - int width, int height, - int quality) { - int i; - int max_tokens = 0; - WebPEncodingError err = VP8_ENC_OK; - VP8LBackwardRefs* refs; - HuffmanTreeToken* tokens = NULL; - HuffmanTreeCode huffman_codes[5] = { { 0, NULL, NULL } }; - const uint16_t histogram_symbols[1] = { 0 }; // only one tree, one symbol - int cache_bits = 0; - VP8LHistogramSet* histogram_image = NULL; - HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc( - 3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree)); - if (huff_tree == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Calculate backward references from ARGB image. - if (VP8LHashChainFill(hash_chain, quality, argb, width, height) == 0) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - refs = VP8LGetBackwardReferences(width, height, argb, quality, 0, &cache_bits, - hash_chain, refs_array); - if (refs == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - histogram_image = VP8LAllocateHistogramSet(1, cache_bits); - if (histogram_image == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Build histogram image and symbols from backward references. - VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]); - - // Create Huffman bit lengths and codes for each histogram image. - assert(histogram_image->size == 1); - if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // No color cache, no Huffman image. - VP8LPutBits(bw, 0, 1); - - // Find maximum number of symbols for the huffman tree-set. - for (i = 0; i < 5; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[i]; - if (max_tokens < codes->num_symbols) { - max_tokens = codes->num_symbols; - } - } - - tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens)); - if (tokens == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Store Huffman codes. - for (i = 0; i < 5; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[i]; - StoreHuffmanCode(bw, huff_tree, tokens, codes); - ClearHuffmanTreeIfOnlyOneSymbol(codes); - } - - // Store actual literals. - err = StoreImageToBitMask(bw, width, 0, refs, histogram_symbols, - huffman_codes); - - Error: - WebPSafeFree(tokens); - WebPSafeFree(huff_tree); - VP8LFreeHistogramSet(histogram_image); - WebPSafeFree(huffman_codes[0].codes); - return err; -} - -static WebPEncodingError EncodeImageInternal(VP8LBitWriter* const bw, - const uint32_t* const argb, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2], - int width, int height, int quality, - int low_effort, - int use_cache, int* cache_bits, - int histogram_bits, - size_t init_byte_position, - int* const hdr_size, - int* const data_size) { - WebPEncodingError err = VP8_ENC_OK; - const uint32_t histogram_image_xysize = - VP8LSubSampleSize(width, histogram_bits) * - VP8LSubSampleSize(height, histogram_bits); - VP8LHistogramSet* histogram_image = NULL; - VP8LHistogramSet* tmp_histos = NULL; - int histogram_image_size = 0; - size_t bit_array_size = 0; - HuffmanTree* huff_tree = NULL; - HuffmanTreeToken* tokens = NULL; - HuffmanTreeCode* huffman_codes = NULL; - VP8LBackwardRefs refs; - VP8LBackwardRefs* best_refs; - uint16_t* const histogram_symbols = - (uint16_t*)WebPSafeMalloc(histogram_image_xysize, - sizeof(*histogram_symbols)); - assert(histogram_bits >= MIN_HUFFMAN_BITS); - assert(histogram_bits <= MAX_HUFFMAN_BITS); - assert(hdr_size != NULL); - assert(data_size != NULL); - - VP8LBackwardRefsInit(&refs, refs_array[0].block_size_); - if (histogram_symbols == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - *cache_bits = use_cache ? MAX_COLOR_CACHE_BITS : 0; - // 'best_refs' is the reference to the best backward refs and points to one - // of refs_array[0] or refs_array[1]. - // Calculate backward references from ARGB image. - if (VP8LHashChainFill(hash_chain, quality, argb, width, height) == 0) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - best_refs = VP8LGetBackwardReferences(width, height, argb, quality, - low_effort, cache_bits, hash_chain, - refs_array); - if (best_refs == NULL || !VP8LBackwardRefsCopy(best_refs, &refs)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - histogram_image = - VP8LAllocateHistogramSet(histogram_image_xysize, *cache_bits); - tmp_histos = VP8LAllocateHistogramSet(2, *cache_bits); - if (histogram_image == NULL || tmp_histos == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Build histogram image and symbols from backward references. - if (!VP8LGetHistoImageSymbols(width, height, &refs, quality, low_effort, - histogram_bits, *cache_bits, histogram_image, - tmp_histos, histogram_symbols)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - // Create Huffman bit lengths and codes for each histogram image. - histogram_image_size = histogram_image->size; - bit_array_size = 5 * histogram_image_size; - huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size, - sizeof(*huffman_codes)); - // Note: some histogram_image entries may point to tmp_histos[], so the latter - // need to outlive the following call to GetHuffBitLengthsAndCodes(). - if (huffman_codes == NULL || - !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - // Free combined histograms. - VP8LFreeHistogramSet(histogram_image); - histogram_image = NULL; - - // Free scratch histograms. - VP8LFreeHistogramSet(tmp_histos); - tmp_histos = NULL; - - // Color Cache parameters. - if (*cache_bits > 0) { - VP8LPutBits(bw, 1, 1); - VP8LPutBits(bw, *cache_bits, 4); - } else { - VP8LPutBits(bw, 0, 1); - } - - // Huffman image + meta huffman. - { - const int write_histogram_image = (histogram_image_size > 1); - VP8LPutBits(bw, write_histogram_image, 1); - if (write_histogram_image) { - uint32_t* const histogram_argb = - (uint32_t*)WebPSafeMalloc(histogram_image_xysize, - sizeof(*histogram_argb)); - int max_index = 0; - uint32_t i; - if (histogram_argb == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - for (i = 0; i < histogram_image_xysize; ++i) { - const int symbol_index = histogram_symbols[i] & 0xffff; - histogram_argb[i] = (symbol_index << 8); - if (symbol_index >= max_index) { - max_index = symbol_index + 1; - } - } - histogram_image_size = max_index; - - VP8LPutBits(bw, histogram_bits - 2, 3); - err = EncodeImageNoHuffman(bw, histogram_argb, hash_chain, refs_array, - VP8LSubSampleSize(width, histogram_bits), - VP8LSubSampleSize(height, histogram_bits), - quality); - WebPSafeFree(histogram_argb); - if (err != VP8_ENC_OK) goto Error; - } - } - - // Store Huffman codes. - { - int i; - int max_tokens = 0; - huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * CODE_LENGTH_CODES, - sizeof(*huff_tree)); - if (huff_tree == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - // Find maximum number of symbols for the huffman tree-set. - for (i = 0; i < 5 * histogram_image_size; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[i]; - if (max_tokens < codes->num_symbols) { - max_tokens = codes->num_symbols; - } - } - tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, - sizeof(*tokens)); - if (tokens == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - for (i = 0; i < 5 * histogram_image_size; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[i]; - StoreHuffmanCode(bw, huff_tree, tokens, codes); - ClearHuffmanTreeIfOnlyOneSymbol(codes); - } - } - - *hdr_size = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position); - // Store actual literals. - err = StoreImageToBitMask(bw, width, histogram_bits, &refs, - histogram_symbols, huffman_codes); - *data_size = - (int)(VP8LBitWriterNumBytes(bw) - init_byte_position - *hdr_size); - - Error: - WebPSafeFree(tokens); - WebPSafeFree(huff_tree); - VP8LFreeHistogramSet(histogram_image); - VP8LFreeHistogramSet(tmp_histos); - VP8LBackwardRefsClear(&refs); - if (huffman_codes != NULL) { - WebPSafeFree(huffman_codes->codes); - WebPSafeFree(huffman_codes); - } - WebPSafeFree(histogram_symbols); - return err; -} - -// ----------------------------------------------------------------------------- -// Transforms - -static void ApplySubtractGreen(VP8LEncoder* const enc, int width, int height, - VP8LBitWriter* const bw) { - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, SUBTRACT_GREEN, 2); - VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height); -} - -static WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc, - int width, int height, - int quality, int low_effort, - int used_subtract_green, - VP8LBitWriter* const bw) { - const int pred_bits = enc->transform_bits_; - const int transform_width = VP8LSubSampleSize(width, pred_bits); - const int transform_height = VP8LSubSampleSize(height, pred_bits); - // we disable near-lossless quantization if palette is used. - const int near_lossless_strength = enc->use_palette_ ? 100 - : enc->config_->near_lossless; - - VP8LResidualImage(width, height, pred_bits, low_effort, enc->argb_, - enc->argb_scratch_, enc->transform_data_, - near_lossless_strength, enc->config_->exact, - used_subtract_green); - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2); - assert(pred_bits >= 2); - VP8LPutBits(bw, pred_bits - 2, 3); - return EncodeImageNoHuffman(bw, enc->transform_data_, - (VP8LHashChain*)&enc->hash_chain_, - (VP8LBackwardRefs*)enc->refs_, // cast const away - transform_width, transform_height, - quality); -} - -static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc, - int width, int height, - int quality, - VP8LBitWriter* const bw) { - const int ccolor_transform_bits = enc->transform_bits_; - const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits); - const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits); - - VP8LColorSpaceTransform(width, height, ccolor_transform_bits, quality, - enc->argb_, enc->transform_data_); - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, CROSS_COLOR_TRANSFORM, 2); - assert(ccolor_transform_bits >= 2); - VP8LPutBits(bw, ccolor_transform_bits - 2, 3); - return EncodeImageNoHuffman(bw, enc->transform_data_, - (VP8LHashChain*)&enc->hash_chain_, - (VP8LBackwardRefs*)enc->refs_, // cast const away - transform_width, transform_height, - quality); -} - -// ----------------------------------------------------------------------------- - -static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic, - size_t riff_size, size_t vp8l_size) { - uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = { - 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P', - 'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE, - }; - PutLE32(riff + TAG_SIZE, (uint32_t)riff_size); - PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size); - if (!pic->writer(riff, sizeof(riff), pic)) { - return VP8_ENC_ERROR_BAD_WRITE; - } - return VP8_ENC_OK; -} - -static int WriteImageSize(const WebPPicture* const pic, - VP8LBitWriter* const bw) { - const int width = pic->width - 1; - const int height = pic->height - 1; - assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION); - - VP8LPutBits(bw, width, VP8L_IMAGE_SIZE_BITS); - VP8LPutBits(bw, height, VP8L_IMAGE_SIZE_BITS); - return !bw->error_; -} - -static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) { - VP8LPutBits(bw, has_alpha, 1); - VP8LPutBits(bw, VP8L_VERSION, VP8L_VERSION_BITS); - return !bw->error_; -} - -static WebPEncodingError WriteImage(const WebPPicture* const pic, - VP8LBitWriter* const bw, - size_t* const coded_size) { - WebPEncodingError err = VP8_ENC_OK; - const uint8_t* const webpll_data = VP8LBitWriterFinish(bw); - const size_t webpll_size = VP8LBitWriterNumBytes(bw); - const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size; - const size_t pad = vp8l_size & 1; - const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad; - - err = WriteRiffHeader(pic, riff_size, vp8l_size); - if (err != VP8_ENC_OK) goto Error; - - if (!pic->writer(webpll_data, webpll_size, pic)) { - err = VP8_ENC_ERROR_BAD_WRITE; - goto Error; - } - - if (pad) { - const uint8_t pad_byte[1] = { 0 }; - if (!pic->writer(pad_byte, 1, pic)) { - err = VP8_ENC_ERROR_BAD_WRITE; - goto Error; - } - } - *coded_size = CHUNK_HEADER_SIZE + riff_size; - return VP8_ENC_OK; - - Error: - return err; -} - -// ----------------------------------------------------------------------------- - -static void ClearTransformBuffer(VP8LEncoder* const enc) { - WebPSafeFree(enc->transform_mem_); - enc->transform_mem_ = NULL; - enc->transform_mem_size_ = 0; -} - -// Allocates the memory for argb (W x H) buffer, 2 rows of context for -// prediction and transform data. -// Flags influencing the memory allocated: -// enc->transform_bits_ -// enc->use_predict_, enc->use_cross_color_ -static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc, - int width, int height) { - WebPEncodingError err = VP8_ENC_OK; - const uint64_t image_size = width * height; - // VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra - // pixel in each, plus 2 regular scanlines of bytes. - // TODO(skal): Clean up by using arithmetic in bytes instead of words. - const uint64_t argb_scratch_size = - enc->use_predict_ - ? (width + 1) * 2 + - (width * 2 + sizeof(uint32_t) - 1) / sizeof(uint32_t) - : 0; - const uint64_t transform_data_size = - (enc->use_predict_ || enc->use_cross_color_) - ? VP8LSubSampleSize(width, enc->transform_bits_) * - VP8LSubSampleSize(height, enc->transform_bits_) - : 0; - const uint64_t max_alignment_in_words = - (WEBP_ALIGN_CST + sizeof(uint32_t) - 1) / sizeof(uint32_t); - const uint64_t mem_size = - image_size + max_alignment_in_words + - argb_scratch_size + max_alignment_in_words + - transform_data_size; - uint32_t* mem = enc->transform_mem_; - if (mem == NULL || mem_size > enc->transform_mem_size_) { - ClearTransformBuffer(enc); - mem = (uint32_t*)WebPSafeMalloc(mem_size, sizeof(*mem)); - if (mem == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - enc->transform_mem_ = mem; - enc->transform_mem_size_ = (size_t)mem_size; - } - enc->argb_ = mem; - mem = (uint32_t*)WEBP_ALIGN(mem + image_size); - enc->argb_scratch_ = mem; - mem = (uint32_t*)WEBP_ALIGN(mem + argb_scratch_size); - enc->transform_data_ = mem; - - enc->current_width_ = width; - Error: - return err; -} - -static WebPEncodingError MakeInputImageCopy(VP8LEncoder* const enc) { - WebPEncodingError err = VP8_ENC_OK; - const WebPPicture* const picture = enc->pic_; - const int width = picture->width; - const int height = picture->height; - int y; - err = AllocateTransformBuffer(enc, width, height); - if (err != VP8_ENC_OK) return err; - for (y = 0; y < height; ++y) { - memcpy(enc->argb_ + y * width, - picture->argb + y * picture->argb_stride, - width * sizeof(*enc->argb_)); - } - assert(enc->current_width_ == width); - return VP8_ENC_OK; -} - -// ----------------------------------------------------------------------------- - -static int SearchColor(const uint32_t sorted[], uint32_t color, int hi) { - int low = 0; - if (sorted[low] == color) return low; // loop invariant: sorted[low] != color - while (1) { - const int mid = (low + hi) >> 1; - if (sorted[mid] == color) { - return mid; - } else if (sorted[mid] < color) { - low = mid; - } else { - hi = mid; - } - } -} - -// Sort palette in increasing order and prepare an inverse mapping array. -static void PrepareMapToPalette(const uint32_t palette[], int num_colors, - uint32_t sorted[], int idx_map[]) { - int i; - memcpy(sorted, palette, num_colors * sizeof(*sorted)); - qsort(sorted, num_colors, sizeof(*sorted), PaletteCompareColorsForQsort); - for (i = 0; i < num_colors; ++i) { - idx_map[SearchColor(sorted, palette[i], num_colors)] = i; - } -} - -static void MapToPalette(const uint32_t sorted_palette[], int num_colors, - uint32_t* const last_pix, int* const last_idx, - const int idx_map[], - const uint32_t* src, uint8_t* dst, int width) { - int x; - int prev_idx = *last_idx; - uint32_t prev_pix = *last_pix; - for (x = 0; x < width; ++x) { - const uint32_t pix = src[x]; - if (pix != prev_pix) { - prev_idx = idx_map[SearchColor(sorted_palette, pix, num_colors)]; - prev_pix = pix; - } - dst[x] = prev_idx; - } - *last_idx = prev_idx; - *last_pix = prev_pix; -} - -// Remap argb values in src[] to packed palettes entries in dst[] -// using 'row' as a temporary buffer of size 'width'. -// We assume that all src[] values have a corresponding entry in the palette. -// Note: src[] can be the same as dst[] -static WebPEncodingError ApplyPalette(const uint32_t* src, uint32_t src_stride, - uint32_t* dst, uint32_t dst_stride, - const uint32_t* palette, int palette_size, - int width, int height, int xbits) { - // TODO(skal): this tmp buffer is not needed if VP8LBundleColorMap() can be - // made to work in-place. - uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row)); - int i, x, y; - int use_LUT = 1; - - if (tmp_row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY; - for (i = 0; i < palette_size; ++i) { - if ((palette[i] & 0xffff00ffu) != 0) { - use_LUT = 0; - break; - } - } - - if (use_LUT) { - uint8_t inv_palette[MAX_PALETTE_SIZE] = { 0 }; - for (i = 0; i < palette_size; ++i) { - const int color = (palette[i] >> 8) & 0xff; - inv_palette[color] = i; - } - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - const int color = (src[x] >> 8) & 0xff; - tmp_row[x] = inv_palette[color]; - } - VP8LBundleColorMap(tmp_row, width, xbits, dst); - src += src_stride; - dst += dst_stride; - } - } else { - // Use 1 pixel cache for ARGB pixels. - uint32_t last_pix; - int last_idx; - uint32_t sorted[MAX_PALETTE_SIZE]; - int idx_map[MAX_PALETTE_SIZE]; - PrepareMapToPalette(palette, palette_size, sorted, idx_map); - last_pix = palette[0]; - last_idx = 0; - for (y = 0; y < height; ++y) { - MapToPalette(sorted, palette_size, &last_pix, &last_idx, - idx_map, src, tmp_row, width); - VP8LBundleColorMap(tmp_row, width, xbits, dst); - src += src_stride; - dst += dst_stride; - } - } - WebPSafeFree(tmp_row); - return VP8_ENC_OK; -} - -// Note: Expects "enc->palette_" to be set properly. -static WebPEncodingError MapImageFromPalette(VP8LEncoder* const enc, - int in_place) { - WebPEncodingError err = VP8_ENC_OK; - const WebPPicture* const pic = enc->pic_; - const int width = pic->width; - const int height = pic->height; - const uint32_t* const palette = enc->palette_; - const uint32_t* src = in_place ? enc->argb_ : pic->argb; - const int src_stride = in_place ? enc->current_width_ : pic->argb_stride; - const int palette_size = enc->palette_size_; - int xbits; - - // Replace each input pixel by corresponding palette index. - // This is done line by line. - if (palette_size <= 4) { - xbits = (palette_size <= 2) ? 3 : 2; - } else { - xbits = (palette_size <= 16) ? 1 : 0; - } - - err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height); - if (err != VP8_ENC_OK) return err; - - err = ApplyPalette(src, src_stride, - enc->argb_, enc->current_width_, - palette, palette_size, width, height, xbits); - return err; -} - -// Save palette_[] to bitstream. -static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, - VP8LEncoder* const enc) { - int i; - uint32_t tmp_palette[MAX_PALETTE_SIZE]; - const int palette_size = enc->palette_size_; - const uint32_t* const palette = enc->palette_; - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, COLOR_INDEXING_TRANSFORM, 2); - assert(palette_size >= 1 && palette_size <= MAX_PALETTE_SIZE); - VP8LPutBits(bw, palette_size - 1, 8); - for (i = palette_size - 1; i >= 1; --i) { - tmp_palette[i] = VP8LSubPixels(palette[i], palette[i - 1]); - } - tmp_palette[0] = palette[0]; - return EncodeImageNoHuffman(bw, tmp_palette, &enc->hash_chain_, enc->refs_, - palette_size, 1, 20 /* quality */); -} - -#ifdef WEBP_EXPERIMENTAL_FEATURES - -static WebPEncodingError EncodeDeltaPalettePredictorImage( - VP8LBitWriter* const bw, VP8LEncoder* const enc, int quality) { - const WebPPicture* const pic = enc->pic_; - const int width = pic->width; - const int height = pic->height; - - const int pred_bits = 5; - const int transform_width = VP8LSubSampleSize(width, pred_bits); - const int transform_height = VP8LSubSampleSize(height, pred_bits); - const int pred = 7; // default is Predictor7 (Top/Left Average) - const int tiles_per_row = VP8LSubSampleSize(width, pred_bits); - const int tiles_per_col = VP8LSubSampleSize(height, pred_bits); - uint32_t* predictors; - int tile_x, tile_y; - WebPEncodingError err = VP8_ENC_OK; - - predictors = (uint32_t*)WebPSafeMalloc(tiles_per_col * tiles_per_row, - sizeof(*predictors)); - if (predictors == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY; - - for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) { - for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) { - predictors[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8); - } - } - - VP8LPutBits(bw, TRANSFORM_PRESENT, 1); - VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2); - VP8LPutBits(bw, pred_bits - 2, 3); - err = EncodeImageNoHuffman(bw, predictors, &enc->hash_chain_, - (VP8LBackwardRefs*)enc->refs_, // cast const away - transform_width, transform_height, - quality); - WebPSafeFree(predictors); - return err; -} - -#endif // WEBP_EXPERIMENTAL_FEATURES - -// ----------------------------------------------------------------------------- -// VP8LEncoder - -static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config, - const WebPPicture* const picture) { - VP8LEncoder* const enc = (VP8LEncoder*)WebPSafeCalloc(1ULL, sizeof(*enc)); - if (enc == NULL) { - WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); - return NULL; - } - enc->config_ = config; - enc->pic_ = picture; - - VP8LEncDspInit(); - - return enc; -} - -static void VP8LEncoderDelete(VP8LEncoder* enc) { - if (enc != NULL) { - VP8LHashChainClear(&enc->hash_chain_); - VP8LBackwardRefsClear(&enc->refs_[0]); - VP8LBackwardRefsClear(&enc->refs_[1]); - ClearTransformBuffer(enc); - WebPSafeFree(enc); - } -} - -// ----------------------------------------------------------------------------- -// Main call - -WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, - const WebPPicture* const picture, - VP8LBitWriter* const bw, int use_cache) { - WebPEncodingError err = VP8_ENC_OK; - const int quality = (int)config->quality; - const int low_effort = (config->method == 0); - const int width = picture->width; - const int height = picture->height; - VP8LEncoder* const enc = VP8LEncoderNew(config, picture); - const size_t byte_position = VP8LBitWriterNumBytes(bw); - int use_near_lossless = 0; - int hdr_size = 0; - int data_size = 0; - int use_delta_palettization = 0; - - if (enc == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // --------------------------------------------------------------------------- - // Analyze image (entropy, num_palettes etc) - - if (!AnalyzeAndInit(enc)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - // Apply near-lossless preprocessing. - use_near_lossless = - (config->near_lossless < 100) && !enc->use_palette_ && !enc->use_predict_; - if (use_near_lossless) { - if (!VP8ApplyNearLossless(width, height, picture->argb, - config->near_lossless)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - } - -#ifdef WEBP_EXPERIMENTAL_FEATURES - if (config->delta_palettization) { - enc->use_predict_ = 1; - enc->use_cross_color_ = 0; - enc->use_subtract_green_ = 0; - enc->use_palette_ = 1; - err = MakeInputImageCopy(enc); - if (err != VP8_ENC_OK) goto Error; - err = WebPSearchOptimalDeltaPalette(enc); - if (err != VP8_ENC_OK) goto Error; - if (enc->use_palette_) { - err = AllocateTransformBuffer(enc, width, height); - if (err != VP8_ENC_OK) goto Error; - err = EncodeDeltaPalettePredictorImage(bw, enc, quality); - if (err != VP8_ENC_OK) goto Error; - use_delta_palettization = 1; - } - } -#endif // WEBP_EXPERIMENTAL_FEATURES - - // Encode palette - if (enc->use_palette_) { - err = EncodePalette(bw, enc); - if (err != VP8_ENC_OK) goto Error; - err = MapImageFromPalette(enc, use_delta_palettization); - if (err != VP8_ENC_OK) goto Error; - } - if (!use_delta_palettization) { - // In case image is not packed. - if (enc->argb_ == NULL) { - err = MakeInputImageCopy(enc); - if (err != VP8_ENC_OK) goto Error; - } - - // ------------------------------------------------------------------------- - // Apply transforms and write transform data. - - if (enc->use_subtract_green_) { - ApplySubtractGreen(enc, enc->current_width_, height, bw); - } - - if (enc->use_predict_) { - err = ApplyPredictFilter(enc, enc->current_width_, height, quality, - low_effort, enc->use_subtract_green_, bw); - if (err != VP8_ENC_OK) goto Error; - } - - if (enc->use_cross_color_) { - err = ApplyCrossColorFilter(enc, enc->current_width_, - height, quality, bw); - if (err != VP8_ENC_OK) goto Error; - } - } - - VP8LPutBits(bw, !TRANSFORM_PRESENT, 1); // No more transforms. - - // --------------------------------------------------------------------------- - // Encode and write the transformed image. - err = EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_, - enc->current_width_, height, quality, low_effort, - use_cache, &enc->cache_bits_, enc->histo_bits_, - byte_position, &hdr_size, &data_size); - if (err != VP8_ENC_OK) goto Error; - - if (picture->stats != NULL) { - WebPAuxStats* const stats = picture->stats; - stats->lossless_features = 0; - if (enc->use_predict_) stats->lossless_features |= 1; - if (enc->use_cross_color_) stats->lossless_features |= 2; - if (enc->use_subtract_green_) stats->lossless_features |= 4; - if (enc->use_palette_) stats->lossless_features |= 8; - stats->histogram_bits = enc->histo_bits_; - stats->transform_bits = enc->transform_bits_; - stats->cache_bits = enc->cache_bits_; - stats->palette_size = enc->palette_size_; - stats->lossless_size = (int)(VP8LBitWriterNumBytes(bw) - byte_position); - stats->lossless_hdr_size = hdr_size; - stats->lossless_data_size = data_size; - } - - Error: - VP8LEncoderDelete(enc); - return err; -} - -int VP8LEncodeImage(const WebPConfig* const config, - const WebPPicture* const picture) { - int width, height; - int has_alpha; - size_t coded_size; - int percent = 0; - int initial_size; - WebPEncodingError err = VP8_ENC_OK; - VP8LBitWriter bw; - - if (picture == NULL) return 0; - - if (config == NULL || picture->argb == NULL) { - err = VP8_ENC_ERROR_NULL_PARAMETER; - WebPEncodingSetError(picture, err); - return 0; - } - - width = picture->width; - height = picture->height; - // Initialize BitWriter with size corresponding to 16 bpp to photo images and - // 8 bpp for graphical images. - initial_size = (config->image_hint == WEBP_HINT_GRAPH) ? - width * height : width * height * 2; - if (!VP8LBitWriterInit(&bw, initial_size)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - if (!WebPReportProgress(picture, 1, &percent)) { - UserAbort: - err = VP8_ENC_ERROR_USER_ABORT; - goto Error; - } - // Reset stats (for pure lossless coding) - if (picture->stats != NULL) { - WebPAuxStats* const stats = picture->stats; - memset(stats, 0, sizeof(*stats)); - stats->PSNR[0] = 99.f; - stats->PSNR[1] = 99.f; - stats->PSNR[2] = 99.f; - stats->PSNR[3] = 99.f; - stats->PSNR[4] = 99.f; - } - - // Write image size. - if (!WriteImageSize(picture, &bw)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - has_alpha = WebPPictureHasTransparency(picture); - // Write the non-trivial Alpha flag and lossless version. - if (!WriteRealAlphaAndVersion(&bw, has_alpha)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - - if (!WebPReportProgress(picture, 5, &percent)) goto UserAbort; - - // Encode main image stream. - err = VP8LEncodeStream(config, picture, &bw, 1 /*use_cache*/); - if (err != VP8_ENC_OK) goto Error; - - // TODO(skal): have a fine-grained progress report in VP8LEncodeStream(). - if (!WebPReportProgress(picture, 90, &percent)) goto UserAbort; - - // Finish the RIFF chunk. - err = WriteImage(picture, &bw, &coded_size); - if (err != VP8_ENC_OK) goto Error; - - if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort; - - // Save size. - if (picture->stats != NULL) { - picture->stats->coded_size += (int)coded_size; - picture->stats->lossless_size = (int)coded_size; - } - - if (picture->extra_info != NULL) { - const int mb_w = (width + 15) >> 4; - const int mb_h = (height + 15) >> 4; - memset(picture->extra_info, 0, mb_w * mb_h * sizeof(*picture->extra_info)); - } - - Error: - if (bw.error_) err = VP8_ENC_ERROR_OUT_OF_MEMORY; - VP8LBitWriterWipeOut(&bw); - if (err != VP8_ENC_OK) { - WebPEncodingSetError(picture, err); - return 0; - } - return 1; -} - -//------------------------------------------------------------------------------ diff --git a/drivers/webp/enc/vp8li.h b/drivers/webp/enc/vp8li.h deleted file mode 100644 index 8e6b360d81..0000000000 --- a/drivers/webp/enc/vp8li.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Lossless encoder: internal header. -// -// Author: Vikas Arora (vikaas.arora@gmail.com) - -#ifndef WEBP_ENC_VP8LI_H_ -#define WEBP_ENC_VP8LI_H_ - -#include "./backward_references.h" -#include "./histogram.h" -#include "../utils/bit_writer.h" -#include "webp/encode.h" -#include "webp/format_constants.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - const WebPConfig* config_; // user configuration and parameters - const WebPPicture* pic_; // input picture. - - uint32_t* argb_; // Transformed argb image data. - uint32_t* argb_scratch_; // Scratch memory for argb rows - // (used for prediction). - uint32_t* transform_data_; // Scratch memory for transform data. - uint32_t* transform_mem_; // Currently allocated memory. - size_t transform_mem_size_; // Currently allocated memory size. - - int current_width_; // Corresponds to packed image width. - - // Encoding parameters derived from quality parameter. - int histo_bits_; - int transform_bits_; - int cache_bits_; // If equal to 0, don't use color cache. - - // Encoding parameters derived from image characteristics. - int use_cross_color_; - int use_subtract_green_; - int use_predict_; - int use_palette_; - int palette_size_; - uint32_t palette_[MAX_PALETTE_SIZE]; - - // Some 'scratch' (potentially large) objects. - struct VP8LBackwardRefs refs_[2]; // Backward Refs array corresponding to - // LZ77 & RLE coding. - VP8LHashChain hash_chain_; // HashChain data for constructing - // backward references. -} VP8LEncoder; - -//------------------------------------------------------------------------------ -// internal functions. Not public. - -// Encodes the picture. -// Returns 0 if config or picture is NULL or picture doesn't have valid argb -// input. -int VP8LEncodeImage(const WebPConfig* const config, - const WebPPicture* const picture); - -// Encodes the main image stream using the supplied bit writer. -// If 'use_cache' is false, disables the use of color cache. -WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, - const WebPPicture* const picture, - VP8LBitWriter* const bw, int use_cache); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_ENC_VP8LI_H_ */ diff --git a/drivers/webp/extras.h b/drivers/webp/extras.h deleted file mode 100644 index 1c24be2e0c..0000000000 --- a/drivers/webp/extras.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// - -#ifndef WEBP_WEBP_EXTRAS_H_ -#define WEBP_WEBP_EXTRAS_H_ - -#include "./types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "./encode.h" - -#define WEBP_EXTRAS_ABI_VERSION 0x0000 // MAJOR(8b) + MINOR(8b) - -//------------------------------------------------------------------------------ - -// Returns the version number of the extras library, packed in hexadecimal using -// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetExtrasVersion(void); - -//------------------------------------------------------------------------------ -// Ad-hoc colorspace importers. - -// Import luma sample (gray scale image) into 'picture'. The 'picture' -// width and height must be set prior to calling this function. -WEBP_EXTERN(int) WebPImportGray(const uint8_t* gray, WebPPicture* picture); - -// Import rgb sample in RGB565 packed format into 'picture'. The 'picture' -// width and height must be set prior to calling this function. -WEBP_EXTERN(int) WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic); - -// Import rgb sample in RGB4444 packed format into 'picture'. The 'picture' -// width and height must be set prior to calling this function. -WEBP_EXTERN(int) WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_WEBP_EXTRAS_H_ */ diff --git a/drivers/webp/image_loader_webp.cpp b/drivers/webp/image_loader_webp.cpp deleted file mode 100644 index 68bb857293..0000000000 --- a/drivers/webp/image_loader_webp.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/*************************************************************************/ -/* image_loader_webp.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "image_loader_webp.h" - -#include "print_string.h" -#include "os/os.h" -#include "drivers/webp/decode.h" -#include "drivers/webp/encode.h" -#include "io/marshalls.h" -#include <stdlib.h> - -static DVector<uint8_t> _webp_lossy_pack(const Image& p_image,float p_quality) { - - ERR_FAIL_COND_V(p_image.empty(),DVector<uint8_t>()); - - Image img=p_image; - if (img.detect_alpha()) - img.convert(Image::FORMAT_RGBA); - else - img.convert(Image::FORMAT_RGB); - - Size2 s(img.get_width(),img.get_height()); - DVector<uint8_t> data = img.get_data(); - DVector<uint8_t>::Read r = data.read(); - - uint8_t *dst_buff=NULL; - size_t dst_size=0; - if (img.get_format()==Image::FORMAT_RGB) { - - dst_size = WebPEncodeRGB(r.ptr(),s.width,s.height,3*s.width,CLAMP(p_quality*100.0,0,100.0),&dst_buff); - } else { - dst_size = WebPEncodeRGBA(r.ptr(),s.width,s.height,4*s.width,CLAMP(p_quality*100.0,0,100.0),&dst_buff); - } - - ERR_FAIL_COND_V(dst_size==0,DVector<uint8_t>()); - DVector<uint8_t> dst; - dst.resize(4+dst_size); - DVector<uint8_t>::Write w = dst.write(); - w[0]='W'; - w[1]='E'; - w[2]='B'; - w[3]='P'; - copymem(&w[4],dst_buff,dst_size); - free(dst_buff); - w=DVector<uint8_t>::Write(); - return dst; -} - -static Image _webp_lossy_unpack(const DVector<uint8_t>& p_buffer) { - - int size = p_buffer.size()-4; - ERR_FAIL_COND_V(size<=0,Image()); - DVector<uint8_t>::Read r = p_buffer.read(); - - ERR_FAIL_COND_V(r[0]!='W' || r[1]!='E' || r[2]!='B' || r[3]!='P',Image()); - WebPBitstreamFeatures features; - if (WebPGetFeatures(&r[4],size,&features)!=VP8_STATUS_OK) { - ERR_EXPLAIN("Error unpacking WEBP image:"); - ERR_FAIL_V(Image()); - } - - //print_line("width: "+itos(features.width)); - //print_line("height: "+itos(features.height)); - //print_line("alpha: "+itos(features.has_alpha)); - - DVector<uint8_t> dst_image; - int datasize = features.width*features.height*(features.has_alpha?4:3); - dst_image.resize(datasize); - - DVector<uint8_t>::Write dst_w = dst_image.write(); - - bool errdec=false; - if (features.has_alpha) { - errdec = WebPDecodeRGBAInto(&r[4],size,dst_w.ptr(),datasize,4*features.width)==NULL; - } else { - errdec = WebPDecodeRGBInto(&r[4],size,dst_w.ptr(),datasize,3*features.width)==NULL; - - } - - //ERR_EXPLAIN("Error decoding webp! - "+p_file); - ERR_FAIL_COND_V(errdec,Image()); - - dst_w = DVector<uint8_t>::Write(); - - return Image(features.width,features.height,0,features.has_alpha?Image::FORMAT_RGBA:Image::FORMAT_RGB,dst_image); - -} - - -Error ImageLoaderWEBP::load_image(Image *p_image,FileAccess *f) { - - - uint32_t size = f->get_len(); - DVector<uint8_t> src_image; - src_image.resize(size); - - WebPBitstreamFeatures features; - - DVector<uint8_t>::Write src_w = src_image.write(); - f->get_buffer(src_w.ptr(),size); - ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_EOF); - - if (WebPGetFeatures(src_w.ptr(),size,&features)!=VP8_STATUS_OK) { - f->close(); - //ERR_EXPLAIN("Error decoding WEBP image: "+p_file); - ERR_FAIL_V(ERR_FILE_CORRUPT); - } - - print_line("width: "+itos(features.width)); - print_line("height: "+itos(features.height)); - print_line("alpha: "+itos(features.has_alpha)); - - src_w = DVector<uint8_t>::Write(); - - DVector<uint8_t> dst_image; - int datasize = features.width*features.height*(features.has_alpha?4:3); - dst_image.resize(datasize); - - DVector<uint8_t>::Read src_r = src_image.read(); - DVector<uint8_t>::Write dst_w = dst_image.write(); - - - bool errdec=false; - if (features.has_alpha) { - errdec = WebPDecodeRGBAInto(src_r.ptr(),size,dst_w.ptr(),datasize,4*features.width)==NULL; - } else { - errdec = WebPDecodeRGBInto(src_r.ptr(),size,dst_w.ptr(),datasize,3*features.width)==NULL; - - } - - //ERR_EXPLAIN("Error decoding webp! - "+p_file); - ERR_FAIL_COND_V(errdec,ERR_FILE_CORRUPT); - - src_r = DVector<uint8_t>::Read(); - dst_w = DVector<uint8_t>::Write(); - - *p_image = Image(features.width,features.height,0,features.has_alpha?Image::FORMAT_RGBA:Image::FORMAT_RGB,dst_image); - - - return OK; - -} - -void ImageLoaderWEBP::get_recognized_extensions(List<String> *p_extensions) const { - - p_extensions->push_back("webp"); -} - - -ImageLoaderWEBP::ImageLoaderWEBP() { - - Image::lossy_packer=_webp_lossy_pack; - Image::lossy_unpacker=_webp_lossy_unpack; -} - - diff --git a/drivers/webp/mux/anim_encode.c b/drivers/webp/mux/anim_encode.c deleted file mode 100644 index 2226febf13..0000000000 --- a/drivers/webp/mux/anim_encode.c +++ /dev/null @@ -1,1534 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// AnimEncoder implementation. -// - -#include <assert.h> -#include <limits.h> -#include <math.h> // for pow() -#include <stdio.h> -#include <stdlib.h> // for abs() - -#include "../utils/utils.h" -#include "webp/decode.h" -#include "webp/encode.h" -#include "webp/format_constants.h" -#include "webp/mux.h" - -#if defined(_MSC_VER) && _MSC_VER < 1900 -#define snprintf _snprintf -#endif - -#define ERROR_STR_MAX_LENGTH 100 - -//------------------------------------------------------------------------------ -// Internal structs. - -// Stores frame rectangle dimensions. -typedef struct { - int x_offset_, y_offset_, width_, height_; -} FrameRect; - -// Used to store two candidates of encoded data for an animation frame. One of -// the two will be chosen later. -typedef struct { - WebPMuxFrameInfo sub_frame_; // Encoded frame rectangle. - WebPMuxFrameInfo key_frame_; // Encoded frame if it is a key-frame. - int is_key_frame_; // True if 'key_frame' has been chosen. -} EncodedFrame; - -struct WebPAnimEncoder { - const int canvas_width_; // Canvas width. - const int canvas_height_; // Canvas height. - const WebPAnimEncoderOptions options_; // Global encoding options. - - FrameRect prev_rect_; // Previous WebP frame rectangle. - WebPConfig last_config_; // Cached in case a re-encode is needed. - WebPConfig last_config_reversed_; // If 'last_config_' uses lossless, then - // this config uses lossy and vice versa; - // only valid if 'options_.allow_mixed' - // is true. - - WebPPicture* curr_canvas_; // Only pointer; we don't own memory. - - // Canvas buffers. - WebPPicture curr_canvas_copy_; // Possibly modified current canvas. - int curr_canvas_copy_modified_; // True if pixels in 'curr_canvas_copy_' - // differ from those in 'curr_canvas_'. - - WebPPicture prev_canvas_; // Previous canvas. - WebPPicture prev_canvas_disposed_; // Previous canvas disposed to background. - - // Encoded data. - EncodedFrame* encoded_frames_; // Array of encoded frames. - size_t size_; // Number of allocated frames. - size_t start_; // Frame start index. - size_t count_; // Number of valid frames. - size_t flush_count_; // If >0, 'flush_count' frames starting from - // 'start' are ready to be added to mux. - - // key-frame related. - int64_t best_delta_; // min(canvas size - frame size) over the frames. - // Can be negative in certain cases due to - // transparent pixels in a frame. - int keyframe_; // Index of selected key-frame relative to 'start_'. - int count_since_key_frame_; // Frames seen since the last key-frame. - - int first_timestamp_; // Timestamp of the first frame. - int prev_timestamp_; // Timestamp of the last added frame. - int prev_candidate_undecided_; // True if it's not yet decided if previous - // frame would be a sub-frame or a key-frame. - - // Misc. - int is_first_frame_; // True if first frame is yet to be added/being added. - int got_null_frame_; // True if WebPAnimEncoderAdd() has already been called - // with a NULL frame. - - size_t in_frame_count_; // Number of input frames processed so far. - size_t out_frame_count_; // Number of frames added to mux so far. This may be - // different from 'in_frame_count_' due to merging. - - WebPMux* mux_; // Muxer to assemble the WebP bitstream. - char error_str_[ERROR_STR_MAX_LENGTH]; // Error string. Empty if no error. -}; - -// ----------------------------------------------------------------------------- -// Life of WebPAnimEncoder object. - -#define DELTA_INFINITY (1ULL << 32) -#define KEYFRAME_NONE (-1) - -// Reset the counters in the WebPAnimEncoder. -static void ResetCounters(WebPAnimEncoder* const enc) { - enc->start_ = 0; - enc->count_ = 0; - enc->flush_count_ = 0; - enc->best_delta_ = DELTA_INFINITY; - enc->keyframe_ = KEYFRAME_NONE; -} - -static void DisableKeyframes(WebPAnimEncoderOptions* const enc_options) { - enc_options->kmax = INT_MAX; - enc_options->kmin = enc_options->kmax - 1; -} - -#define MAX_CACHED_FRAMES 30 - -static void SanitizeEncoderOptions(WebPAnimEncoderOptions* const enc_options) { - int print_warning = enc_options->verbose; - - if (enc_options->minimize_size) { - DisableKeyframes(enc_options); - } - - if (enc_options->kmin <= 0) { - DisableKeyframes(enc_options); - print_warning = 0; - } - if (enc_options->kmax <= 0) { // All frames will be key-frames. - enc_options->kmin = 0; - enc_options->kmax = 0; - return; - } - - if (enc_options->kmin >= enc_options->kmax) { - enc_options->kmin = enc_options->kmax - 1; - if (print_warning) { - fprintf(stderr, "WARNING: Setting kmin = %d, so that kmin < kmax.\n", - enc_options->kmin); - } - } else { - const int kmin_limit = enc_options->kmax / 2 + 1; - if (enc_options->kmin < kmin_limit && kmin_limit < enc_options->kmax) { - // This ensures that enc.keyframe + kmin >= kmax is always true. So, we - // can flush all the frames in the 'count_since_key_frame == kmax' case. - enc_options->kmin = kmin_limit; - if (print_warning) { - fprintf(stderr, - "WARNING: Setting kmin = %d, so that kmin >= kmax / 2 + 1.\n", - enc_options->kmin); - } - } - } - // Limit the max number of frames that are allocated. - if (enc_options->kmax - enc_options->kmin > MAX_CACHED_FRAMES) { - enc_options->kmin = enc_options->kmax - MAX_CACHED_FRAMES; - if (print_warning) { - fprintf(stderr, - "WARNING: Setting kmin = %d, so that kmax - kmin <= %d.\n", - enc_options->kmin, MAX_CACHED_FRAMES); - } - } - assert(enc_options->kmin < enc_options->kmax); -} - -#undef MAX_CACHED_FRAMES - -static void DefaultEncoderOptions(WebPAnimEncoderOptions* const enc_options) { - enc_options->anim_params.loop_count = 0; - enc_options->anim_params.bgcolor = 0xffffffff; // White. - enc_options->minimize_size = 0; - DisableKeyframes(enc_options); - enc_options->allow_mixed = 0; - enc_options->verbose = 0; -} - -int WebPAnimEncoderOptionsInitInternal(WebPAnimEncoderOptions* enc_options, - int abi_version) { - if (enc_options == NULL || - WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) { - return 0; - } - DefaultEncoderOptions(enc_options); - return 1; -} - -// This starting value is more fit to WebPCleanupTransparentAreaLossless(). -#define TRANSPARENT_COLOR 0x00000000 - -static void ClearRectangle(WebPPicture* const picture, - int left, int top, int width, int height) { - int j; - for (j = top; j < top + height; ++j) { - uint32_t* const dst = picture->argb + j * picture->argb_stride; - int i; - for (i = left; i < left + width; ++i) { - dst[i] = TRANSPARENT_COLOR; - } - } -} - -static void WebPUtilClearPic(WebPPicture* const picture, - const FrameRect* const rect) { - if (rect != NULL) { - ClearRectangle(picture, rect->x_offset_, rect->y_offset_, - rect->width_, rect->height_); - } else { - ClearRectangle(picture, 0, 0, picture->width, picture->height); - } -} - -static void MarkNoError(WebPAnimEncoder* const enc) { - enc->error_str_[0] = '\0'; // Empty string. -} - -static void MarkError(WebPAnimEncoder* const enc, const char* str) { - if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s.", str) < 0) { - assert(0); // FIX ME! - } -} - -static void MarkError2(WebPAnimEncoder* const enc, - const char* str, int error_code) { - if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s: %d.", str, - error_code) < 0) { - assert(0); // FIX ME! - } -} - -WebPAnimEncoder* WebPAnimEncoderNewInternal( - int width, int height, const WebPAnimEncoderOptions* enc_options, - int abi_version) { - WebPAnimEncoder* enc; - - if (WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) { - return NULL; - } - if (width <= 0 || height <= 0 || - (width * (uint64_t)height) >= MAX_IMAGE_AREA) { - return NULL; - } - - enc = (WebPAnimEncoder*)WebPSafeCalloc(1, sizeof(*enc)); - if (enc == NULL) return NULL; - // sanity inits, so we can call WebPAnimEncoderDelete(): - enc->encoded_frames_ = NULL; - enc->mux_ = NULL; - MarkNoError(enc); - - // Dimensions and options. - *(int*)&enc->canvas_width_ = width; - *(int*)&enc->canvas_height_ = height; - if (enc_options != NULL) { - *(WebPAnimEncoderOptions*)&enc->options_ = *enc_options; - SanitizeEncoderOptions((WebPAnimEncoderOptions*)&enc->options_); - } else { - DefaultEncoderOptions((WebPAnimEncoderOptions*)&enc->options_); - } - - // Canvas buffers. - if (!WebPPictureInit(&enc->curr_canvas_copy_) || - !WebPPictureInit(&enc->prev_canvas_) || - !WebPPictureInit(&enc->prev_canvas_disposed_)) { - goto Err; - } - enc->curr_canvas_copy_.width = width; - enc->curr_canvas_copy_.height = height; - enc->curr_canvas_copy_.use_argb = 1; - if (!WebPPictureAlloc(&enc->curr_canvas_copy_) || - !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_) || - !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_disposed_)) { - goto Err; - } - WebPUtilClearPic(&enc->prev_canvas_, NULL); - enc->curr_canvas_copy_modified_ = 1; - - // Encoded frames. - ResetCounters(enc); - // Note: one extra storage is for the previous frame. - enc->size_ = enc->options_.kmax - enc->options_.kmin + 1; - // We need space for at least 2 frames. But when kmin, kmax are both zero, - // enc->size_ will be 1. So we handle that special case below. - if (enc->size_ < 2) enc->size_ = 2; - enc->encoded_frames_ = - (EncodedFrame*)WebPSafeCalloc(enc->size_, sizeof(*enc->encoded_frames_)); - if (enc->encoded_frames_ == NULL) goto Err; - - enc->mux_ = WebPMuxNew(); - if (enc->mux_ == NULL) goto Err; - - enc->count_since_key_frame_ = 0; - enc->first_timestamp_ = 0; - enc->prev_timestamp_ = 0; - enc->prev_candidate_undecided_ = 0; - enc->is_first_frame_ = 1; - enc->got_null_frame_ = 0; - - return enc; // All OK. - - Err: - WebPAnimEncoderDelete(enc); - return NULL; -} - -// Release the data contained by 'encoded_frame'. -static void FrameRelease(EncodedFrame* const encoded_frame) { - if (encoded_frame != NULL) { - WebPDataClear(&encoded_frame->sub_frame_.bitstream); - WebPDataClear(&encoded_frame->key_frame_.bitstream); - memset(encoded_frame, 0, sizeof(*encoded_frame)); - } -} - -void WebPAnimEncoderDelete(WebPAnimEncoder* enc) { - if (enc != NULL) { - WebPPictureFree(&enc->curr_canvas_copy_); - WebPPictureFree(&enc->prev_canvas_); - WebPPictureFree(&enc->prev_canvas_disposed_); - if (enc->encoded_frames_ != NULL) { - size_t i; - for (i = 0; i < enc->size_; ++i) { - FrameRelease(&enc->encoded_frames_[i]); - } - WebPSafeFree(enc->encoded_frames_); - } - WebPMuxDelete(enc->mux_); - WebPSafeFree(enc); - } -} - -// ----------------------------------------------------------------------------- -// Frame addition. - -// Returns cached frame at the given 'position'. -static EncodedFrame* GetFrame(const WebPAnimEncoder* const enc, - size_t position) { - assert(enc->start_ + position < enc->size_); - return &enc->encoded_frames_[enc->start_ + position]; -} - -typedef int (*ComparePixelsFunc)(const uint32_t*, int, const uint32_t*, int, - int, int); - -// Returns true if 'length' number of pixels in 'src' and 'dst' are equal, -// assuming the given step sizes between pixels. -// 'max_allowed_diff' is unused and only there to allow function pointer use. -static WEBP_INLINE int ComparePixelsLossless(const uint32_t* src, int src_step, - const uint32_t* dst, int dst_step, - int length, int max_allowed_diff) { - (void)max_allowed_diff; - assert(length > 0); - while (length-- > 0) { - if (*src != *dst) { - return 0; - } - src += src_step; - dst += dst_step; - } - return 1; -} - -// Helper to check if each channel in 'src' and 'dst' is at most off by -// 'max_allowed_diff'. -static WEBP_INLINE int PixelsAreSimilar(uint32_t src, uint32_t dst, - int max_allowed_diff) { - const int src_a = (src >> 24) & 0xff; - const int src_r = (src >> 16) & 0xff; - const int src_g = (src >> 8) & 0xff; - const int src_b = (src >> 0) & 0xff; - const int dst_a = (dst >> 24) & 0xff; - const int dst_r = (dst >> 16) & 0xff; - const int dst_g = (dst >> 8) & 0xff; - const int dst_b = (dst >> 0) & 0xff; - - return (abs(src_r * src_a - dst_r * dst_a) <= (max_allowed_diff * 255)) && - (abs(src_g * src_a - dst_g * dst_a) <= (max_allowed_diff * 255)) && - (abs(src_b * src_a - dst_b * dst_a) <= (max_allowed_diff * 255)) && - (abs(src_a - dst_a) <= max_allowed_diff); -} - -// Returns true if 'length' number of pixels in 'src' and 'dst' are within an -// error bound, assuming the given step sizes between pixels. -static WEBP_INLINE int ComparePixelsLossy(const uint32_t* src, int src_step, - const uint32_t* dst, int dst_step, - int length, int max_allowed_diff) { - assert(length > 0); - while (length-- > 0) { - if (!PixelsAreSimilar(*src, *dst, max_allowed_diff)) { - return 0; - } - src += src_step; - dst += dst_step; - } - return 1; -} - -static int IsEmptyRect(const FrameRect* const rect) { - return (rect->width_ == 0) || (rect->height_ == 0); -} - -static int QualityToMaxDiff(float quality) { - const double val = pow(quality / 100., 0.5); - const double max_diff = 31 * (1 - val) + 1 * val; - return (int)(max_diff + 0.5); -} - -// Assumes that an initial valid guess of change rectangle 'rect' is passed. -static void MinimizeChangeRectangle(const WebPPicture* const src, - const WebPPicture* const dst, - FrameRect* const rect, - int is_lossless, float quality) { - int i, j; - const ComparePixelsFunc compare_pixels = - is_lossless ? ComparePixelsLossless : ComparePixelsLossy; - const int max_allowed_diff_lossy = QualityToMaxDiff(quality); - const int max_allowed_diff = is_lossless ? 0 : max_allowed_diff_lossy; - - // Sanity checks. - assert(src->width == dst->width && src->height == dst->height); - assert(rect->x_offset_ + rect->width_ <= dst->width); - assert(rect->y_offset_ + rect->height_ <= dst->height); - - // Left boundary. - for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { - const uint32_t* const src_argb = - &src->argb[rect->y_offset_ * src->argb_stride + i]; - const uint32_t* const dst_argb = - &dst->argb[rect->y_offset_ * dst->argb_stride + i]; - if (compare_pixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride, - rect->height_, max_allowed_diff)) { - --rect->width_; // Redundant column. - ++rect->x_offset_; - } else { - break; - } - } - if (rect->width_ == 0) goto NoChange; - - // Right boundary. - for (i = rect->x_offset_ + rect->width_ - 1; i >= rect->x_offset_; --i) { - const uint32_t* const src_argb = - &src->argb[rect->y_offset_ * src->argb_stride + i]; - const uint32_t* const dst_argb = - &dst->argb[rect->y_offset_ * dst->argb_stride + i]; - if (compare_pixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride, - rect->height_, max_allowed_diff)) { - --rect->width_; // Redundant column. - } else { - break; - } - } - if (rect->width_ == 0) goto NoChange; - - // Top boundary. - for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { - const uint32_t* const src_argb = - &src->argb[j * src->argb_stride + rect->x_offset_]; - const uint32_t* const dst_argb = - &dst->argb[j * dst->argb_stride + rect->x_offset_]; - if (compare_pixels(src_argb, 1, dst_argb, 1, rect->width_, - max_allowed_diff)) { - --rect->height_; // Redundant row. - ++rect->y_offset_; - } else { - break; - } - } - if (rect->height_ == 0) goto NoChange; - - // Bottom boundary. - for (j = rect->y_offset_ + rect->height_ - 1; j >= rect->y_offset_; --j) { - const uint32_t* const src_argb = - &src->argb[j * src->argb_stride + rect->x_offset_]; - const uint32_t* const dst_argb = - &dst->argb[j * dst->argb_stride + rect->x_offset_]; - if (compare_pixels(src_argb, 1, dst_argb, 1, rect->width_, - max_allowed_diff)) { - --rect->height_; // Redundant row. - } else { - break; - } - } - if (rect->height_ == 0) goto NoChange; - - if (IsEmptyRect(rect)) { - NoChange: - rect->x_offset_ = 0; - rect->y_offset_ = 0; - rect->width_ = 0; - rect->height_ = 0; - } -} - -// Snap rectangle to even offsets (and adjust dimensions if needed). -static WEBP_INLINE void SnapToEvenOffsets(FrameRect* const rect) { - rect->width_ += (rect->x_offset_ & 1); - rect->height_ += (rect->y_offset_ & 1); - rect->x_offset_ &= ~1; - rect->y_offset_ &= ~1; -} - -typedef struct { - int should_try_; // Should try this set of parameters. - int empty_rect_allowed_; // Frame with empty rectangle can be skipped. - FrameRect rect_ll_; // Frame rectangle for lossless compression. - WebPPicture sub_frame_ll_; // Sub-frame pic for lossless compression. - FrameRect rect_lossy_; // Frame rectangle for lossy compression. - // Could be smaller than rect_ll_ as pixels - // with small diffs can be ignored. - WebPPicture sub_frame_lossy_; // Sub-frame pic for lossless compression. -} SubFrameParams; - -static int SubFrameParamsInit(SubFrameParams* const params, - int should_try, int empty_rect_allowed) { - params->should_try_ = should_try; - params->empty_rect_allowed_ = empty_rect_allowed; - if (!WebPPictureInit(¶ms->sub_frame_ll_) || - !WebPPictureInit(¶ms->sub_frame_lossy_)) { - return 0; - } - return 1; -} - -static void SubFrameParamsFree(SubFrameParams* const params) { - WebPPictureFree(¶ms->sub_frame_ll_); - WebPPictureFree(¶ms->sub_frame_lossy_); -} - -// Given previous and current canvas, picks the optimal rectangle for the -// current frame based on 'is_lossless' and other parameters. Assumes that the -// initial guess 'rect' is valid. -static int GetSubRect(const WebPPicture* const prev_canvas, - const WebPPicture* const curr_canvas, int is_key_frame, - int is_first_frame, int empty_rect_allowed, - int is_lossless, float quality, FrameRect* const rect, - WebPPicture* const sub_frame) { - if (!is_key_frame || is_first_frame) { // Optimize frame rectangle. - // Note: This behaves as expected for first frame, as 'prev_canvas' is - // initialized to a fully transparent canvas in the beginning. - MinimizeChangeRectangle(prev_canvas, curr_canvas, rect, - is_lossless, quality); - } - - if (IsEmptyRect(rect)) { - if (empty_rect_allowed) { // No need to get 'sub_frame'. - return 1; - } else { // Force a 1x1 rectangle. - rect->width_ = 1; - rect->height_ = 1; - assert(rect->x_offset_ == 0); - assert(rect->y_offset_ == 0); - } - } - - SnapToEvenOffsets(rect); - return WebPPictureView(curr_canvas, rect->x_offset_, rect->y_offset_, - rect->width_, rect->height_, sub_frame); -} - -// Picks optimal frame rectangle for both lossless and lossy compression. The -// initial guess for frame rectangles will be the full canvas. -static int GetSubRects(const WebPPicture* const prev_canvas, - const WebPPicture* const curr_canvas, int is_key_frame, - int is_first_frame, float quality, - SubFrameParams* const params) { - // Lossless frame rectangle. - params->rect_ll_.x_offset_ = 0; - params->rect_ll_.y_offset_ = 0; - params->rect_ll_.width_ = curr_canvas->width; - params->rect_ll_.height_ = curr_canvas->height; - if (!GetSubRect(prev_canvas, curr_canvas, is_key_frame, is_first_frame, - params->empty_rect_allowed_, 1, quality, - ¶ms->rect_ll_, ¶ms->sub_frame_ll_)) { - return 0; - } - // Lossy frame rectangle. - params->rect_lossy_ = params->rect_ll_; // seed with lossless rect. - return GetSubRect(prev_canvas, curr_canvas, is_key_frame, is_first_frame, - params->empty_rect_allowed_, 0, quality, - ¶ms->rect_lossy_, ¶ms->sub_frame_lossy_); -} - -static void DisposeFrameRectangle(int dispose_method, - const FrameRect* const rect, - WebPPicture* const curr_canvas) { - assert(rect != NULL); - if (dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { - WebPUtilClearPic(curr_canvas, rect); - } -} - -static uint32_t RectArea(const FrameRect* const rect) { - return (uint32_t)rect->width_ * rect->height_; -} - -static int IsLosslessBlendingPossible(const WebPPicture* const src, - const WebPPicture* const dst, - const FrameRect* const rect) { - int i, j; - assert(src->width == dst->width && src->height == dst->height); - assert(rect->x_offset_ + rect->width_ <= dst->width); - assert(rect->y_offset_ + rect->height_ <= dst->height); - for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { - for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { - const uint32_t src_pixel = src->argb[j * src->argb_stride + i]; - const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i]; - const uint32_t dst_alpha = dst_pixel >> 24; - if (dst_alpha != 0xff && src_pixel != dst_pixel) { - // In this case, if we use blending, we can't attain the desired - // 'dst_pixel' value for this pixel. So, blending is not possible. - return 0; - } - } - } - return 1; -} - -static int IsLossyBlendingPossible(const WebPPicture* const src, - const WebPPicture* const dst, - const FrameRect* const rect, - float quality) { - const int max_allowed_diff_lossy = QualityToMaxDiff(quality); - int i, j; - assert(src->width == dst->width && src->height == dst->height); - assert(rect->x_offset_ + rect->width_ <= dst->width); - assert(rect->y_offset_ + rect->height_ <= dst->height); - for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { - for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { - const uint32_t src_pixel = src->argb[j * src->argb_stride + i]; - const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i]; - const uint32_t dst_alpha = dst_pixel >> 24; - if (dst_alpha != 0xff && - !PixelsAreSimilar(src_pixel, dst_pixel, max_allowed_diff_lossy)) { - // In this case, if we use blending, we can't attain the desired - // 'dst_pixel' value for this pixel. So, blending is not possible. - return 0; - } - } - } - return 1; -} - -// For pixels in 'rect', replace those pixels in 'dst' that are same as 'src' by -// transparent pixels. -// Returns true if at least one pixel gets modified. -static int IncreaseTransparency(const WebPPicture* const src, - const FrameRect* const rect, - WebPPicture* const dst) { - int i, j; - int modified = 0; - assert(src != NULL && dst != NULL && rect != NULL); - assert(src->width == dst->width && src->height == dst->height); - for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { - const uint32_t* const psrc = src->argb + j * src->argb_stride; - uint32_t* const pdst = dst->argb + j * dst->argb_stride; - for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { - if (psrc[i] == pdst[i] && pdst[i] != TRANSPARENT_COLOR) { - pdst[i] = TRANSPARENT_COLOR; - modified = 1; - } - } - } - return modified; -} - -#undef TRANSPARENT_COLOR - -// Replace similar blocks of pixels by a 'see-through' transparent block -// with uniform average color. -// Assumes lossy compression is being used. -// Returns true if at least one pixel gets modified. -static int FlattenSimilarBlocks(const WebPPicture* const src, - const FrameRect* const rect, - WebPPicture* const dst, float quality) { - const int max_allowed_diff_lossy = QualityToMaxDiff(quality); - int i, j; - int modified = 0; - const int block_size = 8; - const int y_start = (rect->y_offset_ + block_size) & ~(block_size - 1); - const int y_end = (rect->y_offset_ + rect->height_) & ~(block_size - 1); - const int x_start = (rect->x_offset_ + block_size) & ~(block_size - 1); - const int x_end = (rect->x_offset_ + rect->width_) & ~(block_size - 1); - assert(src != NULL && dst != NULL && rect != NULL); - assert(src->width == dst->width && src->height == dst->height); - assert((block_size & (block_size - 1)) == 0); // must be a power of 2 - // Iterate over each block and count similar pixels. - for (j = y_start; j < y_end; j += block_size) { - for (i = x_start; i < x_end; i += block_size) { - int cnt = 0; - int avg_r = 0, avg_g = 0, avg_b = 0; - int x, y; - const uint32_t* const psrc = src->argb + j * src->argb_stride + i; - uint32_t* const pdst = dst->argb + j * dst->argb_stride + i; - for (y = 0; y < block_size; ++y) { - for (x = 0; x < block_size; ++x) { - const uint32_t src_pixel = psrc[x + y * src->argb_stride]; - const int alpha = src_pixel >> 24; - if (alpha == 0xff && - PixelsAreSimilar(src_pixel, pdst[x + y * dst->argb_stride], - max_allowed_diff_lossy)) { - ++cnt; - avg_r += (src_pixel >> 16) & 0xff; - avg_g += (src_pixel >> 8) & 0xff; - avg_b += (src_pixel >> 0) & 0xff; - } - } - } - // If we have a fully similar block, we replace it with an - // average transparent block. This compresses better in lossy mode. - if (cnt == block_size * block_size) { - const uint32_t color = (0x00 << 24) | - ((avg_r / cnt) << 16) | - ((avg_g / cnt) << 8) | - ((avg_b / cnt) << 0); - for (y = 0; y < block_size; ++y) { - for (x = 0; x < block_size; ++x) { - pdst[x + y * dst->argb_stride] = color; - } - } - modified = 1; - } - } - } - return modified; -} - -static int EncodeFrame(const WebPConfig* const config, WebPPicture* const pic, - WebPMemoryWriter* const memory) { - pic->use_argb = 1; - pic->writer = WebPMemoryWrite; - pic->custom_ptr = memory; - if (!WebPEncode(config, pic)) { - return 0; - } - return 1; -} - -// Struct representing a candidate encoded frame including its metadata. -typedef struct { - WebPMemoryWriter mem_; - WebPMuxFrameInfo info_; - FrameRect rect_; - int evaluate_; // True if this candidate should be evaluated. -} Candidate; - -// Generates a candidate encoded frame given a picture and metadata. -static WebPEncodingError EncodeCandidate(WebPPicture* const sub_frame, - const FrameRect* const rect, - const WebPConfig* const encoder_config, - int use_blending, - Candidate* const candidate) { - WebPConfig config = *encoder_config; - WebPEncodingError error_code = VP8_ENC_OK; - assert(candidate != NULL); - memset(candidate, 0, sizeof(*candidate)); - - // Set frame rect and info. - candidate->rect_ = *rect; - candidate->info_.id = WEBP_CHUNK_ANMF; - candidate->info_.x_offset = rect->x_offset_; - candidate->info_.y_offset = rect->y_offset_; - candidate->info_.dispose_method = WEBP_MUX_DISPOSE_NONE; // Set later. - candidate->info_.blend_method = - use_blending ? WEBP_MUX_BLEND : WEBP_MUX_NO_BLEND; - candidate->info_.duration = 0; // Set in next call to WebPAnimEncoderAdd(). - - // Encode picture. - WebPMemoryWriterInit(&candidate->mem_); - - if (!config.lossless && use_blending) { - // Disable filtering to avoid blockiness in reconstructed frames at the - // time of decoding. - config.autofilter = 0; - config.filter_strength = 0; - } - if (!EncodeFrame(&config, sub_frame, &candidate->mem_)) { - error_code = sub_frame->error_code; - goto Err; - } - - candidate->evaluate_ = 1; - return error_code; - - Err: - WebPMemoryWriterClear(&candidate->mem_); - return error_code; -} - -static void CopyCurrentCanvas(WebPAnimEncoder* const enc) { - if (enc->curr_canvas_copy_modified_) { - WebPCopyPixels(enc->curr_canvas_, &enc->curr_canvas_copy_); - enc->curr_canvas_copy_.progress_hook = enc->curr_canvas_->progress_hook; - enc->curr_canvas_copy_.user_data = enc->curr_canvas_->user_data; - enc->curr_canvas_copy_modified_ = 0; - } -} - -enum { - LL_DISP_NONE = 0, - LL_DISP_BG, - LOSSY_DISP_NONE, - LOSSY_DISP_BG, - CANDIDATE_COUNT -}; - -#define MIN_COLORS_LOSSY 31 // Don't try lossy below this threshold. -#define MAX_COLORS_LOSSLESS 194 // Don't try lossless above this threshold. - -// Generates candidates for a given dispose method given pre-filled sub-frame -// 'params'. -static WebPEncodingError GenerateCandidates( - WebPAnimEncoder* const enc, Candidate candidates[CANDIDATE_COUNT], - WebPMuxAnimDispose dispose_method, int is_lossless, int is_key_frame, - SubFrameParams* const params, - const WebPConfig* const config_ll, const WebPConfig* const config_lossy) { - WebPEncodingError error_code = VP8_ENC_OK; - const int is_dispose_none = (dispose_method == WEBP_MUX_DISPOSE_NONE); - Candidate* const candidate_ll = - is_dispose_none ? &candidates[LL_DISP_NONE] : &candidates[LL_DISP_BG]; - Candidate* const candidate_lossy = is_dispose_none - ? &candidates[LOSSY_DISP_NONE] - : &candidates[LOSSY_DISP_BG]; - WebPPicture* const curr_canvas = &enc->curr_canvas_copy_; - const WebPPicture* const prev_canvas = - is_dispose_none ? &enc->prev_canvas_ : &enc->prev_canvas_disposed_; - int use_blending_ll; - int use_blending_lossy; - - CopyCurrentCanvas(enc); - use_blending_ll = - !is_key_frame && - IsLosslessBlendingPossible(prev_canvas, curr_canvas, ¶ms->rect_ll_); - use_blending_lossy = - !is_key_frame && - IsLossyBlendingPossible(prev_canvas, curr_canvas, ¶ms->rect_lossy_, - config_lossy->quality); - - // Pick candidates to be tried. - if (!enc->options_.allow_mixed) { - candidate_ll->evaluate_ = is_lossless; - candidate_lossy->evaluate_ = !is_lossless; - } else { // Use a heuristic for trying lossless and/or lossy compression. - const int num_colors = WebPGetColorPalette(¶ms->sub_frame_ll_, NULL); - candidate_ll->evaluate_ = (num_colors < MAX_COLORS_LOSSLESS); - candidate_lossy->evaluate_ = (num_colors >= MIN_COLORS_LOSSY); - } - - // Generate candidates. - if (candidate_ll->evaluate_) { - CopyCurrentCanvas(enc); - if (use_blending_ll) { - enc->curr_canvas_copy_modified_ = - IncreaseTransparency(prev_canvas, ¶ms->rect_ll_, curr_canvas); - } - error_code = EncodeCandidate(¶ms->sub_frame_ll_, ¶ms->rect_ll_, - config_ll, use_blending_ll, candidate_ll); - if (error_code != VP8_ENC_OK) return error_code; - } - if (candidate_lossy->evaluate_) { - CopyCurrentCanvas(enc); - if (use_blending_lossy) { - enc->curr_canvas_copy_modified_ = - FlattenSimilarBlocks(prev_canvas, ¶ms->rect_lossy_, curr_canvas, - config_lossy->quality); - } - error_code = - EncodeCandidate(¶ms->sub_frame_lossy_, ¶ms->rect_lossy_, - config_lossy, use_blending_lossy, candidate_lossy); - if (error_code != VP8_ENC_OK) return error_code; - enc->curr_canvas_copy_modified_ = 1; - } - return error_code; -} - -#undef MIN_COLORS_LOSSY -#undef MAX_COLORS_LOSSLESS - -static void GetEncodedData(const WebPMemoryWriter* const memory, - WebPData* const encoded_data) { - encoded_data->bytes = memory->mem; - encoded_data->size = memory->size; -} - -// Sets dispose method of the previous frame to be 'dispose_method'. -static void SetPreviousDisposeMethod(WebPAnimEncoder* const enc, - WebPMuxAnimDispose dispose_method) { - const size_t position = enc->count_ - 2; - EncodedFrame* const prev_enc_frame = GetFrame(enc, position); - assert(enc->count_ >= 2); // As current and previous frames are in enc. - - if (enc->prev_candidate_undecided_) { - assert(dispose_method == WEBP_MUX_DISPOSE_NONE); - prev_enc_frame->sub_frame_.dispose_method = dispose_method; - prev_enc_frame->key_frame_.dispose_method = dispose_method; - } else { - WebPMuxFrameInfo* const prev_info = prev_enc_frame->is_key_frame_ - ? &prev_enc_frame->key_frame_ - : &prev_enc_frame->sub_frame_; - prev_info->dispose_method = dispose_method; - } -} - -static int IncreasePreviousDuration(WebPAnimEncoder* const enc, int duration) { - const size_t position = enc->count_ - 1; - EncodedFrame* const prev_enc_frame = GetFrame(enc, position); - int new_duration; - - assert(enc->count_ >= 1); - assert(prev_enc_frame->sub_frame_.duration == - prev_enc_frame->key_frame_.duration); - assert(prev_enc_frame->sub_frame_.duration == - (prev_enc_frame->sub_frame_.duration & (MAX_DURATION - 1))); - assert(duration == (duration & (MAX_DURATION - 1))); - - new_duration = prev_enc_frame->sub_frame_.duration + duration; - if (new_duration >= MAX_DURATION) { // Special case. - // Separate out previous frame from earlier merged frames to avoid overflow. - // We add a 1x1 transparent frame for the previous frame, with blending on. - const FrameRect rect = { 0, 0, 1, 1 }; - const uint8_t lossless_1x1_bytes[] = { - 0x52, 0x49, 0x46, 0x46, 0x14, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, - 0x56, 0x50, 0x38, 0x4c, 0x08, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, - 0x10, 0x88, 0x88, 0x08 - }; - const WebPData lossless_1x1 = { - lossless_1x1_bytes, sizeof(lossless_1x1_bytes) - }; - const uint8_t lossy_1x1_bytes[] = { - 0x52, 0x49, 0x46, 0x46, 0x40, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, - 0x56, 0x50, 0x38, 0x58, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x4c, 0x50, 0x48, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x56, 0x50, 0x38, 0x20, 0x18, 0x00, 0x00, 0x00, - 0x30, 0x01, 0x00, 0x9d, 0x01, 0x2a, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, - 0x34, 0x25, 0xa4, 0x00, 0x03, 0x70, 0x00, 0xfe, 0xfb, 0xfd, 0x50, 0x00 - }; - const WebPData lossy_1x1 = { lossy_1x1_bytes, sizeof(lossy_1x1_bytes) }; - const int can_use_lossless = - (enc->last_config_.lossless || enc->options_.allow_mixed); - EncodedFrame* const curr_enc_frame = GetFrame(enc, enc->count_); - curr_enc_frame->is_key_frame_ = 0; - curr_enc_frame->sub_frame_.id = WEBP_CHUNK_ANMF; - curr_enc_frame->sub_frame_.x_offset = 0; - curr_enc_frame->sub_frame_.y_offset = 0; - curr_enc_frame->sub_frame_.dispose_method = WEBP_MUX_DISPOSE_NONE; - curr_enc_frame->sub_frame_.blend_method = WEBP_MUX_BLEND; - curr_enc_frame->sub_frame_.duration = duration; - if (!WebPDataCopy(can_use_lossless ? &lossless_1x1 : &lossy_1x1, - &curr_enc_frame->sub_frame_.bitstream)) { - return 0; - } - ++enc->count_; - ++enc->count_since_key_frame_; - enc->flush_count_ = enc->count_ - 1; - enc->prev_candidate_undecided_ = 0; - enc->prev_rect_ = rect; - } else { // Regular case. - // Increase duration of the previous frame by 'duration'. - prev_enc_frame->sub_frame_.duration = new_duration; - prev_enc_frame->key_frame_.duration = new_duration; - } - return 1; -} - -// Pick the candidate encoded frame with smallest size and release other -// candidates. -// TODO(later): Perhaps a rough SSIM/PSNR produced by the encoder should -// also be a criteria, in addition to sizes. -static void PickBestCandidate(WebPAnimEncoder* const enc, - Candidate* const candidates, int is_key_frame, - EncodedFrame* const encoded_frame) { - int i; - int best_idx = -1; - size_t best_size = ~0; - for (i = 0; i < CANDIDATE_COUNT; ++i) { - if (candidates[i].evaluate_) { - const size_t candidate_size = candidates[i].mem_.size; - if (candidate_size < best_size) { - best_idx = i; - best_size = candidate_size; - } - } - } - assert(best_idx != -1); - for (i = 0; i < CANDIDATE_COUNT; ++i) { - if (candidates[i].evaluate_) { - if (i == best_idx) { - WebPMuxFrameInfo* const dst = is_key_frame - ? &encoded_frame->key_frame_ - : &encoded_frame->sub_frame_; - *dst = candidates[i].info_; - GetEncodedData(&candidates[i].mem_, &dst->bitstream); - if (!is_key_frame) { - // Note: Previous dispose method only matters for non-keyframes. - // Also, we don't want to modify previous dispose method that was - // selected when a non key-frame was assumed. - const WebPMuxAnimDispose prev_dispose_method = - (best_idx == LL_DISP_NONE || best_idx == LOSSY_DISP_NONE) - ? WEBP_MUX_DISPOSE_NONE - : WEBP_MUX_DISPOSE_BACKGROUND; - SetPreviousDisposeMethod(enc, prev_dispose_method); - } - enc->prev_rect_ = candidates[i].rect_; // save for next frame. - } else { - WebPMemoryWriterClear(&candidates[i].mem_); - candidates[i].evaluate_ = 0; - } - } - } -} - -// Depending on the configuration, tries different compressions -// (lossy/lossless), dispose methods, blending methods etc to encode the current -// frame and outputs the best one in 'encoded_frame'. -// 'frame_skipped' will be set to true if this frame should actually be skipped. -static WebPEncodingError SetFrame(WebPAnimEncoder* const enc, - const WebPConfig* const config, - int is_key_frame, - EncodedFrame* const encoded_frame, - int* const frame_skipped) { - int i; - WebPEncodingError error_code = VP8_ENC_OK; - const WebPPicture* const curr_canvas = &enc->curr_canvas_copy_; - const WebPPicture* const prev_canvas = &enc->prev_canvas_; - Candidate candidates[CANDIDATE_COUNT]; - const int is_lossless = config->lossless; - const int is_first_frame = enc->is_first_frame_; - - // First frame cannot be skipped as there is no 'previous frame' to merge it - // to. So, empty rectangle is not allowed for the first frame. - const int empty_rect_allowed_none = !is_first_frame; - - // Even if there is exact pixel match between 'disposed previous canvas' and - // 'current canvas', we can't skip current frame, as there may not be exact - // pixel match between 'previous canvas' and 'current canvas'. So, we don't - // allow empty rectangle in this case. - const int empty_rect_allowed_bg = 0; - - // If current frame is a key-frame, dispose method of previous frame doesn't - // matter, so we don't try dispose to background. - // Also, if key-frame insertion is on, and previous frame could be picked as - // either a sub-frame or a key-frame, then we can't be sure about what frame - // rectangle would be disposed. In that case too, we don't try dispose to - // background. - const int dispose_bg_possible = - !is_key_frame && !enc->prev_candidate_undecided_; - - SubFrameParams dispose_none_params; - SubFrameParams dispose_bg_params; - - WebPConfig config_ll = *config; - WebPConfig config_lossy = *config; - config_ll.lossless = 1; - config_lossy.lossless = 0; - enc->last_config_ = *config; - enc->last_config_reversed_ = config->lossless ? config_lossy : config_ll; - *frame_skipped = 0; - - if (!SubFrameParamsInit(&dispose_none_params, 1, empty_rect_allowed_none) || - !SubFrameParamsInit(&dispose_bg_params, 0, empty_rect_allowed_bg)) { - return VP8_ENC_ERROR_INVALID_CONFIGURATION; - } - - for (i = 0; i < CANDIDATE_COUNT; ++i) { - candidates[i].evaluate_ = 0; - } - - // Change-rectangle assuming previous frame was DISPOSE_NONE. - if (!GetSubRects(prev_canvas, curr_canvas, is_key_frame, is_first_frame, - config_lossy.quality, &dispose_none_params)) { - error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; - goto Err; - } - - if ((is_lossless && IsEmptyRect(&dispose_none_params.rect_ll_)) || - (!is_lossless && IsEmptyRect(&dispose_none_params.rect_lossy_))) { - // Don't encode the frame at all. Instead, the duration of the previous - // frame will be increased later. - assert(empty_rect_allowed_none); - *frame_skipped = 1; - goto End; - } - - if (dispose_bg_possible) { - // Change-rectangle assuming previous frame was DISPOSE_BACKGROUND. - WebPPicture* const prev_canvas_disposed = &enc->prev_canvas_disposed_; - WebPCopyPixels(prev_canvas, prev_canvas_disposed); - DisposeFrameRectangle(WEBP_MUX_DISPOSE_BACKGROUND, &enc->prev_rect_, - prev_canvas_disposed); - - if (!GetSubRects(prev_canvas_disposed, curr_canvas, is_key_frame, - is_first_frame, config_lossy.quality, - &dispose_bg_params)) { - error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; - goto Err; - } - assert(!IsEmptyRect(&dispose_bg_params.rect_ll_)); - assert(!IsEmptyRect(&dispose_bg_params.rect_lossy_)); - - if (enc->options_.minimize_size) { // Try both dispose methods. - dispose_bg_params.should_try_ = 1; - dispose_none_params.should_try_ = 1; - } else if ((is_lossless && - RectArea(&dispose_bg_params.rect_ll_) < - RectArea(&dispose_none_params.rect_ll_)) || - (!is_lossless && - RectArea(&dispose_bg_params.rect_lossy_) < - RectArea(&dispose_none_params.rect_lossy_))) { - dispose_bg_params.should_try_ = 1; // Pick DISPOSE_BACKGROUND. - dispose_none_params.should_try_ = 0; - } - } - - if (dispose_none_params.should_try_) { - error_code = GenerateCandidates( - enc, candidates, WEBP_MUX_DISPOSE_NONE, is_lossless, is_key_frame, - &dispose_none_params, &config_ll, &config_lossy); - if (error_code != VP8_ENC_OK) goto Err; - } - - if (dispose_bg_params.should_try_) { - assert(!enc->is_first_frame_); - assert(dispose_bg_possible); - error_code = GenerateCandidates( - enc, candidates, WEBP_MUX_DISPOSE_BACKGROUND, is_lossless, is_key_frame, - &dispose_bg_params, &config_ll, &config_lossy); - if (error_code != VP8_ENC_OK) goto Err; - } - - PickBestCandidate(enc, candidates, is_key_frame, encoded_frame); - - goto End; - - Err: - for (i = 0; i < CANDIDATE_COUNT; ++i) { - if (candidates[i].evaluate_) { - WebPMemoryWriterClear(&candidates[i].mem_); - } - } - - End: - SubFrameParamsFree(&dispose_none_params); - SubFrameParamsFree(&dispose_bg_params); - return error_code; -} - -// Calculate the penalty incurred if we encode given frame as a key frame -// instead of a sub-frame. -static int64_t KeyFramePenalty(const EncodedFrame* const encoded_frame) { - return ((int64_t)encoded_frame->key_frame_.bitstream.size - - encoded_frame->sub_frame_.bitstream.size); -} - -static int CacheFrame(WebPAnimEncoder* const enc, - const WebPConfig* const config) { - int ok = 0; - int frame_skipped = 0; - WebPEncodingError error_code = VP8_ENC_OK; - const size_t position = enc->count_; - EncodedFrame* const encoded_frame = GetFrame(enc, position); - - ++enc->count_; - - if (enc->is_first_frame_) { // Add this as a key-frame. - error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped); - if (error_code != VP8_ENC_OK) goto End; - assert(frame_skipped == 0); // First frame can't be skipped, even if empty. - assert(position == 0 && enc->count_ == 1); - encoded_frame->is_key_frame_ = 1; - enc->flush_count_ = 0; - enc->count_since_key_frame_ = 0; - enc->prev_candidate_undecided_ = 0; - } else { - ++enc->count_since_key_frame_; - if (enc->count_since_key_frame_ <= enc->options_.kmin) { - // Add this as a frame rectangle. - error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped); - if (error_code != VP8_ENC_OK) goto End; - if (frame_skipped) goto Skip; - encoded_frame->is_key_frame_ = 0; - enc->flush_count_ = enc->count_ - 1; - enc->prev_candidate_undecided_ = 0; - } else { - int64_t curr_delta; - - // Add this as a frame rectangle to enc. - error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped); - if (error_code != VP8_ENC_OK) goto End; - if (frame_skipped) goto Skip; - - // Add this as a key-frame to enc, too. - error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped); - if (error_code != VP8_ENC_OK) goto End; - assert(frame_skipped == 0); // Key-frame cannot be an empty rectangle. - - // Analyze size difference of the two variants. - curr_delta = KeyFramePenalty(encoded_frame); - if (curr_delta <= enc->best_delta_) { // Pick this as the key-frame. - if (enc->keyframe_ != KEYFRAME_NONE) { - EncodedFrame* const old_keyframe = GetFrame(enc, enc->keyframe_); - assert(old_keyframe->is_key_frame_); - old_keyframe->is_key_frame_ = 0; - } - encoded_frame->is_key_frame_ = 1; - enc->keyframe_ = (int)position; - enc->best_delta_ = curr_delta; - enc->flush_count_ = enc->count_ - 1; // We can flush previous frames. - } else { - encoded_frame->is_key_frame_ = 0; - } - // Note: We need '>=' below because when kmin and kmax are both zero, - // count_since_key_frame will always be > kmax. - if (enc->count_since_key_frame_ >= enc->options_.kmax) { - enc->flush_count_ = enc->count_ - 1; - enc->count_since_key_frame_ = 0; - enc->keyframe_ = KEYFRAME_NONE; - enc->best_delta_ = DELTA_INFINITY; - } - enc->prev_candidate_undecided_ = 1; - } - } - - // Update previous to previous and previous canvases for next call. - WebPCopyPixels(enc->curr_canvas_, &enc->prev_canvas_); - enc->is_first_frame_ = 0; - - Skip: - ok = 1; - ++enc->in_frame_count_; - - End: - if (!ok || frame_skipped) { - FrameRelease(encoded_frame); - // We reset some counters, as the frame addition failed/was skipped. - --enc->count_; - if (!enc->is_first_frame_) --enc->count_since_key_frame_; - if (!ok) { - MarkError2(enc, "ERROR adding frame. WebPEncodingError", error_code); - } - } - enc->curr_canvas_->error_code = error_code; // report error_code - assert(ok || error_code != VP8_ENC_OK); - return ok; -} - -static int FlushFrames(WebPAnimEncoder* const enc) { - while (enc->flush_count_ > 0) { - WebPMuxError err; - EncodedFrame* const curr = GetFrame(enc, 0); - const WebPMuxFrameInfo* const info = - curr->is_key_frame_ ? &curr->key_frame_ : &curr->sub_frame_; - assert(enc->mux_ != NULL); - err = WebPMuxPushFrame(enc->mux_, info, 1); - if (err != WEBP_MUX_OK) { - MarkError2(enc, "ERROR adding frame. WebPMuxError", err); - return 0; - } - if (enc->options_.verbose) { - fprintf(stderr, "INFO: Added frame. offset:%d,%d dispose:%d blend:%d\n", - info->x_offset, info->y_offset, info->dispose_method, - info->blend_method); - } - ++enc->out_frame_count_; - FrameRelease(curr); - ++enc->start_; - --enc->flush_count_; - --enc->count_; - if (enc->keyframe_ != KEYFRAME_NONE) --enc->keyframe_; - } - - if (enc->count_ == 1 && enc->start_ != 0) { - // Move enc->start to index 0. - const int enc_start_tmp = (int)enc->start_; - EncodedFrame temp = enc->encoded_frames_[0]; - enc->encoded_frames_[0] = enc->encoded_frames_[enc_start_tmp]; - enc->encoded_frames_[enc_start_tmp] = temp; - FrameRelease(&enc->encoded_frames_[enc_start_tmp]); - enc->start_ = 0; - } - return 1; -} - -#undef DELTA_INFINITY -#undef KEYFRAME_NONE - -int WebPAnimEncoderAdd(WebPAnimEncoder* enc, WebPPicture* frame, int timestamp, - const WebPConfig* encoder_config) { - WebPConfig config; - int ok; - - if (enc == NULL) { - return 0; - } - MarkNoError(enc); - - if (!enc->is_first_frame_) { - // Make sure timestamps are non-decreasing (integer wrap-around is OK). - const uint32_t prev_frame_duration = - (uint32_t)timestamp - enc->prev_timestamp_; - if (prev_frame_duration >= MAX_DURATION) { - if (frame != NULL) { - frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; - } - MarkError(enc, "ERROR adding frame: timestamps must be non-decreasing"); - return 0; - } - if (!IncreasePreviousDuration(enc, (int)prev_frame_duration)) { - return 0; - } - } else { - enc->first_timestamp_ = timestamp; - } - - if (frame == NULL) { // Special: last call. - enc->got_null_frame_ = 1; - enc->prev_timestamp_ = timestamp; - return 1; - } - - if (frame->width != enc->canvas_width_ || - frame->height != enc->canvas_height_) { - frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; - MarkError(enc, "ERROR adding frame: Invalid frame dimensions"); - return 0; - } - - if (!frame->use_argb) { // Convert frame from YUV(A) to ARGB. - if (enc->options_.verbose) { - fprintf(stderr, "WARNING: Converting frame from YUV(A) to ARGB format; " - "this incurs a small loss.\n"); - } - if (!WebPPictureYUVAToARGB(frame)) { - MarkError(enc, "ERROR converting frame from YUV(A) to ARGB"); - return 0; - } - } - - if (encoder_config != NULL) { - if (!WebPValidateConfig(encoder_config)) { - MarkError(enc, "ERROR adding frame: Invalid WebPConfig"); - return 0; - } - config = *encoder_config; - } else { - WebPConfigInit(&config); - config.lossless = 1; - } - assert(enc->curr_canvas_ == NULL); - enc->curr_canvas_ = frame; // Store reference. - assert(enc->curr_canvas_copy_modified_ == 1); - CopyCurrentCanvas(enc); - - ok = CacheFrame(enc, &config) && FlushFrames(enc); - - enc->curr_canvas_ = NULL; - enc->curr_canvas_copy_modified_ = 1; - if (ok) { - enc->prev_timestamp_ = timestamp; - } - return ok; -} - -// ----------------------------------------------------------------------------- -// Bitstream assembly. - -static int DecodeFrameOntoCanvas(const WebPMuxFrameInfo* const frame, - WebPPicture* const canvas) { - const WebPData* const image = &frame->bitstream; - WebPPicture sub_image; - WebPDecoderConfig config; - WebPInitDecoderConfig(&config); - WebPUtilClearPic(canvas, NULL); - if (WebPGetFeatures(image->bytes, image->size, &config.input) != - VP8_STATUS_OK) { - return 0; - } - if (!WebPPictureView(canvas, frame->x_offset, frame->y_offset, - config.input.width, config.input.height, &sub_image)) { - return 0; - } - config.output.is_external_memory = 1; - config.output.colorspace = MODE_BGRA; - config.output.u.RGBA.rgba = (uint8_t*)sub_image.argb; - config.output.u.RGBA.stride = sub_image.argb_stride * 4; - config.output.u.RGBA.size = config.output.u.RGBA.stride * sub_image.height; - - if (WebPDecode(image->bytes, image->size, &config) != VP8_STATUS_OK) { - return 0; - } - return 1; -} - -static int FrameToFullCanvas(WebPAnimEncoder* const enc, - const WebPMuxFrameInfo* const frame, - WebPData* const full_image) { - WebPPicture* const canvas_buf = &enc->curr_canvas_copy_; - WebPMemoryWriter mem1, mem2; - WebPMemoryWriterInit(&mem1); - WebPMemoryWriterInit(&mem2); - - if (!DecodeFrameOntoCanvas(frame, canvas_buf)) goto Err; - if (!EncodeFrame(&enc->last_config_, canvas_buf, &mem1)) goto Err; - GetEncodedData(&mem1, full_image); - - if (enc->options_.allow_mixed) { - if (!EncodeFrame(&enc->last_config_reversed_, canvas_buf, &mem2)) goto Err; - if (mem2.size < mem1.size) { - GetEncodedData(&mem2, full_image); - WebPMemoryWriterClear(&mem1); - } else { - WebPMemoryWriterClear(&mem2); - } - } - return 1; - - Err: - WebPMemoryWriterClear(&mem1); - WebPMemoryWriterClear(&mem2); - return 0; -} - -// Convert a single-frame animation to a non-animated image if appropriate. -// TODO(urvang): Can we pick one of the two heuristically (based on frame -// rectangle and/or presence of alpha)? -static WebPMuxError OptimizeSingleFrame(WebPAnimEncoder* const enc, - WebPData* const webp_data) { - WebPMuxError err = WEBP_MUX_OK; - int canvas_width, canvas_height; - WebPMuxFrameInfo frame; - WebPData full_image; - WebPData webp_data2; - WebPMux* const mux = WebPMuxCreate(webp_data, 0); - if (mux == NULL) return WEBP_MUX_BAD_DATA; - assert(enc->out_frame_count_ == 1); - WebPDataInit(&frame.bitstream); - WebPDataInit(&full_image); - WebPDataInit(&webp_data2); - - err = WebPMuxGetFrame(mux, 1, &frame); - if (err != WEBP_MUX_OK) goto End; - if (frame.id != WEBP_CHUNK_ANMF) goto End; // Non-animation: nothing to do. - err = WebPMuxGetCanvasSize(mux, &canvas_width, &canvas_height); - if (err != WEBP_MUX_OK) goto End; - if (!FrameToFullCanvas(enc, &frame, &full_image)) { - err = WEBP_MUX_BAD_DATA; - goto End; - } - err = WebPMuxSetImage(mux, &full_image, 1); - if (err != WEBP_MUX_OK) goto End; - err = WebPMuxAssemble(mux, &webp_data2); - if (err != WEBP_MUX_OK) goto End; - - if (webp_data2.size < webp_data->size) { // Pick 'webp_data2' if smaller. - WebPDataClear(webp_data); - *webp_data = webp_data2; - WebPDataInit(&webp_data2); - } - - End: - WebPDataClear(&frame.bitstream); - WebPDataClear(&full_image); - WebPMuxDelete(mux); - WebPDataClear(&webp_data2); - return err; -} - -int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, WebPData* webp_data) { - WebPMux* mux; - WebPMuxError err; - - if (enc == NULL) { - return 0; - } - MarkNoError(enc); - - if (webp_data == NULL) { - MarkError(enc, "ERROR assembling: NULL input"); - return 0; - } - - if (enc->in_frame_count_ == 0) { - MarkError(enc, "ERROR: No frames to assemble"); - return 0; - } - - if (!enc->got_null_frame_ && enc->in_frame_count_ > 1 && enc->count_ > 0) { - // set duration of the last frame to be avg of durations of previous frames. - const double delta_time = enc->prev_timestamp_ - enc->first_timestamp_; - const int average_duration = (int)(delta_time / (enc->in_frame_count_ - 1)); - if (!IncreasePreviousDuration(enc, average_duration)) { - return 0; - } - } - - // Flush any remaining frames. - enc->flush_count_ = enc->count_; - if (!FlushFrames(enc)) { - return 0; - } - - // Set definitive canvas size. - mux = enc->mux_; - err = WebPMuxSetCanvasSize(mux, enc->canvas_width_, enc->canvas_height_); - if (err != WEBP_MUX_OK) goto Err; - - err = WebPMuxSetAnimationParams(mux, &enc->options_.anim_params); - if (err != WEBP_MUX_OK) goto Err; - - // Assemble into a WebP bitstream. - err = WebPMuxAssemble(mux, webp_data); - if (err != WEBP_MUX_OK) goto Err; - - if (enc->out_frame_count_ == 1) { - err = OptimizeSingleFrame(enc, webp_data); - if (err != WEBP_MUX_OK) goto Err; - } - return 1; - - Err: - MarkError2(enc, "ERROR assembling WebP", err); - return 0; -} - -const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc) { - if (enc == NULL) return NULL; - return enc->error_str_; -} - -// ----------------------------------------------------------------------------- diff --git a/drivers/webp/mux/muxi.h b/drivers/webp/mux/muxi.h deleted file mode 100644 index 3f6428c4df..0000000000 --- a/drivers/webp/mux/muxi.h +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Internal header for mux library. -// -// Author: Urvang (urvang@google.com) - -#ifndef WEBP_MUX_MUXI_H_ -#define WEBP_MUX_MUXI_H_ - -#include <stdlib.h> -#include "../dec/vp8i.h" -#include "../dec/vp8li.h" -#include "webp/mux.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Defines and constants. - -#define MUX_MAJ_VERSION 0 -#define MUX_MIN_VERSION 3 -#define MUX_REV_VERSION 1 - -// Chunk object. -typedef struct WebPChunk WebPChunk; -struct WebPChunk { - uint32_t tag_; - int owner_; // True if *data_ memory is owned internally. - // VP8X, ANIM, and other internally created chunks - // like ANMF/FRGM are always owned. - WebPData data_; - WebPChunk* next_; -}; - -// MuxImage object. Store a full WebP image (including ANMF/FRGM chunk, ALPH -// chunk and VP8/VP8L chunk), -typedef struct WebPMuxImage WebPMuxImage; -struct WebPMuxImage { - WebPChunk* header_; // Corresponds to WEBP_CHUNK_ANMF/WEBP_CHUNK_FRGM. - WebPChunk* alpha_; // Corresponds to WEBP_CHUNK_ALPHA. - WebPChunk* img_; // Corresponds to WEBP_CHUNK_IMAGE. - WebPChunk* unknown_; // Corresponds to WEBP_CHUNK_UNKNOWN. - int width_; - int height_; - int has_alpha_; // Through ALPH chunk or as part of VP8L. - int is_partial_; // True if only some of the chunks are filled. - WebPMuxImage* next_; -}; - -// Main mux object. Stores data chunks. -struct WebPMux { - WebPMuxImage* images_; - WebPChunk* iccp_; - WebPChunk* exif_; - WebPChunk* xmp_; - WebPChunk* anim_; - WebPChunk* vp8x_; - - WebPChunk* unknown_; - int canvas_width_; - int canvas_height_; -}; - -// CHUNK_INDEX enum: used for indexing within 'kChunks' (defined below) only. -// Note: the reason for having two enums ('WebPChunkId' and 'CHUNK_INDEX') is to -// allow two different chunks to have the same id (e.g. WebPChunkId -// 'WEBP_CHUNK_IMAGE' can correspond to CHUNK_INDEX 'IDX_VP8' or 'IDX_VP8L'). -typedef enum { - IDX_VP8X = 0, - IDX_ICCP, - IDX_ANIM, - IDX_ANMF, - IDX_FRGM, - IDX_ALPHA, - IDX_VP8, - IDX_VP8L, - IDX_EXIF, - IDX_XMP, - IDX_UNKNOWN, - - IDX_NIL, - IDX_LAST_CHUNK -} CHUNK_INDEX; - -#define NIL_TAG 0x00000000u // To signal void chunk. - -typedef struct { - uint32_t tag; - WebPChunkId id; - uint32_t size; -} ChunkInfo; - -extern const ChunkInfo kChunks[IDX_LAST_CHUNK]; - -//------------------------------------------------------------------------------ -// Chunk object management. - -// Initialize. -void ChunkInit(WebPChunk* const chunk); - -// Get chunk index from chunk tag. Returns IDX_UNKNOWN if not found. -CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag); - -// Get chunk id from chunk tag. Returns WEBP_CHUNK_UNKNOWN if not found. -WebPChunkId ChunkGetIdFromTag(uint32_t tag); - -// Convert a fourcc string to a tag. -uint32_t ChunkGetTagFromFourCC(const char fourcc[4]); - -// Get chunk index from fourcc. Returns IDX_UNKNOWN if given fourcc is unknown. -CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]); - -// Search for nth chunk with given 'tag' in the chunk list. -// nth = 0 means "last of the list". -WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag); - -// Fill the chunk with the given data. -WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data, - int copy_data, uint32_t tag); - -// Sets 'chunk' at nth position in the 'chunk_list'. -// nth = 0 has the special meaning "last of the list". -// On success ownership is transferred from 'chunk' to the 'chunk_list'. -WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list, - uint32_t nth); - -// Releases chunk and returns chunk->next_. -WebPChunk* ChunkRelease(WebPChunk* const chunk); - -// Deletes given chunk & returns chunk->next_. -WebPChunk* ChunkDelete(WebPChunk* const chunk); - -// Deletes all chunks in the given chunk list. -void ChunkListDelete(WebPChunk** const chunk_list); - -// Returns size of the chunk including chunk header and padding byte (if any). -static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) { - return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U); -} - -// Size of a chunk including header and padding. -static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) { - const size_t data_size = chunk->data_.size; - assert(data_size < MAX_CHUNK_PAYLOAD); - return SizeWithPadding(data_size); -} - -// Total size of a list of chunks. -size_t ChunkListDiskSize(const WebPChunk* chunk_list); - -// Write out the given list of chunks into 'dst'. -uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst); - -//------------------------------------------------------------------------------ -// MuxImage object management. - -// Initialize. -void MuxImageInit(WebPMuxImage* const wpi); - -// Releases image 'wpi' and returns wpi->next. -WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi); - -// Delete image 'wpi' and return the next image in the list or NULL. -// 'wpi' can be NULL. -WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi); - -// Count number of images matching the given tag id in the 'wpi_list'. -// If id == WEBP_CHUNK_NIL, all images will be matched. -int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id); - -// Update width/height/has_alpha info from chunks within wpi. -// Also remove ALPH chunk if not needed. -int MuxImageFinalize(WebPMuxImage* const wpi); - -// Check if given ID corresponds to an image related chunk. -static WEBP_INLINE int IsWPI(WebPChunkId id) { - switch (id) { - case WEBP_CHUNK_ANMF: - case WEBP_CHUNK_FRGM: - case WEBP_CHUNK_ALPHA: - case WEBP_CHUNK_IMAGE: return 1; - default: return 0; - } -} - -// Pushes 'wpi' at the end of 'wpi_list'. -WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list); - -// Delete nth image in the image list. -WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth); - -// Get nth image in the image list. -WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, - WebPMuxImage** wpi); - -// Total size of the given image. -size_t MuxImageDiskSize(const WebPMuxImage* const wpi); - -// Write out the given image into 'dst'. -uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst); - -//------------------------------------------------------------------------------ -// Helper methods for mux. - -// Checks if the given image list contains at least one image with alpha. -int MuxHasAlpha(const WebPMuxImage* images); - -// Write out RIFF header into 'data', given total data size 'size'. -uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size); - -// Returns the list where chunk with given ID is to be inserted in mux. -WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id); - -// Validates the given mux object. -WebPMuxError MuxValidate(const WebPMux* const mux); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_MUX_MUXI_H_ */ diff --git a/drivers/webp/utils/bit_reader.c b/drivers/webp/utils/bit_reader.c deleted file mode 100644 index 13c6cf316e..0000000000 --- a/drivers/webp/utils/bit_reader.c +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Boolean decoder non-inlined methods -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifdef HAVE_CONFIG_H -#include "webp/config.h" -#endif - -#include "./bit_reader_inl.h" -#include "../utils/utils.h" - -//------------------------------------------------------------------------------ -// VP8BitReader - -void VP8BitReaderSetBuffer(VP8BitReader* const br, - const uint8_t* const start, - size_t size) { - br->buf_ = start; - br->buf_end_ = start + size; - br->buf_max_ = - (size >= sizeof(lbit_t)) ? start + size - sizeof(lbit_t) + 1 - : start; -} - -void VP8InitBitReader(VP8BitReader* const br, - const uint8_t* const start, size_t size) { - assert(br != NULL); - assert(start != NULL); - assert(size < (1u << 31)); // limit ensured by format and upstream checks - br->range_ = 255 - 1; - br->value_ = 0; - br->bits_ = -8; // to load the very first 8bits - br->eof_ = 0; - VP8BitReaderSetBuffer(br, start, size); -#ifdef JAVASCRIPT_ENABLED // html5 required aligned reads - while(((uintptr_t)br->buf_ & 1) != 0 && !br->eof_) - VP8LoadFinalBytes(br); -#else - VP8LoadNewBytes(br); -#endif -} - -void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) { - if (br->buf_ != NULL) { - br->buf_ += offset; - br->buf_end_ += offset; - br->buf_max_ += offset; - } -} - -const uint8_t kVP8Log2Range[128] = { - 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, - 0 -}; - -// range = ((range - 1) << kVP8Log2Range[range]) + 1 -const uint8_t kVP8NewRange[128] = { - 127, 127, 191, 127, 159, 191, 223, 127, - 143, 159, 175, 191, 207, 223, 239, 127, - 135, 143, 151, 159, 167, 175, 183, 191, - 199, 207, 215, 223, 231, 239, 247, 127, - 131, 135, 139, 143, 147, 151, 155, 159, - 163, 167, 171, 175, 179, 183, 187, 191, - 195, 199, 203, 207, 211, 215, 219, 223, - 227, 231, 235, 239, 243, 247, 251, 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, 127 -}; - -void VP8LoadFinalBytes(VP8BitReader* const br) { - assert(br != NULL && br->buf_ != NULL); - // Only read 8bits at a time - if (br->buf_ < br->buf_end_) { - br->bits_ += 8; - br->value_ = (bit_t)(*br->buf_++) | (br->value_ << 8); - } else if (!br->eof_) { - br->value_ <<= 8; - br->bits_ += 8; - br->eof_ = 1; - } else { - br->bits_ = 0; // This is to avoid undefined behaviour with shifts. - } -} - -//------------------------------------------------------------------------------ -// Higher-level calls - -uint32_t VP8GetValue(VP8BitReader* const br, int bits) { - uint32_t v = 0; - while (bits-- > 0) { - v |= VP8GetBit(br, 0x80) << bits; - } - return v; -} - -int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) { - const int value = VP8GetValue(br, bits); - return VP8Get(br) ? -value : value; -} - -//------------------------------------------------------------------------------ -// VP8LBitReader - -#define VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits. - -#if defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \ - defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64__) || defined(_M_X64) -#define VP8L_USE_FAST_LOAD -#endif - -static const uint32_t kBitMask[VP8L_MAX_NUM_BIT_READ + 1] = { - 0, - 0x000001, 0x000003, 0x000007, 0x00000f, - 0x00001f, 0x00003f, 0x00007f, 0x0000ff, - 0x0001ff, 0x0003ff, 0x0007ff, 0x000fff, - 0x001fff, 0x003fff, 0x007fff, 0x00ffff, - 0x01ffff, 0x03ffff, 0x07ffff, 0x0fffff, - 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff -}; - -void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const start, - size_t length) { - size_t i; - vp8l_val_t value = 0; - assert(br != NULL); - assert(start != NULL); - assert(length < 0xfffffff8u); // can't happen with a RIFF chunk. - - br->len_ = length; - br->val_ = 0; - br->bit_pos_ = 0; - br->eos_ = 0; - - if (length > sizeof(br->val_)) { - length = sizeof(br->val_); - } - for (i = 0; i < length; ++i) { - value |= (vp8l_val_t)start[i] << (8 * i); - } - br->val_ = value; - br->pos_ = length; - br->buf_ = start; -} - -void VP8LBitReaderSetBuffer(VP8LBitReader* const br, - const uint8_t* const buf, size_t len) { - assert(br != NULL); - assert(buf != NULL); - assert(len < 0xfffffff8u); // can't happen with a RIFF chunk. - br->buf_ = buf; - br->len_ = len; - // pos_ > len_ should be considered a param error. - br->eos_ = (br->pos_ > br->len_) || VP8LIsEndOfStream(br); -} - -static void VP8LSetEndOfStream(VP8LBitReader* const br) { - br->eos_ = 1; - br->bit_pos_ = 0; // To avoid undefined behaviour with shifts. -} - -// If not at EOS, reload up to VP8L_LBITS byte-by-byte -static void ShiftBytes(VP8LBitReader* const br) { - while (br->bit_pos_ >= 8 && br->pos_ < br->len_) { - br->val_ >>= 8; - br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8); - ++br->pos_; - br->bit_pos_ -= 8; - } - if (VP8LIsEndOfStream(br)) { - VP8LSetEndOfStream(br); - } -} - -void VP8LDoFillBitWindow(VP8LBitReader* const br) { - assert(br->bit_pos_ >= VP8L_WBITS); -#if defined(VP8L_USE_FAST_LOAD) - if (br->pos_ + sizeof(br->val_) < br->len_) { - br->val_ >>= VP8L_WBITS; - br->bit_pos_ -= VP8L_WBITS; - br->val_ |= (vp8l_val_t)HToLE32(WebPMemToUint32(br->buf_ + br->pos_)) << - (VP8L_LBITS - VP8L_WBITS); - br->pos_ += VP8L_LOG8_WBITS; - return; - } -#endif - ShiftBytes(br); // Slow path. -} - -uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) { - assert(n_bits >= 0); - // Flag an error if end_of_stream or n_bits is more than allowed limit. - if (!br->eos_ && n_bits <= VP8L_MAX_NUM_BIT_READ) { - const uint32_t val = VP8LPrefetchBits(br) & kBitMask[n_bits]; - const int new_bits = br->bit_pos_ + n_bits; - br->bit_pos_ = new_bits; - ShiftBytes(br); - return val; - } else { - VP8LSetEndOfStream(br); - return 0; - } -} - -//------------------------------------------------------------------------------ diff --git a/drivers/webp/utils/bit_reader.h b/drivers/webp/utils/bit_reader.h deleted file mode 100644 index c2dcc711c0..0000000000 --- a/drivers/webp/utils/bit_reader.h +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Boolean decoder -// -// Author: Skal (pascal.massimino@gmail.com) -// Vikas Arora (vikaas.arora@gmail.com) - -#ifndef WEBP_UTILS_BIT_READER_H_ -#define WEBP_UTILS_BIT_READER_H_ - -#include <assert.h> -#ifdef _MSC_VER -#include <stdlib.h> // _byteswap_ulong -#endif -#include "webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// The Boolean decoder needs to maintain infinite precision on the value_ field. -// However, since range_ is only 8bit, we only need an active window of 8 bits -// for value_. Left bits (MSB) gets zeroed and shifted away when value_ falls -// below 128, range_ is updated, and fresh bits read from the bitstream are -// brought in as LSB. To avoid reading the fresh bits one by one (slow), we -// cache BITS of them ahead. The total of (BITS + 8) bits must fit into a -// natural register (with type bit_t). To fetch BITS bits from bitstream we -// use a type lbit_t. -// -// BITS can be any multiple of 8 from 8 to 56 (inclusive). -// Pick values that fit natural register size. - -#ifdef JAVASCRIPT_ENABLED - -#define BITS 16 - -#else - -#if defined(__i386__) || defined(_M_IX86) // x86 32bit -#define BITS 24 -#elif defined(__x86_64__) || defined(_M_X64) // x86 64bit -#define BITS 56 -#elif defined(__arm__) || defined(_M_ARM) // ARM -#define BITS 24 -#elif defined(__aarch64__) // ARM 64bit -#define BITS 56 -#elif defined(__mips__) // MIPS -#define BITS 24 -#else // reasonable default -#define BITS 24 -#endif - -#endif - -//------------------------------------------------------------------------------ -// Derived types and constants: -// bit_t = natural register type for storing 'value_' (which is BITS+8 bits) -// range_t = register for 'range_' (which is 8bits only) - -#if (BITS > 24) -typedef uint64_t bit_t; -#else -typedef uint32_t bit_t; -#endif - -typedef uint32_t range_t; - -//------------------------------------------------------------------------------ -// Bitreader - -typedef struct VP8BitReader VP8BitReader; -struct VP8BitReader { - // boolean decoder (keep the field ordering as is!) - bit_t value_; // current value - range_t range_; // current range minus 1. In [127, 254] interval. - int bits_; // number of valid bits left - // read buffer - const uint8_t* buf_; // next byte to be read - const uint8_t* buf_end_; // end of read buffer - const uint8_t* buf_max_; // max packed-read position on buffer - int eof_; // true if input is exhausted -}; - -// Initialize the bit reader and the boolean decoder. -void VP8InitBitReader(VP8BitReader* const br, - const uint8_t* const start, size_t size); -// Sets the working read buffer. -void VP8BitReaderSetBuffer(VP8BitReader* const br, - const uint8_t* const start, size_t size); - -// Update internal pointers to displace the byte buffer by the -// relative offset 'offset'. -void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset); - -// return the next value made of 'num_bits' bits -uint32_t VP8GetValue(VP8BitReader* const br, int num_bits); -static WEBP_INLINE uint32_t VP8Get(VP8BitReader* const br) { - return VP8GetValue(br, 1); -} - -// return the next value with sign-extension. -int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits); - -// bit_reader_inl.h will implement the following methods: -// static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) -// static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) -// and should be included by the .c files that actually need them. -// This is to avoid recompiling the whole library whenever this file is touched, -// and also allowing platform-specific ad-hoc hacks. - -// ----------------------------------------------------------------------------- -// Bitreader for lossless format - -// maximum number of bits (inclusive) the bit-reader can handle: -#define VP8L_MAX_NUM_BIT_READ 24 - -#define VP8L_LBITS 64 // Number of bits prefetched (= bit-size of vp8l_val_t). -#define VP8L_WBITS 32 // Minimum number of bytes ready after VP8LFillBitWindow. - -typedef uint64_t vp8l_val_t; // right now, this bit-reader can only use 64bit. - -typedef struct { - vp8l_val_t val_; // pre-fetched bits - const uint8_t* buf_; // input byte buffer - size_t len_; // buffer length - size_t pos_; // byte position in buf_ - int bit_pos_; // current bit-reading position in val_ - int eos_; // true if a bit was read past the end of buffer -} VP8LBitReader; - -void VP8LInitBitReader(VP8LBitReader* const br, - const uint8_t* const start, - size_t length); - -// Sets a new data buffer. -void VP8LBitReaderSetBuffer(VP8LBitReader* const br, - const uint8_t* const buffer, size_t length); - -// Reads the specified number of bits from read buffer. -// Flags an error in case end_of_stream or n_bits is more than the allowed limit -// of VP8L_MAX_NUM_BIT_READ (inclusive). -// Flags eos_ if this read attempt is going to cross the read buffer. -uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits); - -// Return the prefetched bits, so they can be looked up. -static WEBP_INLINE uint32_t VP8LPrefetchBits(VP8LBitReader* const br) { - return (uint32_t)(br->val_ >> (br->bit_pos_ & (VP8L_LBITS - 1))); -} - -// Returns true if there was an attempt at reading bit past the end of -// the buffer. Doesn't set br->eos_ flag. -static WEBP_INLINE int VP8LIsEndOfStream(const VP8LBitReader* const br) { - assert(br->pos_ <= br->len_); - return br->eos_ || ((br->pos_ == br->len_) && (br->bit_pos_ > VP8L_LBITS)); -} - -// For jumping over a number of bits in the bit stream when accessed with -// VP8LPrefetchBits and VP8LFillBitWindow. -static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) { - br->bit_pos_ = val; - br->eos_ = VP8LIsEndOfStream(br); -} - -// Advances the read buffer by 4 bytes to make room for reading next 32 bits. -// Speed critical, but infrequent part of the code can be non-inlined. -extern void VP8LDoFillBitWindow(VP8LBitReader* const br); -static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) { - if (br->bit_pos_ >= VP8L_WBITS) VP8LDoFillBitWindow(br); -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_BIT_READER_H_ */ diff --git a/drivers/webp/utils/bit_reader_inl.h b/drivers/webp/utils/bit_reader_inl.h deleted file mode 100644 index 21faf14d83..0000000000 --- a/drivers/webp/utils/bit_reader_inl.h +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2014 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Specific inlined methods for boolean decoder [VP8GetBit() ...] -// This file should be included by the .c sources that actually need to call -// these methods. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_BIT_READER_INL_H_ -#define WEBP_UTILS_BIT_READER_INL_H_ - -#ifdef HAVE_CONFIG_H -#include "webp/config.h" -#endif - -#ifdef WEBP_FORCE_ALIGNED -#include <string.h> // memcpy -#endif - -#include "../dsp/dsp.h" -#include "./bit_reader.h" -#include "./endian_inl.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Derived type lbit_t = natural type for memory I/O - -#if (BITS > 32) -typedef uint64_t lbit_t; -#elif (BITS > 16) -typedef uint32_t lbit_t; -#elif (BITS > 8) -typedef uint16_t lbit_t; -#else -typedef uint8_t lbit_t; -#endif - -extern const uint8_t kVP8Log2Range[128]; -extern const uint8_t kVP8NewRange[128]; - -// special case for the tail byte-reading -void VP8LoadFinalBytes(VP8BitReader* const br); - -//------------------------------------------------------------------------------ -// Inlined critical functions - -// makes sure br->value_ has at least BITS bits worth of data -static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE -void VP8LoadNewBytes(VP8BitReader* const br) { - assert(br != NULL && br->buf_ != NULL); - // Read 'BITS' bits at a time if possible. - if (br->buf_ < br->buf_max_) { - // convert memory type to register type (with some zero'ing!) - bit_t bits; -#if defined(WEBP_FORCE_ALIGNED) - lbit_t in_bits; - memcpy(&in_bits, br->buf_, sizeof(in_bits)); -#elif defined(WEBP_USE_MIPS32) - // This is needed because of un-aligned read. - lbit_t in_bits; - lbit_t* p_buf_ = (lbit_t*)br->buf_; - __asm__ volatile( - ".set push \n\t" - ".set at \n\t" - ".set macro \n\t" - "ulw %[in_bits], 0(%[p_buf_]) \n\t" - ".set pop \n\t" - : [in_bits]"=r"(in_bits) - : [p_buf_]"r"(p_buf_) - : "memory", "at" - ); -#else - const lbit_t in_bits = *(const lbit_t*)br->buf_; -#endif - br->buf_ += BITS >> 3; -#if !defined(WORDS_BIGENDIAN) -#if (BITS > 32) - bits = BSwap64(in_bits); - bits >>= 64 - BITS; -#elif (BITS >= 24) - bits = BSwap32(in_bits); - bits >>= (32 - BITS); -#elif (BITS == 16) - bits = BSwap16(in_bits); -#else // BITS == 8 - bits = (bit_t)in_bits; -#endif // BITS > 32 -#else // WORDS_BIGENDIAN - bits = (bit_t)in_bits; - if (BITS != 8 * sizeof(bit_t)) bits >>= (8 * sizeof(bit_t) - BITS); -#endif - br->value_ = bits | (br->value_ << BITS); - br->bits_ += BITS; - } else { - VP8LoadFinalBytes(br); // no need to be inlined - } -} - -// Read a bit with proba 'prob'. Speed-critical function! -static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) { - // Don't move this declaration! It makes a big speed difference to store - // 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't - // alter br->range_ value. - range_t range = br->range_; - if (br->bits_ < 0) { - VP8LoadNewBytes(br); - } - { - const int pos = br->bits_; - const range_t split = (range * prob) >> 8; - const range_t value = (range_t)(br->value_ >> pos); -#if defined(__arm__) || defined(_M_ARM) // ARM-specific - const int bit = ((int)(split - value) >> 31) & 1; - if (value > split) { - range -= split + 1; - br->value_ -= (bit_t)(split + 1) << pos; - } else { - range = split; - } -#else // faster version on x86 - int bit; // Don't use 'const int bit = (value > split);", it's slower. - if (value > split) { - range -= split + 1; - br->value_ -= (bit_t)(split + 1) << pos; - bit = 1; - } else { - range = split; - bit = 0; - } -#endif - if (range <= (range_t)0x7e) { - const int shift = kVP8Log2Range[range]; - range = kVP8NewRange[range]; - br->bits_ -= shift; - } - br->range_ = range; - return bit; - } -} - -// simplified version of VP8GetBit() for prob=0x80 (note shift is always 1 here) -static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) { - if (br->bits_ < 0) { - VP8LoadNewBytes(br); - } - { - const int pos = br->bits_; - const range_t split = br->range_ >> 1; - const range_t value = (range_t)(br->value_ >> pos); - const int32_t mask = (int32_t)(split - value) >> 31; // -1 or 0 - br->bits_ -= 1; - br->range_ += mask; - br->range_ |= 1; - br->value_ -= (bit_t)((split + 1) & mask) << pos; - return (v ^ mask) - mask; - } -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // WEBP_UTILS_BIT_READER_INL_H_ diff --git a/drivers/webp/utils/bit_writer.h b/drivers/webp/utils/bit_writer.h deleted file mode 100644 index 867a5ee055..0000000000 --- a/drivers/webp/utils/bit_writer.h +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Bit writing and boolean coder -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_BIT_WRITER_H_ -#define WEBP_UTILS_BIT_WRITER_H_ - -#include "webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Bit-writing - -typedef struct VP8BitWriter VP8BitWriter; -struct VP8BitWriter { - int32_t range_; // range-1 - int32_t value_; - int run_; // number of outstanding bits - int nb_bits_; // number of pending bits - uint8_t* buf_; // internal buffer. Re-allocated regularly. Not owned. - size_t pos_; - size_t max_pos_; - int error_; // true in case of error -}; - -// Initialize the object. Allocates some initial memory based on expected_size. -int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size); -// Finalize the bitstream coding. Returns a pointer to the internal buffer. -uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw); -// Release any pending memory and zeroes the object. Not a mandatory call. -// Only useful in case of error, when the internal buffer hasn't been grabbed! -void VP8BitWriterWipeOut(VP8BitWriter* const bw); - -int VP8PutBit(VP8BitWriter* const bw, int bit, int prob); -int VP8PutBitUniform(VP8BitWriter* const bw, int bit); -void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits); -void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits); - -// Appends some bytes to the internal buffer. Data is copied. -int VP8BitWriterAppend(VP8BitWriter* const bw, - const uint8_t* data, size_t size); - -// return approximate write position (in bits) -static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) { - return (uint64_t)(bw->pos_ + bw->run_) * 8 + 8 + bw->nb_bits_; -} - -// Returns a pointer to the internal buffer. -static WEBP_INLINE uint8_t* VP8BitWriterBuf(const VP8BitWriter* const bw) { - return bw->buf_; -} -// Returns the size of the internal buffer. -static WEBP_INLINE size_t VP8BitWriterSize(const VP8BitWriter* const bw) { - return bw->pos_; -} - -//------------------------------------------------------------------------------ -// VP8LBitWriter - -#if defined(__x86_64__) || defined(_M_X64) // 64bit -typedef uint64_t vp8l_atype_t; // accumulator type -typedef uint32_t vp8l_wtype_t; // writing type -#define WSWAP HToLE32 -#define VP8L_WRITER_BYTES 4 // sizeof(vp8l_wtype_t) -#define VP8L_WRITER_BITS 32 // 8 * sizeof(vp8l_wtype_t) -#define VP8L_WRITER_MAX_BITS 64 // 8 * sizeof(vp8l_atype_t) -#else -typedef uint32_t vp8l_atype_t; -typedef uint16_t vp8l_wtype_t; -#define WSWAP HToLE16 -#define VP8L_WRITER_BYTES 2 -#define VP8L_WRITER_BITS 16 -#define VP8L_WRITER_MAX_BITS 32 -#endif - -typedef struct { - vp8l_atype_t bits_; // bit accumulator - int used_; // number of bits used in accumulator - uint8_t* buf_; // start of buffer - uint8_t* cur_; // current write position - uint8_t* end_; // end of buffer - - // After all bits are written (VP8LBitWriterFinish()), the caller must observe - // the state of error_. A value of 1 indicates that a memory allocation - // failure has happened during bit writing. A value of 0 indicates successful - // writing of bits. - int error_; -} VP8LBitWriter; - -static WEBP_INLINE size_t VP8LBitWriterNumBytes(VP8LBitWriter* const bw) { - return (bw->cur_ - bw->buf_) + ((bw->used_ + 7) >> 3); -} - -// Returns false in case of memory allocation error. -int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size); -// Finalize the bitstream coding. Returns a pointer to the internal buffer. -uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw); -// Release any pending memory and zeroes the object. -void VP8LBitWriterWipeOut(VP8LBitWriter* const bw); - -// Internal function for VP8LPutBits flushing 32 bits from the written state. -void VP8LPutBitsFlushBits(VP8LBitWriter* const bw); - -// PutBits internal function used in the 16 bit vp8l_wtype_t case. -void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits); - -// This function writes bits into bytes in increasing addresses (little endian), -// and within a byte least-significant-bit first. -// This function can write up to 32 bits in one go, but VP8LBitReader can only -// read 24 bits max (VP8L_MAX_NUM_BIT_READ). -// VP8LBitWriter's error_ flag is set in case of memory allocation error. -static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw, - uint32_t bits, int n_bits) { - if (sizeof(vp8l_wtype_t) == 4) { - if (n_bits > 0) { - if (bw->used_ >= 32) { - VP8LPutBitsFlushBits(bw); - } - bw->bits_ |= (vp8l_atype_t)bits << bw->used_; - bw->used_ += n_bits; - } - } else { - VP8LPutBitsInternal(bw, bits, n_bits); - } -} - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_BIT_WRITER_H_ */ diff --git a/drivers/webp/utils/color_cache.h b/drivers/webp/utils/color_cache.h deleted file mode 100644 index 34299e4c4e..0000000000 --- a/drivers/webp/utils/color_cache.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Color Cache for WebP Lossless -// -// Authors: Jyrki Alakuijala (jyrki@google.com) -// Urvang Joshi (urvang@google.com) - -#ifndef WEBP_UTILS_COLOR_CACHE_H_ -#define WEBP_UTILS_COLOR_CACHE_H_ - -#include "webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Main color cache struct. -typedef struct { - uint32_t *colors_; // color entries - int hash_shift_; // Hash shift: 32 - hash_bits_. - int hash_bits_; -} VP8LColorCache; - -static const uint32_t kHashMul = 0x1e35a7bd; - -static WEBP_INLINE uint32_t VP8LColorCacheLookup( - const VP8LColorCache* const cc, uint32_t key) { - assert((key >> cc->hash_bits_) == 0u); - return cc->colors_[key]; -} - -static WEBP_INLINE void VP8LColorCacheSet(const VP8LColorCache* const cc, - uint32_t key, uint32_t argb) { - assert((key >> cc->hash_bits_) == 0u); - cc->colors_[key] = argb; -} - -static WEBP_INLINE void VP8LColorCacheInsert(const VP8LColorCache* const cc, - uint32_t argb) { - const uint32_t key = (kHashMul * argb) >> cc->hash_shift_; - cc->colors_[key] = argb; -} - -static WEBP_INLINE int VP8LColorCacheGetIndex(const VP8LColorCache* const cc, - uint32_t argb) { - return (kHashMul * argb) >> cc->hash_shift_; -} - -static WEBP_INLINE int VP8LColorCacheContains(const VP8LColorCache* const cc, - uint32_t argb) { - const uint32_t key = (kHashMul * argb) >> cc->hash_shift_; - return (cc->colors_[key] == argb); -} - -//------------------------------------------------------------------------------ - -// Initializes the color cache with 'hash_bits' bits for the keys. -// Returns false in case of memory error. -int VP8LColorCacheInit(VP8LColorCache* const color_cache, int hash_bits); - -void VP8LColorCacheCopy(const VP8LColorCache* const src, - VP8LColorCache* const dst); - -// Delete the memory associated to color cache. -void VP8LColorCacheClear(VP8LColorCache* const color_cache); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} -#endif - -#endif // WEBP_UTILS_COLOR_CACHE_H_ diff --git a/drivers/webp/utils/filters.h b/drivers/webp/utils/filters.h deleted file mode 100644 index 4aba3fd3b7..0000000000 --- a/drivers/webp/utils/filters.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Spatial prediction using various filters -// -// Author: Urvang (urvang@google.com) - -#ifndef WEBP_UTILS_FILTERS_H_ -#define WEBP_UTILS_FILTERS_H_ - -#include "webp/types.h" -#include "../dsp/dsp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Fast estimate of a potentially good filter. -WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data, - int width, int height, int stride); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_FILTERS_H_ */ diff --git a/drivers/webp/utils/huffman.c b/drivers/webp/utils/huffman.c deleted file mode 100644 index 7c9d83db9a..0000000000 --- a/drivers/webp/utils/huffman.c +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for building and looking up Huffman trees. -// -// Author: Urvang Joshi (urvang@google.com) - -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include "./huffman.h" -#include "webp/format_constants.h" -#include "./utils.h" - -// Huffman data read via DecodeImageStream is represented in two (red and green) -// bytes. -#define MAX_HTREE_GROUPS 0x10000 - -HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups) { - HTreeGroup* const htree_groups = - (HTreeGroup*)WebPSafeMalloc(num_htree_groups, sizeof(*htree_groups)); - if (htree_groups == NULL) { - return NULL; - } - assert(num_htree_groups <= MAX_HTREE_GROUPS); - return htree_groups; -} - -void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups) { - if (htree_groups != NULL) { - WebPSafeFree(htree_groups); - } -} - -// Returns reverse(reverse(key, len) + 1, len), where reverse(key, len) is the -// bit-wise reversal of the len least significant bits of key. -static WEBP_INLINE uint32_t GetNextKey(uint32_t key, int len) { - uint32_t step = 1 << (len - 1); - while (key & step) { - step >>= 1; - } - return (key & (step - 1)) + step; -} - -// Stores code in table[0], table[step], table[2*step], ..., table[end]. -// Assumes that end is an integer multiple of step. -static WEBP_INLINE void ReplicateValue(HuffmanCode* table, - int step, int end, - HuffmanCode code) { - assert(end % step == 0); - do { - end -= step; - table[end] = code; - } while (end > 0); -} - -// Returns the table width of the next 2nd level table. count is the histogram -// of bit lengths for the remaining symbols, len is the code length of the next -// processed symbol -static WEBP_INLINE int NextTableBitSize(const int* const count, - int len, int root_bits) { - int left = 1 << (len - root_bits); - while (len < MAX_ALLOWED_CODE_LENGTH) { - left -= count[len]; - if (left <= 0) break; - ++len; - left <<= 1; - } - return len - root_bits; -} - -int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits, - const int code_lengths[], int code_lengths_size) { - HuffmanCode* table = root_table; // next available space in table - int total_size = 1 << root_bits; // total size root table + 2nd level table - int* sorted = NULL; // symbols sorted by code length - int len; // current code length - int symbol; // symbol index in original or sorted table - // number of codes of each length: - int count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 }; - // offsets in sorted table for each length: - int offset[MAX_ALLOWED_CODE_LENGTH + 1]; - - assert(code_lengths_size != 0); - assert(code_lengths != NULL); - assert(root_table != NULL); - assert(root_bits > 0); - - // Build histogram of code lengths. - for (symbol = 0; symbol < code_lengths_size; ++symbol) { - if (code_lengths[symbol] > MAX_ALLOWED_CODE_LENGTH) { - return 0; - } - ++count[code_lengths[symbol]]; - } - - // Error, all code lengths are zeros. - if (count[0] == code_lengths_size) { - return 0; - } - - // Generate offsets into sorted symbol table by code length. - offset[1] = 0; - for (len = 1; len < MAX_ALLOWED_CODE_LENGTH; ++len) { - if (count[len] > (1 << len)) { - return 0; - } - offset[len + 1] = offset[len] + count[len]; - } - - sorted = (int*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted)); - if (sorted == NULL) { - return 0; - } - - // Sort symbols by length, by symbol order within each length. - for (symbol = 0; symbol < code_lengths_size; ++symbol) { - const int symbol_code_length = code_lengths[symbol]; - if (code_lengths[symbol] > 0) { - sorted[offset[symbol_code_length]++] = symbol; - } - } - - // Special case code with only one value. - if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) { - HuffmanCode code; - code.bits = 0; - code.value = (uint16_t)sorted[0]; - ReplicateValue(table, 1, total_size, code); - WebPSafeFree(sorted); - return total_size; - } - - { - int step; // step size to replicate values in current table - uint32_t low = -1; // low bits for current root entry - uint32_t mask = total_size - 1; // mask for low bits - uint32_t key = 0; // reversed prefix code - int num_nodes = 1; // number of Huffman tree nodes - int num_open = 1; // number of open branches in current tree level - int table_bits = root_bits; // key length of current table - int table_size = 1 << table_bits; // size of current table - symbol = 0; - // Fill in root table. - for (len = 1, step = 2; len <= root_bits; ++len, step <<= 1) { - num_open <<= 1; - num_nodes += num_open; - num_open -= count[len]; - if (num_open < 0) { - WebPSafeFree(sorted); - return 0; - } - for (; count[len] > 0; --count[len]) { - HuffmanCode code; - code.bits = (uint8_t)len; - code.value = (uint16_t)sorted[symbol++]; - ReplicateValue(&table[key], step, table_size, code); - key = GetNextKey(key, len); - } - } - - // Fill in 2nd level tables and add pointers to root table. - for (len = root_bits + 1, step = 2; len <= MAX_ALLOWED_CODE_LENGTH; - ++len, step <<= 1) { - num_open <<= 1; - num_nodes += num_open; - num_open -= count[len]; - if (num_open < 0) { - WebPSafeFree(sorted); - return 0; - } - for (; count[len] > 0; --count[len]) { - HuffmanCode code; - if ((key & mask) != low) { - table += table_size; - table_bits = NextTableBitSize(count, len, root_bits); - table_size = 1 << table_bits; - total_size += table_size; - low = key & mask; - root_table[low].bits = (uint8_t)(table_bits + root_bits); - root_table[low].value = (uint16_t)((table - root_table) - low); - } - code.bits = (uint8_t)(len - root_bits); - code.value = (uint16_t)sorted[symbol++]; - ReplicateValue(&table[key >> root_bits], step, table_size, code); - key = GetNextKey(key, len); - } - } - - // Check if tree is full. - if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) { - WebPSafeFree(sorted); - return 0; - } - } - - WebPSafeFree(sorted); - return total_size; -} diff --git a/drivers/webp/utils/huffman.h b/drivers/webp/utils/huffman.h deleted file mode 100644 index a8cc0da1c3..0000000000 --- a/drivers/webp/utils/huffman.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for building and looking up Huffman trees. -// -// Author: Urvang Joshi (urvang@google.com) - -#ifndef WEBP_UTILS_HUFFMAN_H_ -#define WEBP_UTILS_HUFFMAN_H_ - -#include <assert.h> -#include "webp/format_constants.h" -#include "webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define HUFFMAN_TABLE_BITS 8 -#define HUFFMAN_TABLE_MASK ((1 << HUFFMAN_TABLE_BITS) - 1) - -#define LENGTHS_TABLE_BITS 7 -#define LENGTHS_TABLE_MASK ((1 << LENGTHS_TABLE_BITS) - 1) - - -// Huffman lookup table entry -typedef struct { - uint8_t bits; // number of bits used for this symbol - uint16_t value; // symbol value or table offset -} HuffmanCode; - -// long version for holding 32b values -typedef struct { - int bits; // number of bits used for this symbol, - // or an impossible value if not a literal code. - uint32_t value; // 32b packed ARGB value if literal, - // or non-literal symbol otherwise -} HuffmanCode32; - -#define HUFFMAN_PACKED_BITS 6 -#define HUFFMAN_PACKED_TABLE_SIZE (1u << HUFFMAN_PACKED_BITS) - -// Huffman table group. -// Includes special handling for the following cases: -// - is_trivial_literal: one common literal base for RED/BLUE/ALPHA (not GREEN) -// - is_trivial_code: only 1 code (no bit is read from bitstream) -// - use_packed_table: few enough literal symbols, so all the bit codes -// can fit into a small look-up table packed_table[] -// The common literal base, if applicable, is stored in 'literal_arb'. -typedef struct HTreeGroup HTreeGroup; -struct HTreeGroup { - HuffmanCode* htrees[HUFFMAN_CODES_PER_META_CODE]; - int is_trivial_literal; // True, if huffman trees for Red, Blue & Alpha - // Symbols are trivial (have a single code). - uint32_t literal_arb; // If is_trivial_literal is true, this is the - // ARGB value of the pixel, with Green channel - // being set to zero. - int is_trivial_code; // true if is_trivial_literal with only one code - int use_packed_table; // use packed table below for short literal code - // table mapping input bits to a packed values, or escape case to literal code - HuffmanCode32 packed_table[HUFFMAN_PACKED_TABLE_SIZE]; -}; - -// Creates the instance of HTreeGroup with specified number of tree-groups. -HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups); - -// Releases the memory allocated for HTreeGroup. -void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups); - -// Builds Huffman lookup table assuming code lengths are in symbol order. -// The 'code_lengths' is pre-allocated temporary memory buffer used for creating -// the huffman table. -// Returns built table size or 0 in case of error (invalid tree or -// memory error). -int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits, - const int code_lengths[], int code_lengths_size); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // WEBP_UTILS_HUFFMAN_H_ diff --git a/drivers/webp/utils/huffman_encode.c b/drivers/webp/utils/huffman_encode.c deleted file mode 100644 index 0be414a8f8..0000000000 --- a/drivers/webp/utils/huffman_encode.c +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// -// Entropy encoding (Huffman) for webp lossless. - -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include "./huffman_encode.h" -#include "webp/format_constants.h" -#include "./utils.h" - -// ----------------------------------------------------------------------------- -// Util function to optimize the symbol map for RLE coding - -// Heuristics for selecting the stride ranges to collapse. -static int ValuesShouldBeCollapsedToStrideAverage(int a, int b) { - return abs(a - b) < 4; -} - -// Change the population counts in a way that the consequent -// Huffman tree compression, especially its RLE-part, give smaller output. -static void OptimizeHuffmanForRle(int length, uint8_t* const good_for_rle, - uint32_t* const counts) { - // 1) Let's make the Huffman code more compatible with rle encoding. - int i; - for (; length >= 0; --length) { - if (length == 0) { - return; // All zeros. - } - if (counts[length - 1] != 0) { - // Now counts[0..length - 1] does not have trailing zeros. - break; - } - } - // 2) Let's mark all population counts that already can be encoded - // with an rle code. - { - // Let's not spoil any of the existing good rle codes. - // Mark any seq of 0's that is longer as 5 as a good_for_rle. - // Mark any seq of non-0's that is longer as 7 as a good_for_rle. - uint32_t symbol = counts[0]; - int stride = 0; - for (i = 0; i < length + 1; ++i) { - if (i == length || counts[i] != symbol) { - if ((symbol == 0 && stride >= 5) || - (symbol != 0 && stride >= 7)) { - int k; - for (k = 0; k < stride; ++k) { - good_for_rle[i - k - 1] = 1; - } - } - stride = 1; - if (i != length) { - symbol = counts[i]; - } - } else { - ++stride; - } - } - } - // 3) Let's replace those population counts that lead to more rle codes. - { - uint32_t stride = 0; - uint32_t limit = counts[0]; - uint32_t sum = 0; - for (i = 0; i < length + 1; ++i) { - if (i == length || good_for_rle[i] || - (i != 0 && good_for_rle[i - 1]) || - !ValuesShouldBeCollapsedToStrideAverage(counts[i], limit)) { - if (stride >= 4 || (stride >= 3 && sum == 0)) { - uint32_t k; - // The stride must end, collapse what we have, if we have enough (4). - uint32_t count = (sum + stride / 2) / stride; - if (count < 1) { - count = 1; - } - if (sum == 0) { - // Don't make an all zeros stride to be upgraded to ones. - count = 0; - } - for (k = 0; k < stride; ++k) { - // We don't want to change value at counts[i], - // that is already belonging to the next stride. Thus - 1. - counts[i - k - 1] = count; - } - } - stride = 0; - sum = 0; - if (i < length - 3) { - // All interesting strides have a count of at least 4, - // at least when non-zeros. - limit = (counts[i] + counts[i + 1] + - counts[i + 2] + counts[i + 3] + 2) / 4; - } else if (i < length) { - limit = counts[i]; - } else { - limit = 0; - } - } - ++stride; - if (i != length) { - sum += counts[i]; - if (stride >= 4) { - limit = (sum + stride / 2) / stride; - } - } - } - } -} - -// A comparer function for two Huffman trees: sorts first by 'total count' -// (more comes first), and then by 'value' (more comes first). -static int CompareHuffmanTrees(const void* ptr1, const void* ptr2) { - const HuffmanTree* const t1 = (const HuffmanTree*)ptr1; - const HuffmanTree* const t2 = (const HuffmanTree*)ptr2; - if (t1->total_count_ > t2->total_count_) { - return -1; - } else if (t1->total_count_ < t2->total_count_) { - return 1; - } else { - assert(t1->value_ != t2->value_); - return (t1->value_ < t2->value_) ? -1 : 1; - } -} - -static void SetBitDepths(const HuffmanTree* const tree, - const HuffmanTree* const pool, - uint8_t* const bit_depths, int level) { - if (tree->pool_index_left_ >= 0) { - SetBitDepths(&pool[tree->pool_index_left_], pool, bit_depths, level + 1); - SetBitDepths(&pool[tree->pool_index_right_], pool, bit_depths, level + 1); - } else { - bit_depths[tree->value_] = level; - } -} - -// Create an optimal Huffman tree. -// -// (data,length): population counts. -// tree_limit: maximum bit depth (inclusive) of the codes. -// bit_depths[]: how many bits are used for the symbol. -// -// Returns 0 when an error has occurred. -// -// The catch here is that the tree cannot be arbitrarily deep -// -// count_limit is the value that is to be faked as the minimum value -// and this minimum value is raised until the tree matches the -// maximum length requirement. -// -// This algorithm is not of excellent performance for very long data blocks, -// especially when population counts are longer than 2**tree_limit, but -// we are not planning to use this with extremely long blocks. -// -// See http://en.wikipedia.org/wiki/Huffman_coding -static void GenerateOptimalTree(const uint32_t* const histogram, - int histogram_size, - HuffmanTree* tree, int tree_depth_limit, - uint8_t* const bit_depths) { - uint32_t count_min; - HuffmanTree* tree_pool; - int tree_size_orig = 0; - int i; - - for (i = 0; i < histogram_size; ++i) { - if (histogram[i] != 0) { - ++tree_size_orig; - } - } - - if (tree_size_orig == 0) { // pretty optimal already! - return; - } - - tree_pool = tree + tree_size_orig; - - // For block sizes with less than 64k symbols we never need to do a - // second iteration of this loop. - // If we actually start running inside this loop a lot, we would perhaps - // be better off with the Katajainen algorithm. - assert(tree_size_orig <= (1 << (tree_depth_limit - 1))); - for (count_min = 1; ; count_min *= 2) { - int tree_size = tree_size_orig; - // We need to pack the Huffman tree in tree_depth_limit bits. - // So, we try by faking histogram entries to be at least 'count_min'. - int idx = 0; - int j; - for (j = 0; j < histogram_size; ++j) { - if (histogram[j] != 0) { - const uint32_t count = - (histogram[j] < count_min) ? count_min : histogram[j]; - tree[idx].total_count_ = count; - tree[idx].value_ = j; - tree[idx].pool_index_left_ = -1; - tree[idx].pool_index_right_ = -1; - ++idx; - } - } - - // Build the Huffman tree. - qsort(tree, tree_size, sizeof(*tree), CompareHuffmanTrees); - - if (tree_size > 1) { // Normal case. - int tree_pool_size = 0; - while (tree_size > 1) { // Finish when we have only one root. - uint32_t count; - tree_pool[tree_pool_size++] = tree[tree_size - 1]; - tree_pool[tree_pool_size++] = tree[tree_size - 2]; - count = tree_pool[tree_pool_size - 1].total_count_ + - tree_pool[tree_pool_size - 2].total_count_; - tree_size -= 2; - { - // Search for the insertion point. - int k; - for (k = 0; k < tree_size; ++k) { - if (tree[k].total_count_ <= count) { - break; - } - } - memmove(tree + (k + 1), tree + k, (tree_size - k) * sizeof(*tree)); - tree[k].total_count_ = count; - tree[k].value_ = -1; - - tree[k].pool_index_left_ = tree_pool_size - 1; - tree[k].pool_index_right_ = tree_pool_size - 2; - tree_size = tree_size + 1; - } - } - SetBitDepths(&tree[0], tree_pool, bit_depths, 0); - } else if (tree_size == 1) { // Trivial case: only one element. - bit_depths[tree[0].value_] = 1; - } - - { - // Test if this Huffman tree satisfies our 'tree_depth_limit' criteria. - int max_depth = bit_depths[0]; - for (j = 1; j < histogram_size; ++j) { - if (max_depth < bit_depths[j]) { - max_depth = bit_depths[j]; - } - } - if (max_depth <= tree_depth_limit) { - break; - } - } - } -} - -// ----------------------------------------------------------------------------- -// Coding of the Huffman tree values - -static HuffmanTreeToken* CodeRepeatedValues(int repetitions, - HuffmanTreeToken* tokens, - int value, int prev_value) { - assert(value <= MAX_ALLOWED_CODE_LENGTH); - if (value != prev_value) { - tokens->code = value; - tokens->extra_bits = 0; - ++tokens; - --repetitions; - } - while (repetitions >= 1) { - if (repetitions < 3) { - int i; - for (i = 0; i < repetitions; ++i) { - tokens->code = value; - tokens->extra_bits = 0; - ++tokens; - } - break; - } else if (repetitions < 7) { - tokens->code = 16; - tokens->extra_bits = repetitions - 3; - ++tokens; - break; - } else { - tokens->code = 16; - tokens->extra_bits = 3; - ++tokens; - repetitions -= 6; - } - } - return tokens; -} - -static HuffmanTreeToken* CodeRepeatedZeros(int repetitions, - HuffmanTreeToken* tokens) { - while (repetitions >= 1) { - if (repetitions < 3) { - int i; - for (i = 0; i < repetitions; ++i) { - tokens->code = 0; // 0-value - tokens->extra_bits = 0; - ++tokens; - } - break; - } else if (repetitions < 11) { - tokens->code = 17; - tokens->extra_bits = repetitions - 3; - ++tokens; - break; - } else if (repetitions < 139) { - tokens->code = 18; - tokens->extra_bits = repetitions - 11; - ++tokens; - break; - } else { - tokens->code = 18; - tokens->extra_bits = 0x7f; // 138 repeated 0s - ++tokens; - repetitions -= 138; - } - } - return tokens; -} - -int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree, - HuffmanTreeToken* tokens, int max_tokens) { - HuffmanTreeToken* const starting_token = tokens; - HuffmanTreeToken* const ending_token = tokens + max_tokens; - const int depth_size = tree->num_symbols; - int prev_value = 8; // 8 is the initial value for rle. - int i = 0; - assert(tokens != NULL); - while (i < depth_size) { - const int value = tree->code_lengths[i]; - int k = i + 1; - int runs; - while (k < depth_size && tree->code_lengths[k] == value) ++k; - runs = k - i; - if (value == 0) { - tokens = CodeRepeatedZeros(runs, tokens); - } else { - tokens = CodeRepeatedValues(runs, tokens, value, prev_value); - prev_value = value; - } - i += runs; - assert(tokens <= ending_token); - } - (void)ending_token; // suppress 'unused variable' warning - return (int)(tokens - starting_token); -} - -// ----------------------------------------------------------------------------- - -// Pre-reversed 4-bit values. -static const uint8_t kReversedBits[16] = { - 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, - 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf -}; - -static uint32_t ReverseBits(int num_bits, uint32_t bits) { - uint32_t retval = 0; - int i = 0; - while (i < num_bits) { - i += 4; - retval |= kReversedBits[bits & 0xf] << (MAX_ALLOWED_CODE_LENGTH + 1 - i); - bits >>= 4; - } - retval >>= (MAX_ALLOWED_CODE_LENGTH + 1 - num_bits); - return retval; -} - -// Get the actual bit values for a tree of bit depths. -static void ConvertBitDepthsToSymbols(HuffmanTreeCode* const tree) { - // 0 bit-depth means that the symbol does not exist. - int i; - int len; - uint32_t next_code[MAX_ALLOWED_CODE_LENGTH + 1]; - int depth_count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 }; - - assert(tree != NULL); - len = tree->num_symbols; - for (i = 0; i < len; ++i) { - const int code_length = tree->code_lengths[i]; - assert(code_length <= MAX_ALLOWED_CODE_LENGTH); - ++depth_count[code_length]; - } - depth_count[0] = 0; // ignore unused symbol - next_code[0] = 0; - { - uint32_t code = 0; - for (i = 1; i <= MAX_ALLOWED_CODE_LENGTH; ++i) { - code = (code + depth_count[i - 1]) << 1; - next_code[i] = code; - } - } - for (i = 0; i < len; ++i) { - const int code_length = tree->code_lengths[i]; - tree->codes[i] = ReverseBits(code_length, next_code[code_length]++); - } -} - -// ----------------------------------------------------------------------------- -// Main entry point - -void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit, - uint8_t* const buf_rle, - HuffmanTree* const huff_tree, - HuffmanTreeCode* const huff_code) { - const int num_symbols = huff_code->num_symbols; - memset(buf_rle, 0, num_symbols * sizeof(*buf_rle)); - OptimizeHuffmanForRle(num_symbols, buf_rle, histogram); - GenerateOptimalTree(histogram, num_symbols, huff_tree, tree_depth_limit, - huff_code->code_lengths); - // Create the actual bit codes for the bit lengths. - ConvertBitDepthsToSymbols(huff_code); -} diff --git a/drivers/webp/utils/huffman_encode.h b/drivers/webp/utils/huffman_encode.h deleted file mode 100644 index 93610066f3..0000000000 --- a/drivers/webp/utils/huffman_encode.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// -// Entropy encoding (Huffman) for webp lossless - -#ifndef WEBP_UTILS_HUFFMAN_ENCODE_H_ -#define WEBP_UTILS_HUFFMAN_ENCODE_H_ - -#include "webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Struct for holding the tree header in coded form. -typedef struct { - uint8_t code; // value (0..15) or escape code (16,17,18) - uint8_t extra_bits; // extra bits for escape codes -} HuffmanTreeToken; - -// Struct to represent the tree codes (depth and bits array). -typedef struct { - int num_symbols; // Number of symbols. - uint8_t* code_lengths; // Code lengths of the symbols. - uint16_t* codes; // Symbol Codes. -} HuffmanTreeCode; - -// Struct to represent the Huffman tree. -typedef struct { - uint32_t total_count_; // Symbol frequency. - int value_; // Symbol value. - int pool_index_left_; // Index for the left sub-tree. - int pool_index_right_; // Index for the right sub-tree. -} HuffmanTree; - -// Turn the Huffman tree into a token sequence. -// Returns the number of tokens used. -int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree, - HuffmanTreeToken* tokens, int max_tokens); - -// Create an optimized tree, and tokenize it. -// 'buf_rle' and 'huff_tree' are pre-allocated and the 'tree' is the constructed -// huffman code tree. -void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit, - uint8_t* const buf_rle, HuffmanTree* const huff_tree, - HuffmanTreeCode* const tree); - -#ifdef __cplusplus -} -#endif - -#endif // WEBP_UTILS_HUFFMAN_ENCODE_H_ diff --git a/drivers/webp/utils/quant_levels.h b/drivers/webp/utils/quant_levels.h deleted file mode 100644 index 3916b977ab..0000000000 --- a/drivers/webp/utils/quant_levels.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Alpha plane quantization utility -// -// Author: Vikas Arora (vikasa@google.com) - -#ifndef WEBP_UTILS_QUANT_LEVELS_H_ -#define WEBP_UTILS_QUANT_LEVELS_H_ - -#include <stdlib.h> - -#include "webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Replace the input 'data' of size 'width'x'height' with 'num-levels' -// quantized values. If not NULL, 'sse' will contain the sum of squared error. -// Valid range for 'num_levels' is [2, 256]. -// Returns false in case of error (data is NULL, or parameters are invalid). -int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels, - uint64_t* const sse); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_QUANT_LEVELS_H_ */ diff --git a/drivers/webp/utils/quant_levels_dec.h b/drivers/webp/utils/quant_levels_dec.h deleted file mode 100644 index c99a475386..0000000000 --- a/drivers/webp/utils/quant_levels_dec.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Alpha plane de-quantization utility -// -// Author: Vikas Arora (vikasa@google.com) - -#ifndef WEBP_UTILS_QUANT_LEVELS_DEC_H_ -#define WEBP_UTILS_QUANT_LEVELS_DEC_H_ - -#include "webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Apply post-processing to input 'data' of size 'width'x'height' assuming that -// the source was quantized to a reduced number of levels. 'stride' is in bytes. -// Strength is in [0..100] and controls the amount of dithering applied. -// Returns false in case of error (data is NULL, invalid parameters, -// malloc failure, ...). -int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride, - int strength); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_H_ */ diff --git a/drivers/webp/utils/random.h b/drivers/webp/utils/random.h deleted file mode 100644 index 745f3e2e87..0000000000 --- a/drivers/webp/utils/random.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Pseudo-random utilities -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_RANDOM_H_ -#define WEBP_UTILS_RANDOM_H_ - -#include <assert.h> -#include "webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define VP8_RANDOM_DITHER_FIX 8 // fixed-point precision for dithering -#define VP8_RANDOM_TABLE_SIZE 55 - -typedef struct { - int index1_, index2_; - uint32_t tab_[VP8_RANDOM_TABLE_SIZE]; - int amp_; -} VP8Random; - -// Initializes random generator with an amplitude 'dithering' in range [0..1]. -void VP8InitRandom(VP8Random* const rg, float dithering); - -// Returns a centered pseudo-random number with 'num_bits' amplitude. -// (uses D.Knuth's Difference-based random generator). -// 'amp' is in VP8_RANDOM_DITHER_FIX fixed-point precision. -static WEBP_INLINE int VP8RandomBits2(VP8Random* const rg, int num_bits, - int amp) { - int diff; - assert(num_bits + VP8_RANDOM_DITHER_FIX <= 31); - diff = rg->tab_[rg->index1_] - rg->tab_[rg->index2_]; - if (diff < 0) diff += (1u << 31); - rg->tab_[rg->index1_] = diff; - if (++rg->index1_ == VP8_RANDOM_TABLE_SIZE) rg->index1_ = 0; - if (++rg->index2_ == VP8_RANDOM_TABLE_SIZE) rg->index2_ = 0; - // sign-extend, 0-center - diff = (int)((uint32_t)diff << 1) >> (32 - num_bits); - diff = (diff * amp) >> VP8_RANDOM_DITHER_FIX; // restrict range - diff += 1 << (num_bits - 1); // shift back to 0.5-center - return diff; -} - -static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) { - return VP8RandomBits2(rg, num_bits, rg->amp_); -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_RANDOM_H_ */ diff --git a/drivers/webp/utils/rescaler.h b/drivers/webp/utils/rescaler.h deleted file mode 100644 index 868467b4d7..0000000000 --- a/drivers/webp/utils/rescaler.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Rescaling functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_RESCALER_H_ -#define WEBP_UTILS_RESCALER_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "webp/types.h" - -#define WEBP_RESCALER_RFIX 32 // fixed-point precision for multiplies -#define WEBP_RESCALER_ONE (1ull << WEBP_RESCALER_RFIX) -#define WEBP_RESCALER_FRAC(x, y) \ - ((uint32_t)(((uint64_t)(x) << WEBP_RESCALER_RFIX) / (y))) - -// Structure used for on-the-fly rescaling -typedef uint32_t rescaler_t; // type for side-buffer -typedef struct WebPRescaler WebPRescaler; -struct WebPRescaler { - int x_expand; // true if we're expanding in the x direction - int y_expand; // true if we're expanding in the y direction - int num_channels; // bytes to jump between pixels - uint32_t fx_scale; // fixed-point scaling factors - uint32_t fy_scale; // '' - uint32_t fxy_scale; // '' - int y_accum; // vertical accumulator - int y_add, y_sub; // vertical increments - int x_add, x_sub; // horizontal increments - int src_width, src_height; // source dimensions - int dst_width, dst_height; // destination dimensions - int src_y, dst_y; // row counters for input and output - uint8_t* dst; - int dst_stride; - rescaler_t* irow, *frow; // work buffer -}; - -// Initialize a rescaler given scratch area 'work' and dimensions of src & dst. -void WebPRescalerInit(WebPRescaler* const rescaler, - int src_width, int src_height, - uint8_t* const dst, - int dst_width, int dst_height, int dst_stride, - int num_channels, - rescaler_t* const work); - -// If either 'scaled_width' or 'scaled_height' (but not both) is 0 the value -// will be calculated preserving the aspect ratio, otherwise the values are -// left unmodified. Returns true on success, false if either value is 0 after -// performing the scaling calculation. -int WebPRescalerGetScaledDimensions(int src_width, int src_height, - int* const scaled_width, - int* const scaled_height); - -// Returns the number of input lines needed next to produce one output line, -// considering that the maximum available input lines are 'max_num_lines'. -int WebPRescaleNeededLines(const WebPRescaler* const rescaler, - int max_num_lines); - -// Import multiple rows over all channels, until at least one row is ready to -// be exported. Returns the actual number of lines that were imported. -int WebPRescalerImport(WebPRescaler* const rescaler, int num_rows, - const uint8_t* src, int src_stride); - -// Export as many rows as possible. Return the numbers of rows written. -int WebPRescalerExport(WebPRescaler* const rescaler); - -// Return true if input is finished -static WEBP_INLINE -int WebPRescalerInputDone(const WebPRescaler* const rescaler) { - return (rescaler->src_y >= rescaler->src_height); -} -// Return true if output is finished -static WEBP_INLINE -int WebPRescalerOutputDone(const WebPRescaler* const rescaler) { - return (rescaler->dst_y >= rescaler->dst_height); -} - -// Return true if there are pending output rows ready. -static WEBP_INLINE -int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) { - return !WebPRescalerOutputDone(rescaler) && (rescaler->y_accum <= 0); -} - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_RESCALER_H_ */ diff --git a/drivers/webp/utils/thread.h b/drivers/webp/utils/thread.h deleted file mode 100644 index 6008bb7c01..0000000000 --- a/drivers/webp/utils/thread.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Multi-threaded worker -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_THREAD_H_ -#define WEBP_UTILS_THREAD_H_ - -#ifdef HAVE_CONFIG_H -#include "webp/config.h" -#endif - -#include "webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// State of the worker thread object -typedef enum { - NOT_OK = 0, // object is unusable - OK, // ready to work - WORK // busy finishing the current task -} WebPWorkerStatus; - -// Function to be called by the worker thread. Takes two opaque pointers as -// arguments (data1 and data2), and should return false in case of error. -typedef int (*WebPWorkerHook)(void*, void*); - -// Platform-dependent implementation details for the worker. -typedef struct WebPWorkerImpl WebPWorkerImpl; - -// Synchronization object used to launch job in the worker thread -typedef struct { - WebPWorkerImpl* impl_; - WebPWorkerStatus status_; - WebPWorkerHook hook; // hook to call - void* data1; // first argument passed to 'hook' - void* data2; // second argument passed to 'hook' - int had_error; // return value of the last call to 'hook' -} WebPWorker; - -// The interface for all thread-worker related functions. All these functions -// must be implemented. -typedef struct { - // Must be called first, before any other method. - void (*Init)(WebPWorker* const worker); - // Must be called to initialize the object and spawn the thread. Re-entrant. - // Will potentially launch the thread. Returns false in case of error. - int (*Reset)(WebPWorker* const worker); - // Makes sure the previous work is finished. Returns true if worker->had_error - // was not set and no error condition was triggered by the working thread. - int (*Sync)(WebPWorker* const worker); - // Triggers the thread to call hook() with data1 and data2 arguments. These - // hook/data1/data2 values can be changed at any time before calling this - // function, but not be changed afterward until the next call to Sync(). - void (*Launch)(WebPWorker* const worker); - // This function is similar to Launch() except that it calls the - // hook directly instead of using a thread. Convenient to bypass the thread - // mechanism while still using the WebPWorker structs. Sync() must - // still be called afterward (for error reporting). - void (*Execute)(WebPWorker* const worker); - // Kill the thread and terminate the object. To use the object again, one - // must call Reset() again. - void (*End)(WebPWorker* const worker); -} WebPWorkerInterface; - -// Install a new set of threading functions, overriding the defaults. This -// should be done before any workers are started, i.e., before any encoding or -// decoding takes place. The contents of the interface struct are copied, it -// is safe to free the corresponding memory after this call. This function is -// not thread-safe. Return false in case of invalid pointer or methods. -WEBP_EXTERN(int) WebPSetWorkerInterface( - const WebPWorkerInterface* const winterface); - -// Retrieve the currently set thread worker interface. -WEBP_EXTERN(const WebPWorkerInterface*) WebPGetWorkerInterface(void); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_THREAD_H_ */ diff --git a/drivers/webp/utils/utils.c b/drivers/webp/utils/utils.c deleted file mode 100644 index b2193c4b47..0000000000 --- a/drivers/webp/utils/utils.c +++ /dev/null @@ -1,305 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Misc. common utility functions -// -// Author: Skal (pascal.massimino@gmail.com) - -#include <stdlib.h> -#include <string.h> // for memcpy() -#include "webp/decode.h" -#include "webp/encode.h" -#include "webp/format_constants.h" // for MAX_PALETTE_SIZE -#include "./utils.h" - -// If PRINT_MEM_INFO is defined, extra info (like total memory used, number of -// alloc/free etc) is printed. For debugging/tuning purpose only (it's slow, -// and not multi-thread safe!). -// An interesting alternative is valgrind's 'massif' tool: -// http://valgrind.org/docs/manual/ms-manual.html -// Here is an example command line: -/* valgrind --tool=massif --massif-out-file=massif.out \ - --stacks=yes --alloc-fn=WebPSafeAlloc --alloc-fn=WebPSafeCalloc - ms_print massif.out -*/ -// In addition: -// * if PRINT_MEM_TRAFFIC is defined, all the details of the malloc/free cycles -// are printed. -// * if MALLOC_FAIL_AT is defined, the global environment variable -// $MALLOC_FAIL_AT is used to simulate a memory error when calloc or malloc -// is called for the nth time. Example usage: -// export MALLOC_FAIL_AT=50 && ./examples/cwebp input.png -// * if MALLOC_LIMIT is defined, the global environment variable $MALLOC_LIMIT -// sets the maximum amount of memory (in bytes) made available to libwebp. -// This can be used to emulate environment with very limited memory. -// Example: export MALLOC_LIMIT=64000000 && ./examples/dwebp picture.webp - -// #define PRINT_MEM_INFO -// #define PRINT_MEM_TRAFFIC -// #define MALLOC_FAIL_AT -// #define MALLOC_LIMIT - -//------------------------------------------------------------------------------ -// Checked memory allocation - -#if defined(PRINT_MEM_INFO) - -#include <stdio.h> - -static int num_malloc_calls = 0; -static int num_calloc_calls = 0; -static int num_free_calls = 0; -static int countdown_to_fail = 0; // 0 = off - -typedef struct MemBlock MemBlock; -struct MemBlock { - void* ptr_; - size_t size_; - MemBlock* next_; -}; - -static MemBlock* all_blocks = NULL; -static size_t total_mem = 0; -static size_t total_mem_allocated = 0; -static size_t high_water_mark = 0; -static size_t mem_limit = 0; - -static int exit_registered = 0; - -static void PrintMemInfo(void) { - fprintf(stderr, "\nMEMORY INFO:\n"); - fprintf(stderr, "num calls to: malloc = %4d\n", num_malloc_calls); - fprintf(stderr, " calloc = %4d\n", num_calloc_calls); - fprintf(stderr, " free = %4d\n", num_free_calls); - fprintf(stderr, "total_mem: %u\n", (uint32_t)total_mem); - fprintf(stderr, "total_mem allocated: %u\n", (uint32_t)total_mem_allocated); - fprintf(stderr, "high-water mark: %u\n", (uint32_t)high_water_mark); - while (all_blocks != NULL) { - MemBlock* b = all_blocks; - all_blocks = b->next_; - free(b); - } -} - -static void Increment(int* const v) { - if (!exit_registered) { -#if defined(MALLOC_FAIL_AT) - { - const char* const malloc_fail_at_str = getenv("MALLOC_FAIL_AT"); - if (malloc_fail_at_str != NULL) { - countdown_to_fail = atoi(malloc_fail_at_str); - } - } -#endif -#if defined(MALLOC_LIMIT) - { - const char* const malloc_limit_str = getenv("MALLOC_LIMIT"); - if (malloc_limit_str != NULL) { - mem_limit = atoi(malloc_limit_str); - } - } -#endif - (void)countdown_to_fail; - (void)mem_limit; - atexit(PrintMemInfo); - exit_registered = 1; - } - ++*v; -} - -static void AddMem(void* ptr, size_t size) { - if (ptr != NULL) { - MemBlock* const b = (MemBlock*)malloc(sizeof(*b)); - if (b == NULL) abort(); - b->next_ = all_blocks; - all_blocks = b; - b->ptr_ = ptr; - b->size_ = size; - total_mem += size; - total_mem_allocated += size; -#if defined(PRINT_MEM_TRAFFIC) -#if defined(MALLOC_FAIL_AT) - fprintf(stderr, "fail-count: %5d [mem=%u]\n", - num_malloc_calls + num_calloc_calls, (uint32_t)total_mem); -#else - fprintf(stderr, "Mem: %u (+%u)\n", (uint32_t)total_mem, (uint32_t)size); -#endif -#endif - if (total_mem > high_water_mark) high_water_mark = total_mem; - } -} - -static void SubMem(void* ptr) { - if (ptr != NULL) { - MemBlock** b = &all_blocks; - // Inefficient search, but that's just for debugging. - while (*b != NULL && (*b)->ptr_ != ptr) b = &(*b)->next_; - if (*b == NULL) { - fprintf(stderr, "Invalid pointer free! (%p)\n", ptr); - abort(); - } - { - MemBlock* const block = *b; - *b = block->next_; - total_mem -= block->size_; -#if defined(PRINT_MEM_TRAFFIC) - fprintf(stderr, "Mem: %u (-%u)\n", - (uint32_t)total_mem, (uint32_t)block->size_); -#endif - free(block); - } - } -} - -#else -#define Increment(v) do {} while (0) -#define AddMem(p, s) do {} while (0) -#define SubMem(p) do {} while (0) -#endif - -// Returns 0 in case of overflow of nmemb * size. -static int CheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) { - const uint64_t total_size = nmemb * size; - if (nmemb == 0) return 1; - if ((uint64_t)size > WEBP_MAX_ALLOCABLE_MEMORY / nmemb) return 0; - if (total_size != (size_t)total_size) return 0; -#if defined(PRINT_MEM_INFO) && defined(MALLOC_FAIL_AT) - if (countdown_to_fail > 0 && --countdown_to_fail == 0) { - return 0; // fake fail! - } -#endif -#if defined(MALLOC_LIMIT) - if (mem_limit > 0 && total_mem + total_size >= mem_limit) { - return 0; // fake fail! - } -#endif - - return 1; -} - -void* WebPSafeMalloc(uint64_t nmemb, size_t size) { - void* ptr; - Increment(&num_malloc_calls); - if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; - assert(nmemb * size > 0); - ptr = malloc((size_t)(nmemb * size)); - AddMem(ptr, (size_t)(nmemb * size)); - return ptr; -} - -void* WebPSafeCalloc(uint64_t nmemb, size_t size) { - void* ptr; - Increment(&num_calloc_calls); - if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; - assert(nmemb * size > 0); - ptr = calloc((size_t)nmemb, size); - AddMem(ptr, (size_t)(nmemb * size)); - return ptr; -} - -void WebPSafeFree(void* const ptr) { - if (ptr != NULL) { - Increment(&num_free_calls); - SubMem(ptr); - } - free(ptr); -} - -// Public API function. -void WebPFree(void* ptr) { - free(ptr); -} - -//------------------------------------------------------------------------------ - -void WebPCopyPlane(const uint8_t* src, int src_stride, - uint8_t* dst, int dst_stride, int width, int height) { - assert(src != NULL && dst != NULL); - assert(src_stride >= width && dst_stride >= width); - while (height-- > 0) { - memcpy(dst, src, width); - src += src_stride; - dst += dst_stride; - } -} - -void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) { - assert(src != NULL && dst != NULL); - assert(src->width == dst->width && src->height == dst->height); - assert(src->use_argb && dst->use_argb); - WebPCopyPlane((uint8_t*)src->argb, 4 * src->argb_stride, (uint8_t*)dst->argb, - 4 * dst->argb_stride, 4 * src->width, src->height); -} - -//------------------------------------------------------------------------------ - -#define MAX_COLOR_COUNT MAX_PALETTE_SIZE -#define COLOR_HASH_SIZE (MAX_COLOR_COUNT * 4) -#define COLOR_HASH_RIGHT_SHIFT 22 // 32 - log2(COLOR_HASH_SIZE). - -int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) { - int i; - int x, y; - int num_colors = 0; - uint8_t in_use[COLOR_HASH_SIZE] = { 0 }; - uint32_t colors[COLOR_HASH_SIZE]; - static const uint32_t kHashMul = 0x1e35a7bdU; - const uint32_t* argb = pic->argb; - const int width = pic->width; - const int height = pic->height; - uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0] - assert(pic != NULL); - assert(pic->use_argb); - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - int key; - if (argb[x] == last_pix) { - continue; - } - last_pix = argb[x]; - key = (kHashMul * last_pix) >> COLOR_HASH_RIGHT_SHIFT; - while (1) { - if (!in_use[key]) { - colors[key] = last_pix; - in_use[key] = 1; - ++num_colors; - if (num_colors > MAX_COLOR_COUNT) { - return MAX_COLOR_COUNT + 1; // Exact count not needed. - } - break; - } else if (colors[key] == last_pix) { - break; // The color is already there. - } else { - // Some other color sits here, so do linear conflict resolution. - ++key; - key &= (COLOR_HASH_SIZE - 1); // Key mask. - } - } - } - argb += pic->argb_stride; - } - - if (palette != NULL) { // Fill the colors into palette. - num_colors = 0; - for (i = 0; i < COLOR_HASH_SIZE; ++i) { - if (in_use[i]) { - palette[num_colors] = colors[i]; - ++num_colors; - } - } - } - return num_colors; -} - -#undef MAX_COLOR_COUNT -#undef COLOR_HASH_SIZE -#undef COLOR_HASH_RIGHT_SHIFT - -//------------------------------------------------------------------------------ diff --git a/drivers/webp/utils/utils.h b/drivers/webp/utils/utils.h deleted file mode 100644 index cef496af78..0000000000 --- a/drivers/webp/utils/utils.h +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Misc. common utility functions -// -// Authors: Skal (pascal.massimino@gmail.com) -// Urvang (urvang@google.com) - -#ifndef WEBP_UTILS_UTILS_H_ -#define WEBP_UTILS_UTILS_H_ - -#ifdef HAVE_CONFIG_H -#include "webp/config.h" -#endif - -#include <assert.h> - -#include "../dsp/dsp.h" -#include "webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//------------------------------------------------------------------------------ -// Memory allocation - -// This is the maximum memory amount that libwebp will ever try to allocate. -#define WEBP_MAX_ALLOCABLE_MEMORY (1ULL << 40) - -// size-checking safe malloc/calloc: verify that the requested size is not too -// large, or return NULL. You don't need to call these for constructs like -// malloc(sizeof(foo)), but only if there's picture-dependent size involved -// somewhere (like: malloc(num_pixels * sizeof(*something))). That's why this -// safe malloc() borrows the signature from calloc(), pointing at the dangerous -// underlying multiply involved. -WEBP_EXTERN(void*) WebPSafeMalloc(uint64_t nmemb, size_t size); -// Note that WebPSafeCalloc() expects the second argument type to be 'size_t' -// in order to favor the "calloc(num_foo, sizeof(foo))" pattern. -WEBP_EXTERN(void*) WebPSafeCalloc(uint64_t nmemb, size_t size); - -// Companion deallocation function to the above allocations. -WEBP_EXTERN(void) WebPSafeFree(void* const ptr); - -//------------------------------------------------------------------------------ -// Alignment - -#define WEBP_ALIGN_CST 31 -#define WEBP_ALIGN(PTR) (((uintptr_t)(PTR) + WEBP_ALIGN_CST) & ~WEBP_ALIGN_CST) - -#if defined(WEBP_FORCE_ALIGNED) -#include <string.h> -// memcpy() is the safe way of moving potentially unaligned 32b memory. -static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) { - uint32_t A; - memcpy(&A, (const int*)ptr, sizeof(A)); - return A; -} -static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { - memcpy(ptr, &val, sizeof(val)); -} -#else -static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE -uint32_t WebPMemToUint32(const uint8_t* const ptr) { - return *(const uint32_t*)ptr; -} -static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE -void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { - *(uint32_t*)ptr = val; -} -#endif - -//------------------------------------------------------------------------------ -// Reading/writing data. - -// Read 16, 24 or 32 bits stored in little-endian order. -static WEBP_INLINE int GetLE16(const uint8_t* const data) { - return (int)(data[0] << 0) | (data[1] << 8); -} - -static WEBP_INLINE int GetLE24(const uint8_t* const data) { - return GetLE16(data) | (data[2] << 16); -} - -static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) { - return GetLE16(data) | ((uint32_t)GetLE16(data + 2) << 16); -} - -// Store 16, 24 or 32 bits in little-endian order. -static WEBP_INLINE void PutLE16(uint8_t* const data, int val) { - assert(val < (1 << 16)); - data[0] = (val >> 0); - data[1] = (val >> 8); -} - -static WEBP_INLINE void PutLE24(uint8_t* const data, int val) { - assert(val < (1 << 24)); - PutLE16(data, val & 0xffff); - data[2] = (val >> 16); -} - -static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) { - PutLE16(data, (int)(val & 0xffff)); - PutLE16(data + 2, (int)(val >> 16)); -} - -// Returns (int)floor(log2(n)). n must be > 0. -// use GNU builtins where available. -#if defined(__GNUC__) && \ - ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) -static WEBP_INLINE int BitsLog2Floor(uint32_t n) { - return 31 ^ __builtin_clz(n); -} -#elif defined(_MSC_VER) && _MSC_VER > 1310 && \ - (defined(_M_X64) || defined(_M_IX86)) -#include <intrin.h> -#pragma intrinsic(_BitScanReverse) - -static WEBP_INLINE int BitsLog2Floor(uint32_t n) { - unsigned long first_set_bit; - _BitScanReverse(&first_set_bit, n); - return first_set_bit; -} -#else -static WEBP_INLINE int BitsLog2Floor(uint32_t n) { - int log = 0; - uint32_t value = n; - int i; - - for (i = 4; i >= 0; --i) { - const int shift = (1 << i); - const uint32_t x = value >> shift; - if (x != 0) { - value = x; - log += shift; - } - } - return log; -} -#endif - -//------------------------------------------------------------------------------ -// Pixel copying. - -struct WebPPicture; - -// Copy width x height pixels from 'src' to 'dst' honoring the strides. -WEBP_EXTERN(void) WebPCopyPlane(const uint8_t* src, int src_stride, - uint8_t* dst, int dst_stride, - int width, int height); - -// Copy ARGB pixels from 'src' to 'dst' honoring strides. 'src' and 'dst' are -// assumed to be already allocated and using ARGB data. -WEBP_EXTERN(void) WebPCopyPixels(const struct WebPPicture* const src, - struct WebPPicture* const dst); - -//------------------------------------------------------------------------------ -// Unique colors. - -// Returns count of unique colors in 'pic', assuming pic->use_argb is true. -// If the unique color count is more than MAX_COLOR_COUNT, returns -// MAX_COLOR_COUNT+1. -// If 'palette' is not NULL and number of unique colors is less than or equal to -// MAX_COLOR_COUNT, also outputs the actual unique colors into 'palette'. -// Note: 'palette' is assumed to be an array already allocated with at least -// MAX_COLOR_COUNT elements. -WEBP_EXTERN(int) WebPGetColorPalette(const struct WebPPicture* const pic, - uint32_t* const palette); - -//------------------------------------------------------------------------------ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* WEBP_UTILS_UTILS_H_ */ diff --git a/drivers/windows/SCsub b/drivers/windows/SCsub index 9fbb467baa..ee39fd2631 100644 --- a/drivers/windows/SCsub +++ b/drivers/windows/SCsub @@ -1,5 +1,7 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.drivers_sources,"*.cpp") +env.add_source_files(env.drivers_sources, "*.cpp") Export('env') diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index 90e43d2518..ad4e8f301c 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -37,12 +37,6 @@ #include <stdio.h> #include "print_string.h" -#ifdef WINRT_ENABLED -#include <Synchapi.h> -#include <collection.h> -#include <ppltasks.h> -#endif - /* [03:57] <reduz> yessopie, so i dont havemak to rely on unicows @@ -135,14 +129,6 @@ Error DirAccessWindows::change_dir(String p_dir) { GLOBAL_LOCK_FUNCTION -#ifdef WINRT_ENABLED - - p_dir = fix_path(p_dir); - current_dir = normalize_path(p_dir); - - return OK; -#else - p_dir=fix_path(p_dir); @@ -178,19 +164,12 @@ Error DirAccessWindows::change_dir(String p_dir) { //} return worked?OK:ERR_INVALID_PARAMETER; -#endif } Error DirAccessWindows::make_dir(String p_dir) { GLOBAL_LOCK_FUNCTION -#ifdef WINRT_ENABLED - - return ERR_CANT_CREATE; - -#else - if (p_dir.is_rel_path()) p_dir=get_current_dir().plus_file(p_dir); @@ -215,8 +194,6 @@ Error DirAccessWindows::make_dir(String p_dir) { }; return ERR_CANT_CREATE; - -#endif } @@ -259,7 +236,6 @@ bool DirAccessWindows::file_exists(String p_file) { return false; return !(fileAttr&FILE_ATTRIBUTE_DIRECTORY); - } bool DirAccessWindows::dir_exists(String p_dir) { @@ -282,7 +258,6 @@ bool DirAccessWindows::dir_exists(String p_dir) { if (INVALID_FILE_ATTRIBUTES == fileAttr) return false; return (fileAttr&FILE_ATTRIBUTE_DIRECTORY); - } Error DirAccessWindows::rename(String p_path,String p_new_path) { diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 3f27068fb2..36dcab1d67 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -124,7 +124,16 @@ void FileAccessWindows::close() { bool rename_error; + +#ifdef WINRT_ENABLED + // WinRT has no PathFileExists, so we check attributes instead + DWORD fileAttr; + + fileAttr = GetFileAttributesW(save_path.c_str()); + if (INVALID_FILE_ATTRIBUTES == fileAttr) { +#else if (!PathFileExistsW(save_path.c_str())) { +#endif //creating new file rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str())!=0; } else { @@ -139,7 +148,6 @@ void FileAccessWindows::close() { ERR_FAIL_COND( rename_error ); } - } bool FileAccessWindows::is_open() const { diff --git a/drivers/windows/semaphore_windows.cpp b/drivers/windows/semaphore_windows.cpp index 74094f482a..8d11d1b1c1 100644 --- a/drivers/windows/semaphore_windows.cpp +++ b/drivers/windows/semaphore_windows.cpp @@ -28,7 +28,7 @@ /*************************************************************************/ #include "semaphore_windows.h" -#if defined(WINDOWS_ENABLED) && !defined(WINRT_ENABLED) +#if defined(WINDOWS_ENABLED) #include "os/memory.h" diff --git a/drivers/xaudio2/SCsub b/drivers/xaudio2/SCsub new file mode 100644 index 0000000000..cb780a893b --- /dev/null +++ b/drivers/xaudio2/SCsub @@ -0,0 +1,9 @@ +#!/usr/bin/env python + +Import('env') + +env.add_source_files(env.drivers_sources, "*.cpp") +env.Append(CXXFLAGS=['-DXAUDIO2_ENABLED']) +env.Append(LINKFLAGS=['xaudio2_8.lib']) + +Export('env') diff --git a/drivers/xaudio2/audio_driver_xaudio2.cpp b/drivers/xaudio2/audio_driver_xaudio2.cpp new file mode 100644 index 0000000000..c7a8962102 --- /dev/null +++ b/drivers/xaudio2/audio_driver_xaudio2.cpp @@ -0,0 +1,235 @@ +/*************************************************************************/ +/* audio_driver_xaudio2.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "audio_driver_xaudio2.h" + +#include "globals.h" +#include "os/os.h" + +const char * AudioDriverXAudio2::get_name() const +{ + return "XAudio2"; +} + +Error AudioDriverXAudio2::init() { + + active = false; + thread_exited = false; + exit_thread = false; + pcm_open = false; + samples_in = NULL; + + + mix_rate = 48000; + output_format = OUTPUT_STEREO; + channels = 2; + + int latency = GLOBAL_DEF("audio/output_latency", 25); + buffer_size = nearest_power_of_2(latency * mix_rate / 1000); + + samples_in = memnew_arr(int32_t, buffer_size*channels); + for (int i = 0; i < AUDIO_BUFFERS; i++) { + samples_out[i] = memnew_arr(int16_t, buffer_size*channels); + xaudio_buffer[i].AudioBytes = buffer_size * channels * sizeof(int16_t); + xaudio_buffer[i].pAudioData = (const BYTE*)(samples_out[i]); + xaudio_buffer[i].Flags = 0; + } + + HRESULT hr; + hr = XAudio2Create(&xaudio, 0, XAUDIO2_DEFAULT_PROCESSOR); + if (hr != S_OK) { + ERR_EXPLAIN("Error creating XAudio2 engine."); + ERR_FAIL_V(ERR_UNAVAILABLE); + } + hr = xaudio->CreateMasteringVoice(&mastering_voice); + if (hr != S_OK) { + ERR_EXPLAIN("Error creating XAudio2 mastering voice."); + ERR_FAIL_V(ERR_UNAVAILABLE); + } + + wave_format.nChannels = channels; + wave_format.cbSize = 0; + wave_format.nSamplesPerSec = mix_rate; + wave_format.wFormatTag = WAVE_FORMAT_PCM; + wave_format.wBitsPerSample = 16; + wave_format.nBlockAlign = channels * wave_format.wBitsPerSample >> 3; + wave_format.nAvgBytesPerSec = mix_rate * wave_format.nBlockAlign; + + hr = xaudio->CreateSourceVoice(&source_voice, &wave_format, 0, XAUDIO2_MAX_FREQ_RATIO, &voice_callback); + if (hr != S_OK) { + ERR_EXPLAIN("Error creating XAudio2 source voice. " + itos(hr)); + ERR_FAIL_V(ERR_UNAVAILABLE); + } + + mutex = Mutex::create(); + thread = Thread::create(AudioDriverXAudio2::thread_func, this); + + return OK; +}; + +void AudioDriverXAudio2::thread_func(void* p_udata) { + + AudioDriverXAudio2* ad = (AudioDriverXAudio2*)p_udata; + + uint64_t usdelay = (ad->buffer_size / float(ad->mix_rate)) * 1000000; + + while (!ad->exit_thread) { + + + if (!ad->active) { + + for (int i = 0; i < AUDIO_BUFFERS; i++) { + ad->xaudio_buffer[i].Flags = XAUDIO2_END_OF_STREAM; + } + + } else { + + ad->lock(); + + ad->audio_server_process(ad->buffer_size, ad->samples_in); + + ad->unlock(); + + for (unsigned int i = 0;i < ad->buffer_size*ad->channels;i++) { + + ad->samples_out[ad->current_buffer][i] = ad->samples_in[i] >> 16; + } + + ad->xaudio_buffer[ad->current_buffer].Flags = 0; + ad->xaudio_buffer[ad->current_buffer].AudioBytes = ad->buffer_size * ad->channels * sizeof(int16_t); + ad->xaudio_buffer[ad->current_buffer].pAudioData = (const BYTE*)(ad->samples_out[ad->current_buffer]); + ad->xaudio_buffer[ad->current_buffer].PlayBegin = 0; + ad->source_voice->SubmitSourceBuffer(&(ad->xaudio_buffer[ad->current_buffer])); + + ad->current_buffer = (ad->current_buffer + 1) % AUDIO_BUFFERS; + + XAUDIO2_VOICE_STATE state; + while (ad->source_voice->GetState(&state), state.BuffersQueued > AUDIO_BUFFERS - 1) + { + WaitForSingleObject(ad->voice_callback.buffer_end_event, INFINITE); + } + } + + }; + + ad->thread_exited = true; + +}; + +void AudioDriverXAudio2::start() { + + active = true; + HRESULT hr = source_voice->Start(0); + if (hr != S_OK) { + ERR_EXPLAIN("XAudio2 start error " + itos(hr)); + ERR_FAIL(); + } +}; + +int AudioDriverXAudio2::get_mix_rate() const { + + return mix_rate; +}; + +AudioDriverSW::OutputFormat AudioDriverXAudio2::get_output_format() const { + + return output_format; +}; + +float AudioDriverXAudio2::get_latency() { + + XAUDIO2_PERFORMANCE_DATA perf_data; + xaudio->GetPerformanceData(&perf_data); + if (perf_data.CurrentLatencyInSamples) { + return (float)(perf_data.CurrentLatencyInSamples / ((float)mix_rate)); + } else { + return 0; + } +} + +void AudioDriverXAudio2::lock() { + + if (!thread || !mutex) + return; + mutex->lock(); +}; +void AudioDriverXAudio2::unlock() { + + if (!thread || !mutex) + return; + mutex->unlock(); +}; + +void AudioDriverXAudio2::finish() { + + if (!thread) + return; + + exit_thread = true; + Thread::wait_to_finish(thread); + + if (source_voice) { + source_voice->Stop(0); + source_voice->DestroyVoice(); + } + + if (samples_in) { + memdelete_arr(samples_in); + }; + if (samples_out[0]) { + for (int i = 0; i < AUDIO_BUFFERS; i++) { + memdelete_arr(samples_out[i]); + } + }; + + mastering_voice->DestroyVoice(); + + memdelete(thread); + if (mutex) + memdelete(mutex); + thread = NULL; +}; + +AudioDriverXAudio2::AudioDriverXAudio2() { + + mutex = NULL; + thread = NULL; + wave_format = { 0 }; + for (int i = 0; i < AUDIO_BUFFERS; i++) { + xaudio_buffer[i] = { 0 }; + samples_out[i] = 0; + } + current_buffer = 0; +}; + +AudioDriverXAudio2::~AudioDriverXAudio2() { + + +}; + + diff --git a/drivers/xaudio2/audio_driver_xaudio2.h b/drivers/xaudio2/audio_driver_xaudio2.h new file mode 100644 index 0000000000..1c6a90500d --- /dev/null +++ b/drivers/xaudio2/audio_driver_xaudio2.h @@ -0,0 +1,109 @@ +/*************************************************************************/ +/* audio_driver_xaudio2.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef AUDIO_DRIVER_XAUDIO2_H +#define AUDIO_DRIVER_XAUDIO2_H + +#include "servers/audio/audio_server_sw.h" + +#include "core/os/thread.h" +#include "core/os/mutex.h" + +#include <windows.h> +#include <mmsystem.h> +#include <mmreg.h> +#include <xaudio2.h> +#include <wrl/client.h> + +class AudioDriverXAudio2 : public AudioDriverSW { + + enum { + AUDIO_BUFFERS = 2 + }; + + struct XAudio2DriverVoiceCallback : public IXAudio2VoiceCallback { + + HANDLE buffer_end_event; + XAudio2DriverVoiceCallback() : buffer_end_event(CreateEvent(NULL, FALSE, FALSE, NULL)) {} + void STDMETHODCALLTYPE OnBufferEnd(void* pBufferContext) { /*print_line("buffer ended");*/ SetEvent(buffer_end_event); } + + //Unused methods are stubs + void STDMETHODCALLTYPE OnStreamEnd() {} + void STDMETHODCALLTYPE OnVoiceProcessingPassEnd() {} + void STDMETHODCALLTYPE OnVoiceProcessingPassStart(UINT32 SamplesRequired) {} + void STDMETHODCALLTYPE OnBufferStart(void * pBufferContext) {} + void STDMETHODCALLTYPE OnLoopEnd(void * pBufferContext) {} + void STDMETHODCALLTYPE OnVoiceError(void * pBufferContext, HRESULT Error) {} + + }; + + Thread* thread; + Mutex* mutex; + + int32_t* samples_in; + int16_t* samples_out[AUDIO_BUFFERS]; + + static void thread_func(void* p_udata); + int buffer_size; + + unsigned int mix_rate; + OutputFormat output_format; + + int channels; + + bool active; + bool thread_exited; + mutable bool exit_thread; + bool pcm_open; + + WAVEFORMATEX wave_format; + Microsoft::WRL::ComPtr<IXAudio2> xaudio; + int current_buffer; + IXAudio2MasteringVoice* mastering_voice; + XAUDIO2_BUFFER xaudio_buffer[AUDIO_BUFFERS]; + IXAudio2SourceVoice* source_voice; + XAudio2DriverVoiceCallback voice_callback; + +public: + + const char* get_name() const; + + virtual Error init(); + virtual void start(); + virtual int get_mix_rate() const; + virtual OutputFormat get_output_format() const; + virtual float get_latency(); + virtual void lock(); + virtual void unlock(); + virtual void finish(); + + AudioDriverXAudio2(); + ~AudioDriverXAudio2(); +}; + +#endif diff --git a/drivers/zlib/SCsub b/drivers/zlib/SCsub new file mode 100644 index 0000000000..6a099aff52 --- /dev/null +++ b/drivers/zlib/SCsub @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +Import('env') + +# Not cloning the env, the includes need to be accessible for core/ + +# Thirdparty source files +# No check here as already done in drivers/SCsub +thirdparty_dir = "#thirdparty/zlib/" +thirdparty_sources = [ + "adler32.c", + "compress.c", + "crc32.c", + "deflate.c", + "infback.c", + "inffast.c", + "inflate.c", + "inftrees.c", + "trees.c", + "uncompr.c", + "zutil.c", +] +thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + +env.add_source_files(env.drivers_sources, thirdparty_sources) +env.Append(CPPPATH = [thirdparty_dir]) diff --git a/main/SCsub b/main/SCsub index fa60ffc3e8..cd9002de0a 100644 --- a/main/SCsub +++ b/main/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.main_sources=[] diff --git a/main/input_default.cpp b/main/input_default.cpp index d84b0b0f58..c60fcd2243 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -504,7 +504,7 @@ void InputDefault::action_release(const StringName& p_action){ action.fixed_frame=OS::get_singleton()->get_fixed_frames(); action.idle_frame=OS::get_singleton()->get_idle_frames(); - action.pressed=true; + action.pressed=false; action_state[p_action]=action; } @@ -655,7 +655,7 @@ static const char *s_ControllerMappings [] = "030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,x:b1,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,", "030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,", "030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,", - "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", + "030000005e0400001907000000010000,X360 Wireless Controller,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:h0.8,lefttrigger:a2,x:b2,dpup:h0.1,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:a5,b:b1,", "030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "030000005e0400008e02000001000000,Microsoft X-Box 360 pad,leftstick:b9,leftx:a0,lefty:a1,dpdown:h0.1,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:h0.2,lefttrigger:a2,x:b2,dpup:h0.4,back:b6,leftshoulder:b4,y:b3,a:b0,dpright:h0.8,righttrigger:a5,b:b1,", "030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", @@ -738,6 +738,10 @@ static const char *s_ControllerMappings [] = "303534632d303563342d576972656c65,PS4 Controller USB/Win,leftx:a0,lefty:a1,dpdown:b15,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a5,lefttrigger:a3,x:b0,dpup:b14,dpleft:b16,dpright:b17,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b1,righttrigger:b7,b:b2,", "c2a94d6963726f736f66742058626f78,Wireless X360 Controller,leftx:a0,lefty:a1,dpdown:b14,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:b11,lefttrigger:a2,x:b2,dpup:b13,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:b12,righttrigger:a5,b:b1,", #endif + + #ifdef WINRT_ENABLED + "__WINRT_GAMEPAD__,Xbox Controller,a:b2,b:b3,x:b4,y:b5,start:b0,back:b1,leftstick:b12,rightstick:b13,leftshoulder:b10,rightshoulder:b11,dpup:b6,dpdown:b7,dpleft:b8,dpright:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,", + #endif NULL }; @@ -845,6 +849,13 @@ uint32_t InputDefault::joy_axis(uint32_t p_last_id, int p_device, int p_axis, co return p_last_id; } + if (ABS(joy.last_axis[p_axis]) > 0.5 && joy.last_axis[p_axis] * p_value.value < 0) { + //changed direction quickly, insert fake event to release pending inputmap actions + JoyAxis jx; + jx.min = p_value.min; + jx.value = p_value.value < 0 ? 0.1 : -0.1; + p_last_id = joy_axis(p_last_id, p_device, p_axis, jx); + } joy.last_axis[p_axis] = p_value.value; float val = p_value.min == 0 ? -1.0f + 2.0f * p_value.value : p_value.value; @@ -1039,8 +1050,8 @@ void InputDefault::parse_mapping(String p_mapping) { if (entry[idx] == "") continue; - String from = entry[idx].get_slice(":", 1); - String to = entry[idx].get_slice(":", 0); + String from = entry[idx].get_slice(":", 1).replace(" ", ""); + String to = entry[idx].get_slice(":", 0).replace(" ", ""); JoyEvent to_event = _find_to_event(to); if (to_event.type == -1) @@ -1148,3 +1159,61 @@ Array InputDefault::get_connected_joysticks() { } return ret; } + +static const char* _buttons[] = { + "Face Button Bottom", + "Face Button Right", + "Face Button Left", + "Face Button Top", + "L", + "R", + "L2", + "R2", + "L3", + "R3", + "Select", + "Start", + "DPAD Up", + "DPAD Down", + "DPAD Left", + "DPAD Right" +}; + +static const char* _axes[] = { + "Left Stick X", + "Left Stick Y", + "Right Stick X", + "Right Stick Y", + "", + "", + "L2", + "R2" +}; + +String InputDefault::get_joy_button_string(int p_button) { + ERR_FAIL_INDEX_V(p_button, JOY_BUTTON_MAX, ""); + return _buttons[p_button]; +} + +int InputDefault::get_joy_button_index_from_string(String p_button) { + for (int i = 0; i < JOY_BUTTON_MAX; i++) { + if (p_button == _buttons[i]) { + return i; + } + } + ERR_FAIL_V(-1); +} + +String InputDefault::get_joy_axis_string(int p_axis) { + ERR_FAIL_INDEX_V(p_axis, JOY_AXIS_MAX, ""); + return _axes[p_axis]; +} + +int InputDefault::get_joy_axis_index_from_string(String p_axis) { + for (int i = 0; i < JOY_AXIS_MAX; i++) { + if (p_axis == _axes[i]) { + return i; + } + } + ERR_FAIL_V(-1); +} diff --git a/main/input_default.h b/main/input_default.h index fbf7837b3b..2db6d28abf 100644 --- a/main/input_default.h +++ b/main/input_default.h @@ -235,6 +235,11 @@ public: virtual bool is_joy_known(int p_device); virtual String get_joy_guid(int p_device) const; + virtual String get_joy_button_string(int p_button); + virtual String get_joy_axis_string(int p_axis); + virtual int get_joy_axis_index_from_string(String p_axis); + virtual int get_joy_button_index_from_string(String p_button); + bool is_joy_mapped(int p_device); String get_joy_guid_remapped(int p_device) const; void set_fallback_mapping(String p_guid); diff --git a/main/main.cpp b/main/main.cpp index e339f399de..912e8adf4f 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -57,7 +57,6 @@ #include "tools/editor/editor_node.h" #include "tools/editor/project_manager.h" -#include "tools/pck/pck_packer.h" #endif #include "io/file_access_network.h" @@ -560,6 +559,16 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas goto error; } + } else if (I->get()=="-epid") { + if (I->next()) { + + int editor_pid=I->next()->get().to_int(); + Globals::get_singleton()->set("editor_pid",editor_pid); + N=I->next()->next(); + } else { + goto error; + + } } else { //test for game path @@ -994,8 +1003,11 @@ Error Main::setup2() { } } #ifdef TOOLS_ENABLED + ObjectTypeDB::set_current_api(ObjectTypeDB::API_EDITOR); EditorNode::register_editor_types(); - ObjectTypeDB::register_type<PCKPacker>(); // todo: move somewhere else + + ObjectTypeDB::set_current_api(ObjectTypeDB::API_CORE); + #endif MAIN_PRINT("Main: Load Scripts, Modules, Drivers"); @@ -1022,6 +1034,8 @@ Error Main::setup2() { _start_success=true; locale=String(); + ObjectTypeDB::set_current_api(ObjectTypeDB::API_NONE); //no more api is registered at this point + MAIN_PRINT("Main: Done"); return OK; @@ -1294,9 +1308,10 @@ bool Main::start() { } + String local_game_path; if (game_path!="" && !project_manager_request) { - String local_game_path=game_path.replace("\\","/"); + local_game_path=game_path.replace("\\","/"); if (!local_game_path.begins_with("res://")) { bool absolute=(local_game_path.size()>1) && (local_game_path[0]=='/' || local_game_path[1]==':'); @@ -1363,98 +1378,99 @@ bool Main::start() { OS::get_singleton()->set_context(OS::CONTEXT_EDITOR); //editor_node->set_edited_scene(game); - } else { + } #endif + } - { - //autoload - List<PropertyInfo> props; - Globals::get_singleton()->get_property_list(&props); - - //first pass, add the constants so they exist before any script is loaded - for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) { - - String s = E->get().name; - if (!s.begins_with("autoload/")) - continue; - String name = s.get_slicec('/',1); - String path = Globals::get_singleton()->get(s); - bool global_var=false; - if (path.begins_with("*")) { - global_var=true; - } - - if (global_var) { - for(int i=0;i<ScriptServer::get_language_count();i++) { - ScriptServer::get_language(i)->add_global_constant(name,Variant()); - } - } - + if (!project_manager_request && !editor) { + if (game_path!="" || script!="") { + //autoload + List<PropertyInfo> props; + Globals::get_singleton()->get_property_list(&props); + + //first pass, add the constants so they exist before any script is loaded + for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) { + + String s = E->get().name; + if (!s.begins_with("autoload/")) + continue; + String name = s.get_slicec('/',1); + String path = Globals::get_singleton()->get(s); + bool global_var=false; + if (path.begins_with("*")) { + global_var=true; } - //second pass, load into global constants - List<Node*> to_add; - for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) { - - String s = E->get().name; - if (!s.begins_with("autoload/")) - continue; - String name = s.get_slicec('/',1); - String path = Globals::get_singleton()->get(s); - bool global_var=false; - if (path.begins_with("*")) { - global_var=true; - path=path.substr(1,path.length()-1); + if (global_var) { + for(int i=0;i<ScriptServer::get_language_count();i++) { + ScriptServer::get_language(i)->add_global_constant(name,Variant()); } + } - RES res = ResourceLoader::load(path); - ERR_EXPLAIN("Can't autoload: "+path); - ERR_CONTINUE(res.is_null()); - Node *n=NULL; - if (res->is_type("PackedScene")) { - Ref<PackedScene> ps = res; - n=ps->instance(); - } else if (res->is_type("Script")) { - Ref<Script> s = res; - StringName ibt = s->get_instance_base_type(); - bool valid_type = ObjectTypeDB::is_type(ibt,"Node"); - ERR_EXPLAIN("Script does not inherit a Node: "+path); - ERR_CONTINUE( !valid_type ); - - Object *obj = ObjectTypeDB::instance(ibt); - - ERR_EXPLAIN("Cannot instance script for autoload, expected 'Node' inheritance, got: "+String(ibt)); - ERR_CONTINUE( obj==NULL ); - - n = obj->cast_to<Node>(); - n->set_script(s.get_ref_ptr()); - } - - ERR_EXPLAIN("Path in autoload not a node or script: "+path); - ERR_CONTINUE(!n); - n->set_name(name); - - //defer so references are all valid on _ready() - //sml->get_root()->add_child(n); - to_add.push_back(n); + } - if (global_var) { - for(int i=0;i<ScriptServer::get_language_count();i++) { - ScriptServer::get_language(i)->add_global_constant(name,n); - } - } + //second pass, load into global constants + List<Node*> to_add; + for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) { + + String s = E->get().name; + if (!s.begins_with("autoload/")) + continue; + String name = s.get_slicec('/',1); + String path = Globals::get_singleton()->get(s); + bool global_var=false; + if (path.begins_with("*")) { + global_var=true; + path=path.substr(1,path.length()-1); + } + RES res = ResourceLoader::load(path); + ERR_EXPLAIN("Can't autoload: "+path); + ERR_CONTINUE(res.is_null()); + Node *n=NULL; + if (res->is_type("PackedScene")) { + Ref<PackedScene> ps = res; + n=ps->instance(); + } else if (res->is_type("Script")) { + Ref<Script> s = res; + StringName ibt = s->get_instance_base_type(); + bool valid_type = ObjectTypeDB::is_type(ibt,"Node"); + ERR_EXPLAIN("Script does not inherit a Node: "+path); + ERR_CONTINUE( !valid_type ); + + Object *obj = ObjectTypeDB::instance(ibt); + + ERR_EXPLAIN("Cannot instance script for autoload, expected 'Node' inheritance, got: "+String(ibt)); + ERR_CONTINUE( obj==NULL ); + + n = obj->cast_to<Node>(); + n->set_script(s.get_ref_ptr()); } - for(List<Node*>::Element *E=to_add.front();E;E=E->next()) { + ERR_EXPLAIN("Path in autoload not a node or script: "+path); + ERR_CONTINUE(!n); + n->set_name(name); - sml->get_root()->add_child(E->get()); + //defer so references are all valid on _ready() + //sml->get_root()->add_child(n); + to_add.push_back(n); + + if (global_var) { + for(int i=0;i<ScriptServer::get_language_count();i++) { + ScriptServer::get_language(i)->add_global_constant(name,n); + } } + } + for(List<Node*>::Element *E=to_add.front();E;E=E->next()) { + sml->get_root()->add_child(E->get()); } + //singletons + } + if (game_path!="") { Node *scene=NULL; Ref<PackedScene> scenedata = ResourceLoader::load(local_game_path); if (scenedata.is_valid()) @@ -1471,12 +1487,7 @@ bool Main::start() { if (icon.load(iconpath)==OK) OS::get_singleton()->set_icon(icon); } - - - //singletons -#ifdef TOOLS_ENABLED } -#endif } #ifdef TOOLS_ENABLED @@ -1753,4 +1764,3 @@ void Main::cleanup() { } - diff --git a/methods.py b/methods.py index e29fd760ba..bd5409e3d4 100755 --- a/methods.py +++ b/methods.py @@ -1379,6 +1379,7 @@ def use_windows_spawn_fix(self, platform=None): cmdline = cmd + " " + newargs rv=0 + env = {str(key): str(value) for key, value in env.iteritems()} if len(cmdline) > 32000 and cmd.endswith("ar") : cmdline = cmd + " " + args[1] + " " + args[2] + " " for i in range(3,len(args)) : @@ -1415,7 +1416,7 @@ def save_active_platforms(apnames,ap): logow.write(str) -def colored(sys,env): +def no_verbose(sys,env): #If the output is not a terminal, do nothing if not sys.stdout.isatty(): @@ -1450,3 +1451,73 @@ def colored(sys,env): env.Append( JARCOMSTR=[java_library_message] ) env.Append( JAVACCOMSTR=[java_compile_source_message] ) +def detect_visual_c_compiler_version(tools_env): + # tools_env is the variable scons uses to call tools that execute tasks, SCons's env['ENV'] that executes tasks... + # (see the SCons documentation for more information on what it does)... + # in order for this function to be well encapsulated i choose to force it to recieve SCons's TOOLS env (env['ENV'] + # and not scons setup environment (env)... so make sure you call the right environment on it or it will fail to detect + # the propper vc version that will be called + + # These is no flag to give to visual c compilers to set the architecture, ie scons bits argument (32,64,ARM etc) + # There are many different cl.exe files that are run, and each one compiles & links to a different architecture + # As far as I know, the only way to figure out what compiler will be run when Scons calls cl.exe via Program() + # is to check the PATH varaible and figure out which one will be called first. Code bellow does that and returns: + # the following string values: + + # "" Compiler not detected + # "amd64" Native 64 bit compiler + # "amd64_x86" 64 bit Cross Compiler for 32 bit + # "x86" Native 32 bit compiler + # "x86_amd64" 32 bit Cross Compiler for 64 bit + + # There are other architectures, but Godot does not support them currently, so this function does not detect arm/amd64_arm + # and similar architectures/compilers + + # Set chosen compiler to "not detected" + vc_chosen_compiler_index = -1 + vc_chosen_compiler_str = "" + + # find() works with -1 so big ifs bellow are needed... the simplest solution, in fact + # First test if amd64 and amd64_x86 compilers are present in the path + vc_amd64_compiler_detection_index = tools_env["PATH"].find(tools_env["VCINSTALLDIR"]+"BIN\\amd64;") + if(vc_amd64_compiler_detection_index > -1): + vc_chosen_compiler_index = vc_amd64_compiler_detection_index + vc_chosen_compiler_str = "amd64" + + vc_amd64_x86_compiler_detection_index = tools_env["PATH"].find(tools_env["VCINSTALLDIR"]+"BIN\\amd64_x86;") + if(vc_amd64_x86_compiler_detection_index > -1 + and (vc_chosen_compiler_index == -1 + or vc_chosen_compiler_index > vc_amd64_x86_compiler_detection_index)): + vc_chosen_compiler_index = vc_amd64_x86_compiler_detection_index + vc_chosen_compiler_str = "amd64_x86" + + + # Now check the 32 bit compilers + vc_x86_compiler_detection_index = tools_env["PATH"].find(tools_env["VCINSTALLDIR"]+"BIN;") + if(vc_x86_compiler_detection_index > -1 + and (vc_chosen_compiler_index == -1 + or vc_chosen_compiler_index > vc_x86_compiler_detection_index)): + vc_chosen_compiler_index = vc_x86_compiler_detection_index + vc_chosen_compiler_str = "x86" + + vc_x86_amd64_compiler_detection_index = tools_env["PATH"].find(tools_env['VCINSTALLDIR']+"BIN\\x86_amd64;") + if(vc_x86_amd64_compiler_detection_index > -1 + and (vc_chosen_compiler_index == -1 + or vc_chosen_compiler_index > vc_x86_amd64_compiler_detection_index)): + vc_chosen_compiler_index = vc_x86_amd64_compiler_detection_index + vc_chosen_compiler_str = "x86_amd64" + + # debug help + #print vc_amd64_compiler_detection_index + #print vc_amd64_x86_compiler_detection_index + #print vc_x86_compiler_detection_index + #print vc_x86_amd64_compiler_detection_index + #print "chosen "+str(vc_chosen_compiler_index)+ " | "+str(vc_chosen_compiler_str) + + return vc_chosen_compiler_str + + +def precious_program(env, program, sources, **args): + program = env.ProgramOriginal(program, sources, **args) + env.Precious(program) + return program diff --git a/modules/SCsub b/modules/SCsub index f37c3a55c7..4084248086 100644 --- a/modules/SCsub +++ b/modules/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env_modules = env.Clone() diff --git a/modules/chibi/SCsub b/modules/chibi/SCsub new file mode 100644 index 0000000000..dffd966753 --- /dev/null +++ b/modules/chibi/SCsub @@ -0,0 +1,9 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_chibi = env_modules.Clone() + +# Godot source files +env_chibi.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/chibi/config.py b/modules/chibi/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/chibi/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/drivers/chibi/cp_config.h b/modules/chibi/cp_config.h index 2ad704ace7..2ad704ace7 100644 --- a/drivers/chibi/cp_config.h +++ b/modules/chibi/cp_config.h diff --git a/drivers/chibi/cp_envelope.cpp b/modules/chibi/cp_envelope.cpp index 9892b6d4b0..9892b6d4b0 100644 --- a/drivers/chibi/cp_envelope.cpp +++ b/modules/chibi/cp_envelope.cpp diff --git a/drivers/chibi/cp_envelope.h b/modules/chibi/cp_envelope.h index d1ada53f7d..d1ada53f7d 100644 --- a/drivers/chibi/cp_envelope.h +++ b/modules/chibi/cp_envelope.h diff --git a/drivers/chibi/cp_file_access_wrapper.h b/modules/chibi/cp_file_access_wrapper.h index 5b361c0ea8..5b361c0ea8 100644 --- a/drivers/chibi/cp_file_access_wrapper.h +++ b/modules/chibi/cp_file_access_wrapper.h diff --git a/drivers/chibi/cp_instrument.cpp b/modules/chibi/cp_instrument.cpp index 7a732e33a4..7a732e33a4 100644 --- a/drivers/chibi/cp_instrument.cpp +++ b/modules/chibi/cp_instrument.cpp diff --git a/drivers/chibi/cp_instrument.h b/modules/chibi/cp_instrument.h index d8eb8333ee..d8eb8333ee 100644 --- a/drivers/chibi/cp_instrument.h +++ b/modules/chibi/cp_instrument.h diff --git a/drivers/chibi/cp_loader.h b/modules/chibi/cp_loader.h index 9d1074d1b8..9d1074d1b8 100644 --- a/drivers/chibi/cp_loader.h +++ b/modules/chibi/cp_loader.h diff --git a/drivers/chibi/cp_loader_it.cpp b/modules/chibi/cp_loader_it.cpp index 20a3960a23..20a3960a23 100644 --- a/drivers/chibi/cp_loader_it.cpp +++ b/modules/chibi/cp_loader_it.cpp diff --git a/drivers/chibi/cp_loader_it.h b/modules/chibi/cp_loader_it.h index 38a1cdd9c4..38a1cdd9c4 100644 --- a/drivers/chibi/cp_loader_it.h +++ b/modules/chibi/cp_loader_it.h diff --git a/drivers/chibi/cp_loader_it_info.cpp b/modules/chibi/cp_loader_it_info.cpp index 0360f7f9a4..0360f7f9a4 100644 --- a/drivers/chibi/cp_loader_it_info.cpp +++ b/modules/chibi/cp_loader_it_info.cpp diff --git a/drivers/chibi/cp_loader_it_instruments.cpp b/modules/chibi/cp_loader_it_instruments.cpp index ccb24bd81c..ccb24bd81c 100644 --- a/drivers/chibi/cp_loader_it_instruments.cpp +++ b/modules/chibi/cp_loader_it_instruments.cpp diff --git a/drivers/chibi/cp_loader_it_patterns.cpp b/modules/chibi/cp_loader_it_patterns.cpp index d951a91620..d951a91620 100644 --- a/drivers/chibi/cp_loader_it_patterns.cpp +++ b/modules/chibi/cp_loader_it_patterns.cpp diff --git a/drivers/chibi/cp_loader_it_samples.cpp b/modules/chibi/cp_loader_it_samples.cpp index ced7252a6c..ced7252a6c 100644 --- a/drivers/chibi/cp_loader_it_samples.cpp +++ b/modules/chibi/cp_loader_it_samples.cpp diff --git a/drivers/chibi/cp_loader_mod.cpp b/modules/chibi/cp_loader_mod.cpp index f867b77914..f867b77914 100644 --- a/drivers/chibi/cp_loader_mod.cpp +++ b/modules/chibi/cp_loader_mod.cpp diff --git a/drivers/chibi/cp_loader_mod.h b/modules/chibi/cp_loader_mod.h index 636f4f00f2..636f4f00f2 100644 --- a/drivers/chibi/cp_loader_mod.h +++ b/modules/chibi/cp_loader_mod.h diff --git a/drivers/chibi/cp_loader_s3m.cpp b/modules/chibi/cp_loader_s3m.cpp index 0fc15c1e2f..0fc15c1e2f 100644 --- a/drivers/chibi/cp_loader_s3m.cpp +++ b/modules/chibi/cp_loader_s3m.cpp diff --git a/drivers/chibi/cp_loader_s3m.h b/modules/chibi/cp_loader_s3m.h index 175e5e80fe..175e5e80fe 100644 --- a/drivers/chibi/cp_loader_s3m.h +++ b/modules/chibi/cp_loader_s3m.h diff --git a/drivers/chibi/cp_loader_xm.cpp b/modules/chibi/cp_loader_xm.cpp index bff8615a32..bff8615a32 100644 --- a/drivers/chibi/cp_loader_xm.cpp +++ b/modules/chibi/cp_loader_xm.cpp diff --git a/drivers/chibi/cp_loader_xm.h b/modules/chibi/cp_loader_xm.h index 9ae480cc8f..9ae480cc8f 100644 --- a/drivers/chibi/cp_loader_xm.h +++ b/modules/chibi/cp_loader_xm.h diff --git a/drivers/chibi/cp_mixer.h b/modules/chibi/cp_mixer.h index 7ad22ac146..7ad22ac146 100644 --- a/drivers/chibi/cp_mixer.h +++ b/modules/chibi/cp_mixer.h diff --git a/drivers/chibi/cp_note.h b/modules/chibi/cp_note.h index 5cfa3f11ec..5cfa3f11ec 100644 --- a/drivers/chibi/cp_note.h +++ b/modules/chibi/cp_note.h diff --git a/drivers/chibi/cp_order.h b/modules/chibi/cp_order.h index 03ecc00bba..03ecc00bba 100644 --- a/drivers/chibi/cp_order.h +++ b/modules/chibi/cp_order.h diff --git a/drivers/chibi/cp_pattern.cpp b/modules/chibi/cp_pattern.cpp index 83e165bf87..83e165bf87 100644 --- a/drivers/chibi/cp_pattern.cpp +++ b/modules/chibi/cp_pattern.cpp diff --git a/drivers/chibi/cp_pattern.h b/modules/chibi/cp_pattern.h index 4065caa5e5..4065caa5e5 100644 --- a/drivers/chibi/cp_pattern.h +++ b/modules/chibi/cp_pattern.h diff --git a/drivers/chibi/cp_player_data.cpp b/modules/chibi/cp_player_data.cpp index 3f3e9a5202..3f3e9a5202 100644 --- a/drivers/chibi/cp_player_data.cpp +++ b/modules/chibi/cp_player_data.cpp diff --git a/drivers/chibi/cp_player_data.h b/modules/chibi/cp_player_data.h index 282592b8f4..282592b8f4 100644 --- a/drivers/chibi/cp_player_data.h +++ b/modules/chibi/cp_player_data.h diff --git a/drivers/chibi/cp_player_data_control.cpp b/modules/chibi/cp_player_data_control.cpp index d9aaed904f..d9aaed904f 100644 --- a/drivers/chibi/cp_player_data_control.cpp +++ b/modules/chibi/cp_player_data_control.cpp diff --git a/drivers/chibi/cp_player_data_effects.cpp b/modules/chibi/cp_player_data_effects.cpp index 3a52a3b91b..3a52a3b91b 100644 --- a/drivers/chibi/cp_player_data_effects.cpp +++ b/modules/chibi/cp_player_data_effects.cpp diff --git a/drivers/chibi/cp_player_data_envelopes.cpp b/modules/chibi/cp_player_data_envelopes.cpp index 96af42d19f..96af42d19f 100644 --- a/drivers/chibi/cp_player_data_envelopes.cpp +++ b/modules/chibi/cp_player_data_envelopes.cpp diff --git a/drivers/chibi/cp_player_data_events.cpp b/modules/chibi/cp_player_data_events.cpp index fb5090461b..fb5090461b 100644 --- a/drivers/chibi/cp_player_data_events.cpp +++ b/modules/chibi/cp_player_data_events.cpp diff --git a/drivers/chibi/cp_player_data_filter.cpp b/modules/chibi/cp_player_data_filter.cpp index 30db807eed..30db807eed 100644 --- a/drivers/chibi/cp_player_data_filter.cpp +++ b/modules/chibi/cp_player_data_filter.cpp diff --git a/drivers/chibi/cp_player_data_nna.cpp b/modules/chibi/cp_player_data_nna.cpp index 844f043694..844f043694 100644 --- a/drivers/chibi/cp_player_data_nna.cpp +++ b/modules/chibi/cp_player_data_nna.cpp diff --git a/drivers/chibi/cp_player_data_notes.cpp b/modules/chibi/cp_player_data_notes.cpp index 621be019e1..621be019e1 100644 --- a/drivers/chibi/cp_player_data_notes.cpp +++ b/modules/chibi/cp_player_data_notes.cpp diff --git a/drivers/chibi/cp_player_data_utils.cpp b/modules/chibi/cp_player_data_utils.cpp index 170a849863..170a849863 100644 --- a/drivers/chibi/cp_player_data_utils.cpp +++ b/modules/chibi/cp_player_data_utils.cpp diff --git a/drivers/chibi/cp_sample.cpp b/modules/chibi/cp_sample.cpp index 55c2c910a5..55c2c910a5 100644 --- a/drivers/chibi/cp_sample.cpp +++ b/modules/chibi/cp_sample.cpp diff --git a/drivers/chibi/cp_sample.h b/modules/chibi/cp_sample.h index 4b3d218106..4b3d218106 100644 --- a/drivers/chibi/cp_sample.h +++ b/modules/chibi/cp_sample.h diff --git a/drivers/chibi/cp_sample_defs.h b/modules/chibi/cp_sample_defs.h index 169963c98e..169963c98e 100644 --- a/drivers/chibi/cp_sample_defs.h +++ b/modules/chibi/cp_sample_defs.h diff --git a/drivers/chibi/cp_sample_manager.cpp b/modules/chibi/cp_sample_manager.cpp index 5c2988e3f9..5c2988e3f9 100644 --- a/drivers/chibi/cp_sample_manager.cpp +++ b/modules/chibi/cp_sample_manager.cpp diff --git a/drivers/chibi/cp_sample_manager.h b/modules/chibi/cp_sample_manager.h index 74bcafc0cf..74bcafc0cf 100644 --- a/drivers/chibi/cp_sample_manager.h +++ b/modules/chibi/cp_sample_manager.h diff --git a/drivers/chibi/cp_song.cpp b/modules/chibi/cp_song.cpp index 4aa1a4228d..4aa1a4228d 100644 --- a/drivers/chibi/cp_song.cpp +++ b/modules/chibi/cp_song.cpp diff --git a/drivers/chibi/cp_song.h b/modules/chibi/cp_song.h index da5d106a63..da5d106a63 100644 --- a/drivers/chibi/cp_song.h +++ b/modules/chibi/cp_song.h diff --git a/drivers/chibi/cp_tables.cpp b/modules/chibi/cp_tables.cpp index 8c62150f31..8c62150f31 100644 --- a/drivers/chibi/cp_tables.cpp +++ b/modules/chibi/cp_tables.cpp diff --git a/drivers/chibi/cp_tables.h b/modules/chibi/cp_tables.h index ac7ee562b7..ac7ee562b7 100644 --- a/drivers/chibi/cp_tables.h +++ b/modules/chibi/cp_tables.h diff --git a/drivers/chibi/event_stream_chibi.cpp b/modules/chibi/event_stream_chibi.cpp index b88f4ee70e..b88f4ee70e 100644 --- a/drivers/chibi/event_stream_chibi.cpp +++ b/modules/chibi/event_stream_chibi.cpp diff --git a/drivers/chibi/event_stream_chibi.h b/modules/chibi/event_stream_chibi.h index cc7b0ace86..cc7b0ace86 100644 --- a/drivers/chibi/event_stream_chibi.h +++ b/modules/chibi/event_stream_chibi.h diff --git a/modules/chibi/register_types.cpp b/modules/chibi/register_types.cpp new file mode 100644 index 0000000000..b2ba16fa03 --- /dev/null +++ b/modules/chibi/register_types.cpp @@ -0,0 +1,41 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#include "event_stream_chibi.h" + +void register_chibi_types() { + + initialize_chibi(); +} + +void unregister_chibi_types() { + + finalize_chibi(); +} diff --git a/modules/chibi/register_types.h b/modules/chibi/register_types.h new file mode 100644 index 0000000000..159823b85d --- /dev/null +++ b/modules/chibi/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_chibi_types(); +void unregister_chibi_types(); diff --git a/modules/cscript/SCsub b/modules/cscript/SCsub index 403fe68f66..0882406761 100644 --- a/modules/cscript/SCsub +++ b/modules/cscript/SCsub @@ -1,5 +1,7 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.modules_sources,"*.cpp") +env.add_source_files(env.modules_sources, "*.cpp") Export('env') diff --git a/modules/dds/SCsub b/modules/dds/SCsub new file mode 100644 index 0000000000..3d92ff02d6 --- /dev/null +++ b/modules/dds/SCsub @@ -0,0 +1,8 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_dds = env_modules.Clone() + +env_dds.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/dds/config.py b/modules/dds/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/dds/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/modules/dds/register_types.cpp b/modules/dds/register_types.cpp new file mode 100644 index 0000000000..0d28e2bbef --- /dev/null +++ b/modules/dds/register_types.cpp @@ -0,0 +1,44 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#include "texture_loader_dds.h" + +static ResourceFormatDDS *resource_loader_dds = NULL; + +void register_dds_types() { + + resource_loader_dds = memnew( ResourceFormatDDS ); + ResourceLoader::add_resource_format_loader(resource_loader_dds); +} + +void unregister_dds_types() { + + memdelete(resource_loader_dds); +} diff --git a/modules/dds/register_types.h b/modules/dds/register_types.h new file mode 100644 index 0000000000..f9ecfb8ef9 --- /dev/null +++ b/modules/dds/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_dds_types(); +void unregister_dds_types(); diff --git a/drivers/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp index 0cc84f02f7..0cc84f02f7 100644 --- a/drivers/dds/texture_loader_dds.cpp +++ b/modules/dds/texture_loader_dds.cpp diff --git a/drivers/dds/texture_loader_dds.h b/modules/dds/texture_loader_dds.h index 371eb1858c..371eb1858c 100644 --- a/drivers/dds/texture_loader_dds.h +++ b/modules/dds/texture_loader_dds.h diff --git a/modules/enet/SCsub b/modules/enet/SCsub index d2bc8801e4..5175803f44 100644 --- a/modules/enet/SCsub +++ b/modules/enet/SCsub @@ -1,8 +1,28 @@ +#!/usr/bin/env python + Import('env') +Import('env_modules') + +# Thirdparty source files + +env_enet = env_modules.Clone() + +if (env["enet"] != "system"): # builtin + thirdparty_dir = "#thirdparty/enet/" + thirdparty_sources = [ + "callbacks.c", + "compress.c", + "host.c", + "list.c", + "packet.c", + "peer.c", + "protocol.c", + "unix.c", + "win32.c", + ] + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] -env.add_source_files(env.modules_sources,"*.cpp") -env.add_source_files(env.modules_sources,"*.c") -#TODO: Make it possible to build against system enet -env.Append(CPPPATH = ["#modules/enet"]) + env_enet.add_source_files(env.modules_sources, thirdparty_sources) + env_enet.Append(CPPPATH = [thirdparty_dir]) -Export('env') +env_enet.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/enet/config.py b/modules/enet/config.py index ea7e83378a..368e97e152 100644 --- a/modules/enet/config.py +++ b/modules/enet/config.py @@ -1,11 +1,6 @@ - def can_build(platform): - return True - + return True def configure(env): pass - - - diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index 18a4347edf..a82283591d 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -1,3 +1,31 @@ +/*************************************************************************/ +/* networked_multiplayer_enet.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ #include "os/os.h" #include "io/marshalls.h" #include "networked_multiplayer_enet.h" @@ -32,7 +60,7 @@ Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int host = enet_host_create (& address /* the address to bind the server host to */, p_max_clients /* allow up to 32 clients and/or outgoing connections */, - 2 /* allow up to 2 channels to be used, 0 and 1 */, + SYSCH_MAX /* allow up to SYSCH_MAX channels to be used */, p_in_bandwidth /* assume any amount of incoming bandwidth */, p_out_bandwidth /* assume any amount of outgoing bandwidth */); @@ -49,10 +77,11 @@ Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int Error NetworkedMultiplayerENet::create_client(const IP_Address& p_ip, int p_port, int p_in_bandwidth, int p_out_bandwidth){ ERR_FAIL_COND_V(active,ERR_ALREADY_IN_USE); + ERR_FAIL_COND_V(p_ip.type != IP_Address::TYPE_IPV4, ERR_INVALID_PARAMETER); host = enet_host_create (NULL /* create a client host */, 1 /* only allow 1 outgoing connection */, - 2 /* allow up 2 channels to be used, 0 and 1 */, + SYSCH_MAX /* allow up to SYSCH_MAX channels to be used */, p_in_bandwidth /* 56K modem with 56 Kbps downstream bandwidth */, p_out_bandwidth /* 56K modem with 14 Kbps upstream bandwidth */); @@ -62,7 +91,7 @@ Error NetworkedMultiplayerENet::create_client(const IP_Address& p_ip, int p_port _setup_compressor(); ENetAddress address; - address.host=p_ip.host; + address.host=p_ip.field32[0]; address.port=p_port; //enet_address_set_host (& address, "localhost"); @@ -70,8 +99,8 @@ Error NetworkedMultiplayerENet::create_client(const IP_Address& p_ip, int p_port unique_id=_gen_unique_id(); - /* Initiate the connection, allocating the two channels 0 and 1. */ - ENetPeer *peer = enet_host_connect (host, & address, 2, unique_id); + /* Initiate the connection, allocating the enough channels */ + ENetPeer *peer = enet_host_connect (host, & address, SYSCH_MAX, unique_id); if (peer == NULL) { enet_host_destroy(host); @@ -121,7 +150,8 @@ void NetworkedMultiplayerENet::poll(){ } IP_Address ip; - ip.host=event.peer -> address.host; + ip.type = IP_Address::TYPE_IPV4; + ip.field32[0]=event.peer -> address.host; int *new_id = memnew( int ); *new_id = event.data; @@ -148,12 +178,12 @@ void NetworkedMultiplayerENet::poll(){ ENetPacket * packet = enet_packet_create (NULL,8,ENET_PACKET_FLAG_RELIABLE); encode_uint32(SYSMSG_ADD_PEER,&packet->data[0]); encode_uint32(E->key(),&packet->data[4]); - enet_peer_send(event.peer,1,packet); + enet_peer_send(event.peer,SYSCH_CONFIG,packet); //send the new peer to existing peers packet = enet_packet_create (NULL,8,ENET_PACKET_FLAG_RELIABLE); encode_uint32(SYSMSG_ADD_PEER,&packet->data[0]); encode_uint32(*new_id,&packet->data[4]); - enet_peer_send(E->get(),1,packet); + enet_peer_send(E->get(),SYSCH_CONFIG,packet); } } else { @@ -185,7 +215,7 @@ void NetworkedMultiplayerENet::poll(){ ENetPacket* packet = enet_packet_create (NULL,8,ENET_PACKET_FLAG_RELIABLE); encode_uint32(SYSMSG_REMOVE_PEER,&packet->data[0]); encode_uint32(*id,&packet->data[4]); - enet_peer_send(E->get(),1,packet); + enet_peer_send(E->get(),SYSCH_CONFIG,packet); } } else if (!server) { emit_signal("server_disconnected"); @@ -204,10 +234,13 @@ void NetworkedMultiplayerENet::poll(){ case ENET_EVENT_TYPE_RECEIVE: { - if (event.channelID==1) { + if (event.channelID==SYSCH_CONFIG) { //some config message ERR_CONTINUE( event.packet->dataLength < 8); + // Only server can send config messages + ERR_CONTINUE( server ); + int msg = decode_uint32(&event.packet->data[0]); int id = decode_uint32(&event.packet->data[4]); @@ -226,12 +259,12 @@ void NetworkedMultiplayerENet::poll(){ } enet_packet_destroy(event.packet); - } else if (event.channelID==0){ + } else if (event.channelID < SYSCH_MAX){ Packet packet; packet.packet = event.packet; - int *id = (int*)event.peer -> data; + uint32_t *id = (uint32_t*)event.peer->data; ERR_CONTINUE(event.packet->dataLength<12) @@ -243,6 +276,8 @@ void NetworkedMultiplayerENet::poll(){ packet.from=source; if (server) { + // Someone is cheating and trying to fake the source! + ERR_CONTINUE(source!=*id); packet.from=*id; @@ -258,7 +293,7 @@ void NetworkedMultiplayerENet::poll(){ ENetPacket* packet2 = enet_packet_create (packet.packet->data,packet.packet->dataLength,flags); - enet_peer_send(E->get(),0,packet2); + enet_peer_send(E->get(),event.channelID,packet2); } } else if (target<0) { @@ -272,7 +307,7 @@ void NetworkedMultiplayerENet::poll(){ ENetPacket* packet2 = enet_packet_create (packet.packet->data,packet.packet->dataLength,flags); - enet_peer_send(E->get(),0,packet2); + enet_peer_send(E->get(),event.channelID,packet2); } if (-target != 1) { @@ -289,7 +324,7 @@ void NetworkedMultiplayerENet::poll(){ } else { //to someone else, specifically ERR_CONTINUE(!peer_map.has(target)); - enet_peer_send(peer_map[target],0,packet.packet); + enet_peer_send(peer_map[target],event.channelID,packet.packet); } } else { @@ -359,7 +394,7 @@ Error NetworkedMultiplayerENet::get_packet(const uint8_t **r_buffer,int &r_buffe incoming_packets.pop_front(); *r_buffer=(const uint8_t*)(¤t_packet.packet->data[12]); - r_buffer_size=current_packet.packet->dataLength; + r_buffer_size=current_packet.packet->dataLength-12; return OK; } @@ -369,16 +404,20 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer,int p_buffer_ ERR_FAIL_COND_V(connection_status!=CONNECTION_CONNECTED,ERR_UNCONFIGURED); int packet_flags=0; + int channel=SYSCH_RELIABLE; switch(transfer_mode) { case TRANSFER_MODE_UNRELIABLE: { packet_flags=ENET_PACKET_FLAG_UNSEQUENCED; + channel=SYSCH_UNRELIABLE; } break; case TRANSFER_MODE_UNRELIABLE_ORDERED: { packet_flags=0; + channel=SYSCH_UNRELIABLE; } break; case TRANSFER_MODE_RELIABLE: { packet_flags=ENET_PACKET_FLAG_RELIABLE; + channel=SYSCH_RELIABLE; } break; } @@ -402,7 +441,7 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer,int p_buffer_ if (server) { if (target_peer==0) { - enet_host_broadcast(host,0,packet); + enet_host_broadcast(host,channel,packet); } else if (target_peer<0) { //send to all but one //and make copies for sending @@ -416,18 +455,18 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer,int p_buffer_ ENetPacket* packet2 = enet_packet_create (packet->data,packet->dataLength,packet_flags); - enet_peer_send(F->get(),0,packet2); + enet_peer_send(F->get(),channel,packet2); } enet_packet_destroy(packet); //original packet no longer needed } else { - enet_peer_send (E->get(), 0, packet); + enet_peer_send (E->get(), channel, packet); } } else { ERR_FAIL_COND_V(!peer_map.has(1),ERR_BUG); - enet_peer_send (peer_map[1], 0, packet); //send to server for broadcast.. + enet_peer_send (peer_map[1], channel, packet); //send to server for broadcast.. } @@ -646,5 +685,6 @@ NetworkedMultiplayerENet::~NetworkedMultiplayerENet(){ // sets IP for ENet to bind when using create_server // if no IP is set, then ENet bind to ENET_HOST_ANY void NetworkedMultiplayerENet::set_bind_ip(const IP_Address& p_ip){ - bind_ip=p_ip.host; + ERR_FAIL_COND(p_ip.type != IP_Address::TYPE_IPV4); + bind_ip=p_ip.field32[0]; } diff --git a/modules/enet/networked_multiplayer_enet.h b/modules/enet/networked_multiplayer_enet.h index 59863c1f78..3db318c96a 100644 --- a/modules/enet/networked_multiplayer_enet.h +++ b/modules/enet/networked_multiplayer_enet.h @@ -1,3 +1,31 @@ +/*************************************************************************/ +/* networked_multiplayer_enet.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ #ifndef NETWORKED_MULTIPLAYER_ENET_H #define NETWORKED_MULTIPLAYER_ENET_H @@ -23,6 +51,13 @@ private: SYSMSG_REMOVE_PEER }; + enum { + SYSCH_CONFIG, + SYSCH_RELIABLE, + SYSCH_UNRELIABLE, + SYSCH_MAX + }; + bool active; bool server; diff --git a/modules/enet/win32.c b/modules/enet/win32.c deleted file mode 100644 index d77fa9a49a..0000000000 --- a/modules/enet/win32.c +++ /dev/null @@ -1,422 +0,0 @@ -/** - @file win32.c - @brief ENet Win32 system specific functions -*/ -#ifdef _WIN32 - -#define ENET_BUILDING_LIB 0 -#include "enet/enet.h" -#include <windows.h> -#include <mmsystem.h> - -static enet_uint32 timeBase = 0; - -int -enet_initialize (void) -{ - WORD versionRequested = MAKEWORD (1, 1); - WSADATA wsaData; - - if (WSAStartup (versionRequested, & wsaData)) - return -1; - - if (LOBYTE (wsaData.wVersion) != 1|| - HIBYTE (wsaData.wVersion) != 1) - { - WSACleanup (); - - return -1; - } - - timeBeginPeriod (1); - - return 0; -} - -void -enet_deinitialize (void) -{ - timeEndPeriod (1); - - WSACleanup (); -} - -enet_uint32 -enet_host_random_seed (void) -{ - return (enet_uint32) timeGetTime (); -} - -enet_uint32 -enet_time_get (void) -{ - return (enet_uint32) timeGetTime () - timeBase; -} - -void -enet_time_set (enet_uint32 newTimeBase) -{ - timeBase = (enet_uint32) timeGetTime () - newTimeBase; -} - -int -enet_address_set_host (ENetAddress * address, const char * name) -{ - struct hostent * hostEntry; - - hostEntry = gethostbyname (name); - if (hostEntry == NULL || - hostEntry -> h_addrtype != AF_INET) - { - unsigned long host = inet_addr (name); - if (host == INADDR_NONE) - return -1; - address -> host = host; - return 0; - } - - address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0]; - - return 0; -} - -int -enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength) -{ - char * addr = inet_ntoa (* (struct in_addr *) & address -> host); - if (addr == NULL) - return -1; - else - { - size_t addrLen = strlen(addr); - if (addrLen >= nameLength) - return -1; - memcpy (name, addr, addrLen + 1); - } - return 0; -} - -int -enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength) -{ - struct in_addr in; - struct hostent * hostEntry; - - in.s_addr = address -> host; - - hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET); - if (hostEntry == NULL) - return enet_address_get_host_ip (address, name, nameLength); - else - { - size_t hostLen = strlen (hostEntry -> h_name); - if (hostLen >= nameLength) - return -1; - memcpy (name, hostEntry -> h_name, hostLen + 1); - } - - return 0; -} - -int -enet_socket_bind (ENetSocket socket, const ENetAddress * address) -{ - struct sockaddr_in sin; - - memset (& sin, 0, sizeof (struct sockaddr_in)); - - sin.sin_family = AF_INET; - - if (address != NULL) - { - sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); - sin.sin_addr.s_addr = address -> host; - } - else - { - sin.sin_port = 0; - sin.sin_addr.s_addr = INADDR_ANY; - } - - return bind (socket, - (struct sockaddr *) & sin, - sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0; -} - -int -enet_socket_get_address (ENetSocket socket, ENetAddress * address) -{ - struct sockaddr_in sin; - int sinLength = sizeof (struct sockaddr_in); - - if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1) - return -1; - - address -> host = (enet_uint32) sin.sin_addr.s_addr; - address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); - - return 0; -} - -int -enet_socket_listen (ENetSocket socket, int backlog) -{ - return listen (socket, backlog < 0 ? SOMAXCONN : backlog) == SOCKET_ERROR ? -1 : 0; -} - -ENetSocket -enet_socket_create (ENetSocketType type) -{ - return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); -} - -int -enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) -{ - int result = SOCKET_ERROR; - switch (option) - { - case ENET_SOCKOPT_NONBLOCK: - { - u_long nonBlocking = (u_long) value; - result = ioctlsocket (socket, FIONBIO, & nonBlocking); - break; - } - - case ENET_SOCKOPT_BROADCAST: - result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int)); - break; - - case ENET_SOCKOPT_REUSEADDR: - result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int)); - break; - - case ENET_SOCKOPT_RCVBUF: - result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int)); - break; - - case ENET_SOCKOPT_SNDBUF: - result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int)); - break; - - case ENET_SOCKOPT_RCVTIMEO: - result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & value, sizeof (int)); - break; - - case ENET_SOCKOPT_SNDTIMEO: - result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & value, sizeof (int)); - break; - - case ENET_SOCKOPT_NODELAY: - result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int)); - break; - - default: - break; - } - return result == SOCKET_ERROR ? -1 : 0; -} - -int -enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value) -{ - int result = SOCKET_ERROR, len; - switch (option) - { - case ENET_SOCKOPT_ERROR: - len = sizeof(int); - result = getsockopt (socket, SOL_SOCKET, SO_ERROR, (char *) value, & len); - break; - - default: - break; - } - return result == SOCKET_ERROR ? -1 : 0; -} - -int -enet_socket_connect (ENetSocket socket, const ENetAddress * address) -{ - struct sockaddr_in sin; - int result; - - memset (& sin, 0, sizeof (struct sockaddr_in)); - - sin.sin_family = AF_INET; - sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); - sin.sin_addr.s_addr = address -> host; - - result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); - if (result == SOCKET_ERROR && WSAGetLastError () != WSAEWOULDBLOCK) - return -1; - - return 0; -} - -ENetSocket -enet_socket_accept (ENetSocket socket, ENetAddress * address) -{ - SOCKET result; - struct sockaddr_in sin; - int sinLength = sizeof (struct sockaddr_in); - - result = accept (socket, - address != NULL ? (struct sockaddr *) & sin : NULL, - address != NULL ? & sinLength : NULL); - - if (result == INVALID_SOCKET) - return ENET_SOCKET_NULL; - - if (address != NULL) - { - address -> host = (enet_uint32) sin.sin_addr.s_addr; - address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); - } - - return result; -} - -int -enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how) -{ - return shutdown (socket, (int) how) == SOCKET_ERROR ? -1 : 0; -} - -void -enet_socket_destroy (ENetSocket socket) -{ - if (socket != INVALID_SOCKET) - closesocket (socket); -} - -int -enet_socket_send (ENetSocket socket, - const ENetAddress * address, - const ENetBuffer * buffers, - size_t bufferCount) -{ - struct sockaddr_in sin; - DWORD sentLength; - - if (address != NULL) - { - memset (& sin, 0, sizeof (struct sockaddr_in)); - - sin.sin_family = AF_INET; - sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); - sin.sin_addr.s_addr = address -> host; - } - - if (WSASendTo (socket, - (LPWSABUF) buffers, - (DWORD) bufferCount, - & sentLength, - 0, - address != NULL ? (struct sockaddr *) & sin : NULL, - address != NULL ? sizeof (struct sockaddr_in) : 0, - NULL, - NULL) == SOCKET_ERROR) - { - if (WSAGetLastError () == WSAEWOULDBLOCK) - return 0; - - return -1; - } - - return (int) sentLength; -} - -int -enet_socket_receive (ENetSocket socket, - ENetAddress * address, - ENetBuffer * buffers, - size_t bufferCount) -{ - INT sinLength = sizeof (struct sockaddr_in); - DWORD flags = 0, - recvLength; - struct sockaddr_in sin; - - if (WSARecvFrom (socket, - (LPWSABUF) buffers, - (DWORD) bufferCount, - & recvLength, - & flags, - address != NULL ? (struct sockaddr *) & sin : NULL, - address != NULL ? & sinLength : NULL, - NULL, - NULL) == SOCKET_ERROR) - { - switch (WSAGetLastError ()) - { - case WSAEWOULDBLOCK: - case WSAECONNRESET: - return 0; - } - - return -1; - } - - if (flags & MSG_PARTIAL) - return -1; - - if (address != NULL) - { - address -> host = (enet_uint32) sin.sin_addr.s_addr; - address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); - } - - return (int) recvLength; -} - -int -enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout) -{ - struct timeval timeVal; - - timeVal.tv_sec = timeout / 1000; - timeVal.tv_usec = (timeout % 1000) * 1000; - - return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal); -} - -int -enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout) -{ - fd_set readSet, writeSet; - struct timeval timeVal; - int selectCount; - - timeVal.tv_sec = timeout / 1000; - timeVal.tv_usec = (timeout % 1000) * 1000; - - FD_ZERO (& readSet); - FD_ZERO (& writeSet); - - if (* condition & ENET_SOCKET_WAIT_SEND) - FD_SET (socket, & writeSet); - - if (* condition & ENET_SOCKET_WAIT_RECEIVE) - FD_SET (socket, & readSet); - - selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal); - - if (selectCount < 0) - return -1; - - * condition = ENET_SOCKET_WAIT_NONE; - - if (selectCount == 0) - return 0; - - if (FD_ISSET (socket, & writeSet)) - * condition |= ENET_SOCKET_WAIT_SEND; - - if (FD_ISSET (socket, & readSet)) - * condition |= ENET_SOCKET_WAIT_RECEIVE; - - return 0; -} - -#endif - diff --git a/modules/etc1/SCsub b/modules/etc1/SCsub new file mode 100644 index 0000000000..ea035fcde3 --- /dev/null +++ b/modules/etc1/SCsub @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_etc1 = env_modules.Clone() + +# Thirdparty source files +# Not unbundled so far since not widespread as shared library +thirdparty_dir = "#thirdparty/rg-etc1/" +thirdparty_sources = [ + "rg_etc1.cpp", +] +thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + +env_etc1.add_source_files(env.modules_sources, thirdparty_sources) +env_etc1.Append(CPPPATH = [thirdparty_dir]) + +# Godot source files +env_etc1.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/etc1/config.py b/modules/etc1/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/etc1/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/drivers/etc1/image_etc.cpp b/modules/etc1/image_etc.cpp index cf2384240b..cf2384240b 100644 --- a/drivers/etc1/image_etc.cpp +++ b/modules/etc1/image_etc.cpp diff --git a/drivers/etc1/image_etc.h b/modules/etc1/image_etc.h index edcff39bfd..edcff39bfd 100644 --- a/drivers/etc1/image_etc.h +++ b/modules/etc1/image_etc.h diff --git a/modules/etc1/register_types.cpp b/modules/etc1/register_types.cpp new file mode 100644 index 0000000000..e9eba6c864 --- /dev/null +++ b/modules/etc1/register_types.cpp @@ -0,0 +1,47 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#include "image_etc.h" +#include "texture_loader_pkm.h" + +static ResourceFormatPKM *resource_loader_pkm = NULL; + +void register_etc1_types() { + + resource_loader_pkm = memnew( ResourceFormatPKM ); + ResourceLoader::add_resource_format_loader(resource_loader_pkm); + + _register_etc1_compress_func(); +} + +void unregister_etc1_types() { + + memdelete(resource_loader_pkm); +} diff --git a/modules/etc1/register_types.h b/modules/etc1/register_types.h new file mode 100644 index 0000000000..bc26699d54 --- /dev/null +++ b/modules/etc1/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_etc1_types(); +void unregister_etc1_types(); diff --git a/drivers/etc1/texture_loader_pkm.cpp b/modules/etc1/texture_loader_pkm.cpp index 275afc1fd6..275afc1fd6 100644 --- a/drivers/etc1/texture_loader_pkm.cpp +++ b/modules/etc1/texture_loader_pkm.cpp diff --git a/drivers/etc1/texture_loader_pkm.h b/modules/etc1/texture_loader_pkm.h index 5788716d9f..5788716d9f 100644 --- a/drivers/etc1/texture_loader_pkm.h +++ b/modules/etc1/texture_loader_pkm.h diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub new file mode 100644 index 0000000000..1f759dee9a --- /dev/null +++ b/modules/freetype/SCsub @@ -0,0 +1,90 @@ +#!/usr/bin/env python + +Import('env') + +# Not building in a separate env as core needs it + +# Thirdparty source files +if (env["freetype"] != "system"): # builtin + thirdparty_dir = "#thirdparty/freetype/" + thirdparty_sources = [ + "src/autofit/autofit.c", + "src/base/ftapi.c", + "src/base/ftbase.c", + "src/base/ftbbox.c", + "src/base/ftbdf.c", + "src/base/ftbitmap.c", + "src/base/ftcid.c", + "src/base/ftdebug.c", + "src/base/ftfntfmt.c", + "src/base/ftfstype.c", + "src/base/ftgasp.c", + "src/base/ftglyph.c", + "src/base/ftgxval.c", + "src/base/ftinit.c", + "src/base/ftlcdfil.c", + "src/base/ftmm.c", + "src/base/ftotval.c", + "src/base/ftpatent.c", + "src/base/ftpfr.c", + "src/base/ftpic.c", + "src/base/ftstroke.c", + "src/base/ftsynth.c", + "src/base/ftsystem.c", + "src/base/fttype1.c", + "src/base/ftwinfnt.c", + "src/bdf/bdf.c", + "src/cache/ftcache.c", + "src/cff/cff.c", + "src/cid/type1cid.c", + "src/gxvalid/gxvalid.c", + "src/otvalid/otvalid.c", + "src/pcf/pcf.c", + "src/pfr/pfr.c", + "src/psaux/psaux.c", + "src/pshinter/pshinter.c", + "src/psnames/psnames.c", + "src/raster/raster.c", + "src/sfnt/sfnt.c", + "src/smooth/smooth.c", + "src/truetype/truetype.c", + "src/type1/type1.c", + "src/type42/type42.c", + "src/winfonts/winfnt.c", + ] + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + + # Include header for WinRT to fix build issues + if "platform" in env and env["platform"] == "winrt": + env.Append(CCFLAGS = ['/FI', '"modules/freetype/winrtdef.h"']) + + env.Append(CPPPATH = [thirdparty_dir, thirdparty_dir + "/include"]) + + # also requires libpng headers + if (env["libpng"] != "system"): # builtin + env.Append(CPPPATH = ["#thirdparty/libpng"]) + + """ FIXME: Remove this commented code if Windows can handle the monolithic lib + # fix for Windows' shell miserably failing on long lines, split in two libraries + half1 = [] + half2 = [] + for x in thirdparty_sources: + if (x.find("src/base") != -1 and x.find("src/sfnt") != -1): + half1.append(x) + else: + half2.append(x) + + lib = env.Library("freetype_builtin1", half2) + env.Append(LIBS = [lib]) + lib = env.Library("freetype_builtin2", half1) + env.Append(LIBS = [lib]) + """ + + lib = env.Library("freetype_builtin", thirdparty_sources) + env.Append(LIBS = [lib]) + +# Godot source files +env.add_source_files(env.modules_sources, "*.cpp") +env.Append(CCFLAGS = ['-DFREETYPE_ENABLED']) + +Export('env') diff --git a/modules/freetype/config.py b/modules/freetype/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/freetype/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/modules/freetype/register_types.cpp b/modules/freetype/register_types.cpp new file mode 100644 index 0000000000..2b9f47f54c --- /dev/null +++ b/modules/freetype/register_types.cpp @@ -0,0 +1,33 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +void register_freetype_types() {} + +void unregister_freetype_types() {} diff --git a/modules/freetype/register_types.h b/modules/freetype/register_types.h new file mode 100644 index 0000000000..326cd2e6ea --- /dev/null +++ b/modules/freetype/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_freetype_types(); +void unregister_freetype_types(); diff --git a/modules/freetype/winrtdef.h b/modules/freetype/winrtdef.h new file mode 100644 index 0000000000..69c6baf532 --- /dev/null +++ b/modules/freetype/winrtdef.h @@ -0,0 +1,32 @@ +/*************************************************************************/ +/* winrtdef.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +// "generic" is a reserved keyword in C++/CX code +// this avoids the errors in the variable name from Freetype code +#define generic freetype_generic diff --git a/modules/gdscript/SCsub b/modules/gdscript/SCsub index 403fe68f66..0882406761 100644 --- a/modules/gdscript/SCsub +++ b/modules/gdscript/SCsub @@ -1,5 +1,7 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.modules_sources,"*.cpp") +env.add_source_files(env.modules_sources, "*.cpp") Export('env') diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp index ce8b6a6ea4..b75b13551e 100644 --- a/modules/gdscript/gd_compiler.cpp +++ b/modules/gdscript/gd_compiler.cpp @@ -662,6 +662,46 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre return p_stack_level|GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS; } break; + // ternary operators + case GDParser::OperatorNode::OP_TERNARY_IF: { + + // x IF a ELSE y operator with early out on failure + + int res = _parse_expression(codegen,on->arguments[0],p_stack_level); + if (res<0) + return res; + codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF_NOT); + codegen.opcodes.push_back(res); + int jump_fail_pos=codegen.opcodes.size(); + codegen.opcodes.push_back(0); + + + res = _parse_expression(codegen,on->arguments[1],p_stack_level); + if (res<0) + return res; + + codegen.alloc_stack(p_stack_level); //it will be used.. + codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN); + codegen.opcodes.push_back(p_stack_level|GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS); + codegen.opcodes.push_back(res); + codegen.opcodes.push_back(GDFunction::OPCODE_JUMP); + int jump_past_pos=codegen.opcodes.size(); + codegen.opcodes.push_back(0); + + codegen.opcodes[jump_fail_pos]=codegen.opcodes.size(); + res = _parse_expression(codegen,on->arguments[2],p_stack_level); + if (res<0) + return res; + + codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN); + codegen.opcodes.push_back(p_stack_level|GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS); + codegen.opcodes.push_back(res); + + codegen.opcodes[jump_past_pos]=codegen.opcodes.size(); + + return p_stack_level|GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS; + + } break; //unary operators case GDParser::OperatorNode::OP_NEG: { if (!_create_unary_operator(codegen,on,Variant::OP_NEGATE,p_stack_level)) return -1;} break; case GDParser::OperatorNode::OP_NOT: { if (!_create_unary_operator(codegen,on,Variant::OP_NOT,p_stack_level)) return -1;} break; @@ -965,12 +1005,12 @@ Error GDCompiler::_parse_block(CodeGen& codegen,const GDParser::BlockNode *p_blo switch(s->type) { case GDParser::Node::TYPE_NEWLINE: { - +#ifdef DEBUG_ENABLED const GDParser::NewLineNode *nl = static_cast<const GDParser::NewLineNode*>(s); codegen.opcodes.push_back(GDFunction::OPCODE_LINE); codegen.opcodes.push_back(nl->line); codegen.current_line=nl->line; - +#endif } break; case GDParser::Node::TYPE_CONTROL_FLOW: { // try subblocks @@ -1161,8 +1201,10 @@ Error GDCompiler::_parse_block(CodeGen& codegen,const GDParser::BlockNode *p_blo codegen.opcodes.push_back(ret); } break; case GDParser::Node::TYPE_BREAKPOINT: { +#ifdef DEBUG_ENABLED // try subblocks codegen.opcodes.push_back(GDFunction::OPCODE_BREAKPOINT); +#endif } break; case GDParser::Node::TYPE_LOCAL_VAR: { @@ -1403,6 +1445,10 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode * #endif if (p_func) { gdfunc->_initial_line=p_func->line; +#ifdef TOOLS_ENABLED + + p_script->member_lines[func_name]=p_func->line; +#endif } else { gdfunc->_initial_line=0; } @@ -1632,6 +1678,12 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa p_script->member_indices[name]=minfo; p_script->members.insert(name); +#ifdef TOOLS_ENABLED + + p_script->member_lines[name]=p_class->variables[i].line; +#endif + + } for(int i=0;i<p_class->constant_expressions.size();i++) { @@ -1643,6 +1695,11 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa p_script->constants.insert(name,constant->value); //p_script->constants[constant->value].make_const(); +#ifdef TOOLS_ENABLED + + p_script->member_lines[name]=p_class->constant_expressions[i].expression->line; +#endif + } for(int i=0;i<p_class->_signals.size();i++) { @@ -1691,6 +1748,10 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa if (err) return err; +#ifdef TOOLS_ENABLED + + p_script->member_lines[name]=p_class->subclasses[i]->line; +#endif p_script->constants.insert(name,subclass); //once parsed, goes to the list of constants p_script->subclasses.insert(name,subclass); diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index 5b74dab889..c3e59836a2 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -47,16 +47,14 @@ void GDScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const { Ref<Script> GDScriptLanguage::get_template(const String& p_class_name, const String& p_base_class_name) const { String _template = String()+ - "\nextends %BASE%\n\n"+ - "# member variables here, example:\n"+ - "# var a=2\n"+ - "# var b=\"textvar\"\n\n"+ + "extends %BASE%\n\n"+ + "# class member variables go here, for example:\n"+ + "# var a = 2\n"+ + "# var b = \"textvar\"\n\n"+ "func _ready():\n"+ "\t# Called every time the node is added to the scene.\n"+ "\t# Initialization here\n"+ - "\tpass\n"+ - "\n"+ - "\n"; + "\tpass\n"; _template = _template.replace("%BASE%",p_base_class_name); @@ -353,6 +351,7 @@ struct GDCompletionIdentifier { Ref<GDScript> script; Variant::Type type; Variant value; //im case there is a value, also return it + }; @@ -937,6 +936,7 @@ static bool _guess_expression_type(GDCompletionContext& context,const GDParser:: return false; } + static bool _guess_identifier_type_in_block(GDCompletionContext& context,int p_line,const StringName& p_identifier,GDCompletionIdentifier &r_type) { @@ -2096,7 +2096,7 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base GDParser p; - Error err = p.parse(p_code,p_base_path,false,"",true); + p.parse(p_code,p_base_path,false,"",true); bool isfunction=false; Set<String> options; @@ -2143,7 +2143,18 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base GDCompletionIdentifier t; if (_guess_expression_type(context,static_cast<const GDParser::OperatorNode *>(node)->arguments[0],p.get_completion_line(),t)) { - if (t.type==Variant::OBJECT && t.obj_type!=StringName()) { + if (t.type==Variant::OBJECT && t.obj_type=="GDNativeClass") { + //native enum + Ref<GDNativeClass> gdn = t.value; + if (gdn.is_valid()) { + StringName cn = gdn->get_name(); + List<String> cnames; + ObjectTypeDB::get_integer_constant_list(cn,&cnames); + for (List<String>::Element *E=cnames.front();E;E=E->next()) { + options.insert(E->get()); + } + } + } else if (t.type==Variant::OBJECT && t.obj_type!=StringName()) { Ref<GDScript> on_script; @@ -2513,3 +2524,442 @@ void GDScriptLanguage::auto_indent_code(String& p_code,int p_from_line,int p_to_ } } + +#ifdef TOOLS_ENABLED + +Error GDScriptLanguage::lookup_code(const String& p_code, const String& p_symbol,const String& p_base_path, Object*p_owner,LookupResult& r_result) { + + + //before parsing, try the usual stuff + if (ObjectTypeDB::type_exists(p_symbol)) { + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS; + r_result.class_name=p_symbol; + return OK; + } + + for(int i=0;i<Variant::VARIANT_MAX;i++) { + Variant::Type t = Variant::Type(i); + if (Variant::get_type_name(t)==p_symbol) { + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS; + r_result.class_name=Variant::get_type_name(t); + return OK; + } + } + + for(int i=0;i<GDFunctions::FUNC_MAX;i++) { + if (GDFunctions::get_func_name(GDFunctions::Function(i))==p_symbol) { + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_METHOD; + r_result.class_name="@GDScript"; + r_result.class_member=p_symbol; + return OK; + } + } + + GDParser p; + p.parse(p_code,p_base_path,false,"",true); + + if (p.get_completion_type()==GDParser::COMPLETION_NONE) + return ERR_CANT_RESOLVE; + + GDCompletionContext context; + + context._class=p.get_completion_class(); + context.block=p.get_completion_block(); + context.function=p.get_completion_function(); + context.base=p_owner; + context.base_path=p_base_path; + bool isfunction=false; + + switch(p.get_completion_type()) { + + case GDParser::COMPLETION_NONE: { + } break; + case GDParser::COMPLETION_BUILT_IN_TYPE_CONSTANT: { + + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT; + r_result.class_name=Variant::get_type_name(p.get_completion_built_in_constant()); + r_result.class_member=p_symbol; + return OK; + + } break; + case GDParser::COMPLETION_FUNCTION: { + + + if (context._class && context._class->functions.size()) { + for(int i=0;i<context._class->functions.size();i++) { + if (context._class->functions[i]->name==p_symbol) { + r_result.type=ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION; + r_result.location=context._class->functions[i]->line; + return OK; + } + } + } + + Ref<GDScript> parent = _get_parent_class(context); + while(parent.is_valid()) { + int line = parent->get_member_line(p_symbol); + if (line>=0) { + r_result.type=ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION; + r_result.location=line; + r_result.script=parent; + return OK; + + } + + parent=parent->get_base(); + } + + GDCompletionIdentifier identifier = _get_native_class(context); + print_line("identifier: "+String(identifier.obj_type)); + + if (ObjectTypeDB::has_method(identifier.obj_type,p_symbol)) { + + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_METHOD; + r_result.class_name=identifier.obj_type; + r_result.class_member=p_symbol; + return OK; + } + + + } break; + case GDParser::COMPLETION_IDENTIFIER: { + + //check if a function + if (p.get_completion_identifier_is_function()) { + if (context._class && context._class->functions.size()) { + for(int i=0;i<context._class->functions.size();i++) { + if (context._class->functions[i]->name==p_symbol) { + r_result.type=ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION; + r_result.location=context._class->functions[i]->line; + return OK; + } + } + } + + Ref<GDScript> parent = _get_parent_class(context); + while(parent.is_valid()) { + int line = parent->get_member_line(p_symbol); + if (line>=0) { + r_result.type=ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION; + r_result.location=line; + r_result.script=parent; + return OK; + + } + + parent=parent->get_base(); + } + + GDCompletionIdentifier identifier = _get_native_class(context); + + + if (ObjectTypeDB::has_method(identifier.obj_type,p_symbol)) { + + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_METHOD; + r_result.class_name=identifier.obj_type; + r_result.class_member=p_symbol; + return OK; + } + } else { + + + const GDParser::BlockNode *block=context.block; + //search in blocks going up (local var?) + while(block) { + + + + for (int i=0;i<block->statements.size();i++) { + + if (block->statements[i]->line>p.get_completion_line()) + continue; + + + if (block->statements[i]->type==GDParser::BlockNode::TYPE_LOCAL_VAR) { + + const GDParser::LocalVarNode *lv=static_cast<const GDParser::LocalVarNode *>(block->statements[i]); + + if (lv->assign && lv->name==p_symbol) { + + r_result.type=ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION; + r_result.location=block->statements[i]->line; + return OK; + } + } + } + block=block->parent_block; + } + + //guess from function arguments + if (context.function && context.function->name!=StringName()) { + + for(int i=0;i<context.function->arguments.size();i++) { + + if (context.function->arguments[i]==p_symbol) { + r_result.type=ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION; + r_result.location=context.function->line; + return OK; + } + + } + } + + //guess in class constants + + for(int i=0;i<context._class->constant_expressions.size();i++) { + + if (context._class->constant_expressions[i].identifier==p_symbol) { + r_result.type=ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION; + r_result.location=context._class->constant_expressions[i].expression->line; + return OK; + } + } + + //guess in class variables + if (!(context.function && context.function->_static)) { + + for(int i=0;i<context._class->variables.size();i++) { + + if (context._class->variables[i].identifier==p_symbol) { + + r_result.type=ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION; + r_result.location=context._class->variables[i].line; + return OK; + } + } + } + + //guess in autoloads as singletons + List<PropertyInfo> props; + Globals::get_singleton()->get_property_list(&props); + + for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) { + + String s = E->get().name; + if (!s.begins_with("autoload/")) + continue; + String name = s.get_slice("/",1); + if (name==String(p_symbol)) { + + String path = Globals::get_singleton()->get(s); + if (path.begins_with("*")) { + String script =path.substr(1,path.length()); + + if (!script.ends_with(".gd")) { + //not a script, try find the script anyway, + //may have some success + script=script.basename()+".gd"; + } + + if (FileAccess::exists(script)) { + + r_result.type=ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION; + r_result.location=0; + r_result.script=ResourceLoader::load(script); + return OK; + } + } + } + } + + //global + for(Map<StringName,int>::Element *E=GDScriptLanguage::get_singleton()->get_global_map().front();E;E=E->next()) { + if (E->key()==p_symbol) { + + Variant value = GDScriptLanguage::get_singleton()->get_global_array()[E->get()]; + if (value.get_type()==Variant::OBJECT) { + Object *obj = value; + if (obj) { + + if (obj->cast_to<GDNativeClass>()) { + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS; + r_result.class_name=obj->cast_to<GDNativeClass>()->get_name(); + + } else { + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS; + r_result.class_name=obj->get_type(); + } + return OK; + } + } else { + + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT; + r_result.class_name="@Global Scope"; + r_result.class_member=p_symbol; + return OK; + } + } + + } +#if 0 + GDCompletionIdentifier identifier; + if (_guess_identifier_type(context,p.get_completion_line(),p_symbol,identifier)) { + + print_line("var type: "+Variant::get_type_name(identifier.type)); + if (identifier.script.is_valid()) { + print_line("var script: "+identifier.script->get_path()); + } + print_line("obj type: "+String(identifier.obj_type)); + print_line("value: "+String(identifier.value)); + } +#endif + } + + } break; + case GDParser::COMPLETION_PARENT_FUNCTION: { + + } break; + case GDParser::COMPLETION_METHOD: + isfunction=true; + case GDParser::COMPLETION_INDEX: { + + const GDParser::Node *node = p.get_completion_node(); + if (node->type!=GDParser::Node::TYPE_OPERATOR) + break; + + + + + GDCompletionIdentifier t; + if (_guess_expression_type(context,static_cast<const GDParser::OperatorNode *>(node)->arguments[0],p.get_completion_line(),t)) { + + if (t.type==Variant::OBJECT && t.obj_type=="GDNativeClass") { + //native enum + Ref<GDNativeClass> gdn = t.value; + if (gdn.is_valid()) { + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT; + r_result.class_name=gdn->get_name();; + r_result.class_member=p_symbol; + return OK; + + } + } else if (t.type==Variant::OBJECT && t.obj_type!=StringName()) { + + Ref<GDScript> on_script; + + if (t.value.get_type()) { + Object *obj=t.value; + + + if (obj) { + + + on_script=obj->get_script(); + + if (on_script.is_valid()) { + int loc = on_script->get_member_line(p_symbol); + if (loc>=0) { + r_result.script=on_script; + r_result.type=ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION; + r_result.location=loc; + return OK; + } + } + } + } + + if (ObjectTypeDB::has_method(t.obj_type,p_symbol)) { + + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_METHOD; + r_result.class_name=t.obj_type; + r_result.class_member=p_symbol; + return OK; + + } + + bool success; + ObjectTypeDB::get_integer_constant(t.obj_type,p_symbol,&success); + if (success) { + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT; + r_result.class_name=t.obj_type; + r_result.class_member=p_symbol; + return OK; + } + + ObjectTypeDB::get_property_type(t.obj_type,p_symbol,&success); + + if (success) { + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_PROPERTY; + r_result.class_name=t.obj_type; + r_result.class_member=p_symbol; + return OK; + } + + + } else { + + Variant::CallError ce; + Variant v = Variant::construct(t.type,NULL,0,ce); + + bool valid; + v.get_numeric_constant_value(t.type,p_symbol,&valid); + if (valid) { + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT; + r_result.class_name=Variant::get_type_name(t.type); + r_result.class_member=p_symbol; + return OK; + } + + //todo check all inputevent types for property + + v.get(p_symbol,&valid); + + if (valid) { + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_PROPERTY; + r_result.class_name=Variant::get_type_name(t.type); + r_result.class_member=p_symbol; + return OK; + } + + if (v.has_method(p_symbol)) { + + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_METHOD; + r_result.class_name=Variant::get_type_name(t.type); + r_result.class_member=p_symbol; + return OK; + + } + + + } + } + + + } break; + case GDParser::COMPLETION_CALL_ARGUMENTS: { + + return ERR_CANT_RESOLVE; + } break; + case GDParser::COMPLETION_VIRTUAL_FUNC: { + + GDCompletionIdentifier cid = _get_native_class(context); + + if (cid.obj_type!=StringName()) { + List<MethodInfo> vm; + ObjectTypeDB::get_virtual_methods(cid.obj_type,&vm); + for(List<MethodInfo>::Element *E=vm.front();E;E=E->next()) { + + if (p_symbol==E->get().name) { + + r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_METHOD; + r_result.class_name=cid.obj_type; + r_result.class_member=p_symbol; + return OK; + + } + } + } + } break; + case GDParser::COMPLETION_YIELD: { + + return ERR_CANT_RESOLVE; + + } break; + + } + + + return ERR_CANT_RESOLVE; +} + +#endif diff --git a/modules/gdscript/gd_function.cpp b/modules/gdscript/gd_function.cpp index b2cc6341c1..094e21bb4f 100644 --- a/modules/gdscript/gd_function.cpp +++ b/modules/gdscript/gd_function.cpp @@ -1437,7 +1437,7 @@ void GDFunctionState::_bind_methods() { ObjectTypeDB::bind_method(_MD("resume:Variant","arg"),&GDFunctionState::resume,DEFVAL(Variant())); ObjectTypeDB::bind_method(_MD("is_valid"),&GDFunctionState::is_valid); - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"_signal_callback",&GDFunctionState::_signal_callback,MethodInfo("_signal_callback")); + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"_signal_callback",&GDFunctionState::_signal_callback,MethodInfo("_signal_callback")); } diff --git a/modules/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp index a565e866d0..d3f7dcd35f 100644 --- a/modules/gdscript/gd_functions.cpp +++ b/modules/gdscript/gd_functions.cpp @@ -88,6 +88,7 @@ const char *GDFunctions::get_func_name(Function p_func) { "convert", "typeof", "type_exists", + "char", "str", "print", "printt", @@ -538,6 +539,12 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va r_ret = ObjectTypeDB::type_exists(*p_args[0]); } break; + case TEXT_CHAR: { + VALIDATE_ARG_COUNT(1); + VALIDATE_ARG_NUM(0); + CharType result[2] = {*p_args[0], 0}; + r_ret=String(result); + } break; case TEXT_STR: { String str; @@ -840,8 +847,9 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; r_ret=Variant(); + } else { + r_ret=ResourceLoader::load(*p_args[0]); } - r_ret=ResourceLoader::load(*p_args[0]); } break; case INST2DICT: { @@ -1133,6 +1141,7 @@ bool GDFunctions::is_deterministic(Function p_func) { case TYPE_CONVERT: case TYPE_OF: case TYPE_EXISTS: + case TEXT_CHAR: case TEXT_STR: case COLOR8: // enable for debug only, otherwise not desirable - case GEN_RANGE: @@ -1403,6 +1412,13 @@ MethodInfo GDFunctions::get_info(Function p_func) { return mi; } break; + case TEXT_CHAR: { + + MethodInfo mi("char",PropertyInfo(Variant::INT,"ascii")); + mi.return_val.type=Variant::STRING; + return mi; + + } break; case TEXT_STR: { MethodInfo mi("str",PropertyInfo(Variant::NIL,"what"),PropertyInfo(Variant::NIL,"...")); diff --git a/modules/gdscript/gd_functions.h b/modules/gdscript/gd_functions.h index c78956fe20..f444bb3b5b 100644 --- a/modules/gdscript/gd_functions.h +++ b/modules/gdscript/gd_functions.h @@ -82,6 +82,7 @@ public: TYPE_CONVERT, TYPE_OF, TYPE_EXISTS, + TEXT_CHAR, TEXT_STR, TEXT_PRINT, TEXT_PRINT_TABBED, diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index e5a8dc0152..434f918355 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -121,6 +121,7 @@ bool GDParser::_parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_stat tokenizer->advance(); } else { + parenthesis ++; int argidx=0; while(true) { @@ -165,6 +166,7 @@ bool GDParser::_parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_stat } } + parenthesis --; } return true; @@ -203,6 +205,7 @@ bool GDParser::_get_completable_identifier(CompletionType p_type,StringName& ide completion_line=tokenizer->get_token_line(); completion_block=current_block; completion_found=true; + completion_ident_is_call=false; tokenizer->advance(); if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) { @@ -210,6 +213,9 @@ bool GDParser::_get_completable_identifier(CompletionType p_type,StringName& ide tokenizer->advance(); } + if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_OPEN) { + completion_ident_is_call=true; + } return true; } @@ -360,18 +366,23 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ OperatorNode *yield = alloc_node<OperatorNode>(); yield->op=OperatorNode::OP_YIELD; + while (tokenizer->get_token()==GDTokenizer::TK_NEWLINE) { + tokenizer->advance(); + } + if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) { expr=yield; tokenizer->advance(); } else { + parenthesis ++; + Node *object = _parse_and_reduce_expression(p_parent,p_static); if (!object) return NULL; yield->arguments.push_back(object); if (tokenizer->get_token()!=GDTokenizer::TK_COMMA) { - _set_error("Expected ',' after first argument of 'yield'"); return NULL; } @@ -399,11 +410,12 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ yield->arguments.push_back(signal); if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')' after second argument of 'yield'"); return NULL; } + parenthesis --; + tokenizer->advance(); expr=yield; @@ -936,6 +948,8 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ case GDTokenizer::TK_OP_BIT_OR: op=OperatorNode::OP_BIT_OR ; break; case GDTokenizer::TK_OP_BIT_XOR: op=OperatorNode::OP_BIT_XOR ; break; case GDTokenizer::TK_PR_EXTENDS: op=OperatorNode::OP_EXTENDS; break; + case GDTokenizer::TK_CF_IF: op=OperatorNode::OP_TERNARY_IF; break; + case GDTokenizer::TK_CF_ELSE: op=OperatorNode::OP_TERNARY_ELSE; break; default: valid=false; break; } @@ -958,6 +972,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ int next_op=-1; int min_priority=0xFFFFF; bool is_unary=false; + bool is_ternary=false; for(int i=0;i<expression.size();i++) { @@ -971,6 +986,8 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ int priority; bool unary=false; + bool ternary=false; + bool error=false; switch(expression[i].op) { @@ -1001,25 +1018,27 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ case OperatorNode::OP_EQUAL: priority=8; break; case OperatorNode::OP_NOT_EQUAL: priority=8; break; + case OperatorNode::OP_IN: priority=10; break; - + case OperatorNode::OP_NOT: priority=11; unary=true; break; case OperatorNode::OP_AND: priority=12; break; case OperatorNode::OP_OR: priority=13; break; - - // ?: = 10 - - case OperatorNode::OP_ASSIGN: priority=14; break; - case OperatorNode::OP_ASSIGN_ADD: priority=14; break; - case OperatorNode::OP_ASSIGN_SUB: priority=14; break; - case OperatorNode::OP_ASSIGN_MUL: priority=14; break; - case OperatorNode::OP_ASSIGN_DIV: priority=14; break; - case OperatorNode::OP_ASSIGN_MOD: priority=14; break; - case OperatorNode::OP_ASSIGN_SHIFT_LEFT: priority=14; break; - case OperatorNode::OP_ASSIGN_SHIFT_RIGHT: priority=14; break; - case OperatorNode::OP_ASSIGN_BIT_AND: priority=14; break; - case OperatorNode::OP_ASSIGN_BIT_OR: priority=14; break; - case OperatorNode::OP_ASSIGN_BIT_XOR: priority=14; break; + + case OperatorNode::OP_TERNARY_IF: priority=14; ternary=true; break; + case OperatorNode::OP_TERNARY_ELSE: priority=14; error=true; break; // Errors out when found without IF (since IF would consume it) + + case OperatorNode::OP_ASSIGN: priority=15; break; + case OperatorNode::OP_ASSIGN_ADD: priority=15; break; + case OperatorNode::OP_ASSIGN_SUB: priority=15; break; + case OperatorNode::OP_ASSIGN_MUL: priority=15; break; + case OperatorNode::OP_ASSIGN_DIV: priority=15; break; + case OperatorNode::OP_ASSIGN_MOD: priority=15; break; + case OperatorNode::OP_ASSIGN_SHIFT_LEFT: priority=15; break; + case OperatorNode::OP_ASSIGN_SHIFT_RIGHT: priority=15; break; + case OperatorNode::OP_ASSIGN_BIT_AND: priority=15; break; + case OperatorNode::OP_ASSIGN_BIT_OR: priority=15; break; + case OperatorNode::OP_ASSIGN_BIT_XOR: priority=15; break; default: { @@ -1030,11 +1049,16 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ } if (priority<min_priority) { + if(error) { + _set_error("Unexpected operator"); + return NULL; + } // < is used for left to right (default) // <= is used for right to left next_op=i; min_priority=priority; is_unary=unary; + is_ternary=ternary; } } @@ -1075,6 +1099,62 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ } + } else if(is_ternary) { + if (next_op <1 || next_op>=(expression.size()-1)) { + _set_error("Parser bug.."); + ERR_FAIL_V(NULL); + } + + if(next_op>=(expression.size()-2) || expression[next_op+2].op != OperatorNode::OP_TERNARY_ELSE) { + _set_error("Expected else after ternary if."); + ERR_FAIL_V(NULL); + } + if(next_op>=(expression.size()-3)) { + _set_error("Expected value after ternary else."); + ERR_FAIL_V(NULL); + } + + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=expression[next_op].op; + op->line=op_line; //line might have been changed from a \n + + if (expression[next_op-1].is_op) { + + _set_error("Parser bug.."); + ERR_FAIL_V(NULL); + } + + if (expression[next_op+1].is_op) { + // this is not invalid and can really appear + // but it becomes invalid anyway because no binary op + // can be followed by an unary op in a valid combination, + // due to how precedence works, unaries will always dissapear first + + _set_error("Unexpected two consecutive operators after ternary if."); + return NULL; + } + + if (expression[next_op+3].is_op) { + // this is not invalid and can really appear + // but it becomes invalid anyway because no binary op + // can be followed by an unary op in a valid combination, + // due to how precedence works, unaries will always dissapear first + + _set_error("Unexpected two consecutive operators after ternary else."); + return NULL; + } + + + op->arguments.push_back(expression[next_op+1].node); //next expression goes as first + op->arguments.push_back(expression[next_op-1].node); //left expression goes as when-true + op->arguments.push_back(expression[next_op+3].node); //expression after next goes as when-false + + //replace all 3 nodes by this operator and make it an expression + expression[next_op-1].node=op; + expression.remove(next_op); + expression.remove(next_op); + expression.remove(next_op); + expression.remove(next_op); } else { if (next_op <1 || next_op>=(expression.size()-1)) { @@ -1633,6 +1713,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { case GDTokenizer::TK_CF_IF: { tokenizer->advance(); + Node *condition = _parse_and_reduce_expression(p_block,p_static); if (!condition) { if (_recover_from_completion()) { @@ -2233,6 +2314,11 @@ void GDParser::_parse_class(ClassNode *p_class) { bool defaulting=false; while(true) { + if (tokenizer->get_token()==GDTokenizer::TK_NEWLINE) { + tokenizer->advance(); + continue; + } + if (tokenizer->get_token()==GDTokenizer::TK_PR_VAR) { tokenizer->advance(); //var before the identifier is allowed @@ -2285,6 +2371,10 @@ void GDParser::_parse_class(ClassNode *p_class) { default_values.push_back(on); } + while (tokenizer->get_token()==GDTokenizer::TK_NEWLINE) { + tokenizer->advance(); + } + if (tokenizer->get_token()==GDTokenizer::TK_COMMA) { tokenizer->advance(); continue; @@ -2326,6 +2416,7 @@ void GDParser::_parse_class(ClassNode *p_class) { if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { //has arguments + parenthesis ++; while(true) { Node *arg = _parse_and_reduce_expression(p_class,_static); @@ -2343,6 +2434,7 @@ void GDParser::_parse_class(ClassNode *p_class) { break; } + parenthesis --; } tokenizer->advance(); @@ -2406,6 +2498,10 @@ void GDParser::_parse_class(ClassNode *p_class) { if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_OPEN) { tokenizer->advance(); while(true) { + if (tokenizer->get_token()==GDTokenizer::TK_NEWLINE) { + tokenizer->advance(); + continue; + } if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) { @@ -2421,6 +2517,10 @@ void GDParser::_parse_class(ClassNode *p_class) { sig.arguments.push_back(tokenizer->get_token_identifier()); tokenizer->advance(); + while (tokenizer->get_token()==GDTokenizer::TK_NEWLINE) { + tokenizer->advance(); + } + if (tokenizer->get_token()==GDTokenizer::TK_COMMA) { tokenizer->advance(); } else if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { @@ -3029,6 +3129,16 @@ void GDParser::_parse_class(ClassNode *p_class) { } member._export.type=cn->value.get_type(); member._export.usage|=PROPERTY_USAGE_SCRIPT_VARIABLE; + if (cn->value.get_type()==Variant::OBJECT) { + Object *obj = cn->value; + Resource *res = obj->cast_to<Resource>(); + if(res==NULL) { + _set_error("Exported constant not a type or resource."); + return; + } + member._export.hint=PROPERTY_HINT_RESOURCE_TYPE; + member._export.hint_string=res->get_type(); + } } } #ifdef TOOLS_ENABLED @@ -3157,6 +3267,114 @@ void GDParser::_parse_class(ClassNode *p_class) { } } break; + case GDTokenizer::TK_PR_ENUM: { + //mutiple constant declarations.. + + int last_assign = -1; // Incremented by 1 right before the assingment. + String enum_name; + Dictionary enum_dict; + + tokenizer->advance(); + if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) { + enum_name=tokenizer->get_token_identifier(); + tokenizer->advance(); + } + if (tokenizer->get_token()!=GDTokenizer::TK_CURLY_BRACKET_OPEN) { + _set_error("Expected '{' in enum declaration"); + return; + } + tokenizer->advance(); + + while(true) { + if(tokenizer->get_token()==GDTokenizer::TK_NEWLINE) { + + tokenizer->advance(); // Ignore newlines + } else if (tokenizer->get_token()==GDTokenizer::TK_CURLY_BRACKET_CLOSE) { + + tokenizer->advance(); + break; // End of enum + } else if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { + + if(tokenizer->get_token()==GDTokenizer::TK_EOF) { + _set_error("Unexpected end of file."); + } else { + _set_error(String("Unexpected ") + GDTokenizer::get_token_name(tokenizer->get_token()) + ", expected identifier"); + } + + return; + } else { // tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER + ClassNode::Constant constant; + + constant.identifier=tokenizer->get_token_identifier(); + + tokenizer->advance(); + + if (tokenizer->get_token()==GDTokenizer::TK_OP_ASSIGN) { + tokenizer->advance(); + + Node *subexpr=NULL; + + subexpr = _parse_and_reduce_expression(p_class,true,true); + if (!subexpr) { + if (_recover_from_completion()) { + break; + } + return; + } + + if (subexpr->type!=Node::TYPE_CONSTANT) { + _set_error("Expected constant expression"); + } + + const ConstantNode *subexpr_const = static_cast<const ConstantNode*>(subexpr); + + if(subexpr_const->value.get_type() != Variant::INT) { + _set_error("Expected an int value for enum"); + } + + last_assign = subexpr_const->value; + + constant.expression=subexpr; + + } else { + last_assign = last_assign + 1; + ConstantNode *cn = alloc_node<ConstantNode>(); + cn->value = last_assign; + constant.expression = cn; + } + + if(tokenizer->get_token()==GDTokenizer::TK_COMMA) { + tokenizer->advance(); + } + + if(enum_name != "") { + const ConstantNode *cn = static_cast<const ConstantNode*>(constant.expression); + enum_dict[constant.identifier] = cn->value; + } + + p_class->constant_expressions.push_back(constant); + } + + } + + if(enum_name != "") { + ClassNode::Constant enum_constant; + enum_constant.identifier=enum_name; + ConstantNode *cn = alloc_node<ConstantNode>(); + cn->value = enum_dict; + enum_constant.expression=cn; + p_class->constant_expressions.push_back(enum_constant); + } + + if (!_end_statement()) { + _set_error("Expected end of statement (enum)"); + return; + } + + + + + } break; default: { @@ -3376,6 +3594,11 @@ int GDParser::get_completion_argument_index() { return completion_argument; } +int GDParser::get_completion_identifier_is_function() { + + return completion_ident_is_call; +} + GDParser::GDParser() { head=NULL; diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h index 9e6f6e6765..75653e0916 100644 --- a/modules/gdscript/gd_parser.h +++ b/modules/gdscript/gd_parser.h @@ -247,6 +247,9 @@ public: OP_BIT_AND, OP_BIT_OR, OP_BIT_XOR, + //ternary operators + OP_TERNARY_IF, + OP_TERNARY_ELSE, }; Operator op; @@ -429,6 +432,7 @@ private: int completion_line; int completion_argument; bool completion_found; + bool completion_ident_is_call; PropertyInfo current_export; @@ -475,7 +479,7 @@ public: BlockNode *get_completion_block(); FunctionNode *get_completion_function(); int get_completion_argument_index(); - + int get_completion_identifier_is_function(); void clear(); GDParser(); diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp index b97a0fcbb6..0ea10950df 100644 --- a/modules/gdscript/gd_script.cpp +++ b/modules/gdscript/gd_script.cpp @@ -751,7 +751,7 @@ void GDScript::_get_property_list(List<PropertyInfo> *p_properties) const { void GDScript::_bind_methods() { - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"new",&GDScript::_new,MethodInfo(Variant::OBJECT,"new")); + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"new",&GDScript::_new,MethodInfo(Variant::OBJECT,"new")); ObjectTypeDB::bind_method(_MD("get_as_byte_code"),&GDScript::get_as_byte_code); diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h index 0c3e1eb614..051e80634f 100644 --- a/modules/gdscript/gd_script.h +++ b/modules/gdscript/gd_script.h @@ -65,6 +65,7 @@ class GDScript : public Script { StringName setter; StringName getter; ScriptInstance::RPCMode rpc_mode; + }; friend class GDInstance; @@ -86,8 +87,11 @@ friend class GDScriptLanguage; Map<StringName,Ref<GDScript> > subclasses; Map<StringName,Vector<StringName> > _signals; + #ifdef TOOLS_ENABLED + Map<StringName,int> member_lines; + Map<StringName,Variant> member_default_values; List<PropertyInfo> members_cache; @@ -193,6 +197,16 @@ public: virtual ScriptLanguage *get_language() const; + virtual int get_member_line(const StringName& p_member) const { +#ifdef TOOLS_ENABLED + if (member_lines.has(p_member)) + return member_lines[p_member]; + else +#endif + return -1; + + } + GDScript(); ~GDScript(); }; @@ -394,6 +408,9 @@ public: virtual int find_function(const String& p_function,const String& p_code) const; virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const; virtual Error complete_code(const String& p_code, const String& p_base_path, Object*p_owner,List<String>* r_options,String& r_call_hint); +#ifdef TOOLS_ENABLED + virtual Error lookup_code(const String& p_code, const String& p_symbol, const String& p_base_path, Object*p_owner, LookupResult& r_result); +#endif virtual void auto_indent_code(String& p_code,int p_from_line,int p_to_line) const; virtual void add_global_constant(const StringName& p_variable,const Variant& p_value); diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp index 47e740b227..39c4530d96 100644 --- a/modules/gdscript/gd_tokenizer.cpp +++ b/modules/gdscript/gd_tokenizer.cpp @@ -95,6 +95,7 @@ const char* GDTokenizer::token_names[TK_MAX]={ "setget", "const", "var", +"enum", "preload", "assert", "yield", @@ -281,7 +282,7 @@ void GDTokenizerText::_advance() { case '\n': { line++; INCPOS(1); - column=0; + column=1; int i=0; while(GETCHAR(i)==' ' || GETCHAR(i)=='\t') { i++; @@ -302,7 +303,7 @@ void GDTokenizerText::_advance() { } } INCPOS(1); - column=0; + column=1; line++; int i=0; while(GETCHAR(i)==' ' || GETCHAR(i)=='\t') { @@ -334,7 +335,7 @@ void GDTokenizerText::_advance() { break; } else if (_code[pos]=='\n') { new_line++; - new_col=0; + new_col=1; } else { new_col++; } @@ -357,7 +358,7 @@ void GDTokenizerText::_advance() { } } INCPOS(1); - column=0; + column=1; line++; continue; @@ -653,7 +654,7 @@ void GDTokenizerText::_advance() { } else { if (CharType(GETCHAR(i))=='\n') { line++; - column=0; + column=1; } str+=CharType(GETCHAR(i)); @@ -874,6 +875,7 @@ void GDTokenizerText::_advance() { {TK_PR_SLAVE,"slave"}, {TK_PR_SYNC,"sync"}, {TK_PR_CONST,"const"}, + {TK_PR_ENUM,"enum"}, //controlflow {TK_CF_IF,"if"}, {TK_CF_ELIF,"elif"}, @@ -941,7 +943,7 @@ void GDTokenizerText::set_code(const String& p_code) { } code_pos=0; line=1; //it is stand-ar-ized that lines begin in 1 in code.. - column=0; + column=1; //the same holds for columns tk_rb_pos=0; error_flag=false; last_error=""; @@ -1330,7 +1332,7 @@ StringName GDTokenizerBuffer::get_token_identifier(int p_offset) const{ ERR_FAIL_INDEX_V(offset,tokens.size(),StringName()); uint32_t identifier = tokens[offset]>>TOKEN_BITS; - ERR_FAIL_INDEX_V(identifier,identifiers.size(),StringName()); + ERR_FAIL_INDEX_V(identifier,(uint32_t)identifiers.size(),StringName()); return identifiers[identifier]; } @@ -1389,7 +1391,7 @@ const Variant& GDTokenizerBuffer::get_token_constant(int p_offset) const{ int offset = token+p_offset; ERR_FAIL_INDEX_V(offset,tokens.size(),nil); uint32_t constant = tokens[offset]>>TOKEN_BITS; - ERR_FAIL_INDEX_V(constant,constants.size(),nil); + ERR_FAIL_INDEX_V(constant,(uint32_t)constants.size(),nil); return constants[constant]; } diff --git a/modules/gdscript/gd_tokenizer.h b/modules/gdscript/gd_tokenizer.h index 1815f82894..b91229ab1e 100644 --- a/modules/gdscript/gd_tokenizer.h +++ b/modules/gdscript/gd_tokenizer.h @@ -102,6 +102,7 @@ public: TK_PR_SETGET, TK_PR_CONST, TK_PR_VAR, + TK_PR_ENUM, TK_PR_PRELOAD, TK_PR_ASSERT, TK_PR_YIELD, diff --git a/modules/gridmap/SCsub b/modules/gridmap/SCsub index 211a043468..0882406761 100644 --- a/modules/gridmap/SCsub +++ b/modules/gridmap/SCsub @@ -1,3 +1,7 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.modules_sources,"*.cpp") +env.add_source_files(env.modules_sources, "*.cpp") + +Export('env') diff --git a/modules/ik/SCsub b/modules/ik/SCsub index 211a043468..0882406761 100644 --- a/modules/ik/SCsub +++ b/modules/ik/SCsub @@ -1,3 +1,7 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.modules_sources,"*.cpp") +env.add_source_files(env.modules_sources, "*.cpp") + +Export('env') diff --git a/modules/jpg/SCsub b/modules/jpg/SCsub new file mode 100644 index 0000000000..28fb81895d --- /dev/null +++ b/modules/jpg/SCsub @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_jpg = env_modules.Clone() + +# Thirdparty source files +# Not unbundled for now as they are not commonly available as shared library +thirdparty_dir = "#thirdparty/jpeg-compressor/" +thirdparty_sources = [ + "jpgd.cpp", +] +thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + +env_jpg.add_source_files(env.modules_sources, thirdparty_sources) +env_jpg.Append(CPPPATH = [thirdparty_dir]) + +# Godot's own source files +env_jpg.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/jpg/config.py b/modules/jpg/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/jpg/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/modules/jpg/image_loader_jpegd.cpp b/modules/jpg/image_loader_jpegd.cpp new file mode 100644 index 0000000000..03c3b19fc0 --- /dev/null +++ b/modules/jpg/image_loader_jpegd.cpp @@ -0,0 +1,144 @@ +/*************************************************************************/ +/* image_loader_jpegd.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "image_loader_jpegd.h" + +#include "print_string.h" +#include "os/os.h" + +#include <jpgd.h> +#include <string.h> + + +Error jpeg_load_image_from_buffer(Image *p_image,const uint8_t* p_buffer, int p_buffer_len) { + + jpgd::jpeg_decoder_mem_stream mem_stream(p_buffer,p_buffer_len); + + jpgd::jpeg_decoder decoder(&mem_stream); + + if (decoder.get_error_code() != jpgd::JPGD_SUCCESS) { + return ERR_CANT_OPEN; + } + + const int image_width = decoder.get_width(); + const int image_height = decoder.get_height(); + int comps = decoder.get_num_components(); + if (comps==3) + comps=4; //weird + + if (decoder.begin_decoding() != jpgd::JPGD_SUCCESS) + return ERR_FILE_CORRUPT; + + const int dst_bpl = image_width * comps; + + DVector<uint8_t> data; + + data.resize(dst_bpl * image_height); + + DVector<uint8_t>::Write dw = data.write(); + + jpgd::uint8 *pImage_data = (jpgd::uint8*)dw.ptr(); + + for (int y = 0; y < image_height; y++) + { + const jpgd::uint8* pScan_line; + jpgd::uint scan_line_len; + if (decoder.decode((const void**)&pScan_line, &scan_line_len) != jpgd::JPGD_SUCCESS) + { + return ERR_FILE_CORRUPT; + } + + jpgd::uint8 *pDst = pImage_data + y * dst_bpl; + memcpy(pDst, pScan_line, dst_bpl); + + + } + + + //all good + + Image::Format fmt; + if (comps==1) + fmt=Image::FORMAT_GRAYSCALE; + else + fmt=Image::FORMAT_RGBA; + + dw = DVector<uint8_t>::Write(); + p_image->create(image_width,image_height,0,fmt,data); + + return OK; + +} + + +Error ImageLoaderJPG::load_image(Image *p_image,FileAccess *f) { + + + DVector<uint8_t> src_image; + int src_image_len = f->get_len(); + ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); + src_image.resize(src_image_len); + + DVector<uint8_t>::Write w = src_image.write(); + + f->get_buffer(&w[0],src_image_len); + + f->close(); + + + Error err = jpeg_load_image_from_buffer(p_image,w.ptr(),src_image_len); + + w = DVector<uint8_t>::Write(); + + return err; + +} + +void ImageLoaderJPG::get_recognized_extensions(List<String> *p_extensions) const { + + p_extensions->push_back("jpg"); + p_extensions->push_back("jpeg"); +} + + +static Image _jpegd_mem_loader_func(const uint8_t* p_png,int p_size) { + + Image img; + Error err = jpeg_load_image_from_buffer(&img,p_png,p_size); + if (err) + ERR_PRINT("Couldn't initialize ImageLoaderJPG with the given resource."); + + return img; +} + +ImageLoaderJPG::ImageLoaderJPG() { + + Image::_jpg_mem_loader_func=_jpegd_mem_loader_func; +} + + diff --git a/drivers/jpegd/image_loader_jpegd.h b/modules/jpg/image_loader_jpegd.h index 2c52309ab1..2c52309ab1 100644 --- a/drivers/jpegd/image_loader_jpegd.h +++ b/modules/jpg/image_loader_jpegd.h diff --git a/modules/jpg/register_types.cpp b/modules/jpg/register_types.cpp new file mode 100644 index 0000000000..a648423cdf --- /dev/null +++ b/modules/jpg/register_types.cpp @@ -0,0 +1,44 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#include "image_loader_jpegd.h" + +static ImageLoaderJPG *image_loader_jpg = NULL; + +void register_jpg_types() { + + image_loader_jpg = memnew( ImageLoaderJPG ); + ImageLoader::add_image_format_loader(image_loader_jpg); +} + +void unregister_jpg_types() { + + memdelete( image_loader_jpg ); +} diff --git a/modules/jpg/register_types.h b/modules/jpg/register_types.h new file mode 100644 index 0000000000..0e06c4ff81 --- /dev/null +++ b/modules/jpg/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_jpg_types(); +void unregister_jpg_types(); diff --git a/modules/mpc/SCsub b/modules/mpc/SCsub new file mode 100644 index 0000000000..09f0c05daa --- /dev/null +++ b/modules/mpc/SCsub @@ -0,0 +1,28 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_mpc = env_modules.Clone() + +# Thirdparty source files +if (env["libmpcdec"] != "system"): # builtin + thirdparty_dir = "#thirdparty/libmpcdec/" + thirdparty_sources = [ + "huffman.c", + "mpc_bits_reader.c", + "mpc_decoder.c", + "mpc_demux.c", + "mpc_reader.c", + "requant.c", + "streaminfo.c", + "synth_filter.c", + ] + + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + + env_mpc.add_source_files(env.modules_sources, thirdparty_sources) + env_mpc.Append(CPPPATH = [thirdparty_dir]) + +# Godot source files +env_mpc.add_source_files(env.modules_sources, "*.cpp") diff --git a/drivers/mpc/audio_stream_mpc.cpp b/modules/mpc/audio_stream_mpc.cpp index 9713eb3c77..9713eb3c77 100644 --- a/drivers/mpc/audio_stream_mpc.cpp +++ b/modules/mpc/audio_stream_mpc.cpp diff --git a/modules/mpc/audio_stream_mpc.h b/modules/mpc/audio_stream_mpc.h new file mode 100644 index 0000000000..c982bdc358 --- /dev/null +++ b/modules/mpc/audio_stream_mpc.h @@ -0,0 +1,146 @@ +/*************************************************************************/ +/* audio_stream_mpc.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef AUDIO_STREAM_MPC_H +#define AUDIO_STREAM_MPC_H + +#include "io/resource_loader.h" +#include "os/file_access.h" +#include "os/thread_safe.h" +#include "scene/resources/audio_stream.h" + +#include <mpc/mpcdec.h> + +class AudioStreamPlaybackMPC : public AudioStreamPlayback { + + OBJ_TYPE( AudioStreamPlaybackMPC, AudioStreamPlayback ); + + bool preload; + FileAccess *f; + String file; + DVector<uint8_t> data; + int data_ofs; + int streamlen; + + + bool active; + bool paused; + bool loop; + int loops; + + // mpc + mpc_reader reader; + mpc_demux* demux; + mpc_streaminfo si; + MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH]; + + static mpc_int32_t _mpc_read(mpc_reader *p_reader,void *p_dst, mpc_int32_t p_bytes); + static mpc_bool_t _mpc_seek(mpc_reader *p_reader,mpc_int32_t p_offset); + static mpc_int32_t _mpc_tell(mpc_reader *p_reader); + static mpc_int32_t _mpc_get_size(mpc_reader *p_reader); + static mpc_bool_t _mpc_canseek(mpc_reader *p_reader); + + int stream_min_size; + int stream_rate; + int stream_channels; + +protected: + Error _open_file(); + void _close_file(); + int _read_file(void *p_dst,int p_bytes); + bool _seek_file(int p_pos); + int _tell_file() const; + int _sizeof_file() const; + bool _canseek_file() const; + + + Error _reload(); + static void _bind_methods(); + +public: + + void set_file(const String& p_file); + String get_file() const; + + virtual void play(float p_offset=0); + virtual void stop(); + virtual bool is_playing() const; + + + virtual void set_loop(bool p_enable); + virtual bool has_loop() const; + + virtual float get_length() const; + + virtual String get_stream_name() const; + + virtual int get_loop_count() const; + + virtual float get_pos() const; + virtual void seek_pos(float p_time); + + virtual int get_channels() const { return stream_channels; } + virtual int get_mix_rate() const { return stream_rate; } + + virtual int get_minimum_buffer_size() const { return stream_min_size; } + virtual int mix(int16_t* p_bufer,int p_frames); + + virtual void set_loop_restart_time(float p_time) { } + + AudioStreamPlaybackMPC(); + ~AudioStreamPlaybackMPC(); +}; + +class AudioStreamMPC : public AudioStream { + + OBJ_TYPE( AudioStreamMPC, AudioStream ); + + String file; +public: + + Ref<AudioStreamPlayback> instance_playback() { + Ref<AudioStreamPlaybackMPC> pb = memnew( AudioStreamPlaybackMPC ); + pb->set_file(file); + return pb; + } + + void set_file(const String& p_file) { file=p_file; } + + +}; + +class ResourceFormatLoaderAudioStreamMPC : public ResourceFormatLoader { +public: + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String& p_type) const; + virtual String get_resource_type(const String &p_path) const; + +}; + +#endif // AUDIO_STREAM_MPC_H diff --git a/modules/mpc/config.py b/modules/mpc/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/mpc/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/modules/mpc/register_types.cpp b/modules/mpc/register_types.cpp new file mode 100644 index 0000000000..f6a1f59dca --- /dev/null +++ b/modules/mpc/register_types.cpp @@ -0,0 +1,45 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#include "audio_stream_mpc.h" + +static ResourceFormatLoaderAudioStreamMPC* mpc_stream_loader = NULL; + +void register_mpc_types() { + + mpc_stream_loader=memnew( ResourceFormatLoaderAudioStreamMPC ); + ResourceLoader::add_resource_format_loader(mpc_stream_loader); + ObjectTypeDB::register_type<AudioStreamMPC>(); +} + +void unregister_mpc_types() { + + memdelete( mpc_stream_loader ); +} diff --git a/modules/mpc/register_types.h b/modules/mpc/register_types.h new file mode 100644 index 0000000000..3d0661ed62 --- /dev/null +++ b/modules/mpc/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_mpc_types(); +void unregister_mpc_types(); diff --git a/modules/ogg/SCsub b/modules/ogg/SCsub new file mode 100644 index 0000000000..2e1fe2e0c0 --- /dev/null +++ b/modules/ogg/SCsub @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_ogg = env_modules.Clone() + +# Thirdparty source files +if (env["libogg"] != "system"): # builtin + thirdparty_dir = "#thirdparty/libogg/" + thirdparty_sources = [ + "bitwise.c", + "framing.c", + ] + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + + env_ogg.add_source_files(env.modules_sources, thirdparty_sources) + env_ogg.Append(CPPPATH = [thirdparty_dir]) + +# Godot source files +env_ogg.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/ogg/config.py b/modules/ogg/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/ogg/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/modules/ogg/register_types.cpp b/modules/ogg/register_types.cpp new file mode 100644 index 0000000000..823ca510ca --- /dev/null +++ b/modules/ogg/register_types.cpp @@ -0,0 +1,35 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +// Dummy module as libogg is needed by other modules (vorbis, theora, opus, ...) + +void register_ogg_types() {} + +void unregister_ogg_types() {} diff --git a/modules/ogg/register_types.h b/modules/ogg/register_types.h new file mode 100644 index 0000000000..b5268a1df4 --- /dev/null +++ b/modules/ogg/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_ogg_types(); +void unregister_ogg_types(); diff --git a/modules/openssl/SCsub b/modules/openssl/SCsub new file mode 100644 index 0000000000..2327cf483c --- /dev/null +++ b/modules/openssl/SCsub @@ -0,0 +1,687 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_openssl = env_modules.Clone() + +# Thirdparty source files +if (env["openssl"] != "system"): # builtin + thirdparty_dir = "#thirdparty/openssl/" + + thirdparty_sources = [ + "ssl/t1_lib.c", + "ssl/t1_ext.c", + "ssl/s3_srvr.c", + "ssl/t1_enc.c", + "ssl/t1_meth.c", + "ssl/s23_clnt.c", + "ssl/ssl_asn1.c", + "ssl/tls_srp.c", + "ssl/kssl.c", + "ssl/d1_both.c", + "ssl/t1_clnt.c", + "ssl/bio_ssl.c", + "ssl/d1_srtp.c", + "ssl/t1_reneg.c", + "ssl/ssl_cert.c", + "ssl/s3_lib.c", + "ssl/d1_srvr.c", + "ssl/s23_meth.c", + "ssl/ssl_stat.c", + "ssl/ssl_err.c", + "ssl/ssl_algs.c", + "ssl/s3_cbc.c", + "ssl/d1_clnt.c", + "ssl/s3_pkt.c", + "ssl/d1_meth.c", + "ssl/s3_both.c", + "ssl/s2_enc.c", + "ssl/s3_meth.c", + "ssl/s3_enc.c", + "ssl/s23_pkt.c", + "ssl/s2_pkt.c", + "ssl/d1_pkt.c", + "ssl/ssl_rsa.c", + "ssl/s23_srvr.c", + "ssl/s2_meth.c", + "ssl/s3_clnt.c", + "ssl/s23_lib.c", + "ssl/t1_srvr.c", + "ssl/ssl_lib.c", + "ssl/ssl_txt.c", + "ssl/s2_srvr.c", + "ssl/ssl_sess.c", + "ssl/s2_clnt.c", + "ssl/d1_lib.c", + "ssl/s2_lib.c", + "ssl/ssl_err2.c", + "ssl/ssl_ciph.c", + "crypto/dsa/dsa_lib.c", + "crypto/dsa/dsa_pmeth.c", + "crypto/dsa/dsa_ossl.c", + "crypto/dsa/dsa_gen.c", + "crypto/dsa/dsa_asn1.c", + "crypto/dsa/dsa_prn.c", + "crypto/dsa/dsa_sign.c", + "crypto/dsa/dsa_key.c", + "crypto/dsa/dsa_vrf.c", + "crypto/dsa/dsa_err.c", + "crypto/dsa/dsa_ameth.c", + "crypto/dsa/dsa_depr.c", + "crypto/x509/x509_lu.c", + "crypto/x509/x509cset.c", + "crypto/x509/x509_set.c", + "crypto/x509/x509_d2.c", + "crypto/x509/x509_txt.c", + "crypto/x509/x509rset.c", + "crypto/x509/by_dir.c", + "crypto/x509/x509_vpm.c", + "crypto/x509/x509_vfy.c", + "crypto/x509/x509_trs.c", + "crypto/x509/by_file.c", + "crypto/x509/x509_obj.c", + "crypto/x509/x509spki.c", + "crypto/x509/x509_v3.c", + "crypto/x509/x509_req.c", + "crypto/x509/x509_att.c", + "crypto/x509/x_all.c", + "crypto/x509/x509_ext.c", + "crypto/x509/x509type.c", + "crypto/x509/x509_def.c", + "crypto/x509/x509_err.c", + "crypto/x509/x509name.c", + "crypto/x509/x509_r2x.c", + "crypto/x509/x509_cmp.c", + "crypto/asn1/x_pkey.c", + "crypto/asn1/a_gentm.c", + "crypto/asn1/x_sig.c", + "crypto/asn1/t_req.c", + "crypto/asn1/t_pkey.c", + "crypto/asn1/p8_pkey.c", + "crypto/asn1/a_i2d_fp.c", + "crypto/asn1/x_val.c", + "crypto/asn1/f_string.c", + "crypto/asn1/p5_pbe.c", + "crypto/asn1/bio_ndef.c", + "crypto/asn1/a_bool.c", + "crypto/asn1/asn1_gen.c", + "crypto/asn1/x_algor.c", + "crypto/asn1/bio_asn1.c", + "crypto/asn1/asn_mime.c", + "crypto/asn1/t_x509.c", + "crypto/asn1/a_strex.c", + "crypto/asn1/x_nx509.c", + "crypto/asn1/asn1_err.c", + "crypto/asn1/x_crl.c", + "crypto/asn1/a_print.c", + "crypto/asn1/a_type.c", + "crypto/asn1/tasn_new.c", + "crypto/asn1/n_pkey.c", + "crypto/asn1/x_bignum.c", + "crypto/asn1/asn_pack.c", + "crypto/asn1/evp_asn1.c", + "crypto/asn1/t_bitst.c", + "crypto/asn1/x_req.c", + "crypto/asn1/a_time.c", + "crypto/asn1/x_name.c", + "crypto/asn1/x_pubkey.c", + "crypto/asn1/tasn_typ.c", + "crypto/asn1/asn_moid.c", + "crypto/asn1/a_utctm.c", + "crypto/asn1/asn1_lib.c", + "crypto/asn1/x_x509a.c", + "crypto/asn1/a_set.c", + "crypto/asn1/t_crl.c", + "crypto/asn1/p5_pbev2.c", + "crypto/asn1/tasn_enc.c", + "crypto/asn1/a_mbstr.c", + "crypto/asn1/tasn_dec.c", + "crypto/asn1/x_x509.c", + "crypto/asn1/a_octet.c", + "crypto/asn1/x_long.c", + "crypto/asn1/a_bytes.c", + "crypto/asn1/t_x509a.c", + "crypto/asn1/a_enum.c", + "crypto/asn1/a_int.c", + "crypto/asn1/tasn_prn.c", + "crypto/asn1/i2d_pr.c", + "crypto/asn1/a_utf8.c", + "crypto/asn1/t_spki.c", + "crypto/asn1/a_digest.c", + "crypto/asn1/a_dup.c", + "crypto/asn1/i2d_pu.c", + "crypto/asn1/a_verify.c", + "crypto/asn1/f_enum.c", + "crypto/asn1/a_sign.c", + "crypto/asn1/d2i_pr.c", + "crypto/asn1/asn1_par.c", + "crypto/asn1/x_spki.c", + "crypto/asn1/a_d2i_fp.c", + "crypto/asn1/f_int.c", + "crypto/asn1/x_exten.c", + "crypto/asn1/tasn_utl.c", + "crypto/asn1/nsseq.c", + "crypto/asn1/a_bitstr.c", + "crypto/asn1/x_info.c", + "crypto/asn1/a_strnid.c", + "crypto/asn1/a_object.c", + "crypto/asn1/tasn_fre.c", + "crypto/asn1/d2i_pu.c", + "crypto/asn1/ameth_lib.c", + "crypto/asn1/x_attrib.c", + "crypto/evp/m_sha.c", + "crypto/evp/e_camellia.c", + "crypto/evp/e_aes.c", + "crypto/evp/bio_b64.c", + "crypto/evp/m_sigver.c", + "crypto/evp/m_wp.c", + "crypto/evp/m_sha1.c", + "crypto/evp/p_seal.c", + "crypto/evp/c_alld.c", + "crypto/evp/p5_crpt.c", + "crypto/evp/e_rc4.c", + "crypto/evp/m_ecdsa.c", + "crypto/evp/bio_enc.c", + "crypto/evp/e_des3.c", + "crypto/evp/m_null.c", + "crypto/evp/bio_ok.c", + "crypto/evp/pmeth_gn.c", + "crypto/evp/e_rc5.c", + "crypto/evp/e_rc2.c", + "crypto/evp/p_dec.c", + "crypto/evp/p_verify.c", + "crypto/evp/e_rc4_hmac_md5.c", + "crypto/evp/pmeth_lib.c", + "crypto/evp/m_ripemd.c", + "crypto/evp/m_md5.c", + "crypto/evp/e_bf.c", + "crypto/evp/p_enc.c", + "crypto/evp/m_dss.c", + "crypto/evp/bio_md.c", + "crypto/evp/evp_pbe.c", + "crypto/evp/e_seed.c", + "crypto/evp/e_cast.c", + "crypto/evp/p_open.c", + "crypto/evp/p5_crpt2.c", + "crypto/evp/m_dss1.c", + "crypto/evp/names.c", + "crypto/evp/evp_acnf.c", + "crypto/evp/e_des.c", + "crypto/evp/evp_cnf.c", + "crypto/evp/evp_lib.c", + "crypto/evp/digest.c", + "crypto/evp/evp_err.c", + "crypto/evp/evp_enc.c", + "crypto/evp/e_old.c", + "crypto/evp/c_all.c", + "crypto/evp/m_md2.c", + "crypto/evp/e_xcbc_d.c", + "crypto/evp/pmeth_fn.c", + "crypto/evp/p_lib.c", + "crypto/evp/evp_key.c", + "crypto/evp/encode.c", + "crypto/evp/e_aes_cbc_hmac_sha1.c", + "crypto/evp/e_aes_cbc_hmac_sha256.c", + "crypto/evp/m_mdc2.c", + "crypto/evp/e_null.c", + "crypto/evp/p_sign.c", + "crypto/evp/e_idea.c", + "crypto/evp/c_allc.c", + "crypto/evp/evp_pkey.c", + "crypto/evp/m_md4.c", + "crypto/ex_data.c", + "crypto/pkcs12/p12_p8e.c", + "crypto/pkcs12/p12_crt.c", + "crypto/pkcs12/p12_utl.c", + "crypto/pkcs12/p12_attr.c", + "crypto/pkcs12/p12_npas.c", + "crypto/pkcs12/p12_decr.c", + "crypto/pkcs12/p12_init.c", + "crypto/pkcs12/p12_kiss.c", + "crypto/pkcs12/p12_add.c", + "crypto/pkcs12/p12_p8d.c", + "crypto/pkcs12/p12_mutl.c", + "crypto/pkcs12/p12_crpt.c", + "crypto/pkcs12/pk12err.c", + "crypto/pkcs12/p12_asn.c", + "crypto/pkcs12/p12_key.c", + "crypto/ecdh/ech_key.c", + "crypto/ecdh/ech_ossl.c", + "crypto/ecdh/ech_lib.c", + "crypto/ecdh/ech_err.c", + "crypto/ecdh/ech_kdf.c", + "crypto/o_str.c", + "crypto/conf/conf_api.c", + "crypto/conf/conf_err.c", + "crypto/conf/conf_def.c", + "crypto/conf/conf_lib.c", + "crypto/conf/conf_mall.c", + "crypto/conf/conf_sap.c", + "crypto/conf/conf_mod.c", + "crypto/ebcdic.c", + "crypto/ecdsa/ecs_lib.c", + "crypto/ecdsa/ecs_asn1.c", + "crypto/ecdsa/ecs_ossl.c", + "crypto/ecdsa/ecs_vrf.c", + "crypto/ecdsa/ecs_sign.c", + "crypto/ecdsa/ecs_err.c", + "crypto/dso/dso_win32.c", + "crypto/dso/dso_lib.c", + "crypto/dso/dso_dlfcn.c", + "crypto/dso/dso_dl.c", + "crypto/dso/dso_beos.c", + "crypto/dso/dso_null.c", + "crypto/dso/dso_vms.c", + "crypto/dso/dso_err.c", + "crypto/dso/dso_openssl.c", + "crypto/cryptlib.c", + "crypto/md5/md5_one.c", + "crypto/md5/md5_dgst.c", + "crypto/pkcs7/pkcs7err.c", + "crypto/pkcs7/pk7_smime.c", + "crypto/pkcs7/bio_pk7.c", + "crypto/pkcs7/pk7_mime.c", + "crypto/pkcs7/pk7_lib.c", + "crypto/pkcs7/pk7_asn1.c", + "crypto/pkcs7/pk7_doit.c", + "crypto/pkcs7/pk7_attr.c", + "crypto/md4/md4_one.c", + "crypto/md4/md4_dgst.c", + "crypto/o_dir.c", + "crypto/buffer/buf_err.c", + "crypto/buffer/buf_str.c", + "crypto/buffer/buffer.c", + "crypto/cms/cms_lib.c", + "crypto/cms/cms_io.c", + "crypto/cms/cms_err.c", + "crypto/cms/cms_dd.c", + "crypto/cms/cms_smime.c", + "crypto/cms/cms_att.c", + "crypto/cms/cms_pwri.c", + "crypto/cms/cms_cd.c", + "crypto/cms/cms_sd.c", + "crypto/cms/cms_asn1.c", + "crypto/cms/cms_env.c", + "crypto/cms/cms_enc.c", + "crypto/cms/cms_ess.c", + "crypto/cms/cms_kari.c", + "crypto/mem_dbg.c", + "crypto/uid.c", + "crypto/stack/stack.c", + "crypto/ec/ec_ameth.c", + "crypto/ec/ec_err.c", + "crypto/ec/ec_lib.c", + "crypto/ec/ec_curve.c", + "crypto/ec/ec_oct.c", + "crypto/ec/ec_asn1.c", + "crypto/ec/ecp_oct.c", + "crypto/ec/ec_print.c", + "crypto/ec/ec2_smpl.c", + "crypto/ec/ecp_nistp224.c", + "crypto/ec/ec2_oct.c", + "crypto/ec/eck_prn.c", + "crypto/ec/ec_key.c", + "crypto/ec/ecp_nist.c", + "crypto/ec/ec_check.c", + "crypto/ec/ecp_smpl.c", + "crypto/ec/ec2_mult.c", + "crypto/ec/ecp_mont.c", + "crypto/ec/ecp_nistp521.c", + "crypto/ec/ec_mult.c", + "crypto/ec/ecp_nistputil.c", + "crypto/ec/ec_pmeth.c", + "crypto/ec/ec_cvt.c", + "crypto/ec/ecp_nistp256.c", + "crypto/krb5/krb5_asn.c", + "crypto/hmac/hmac.c", + "crypto/hmac/hm_ameth.c", + "crypto/hmac/hm_pmeth.c", + "crypto/comp/c_rle.c", + "crypto/comp/c_zlib.c", + "crypto/comp/comp_lib.c", + "crypto/comp/comp_err.c", + "crypto/des/fcrypt.c", + "crypto/des/str2key.c", + "crypto/des/cbc_cksm.c", + "crypto/des/des_enc.c", + "crypto/des/ofb_enc.c", + "crypto/des/read2pwd.c", + "crypto/des/ecb3_enc.c", + "crypto/des/rand_key.c", + "crypto/des/cfb64ede.c", + "crypto/des/rpc_enc.c", + "crypto/des/ofb64ede.c", + "crypto/des/qud_cksm.c", + "crypto/des/enc_writ.c", + "crypto/des/set_key.c", + "crypto/des/xcbc_enc.c", + "crypto/des/fcrypt_b.c", + "crypto/des/ede_cbcm_enc.c", + "crypto/des/des_old2.c", + "crypto/des/cfb_enc.c", + "crypto/des/ecb_enc.c", + "crypto/des/enc_read.c", + "crypto/des/des_old.c", + "crypto/des/ofb64enc.c", + "crypto/des/pcbc_enc.c", + "crypto/des/cbc_enc.c", + "crypto/des/cfb64enc.c", + "crypto/lhash/lh_stats.c", + "crypto/lhash/lhash.c", + "crypto/x509v3/v3_genn.c", + "crypto/x509v3/pcy_cache.c", + "crypto/x509v3/v3_sxnet.c", + "crypto/x509v3/v3_scts.c", + "crypto/x509v3/v3err.c", + "crypto/x509v3/v3_conf.c", + "crypto/x509v3/v3_utl.c", + "crypto/x509v3/v3_akeya.c", + "crypto/x509v3/v3_lib.c", + "crypto/x509v3/pcy_lib.c", + "crypto/x509v3/v3_cpols.c", + "crypto/x509v3/v3_ia5.c", + "crypto/x509v3/v3_bitst.c", + "crypto/x509v3/v3_skey.c", + "crypto/x509v3/v3_info.c", + "crypto/x509v3/v3_asid.c", + "crypto/x509v3/pcy_tree.c", + "crypto/x509v3/v3_pcons.c", + "crypto/x509v3/v3_bcons.c", + "crypto/x509v3/v3_pku.c", + "crypto/x509v3/v3_ocsp.c", + "crypto/x509v3/pcy_map.c", + "crypto/x509v3/v3_ncons.c", + "crypto/x509v3/v3_purp.c", + "crypto/x509v3/v3_enum.c", + "crypto/x509v3/v3_pmaps.c", + "crypto/x509v3/pcy_node.c", + "crypto/x509v3/v3_pcia.c", + "crypto/x509v3/v3_crld.c", + "crypto/x509v3/v3_pci.c", + "crypto/x509v3/v3_akey.c", + "crypto/x509v3/v3_addr.c", + "crypto/x509v3/v3_int.c", + "crypto/x509v3/v3_alt.c", + "crypto/x509v3/v3_extku.c", + "crypto/x509v3/v3_prn.c", + "crypto/x509v3/pcy_data.c", + "crypto/aes/aes_ofb.c", + "crypto/aes/aes_ctr.c", + "crypto/aes/aes_ecb.c", + "crypto/aes/aes_cfb.c", + "crypto/aes/aes_wrap.c", + "crypto/aes/aes_ige.c", + "crypto/aes/aes_misc.c", + "crypto/pqueue/pqueue.c", + "crypto/sha/sha_one.c", + "crypto/sha/sha_dgst.c", + "crypto/sha/sha512.c", + "crypto/sha/sha1_one.c", + "crypto/sha/sha1dgst.c", + "crypto/sha/sha256.c", + "crypto/whrlpool/wp_dgst.c", + "crypto/objects/obj_xref.c", + "crypto/objects/o_names.c", + "crypto/objects/obj_err.c", + "crypto/objects/obj_dat.c", + "crypto/objects/obj_lib.c", + "crypto/mem.c", + "crypto/fips_ers.c", + "crypto/o_fips.c", + "crypto/engine/eng_rdrand.c", + "crypto/engine/eng_err.c", + "crypto/engine/tb_ecdsa.c", + "crypto/engine/tb_rsa.c", + "crypto/engine/tb_cipher.c", + "crypto/engine/tb_dsa.c", + "crypto/engine/eng_lib.c", + "crypto/engine/tb_asnmth.c", + "crypto/engine/tb_ecdh.c", + "crypto/engine/tb_dh.c", + "crypto/engine/tb_store.c", + "crypto/engine/eng_init.c", + "crypto/engine/eng_cnf.c", + "crypto/engine/eng_all.c", + "crypto/engine/tb_digest.c", + "crypto/engine/tb_pkmeth.c", + "crypto/engine/eng_table.c", + "crypto/engine/eng_ctrl.c", + "crypto/engine/eng_list.c", + "crypto/engine/eng_cryptodev.c", + "crypto/engine/eng_pkey.c", + "crypto/engine/tb_rand.c", + "crypto/engine/eng_openssl.c", + "crypto/engine/eng_fat.c", + "crypto/engine/eng_dyn.c", + "crypto/ts/ts_rsp_verify.c", + "crypto/ts/ts_req_print.c", + "crypto/ts/ts_verify_ctx.c", + "crypto/ts/ts_req_utils.c", + "crypto/ts/ts_err.c", + "crypto/ts/ts_rsp_print.c", + "crypto/ts/ts_rsp_utils.c", + "crypto/ts/ts_lib.c", + "crypto/ts/ts_conf.c", + "crypto/ts/ts_asn1.c", + "crypto/ts/ts_rsp_sign.c", + "crypto/ocsp/ocsp_ext.c", + "crypto/ocsp/ocsp_cl.c", + "crypto/ocsp/ocsp_ht.c", + "crypto/ocsp/ocsp_lib.c", + "crypto/ocsp/ocsp_srv.c", + "crypto/ocsp/ocsp_vfy.c", + "crypto/ocsp/ocsp_err.c", + "crypto/ocsp/ocsp_prn.c", + "crypto/ocsp/ocsp_asn.c", + "crypto/bf/bf_cfb64.c", + "crypto/bf/bf_ecb.c", + "crypto/bf/bf_enc.c", + "crypto/bf/bf_skey.c", + "crypto/bf/bf_ofb64.c", + "crypto/idea/i_skey.c", + "crypto/idea/i_ofb64.c", + "crypto/idea/i_cbc.c", + "crypto/idea/i_ecb.c", + "crypto/idea/i_cfb64.c", + "crypto/cmac/cm_ameth.c", + "crypto/cmac/cmac.c", + "crypto/cmac/cm_pmeth.c", + "crypto/dh/dh_lib.c", + "crypto/dh/dh_key.c", + "crypto/dh/dh_asn1.c", + "crypto/dh/dh_depr.c", + "crypto/dh/dh_pmeth.c", + "crypto/dh/dh_prn.c", + "crypto/dh/dh_gen.c", + "crypto/dh/dh_ameth.c", + "crypto/dh/dh_check.c", + "crypto/dh/dh_err.c", + "crypto/dh/dh_kdf.c", + "crypto/dh/dh_rfc5114.c", + "crypto/modes/ccm128.c", + "crypto/modes/ofb128.c", + "crypto/modes/cts128.c", + "crypto/modes/ctr128.c", + "crypto/modes/gcm128.c", + "crypto/modes/cbc128.c", + "crypto/modes/cfb128.c", + "crypto/modes/xts128.c", + "crypto/modes/wrap128.c", + "crypto/camellia/cmll_cfb.c", + "crypto/camellia/cmll_ecb.c", + "crypto/camellia/cmll_utl.c", + "crypto/camellia/cmll_misc.c", + "crypto/camellia/cmll_ofb.c", + "crypto/camellia/cmll_ctr.c", + "crypto/seed/seed_ecb.c", + "crypto/seed/seed_cbc.c", + "crypto/seed/seed.c", + "crypto/seed/seed_ofb.c", + "crypto/seed/seed_cfb.c", + "crypto/txt_db/txt_db.c", + "crypto/cpt_err.c", + "crypto/pem/pem_pk8.c", + "crypto/pem/pem_lib.c", + "crypto/pem/pem_sign.c", + "crypto/pem/pem_all.c", + "crypto/pem/pem_info.c", + "crypto/pem/pem_pkey.c", + "crypto/pem/pem_seal.c", + "crypto/pem/pem_err.c", + "crypto/pem/pem_xaux.c", + "crypto/pem/pvkfmt.c", + "crypto/pem/pem_x509.c", + "crypto/pem/pem_oth.c", + "crypto/rand/rand_lib.c", + "crypto/rand/randfile.c", + "crypto/rand/rand_os2.c", + "crypto/rand/rand_unix.c", + "crypto/rand/rand_nw.c", + "crypto/rand/md_rand.c", + "crypto/rand/rand_err.c", + "crypto/rand/rand_win.c", + "crypto/rand/rand_egd.c", + "crypto/cversion.c", + "crypto/cast/c_ecb.c", + "crypto/cast/c_skey.c", + "crypto/cast/c_ofb64.c", + "crypto/cast/c_enc.c", + "crypto/cast/c_cfb64.c", + "crypto/o_time.c", + "crypto/mdc2/mdc2dgst.c", + "crypto/mdc2/mdc2_one.c", + "crypto/rc4/rc4_utl.c", + "crypto/ui/ui_compat.c", + "crypto/ui/ui_util.c", + "crypto/ui/ui_lib.c", + "crypto/ui/ui_err.c", + "crypto/ui/ui_openssl.c", + "crypto/bio/bf_buff.c", + "crypto/bio/bss_null.c", + "crypto/bio/bss_acpt.c", + "crypto/bio/bss_conn.c", + "crypto/bio/bss_fd.c", + "crypto/bio/bf_null.c", + "crypto/bio/bio_err.c", + "crypto/bio/bss_sock.c", + "crypto/bio/bss_mem.c", + "crypto/bio/b_dump.c", + "crypto/bio/b_print.c", + "crypto/bio/b_sock.c", + "crypto/bio/bss_dgram.c", + "crypto/bio/bf_nbio.c", + "crypto/bio/bio_lib.c", + "crypto/bio/bss_file.c", + "crypto/bio/bss_bio.c", + "crypto/bio/bss_log.c", + "crypto/bio/bio_cb.c", + "crypto/o_init.c", + "crypto/rc2/rc2_skey.c", + "crypto/rc2/rc2_cbc.c", + "crypto/rc2/rc2cfb64.c", + "crypto/rc2/rc2_ecb.c", + "crypto/rc2/rc2ofb64.c", + "crypto/bn/bn_x931p.c", + "crypto/bn/bn_blind.c", + "crypto/bn/bn_gf2m.c", + "crypto/bn/bn_const.c", + "crypto/bn/bn_sqr.c", + "crypto/bn/bn_nist.c", + "crypto/bn/bn_rand.c", + "crypto/bn/bn_err.c", + "crypto/bn/bn_div.c", + "crypto/bn/bn_kron.c", + "crypto/bn/bn_ctx.c", + "crypto/bn/bn_shift.c", + "crypto/bn/bn_mod.c", + "crypto/bn/bn_exp2.c", + "crypto/bn/bn_word.c", + "crypto/bn/bn_add.c", + "crypto/bn/bn_exp.c", + "crypto/bn/bn_mont.c", + "crypto/bn/bn_print.c", + "crypto/bn/bn_mul.c", + "crypto/bn/bn_prime.c", + "crypto/bn/bn_depr.c", + "crypto/bn/bn_gcd.c", + "crypto/bn/bn_mpi.c", + "crypto/bn/bn_sqrt.c", + "crypto/bn/bn_recp.c", + "crypto/bn/bn_lib.c", + "crypto/ripemd/rmd_dgst.c", + "crypto/ripemd/rmd_one.c", + "crypto/rsa/rsa_x931.c", + "crypto/rsa/rsa_depr.c", + "crypto/rsa/rsa_saos.c", + "crypto/rsa/rsa_crpt.c", + "crypto/rsa/rsa_pss.c", + "crypto/rsa/rsa_oaep.c", + "crypto/rsa/rsa_null.c", + "crypto/rsa/rsa_gen.c", + "crypto/rsa/rsa_prn.c", + "crypto/rsa/rsa_pmeth.c", + "crypto/rsa/rsa_asn1.c", + "crypto/rsa/rsa_ssl.c", + "crypto/rsa/rsa_ameth.c", + "crypto/rsa/rsa_pk1.c", + "crypto/rsa/rsa_err.c", + "crypto/rsa/rsa_lib.c", + "crypto/rsa/rsa_none.c", + "crypto/rsa/rsa_chk.c", + "crypto/rsa/rsa_eay.c", + "crypto/rsa/rsa_sign.c", + "crypto/srp/srp_lib.c", + "crypto/srp/srp_vfy.c", + "crypto/err/err.c", + "crypto/err/err_prn.c", + "crypto/err/err_all.c", + "crypto/mem_clr.c", + "crypto/rc4/rc4_skey.c", + "crypto/rc4/rc4_enc.c", + "crypto/camellia/camellia.c", + "crypto/camellia/cmll_cbc.c", + #"crypto/aes/aes_x86core.c", + "crypto/aes/aes_core.c", + "crypto/aes/aes_cbc.c", + "crypto/whrlpool/wp_block.c", + "crypto/bn/bn_asm.c", + ] + + if "platform" in env and env["platform"] == "winrt": + thirdparty_sources += ['winrt.cpp'] + + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + + env_openssl.add_source_files(env.modules_sources, thirdparty_sources) + + # FIXME: Clone the environment to make a env_openssl and not pollute the modules env + thirdparty_include_paths = [ + "", + "crypto", + "crypto/asn1", + "crypto/evp", + "crypto/modes", + "openssl", + ] + env_openssl.Append(CPPPATH = [thirdparty_dir + "/" + dir for dir in thirdparty_include_paths]) + + env_openssl.Append(CPPFLAGS = ["-DOPENSSL_NO_ASM", "-DOPENSSL_THREADS", "-DL_ENDIAN"]) + + # Workaround for compilation error with GCC/Clang when -Werror is too greedy (GH-4517) + import os + import methods + if not (os.name=="nt" and os.getenv("VCINSTALLDIR")): # not Windows and not MSVC + env_openssl.Append(CFLAGS = ["-Wno-error=implicit-function-declaration"]) + + +# Module sources +env_openssl.add_source_files(env.modules_sources, "*.cpp") +env_openssl.add_source_files(env.modules_sources, "*.c") + +# platform/winrt need to know openssl is available, pass to main env +if "platform" in env and env["platform"] == "winrt": + env.Append(CPPPATH = [thirdparty_dir]) + env.Append(CPPFLAGS = ['-DOPENSSL_ENABLED']); + +Export('env') diff --git a/modules/openssl/config.py b/modules/openssl/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/openssl/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/modules/openssl/curl_hostcheck.c b/modules/openssl/curl_hostcheck.c new file mode 100644 index 0000000000..feef232619 --- /dev/null +++ b/modules/openssl/curl_hostcheck.c @@ -0,0 +1,217 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This file is an amalgamation of hostcheck.c and most of rawstr.c + from cURL. The contents of the COPYING file mentioned above are: + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1996 - 2013, Daniel Stenberg, <daniel@haxx.se>. + +All rights reserved. + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization of the copyright holder. +*/ + +#include "curl_hostcheck.h" +#include <string.h> + +/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because + its behavior is altered by the current locale. */ +static char Curl_raw_toupper(char in) +{ + switch (in) { + case 'a': + return 'A'; + case 'b': + return 'B'; + case 'c': + return 'C'; + case 'd': + return 'D'; + case 'e': + return 'E'; + case 'f': + return 'F'; + case 'g': + return 'G'; + case 'h': + return 'H'; + case 'i': + return 'I'; + case 'j': + return 'J'; + case 'k': + return 'K'; + case 'l': + return 'L'; + case 'm': + return 'M'; + case 'n': + return 'N'; + case 'o': + return 'O'; + case 'p': + return 'P'; + case 'q': + return 'Q'; + case 'r': + return 'R'; + case 's': + return 'S'; + case 't': + return 'T'; + case 'u': + return 'U'; + case 'v': + return 'V'; + case 'w': + return 'W'; + case 'x': + return 'X'; + case 'y': + return 'Y'; + case 'z': + return 'Z'; + } + return in; +} + +/* + * Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant + * to be locale independent and only compare strings we know are safe for + * this. See http://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for + * some further explanation to why this function is necessary. + * + * The function is capable of comparing a-z case insensitively even for + * non-ascii. + */ + +static int Curl_raw_equal(const char *first, const char *second) +{ + while(*first && *second) { + if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) + /* get out of the loop as soon as they don't match */ + break; + first++; + second++; + } + /* we do the comparison here (possibly again), just to make sure that if the + loop above is skipped because one of the strings reached zero, we must not + return this as a successful match */ + return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second)); +} + +static int Curl_raw_nequal(const char *first, const char *second, size_t max) +{ + while(*first && *second && max) { + if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) { + break; + } + max--; + first++; + second++; + } + if(0 == max) + return 1; /* they are equal this far */ + + return Curl_raw_toupper(*first) == Curl_raw_toupper(*second); +} + +/* + * Match a hostname against a wildcard pattern. + * E.g. + * "foo.host.com" matches "*.host.com". + * + * We use the matching rule described in RFC6125, section 6.4.3. + * http://tools.ietf.org/html/rfc6125#section-6.4.3 + */ + +static int hostmatch(const char *hostname, const char *pattern) +{ + const char *pattern_label_end, *pattern_wildcard, *hostname_label_end; + int wildcard_enabled; + size_t prefixlen, suffixlen; + pattern_wildcard = strchr(pattern, '*'); + if(pattern_wildcard == NULL) + return Curl_raw_equal(pattern, hostname) ? + CURL_HOST_MATCH : CURL_HOST_NOMATCH; + + /* We require at least 2 dots in pattern to avoid too wide wildcard + match. */ + wildcard_enabled = 1; + pattern_label_end = strchr(pattern, '.'); + if(pattern_label_end == NULL || strchr(pattern_label_end+1, '.') == NULL || + pattern_wildcard > pattern_label_end || + Curl_raw_nequal(pattern, "xn--", 4)) { + wildcard_enabled = 0; + } + if(!wildcard_enabled) + return Curl_raw_equal(pattern, hostname) ? + CURL_HOST_MATCH : CURL_HOST_NOMATCH; + + hostname_label_end = strchr(hostname, '.'); + if(hostname_label_end == NULL || + !Curl_raw_equal(pattern_label_end, hostname_label_end)) + return CURL_HOST_NOMATCH; + + /* The wildcard must match at least one character, so the left-most + label of the hostname is at least as large as the left-most label + of the pattern. */ + if(hostname_label_end - hostname < pattern_label_end - pattern) + return CURL_HOST_NOMATCH; + + prefixlen = pattern_wildcard - pattern; + suffixlen = pattern_label_end - (pattern_wildcard+1); + return Curl_raw_nequal(pattern, hostname, prefixlen) && + Curl_raw_nequal(pattern_wildcard+1, hostname_label_end - suffixlen, + suffixlen) ? + CURL_HOST_MATCH : CURL_HOST_NOMATCH; +} + +int Tool_Curl_cert_hostcheck(const char *match_pattern, const char *hostname) +{ + if(!match_pattern || !*match_pattern || + !hostname || !*hostname) /* sanity check */ + return 0; + + if(Curl_raw_equal(hostname, match_pattern)) /* trivial case */ + return 1; + + if(hostmatch(hostname,match_pattern) == CURL_HOST_MATCH) + return 1; + return 0; +} diff --git a/modules/openssl/curl_hostcheck.h b/modules/openssl/curl_hostcheck.h new file mode 100644 index 0000000000..1b7fbe81e3 --- /dev/null +++ b/modules/openssl/curl_hostcheck.h @@ -0,0 +1,39 @@ +#ifndef HEADER_TOOL_CURL_HOSTCHECK_H +#define HEADER_TOOL_CURL_HOSTCHECK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#define CURL_HOST_NOMATCH 0 +#define CURL_HOST_MATCH 1 +int Tool_Curl_cert_hostcheck(const char *match_pattern, const char *hostname); + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_CURL_HOSTCHECK_H */ + diff --git a/modules/openssl/register_types.cpp b/modules/openssl/register_types.cpp new file mode 100644 index 0000000000..4aba9f530e --- /dev/null +++ b/modules/openssl/register_types.cpp @@ -0,0 +1,42 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#include "stream_peer_openssl.h" + +void register_openssl_types() { + + ObjectTypeDB::register_type<StreamPeerOpenSSL>(); + StreamPeerOpenSSL::initialize_ssl(); +} + +void unregister_openssl_types() { + + StreamPeerOpenSSL::finalize_ssl(); +} diff --git a/modules/openssl/register_types.h b/modules/openssl/register_types.h new file mode 100644 index 0000000000..2db140cc80 --- /dev/null +++ b/modules/openssl/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_openssl_types(); +void unregister_openssl_types(); diff --git a/modules/openssl/stream_peer_openssl.cpp b/modules/openssl/stream_peer_openssl.cpp new file mode 100644 index 0000000000..b9bec4ca0b --- /dev/null +++ b/modules/openssl/stream_peer_openssl.cpp @@ -0,0 +1,646 @@ +/*************************************************************************/ +/* stream_peer_openssl.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "stream_peer_openssl.h" +//hostname matching code from curl + + +//#include <openssl/applink.c> // To prevent crashing (see the OpenSSL FAQ) + +bool StreamPeerOpenSSL::_match_host_name(const char *name, const char *hostname) { + + return Tool_Curl_cert_hostcheck(name,hostname)==CURL_HOST_MATCH; +// print_line("MATCH: "+String(name)+" vs "+String(hostname)); +// return true; +} + +Error StreamPeerOpenSSL::_match_common_name(const char *hostname, const X509 *server_cert) { + + int common_name_loc = -1; + X509_NAME_ENTRY *common_name_entry = NULL; + ASN1_STRING *common_name_asn1 = NULL; + char *common_name_str = NULL; + + // Find the position of the CN field in the Subject field of the certificate + common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name((X509 *) server_cert), NID_commonName, -1); + + ERR_FAIL_COND_V(common_name_loc < 0, ERR_INVALID_PARAMETER ); + + // Extract the CN field + common_name_entry = X509_NAME_get_entry(X509_get_subject_name((X509 *) server_cert), common_name_loc); + + ERR_FAIL_COND_V(common_name_entry == NULL, ERR_INVALID_PARAMETER ); + + // Convert the CN field to a C string + common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry); + + ERR_FAIL_COND_V(common_name_asn1 == NULL, ERR_INVALID_PARAMETER ); + + common_name_str = (char *) ASN1_STRING_data(common_name_asn1); + + // Make sure there isn't an embedded NUL character in the CN + bool malformed_certificate = (size_t)ASN1_STRING_length(common_name_asn1) != strlen(common_name_str); + + ERR_FAIL_COND_V(malformed_certificate, ERR_INVALID_PARAMETER ); + + + // Compare expected hostname with the CN + + + return _match_host_name(common_name_str,hostname)?OK:FAILED; + +} + + +/** +* Tries to find a match for hostname in the certificate's Subject Alternative Name extension. +* +*/ + +Error StreamPeerOpenSSL::_match_subject_alternative_name(const char *hostname, const X509 *server_cert) { + + Error result = FAILED; + int i; + int san_names_nb = -1; + STACK_OF(GENERAL_NAME) *san_names = NULL; + + // Try to extract the names within the SAN extension from the certificate + san_names = (STACK_OF(GENERAL_NAME) *)X509_get_ext_d2i((X509 *) server_cert, NID_subject_alt_name, NULL, NULL); + if (san_names == NULL) { + return ERR_FILE_NOT_FOUND; + } + san_names_nb = sk_GENERAL_NAME_num(san_names); + + // Check each name within the extension + for (i=0; i<san_names_nb; i++) { + const GENERAL_NAME *current_name = sk_GENERAL_NAME_value(san_names, i); + + if (current_name->type == GEN_DNS) { + // Current name is a DNS name, let's check it + char *dns_name = (char *) ASN1_STRING_data(current_name->d.dNSName); + + // Make sure there isn't an embedded NUL character in the DNS name + if ((size_t)ASN1_STRING_length(current_name->d.dNSName) != strlen(dns_name)) { + result = ERR_INVALID_PARAMETER; + break; + } + else { // Compare expected hostname with the DNS name + if (_match_host_name(dns_name, hostname)) { + result = OK; + break; + } + } + } + } + sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free); + + return result; +} + +/* See http://archives.seul.org/libevent/users/Jan-2013/msg00039.html */ +int StreamPeerOpenSSL::_cert_verify_callback(X509_STORE_CTX *x509_ctx, void *arg) { + + /* This is the function that OpenSSL would call if we hadn't called + * SSL_CTX_set_cert_verify_callback(). Therefore, we are "wrapping" + * the default functionality, rather than replacing it. */ + + bool base_cert_valid = X509_verify_cert(x509_ctx); + if (!base_cert_valid) { + print_line("Cause: "+String(X509_verify_cert_error_string(X509_STORE_CTX_get_error(x509_ctx)))); + ERR_print_errors_fp(stdout); + } + X509 *server_cert = X509_STORE_CTX_get_current_cert(x509_ctx); + + ERR_FAIL_COND_V(!server_cert,0); + + char cert_str[256]; + X509_NAME_oneline(X509_get_subject_name (server_cert), + cert_str, sizeof (cert_str)); + + print_line("CERT STR: "+String(cert_str)); + print_line("VALID: "+itos(base_cert_valid)); + + if (!base_cert_valid) + return 0; + + StreamPeerOpenSSL *ssl = (StreamPeerOpenSSL *)arg; + + if (ssl->validate_hostname) { + + Error err = _match_subject_alternative_name(ssl->hostname.utf8().get_data(),server_cert); + + if (err==ERR_FILE_NOT_FOUND) { + + err = _match_common_name(ssl->hostname.utf8().get_data(),server_cert); + } + + if (err!=OK) { + + ssl->status=STATUS_ERROR_HOSTNAME_MISMATCH; + return 0; + } + } + + return 1; + +} + + + +int StreamPeerOpenSSL::_bio_create( BIO *b ) { + b->init = 1; + b->num = 0; + b->ptr = NULL; + b->flags = 0; + return 1; +} + +int StreamPeerOpenSSL::_bio_destroy( BIO *b ) +{ + if ( b == NULL ) + return 0; + + b->ptr = NULL; /* sb_tls_remove() will free it */ + b->init = 0; + b->flags = 0; + return 1; +} + +int StreamPeerOpenSSL::_bio_read( BIO *b, char *buf, int len ) { + + + if ( buf == NULL || len <= 0 ) return 0; + + StreamPeerOpenSSL *sp = (StreamPeerOpenSSL *)b->ptr; + + ERR_FAIL_COND_V( sp == NULL, 0); + + BIO_clear_retry_flags( b ); + if (sp->use_blocking) { + + Error err = sp->base->get_data((uint8_t*)buf,len); + if (err!=OK) { + return -1; + } + + return len; + } else { + + int got; + Error err = sp->base->get_partial_data((uint8_t*)buf,len,got); + if (err!=OK) { + return -1; + } + if (got==0) { + BIO_set_retry_read( b ); + } + return got; + } + + //unreachable + return 0; +} + +int StreamPeerOpenSSL::_bio_write( BIO *b, const char *buf, int len ) { + + if ( buf == NULL || len <= 0 ) return 0; + + StreamPeerOpenSSL *sp = (StreamPeerOpenSSL *)b->ptr; + + ERR_FAIL_COND_V( sp == NULL, 0); + + BIO_clear_retry_flags( b ); + if (sp->use_blocking) { + + Error err = sp->base->put_data((const uint8_t*)buf,len); + if (err!=OK) { + return -1; + } + + return len; + } else { + + int sent; + Error err = sp->base->put_partial_data((const uint8_t*)buf,len,sent); + if (err!=OK) { + return -1; + } + if (sent==0) { + BIO_set_retry_write( b ); + } + return sent; + + } + + //unreachable + return 0; +} + +long StreamPeerOpenSSL::_bio_ctrl( BIO *b, int cmd, long num, void *ptr ) +{ + if ( cmd == BIO_CTRL_FLUSH ) { + /* The OpenSSL library needs this */ + return 1; + } + return 0; +} + +int StreamPeerOpenSSL::_bio_gets( BIO *b, char *buf, int len ) +{ + return -1; +} + +int StreamPeerOpenSSL::_bio_puts( BIO *b, const char *str ) +{ + return _bio_write( b, str, strlen( str ) ); +} + +BIO_METHOD StreamPeerOpenSSL::_bio_method = { + /* it's a source/sink BIO */ + ( 100 | 0x400 ), + "streampeer glue", + _bio_write, + _bio_read, + _bio_puts, + _bio_gets, + _bio_ctrl, + _bio_create, + _bio_destroy +}; + +Error StreamPeerOpenSSL::connect(Ref<StreamPeer> p_base, bool p_validate_certs, const String& p_for_hostname) { + + if (connected) + disconnect(); + + + hostname=p_for_hostname; + status=STATUS_DISCONNECTED; + + // Set up a SSL_CTX object, which will tell our BIO object how to do its work + ctx = SSL_CTX_new(SSLv23_client_method()); + base=p_base; + validate_certs=p_validate_certs; + validate_hostname=p_for_hostname!=""; + + + + + if (p_validate_certs) { + + + if (certs.size()) { + //yay for undocumented OpenSSL functions + + X509_STORE *store = SSL_CTX_get_cert_store(ctx); + for(int i=0;i<certs.size();i++) { + + X509_STORE_add_cert(store,certs[i]); + + } +#if 0 + const unsigned char *in=(const unsigned char *)certs.ptr(); + X509 *Cert = d2i_X509(NULL, &in, certs.size()-1); + if (!Cert) { + print_line(String(ERR_error_string(ERR_get_error(),NULL))); + } + ERR_FAIL_COND_V(!Cert,ERR_PARSE_ERROR); + + X509_STORE *store = SSL_CTX_get_cert_store(ctx); + X509_STORE_add_cert(store,Cert); + + //char *str = X509_NAME_oneline(X509_get_subject_name(Cert),0,0); + //printf ("subject: %s\n", str); /* [1] */ +#endif + } + + //used for testing + //int res = SSL_CTX_load_verify_locations(ctx,"/etc/ssl/certs/ca-certificates.crt",NULL); + //print_line("verify locations res: "+itos(res)); + + + /* Ask OpenSSL to verify the server certificate. Note that this + * does NOT include verifying that the hostname is correct. + * So, by itself, this means anyone with any legitimate + * CA-issued certificate for any website, can impersonate any + * other website in the world. This is not good. See "The + * Most Dangerous Code in the World" article at + * https://crypto.stanford.edu/~dabo/pubs/abstracts/ssl-client-bugs.html + */ + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); + /* This is how we solve the problem mentioned in the previous + * comment. We "wrap" OpenSSL's validation routine in our + * own routine, which also validates the hostname by calling + * the code provided by iSECPartners. Note that even though + * the "Everything You've Always Wanted to Know About + * Certificate Validation With OpenSSL (But Were Afraid to + * Ask)" paper from iSECPartners says very explicitly not to + * call SSL_CTX_set_cert_verify_callback (at the bottom of + * page 2), what we're doing here is safe because our + * cert_verify_callback() calls X509_verify_cert(), which is + * OpenSSL's built-in routine which would have been called if + * we hadn't set the callback. Therefore, we're just + * "wrapping" OpenSSL's routine, not replacing it. */ + SSL_CTX_set_cert_verify_callback (ctx, _cert_verify_callback,this); + + //Let the verify_callback catch the verify_depth error so that we get an appropriate error in the logfile. (??) + SSL_CTX_set_verify_depth(ctx,max_cert_chain_depth + 1); + + } + + + + + + ssl = SSL_new( ctx ); + bio = BIO_new( &_bio_method ); + bio->ptr = this; + SSL_set_bio( ssl, bio, bio ); + + if (p_for_hostname!=String()) { + SSL_set_tlsext_host_name(ssl,p_for_hostname.utf8().get_data()); + } + + use_blocking=true; // let handshake use blocking + // Set the SSL to automatically retry on failure. + SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); + + // Same as before, try to connect. + int result = SSL_connect( ssl ); + + print_line("CONNECTION RESULT: "+itos(result)); + if (result<1) { + ERR_print_errors_fp(stdout); + _print_error(result); + } + + X509 * peer = SSL_get_peer_certificate(ssl); + + if (peer) { + bool cert_ok = SSL_get_verify_result(ssl) == X509_V_OK; + print_line("cert_ok: "+itos(cert_ok)); + + } else if (validate_certs){ + status=STATUS_ERROR_NO_CERTIFICATE; + } + + connected=true; + status=STATUS_CONNECTED; + + return OK; +} + +Error StreamPeerOpenSSL::accept(Ref<StreamPeer> p_base) { + + + return ERR_UNAVAILABLE; +} + +void StreamPeerOpenSSL::_print_error(int err) { + + err = SSL_get_error(ssl,err); + switch(err) { + case SSL_ERROR_NONE: ERR_PRINT("NO ERROR: The TLS/SSL I/O operation completed"); break; + case SSL_ERROR_ZERO_RETURN: ERR_PRINT("The TLS/SSL connection has been closed."); + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + ERR_PRINT("The operation did not complete."); break; + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + ERR_PRINT("The connect/accept operation did not complete"); break; + case SSL_ERROR_WANT_X509_LOOKUP: + ERR_PRINT("The operation did not complete because an application callback set by SSL_CTX_set_client_cert_cb() has asked to be called again."); break; + case SSL_ERROR_SYSCALL: + ERR_PRINT("Some I/O error occurred. The OpenSSL error queue may contain more information on the error."); break; + case SSL_ERROR_SSL: + ERR_PRINT("A failure in the SSL library occurred, usually a protocol error."); break; + + } +} + +Error StreamPeerOpenSSL::put_data(const uint8_t* p_data,int p_bytes) { + + ERR_FAIL_COND_V(!connected,ERR_UNCONFIGURED); + + while(p_bytes>0) { + int ret = SSL_write(ssl,p_data,p_bytes); + if (ret<=0) { + _print_error(ret); + disconnect(); + return ERR_CONNECTION_ERROR; + } + p_data+=ret; + p_bytes-=ret; + } + + return OK; + +} + +Error StreamPeerOpenSSL::put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent){ + + ERR_FAIL_COND_V(!connected,ERR_UNCONFIGURED); + if (p_bytes==0) + return OK; + + Error err = put_data(p_data,p_bytes); + if (err!=OK) + return err; + + r_sent=p_bytes; + return OK; + +} + +Error StreamPeerOpenSSL::get_data(uint8_t* p_buffer, int p_bytes){ + + ERR_FAIL_COND_V(!connected,ERR_UNCONFIGURED); + + while(p_bytes>0) { + + int ret = SSL_read(ssl,p_buffer,p_bytes); + if (ret<=0) { + _print_error(ret); + disconnect(); + return ERR_CONNECTION_ERROR; + } + p_buffer+=ret; + p_bytes-=ret; + } + + return OK; +} + +Error StreamPeerOpenSSL::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received){ + + ERR_FAIL_COND_V(!connected,ERR_UNCONFIGURED); + if (p_bytes==0) { + r_received=0; + return OK; + } + + Error err = get_data(p_buffer,p_bytes); + if (err!=OK) + return err; + r_received=p_bytes; + return OK; +} + +int StreamPeerOpenSSL::get_available_bytes() const { + + ERR_FAIL_COND_V(!connected,0); + + return SSL_pending(ssl); + +} +StreamPeerOpenSSL::StreamPeerOpenSSL() { + + ctx=NULL; + ssl=NULL; + bio=NULL; + connected=false; + use_blocking=true; //might be improved int the future, but for now it always blocks + max_cert_chain_depth=9; + flags=0; +} + +void StreamPeerOpenSSL::disconnect() { + + if (!connected) + return; + SSL_shutdown( ssl ); + SSL_free( ssl ); + SSL_CTX_free(ctx); + base=Ref<StreamPeer>(); + connected=false; + validate_certs=false; + validate_hostname=false; + status=STATUS_DISCONNECTED; + + +} + +StreamPeerOpenSSL::Status StreamPeerOpenSSL::get_status() const { + + return status; +} + + +StreamPeerOpenSSL::~StreamPeerOpenSSL() { + disconnect(); +} + +StreamPeerSSL* StreamPeerOpenSSL::_create_func() { + + return memnew( StreamPeerOpenSSL ); +} + + +Vector<X509*> StreamPeerOpenSSL::certs; + + +void StreamPeerOpenSSL::_load_certs(const ByteArray& p_array) { + + ByteArray::Read r = p_array.read(); + BIO* mem = BIO_new(BIO_s_mem()); + BIO_puts(mem,(const char*)r.ptr()); + while(true) { + X509*cert = PEM_read_bio_X509(mem, NULL, 0, NULL); + if (!cert) + break; + certs.push_back(cert); + } + BIO_free(mem); +} + +void StreamPeerOpenSSL::initialize_ssl() { + + available=true; + + load_certs_func=_load_certs; + + _create=_create_func; + CRYPTO_malloc_init(); // Initialize malloc, free, etc for OpenSSL's use + SSL_library_init(); // Initialize OpenSSL's SSL libraries + SSL_load_error_strings(); // Load SSL error strings + ERR_load_BIO_strings(); // Load BIO error strings + OpenSSL_add_all_algorithms(); // Load all available encryption algorithms + String certs_path =GLOBAL_DEF("ssl/certificates",""); + Globals::get_singleton()->set_custom_property_info("ssl/certificates",PropertyInfo(Variant::STRING,"ssl/certificates",PROPERTY_HINT_FILE,"*.crt")); + if (certs_path!="") { + + + + FileAccess *f=FileAccess::open(certs_path,FileAccess::READ); + if (f) { + ByteArray arr; + int flen = f->get_len(); + arr.resize(flen+1); + { + ByteArray::Write w = arr.write(); + f->get_buffer(w.ptr(),flen); + w[flen]=0; //end f string + } + + memdelete(f); + + _load_certs(arr); + print_line("Loaded certs from '"+certs_path+"': "+itos(certs.size())); + } + } + String config_path =GLOBAL_DEF("ssl/config",""); + Globals::get_singleton()->set_custom_property_info("ssl/config",PropertyInfo(Variant::STRING,"ssl/config",PROPERTY_HINT_FILE,"*.cnf")); + if (config_path!="") { + + Vector<uint8_t> data = FileAccess::get_file_as_array(config_path); + if (data.size()) { + data.push_back(0); + BIO* mem = BIO_new(BIO_s_mem()); + BIO_puts(mem,(const char*) data.ptr()); + + while(true) { + X509*cert = PEM_read_bio_X509(mem, NULL, 0, NULL); + if (!cert) + break; + certs.push_back(cert); + } + BIO_free(mem); + } + print_line("Loaded certs from '"+certs_path+"': "+itos(certs.size())); + + } + +} + +void StreamPeerOpenSSL::finalize_ssl(){ + + for(int i=0;i<certs.size();i++) { + X509_free(certs[i]); + } + certs.clear(); +} diff --git a/modules/openssl/stream_peer_openssl.h b/modules/openssl/stream_peer_openssl.h new file mode 100644 index 0000000000..853ede2036 --- /dev/null +++ b/modules/openssl/stream_peer_openssl.h @@ -0,0 +1,109 @@ +/*************************************************************************/ +/* stream_peer_openssl.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef STREAM_PEER_OPEN_SSL_H +#define STREAM_PEER_OPEN_SSL_H + +#include <stdio.h> // If you don't know what this is for stop reading now. +#include "io/stream_peer_ssl.h" +#include "globals.h" +#include "os/file_access.h" +#include "curl_hostcheck.h" + +#include <openssl/bio.h> // BIO objects for I/O +#include <openssl/ssl.h> // SSL and SSL_CTX for SSL connections +#include <openssl/err.h> // Error reporting +#include <openssl/x509v3.h> + +class StreamPeerOpenSSL : public StreamPeerSSL { +private: + static int _bio_create( BIO *b ); + static int _bio_destroy( BIO *b ); + static int _bio_read( BIO *b, char *buf, int len ); + static int _bio_write( BIO *b, const char *buf, int len ); + static long _bio_ctrl( BIO *b, int cmd, long num, void *ptr ); + static int _bio_gets( BIO *b, char *buf, int len ); + static int _bio_puts( BIO *b, const char *str ); + + static BIO_METHOD _bio_method; + + static bool _match_host_name(const char *name, const char *hostname); + static Error _match_common_name(const char *hostname, const X509 *server_cert); + static Error _match_subject_alternative_name(const char *hostname, const X509 *server_cert); + + + static int _cert_verify_callback(X509_STORE_CTX *x509_ctx, void *arg); + + + Status status; + String hostname; + int max_cert_chain_depth; + SSL_CTX* ctx; + SSL* ssl; + BIO* bio; + bool connected; + int flags; + bool use_blocking; + bool validate_certs; + bool validate_hostname; + + Ref<StreamPeer> base; + + static StreamPeerSSL* _create_func(); + void _print_error(int err); + + static Vector<X509*> certs; + + static void _load_certs(const ByteArray& p_array); +protected: + static void _bind_methods(); +public: + + + virtual Error accept(Ref<StreamPeer> p_base); + virtual Error connect(Ref<StreamPeer> p_base,bool p_validate_certs=false,const String& p_for_hostname=String()); + virtual Status get_status() const; + + virtual void disconnect(); + + virtual Error put_data(const uint8_t* p_data,int p_bytes); + virtual Error put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent); + + virtual Error get_data(uint8_t* p_buffer, int p_bytes); + virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received); + + virtual int get_available_bytes() const; + + static void initialize_ssl(); + static void finalize_ssl(); + + StreamPeerOpenSSL(); + ~StreamPeerOpenSSL(); +}; + +#endif // STREAM_PEER_SSL_H diff --git a/modules/opus/SCsub b/modules/opus/SCsub new file mode 100644 index 0000000000..603f5a48c4 --- /dev/null +++ b/modules/opus/SCsub @@ -0,0 +1,215 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_opus = env_modules.Clone() + +# Thirdparty source files +if (env["opus"] != "system"): # builtin + thirdparty_dir = "#thirdparty/opus/" + + thirdparty_sources = [ + "silk/tables_other.c", + "silk/sum_sqr_shift.c", + "silk/PLC.c", + "silk/dec_API.c", + "silk/decode_pulses.c", + "silk/inner_prod_aligned.c", + "silk/init_encoder.c", + "silk/interpolate.c", + "silk/stereo_encode_pred.c", + "silk/decode_frame.c", + "silk/NLSF_del_dec_quant.c", + "silk/VAD.c", + "silk/resampler_private_AR2.c", + "silk/NLSF_unpack.c", + "silk/resampler_down2.c", + "silk/sort.c", + "silk/resampler_private_IIR_FIR.c", + "silk/resampler_down2_3.c", + "silk/resampler_private_up2_HQ.c", + "silk/tables_gain.c", + "silk/stereo_find_predictor.c", + "silk/stereo_quant_pred.c", + "silk/NLSF_stabilize.c", + "silk/ana_filt_bank_1.c", + "silk/check_control_input.c", + "silk/bwexpander.c", + "silk/A2NLSF.c", + "silk/LPC_inv_pred_gain.c", + "silk/log2lin.c", + "silk/process_NLSFs.c", + "silk/sigm_Q15.c", + "silk/VQ_WMat_EC.c", + "silk/quant_LTP_gains.c", + "silk/resampler_private_down_FIR.c", + "silk/NLSF_decode.c", + "silk/control_codec.c", + "silk/NLSF_VQ_weights_laroia.c", + "silk/decode_pitch.c", + "silk/stereo_decode_pred.c", + "silk/tables_pulses_per_block.c", + "silk/init_decoder.c", + "silk/table_LSF_cos.c", + "silk/decode_core.c", + "silk/code_signs.c", + "silk/enc_API.c", + "silk/tables_LTP.c", + "silk/pitch_est_tables.c", + "silk/biquad_alt.c", + "silk/encode_indices.c", + "silk/tables_NLSF_CB_WB.c", + "silk/debug.c", + "silk/decode_parameters.c", + "silk/tables_pitch_lag.c", + "silk/NLSF2A.c", + "silk/resampler.c", + "silk/decode_indices.c", + "silk/NLSF_VQ.c", + "silk/bwexpander_32.c", + "silk/tables_NLSF_CB_NB_MB.c", + "silk/encode_pulses.c", + "silk/NSQ_del_dec.c", + "silk/control_SNR.c", + "silk/shell_coder.c", + "silk/NLSF_encode.c", + "silk/stereo_MS_to_LR.c", + "silk/stereo_LR_to_MS.c", + "silk/HP_variable_cutoff.c", + "silk/LPC_analysis_filter.c", + "silk/CNG.c", + "silk/decoder_set_fs.c", + "silk/resampler_rom.c", + "silk/control_audio_bandwidth.c", + "silk/lin2log.c", + "silk/LP_variable_cutoff.c", + "silk/NSQ.c", + "silk/gain_quant.c", + "celt/laplace.c", + "celt/vq.c", + "celt/quant_bands.c", + "celt/kiss_fft.c", + "celt/entcode.c", + "celt/entenc.c", + "celt/celt_lpc.c", + "celt/pitch.c", + "celt/rate.c", + "celt/mathops.c", + #"celt/arm/armcpu.c", + #"celt/arm/celt_neon_intr.c", + #"celt/arm/celt_ne10_mdct.c", + #"celt/arm/celt_ne10_fft.c", + #"celt/arm/arm_celt_map.c", + "celt/celt_encoder.c", + "celt/celt.c", + "celt/bands.c", + "celt/cwrs.c", + "celt/entdec.c", + "celt/celt_decoder.c", + "celt/mdct.c", + "celt/modes.c", + "repacketizer.c", + "mlp_data.c", + "opus_multistream.c", + "opusfile.c", + "opus_encoder.c", + "analysis.c", + "mlp.c", + "info.c", + "stream.c", + "opus_decoder.c", + "internal.c", + "wincerts.c", + "opus.c", + "opus_multistream_encoder.c", + "http.c", + "opus_multistream_decoder.c" + ] + + opus_sources_silk = [] + + if("opus_fixed_point" in env and env.opus_fixed_point=="yes"): + env_opus.Append(CFLAGS = ["-DFIXED_POINT"]) + opus_sources_silk = [ + "silk/fixed/schur64_FIX.c", + "silk/fixed/residual_energy16_FIX.c", + "silk/fixed/encode_frame_FIX.c", + "silk/fixed/regularize_correlations_FIX.c", + "silk/fixed/apply_sine_window_FIX.c", + "silk/fixed/solve_LS_FIX.c", + "silk/fixed/schur_FIX.c", + "silk/fixed/pitch_analysis_core_FIX.c", + "silk/fixed/noise_shape_analysis_FIX.c", + "silk/fixed/find_LTP_FIX.c", + "silk/fixed/vector_ops_FIX.c", + "silk/fixed/autocorr_FIX.c", + "silk/fixed/warped_autocorrelation_FIX.c", + "silk/fixed/find_pitch_lags_FIX.c", + "silk/fixed/k2a_Q16_FIX.c", + "silk/fixed/LTP_scale_ctrl_FIX.c", + "silk/fixed/corrMatrix_FIX.c", + "silk/fixed/prefilter_FIX.c", + "silk/fixed/find_LPC_FIX.c", + "silk/fixed/residual_energy_FIX.c", + "silk/fixed/process_gains_FIX.c", + "silk/fixed/LTP_analysis_filter_FIX.c", + "silk/fixed/k2a_FIX.c", + "silk/fixed/burg_modified_FIX.c", + "silk/fixed/find_pred_coefs_FIX.c" + ] + else: + opus_sources_silk = [ + "silk/float/LTP_scale_ctrl_FLP.c", + "silk/float/regularize_correlations_FLP.c", + "silk/float/corrMatrix_FLP.c", + "silk/float/LPC_analysis_filter_FLP.c", + "silk/float/levinsondurbin_FLP.c", + "silk/float/schur_FLP.c", + "silk/float/scale_vector_FLP.c", + "silk/float/apply_sine_window_FLP.c", + "silk/float/pitch_analysis_core_FLP.c", + "silk/float/wrappers_FLP.c", + "silk/float/bwexpander_FLP.c", + "silk/float/warped_autocorrelation_FLP.c", + "silk/float/solve_LS_FLP.c", + "silk/float/find_LPC_FLP.c", + "silk/float/autocorrelation_FLP.c", + "silk/float/find_pred_coefs_FLP.c", + "silk/float/find_pitch_lags_FLP.c", + "silk/float/burg_modified_FLP.c", + "silk/float/find_LTP_FLP.c", + "silk/float/energy_FLP.c", + "silk/float/sort_FLP.c", + "silk/float/LPC_inv_pred_gain_FLP.c", + "silk/float/k2a_FLP.c", + "silk/float/noise_shape_analysis_FLP.c", + "silk/float/inner_product_FLP.c", + "silk/float/process_gains_FLP.c", + "silk/float/encode_frame_FLP.c", + "silk/float/scale_copy_vector_FLP.c", + "silk/float/residual_energy_FLP.c", + "silk/float/LTP_analysis_filter_FLP.c", + "silk/float/prefilter_FLP.c" + ] + + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources + opus_sources_silk] + + env_opus.add_source_files(env.modules_sources, thirdparty_sources) + env_opus.Append(CFLAGS=["-DHAVE_CONFIG_H"]) + + thirdparty_include_paths = [ + "", + "celt", + "silk", + "silk/fixed", + "silk/float", + ] + env_opus.Append(CPPPATH = [thirdparty_dir + "/" + dir for dir in thirdparty_include_paths]) + + # also requires libogg + if (env["libogg"] != "system"): # builtin + env_opus.Append(CPPPATH = ["#thirdparty/libogg"]) + +# Module files +env_opus.add_source_files(env.modules_sources, "*.cpp") diff --git a/drivers/opus/audio_stream_opus.cpp b/modules/opus/audio_stream_opus.cpp index ab53fee0c9..ab53fee0c9 100644 --- a/drivers/opus/audio_stream_opus.cpp +++ b/modules/opus/audio_stream_opus.cpp diff --git a/modules/opus/audio_stream_opus.h b/modules/opus/audio_stream_opus.h new file mode 100644 index 0000000000..4da66fe167 --- /dev/null +++ b/modules/opus/audio_stream_opus.h @@ -0,0 +1,141 @@ +/*************************************************************************/ +/* audio_stream_opus.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Author: George Marques <george@gmarqu.es> */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef AUDIO_STREAM_OPUS_H +#define AUDIO_STREAM_OPUS_H + +#include "io/resource_loader.h" +#include "os/file_access.h" +#include "scene/resources/audio_stream.h" + +#include <opusfile.h> + +class AudioStreamPlaybackOpus : public AudioStreamPlayback { + + OBJ_TYPE(AudioStreamPlaybackOpus,AudioStreamPlayback) + + enum { + MIN_MIX=1024 + }; + + FileAccess *f; + + OpusFileCallbacks _op_callbacks; + float length; + static int _op_read_func(void *_stream, unsigned char *_ptr, int _nbytes); + static int _op_seek_func(void *_stream, opus_int64 _offset, int _whence); + static int _op_close_func(void *_stream); + static opus_int64 _op_tell_func(void *_stream); + static const float osrate; + + String file; + int64_t frames_mixed; + + bool stream_loaded; + volatile bool playing; + OggOpusFile *opus_file; + int stream_channels; + int current_section; + int pre_skip; + + bool paused; + bool loops; + int repeats; + + Error _load_stream(); + void _clear_stream(); + void _close_file(); + + bool stream_valid; + float loop_restart_time; + +public: + Error set_file(const String& p_file); + + virtual void play(float p_from=0); + virtual void stop(); + virtual bool is_playing() const { return playing; } + + virtual void set_loop_restart_time(float p_time) { loop_restart_time=p_time; } + + virtual void set_paused(bool p_paused) { paused=p_paused; } + virtual bool is_paused() const { return paused; } + + virtual void set_loop(bool p_enable) { loops=p_enable; } + virtual bool has_loop() const {return loops; } + + virtual float get_length() const; + + virtual String get_stream_name() const { return ""; } + + virtual int get_loop_count() const { return repeats; } + + virtual float get_pos() const; + virtual void seek_pos(float p_time); + + virtual int get_channels() const { return stream_channels; } + virtual int get_mix_rate() const { return osrate; } + + virtual int get_minimum_buffer_size() const; + + virtual int mix(int16_t* p_bufer,int p_frames); + + AudioStreamPlaybackOpus(); + ~AudioStreamPlaybackOpus(); +}; + + +class AudioStreamOpus: public AudioStream { + + OBJ_TYPE(AudioStreamOpus,AudioStream) + + String file; +public: + + Ref<AudioStreamPlayback> instance_playback() { + Ref<AudioStreamPlaybackOpus> pb = memnew( AudioStreamPlaybackOpus ); + pb->set_file(file); + return pb; + } + + void set_file(const String& p_file) { file=p_file; } + +}; + +class ResourceFormatLoaderAudioStreamOpus: public ResourceFormatLoader { +public: + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String& p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + +#endif // AUDIO_STREAM_OPUS_H diff --git a/modules/opus/config.py b/modules/opus/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/opus/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/modules/opus/register_types.cpp b/modules/opus/register_types.cpp new file mode 100644 index 0000000000..a4d71a52c7 --- /dev/null +++ b/modules/opus/register_types.cpp @@ -0,0 +1,45 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#include "audio_stream_opus.h" + +static ResourceFormatLoaderAudioStreamOpus *opus_stream_loader = NULL; + +void register_opus_types() { + + opus_stream_loader = memnew( ResourceFormatLoaderAudioStreamOpus ); + ResourceLoader::add_resource_format_loader(opus_stream_loader); + ObjectTypeDB::register_type<AudioStreamOpus>(); +} + +void unregister_opus_types() { + + memdelete( opus_stream_loader ); +} diff --git a/modules/opus/register_types.h b/modules/opus/register_types.h new file mode 100644 index 0000000000..f4386c373a --- /dev/null +++ b/modules/opus/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_opus_types(); +void unregister_opus_types(); diff --git a/modules/pbm/SCsub b/modules/pbm/SCsub new file mode 100644 index 0000000000..fa328be025 --- /dev/null +++ b/modules/pbm/SCsub @@ -0,0 +1,8 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_pbm = env_modules.Clone() + +env_pbm.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/pbm/bitmap_loader_pbm.cpp b/modules/pbm/bitmap_loader_pbm.cpp new file mode 100644 index 0000000000..1d08b10824 --- /dev/null +++ b/modules/pbm/bitmap_loader_pbm.cpp @@ -0,0 +1,252 @@ +/*************************************************************************/ +/* bitmap_loader_pbm.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "bitmap_loader_pbm.h" +#include "os/file_access.h" +#include "scene/resources/bit_mask.h" + + +static bool _get_token(FileAccessRef& f,uint8_t &saved,DVector<uint8_t>& r_token,bool p_binary=false,bool p_single_chunk=false) { + + + int token_max = r_token.size(); + DVector<uint8_t>::Write w; + if (token_max) + w=r_token.write(); + int ofs=0; + bool lf=false; + + + while(true) { + + uint8_t b; + if (saved) { + b=saved; + saved=0; + } else { + b = f->get_8(); + } + if (f->eof_reached()) { + if (ofs) { + w=DVector<uint8_t>::Write(); + r_token.resize(ofs); + return true; + } else { + return false; + } + } + + if (!ofs && !p_binary && b=='#') { + //skip comment + while(b!='\n') { + if (f->eof_reached()) { + return false; + } + + b = f->get_8(); + } + + lf=true; + + } else if (b<=32 && !(p_binary && (ofs || lf))) { + + if (b=='\n') { + lf=true; + } + + + if (ofs && !p_single_chunk) { + w=DVector<uint8_t>::Write(); + r_token.resize(ofs); + saved=b; + + return true; + } + } else { + + bool resized=false; + while (ofs>=token_max) { + if (token_max) + token_max<<=1; + else + token_max=1; + resized=true; + } + if (resized) { + w=DVector<uint8_t>::Write(); + r_token.resize(token_max); + w=r_token.write(); + } + w[ofs++]=b; + } + } + + return false; +} + +static int _get_number_from_token(DVector<uint8_t>& r_token) { + + int len = r_token.size(); + DVector<uint8_t>::Read r = r_token.read(); + return String::to_int((const char*)r.ptr(),len); + +} + + +RES ResourceFormatPBM::load(const String &p_path,const String& p_original_path,Error *r_error) { + +#define _RETURN(m_err)\ +{\ + if (r_error)\ + *r_error=m_err;\ + ERR_FAIL_V(RES());\ +} + + + FileAccessRef f=FileAccess::open(p_path,FileAccess::READ); + uint8_t saved=0; + if (!f) + _RETURN(ERR_CANT_OPEN); + + DVector<uint8_t> token; + + if (!_get_token(f,saved,token)) { + _RETURN(ERR_PARSE_ERROR); + } + + if (token.size()!=2) { + _RETURN(ERR_FILE_CORRUPT); + } + if (token[0]!='P') { + _RETURN(ERR_FILE_CORRUPT); + } + if (token[1]!='1' && token[1]!='4') { + _RETURN(ERR_FILE_CORRUPT); + } + + bool bits = token[1]=='4'; + + if (!_get_token(f,saved,token)) { + _RETURN(ERR_PARSE_ERROR); + } + + int width = _get_number_from_token(token); + if (width<=0) { + _RETURN(ERR_FILE_CORRUPT); + } + + + if (!_get_token(f,saved,token)) { + _RETURN(ERR_PARSE_ERROR); + } + + int height = _get_number_from_token(token); + if (height<=0) { + _RETURN(ERR_FILE_CORRUPT); + } + + + Ref<BitMap> bm; + bm.instance(); + bm->create(Size2i(width,height)); + + if (!bits) { + + int required_bytes = width*height; + if (!_get_token(f,saved,token,false,true)) { + _RETURN(ERR_PARSE_ERROR); + } + + if (token.size()<required_bytes) { + _RETURN(ERR_FILE_CORRUPT); + } + + DVector<uint8_t>::Read r=token.read(); + + for(int i=0;i<height;i++) { + for(int j=0;j<width;j++) { + + + char num = r[i*width+j]; + bm->set_bit(Point2i(j,i),num=='0'); + } + + } + + + + } else { + //a single, entire token of bits! + if (!_get_token(f,saved,token,true)) { + _RETURN(ERR_PARSE_ERROR); + } + int required_bytes = Math::ceil((width*height)/8.0); + if (token.size()<required_bytes) { + _RETURN(ERR_FILE_CORRUPT); + } + + DVector<uint8_t>::Read r=token.read(); + int bitwidth = width; + if (bitwidth % 8) + bitwidth+=8-(bitwidth%8); + + for(int i=0;i<height;i++) { + for(int j=0;j<width;j++) { + + int ofs = bitwidth*i+j; + + uint8_t byte = r[ofs/8]; + bool bit = (byte>>(7-(ofs%8)))&1; + + bm->set_bit(Point2i(j,i),!bit); + + } + + } + + } + + return bm; + + +} + +void ResourceFormatPBM::get_recognized_extensions(List<String> *p_extensions) const { + p_extensions->push_back("pbm"); +} +bool ResourceFormatPBM::handles_type(const String& p_type) const { + return p_type=="BitMap"; +} +String ResourceFormatPBM::get_resource_type(const String &p_path) const { + + if (p_path.extension().to_lower()=="pbm") + return "BitMap"; + return ""; +} + + diff --git a/modules/pbm/bitmap_loader_pbm.h b/modules/pbm/bitmap_loader_pbm.h new file mode 100644 index 0000000000..4f7144b3e0 --- /dev/null +++ b/modules/pbm/bitmap_loader_pbm.h @@ -0,0 +1,50 @@ +/*************************************************************************/ +/* bitmap_loader_pbm.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef BITMAP_LOADER_PBM_H +#define BITMAP_LOADER_PBM_H + +#include "io/resource_loader.h" + +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ +class ResourceFormatPBM : public ResourceFormatLoader { + + +public: + + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String& p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + + + +#endif diff --git a/modules/pbm/config.py b/modules/pbm/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/pbm/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/modules/pbm/register_types.cpp b/modules/pbm/register_types.cpp new file mode 100644 index 0000000000..181083773a --- /dev/null +++ b/modules/pbm/register_types.cpp @@ -0,0 +1,44 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#include "bitmap_loader_pbm.h" + +static ResourceFormatPBM * pbm_loader = NULL; + +void register_pbm_types() { + + pbm_loader = memnew( ResourceFormatPBM ); + ResourceLoader::add_resource_format_loader(pbm_loader); +} + +void unregister_pbm_types() { + + memdelete( pbm_loader ); +} diff --git a/modules/pbm/register_types.h b/modules/pbm/register_types.h new file mode 100644 index 0000000000..20c8133c2c --- /dev/null +++ b/modules/pbm/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_pbm_types(); +void unregister_pbm_types(); diff --git a/modules/pvr/SCsub b/modules/pvr/SCsub new file mode 100644 index 0000000000..4ead52f82f --- /dev/null +++ b/modules/pvr/SCsub @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_pvr = env_modules.Clone() + +# Thirdparty source files +# Not unbundled so far since not widespread as shared library +thirdparty_dir = "#thirdparty/pvrtccompressor/" +thirdparty_sources = [ + "BitScale.cpp", + "MortonTable.cpp", + "PvrTcDecoder.cpp", + "PvrTcEncoder.cpp", + "PvrTcPacket.cpp", +] +thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + +env_pvr.add_source_files(env.modules_sources, thirdparty_sources) +env_pvr.Append(CPPPATH = [thirdparty_dir]) + +# Godot source files +env_pvr.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/pvr/config.py b/modules/pvr/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/pvr/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/modules/pvr/register_types.cpp b/modules/pvr/register_types.cpp new file mode 100644 index 0000000000..e5e18fb3d1 --- /dev/null +++ b/modules/pvr/register_types.cpp @@ -0,0 +1,44 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#include "texture_loader_pvr.h" + +static ResourceFormatPVR *resource_loader_pvr = NULL; + +void register_pvr_types() { + + resource_loader_pvr = memnew( ResourceFormatPVR ); + ResourceLoader::add_resource_format_loader(resource_loader_pvr); +} + +void unregister_pvr_types() { + + memdelete(resource_loader_pvr); +} diff --git a/modules/pvr/register_types.h b/modules/pvr/register_types.h new file mode 100644 index 0000000000..d600f54d51 --- /dev/null +++ b/modules/pvr/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_pvr_types(); +void unregister_pvr_types(); diff --git a/drivers/pvr/texture_loader_pvr.cpp b/modules/pvr/texture_loader_pvr.cpp index 3ab3240512..3ab3240512 100644 --- a/drivers/pvr/texture_loader_pvr.cpp +++ b/modules/pvr/texture_loader_pvr.cpp diff --git a/drivers/pvr/texture_loader_pvr.h b/modules/pvr/texture_loader_pvr.h index 5efb3b2507..5efb3b2507 100644 --- a/drivers/pvr/texture_loader_pvr.h +++ b/modules/pvr/texture_loader_pvr.h diff --git a/modules/squish/SCsub b/modules/squish/SCsub new file mode 100644 index 0000000000..3fdc587652 --- /dev/null +++ b/modules/squish/SCsub @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_squish = env_modules.Clone() + +# Thirdparty source files +if (env["squish"] != "system"): # builtin + thirdparty_dir = "#thirdparty/squish/" + thirdparty_sources = [ + "alpha.cpp", + "clusterfit.cpp", + "colourblock.cpp", + "colourfit.cpp", + "colourset.cpp", + "maths.cpp", + "rangefit.cpp", + "singlecolourfit.cpp", + "squish.cpp", + ] + + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + + env_squish.add_source_files(env.modules_sources, thirdparty_sources) + env_squish.Append(CPPPATH = [thirdparty_dir]) + +# Godot source files +env_squish.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/squish/config.py b/modules/squish/config.py new file mode 100644 index 0000000000..d28d9c702e --- /dev/null +++ b/modules/squish/config.py @@ -0,0 +1,10 @@ + +def can_build(platform): + return True + +def configure(env): + # Tools only, disabled for non-tools + # TODO: Find a cleaner way to achieve that + if (env["tools"] == "no"): + env["module_squish_enabled"] = "no" + env.disabled_modules.append("squish") diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp new file mode 100644 index 0000000000..ac7c935ceb --- /dev/null +++ b/modules/squish/image_compress_squish.cpp @@ -0,0 +1,92 @@ +/*************************************************************************/ +/* image_compress_squish.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "image_compress_squish.h" + +#include "print_string.h" + +#include <squish.h> + +void image_compress_squish(Image *p_image) { + + int w=p_image->get_width(); + int h=p_image->get_height(); + + if (p_image->get_mipmaps() == 0) { + ERR_FAIL_COND( !w || w % 4 != 0); + ERR_FAIL_COND( !h || h % 4 != 0); + } else { + ERR_FAIL_COND( !w || w !=nearest_power_of_2(w) ); + ERR_FAIL_COND( !h || h !=nearest_power_of_2(h) ); + }; + + if (p_image->get_format()>=Image::FORMAT_BC1) + return; //do not compress, already compressed + + int shift=0; + int squish_comp=squish::kColourRangeFit; + Image::Format target_format; + + if (p_image->get_format()==Image::FORMAT_GRAYSCALE_ALPHA) { + //compressed normalmap + target_format = Image::FORMAT_BC3; squish_comp|=squish::kDxt5;; + } else if (p_image->detect_alpha()!=Image::ALPHA_NONE) { + + target_format = Image::FORMAT_BC2; squish_comp|=squish::kDxt3;; + } else { + target_format = Image::FORMAT_BC1; shift=1; squish_comp|=squish::kDxt1;; + } + + p_image->convert(Image::FORMAT_RGBA); //always expects rgba + + int mm_count = p_image->get_mipmaps(); + + DVector<uint8_t> data; + int target_size = Image::get_image_data_size(w,h,target_format,mm_count); + data.resize(target_size); + + DVector<uint8_t>::Read rb = p_image->get_data().read(); + DVector<uint8_t>::Write wb = data.write(); + + int dst_ofs=0; + + for(int i=0;i<=mm_count;i++) { + + int src_ofs = p_image->get_mipmap_offset(i); + squish::CompressImage( &rb[src_ofs],w,h,&wb[dst_ofs],squish_comp); + dst_ofs+=(MAX(4,w)*MAX(4,h))>>shift; + w>>=1; + h>>=1; + } + + rb = DVector<uint8_t>::Read(); + wb = DVector<uint8_t>::Write(); + + p_image->create(p_image->get_width(),p_image->get_height(),p_image->get_mipmaps(),target_format,data); + +} diff --git a/modules/squish/image_compress_squish.h b/modules/squish/image_compress_squish.h new file mode 100644 index 0000000000..19dd900674 --- /dev/null +++ b/modules/squish/image_compress_squish.h @@ -0,0 +1,36 @@ +/*************************************************************************/ +/* image_compress_squish.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef IMAGE_COMPRESS_SQUISH_H +#define IMAGE_COMPRESS_SQUISH_H + +#include "image.h" + +void image_compress_squish(Image *p_image); + +#endif // IMAGE_COMPRESS_SQUISH_H diff --git a/modules/squish/register_types.cpp b/modules/squish/register_types.cpp new file mode 100644 index 0000000000..9e9621eb64 --- /dev/null +++ b/modules/squish/register_types.cpp @@ -0,0 +1,42 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#ifdef TOOLS_ENABLED + +#include "image_compress_squish.h" + +void register_squish_types() { + + Image::set_compress_bc_func(image_compress_squish); +} + +void unregister_squish_types() {} + +#endif diff --git a/modules/squish/register_types.h b/modules/squish/register_types.h new file mode 100644 index 0000000000..bbde6a44bf --- /dev/null +++ b/modules/squish/register_types.h @@ -0,0 +1,32 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifdef TOOLS_ENABLED +void register_squish_types(); +void unregister_squish_types(); +#endif diff --git a/modules/theora/SCsub b/modules/theora/SCsub new file mode 100644 index 0000000000..22c618fe8b --- /dev/null +++ b/modules/theora/SCsub @@ -0,0 +1,83 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_theora = env_modules.Clone() + +# Thirdparty source files +if (env["libtheora"] != "system"): # builtin + thirdparty_dir = "#thirdparty/libtheora/" + thirdparty_sources = [ + #"analyze.c", + #"apiwrapper.c", + "bitpack.c", + "cpu.c", + #"decapiwrapper.c", + "decinfo.c", + "decode.c", + "dequant.c", + #"encapiwrapper.c", + #"encfrag.c", + #"encinfo.c", + #"encode.c", + #"encoder_disabled.c", + #"enquant.c", + #"fdct.c", + "fragment.c", + "huffdec.c", + #"huffenc.c", + "idct.c", + "info.c", + "internal.c", + #"mathops.c", + #"mcenc.c", + "quant.c", + #"rate.c", + "state.c", + #"tokenize.c", + ] + + thirdparty_sources_x86 = [ + #"x86/mmxencfrag.c", + #"x86/mmxfdct.c", + "x86/mmxfrag.c", + "x86/mmxidct.c", + "x86/mmxstate.c", + #"x86/sse2fdct.c", + #"x86/x86enc.c", + "x86/x86state.c", + ] + + thirdparty_sources_x86_vc = [ + #"x86_vc/mmxencfrag.c", + #"x86_vc/mmxfdct.c", + "x86_vc/mmxfrag.c", + "x86_vc/mmxidct.c", + "x86_vc/mmxstate.c", + #"x86_vc/x86enc.c", + "x86_vc/x86state.c", + ] + + if (env["x86_libtheora_opt_gcc"]): + thirdparty_sources += thirdparty_sources_x86 + + if (env["x86_libtheora_opt_vc"]): + thirdparty_sources += thirdparty_sources_x86_vc + + if (env["x86_libtheora_opt_gcc"] or env["x86_libtheora_opt_vc"]): + env_theora.Append(CCFLAGS = ["-DOC_X86_ASM"]) + + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + + env_theora.add_source_files(env.modules_sources, thirdparty_sources) + env_theora.Append(CPPPATH = [thirdparty_dir]) + + # also requires libogg and libvorbis + if (env["libogg"] != "system"): # builtin + env_theora.Append(CPPPATH = ["#thirdparty/libogg"]) + if (env["libvorbis"] != "system"): # builtin + env_theora.Append(CPPPATH = ["#thirdparty/libvorbis"]) + +# Godot source files +env_theora.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/theora/config.py b/modules/theora/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/theora/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/modules/theora/register_types.cpp b/modules/theora/register_types.cpp new file mode 100644 index 0000000000..282b59b0ec --- /dev/null +++ b/modules/theora/register_types.cpp @@ -0,0 +1,45 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#include "video_stream_theora.h" + +static ResourceFormatLoaderVideoStreamTheora* theora_stream_loader = NULL; + +void register_theora_types() { + + theora_stream_loader = memnew( ResourceFormatLoaderVideoStreamTheora ); + ResourceLoader::add_resource_format_loader(theora_stream_loader); + ObjectTypeDB::register_type<VideoStreamTheora>(); +} + +void unregister_theora_types() { + + memdelete( theora_stream_loader ); +} diff --git a/modules/theora/register_types.h b/modules/theora/register_types.h new file mode 100644 index 0000000000..18bdbf0c4c --- /dev/null +++ b/modules/theora/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_theora_types(); +void unregister_theora_types(); diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp new file mode 100644 index 0000000000..3ddfee3a1d --- /dev/null +++ b/modules/theora/video_stream_theora.cpp @@ -0,0 +1,940 @@ +/*************************************************************************/ +/* video_stream_theora.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "video_stream_theora.h" + +#include "globals.h" +#include "os/os.h" +#include "yuv2rgb.h" + +int VideoStreamPlaybackTheora:: buffer_data() { + + char *buffer=ogg_sync_buffer(&oy,4096); + +#ifdef THEORA_USE_THREAD_STREAMING + + int read; + + do { + thread_sem->post(); + read = MIN(ring_buffer.data_left(),4096); + if (read) { + ring_buffer.read((uint8_t*)buffer,read); + ogg_sync_wrote(&oy,read); + } else { + OS::get_singleton()->delay_usec(100); + } + + } while(read==0); + + return read; + +#else + + int bytes=file->get_buffer((uint8_t*)buffer, 4096); + ogg_sync_wrote(&oy,bytes); + return(bytes); + +#endif +} + +int VideoStreamPlaybackTheora::queue_page(ogg_page *page){ + if(theora_p) { + ogg_stream_pagein(&to,page); + if (to.e_o_s) + theora_eos=true; + } + if(vorbis_p) { + ogg_stream_pagein(&vo,page); + if (vo.e_o_s) + vorbis_eos=true; + } + return 0; +} + +void VideoStreamPlaybackTheora::video_write(void){ + th_ycbcr_buffer yuv; + th_decode_ycbcr_out(td,yuv); + + /* + int y_offset, uv_offset; + y_offset=(ti.pic_x&~1)+yuv[0].stride*(ti.pic_y&~1); + + { + int pixels = size.x * size.y; + frame_data.resize(pixels * 4); + DVector<uint8_t>::Write w = frame_data.write(); + char* dst = (char*)w.ptr(); + int p = 0; + for (int i=0; i<size.y; i++) { + + char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; + char *out = dst + (int)size.x * 4 * i; + for (int j=0;j<size.x;j++) { + + dst[p++] = in_y[j]; + dst[p++] = in_y[j]; + dst[p++] = in_y[j]; + dst[p++] = 255; + }; + } + format = Image::FORMAT_RGBA; + } + // */ + + //* + + int pitch = 4; + frame_data.resize(size.x * size.y * pitch); + { + DVector<uint8_t>::Write w = frame_data.write(); + char* dst = (char*)w.ptr(); + + //uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y/2); + + if (px_fmt == TH_PF_444) { + + yuv444_2_rgb8888((uint8_t*)dst, (uint8_t*)yuv[0].data, (uint8_t*)yuv[1].data, (uint8_t*)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x<<2, 0); + + } else if (px_fmt == TH_PF_422) { + + yuv422_2_rgb8888((uint8_t*)dst, (uint8_t*)yuv[0].data, (uint8_t*)yuv[1].data, (uint8_t*)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x<<2, 0); + + } else if (px_fmt == TH_PF_420) { + + yuv420_2_rgb8888((uint8_t*)dst, (uint8_t*)yuv[0].data, (uint8_t*)yuv[2].data, (uint8_t*)yuv[1].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x<<2, 0); + }; + + format = Image::FORMAT_RGBA; + } + + Image img(size.x,size.y,0,Image::FORMAT_RGBA,frame_data); //zero copy image creation + + texture->set_data(img); //zero copy send to visual server + + /* + + if (px_fmt == TH_PF_444) { + + int pitch = 3; + frame_data.resize(size.x * size.y * pitch); + DVector<uint8_t>::Write w = frame_data.write(); + char* dst = (char*)w.ptr(); + + for(int i=0;i<size.y;i++) { + + char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; + char *out = dst + (int)size.x * pitch * i; + char *in_u = (char *)yuv[1].data+uv_offset+yuv[1].stride*i; + char *in_v = (char *)yuv[2].data+uv_offset+yuv[2].stride*i; + for (int j=0;j<size.x;j++) { + + out[j*3+0] = in_y[j]; + out[j*3+1] = in_u[j]; + out[j*3+2] = in_v[j]; + }; + } + + format = Image::FORMAT_YUV_444; + + } else { + + int div; + if (px_fmt!=TH_PF_422) { + div = 2; + } + + bool rgba = true; + if (rgba) { + + int pitch = 4; + frame_data.resize(size.x * size.y * pitch); + DVector<uint8_t>::Write w = frame_data.write(); + char* dst = (char*)w.ptr(); + + uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y / div); + for(int i=0;i<size.y;i++) { + char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; + char *in_u = (char *)yuv[1].data+uv_offset+yuv[1].stride*(i/div); + char *in_v = (char *)yuv[2].data+uv_offset+yuv[2].stride*(i/div); + uint8_t *out = (uint8_t*)dst + (int)size.x * pitch * i; + int ofs = 0; + for (int j=0;j<size.x;j++) { + + uint8_t y, u, v; + y = in_y[j]; + u = in_u[j/2]; + v = in_v[j/2]; + + int32_t r = Math::fast_ftoi(1.164 * (y - 16) + 1.596 * (v - 128)); + int32_t g = Math::fast_ftoi(1.164 * (y - 16) - 0.813 * (v - 128) - 0.391 * (u - 128)); + int32_t b = Math::fast_ftoi(1.164 * (y - 16) + 2.018 * (u - 128)); + + out[ofs++] = CLAMP(r, 0, 255); + out[ofs++] = CLAMP(g, 0, 255); + out[ofs++] = CLAMP(b, 0, 255); + out[ofs++] = 255; + } + } + + format = Image::FORMAT_RGBA; + + } else { + + int pitch = 2; + frame_data.resize(size.x * size.y * pitch); + DVector<uint8_t>::Write w = frame_data.write(); + char* dst = (char*)w.ptr(); + + uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y / div); + for(int i=0;i<size.y;i++) { + char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; + char *out = dst + (int)size.x * pitch * i; + for (int j=0;j<size.x;j++) + out[j*2] = in_y[j]; + char *in_u = (char *)yuv[1].data+uv_offset+yuv[1].stride*(i/div); + char *in_v = (char *)yuv[2].data+uv_offset+yuv[2].stride*(i/div); + for (int j=0;j<(int)size.x>>1;j++) { + out[j*4+1] = in_u[j]; + out[j*4+3] = in_v[j]; + } + } + + format = Image::FORMAT_YUV_422; + }; + }; + // */ + + frames_pending = 1; +} + +void VideoStreamPlaybackTheora::clear() { + + if (!file) + return; + + if(vorbis_p){ + ogg_stream_clear(&vo); + if (vorbis_p >= 3) { + vorbis_block_clear(&vb); + vorbis_dsp_clear(&vd); + }; + vorbis_comment_clear(&vc); + vorbis_info_clear(&vi); + vorbis_p = 0; + } + if(theora_p){ + ogg_stream_clear(&to); + th_decode_free(td); + th_comment_clear(&tc); + th_info_clear(&ti); + theora_p = 0; + } + ogg_sync_clear(&oy); + +#ifdef THEORA_USE_THREAD_STREAMING + thread_exit=true; + thread_sem->post(); //just in case + Thread::wait_to_finish(thread); + memdelete(thread); + thread=NULL; + ring_buffer.clear(); +#endif + //file_name = ""; + + theora_p = 0; + vorbis_p = 0; + videobuf_ready = 0; + frames_pending = 0; + videobuf_time = 0; + theora_eos=false; + vorbis_eos=false; + + if (file) { + memdelete(file); + } + file=NULL; + playing = false; +}; + +void VideoStreamPlaybackTheora::set_file(const String& p_file) { + + ERR_FAIL_COND(playing); + ogg_packet op; + th_setup_info *ts = NULL; + + file_name = p_file; + if (file) { + memdelete(file); + } + file = FileAccess::open(p_file, FileAccess::READ); + ERR_FAIL_COND(!file); + +#ifdef THEORA_USE_THREAD_STREAMING + thread_exit=false; + thread_eof=false; + //pre-fill buffer + int to_read = ring_buffer.space_left(); + int read = file->get_buffer(read_buffer.ptr(),to_read); + ring_buffer.write(read_buffer.ptr(),read); + + thread=Thread::create(_streaming_thread,this); + +#endif + + ogg_sync_init(&oy); + + /* init supporting Vorbis structures needed in header parsing */ + vorbis_info_init(&vi); + vorbis_comment_init(&vc); + + /* init supporting Theora structures needed in header parsing */ + th_comment_init(&tc); + th_info_init(&ti); + + theora_eos=false; + vorbis_eos=false; + + /* Ogg file open; parse the headers */ + /* Only interested in Vorbis/Theora streams */ + int stateflag = 0; + + int audio_track_skip=audio_track; + + + while(!stateflag){ + int ret=buffer_data(); + if(ret==0)break; + while(ogg_sync_pageout(&oy,&og)>0){ + ogg_stream_state test; + + /* is this a mandated initial header? If not, stop parsing */ + if(!ogg_page_bos(&og)){ + /* don't leak the page; get it into the appropriate stream */ + queue_page(&og); + stateflag=1; + break; + } + + ogg_stream_init(&test,ogg_page_serialno(&og)); + ogg_stream_pagein(&test,&og); + ogg_stream_packetout(&test,&op); + + + /* identify the codec: try theora */ + if(!theora_p && th_decode_headerin(&ti,&tc,&ts,&op)>=0){ + /* it is theora */ + copymem(&to,&test,sizeof(test)); + theora_p=1; + }else if(!vorbis_p && vorbis_synthesis_headerin(&vi,&vc,&op)>=0){ + + + /* it is vorbis */ + if (audio_track_skip) { + vorbis_info_clear(&vi); + vorbis_comment_clear(&vc); + ogg_stream_clear(&test); + vorbis_info_init(&vi); + vorbis_comment_init(&vc); + + audio_track_skip--; + } else { + copymem(&vo,&test,sizeof(test)); + vorbis_p=1; + } + }else{ + /* whatever it is, we don't care about it */ + ogg_stream_clear(&test); + } + } + /* fall through to non-bos page parsing */ + } + + /* we're expecting more header packets. */ + while((theora_p && theora_p<3) || (vorbis_p && vorbis_p<3)){ + int ret; + + /* look for further theora headers */ + while(theora_p && (theora_p<3) && (ret=ogg_stream_packetout(&to,&op))){ + if(ret<0){ + fprintf(stderr,"Error parsing Theora stream headers; " + "corrupt stream?\n"); + clear(); + return; + } + if(!th_decode_headerin(&ti,&tc,&ts,&op)){ + fprintf(stderr,"Error parsing Theora stream headers; " + "corrupt stream?\n"); + clear(); + return; + } + theora_p++; + } + + /* look for more vorbis header packets */ + while(vorbis_p && (vorbis_p<3) && (ret=ogg_stream_packetout(&vo,&op))){ + if(ret<0){ + fprintf(stderr,"Error parsing Vorbis stream headers; corrupt stream?\n"); + clear(); + return; + } + ret = vorbis_synthesis_headerin(&vi,&vc,&op); + if(ret){ + fprintf(stderr,"Error parsing Vorbis stream headers; corrupt stream?\n"); + clear(); + return; + } + vorbis_p++; + if(vorbis_p==3)break; + } + + /* The header pages/packets will arrive before anything else we + care about, or the stream is not obeying spec */ + + if(ogg_sync_pageout(&oy,&og)>0){ + queue_page(&og); /* demux into the appropriate stream */ + }else{ + int ret=buffer_data(); /* someone needs more data */ + if(ret==0){ + fprintf(stderr,"End of file while searching for codec headers.\n"); + clear(); + return; + } + } + } + + /* and now we have it all. initialize decoders */ + if(theora_p){ + td=th_decode_alloc(&ti,ts); + printf("Ogg logical stream %lx is Theora %dx%d %.02f fps", + to.serialno,ti.pic_width,ti.pic_height, + (double)ti.fps_numerator/ti.fps_denominator); + px_fmt=ti.pixel_fmt; + switch(ti.pixel_fmt){ + case TH_PF_420: printf(" 4:2:0 video\n"); break; + case TH_PF_422: printf(" 4:2:2 video\n"); break; + case TH_PF_444: printf(" 4:4:4 video\n"); break; + case TH_PF_RSVD: + default: + printf(" video\n (UNKNOWN Chroma sampling!)\n"); + break; + } + if(ti.pic_width!=ti.frame_width || ti.pic_height!=ti.frame_height) + printf(" Frame content is %dx%d with offset (%d,%d).\n", + ti.frame_width, ti.frame_height, ti.pic_x, ti.pic_y); + th_decode_ctl(td,TH_DECCTL_GET_PPLEVEL_MAX,&pp_level_max, + sizeof(pp_level_max)); + pp_level=pp_level_max; + pp_level=0; + th_decode_ctl(td,TH_DECCTL_SET_PPLEVEL,&pp_level,sizeof(pp_level)); + pp_inc=0; + + /*{ + int arg = 0xffff; + th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_MBMODE,&arg,sizeof(arg)); + th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_MV,&arg,sizeof(arg)); + th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_QI,&arg,sizeof(arg)); + arg=10; + th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_BITS,&arg,sizeof(arg)); + }*/ + + int w; + int h; + w=(ti.pic_x+ti.frame_width+1&~1)-(ti.pic_x&~1); + h=(ti.pic_y+ti.frame_height+1&~1)-(ti.pic_y&~1); + size.x = w; + size.y = h; + + texture->create(w,h,Image::FORMAT_RGBA,Texture::FLAG_FILTER|Texture::FLAG_VIDEO_SURFACE); + + }else{ + /* tear down the partial theora setup */ + th_info_clear(&ti); + th_comment_clear(&tc); + } + + th_setup_free(ts); + + if(vorbis_p){ + vorbis_synthesis_init(&vd,&vi); + vorbis_block_init(&vd,&vb); + fprintf(stderr,"Ogg logical stream %lx is Vorbis %d channel %ld Hz audio.\n", + vo.serialno,vi.channels,vi.rate); + //_setup(vi.channels, vi.rate); + + }else{ + /* tear down the partial vorbis setup */ + vorbis_info_clear(&vi); + vorbis_comment_clear(&vc); + } + + playing = false; + buffering=true; + time=0; + audio_frames_wrote=0; + + +}; + +float VideoStreamPlaybackTheora::get_time() const { + + //print_line("total: "+itos(get_total())+" todo: "+itos(get_todo())); + //return MAX(0,time-((get_total())/(float)vi.rate)); + return time-AudioServer::get_singleton()->get_output_delay()-delay_compensation;//-((get_total())/(float)vi.rate); +}; + +Ref<Texture> VideoStreamPlaybackTheora::get_texture() { + + return texture; +} + +void VideoStreamPlaybackTheora::update(float p_delta) { + + if (!file) + return; + + if (!playing || paused) { + //printf("not playing\n"); + return; + }; + + + +#ifdef THEORA_USE_THREAD_STREAMING + thread_sem->post(); +#endif + + //double ctime =AudioServer::get_singleton()->get_mix_time(); + + //print_line("play "+rtos(p_delta)); + time+=p_delta; + + if (videobuf_time>get_time()) { + return; //no new frames need to be produced + } + + bool frame_done=false; + bool audio_done=!vorbis_p; + + while (!frame_done || (!audio_done && !vorbis_eos)) { + //a frame needs to be produced + + ogg_packet op; + bool no_theora=false; + + + while (vorbis_p) { + int ret; + float **pcm; + + bool buffer_full=false; + + /* if there's pending, decoded audio, grab it */ + if ((ret=vorbis_synthesis_pcmout(&vd,&pcm))>0) { + + + + const int AUXBUF_LEN=4096; + int to_read = ret; + int16_t aux_buffer[AUXBUF_LEN]; + + while(to_read) { + + int m = MIN(AUXBUF_LEN/vi.channels,to_read); + + int count = 0; + + for(int j=0;j<m;j++){ + for(int i=0;i<vi.channels;i++){ + + int val=Math::fast_ftoi(pcm[i][j]*32767.f); + if(val>32767)val=32767; + if(val<-32768)val=-32768; + aux_buffer[count++] = val; + } + } + + if (mix_callback) { + int mixed = mix_callback(mix_udata,aux_buffer,m); + to_read-=mixed; + if (mixed!=m) { //could mix no more + buffer_full=true; + break; + } + } else { + to_read-=m; //just pretend we sent the audio + } + + + } + + + int tr = vorbis_synthesis_read(&vd, ret-to_read); + + + if (vd.granulepos>=0) { + // print_line("wrote: "+itos(audio_frames_wrote)+" gpos: "+itos(vd.granulepos)); + } + + //print_line("mix audio!"); + + audio_frames_wrote+=ret-to_read; + + //print_line("AGP: "+itos(vd.granulepos)+" added "+itos(ret-to_read)); + + + } else { + + /* no pending audio; is there a pending packet to decode? */ + if (ogg_stream_packetout(&vo,&op)>0){ + if(vorbis_synthesis(&vb,&op)==0) { /* test for success! */ + vorbis_synthesis_blockin(&vd,&vb); + } + } else { /* we need more data; break out to suck in another page */ + //printf("need moar data\n"); + break; + }; + } + + + audio_done = videobuf_time < (audio_frames_wrote/float(vi.rate)); + + if (buffer_full) + break; + } + + while(theora_p && !frame_done){ + /* theora is one in, one out... */ + if(ogg_stream_packetout(&to,&op)>0){ + + + if(false && pp_inc){ + pp_level+=pp_inc; + th_decode_ctl(td,TH_DECCTL_SET_PPLEVEL,&pp_level, + sizeof(pp_level)); + pp_inc=0; + } + /*HACK: This should be set after a seek or a gap, but we might not have + a granulepos for the first packet (we only have them for the last + packet on a page), so we just set it as often as we get it. + To do this right, we should back-track from the last packet on the + page and compute the correct granulepos for the first packet after + a seek or a gap.*/ + if(op.granulepos>=0){ + th_decode_ctl(td,TH_DECCTL_SET_GRANPOS,&op.granulepos, + sizeof(op.granulepos)); + } + ogg_int64_t videobuf_granulepos; + if(th_decode_packetin(td,&op,&videobuf_granulepos)==0){ + videobuf_time=th_granule_time(td,videobuf_granulepos); + + //printf("frame time %f, play time %f, ready %i\n", (float)videobuf_time, get_time(), videobuf_ready); + + /* is it already too old to be useful? This is only actually + useful cosmetically after a SIGSTOP. Note that we have to + decode the frame even if we don't show it (for now) due to + keyframing. Soon enough libtheora will be able to deal + with non-keyframe seeks. */ + + if(videobuf_time>=get_time()) { + frame_done=true; + } else{ + /*If we are too slow, reduce the pp level.*/ + pp_inc=pp_level>0?-1:0; + } + } else { + + } + + } else { + no_theora=true; + break; + } + } + + + //print_line("no theora: "+itos(no_theora)+" theora eos: "+itos(theora_eos)+" frame done "+itos(frame_done)); + +#ifdef THEORA_USE_THREAD_STREAMING + if (file && thread_eof && no_theora && theora_eos && ring_buffer.data_left()==0) { +#else + if (file && /*!videobuf_ready && */ no_theora && theora_eos) { +#endif + printf("video done, stopping\n"); + stop(); + return; + }; + #if 0 + if (!videobuf_ready || audio_todo > 0){ + /* no data yet for somebody. Grab another page */ + + buffer_data(); + while(ogg_sync_pageout(&oy,&og)>0){ + queue_page(&og); + } + } + #else + + + if (!frame_done || !audio_done){ + //what's the point of waiting for audio to grab a page? + + buffer_data(); + while(ogg_sync_pageout(&oy,&og)>0){ + queue_page(&og); + } + } + #endif + /* If playback has begun, top audio buffer off immediately. */ + //if(stateflag) audio_write_nonblocking(); + + /* are we at or past time for this video frame? */ + if(videobuf_ready && videobuf_time<=get_time()){ + + //video_write(); + //videobuf_ready=0; + } else { + //printf("frame at %f not ready (time %f), ready %i\n", (float)videobuf_time, get_time(), videobuf_ready); + } + + float tdiff=videobuf_time-get_time(); + /*If we have lots of extra time, increase the post-processing level.*/ + if(tdiff>ti.fps_denominator*0.25/ti.fps_numerator){ + pp_inc=pp_level<pp_level_max?1:0; + } + else if(tdiff<ti.fps_denominator*0.05/ti.fps_numerator){ + pp_inc=pp_level>0?-1:0; + } + + } + + video_write(); + +}; + + +void VideoStreamPlaybackTheora::play() { + + if (!playing) + time=0; + else { + stop(); + } + + playing = true; + delay_compensation=Globals::get_singleton()->get("audio/video_delay_compensation_ms"); + delay_compensation/=1000.0; + + +}; + +void VideoStreamPlaybackTheora::stop() { + + if (playing) { + + clear(); + set_file(file_name); //reset + } + playing = false; + time=0; +}; + +bool VideoStreamPlaybackTheora::is_playing() const { + + return playing; +}; + +void VideoStreamPlaybackTheora::set_paused(bool p_paused) { + + paused=p_paused; + //pau = !p_paused; +}; + +bool VideoStreamPlaybackTheora::is_paused(bool p_paused) const { + + return paused; +}; + +void VideoStreamPlaybackTheora::set_loop(bool p_enable) { + +}; + +bool VideoStreamPlaybackTheora::has_loop() const { + + return false; +}; + +float VideoStreamPlaybackTheora::get_length() const { + + return 0; +}; + +String VideoStreamPlaybackTheora::get_stream_name() const { + + return ""; +}; + +int VideoStreamPlaybackTheora::get_loop_count() const { + + return 0; +}; + +float VideoStreamPlaybackTheora::get_pos() const { + + return get_time(); +}; + +void VideoStreamPlaybackTheora::seek_pos(float p_time) { + + // no +}; + +void VideoStreamPlaybackTheora::set_mix_callback(AudioMixCallback p_callback,void *p_userdata) { + + mix_callback=p_callback; + mix_udata=p_userdata; +} + +int VideoStreamPlaybackTheora::get_channels() const{ + + return vi.channels; +} + +void VideoStreamPlaybackTheora::set_audio_track(int p_idx) { + + audio_track=p_idx; +} + +int VideoStreamPlaybackTheora::get_mix_rate() const{ + + return vi.rate; +} + +#ifdef THEORA_USE_THREAD_STREAMING + + +void VideoStreamPlaybackTheora::_streaming_thread(void *ud) { + + VideoStreamPlaybackTheora *vs=(VideoStreamPlaybackTheora*)ud; + + while(!vs->thread_exit) { + + //just fill back the buffer + if (!vs->thread_eof) { + + int to_read = vs->ring_buffer.space_left(); + if (to_read) { + int read = vs->file->get_buffer(vs->read_buffer.ptr(),to_read); + vs->ring_buffer.write(vs->read_buffer.ptr(),read); + vs->thread_eof=vs->file->eof_reached(); + } + + + } + + vs->thread_sem->wait(); + } +} + +#endif + +VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() { + + file = NULL; + theora_p = 0; + vorbis_p = 0; + videobuf_ready = 0; + playing = false; + frames_pending = 0; + videobuf_time = 0; + paused=false; + + buffering=false; + texture = Ref<ImageTexture>( memnew(ImageTexture )); + mix_callback=NULL; + mix_udata=NULL; + audio_track=0; + delay_compensation=0; + audio_frames_wrote=0; + +#ifdef THEORA_USE_THREAD_STREAMING + int rb_power = nearest_shift(RB_SIZE_KB*1024); + ring_buffer.resize(rb_power); + read_buffer.resize(RB_SIZE_KB*1024); + thread_sem=Semaphore::create(); + thread=NULL; + thread_exit=false; + thread_eof=false; + +#endif +}; + +VideoStreamPlaybackTheora::~VideoStreamPlaybackTheora() { + +#ifdef THEORA_USE_THREAD_STREAMING + + memdelete(thread_sem); +#endif + clear(); + + if (file) + memdelete(file); + + +}; + + +RES ResourceFormatLoaderVideoStreamTheora::load(const String &p_path,const String& p_original_path, Error *r_error) { + if (r_error) + *r_error=ERR_FILE_CANT_OPEN; + + VideoStreamTheora *stream = memnew(VideoStreamTheora); + stream->set_file(p_path); + + if (r_error) + *r_error=OK; + + return Ref<VideoStreamTheora>(stream); +} + +void ResourceFormatLoaderVideoStreamTheora::get_recognized_extensions(List<String> *p_extensions) const { + + p_extensions->push_back("ogm"); + p_extensions->push_back("ogv"); +} +bool ResourceFormatLoaderVideoStreamTheora::handles_type(const String& p_type) const { + return (p_type=="VideoStream" || p_type=="VideoStreamTheora"); +} + +String ResourceFormatLoaderVideoStreamTheora::get_resource_type(const String &p_path) const { + + String exl=p_path.extension().to_lower(); + if (exl=="ogm" || exl=="ogv") + return "VideoStreamTheora"; + return ""; +} diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h new file mode 100644 index 0000000000..04a5c56ee5 --- /dev/null +++ b/modules/theora/video_stream_theora.h @@ -0,0 +1,199 @@ +/*************************************************************************/ +/* video_stream_theora.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef VIDEO_STREAM_THEORA_H +#define VIDEO_STREAM_THEORA_H + +#include "io/resource_loader.h" +#include "os/file_access.h" +#include "os/thread.h" +#include "os/semaphore.h" +#include "ring_buffer.h" +#include "scene/resources/video_stream.h" + +#include <theora/theoradec.h> +#include <vorbis/codec.h> + +//#define THEORA_USE_THREAD_STREAMING + +class VideoStreamPlaybackTheora : public VideoStreamPlayback { + + OBJ_TYPE(VideoStreamPlaybackTheora, VideoStreamPlayback); + + enum { + MAX_FRAMES = 4, + }; + + //Image frames[MAX_FRAMES]; + Image::Format format; + DVector<uint8_t> frame_data; + int frames_pending; + FileAccess* file; + String file_name; + int audio_frames_wrote; + Point2i size; + + int buffer_data(); + int queue_page(ogg_page *page); + void video_write(void); + float get_time() const; + + bool theora_eos; + bool vorbis_eos; + + ogg_sync_state oy; + ogg_page og; + ogg_stream_state vo; + ogg_stream_state to; + th_info ti; + th_comment tc; + th_dec_ctx *td; + vorbis_info vi; + vorbis_dsp_state vd; + vorbis_block vb; + vorbis_comment vc; + th_pixel_fmt px_fmt; + double videobuf_time; + int pp_inc; + + int theora_p; + int vorbis_p; + int pp_level_max; + int pp_level; + int videobuf_ready; + + bool playing; + bool buffering; + + double last_update_time; + double time; + double delay_compensation; + + Ref<ImageTexture> texture; + + AudioMixCallback mix_callback; + void* mix_udata; + bool paused; + +#ifdef THEORA_USE_THREAD_STREAMING + + enum { + RB_SIZE_KB=1024 + }; + + RingBuffer<uint8_t> ring_buffer; + Vector<uint8_t> read_buffer; + bool thread_eof; + Semaphore *thread_sem; + Thread *thread; + volatile bool thread_exit; + + static void _streaming_thread(void *ud); + +#endif + + + int audio_track; + +protected: + + void clear(); + +public: + + virtual void play(); + virtual void stop(); + virtual bool is_playing() const; + + virtual void set_paused(bool p_paused); + virtual bool is_paused(bool p_paused) const; + + virtual void set_loop(bool p_enable); + virtual bool has_loop() const; + + virtual float get_length() const; + + virtual String get_stream_name() const; + + virtual int get_loop_count() const; + + virtual float get_pos() const; + virtual void seek_pos(float p_time); + + + void set_file(const String& p_file); + + virtual Ref<Texture> get_texture(); + virtual void update(float p_delta); + + virtual void set_mix_callback(AudioMixCallback p_callback,void *p_userdata); + virtual int get_channels() const; + virtual int get_mix_rate() const; + + virtual void set_audio_track(int p_idx); + + VideoStreamPlaybackTheora(); + ~VideoStreamPlaybackTheora(); +}; + + + +class VideoStreamTheora : public VideoStream { + + OBJ_TYPE(VideoStreamTheora,VideoStream); + + String file; + int audio_track; + + +public: + + Ref<VideoStreamPlayback> instance_playback() { + Ref<VideoStreamPlaybackTheora> pb = memnew( VideoStreamPlaybackTheora ); + pb->set_audio_track(audio_track); + pb->set_file(file); + return pb; + } + + void set_file(const String& p_file) { file=p_file; } + void set_audio_track(int p_track) { audio_track=p_track; } + + VideoStreamTheora() { audio_track=0; } + +}; + +class ResourceFormatLoaderVideoStreamTheora : public ResourceFormatLoader { +public: + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String& p_type) const; + virtual String get_resource_type(const String &p_path) const; + +}; + +#endif diff --git a/drivers/theora/yuv2rgb.h b/modules/theora/yuv2rgb.h index 59101bd057..59101bd057 100644 --- a/drivers/theora/yuv2rgb.h +++ b/modules/theora/yuv2rgb.h diff --git a/modules/visual_script/SCsub b/modules/visual_script/SCsub index 403fe68f66..0882406761 100644 --- a/modules/visual_script/SCsub +++ b/modules/visual_script/SCsub @@ -1,5 +1,7 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.modules_sources,"*.cpp") +env.add_source_files(env.modules_sources, "*.cpp") Export('env') diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp index 0e97107660..ad54149b51 100644 --- a/modules/visual_script/register_types.cpp +++ b/modules/visual_script/register_types.cpp @@ -36,6 +36,7 @@ #include "visual_script_builtin_funcs.h" #include "visual_script_flow_control.h" #include "visual_script_yield_nodes.h" +#include "visual_script_expression.h" VisualScriptLanguage *visual_script_language=NULL; @@ -98,11 +99,14 @@ void register_visual_script_types() { ObjectTypeDB::register_type<VisualScriptBuiltinFunc>(); + ObjectTypeDB::register_type<VisualScriptExpression>(); + register_visual_script_nodes(); register_visual_script_func_nodes(); register_visual_script_builtin_func_node(); register_visual_script_flow_control_nodes(); register_visual_script_yield_nodes(); + register_visual_script_expression_node(); #ifdef TOOLS_ENABLED VisualScriptEditor::register_editor(); diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index e69e6ac278..bd042c8989 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -3,7 +3,7 @@ #include "scene/main/node.h" #include "os/os.h" #include "globals.h" -#define SCRIPT_VARIABLES_PREFIX "script_variables/" + //used by editor, this is not really saved @@ -615,8 +615,6 @@ void VisualScript::add_variable(const StringName& p_name,const Variant& p_defaul v._export=p_export; variables[p_name]=v; - script_variable_remap[SCRIPT_VARIABLES_PREFIX+String(p_name)]=p_name; - #ifdef TOOLS_ENABLED _update_placeholders(); @@ -633,7 +631,6 @@ void VisualScript::remove_variable(const StringName& p_name) { ERR_FAIL_COND(!variables.has(p_name)); variables.erase(p_name); - script_variable_remap.erase(SCRIPT_VARIABLES_PREFIX+String(p_name)); #ifdef TOOLS_ENABLED _update_placeholders(); @@ -928,7 +925,7 @@ void VisualScript::_update_placeholders() { continue; PropertyInfo p = E->get().info; - p.name=SCRIPT_VARIABLES_PREFIX+String(E->key()); + p.name=String(E->key()); pinfo.push_back(p); values[p.name]=E->get().default_value; } @@ -964,7 +961,7 @@ ScriptInstance* VisualScript::instance_create(Object *p_this) { continue; PropertyInfo p = E->get().info; - p.name=SCRIPT_VARIABLES_PREFIX+String(E->key()); + p.name=String(E->key()); pinfo.push_back(p); values[p.name]=E->get().default_value; } @@ -1062,10 +1059,10 @@ void VisualScript::get_script_signal_list(List<MethodInfo> *r_signals) const { bool VisualScript::get_property_default_value(const StringName& p_property,Variant& r_value) const { - if (!script_variable_remap.has(p_property)) + if (!variables.has(p_property)) return false; - r_value=variables[ script_variable_remap[p_property] ].default_value; + r_value=variables[ p_property ].default_value; return true; } void VisualScript::get_script_method_list(List<MethodInfo> *p_list) const { @@ -1133,6 +1130,7 @@ void VisualScript::get_script_property_list(List<PropertyInfo> *p_list) const { } } +#ifdef TOOLS_ENABLED bool VisualScript::are_subnodes_edited() const { for(const Map<StringName,Function>::Element *E=functions.front();E;E=E->next()) { @@ -1146,7 +1144,7 @@ bool VisualScript::are_subnodes_edited() const { return false; } - +#endif void VisualScript::_set_data(const Dictionary& p_data) { @@ -1402,12 +1400,10 @@ VisualScript::~VisualScript() { bool VisualScriptInstance::set(const StringName& p_name, const Variant& p_value) { - const Map<StringName,StringName>::Element *remap = script->script_variable_remap.find(p_name); - if (!remap) - return false; - Map<StringName,Variant>::Element *E=variables.find(remap->get()); - ERR_FAIL_COND_V(!E,false); + Map<StringName,Variant>::Element *E=variables.find(p_name); + if (!E) + return false; E->get()=p_value; @@ -1417,14 +1413,12 @@ bool VisualScriptInstance::set(const StringName& p_name, const Variant& p_value) bool VisualScriptInstance::get(const StringName& p_name, Variant &r_ret) const { - const Map<StringName,StringName>::Element *remap = script->script_variable_remap.find(p_name); - if (!remap) + const Map<StringName,Variant>::Element *E=variables.find(p_name); + if (!E) return false; - const Map<StringName,Variant>::Element *E=variables.find(remap->get()); - ERR_FAIL_COND_V(!E,false); - - return E->get(); + r_ret=E->get(); + return true; } void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const{ @@ -1433,21 +1427,15 @@ void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) c if (!E->get()._export) continue; PropertyInfo p = E->get().info; - p.name=SCRIPT_VARIABLES_PREFIX+String(E->key()); + p.name=String(E->key()); p_properties->push_back(p); } } Variant::Type VisualScriptInstance::get_property_type(const StringName& p_name,bool *r_is_valid) const{ - const Map<StringName,StringName>::Element *remap = script->script_variable_remap.find(p_name); - if (!remap) { - if (r_is_valid) - *r_is_valid=false; - return Variant::NIL; - } - const Map<StringName,VisualScript::Variable>::Element *E=script->variables.find(remap->get()); + const Map<StringName,VisualScript::Variable>::Element *E=script->variables.find(p_name); if (!E) { if (r_is_valid) *r_is_valid=false; @@ -1909,17 +1897,21 @@ Variant VisualScriptInstance::_call_internal(const StringName& p_method, void* p if (node && (r_error.error!=Variant::CallError::CALL_ERROR_INVALID_METHOD || error_str==String())) { + if (error_str!=String()) { + error_str+=" "; + } + if (r_error.error==Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) { int errorarg=r_error.argument; - error_str="Cannot convert argument "+itos(errorarg+1)+" to "+Variant::get_type_name(r_error.expected)+"."; + error_str+="Cannot convert argument "+itos(errorarg+1)+" to "+Variant::get_type_name(r_error.expected)+"."; } else if (r_error.error==Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) { - error_str="Expected "+itos(r_error.argument)+" arguments."; + error_str+="Expected "+itos(r_error.argument)+" arguments."; } else if (r_error.error==Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) { - error_str="Expected "+itos(r_error.argument)+" arguments."; + error_str+="Expected "+itos(r_error.argument)+" arguments."; } else if (r_error.error==Variant::CallError::CALL_ERROR_INVALID_METHOD) { - error_str="Invalid Call."; + error_str+="Invalid Call."; } else if (r_error.error==Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL) { - error_str="Instance is null"; + error_str+="Base Instance is null"; } } @@ -2447,7 +2439,7 @@ void VisualScriptFunctionState::_bind_methods() { ObjectTypeDB::bind_method(_MD("connect_to_signal","obj","signals","args"),&VisualScriptFunctionState::connect_to_signal); ObjectTypeDB::bind_method(_MD("resume:Array","args"),&VisualScriptFunctionState::resume,DEFVAL(Variant())); ObjectTypeDB::bind_method(_MD("is_valid"),&VisualScriptFunctionState::is_valid); - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"_signal_callback",&VisualScriptFunctionState::_signal_callback,MethodInfo("_signal_callback")); + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"_signal_callback",&VisualScriptFunctionState::_signal_callback,MethodInfo("_signal_callback")); } VisualScriptFunctionState::VisualScriptFunctionState() { diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index e59dd76313..63b018b0c2 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -227,7 +227,6 @@ friend class VisualScriptInstance; Map<StringName,Function> functions; Map<StringName,Variable> variables; - Map<StringName,StringName> script_variable_remap; Map<StringName,Vector<Argument> > custom_signals; Map<Object*,VisualScriptInstance*> instances; @@ -345,7 +344,9 @@ public: virtual void get_script_property_list(List<PropertyInfo> *p_list) const; +#ifdef TOOLS_ENABLED virtual bool are_subnodes_edited() const; +#endif VisualScript(); ~VisualScript(); diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index 1d0bca0b30..2bfb6bc9ea 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -55,6 +55,7 @@ const char* VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX "convert", "typeof", "type_exists", + "char", "str", "print", "printerr", @@ -65,6 +66,21 @@ const char* VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX "bytes2var", }; +VisualScriptBuiltinFunc::BuiltinFunc VisualScriptBuiltinFunc::find_function(const String& p_string) { + + for(int i=0;i<FUNC_MAX;i++) { + if (p_string==func_name[i]) + return BuiltinFunc(i); + } + + return FUNC_MAX; +} + +String VisualScriptBuiltinFunc::get_func_name(BuiltinFunc p_func) { + + ERR_FAIL_INDEX_V(p_func,FUNC_MAX,String()); + return func_name[p_func]; +} int VisualScriptBuiltinFunc::get_output_sequence_port_count() const { @@ -88,10 +104,10 @@ bool VisualScriptBuiltinFunc::has_input_sequence_port() const{ } -int VisualScriptBuiltinFunc::get_input_value_port_count() const{ +int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) { - switch(func) { + switch(p_func) { case MATH_RANDOMIZE: case MATH_RAND: @@ -126,6 +142,7 @@ int VisualScriptBuiltinFunc::get_input_value_port_count() const{ case LOGIC_NEAREST_PO2: case OBJ_WEAKREF: case TYPE_OF: + case TEXT_CHAR: case TEXT_STR: case TEXT_PRINT: case TEXT_PRINTERR: @@ -157,6 +174,11 @@ int VisualScriptBuiltinFunc::get_input_value_port_count() const{ } return 0; } + +int VisualScriptBuiltinFunc::get_input_value_port_count() const{ + + return get_func_argument_count(func); +} int VisualScriptBuiltinFunc::get_output_value_port_count() const{ switch(func) { @@ -342,6 +364,12 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const return PropertyInfo(Variant::STRING,"type"); } break; + case TEXT_CHAR: { + + return PropertyInfo(Variant::INT,"ascii"); + + + } break; case TEXT_STR: { return PropertyInfo(Variant::NIL,"value"); @@ -497,6 +525,7 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons t=Variant::BOOL; } break; + case TEXT_CHAR: case TEXT_STR: { t=Variant::STRING; @@ -560,118 +589,124 @@ VisualScriptBuiltinFunc::BuiltinFunc VisualScriptBuiltinFunc::get_func() { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;\ r_error.argument=m_arg;\ r_error.expected=Variant::REAL;\ - return 0;\ + return;\ } -class VisualScriptNodeInstanceBuiltinFunc : public VisualScriptNodeInstance { -public: - VisualScriptBuiltinFunc *node; - VisualScriptInstance *instance; +void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func,const Variant** p_inputs,Variant* r_return,Variant::CallError& r_error,String& r_error_str) { - VisualScriptBuiltinFunc::BuiltinFunc func; + switch(p_func) { + case VisualScriptBuiltinFunc::MATH_SIN: { + VALIDATE_ARG_NUM(0); + *r_return=Math::sin(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_COS: { - //virtual int get_working_memory_size() const { return 0; } - //virtual bool is_output_port_unsequenced(int p_idx) const { return false; } - //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; } + VALIDATE_ARG_NUM(0); + *r_return=Math::cos(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_TAN: { - virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) { + VALIDATE_ARG_NUM(0); + *r_return=Math::tan(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_SINH: { - switch(func) { - case VisualScriptBuiltinFunc::MATH_SIN: { + VALIDATE_ARG_NUM(0); + *r_return=Math::sinh(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_COSH: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::sin(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_COS: { + VALIDATE_ARG_NUM(0); + *r_return=Math::cosh(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_TANH: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::cos(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_TAN: { + VALIDATE_ARG_NUM(0); + *r_return=Math::tanh(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ASIN: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::tan(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_SINH: { + VALIDATE_ARG_NUM(0); + *r_return=Math::asin(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ACOS: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::sinh(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_COSH: { + VALIDATE_ARG_NUM(0); + *r_return=Math::acos(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ATAN: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::cosh(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_TANH: { + VALIDATE_ARG_NUM(0); + *r_return=Math::atan(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ATAN2: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::tanh(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_ASIN: { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *r_return=Math::atan2(*p_inputs[0],*p_inputs[1]); + } break; + case VisualScriptBuiltinFunc::MATH_SQRT: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::asin(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_ACOS: { + VALIDATE_ARG_NUM(0); + *r_return=Math::sqrt(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_FMOD: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::acos(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_ATAN: { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *r_return=Math::fmod(*p_inputs[0],*p_inputs[1]); + } break; + case VisualScriptBuiltinFunc::MATH_FPOSMOD: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::atan(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_ATAN2: { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *r_return=Math::fposmod(*p_inputs[0],*p_inputs[1]); + } break; + case VisualScriptBuiltinFunc::MATH_FLOOR: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - *p_outputs[0]=Math::atan2(*p_inputs[0],*p_inputs[1]); - } break; - case VisualScriptBuiltinFunc::MATH_SQRT: { + VALIDATE_ARG_NUM(0); + *r_return=Math::floor(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_CEIL: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::sqrt(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_FMOD: { + VALIDATE_ARG_NUM(0); + *r_return=Math::ceil(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ROUND: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - *p_outputs[0]=Math::fmod(*p_inputs[0],*p_inputs[1]); - } break; - case VisualScriptBuiltinFunc::MATH_FPOSMOD: { + VALIDATE_ARG_NUM(0); + *r_return=Math::round(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ABS: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - *p_outputs[0]=Math::fposmod(*p_inputs[0],*p_inputs[1]); - } break; - case VisualScriptBuiltinFunc::MATH_FLOOR: { + if (p_inputs[0]->get_type()==Variant::INT) { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::floor(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_CEIL: { + int64_t i = *p_inputs[0]; + *r_return=ABS(i); + } else if (p_inputs[0]->get_type()==Variant::REAL) { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::ceil(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_ROUND: { + real_t r = *p_inputs[0]; + *r_return=Math::abs(r); + } else { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::round(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_ABS: { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::REAL; + + } + } break; + case VisualScriptBuiltinFunc::MATH_SIGN: { if (p_inputs[0]->get_type()==Variant::INT) { int64_t i = *p_inputs[0]; - *p_outputs[0]=ABS(i); + *r_return= i < 0 ? -1 : ( i > 0 ? +1 : 0); } else if (p_inputs[0]->get_type()==Variant::REAL) { real_t r = *p_inputs[0]; - *p_outputs[0]=Math::abs(r); + *r_return= r < 0.0 ? -1.0 : ( r > 0.0 ? +1.0 : 0.0); } else { r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; @@ -679,410 +714,419 @@ public: r_error.expected=Variant::REAL; } - } break; - case VisualScriptBuiltinFunc::MATH_SIGN: { + } break; + case VisualScriptBuiltinFunc::MATH_POW: { - if (p_inputs[0]->get_type()==Variant::INT) { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *r_return=Math::pow(*p_inputs[0],*p_inputs[1]); + } break; + case VisualScriptBuiltinFunc::MATH_LOG: { - int64_t i = *p_inputs[0]; - *p_outputs[0]= i < 0 ? -1 : ( i > 0 ? +1 : 0); - } else if (p_inputs[0]->get_type()==Variant::REAL) { + VALIDATE_ARG_NUM(0); + *r_return=Math::log(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_EXP: { - real_t r = *p_inputs[0]; - *p_outputs[0]= r < 0.0 ? -1.0 : ( r > 0.0 ? +1.0 : 0.0); - } else { + VALIDATE_ARG_NUM(0); + *r_return=Math::exp(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ISNAN: { - r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument=0; - r_error.expected=Variant::REAL; + VALIDATE_ARG_NUM(0); + *r_return=Math::is_nan(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_ISINF: { - } - } break; - case VisualScriptBuiltinFunc::MATH_POW: { + VALIDATE_ARG_NUM(0); + *r_return=Math::is_inf(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_EASE: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - *p_outputs[0]=Math::pow(*p_inputs[0],*p_inputs[1]); - } break; - case VisualScriptBuiltinFunc::MATH_LOG: { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *r_return=Math::ease(*p_inputs[0],*p_inputs[1]); + } break; + case VisualScriptBuiltinFunc::MATH_DECIMALS: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::log(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_EXP: { + VALIDATE_ARG_NUM(0); + *r_return=Math::step_decimals(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_STEPIFY: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::exp(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_ISNAN: { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *r_return=Math::stepify(*p_inputs[0],*p_inputs[1]); + } break; + case VisualScriptBuiltinFunc::MATH_LERP: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::is_nan(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_ISINF: { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + VALIDATE_ARG_NUM(2); + *r_return=Math::lerp(*p_inputs[0],*p_inputs[1],*p_inputs[2]); + } break; + case VisualScriptBuiltinFunc::MATH_DECTIME: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::is_inf(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_EASE: { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + VALIDATE_ARG_NUM(2); + *r_return=Math::dectime(*p_inputs[0],*p_inputs[1],*p_inputs[2]); + } break; + case VisualScriptBuiltinFunc::MATH_RANDOMIZE: { + Math::randomize(); - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - *p_outputs[0]=Math::ease(*p_inputs[0],*p_inputs[1]); - } break; - case VisualScriptBuiltinFunc::MATH_DECIMALS: { + } break; + case VisualScriptBuiltinFunc::MATH_RAND: { + *r_return=Math::rand(); + } break; + case VisualScriptBuiltinFunc::MATH_RANDF: { + *r_return=Math::randf(); + } break; + case VisualScriptBuiltinFunc::MATH_RANDOM: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::step_decimals(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_STEPIFY: { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *r_return=Math::random(*p_inputs[0],*p_inputs[1]); + } break; + case VisualScriptBuiltinFunc::MATH_SEED: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - *p_outputs[0]=Math::stepify(*p_inputs[0],*p_inputs[1]); - } break; - case VisualScriptBuiltinFunc::MATH_LERP: { + VALIDATE_ARG_NUM(0); + uint32_t seed=*p_inputs[0]; + Math::seed(seed); - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(2); - *p_outputs[0]=Math::lerp(*p_inputs[0],*p_inputs[1],*p_inputs[2]); - } break; - case VisualScriptBuiltinFunc::MATH_DECTIME: { + } break; + case VisualScriptBuiltinFunc::MATH_RANDSEED: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(2); - *p_outputs[0]=Math::dectime(*p_inputs[0],*p_inputs[1],*p_inputs[2]); - } break; - case VisualScriptBuiltinFunc::MATH_RANDOMIZE: { - Math::randomize(); - - } break; - case VisualScriptBuiltinFunc::MATH_RAND: { - *p_outputs[0]=Math::rand(); - } break; - case VisualScriptBuiltinFunc::MATH_RANDF: { - *p_outputs[0]=Math::randf(); - } break; - case VisualScriptBuiltinFunc::MATH_RANDOM: { + VALIDATE_ARG_NUM(0); + uint32_t seed=*p_inputs[0]; + int ret = Math::rand_from_seed(&seed); + Array reta; + reta.push_back(ret); + reta.push_back(seed); + *r_return=reta; + + } break; + case VisualScriptBuiltinFunc::MATH_DEG2RAD: { + + VALIDATE_ARG_NUM(0); + *r_return=Math::deg2rad(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_RAD2DEG: { + VALIDATE_ARG_NUM(0); + *r_return=Math::rad2deg(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_LINEAR2DB: { + + VALIDATE_ARG_NUM(0); + *r_return=Math::linear2db(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::MATH_DB2LINEAR: { + + VALIDATE_ARG_NUM(0); + *r_return=Math::db2linear(*p_inputs[0]); + } break; + case VisualScriptBuiltinFunc::LOGIC_MAX: { + + if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT) { + + int64_t a = *p_inputs[0]; + int64_t b = *p_inputs[1]; + *r_return=MAX(a,b); + } else { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); - *p_outputs[0]=Math::random(*p_inputs[0],*p_inputs[1]); - } break; - case VisualScriptBuiltinFunc::MATH_SEED: { - VALIDATE_ARG_NUM(0); - uint32_t seed=*p_inputs[0]; - Math::seed(seed); + real_t a = *p_inputs[0]; + real_t b = *p_inputs[1]; - } break; - case VisualScriptBuiltinFunc::MATH_RANDSEED: { + *r_return=MAX(a,b); + } - VALIDATE_ARG_NUM(0); - uint32_t seed=*p_inputs[0]; - int ret = Math::rand_from_seed(&seed); - Array reta; - reta.push_back(ret); - reta.push_back(seed); - *p_outputs[0]=reta; + } break; + case VisualScriptBuiltinFunc::LOGIC_MIN: { - } break; - case VisualScriptBuiltinFunc::MATH_DEG2RAD: { + if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT) { + int64_t a = *p_inputs[0]; + int64_t b = *p_inputs[1]; + *r_return=MIN(a,b); + } else { VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::deg2rad(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_RAD2DEG: { + VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::rad2deg(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_LINEAR2DB: { + real_t a = *p_inputs[0]; + real_t b = *p_inputs[1]; - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::linear2db(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::MATH_DB2LINEAR: { + *r_return=MIN(a,b); + } + } break; + case VisualScriptBuiltinFunc::LOGIC_CLAMP: { - VALIDATE_ARG_NUM(0); - *p_outputs[0]=Math::db2linear(*p_inputs[0]); - } break; - case VisualScriptBuiltinFunc::LOGIC_MAX: { + if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT && p_inputs[2]->get_type()==Variant::INT) { - if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT) { + int64_t a = *p_inputs[0]; + int64_t b = *p_inputs[1]; + int64_t c = *p_inputs[2]; + *r_return=CLAMP(a,b,c); + } else { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + VALIDATE_ARG_NUM(2); - int64_t a = *p_inputs[0]; - int64_t b = *p_inputs[1]; - *p_outputs[0]=MAX(a,b); - } else { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); + real_t a = *p_inputs[0]; + real_t b = *p_inputs[1]; + real_t c = *p_inputs[2]; - real_t a = *p_inputs[0]; - real_t b = *p_inputs[1]; + *r_return=CLAMP(a,b,c); + } + } break; + case VisualScriptBuiltinFunc::LOGIC_NEAREST_PO2: { - *p_outputs[0]=MAX(a,b); - } + VALIDATE_ARG_NUM(0); + int64_t num = *p_inputs[0]; + *r_return = nearest_power_of_2(num); + } break; + case VisualScriptBuiltinFunc::OBJ_WEAKREF: { - } break; - case VisualScriptBuiltinFunc::LOGIC_MIN: { + if (p_inputs[0]->get_type()!=Variant::OBJECT) { - if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::OBJECT; - int64_t a = *p_inputs[0]; - int64_t b = *p_inputs[1]; - *p_outputs[0]=MIN(a,b); - } else { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); + return; - real_t a = *p_inputs[0]; - real_t b = *p_inputs[1]; + } - *p_outputs[0]=MIN(a,b); - } - } break; - case VisualScriptBuiltinFunc::LOGIC_CLAMP: { + if (p_inputs[0]->is_ref()) { - if (p_inputs[0]->get_type()==Variant::INT && p_inputs[1]->get_type()==Variant::INT && p_inputs[2]->get_type()==Variant::INT) { + REF r = *p_inputs[0]; + if (!r.is_valid()) { - int64_t a = *p_inputs[0]; - int64_t b = *p_inputs[1]; - int64_t c = *p_inputs[2]; - *p_outputs[0]=CLAMP(a,b,c); - } else { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(2); + return; + } - real_t a = *p_inputs[0]; - real_t b = *p_inputs[1]; - real_t c = *p_inputs[2]; + Ref<WeakRef> wref = memnew( WeakRef ); + wref->set_ref(r); + *r_return=wref; + } else { + Object *obj = *p_inputs[0]; + if (!obj) { - *p_outputs[0]=CLAMP(a,b,c); + return; } - } break; - case VisualScriptBuiltinFunc::LOGIC_NEAREST_PO2: { + Ref<WeakRef> wref = memnew( WeakRef ); + wref->set_obj(obj); + *r_return=wref; + } - VALIDATE_ARG_NUM(0); - int64_t num = *p_inputs[0]; - *p_outputs[0] = nearest_power_of_2(num); - } break; - case VisualScriptBuiltinFunc::OBJ_WEAKREF: { - if (p_inputs[0]->get_type()!=Variant::OBJECT) { - r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument=0; - r_error.expected=Variant::OBJECT; - return 0; + } break; + case VisualScriptBuiltinFunc::FUNC_FUNCREF: { - } + if (p_inputs[0]->get_type()!=Variant::OBJECT) { - if (p_inputs[0]->is_ref()) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::OBJECT; - REF r = *p_inputs[0]; - if (!r.is_valid()) { + return; - return 0; - } + } + if (p_inputs[1]->get_type()!=Variant::STRING && p_inputs[1]->get_type()!=Variant::NODE_PATH) { - Ref<WeakRef> wref = memnew( WeakRef ); - wref->set_ref(r); - *p_outputs[0]=wref; - } else { - Object *obj = *p_inputs[0]; - if (!obj) { - - return 0; - } - Ref<WeakRef> wref = memnew( WeakRef ); - wref->set_obj(obj); - *p_outputs[0]=wref; - } + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=1; + r_error.expected=Variant::STRING; + return; + } + Ref<FuncRef> fr = memnew( FuncRef); - } break; - case VisualScriptBuiltinFunc::FUNC_FUNCREF: { + fr->set_instance(*p_inputs[0]); + fr->set_function(*p_inputs[1]); - if (p_inputs[0]->get_type()!=Variant::OBJECT) { + *r_return=fr; - r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument=0; - r_error.expected=Variant::OBJECT; + } break; + case VisualScriptBuiltinFunc::TYPE_CONVERT: { - return 0; + VALIDATE_ARG_NUM(1); + int type=*p_inputs[1]; + if (type<0 || type>=Variant::VARIANT_MAX) { - } - if (p_inputs[1]->get_type()!=Variant::STRING && p_inputs[1]->get_type()!=Variant::NODE_PATH) { + r_error_str=RTR("Invalid type argument to convert(), use TYPE_* constants."); + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::INT; + return; - r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument=1; - r_error.expected=Variant::STRING; + } else { - return 0; - } + *r_return=Variant::construct(Variant::Type(type),p_inputs,1,r_error); + } + } break; + case VisualScriptBuiltinFunc::TYPE_OF: { - Ref<FuncRef> fr = memnew( FuncRef); - fr->set_instance(*p_inputs[0]); - fr->set_function(*p_inputs[1]); + *r_return = p_inputs[0]->get_type(); - *p_outputs[0]=fr; + } break; + case VisualScriptBuiltinFunc::TYPE_EXISTS: { - } break; - case VisualScriptBuiltinFunc::TYPE_CONVERT: { - VALIDATE_ARG_NUM(1); - int type=*p_inputs[1]; - if (type<0 || type>=Variant::VARIANT_MAX) { + *r_return = ObjectTypeDB::type_exists(*p_inputs[0]); - *p_outputs[0]=RTR("Invalid type argument to convert(), use TYPE_* constants."); - r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument=0; - r_error.expected=Variant::INT; - return 0; + } break; + case VisualScriptBuiltinFunc::TEXT_CHAR: { - } else { + CharType result[2] = {*p_inputs[0], 0}; + + *r_return=String(result); + } break; + case VisualScriptBuiltinFunc::TEXT_STR: { - *p_outputs[0]=Variant::construct(Variant::Type(type),p_inputs,1,r_error); - } - } break; - case VisualScriptBuiltinFunc::TYPE_OF: { + String str = *p_inputs[0]; + *r_return=str; - *p_outputs[0] = p_inputs[0]->get_type(); + } break; + case VisualScriptBuiltinFunc::TEXT_PRINT: { - } break; - case VisualScriptBuiltinFunc::TYPE_EXISTS: { + String str = *p_inputs[0]; + print_line(str); - *p_outputs[0] = ObjectTypeDB::type_exists(*p_inputs[0]); + } break; - } break; - case VisualScriptBuiltinFunc::TEXT_STR: { + case VisualScriptBuiltinFunc::TEXT_PRINTERR: { - String str = *p_inputs[0]; + String str = *p_inputs[0]; - *p_outputs[0]=str; + //str+="\n"; + OS::get_singleton()->printerr("%s\n",str.utf8().get_data()); - } break; - case VisualScriptBuiltinFunc::TEXT_PRINT: { - String str = *p_inputs[0]; - print_line(str); + } break; + case VisualScriptBuiltinFunc::TEXT_PRINTRAW: { + String str = *p_inputs[0]; + //str+="\n"; + OS::get_singleton()->print("%s",str.utf8().get_data()); - } break; - case VisualScriptBuiltinFunc::TEXT_PRINTERR: { + } break; + case VisualScriptBuiltinFunc::VAR_TO_STR: { - String str = *p_inputs[0]; + String vars; + VariantWriter::write_to_string(*p_inputs[0],vars); + *r_return=vars; + } break; + case VisualScriptBuiltinFunc::STR_TO_VAR: { - //str+="\n"; - OS::get_singleton()->printerr("%s\n",str.utf8().get_data()); + if (p_inputs[0]->get_type()!=Variant::STRING) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::STRING; + return; + } - } break; - case VisualScriptBuiltinFunc::TEXT_PRINTRAW: { - String str = *p_inputs[0]; + VariantParser::StreamString ss; + ss.s=*p_inputs[0]; - //str+="\n"; - OS::get_singleton()->print("%s",str.utf8().get_data()); + String errs; + int line; + Error err = VariantParser::parse(&ss,*r_return,errs,line); + if (err!=OK) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::STRING; + *r_return="Parse error at line "+itos(line)+": "+errs; + return; + } - } break; - case VisualScriptBuiltinFunc::VAR_TO_STR: { + } break; + case VisualScriptBuiltinFunc::VAR_TO_BYTES: { - String vars; - VariantWriter::write_to_string(*p_inputs[0],vars); - *p_outputs[0]=vars; - } break; - case VisualScriptBuiltinFunc::STR_TO_VAR: { - if (p_inputs[0]->get_type()!=Variant::STRING) { - r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument=0; - r_error.expected=Variant::STRING; + ByteArray barr; + int len; + Error err = encode_variant(*p_inputs[0],NULL,len); + if (err) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::NIL; + r_error_str="Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID)."; + return; + } - return 0; - } + barr.resize(len); + { + ByteArray::Write w = barr.write(); + encode_variant(*p_inputs[0],w.ptr(),len); - VariantParser::StreamString ss; - ss.s=*p_inputs[0]; + } + *r_return=barr; + } break; + case VisualScriptBuiltinFunc::BYTES_TO_VAR: { - String errs; - int line; - Error err = VariantParser::parse(&ss,*p_outputs[0],errs,line); + if (p_inputs[0]->get_type()!=Variant::RAW_ARRAY) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::RAW_ARRAY; + return; + } + + ByteArray varr=*p_inputs[0]; + Variant ret; + { + ByteArray::Read r=varr.read(); + Error err = decode_variant(ret,r.ptr(),varr.size(),NULL); if (err!=OK) { + r_error_str=RTR("Not enough bytes for decoding bytes, or invalid format."); r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument=0; - r_error.expected=Variant::STRING; - *p_outputs[0]="Parse error at line "+itos(line)+": "+errs; - return 0; + r_error.expected=Variant::RAW_ARRAY; + return; } - } break; - case VisualScriptBuiltinFunc::VAR_TO_BYTES: { + } + *r_return=ret; - ByteArray barr; - int len; - Error err = encode_variant(*p_inputs[0],NULL,len); - if (err) { - r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument=0; - r_error.expected=Variant::NIL; - *p_outputs[0]="Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID)."; - return 0; - } + } break; + default: {} + } - barr.resize(len); - { - ByteArray::Write w = barr.write(); - encode_variant(*p_inputs[0],w.ptr(),len); +} - } - *p_outputs[0]=barr; - } break; - case VisualScriptBuiltinFunc::BYTES_TO_VAR: { - if (p_inputs[0]->get_type()!=Variant::RAW_ARRAY) { - r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument=0; - r_error.expected=Variant::RAW_ARRAY; +class VisualScriptNodeInstanceBuiltinFunc : public VisualScriptNodeInstance { +public: - return 0; - } + VisualScriptBuiltinFunc *node; + VisualScriptInstance *instance; - ByteArray varr=*p_inputs[0]; - Variant ret; - { - ByteArray::Read r=varr.read(); - Error err = decode_variant(ret,r.ptr(),varr.size(),NULL); - if (err!=OK) { - *p_outputs[0]=RTR("Not enough bytes for decoding bytes, or invalid format."); - r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument=0; - r_error.expected=Variant::RAW_ARRAY; - return 0; - } + VisualScriptBuiltinFunc::BuiltinFunc func; - } - *p_outputs[0]=ret; + //virtual int get_working_memory_size() const { return 0; } + //virtual bool is_output_port_unsequenced(int p_idx) const { return false; } + //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; } + + virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) { - } break; - default: {} - } + VisualScriptBuiltinFunc::exec_func(func,p_inputs,p_outputs[0],r_error,r_error_str); return 0; } @@ -1185,6 +1229,7 @@ void register_visual_script_builtin_func_node() { VisualScriptLanguage::singleton->add_register_func("functions/built_in/convert",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_CONVERT>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/typeof",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_OF>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/type_exists",create_builtin_func_node<VisualScriptBuiltinFunc::TYPE_EXISTS>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/char",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_CHAR>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/str",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_STR>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/print",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINT>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/printerr",create_builtin_func_node<VisualScriptBuiltinFunc::TEXT_PRINTERR>); diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h index ebf227a192..8b0d70c1ea 100644 --- a/modules/visual_script/visual_script_builtin_funcs.h +++ b/modules/visual_script/visual_script_builtin_funcs.h @@ -57,6 +57,7 @@ public: TYPE_CONVERT, TYPE_OF, TYPE_EXISTS, + TEXT_CHAR, TEXT_STR, TEXT_PRINT, TEXT_PRINTERR, @@ -68,6 +69,11 @@ public: FUNC_MAX }; + static int get_func_argument_count(BuiltinFunc p_func); + static String get_func_name(BuiltinFunc p_func); + static void exec_func(BuiltinFunc p_func, const Variant** p_inputs, Variant* r_return, Variant::CallError& r_error, String& r_error_str); + static BuiltinFunc find_function(const String& p_string); + private: static const char* func_name[FUNC_MAX]; BuiltinFunc func; diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index ccd8635930..02d3c453c4 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -3,6 +3,7 @@ #include "visual_script_nodes.h" #include "visual_script_flow_control.h" #include "visual_script_func_nodes.h" +#include "visual_script_expression.h" #include "os/input.h" #include "tools/editor/editor_resource_preview.h" #include "os/keyboard.h" @@ -330,7 +331,7 @@ static Color _color_from_type(Variant::Type p_type) { case Variant::QUAT: color = Color::html("ec69a3"); break; case Variant::_AABB: color = Color::html("ee7991"); break; case Variant::MATRIX3: color = Color::html("e3ec69"); break; - case Variant::TRANSFORM: color = Color::html("ecd669"); break; + case Variant::TRANSFORM: color = Color::html("f6a86e"); break; case Variant::COLOR: color = Color::html("9dff70"); break; case Variant::IMAGE: color = Color::html("93f1b9"); break; @@ -502,9 +503,20 @@ void VisualScriptEditor::_update_graph(int p_only_id) { } - Label *text = memnew( Label ); - text->set_text(node->get_text()); - gnode->add_child(text); + if (node->cast_to<VisualScriptExpression>()) { + + LineEdit *line_edit = memnew( LineEdit ); + line_edit->set_text(node->get_text()); + line_edit->set_expand_to_text_length(true); + line_edit->add_font_override("font",get_font("source","EditorFonts")); + gnode->add_child(line_edit); + line_edit->connect("text_changed",this,"_expression_text_changed",varray(E->get())); + } else { + Label *text = memnew( Label ); + text->set_text(node->get_text()); + gnode->add_child(text); + } + if (node->cast_to<VisualScriptComment>()) { Ref<VisualScriptComment> vsc=node; @@ -1197,6 +1209,30 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt } } +void VisualScriptEditor::_expression_text_changed(const String& p_text,int p_id) { + + Ref<VisualScriptExpression> vse = script->get_node(edited_func,p_id); + if (!vse.is_valid()) + return; + + + updating_graph=true; + + undo_redo->create_action(TTR("Change Expression"),UndoRedo::MERGE_ENDS); + undo_redo->add_do_property(vse.ptr(),"expression",p_text); + undo_redo->add_undo_property(vse.ptr(),"expression",vse->get("expression")); + undo_redo->add_do_method(this,"_update_graph",p_id); + undo_redo->add_undo_method(this,"_update_graph",p_id); + undo_redo->commit_action(); + + Node *node = graph->get_node(itos(p_id)); + if (node->cast_to<Control>()) + node->cast_to<Control>()->set_size(Vector2(1,1)); //shrink if text is smaller + + updating_graph=false; + +} + void VisualScriptEditor::_available_node_doubleclicked() { TreeItem *item = nodes->get_selected(); @@ -2104,6 +2140,7 @@ Vector<String> VisualScriptEditor::get_functions(){ void VisualScriptEditor::set_edited_script(const Ref<Script>& p_script){ + script=p_script; signal_editor->script=p_script; signal_editor->undo_redo=undo_redo; @@ -3220,6 +3257,7 @@ void VisualScriptEditor::_bind_methods() { ObjectTypeDB::bind_method("_button_resource_previewed",&VisualScriptEditor::_button_resource_previewed); ObjectTypeDB::bind_method("_port_action_menu",&VisualScriptEditor::_port_action_menu); ObjectTypeDB::bind_method("_selected_connect_node_method_or_setget",&VisualScriptEditor::_selected_connect_node_method_or_setget); + ObjectTypeDB::bind_method("_expression_text_changed",&VisualScriptEditor::_expression_text_changed); diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index 5191ed540a..483ae1644c 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -168,6 +168,7 @@ class VisualScriptEditor : public ScriptEditorBase { void _member_button(Object *p_item, int p_column, int p_button); + void _expression_text_changed(const String& p_text,int p_id); String revert_on_drag; diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp new file mode 100644 index 0000000000..cc3b5f2174 --- /dev/null +++ b/modules/visual_script/visual_script_expression.cpp @@ -0,0 +1,1523 @@ +#include "visual_script_expression.h" + + +bool VisualScriptExpression::_set(const StringName& p_name, const Variant& p_value) { + + if (String(p_name)=="expression") { + expression=p_value; + expression_dirty=true; + ports_changed_notify(); + return true; + } + + if (String(p_name)=="out_type") { + output_type=Variant::Type(int(p_value)); + expression_dirty=true; + ports_changed_notify(); + return true; + } + if (String(p_name)=="sequenced") { + sequenced=p_value; + ports_changed_notify(); + return true; + } + + if (String(p_name)=="input_count") { + + int from=inputs.size(); + inputs.resize(int(p_value)); + for(int i=from;i<inputs.size();i++) { + inputs[i].name=String::chr('a'+i); + if (from==0) { + inputs[i].type=output_type; + } else { + inputs[i].type=inputs[from-1].type; + } + } + expression_dirty=true; + ports_changed_notify(); + _change_notify(); + return true; + } + + if (String(p_name).begins_with("input/")) { + + int idx=String(p_name).get_slice("/",1).to_int(); + ERR_FAIL_INDEX_V(idx,inputs.size(),false); + + String what=String(p_name).get_slice("/",2); + + if (what=="type") { + + inputs[idx].type=Variant::Type(int(p_value)); + } else if (what=="name") { + + inputs[idx].name=p_value; + } else { + return false; + } + + expression_dirty=true; + ports_changed_notify(); + return true; + } + + + return false; + +} + +bool VisualScriptExpression::_get(const StringName& p_name,Variant &r_ret) const { + + if (String(p_name)=="expression") { + r_ret=expression; + return true; + } + + if (String(p_name)=="out_type") { + r_ret=output_type; + return true; + } + + if (String(p_name)=="sequenced") { + r_ret=sequenced; + return true; + } + + if (String(p_name)=="input_count") { + r_ret=inputs.size(); + return true; + } + + if (String(p_name).begins_with("input/")) { + + int idx=String(p_name).get_slice("/",1).to_int(); + ERR_FAIL_INDEX_V(idx,inputs.size(),false); + + String what=String(p_name).get_slice("/",2); + + if (what=="type") { + + r_ret=inputs[idx].type; + } else if (what=="name") { + + r_ret=inputs[idx].name; + } else { + return false; + } + + return true; + } + + + return false; +} +void VisualScriptExpression::_get_property_list( List<PropertyInfo> *p_list) const { + + + String argt="Any"; + for(int i=1;i<Variant::VARIANT_MAX;i++) { + argt+=","+Variant::get_type_name(Variant::Type(i)); + } + + p_list->push_back(PropertyInfo(Variant::STRING,"expression",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::INT,"out_type",PROPERTY_HINT_ENUM,argt)); + p_list->push_back(PropertyInfo(Variant::INT,"input_count",PROPERTY_HINT_RANGE,"0,64,1")); + p_list->push_back(PropertyInfo(Variant::BOOL,"sequenced")); + + for(int i=0;i<inputs.size();i++) { + + p_list->push_back(PropertyInfo(Variant::INT,"input/"+itos(i)+"/type",PROPERTY_HINT_ENUM,argt)); + p_list->push_back(PropertyInfo(Variant::STRING,"input/"+itos(i)+"/name")); + } +} + +int VisualScriptExpression::get_output_sequence_port_count() const { + + return sequenced?1:0; +} +bool VisualScriptExpression::has_input_sequence_port() const{ + + return sequenced; +} + + +String VisualScriptExpression::get_output_sequence_port_text(int p_port) const{ + + return String(); +} + + +int VisualScriptExpression::get_input_value_port_count() const{ + + return inputs.size(); + +} +int VisualScriptExpression::get_output_value_port_count() const{ + + return 1; +} + + +PropertyInfo VisualScriptExpression::get_input_value_port_info(int p_idx) const{ + + return PropertyInfo(inputs[p_idx].type,inputs[p_idx].name); +} +PropertyInfo VisualScriptExpression::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(output_type,"result"); +} + +String VisualScriptExpression::get_caption() const{ + + return "Expression"; +} +String VisualScriptExpression::get_text() const{ + + return expression; +} + + +Error VisualScriptExpression::_get_token(Token& r_token) { + + while (true) { +#define GET_CHAR() (str_ofs>=expression.length()?0:expression[str_ofs++]) + + CharType cchar = GET_CHAR(); + if (cchar==0) { + r_token.type=TK_EOF; + return OK; + } + + + switch(cchar) { + + case 0: { + r_token.type=TK_EOF; + return OK; + } break; + case '{': { + + r_token.type=TK_CURLY_BRACKET_OPEN; + return OK; + }; + case '}': { + + r_token.type=TK_CURLY_BRACKET_CLOSE; + return OK; + }; + case '[': { + + r_token.type=TK_BRACKET_OPEN; + return OK; + }; + case ']': { + + r_token.type=TK_BRACKET_CLOSE; + return OK; + }; + case '(': { + + r_token.type=TK_PARENTHESIS_OPEN; + return OK; + }; + case ')': { + + r_token.type=TK_PARENTHESIS_CLOSE; + return OK; + }; + case ',': { + + r_token.type=TK_COMMA; + return OK; + }; + case ':': { + + r_token.type=TK_COLON; + return OK; + }; + case '.': { + + r_token.type=TK_PERIOD; + return OK; + }; + case '=': { + + cchar=GET_CHAR(); + if (cchar=='=') { + r_token.type=TK_OP_EQUAL; + } else { + _set_error("Expected '='"); + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } + return OK; + }; + case '!': { + + if (expression[str_ofs]=='=') { + r_token.type=TK_OP_NOT_EQUAL; + str_ofs++; + } else { + r_token.type=TK_OP_NOT; + } + return OK; + }; + case '>': { + + if (expression[str_ofs]=='=') { + r_token.type=TK_OP_GREATER_EQUAL; + str_ofs++; + } else if (expression[str_ofs]=='>') { + r_token.type=TK_OP_SHIFT_RIGHT; + str_ofs++; + } else { + r_token.type=TK_OP_GREATER; + } + return OK; + }; + case '<': { + + if (expression[str_ofs]=='=') { + r_token.type=TK_OP_LESS_EQUAL; + str_ofs++; + } else if (expression[str_ofs]=='<') { + r_token.type=TK_OP_SHIFT_LEFT; + str_ofs++; + } else { + r_token.type=TK_OP_LESS; + } + return OK; + }; + case '+': { + r_token.type=TK_OP_ADD; + return OK; + }; + case '-': { + r_token.type=TK_OP_SUB; + return OK; + }; + case '/': { + r_token.type=TK_OP_DIV; + return OK; + }; + case '*': { + r_token.type=TK_OP_MUL; + return OK; + }; + case '%': { + r_token.type=TK_OP_MOD; + return OK; + }; + case '&': { + + if (expression[str_ofs]=='&') { + r_token.type=TK_OP_AND; + str_ofs++; + } else { + r_token.type=TK_OP_BIT_AND; + } + return OK; + }; + case '|': { + + if (expression[str_ofs]=='|') { + r_token.type=TK_OP_OR; + str_ofs++; + } else { + r_token.type=TK_OP_BIT_OR; + } + return OK; + }; + case '^': { + + r_token.type=TK_OP_BIT_XOR; + + return OK; + }; + case '~': { + + r_token.type=TK_OP_BIT_INVERT; + + return OK; + }; + case '"': { + + + String str; + while(true) { + + CharType ch=GET_CHAR(); + + if (ch==0) { + _set_error("Unterminated String"); + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } else if (ch=='"') { + break; + } else if (ch=='\\') { + //escaped characters... + + CharType next = GET_CHAR(); + if (next==0) { + _set_error("Unterminated String"); + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } + CharType res=0; + + switch(next) { + + case 'b': res=8; break; + case 't': res=9; break; + case 'n': res=10; break; + case 'f': res=12; break; + case 'r': res=13; break; + case 'u': { + //hexnumbarh - oct is deprecated + + + for(int j=0;j<4;j++) { + CharType c = GET_CHAR(); + + if (c==0) { + _set_error("Unterminated String"); + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } + if (!((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'))) { + + _set_error("Malformed hex constant in string"); + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } + CharType v; + if (c>='0' && c<='9') { + v=c-'0'; + } else if (c>='a' && c<='f') { + v=c-'a'; + v+=10; + } else if (c>='A' && c<='F') { + v=c-'A'; + v+=10; + } else { + ERR_PRINT("BUG"); + v=0; + } + + res<<=4; + res|=v; + + + } + + + + } break; + //case '\"': res='\"'; break; + //case '\\': res='\\'; break; + //case '/': res='/'; break; + default: { + res = next; + //r_err_str="Invalid escape sequence"; + //return ERR_PARSE_ERROR; + } break; + } + + str+=res; + + } else { + str+=ch; + } + } + + r_token.type=TK_CONSTANT; + r_token.value=str; + return OK; + + } break; + default: { + + if (cchar<=32) { + break; + } + + if (cchar=='-' || (cchar>='0' && cchar<='9')) { + //a number + + + String num; +#define READING_SIGN 0 +#define READING_INT 1 +#define READING_DEC 2 +#define READING_EXP 3 +#define READING_DONE 4 + int reading=READING_INT; + + if (cchar=='-') { + num+='-'; + cchar=GET_CHAR(); + + } + + + + CharType c = cchar; + bool exp_sign=false; + bool exp_beg=false; + bool is_float=false; + + while(true) { + + switch(reading) { + case READING_INT: { + + if (c>='0' && c<='9') { + //pass + } else if (c=='.') { + reading=READING_DEC; + is_float=true; + } else if (c=='e') { + reading=READING_EXP; + } else { + reading=READING_DONE; + } + + } break; + case READING_DEC: { + + if (c>='0' && c<='9') { + + } else if (c=='e') { + reading=READING_EXP; + + } else { + reading=READING_DONE; + } + + } break; + case READING_EXP: { + + if (c>='0' && c<='9') { + exp_beg=true; + + } else if ((c=='-' || c=='+') && !exp_sign && !exp_beg) { + if (c=='-') + is_float=true; + exp_sign=true; + + } else { + reading=READING_DONE; + } + } break; + } + + if (reading==READING_DONE) + break; + num+=String::chr(c); + c = GET_CHAR(); + + + } + + str_ofs--; + + r_token.type=TK_CONSTANT; + + if (is_float) + r_token.value=num.to_double(); + else + r_token.value=num.to_int(); + return OK; + + } else if ((cchar>='A' && cchar<='Z') || (cchar>='a' && cchar<='z') || cchar=='_') { + + String id; + bool first=true; + + while((cchar>='A' && cchar<='Z') || (cchar>='a' && cchar<='z') || cchar=='_' || (!first && cchar>='0' && cchar<='9')) { + + id+=String::chr(cchar); + cchar=GET_CHAR(); + first=false; + } + + str_ofs--; //go back one + + if (id=="in") { + r_token.type=TK_OP_IN; + } else if (id=="null") { + r_token.type=TK_CONSTANT; + r_token.value=Variant(); + } else if (id=="true") { + r_token.type=TK_CONSTANT; + r_token.value=true; + } else if (id=="false") { + r_token.type=TK_CONSTANT; + r_token.value=false; + } else if (id=="PI") { + r_token.type=TK_CONSTANT; + r_token.value=Math_PI; + } else if (id=="not") { + r_token.type=TK_OP_NOT; + } else if (id=="or") { + r_token.type=TK_OP_OR; + } else if (id=="and") { + r_token.type=TK_OP_AND; + } else if (id=="self") { + r_token.type=TK_SELF; + } else { + + for(int i=0;i<Variant::VARIANT_MAX;i++) { + if (id==Variant::get_type_name(Variant::Type(i))) { + r_token.type=TK_BASIC_TYPE; + r_token.value=i; + return OK; + break; + } + } + + VisualScriptBuiltinFunc::BuiltinFunc bifunc = VisualScriptBuiltinFunc::find_function(id); + if (bifunc!=VisualScriptBuiltinFunc::FUNC_MAX) { + r_token.type=TK_BUILTIN_FUNC; + r_token.value=bifunc; + return OK; + } + + r_token.type=TK_IDENTIFIER; + r_token.value=id; + } + + return OK; + } else { + _set_error("Unexpected character."); + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } + } + } + } + + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; +} + +const char* VisualScriptExpression::token_name[TK_MAX]={ +"CURLY BRACKET OPEN", +"CURLY BRACKET CLOSE", +"BRACKET OPEN", +"BRACKET CLOSE", +"PARENTHESIS OPEN", +"PARENTHESIS CLOSE", +"IDENTIFIER", +"BUILTIN FUNC", +"SELF", +"CONSTANT", +"BASIC TYPE", +"COLON", +"COMMA", +"PERIOD", +"OP IN", +"OP EQUAL", +"OP NOT EQUAL", +"OP LESS", +"OP LESS EQUAL", +"OP GREATER", +"OP GREATER EQUAL", +"OP AND", +"OP OR", +"OP NOT", +"OP ADD", +"OP SUB", +"OP MUL", +"OP DIV", +"OP MOD", +"OP SHIFT LEFT", +"OP SHIFT RIGHT", +"OP BIT AND", +"OP BIT OR", +"OP BIT XOR", +"OP BIT INVERT", +"EOF", +"ERROR" +}; + +VisualScriptExpression::ENode* VisualScriptExpression::_parse_expression() { + + + Vector<Expression> expression; + + while(true) { + //keep appending stuff to expression + ENode*expr=NULL; + + Token tk; + _get_token(tk); + if (error_set) + return NULL; + + + + switch(tk.type) { + case TK_CURLY_BRACKET_OPEN: { + //a dictionary + DictionaryNode *dn = alloc_node<DictionaryNode>(); + + + while(true) { + + int cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_CURLY_BRACKET_CLOSE) { + break; + } + str_ofs=cofs; //revert + //parse an expression + ENode* expr=_parse_expression(); + if (!expr) + return NULL; + dn->dict.push_back(expr); + + _get_token(tk); + if (tk.type!=TK_COLON) { + _set_error("Expected ':'"); + return NULL; + } + + expr=_parse_expression(); + if (!expr) + return NULL; + + dn->dict.push_back(expr); + + cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_COMMA) { + //all good + } else if (tk.type==TK_CURLY_BRACKET_CLOSE) { + str_ofs=cofs; + } else { + _set_error("Expected ',' or '}'"); + } + } + + expr=dn; + } break; + case TK_BRACKET_OPEN: { + //an array + + ArrayNode *an = alloc_node<ArrayNode>(); + + + while(true) { + + int cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_BRACKET_CLOSE) { + break; + } + str_ofs=cofs; //revert + //parse an expression + ENode* expr=_parse_expression(); + if (!expr) + return NULL; + an->array.push_back(expr); + + cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_COMMA) { + //all good + } else if (tk.type==TK_BRACKET_CLOSE) { + str_ofs=cofs; + } else { + _set_error("Expected ',' or ']'"); + } + } + + expr=an; + } break; + case TK_PARENTHESIS_OPEN: { + //a suexpression + ENode* e=_parse_expression(); + if (error_set) + return NULL; + _get_token(tk); + if (tk.type!=TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')'"); + return NULL; + } + + expr=e; + + } break; + case TK_IDENTIFIER: { + + String what = tk.value; + int index=-1; + for(int i=0;i<inputs.size();i++) { + if (what==inputs[i].name) { + index=i; + break; + } + } + + if (index!=-1) { + InputNode *input = alloc_node<InputNode>(); + input->index=index; + expr=input; + } else { + _set_error("Invalid input identifier '"+what+"'. For script variables, use self (locals are for inputs)."+what); + return NULL; + } + } break; + case TK_SELF: { + + SelfNode *self = alloc_node<SelfNode>(); + expr=self; + } break; + case TK_CONSTANT: { + ConstantNode *constant = alloc_node<ConstantNode>(); + constant->value=tk.value; + expr=constant; + } break; + case TK_BASIC_TYPE: { + //constructor.. + + Variant::Type bt = Variant::Type(int(tk.value)); + _get_token(tk); + if (tk.type!=TK_PARENTHESIS_OPEN) { + _set_error("Expected '('"); + return NULL; + } + + ConstructorNode *constructor = alloc_node<ConstructorNode>(); + constructor->data_type=bt; + + while(true) { + + int cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_PARENTHESIS_CLOSE) { + break; + } + str_ofs=cofs; //revert + //parse an expression + ENode* expr=_parse_expression(); + if (!expr) + return NULL; + + constructor->arguments.push_back(expr); + + cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_COMMA) { + //all good + } else if (tk.type==TK_PARENTHESIS_CLOSE) { + str_ofs=cofs; + } else { + _set_error("Expected ',' or ')'"); + } + } + + expr=constructor; + + } break; + case TK_BUILTIN_FUNC: { + //builtin function + + Variant::Type bt = Variant::Type(int(tk.value)); + _get_token(tk); + if (tk.type!=TK_PARENTHESIS_OPEN) { + _set_error("Expected '('"); + return NULL; + } + + BuiltinFuncNode *bifunc = alloc_node<BuiltinFuncNode>(); + bifunc->func=VisualScriptBuiltinFunc::BuiltinFunc(int(tk.value)); + + while(true) { + + int cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_PARENTHESIS_CLOSE) { + break; + } + str_ofs=cofs; //revert + //parse an expression + ENode* expr=_parse_expression(); + if (!expr) + return NULL; + + bifunc->arguments.push_back(expr); + + cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_COMMA) { + //all good + } else if (tk.type==TK_PARENTHESIS_CLOSE) { + str_ofs=cofs; + } else { + _set_error("Expected ',' or ')'"); + } + } + + int expected_args = VisualScriptBuiltinFunc::get_func_argument_count(bifunc->func); + if (bifunc->arguments.size() != expected_args) { + _set_error("Builtin func '"+VisualScriptBuiltinFunc::get_func_name(bifunc->func)+"' expects "+itos(expected_args)+" arguments."); + } + + expr=bifunc; + + } break; + case TK_OP_SUB: { + + Expression e; + e.is_op=true; + e.op=Variant::OP_NEGATE; + expression.push_back(e); + continue; + } break; + case TK_OP_NOT: { + + Expression e; + e.is_op=true; + e.op=Variant::OP_NOT; + expression.push_back(e); + continue; + } break; + + default: { + _set_error("Expected expression."); + return NULL; + } break; + + } + + //before going to operators, must check indexing! + + while(true) { + int cofs2=str_ofs; + _get_token(tk); + if (error_set) + return NULL; + + bool done=false; + + switch(tk.type) { + case TK_BRACKET_OPEN: { + //value indexing + + IndexNode *index = alloc_node<IndexNode>(); + index->base=expr; + + ENode* what=_parse_expression(); + if (!what) + return NULL; + + index->index=what; + + _get_token(tk); + if (tk.type!=TK_BRACKET_CLOSE) { + _set_error("Expected ']' at end of index."); + return NULL; + } + expr=index; + + } break; + case TK_PERIOD: { + //named indexing or function call + _get_token(tk); + if (tk.type!=TK_IDENTIFIER) { + _set_error("Expected identifier after '.'"); + return NULL; + } + + StringName identifier=tk.value; + + int cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_PARENTHESIS_OPEN) { + //function call + CallNode *func_call = alloc_node<CallNode>(); + func_call->method=identifier; + func_call->base=expr; + + while(true) { + + int cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_PARENTHESIS_CLOSE) { + break; + } + str_ofs=cofs; //revert + //parse an expression + ENode* expr=_parse_expression(); + if (!expr) + return NULL; + + func_call->arguments.push_back(expr); + + cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_COMMA) { + //all good + } else if (tk.type==TK_PARENTHESIS_CLOSE) { + str_ofs=cofs; + } else { + _set_error("Expected ',' or ')'"); + } + } + + expr=func_call; + } else { + //named indexing + str_ofs=cofs; + + NamedIndexNode *index = alloc_node<NamedIndexNode>(); + index->base=expr; + index->name=identifier; + expr=index; + + } + + } break; + default: { + str_ofs=cofs2; + done=true; + } break; + } + + if (done) + break; + } + + //push expression + { + Expression e; + e.is_op=false; + e.node=expr; + expression.push_back(e); + } + + //ok finally look for an operator + + + int cofs=str_ofs; + _get_token(tk); + if (error_set) + return NULL; + + + Variant::Operator op = Variant::OP_MAX; + + switch(tk.type) { + case TK_OP_IN: op=Variant::OP_IN; break; + case TK_OP_EQUAL: op=Variant::OP_EQUAL; break; + case TK_OP_NOT_EQUAL: op=Variant::OP_NOT_EQUAL; break; + case TK_OP_LESS: op=Variant::OP_LESS; break; + case TK_OP_LESS_EQUAL: op=Variant::OP_LESS_EQUAL; break; + case TK_OP_GREATER: op=Variant::OP_GREATER; break; + case TK_OP_GREATER_EQUAL: op=Variant::OP_GREATER_EQUAL; break; + case TK_OP_AND: op=Variant::OP_AND; break; + case TK_OP_OR: op=Variant::OP_OR; break; + case TK_OP_NOT: op=Variant::OP_NOT; break; + case TK_OP_ADD: op=Variant::OP_ADD; break; + case TK_OP_SUB: op=Variant::OP_SUBSTRACT; break; + case TK_OP_MUL: op=Variant::OP_MULTIPLY; break; + case TK_OP_DIV: op=Variant::OP_DIVIDE; break; + case TK_OP_MOD: op=Variant::OP_MODULE; break; + case TK_OP_SHIFT_LEFT: op=Variant::OP_SHIFT_LEFT; break; + case TK_OP_SHIFT_RIGHT: op=Variant::OP_SHIFT_RIGHT; break; + case TK_OP_BIT_AND: op=Variant::OP_BIT_AND; break; + case TK_OP_BIT_OR: op=Variant::OP_BIT_OR; break; + case TK_OP_BIT_XOR: op=Variant::OP_BIT_XOR; break; + case TK_OP_BIT_INVERT: op=Variant::OP_BIT_NEGATE; break; + default: {}; + } + + if (op==Variant::OP_MAX) { //stop appending stuff + str_ofs=cofs; + break; + } + + //push operator and go on + { + Expression e; + e.is_op=true; + e.op=op; + expression.push_back(e); + } + } + + + /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */ + + + while(expression.size()>1) { + + int next_op=-1; + int min_priority=0xFFFFF; + bool is_unary=false; + + for(int i=0;i<expression.size();i++) { + + + + if (!expression[i].is_op) { + + continue; + } + + int priority; + + bool unary=false; + + switch(expression[i].op) { + + + case Variant::OP_BIT_NEGATE: priority=0; unary=true; break; + case Variant::OP_NEGATE: priority=1; unary=true; break; + + case Variant::OP_MULTIPLY: priority=2; break; + case Variant::OP_DIVIDE: priority=2; break; + case Variant::OP_MODULE: priority=2; break; + + case Variant::OP_ADD: priority=3; break; + case Variant::OP_SUBSTRACT: priority=3; break; + + case Variant::OP_SHIFT_LEFT: priority=4; break; + case Variant::OP_SHIFT_RIGHT: priority=4; break; + + case Variant::OP_BIT_AND: priority=5; break; + case Variant::OP_BIT_XOR: priority=6; break; + case Variant::OP_BIT_OR: priority=7; break; + + case Variant::OP_LESS: priority=8; break; + case Variant::OP_LESS_EQUAL: priority=8; break; + case Variant::OP_GREATER: priority=8; break; + case Variant::OP_GREATER_EQUAL: priority=8; break; + + case Variant::OP_EQUAL: priority=8; break; + case Variant::OP_NOT_EQUAL: priority=8; break; + + case Variant::OP_IN: priority=10; break; + + case Variant::OP_NOT: priority=11; unary=true; break; + case Variant::OP_AND: priority=12; break; + case Variant::OP_OR: priority=13; break; + + + default: { + _set_error("Parser bug, invalid operator in expression: "+itos(expression[i].op)); + return NULL; + } + + } + + if (priority<min_priority) { + // < is used for left to right (default) + // <= is used for right to left + + next_op=i; + min_priority=priority; + is_unary=unary; + } + + } + + if (next_op==-1) { + + + _set_error("Yet another parser bug...."); + ERR_FAIL_COND_V(next_op==-1,NULL); + } + + + // OK! create operator.. + if (is_unary) { + + int expr_pos=next_op; + while(expression[expr_pos].is_op) { + + expr_pos++; + if (expr_pos==expression.size()) { + //can happen.. + _set_error("Unexpected end of expression.."); + return NULL; + } + } + + //consecutively do unary opeators + for(int i=expr_pos-1;i>=next_op;i--) { + + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=expression[i].op; + op->nodes[0]=expression[i+1].node; + op->nodes[1]=NULL; + expression[i].is_op=false; + expression[i].node=op; + expression.remove(i+1); + } + + + } else { + + if (next_op <1 || next_op>=(expression.size()-1)) { + _set_error("Parser bug.."); + ERR_FAIL_V(NULL); + } + + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=expression[next_op].op; + + if (expression[next_op-1].is_op) { + + _set_error("Parser bug.."); + ERR_FAIL_V(NULL); + } + + if (expression[next_op+1].is_op) { + // this is not invalid and can really appear + // but it becomes invalid anyway because no binary op + // can be followed by an unary op in a valid combination, + // due to how precedence works, unaries will always dissapear first + + _set_error("Unexpected two consecutive operators."); + return NULL; + } + + + op->nodes[0]=expression[next_op-1].node; //expression goes as left + op->nodes[1]=expression[next_op+1].node; //next expression goes as right + + //replace all 3 nodes by this operator and make it an expression + expression[next_op-1].node=op; + expression.remove(next_op); + expression.remove(next_op); + } + } + + return expression[0].node; +} + +bool VisualScriptExpression::_compile_expression() { + + if (!expression_dirty) + return error_set; + + if (nodes) { + memdelete(nodes); + nodes=NULL; + root=NULL; + + } + + error_str=String(); + error_set=false; + str_ofs=0; + + root=_parse_expression(); + + if (error_set) { + root=NULL; + if (nodes) { + memdelete(nodes); + } + nodes=NULL; + return true; + } + + expression_dirty=false; + return false; +} + + +class VisualScriptNodeInstanceExpression : public VisualScriptNodeInstance { +public: + + VisualScriptInstance* instance; + VisualScriptExpression *expression; + + //virtual int get_working_memory_size() const { return 0; } + //execute by parsing the tree directly + virtual bool _execute(const Variant** p_inputs,VisualScriptExpression::ENode *p_node,Variant& r_ret,String& r_error_str,Variant::CallError &ce) { + + switch(p_node->type) { + case VisualScriptExpression::ENode::TYPE_INPUT: { + + const VisualScriptExpression::InputNode *in = static_cast<const VisualScriptExpression::InputNode*>(p_node); + r_ret=*p_inputs[in->index]; + } break; + case VisualScriptExpression::ENode::TYPE_CONSTANT: { + + const VisualScriptExpression::ConstantNode *c = static_cast<const VisualScriptExpression::ConstantNode*>(p_node); + r_ret=c->value; + + } break; + case VisualScriptExpression::ENode::TYPE_SELF: { + + r_ret=instance->get_owner_ptr(); + } break; + case VisualScriptExpression::ENode::TYPE_OPERATOR: { + + + const VisualScriptExpression::OperatorNode *op = static_cast<const VisualScriptExpression::OperatorNode*>(p_node); + + Variant a; + bool ret = _execute(p_inputs,op->nodes[0],a,r_error_str,ce); + if (ret) + return true; + + Variant b; + + if (op->nodes[1]) { + ret = _execute(p_inputs,op->nodes[1],b,r_error_str,ce); + if (ret) + return true; + } + + bool valid=true; + Variant::evaluate(op->op,a,b,r_ret,valid); + if (!valid) { + r_error_str="Invalid operands to operator "+Variant::get_operator_name(op->op)+": "+Variant::get_type_name(a.get_type())+" and "+Variant::get_type_name(b.get_type())+"."; + return true; + } + + } break; + case VisualScriptExpression::ENode::TYPE_INDEX: { + + const VisualScriptExpression::IndexNode *index = static_cast<const VisualScriptExpression::IndexNode*>(p_node); + + Variant base; + bool ret = _execute(p_inputs,index->base,base,r_error_str,ce); + if (ret) + return true; + + Variant idx; + + ret = _execute(p_inputs,index->index,idx,r_error_str,ce); + if (ret) + return true; + + bool valid; + r_ret=base.get(idx,&valid); + if (!valid) { + r_error_str="Invalid index of type "+Variant::get_type_name(idx.get_type())+" for base of type "+Variant::get_type_name(base.get_type())+"."; + return true; + } + + + + } break; + case VisualScriptExpression::ENode::TYPE_NAMED_INDEX: { + + const VisualScriptExpression::NamedIndexNode *index = static_cast<const VisualScriptExpression::NamedIndexNode*>(p_node); + + Variant base; + bool ret = _execute(p_inputs,index->base,base,r_error_str,ce); + if (ret) + return true; + + bool valid; + r_ret=base.get_named(index->name,&valid); + if (!valid) { + r_error_str="Invalid index '"+String(index->name)+"' for base of type "+Variant::get_type_name(base.get_type())+"."; + return true; + } + + } break; + case VisualScriptExpression::ENode::TYPE_ARRAY: { + const VisualScriptExpression::ArrayNode *array = static_cast<const VisualScriptExpression::ArrayNode*>(p_node); + + Array arr; + arr.resize(array->array.size()); + for (int i=0;i<array->array.size();i++) { + + Variant value; + bool ret = _execute(p_inputs,array->array[i],value,r_error_str,ce); + if (ret) + return true; + arr[i]=value; + } + + r_ret=arr; + + } break; + case VisualScriptExpression::ENode::TYPE_DICTIONARY: { + const VisualScriptExpression::DictionaryNode *dictionary = static_cast<const VisualScriptExpression::DictionaryNode*>(p_node); + + Dictionary d; + for (int i=0;i<dictionary->dict.size();i+=2) { + + Variant key; + bool ret = _execute(p_inputs,dictionary->dict[i+0],key,r_error_str,ce); + if (ret) + return true; + + Variant value; + ret = _execute(p_inputs,dictionary->dict[i+1],value,r_error_str,ce); + if (ret) + return true; + + d[key]=value; + } + + r_ret=d; + } break; + case VisualScriptExpression::ENode::TYPE_CONSTRUCTOR: { + + const VisualScriptExpression::ConstructorNode *constructor = static_cast<const VisualScriptExpression::ConstructorNode*>(p_node); + + Vector<Variant> arr; + Vector<const Variant*> argp; + arr.resize(constructor->arguments.size()); + argp.resize(constructor->arguments.size()); + + for (int i=0;i<constructor->arguments.size();i++) { + + Variant value; + bool ret = _execute(p_inputs,constructor->arguments[i],value,r_error_str,ce); + if (ret) + return true; + arr[i]=value; + argp[i]=&arr[i]; + } + + + r_ret=Variant::construct(constructor->data_type,argp.ptr(),argp.size(),ce); + + if (ce.error!=Variant::CallError::CALL_OK) { + r_error_str="Invalid arguments to construct '"+Variant::get_type_name(constructor->data_type)+"'."; + return true; + } + + + } break; + case VisualScriptExpression::ENode::TYPE_BUILTIN_FUNC: { + + const VisualScriptExpression::BuiltinFuncNode *bifunc = static_cast<const VisualScriptExpression::BuiltinFuncNode*>(p_node); + + Vector<Variant> arr; + Vector<const Variant*> argp; + arr.resize(bifunc->arguments.size()); + argp.resize(bifunc->arguments.size()); + + for (int i=0;i<bifunc->arguments.size();i++) { + + Variant value; + bool ret = _execute(p_inputs,bifunc->arguments[i],value,r_error_str,ce); + if (ret) + return true; + arr[i]=value; + argp[i]=&arr[i]; + } + + + VisualScriptBuiltinFunc::exec_func(bifunc->func,argp.ptr(),&r_ret,ce,r_error_str); + + if (ce.error!=Variant::CallError::CALL_OK) { + r_error_str="Builtin Call Failed. "+r_error_str; + return true; + } + + } break; + case VisualScriptExpression::ENode::TYPE_CALL: { + + const VisualScriptExpression::CallNode *call = static_cast<const VisualScriptExpression::CallNode*>(p_node); + + + Variant base; + bool ret = _execute(p_inputs,call->base,base,r_error_str,ce); + if (ret) + return true; + + Vector<Variant> arr; + Vector<const Variant*> argp; + arr.resize(call->arguments.size()); + argp.resize(call->arguments.size()); + + for (int i=0;i<call->arguments.size();i++) { + + Variant value; + bool ret = _execute(p_inputs,call->arguments[i],value,r_error_str,ce); + if (ret) + return true; + arr[i]=value; + argp[i]=&arr[i]; + } + + + r_ret=base.call(call->method,argp.ptr(),argp.size(),ce); + + if (ce.error!=Variant::CallError::CALL_OK) { + r_error_str="On call to '"+String(call->method)+"':"; + return true; + } + + } break; + } + return false; + } + + virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) { + + if (!expression->root || expression->error_set) { + r_error_str=expression->error_str; + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + return 0; + } + + + bool error = _execute(p_inputs,expression->root,*p_outputs[0],r_error_str,r_error); + if (error && r_error.error==Variant::CallError::CALL_OK) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + } + +#ifdef DEBUG_ENABLED + if (!error && expression->output_type!=Variant::NIL && !Variant::can_convert_strict(p_outputs[0]->get_type(),expression->output_type)) { + + r_error_str+="Can't convert expression result from "+Variant::get_type_name(p_outputs[0]->get_type())+" to "+Variant::get_type_name(expression->output_type)+"."; + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + + } +#endif + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptExpression::instance(VisualScriptInstance* p_instance){ + + _compile_expression(); + VisualScriptNodeInstanceExpression *instance = memnew( VisualScriptNodeInstanceExpression ); + instance->instance=p_instance; + instance->expression=this; + return instance; +} + + +VisualScriptExpression::VisualScriptExpression() +{ + output_type=Variant::NIL; + expression_dirty=true; + error_set=true; + root=NULL; + nodes=NULL; + sequenced=false; +} + +VisualScriptExpression::~VisualScriptExpression() { + + if (nodes) { + memdelete(nodes); + } +} + + +void register_visual_script_expression_node() { + + VisualScriptLanguage::singleton->add_register_func("operators/expression",create_node_generic<VisualScriptExpression>); + +} diff --git a/modules/visual_script/visual_script_expression.h b/modules/visual_script/visual_script_expression.h new file mode 100644 index 0000000000..4edae133c7 --- /dev/null +++ b/modules/visual_script/visual_script_expression.h @@ -0,0 +1,280 @@ +#ifndef VISUALSCRIPTEXPRESSION_H +#define VISUALSCRIPTEXPRESSION_H + +#include "visual_script.h" +#include "visual_script_builtin_funcs.h" + +class VisualScriptExpression : public VisualScriptNode { + + OBJ_TYPE(VisualScriptExpression,VisualScriptNode) +friend class VisualScriptNodeInstanceExpression; + + struct Input { + + Variant::Type type; + String name; + + Input() { type=Variant::NIL; } + }; + + Vector<Input> inputs; + Variant::Type output_type; + + String expression; + + bool sequenced; + int str_ofs; + bool expression_dirty; + + bool _compile_expression(); + + enum TokenType { + TK_CURLY_BRACKET_OPEN, + TK_CURLY_BRACKET_CLOSE, + TK_BRACKET_OPEN, + TK_BRACKET_CLOSE, + TK_PARENTHESIS_OPEN, + TK_PARENTHESIS_CLOSE, + TK_IDENTIFIER, + TK_BUILTIN_FUNC, + TK_SELF, + TK_CONSTANT, + TK_BASIC_TYPE, + TK_COLON, + TK_COMMA, + TK_PERIOD, + TK_OP_IN, + TK_OP_EQUAL, + TK_OP_NOT_EQUAL, + TK_OP_LESS, + TK_OP_LESS_EQUAL, + TK_OP_GREATER, + TK_OP_GREATER_EQUAL, + TK_OP_AND, + TK_OP_OR, + TK_OP_NOT, + TK_OP_ADD, + TK_OP_SUB, + TK_OP_MUL, + TK_OP_DIV, + TK_OP_MOD, + TK_OP_SHIFT_LEFT, + TK_OP_SHIFT_RIGHT, + TK_OP_BIT_AND, + TK_OP_BIT_OR, + TK_OP_BIT_XOR, + TK_OP_BIT_INVERT, + TK_EOF, + TK_ERROR, + TK_MAX + }; + + static const char* token_name[TK_MAX]; + struct Token { + + TokenType type; + Variant value; + }; + + + void _set_error(const String& p_err) { + if (error_set) + return; + error_str=p_err; + error_set=true; + } + + Error _get_token(Token& r_token); + + String error_str; + bool error_set; + + + + struct ENode { + + enum Type { + TYPE_INPUT, + TYPE_CONSTANT, + TYPE_SELF, + TYPE_OPERATOR, + TYPE_INDEX, + TYPE_NAMED_INDEX, + TYPE_ARRAY, + TYPE_DICTIONARY, + TYPE_CONSTRUCTOR, + TYPE_BUILTIN_FUNC, + TYPE_CALL + }; + + ENode *next; + + Type type; + + ENode() { next=NULL; } + virtual ~ENode() { if (next) { memdelete(next); } } + }; + + struct Expression { + + bool is_op; + union { + Variant::Operator op; + ENode *node; + }; + }; + + ENode* _parse_expression(); + + struct InputNode : public ENode { + + int index; + InputNode() { + type=TYPE_INPUT; + } + }; + + + struct ConstantNode : public ENode { + + Variant value; + ConstantNode() { + type=TYPE_CONSTANT; + } + }; + + struct OperatorNode : public ENode { + + Variant::Operator op; + + ENode* nodes[2]; + + OperatorNode() { + type=TYPE_OPERATOR; + } + }; + + struct SelfNode : public ENode { + + + SelfNode() { + type=TYPE_SELF; + } + }; + + struct IndexNode : public ENode { + ENode*base; + ENode*index; + + IndexNode() { + type=TYPE_INDEX; + } + }; + + struct NamedIndexNode : public ENode { + ENode*base; + StringName name; + + NamedIndexNode() { + type=TYPE_NAMED_INDEX; + } + + }; + + struct ConstructorNode : public ENode { + Variant::Type data_type; + Vector<ENode*> arguments; + + ConstructorNode() { + type=TYPE_CONSTRUCTOR; + } + }; + + struct CallNode : public ENode { + ENode*base; + StringName method; + Vector<ENode*> arguments; + + CallNode() { + type=TYPE_CALL; + } + + }; + + struct ArrayNode : public ENode { + Vector<ENode*> array; + ArrayNode() { + type=TYPE_ARRAY; + } + + }; + + struct DictionaryNode : public ENode { + Vector<ENode*> dict; + DictionaryNode() { + type=TYPE_DICTIONARY; + } + + }; + + struct BuiltinFuncNode : public ENode { + VisualScriptBuiltinFunc::BuiltinFunc func; + Vector<ENode*> arguments; + BuiltinFuncNode() { + type=TYPE_BUILTIN_FUNC; + } + }; + + template<class T> + T* alloc_node() { + T* node = memnew(T); + node->next=nodes; + nodes=node; + return node; + } + + ENode *root; + ENode *nodes; + + + + + +protected: + + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List<PropertyInfo> *p_list) const; + +public: + + + virtual int get_output_sequence_port_count() const; + virtual bool has_input_sequence_port() const; + + + virtual String get_output_sequence_port_text(int p_port) const; + + + virtual int get_input_value_port_count() const; + virtual int get_output_value_port_count() const; + + + virtual PropertyInfo get_input_value_port_info(int p_idx) const; + virtual PropertyInfo get_output_value_port_info(int p_idx) const; + + virtual String get_caption() const; + virtual String get_text() const; + virtual String get_category() const { return "operators"; } + + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + + VisualScriptExpression(); + ~VisualScriptExpression(); +}; + + +void register_visual_script_expression_node(); + + +#endif // VISUALSCRIPTEXPRESSION_H diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index de99beacaf..5a21cb40e9 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -417,6 +417,14 @@ void VisualScriptFunctionCall::_update_method_cache() { method_cache.return_val = mb->get_argument_info(-1); #endif + + if (mb->is_vararg()) { + //for vararg just give it 10 arguments (should be enough for most use cases) + for(int i=0;i<10;i++) { + method_cache.arguments.push_back(PropertyInfo(Variant::NIL,"arg"+itos(i))); + use_default_args++; + } + } } else if (script.is_valid() && script->has_method(function)) { method_cache = script->get_method_info(function); diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 03fd70b0a3..7ada292b13 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -553,7 +553,7 @@ void VisualScriptOperator::_bind_methods() { argt+=","+Variant::get_type_name(Variant::Type(i)); } - ADD_PROPERTY(PropertyInfo(Variant::INT,"operator_value/type",PROPERTY_HINT_ENUM,types,PROPERTY_USAGE_NOEDITOR),_SCS("set_operator"),_SCS("get_operator")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"operator_value/type",PROPERTY_HINT_ENUM,types),_SCS("set_operator"),_SCS("get_operator")); ADD_PROPERTY(PropertyInfo(Variant::INT,"typed_value/typed",PROPERTY_HINT_ENUM,argt),_SCS("set_typed"),_SCS("get_typed")); } diff --git a/modules/vorbis/SCsub b/modules/vorbis/SCsub new file mode 100644 index 0000000000..3220cb454c --- /dev/null +++ b/modules/vorbis/SCsub @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_vorbis = env_modules.Clone() + +# Thirdparty source files +if (env["libvorbis"] != "system"): # builtin + thirdparty_dir = "#thirdparty/libvorbis/" + thirdparty_sources = [ + #"analysis.c", + #"barkmel.c", + "bitrate.c", + "block.c", + "codebook.c", + "envelope.c", + "floor0.c", + "floor1.c", + "info.c", + "lookup.c", + "lpc.c", + "lsp.c", + "mapping0.c", + "mdct.c", + "psy.c", + #"psytune.c", + "registry.c", + "res0.c", + "sharedbook.c", + "smallft.c", + "synthesis.c", + #"tone.c", + #"vorbisenc.c", + "vorbisfile.c", + "window.c", + ] + + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + + env_vorbis.add_source_files(env.modules_sources, thirdparty_sources) + env_vorbis.Append(CPPPATH = [thirdparty_dir]) + + # also requires libogg + if (env["libogg"] != "system"): # builtin + env_vorbis.Append(CPPPATH = ["#thirdparty/libogg"]) + +# Godot source files +env_vorbis.add_source_files(env.modules_sources, "*.cpp") diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp index 4ce7940a01..4ce7940a01 100644 --- a/drivers/vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp diff --git a/modules/vorbis/audio_stream_ogg_vorbis.h b/modules/vorbis/audio_stream_ogg_vorbis.h new file mode 100644 index 0000000000..8d8d7392b5 --- /dev/null +++ b/modules/vorbis/audio_stream_ogg_vorbis.h @@ -0,0 +1,142 @@ +/*************************************************************************/ +/* audio_stream_ogg_vorbis.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef AUDIO_STREAM_OGG_VORBIS_H +#define AUDIO_STREAM_OGG_VORBIS_H + +#include "io/resource_loader.h" +#include "os/file_access.h" +#include "os/thread_safe.h" +#include "scene/resources/audio_stream.h" + +#include <vorbis/vorbisfile.h> + +class AudioStreamPlaybackOGGVorbis : public AudioStreamPlayback { + + OBJ_TYPE(AudioStreamPlaybackOGGVorbis,AudioStreamPlayback); + + enum { + MIN_MIX=1024 + }; + + FileAccess *f; + + ov_callbacks _ov_callbacks; + float length; + static size_t _ov_read_func(void *p_dst,size_t p_data, size_t p_count, void *_f); + static int _ov_seek_func(void *_f,ogg_int64_t offs, int whence); + static int _ov_close_func(void *_f); + static long _ov_tell_func(void *_f); + + String file; + int64_t frames_mixed; + + bool stream_loaded; + volatile bool playing; + OggVorbis_File vf; + int stream_channels; + int stream_srate; + int current_section; + + + bool paused; + bool loops; + int repeats; + + Error _load_stream(); + void _clear_stream(); + void _close_file(); + + bool stream_valid; + float loop_restart_time; + + +public: + + + Error set_file(const String& p_file); + + virtual void play(float p_from=0); + virtual void stop(); + virtual bool is_playing() const; + + virtual void set_loop_restart_time(float p_time) { loop_restart_time=p_time; } + + virtual void set_paused(bool p_paused); + virtual bool is_paused(bool p_paused) const; + + virtual void set_loop(bool p_enable); + virtual bool has_loop() const; + + virtual float get_length() const; + + virtual String get_stream_name() const; + + virtual int get_loop_count() const; + + virtual float get_pos() const; + virtual void seek_pos(float p_time); + + virtual int get_channels() const { return stream_channels; } + virtual int get_mix_rate() const { return stream_srate; } + + virtual int get_minimum_buffer_size() const { return 0; } + virtual int mix(int16_t* p_bufer,int p_frames); + + AudioStreamPlaybackOGGVorbis(); + ~AudioStreamPlaybackOGGVorbis(); +}; + + +class AudioStreamOGGVorbis : public AudioStream { + + OBJ_TYPE(AudioStreamOGGVorbis,AudioStream); + + String file; +public: + + Ref<AudioStreamPlayback> instance_playback() { + Ref<AudioStreamPlaybackOGGVorbis> pb = memnew( AudioStreamPlaybackOGGVorbis ); + pb->set_file(file); + return pb; + } + + void set_file(const String& p_file) { file=p_file; } + +}; + +class ResourceFormatLoaderAudioStreamOGGVorbis : public ResourceFormatLoader { +public: + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String& p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + + +#endif // AUDIO_STREAM_OGG_H diff --git a/modules/vorbis/config.py b/modules/vorbis/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/vorbis/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/modules/vorbis/register_types.cpp b/modules/vorbis/register_types.cpp new file mode 100644 index 0000000000..ae63b5af3c --- /dev/null +++ b/modules/vorbis/register_types.cpp @@ -0,0 +1,45 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#include "audio_stream_ogg_vorbis.h" + +static ResourceFormatLoaderAudioStreamOGGVorbis *vorbis_stream_loader = NULL; + +void register_vorbis_types() { + + vorbis_stream_loader = memnew( ResourceFormatLoaderAudioStreamOGGVorbis ); + ResourceLoader::add_resource_format_loader(vorbis_stream_loader); + ObjectTypeDB::register_type<AudioStreamOGGVorbis>(); +} + +void unregister_vorbis_types() { + + memdelete( vorbis_stream_loader ); +} diff --git a/modules/vorbis/register_types.h b/modules/vorbis/register_types.h new file mode 100644 index 0000000000..6baaed7ce8 --- /dev/null +++ b/modules/vorbis/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_vorbis_types(); +void unregister_vorbis_types(); diff --git a/modules/webp/SCsub b/modules/webp/SCsub new file mode 100644 index 0000000000..38585a1ff2 --- /dev/null +++ b/modules/webp/SCsub @@ -0,0 +1,121 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_webp = env_modules.Clone() + +# Thirdparty source files +if (env["libwebp"] != "system"): # builtin + thirdparty_dir = "#thirdparty/libwebp/" + thirdparty_sources = [ + "enc/webpenc.c", + "enc/near_lossless.c", + "enc/frame.c", + "enc/alpha.c", + "enc/picture_csp.c", + "enc/vp8l.c", + "enc/picture_psnr.c", + "enc/delta_palettization.c", + "enc/syntax.c", + "enc/backward_references.c", + "enc/token.c", + "enc/analysis.c", + "enc/iterator.c", + "enc/picture_tools.c", + "enc/picture_rescale.c", + "enc/config.c", + "enc/tree.c", + "enc/cost.c", + "enc/picture.c", + "enc/quant.c", + "enc/filter.c", + "enc/histogram.c", + "utils/rescaler.c", + "utils/filters.c", + "utils/quant_levels_dec.c", + "utils/huffman.c", + "utils/thread.c", + "utils/quant_levels.c", + "utils/bit_writer.c", + "utils/bit_reader.c", + "utils/random.c", + "utils/utils.c", + "utils/huffman_encode.c", + "utils/color_cache.c", + "mux/muxinternal.c", + "mux/muxread.c", + "mux/anim_encode.c", + "mux/muxedit.c", + "dec/webp.c", + "dec/frame.c", + "dec/alpha.c", + "dec/vp8l.c", + "dec/io.c", + "dec/vp8.c", + "dec/idec.c", + "dec/tree.c", + "dec/buffer.c", + "dec/quant.c", + "demux/demux.c", + "demux/anim_decode.c", + "dsp/yuv.c", + "dsp/filters_sse2.c", + "dsp/dec_sse41.c", + "dsp/rescaler.c", + "dsp/lossless_sse2.c", + "dsp/alpha_processing_sse41.c", + "dsp/alpha_processing_sse2.c", + "dsp/filters.c", + "dsp/upsampling_mips_dsp_r2.c", + "dsp/dec_neon.c", + "dsp/enc_neon.c", + "dsp/lossless_enc_mips32.c", + "dsp/lossless_enc_sse2.c", + "dsp/upsampling.c", + "dsp/lossless_enc_neon.c", + "dsp/alpha_processing.c", + "dsp/cost_sse2.c", + "dsp/dec_mips32.c", + "dsp/enc_avx2.c", + "dsp/rescaler_mips32.c", + "dsp/enc.c", + "dsp/lossless_enc_sse41.c", + "dsp/cost_mips32.c", + "dsp/lossless_mips_dsp_r2.c", + "dsp/filters_mips_dsp_r2.c", + "dsp/upsampling_neon.c", + "dsp/alpha_processing_mips_dsp_r2.c", + "dsp/enc_mips_dsp_r2.c", + "dsp/lossless.c", + "dsp/yuv_mips_dsp_r2.c", + "dsp/cost_mips_dsp_r2.c", + "dsp/argb.c", + "dsp/dec_sse2.c", + "dsp/rescaler_sse2.c", + "dsp/enc_sse41.c", + "dsp/argb_mips_dsp_r2.c", + "dsp/lossless_enc_mips_dsp_r2.c", + "dsp/dec_clip_tables.c", + "dsp/yuv_mips32.c", + "dsp/cpu.c", + "dsp/dec.c", + "dsp/argb_sse2.c", + "dsp/lossless_neon.c", + "dsp/lossless_enc.c", + "dsp/enc_mips32.c", + "dsp/cost.c", + "dsp/rescaler_mips_dsp_r2.c", + "dsp/dec_mips_dsp_r2.c", + "dsp/rescaler_neon.c", + "dsp/yuv_sse2.c", + "dsp/enc_sse2.c", + "dsp/upsampling_sse2.c", + ] + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + + env_webp.add_source_files(env.modules_sources, thirdparty_sources) + env_webp.Append(CPPPATH = [thirdparty_dir]) + +# Godot source files +env_webp.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/webp/config.py b/modules/webp/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/webp/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/modules/webp/image_loader_webp.cpp b/modules/webp/image_loader_webp.cpp new file mode 100644 index 0000000000..0fe2db3261 --- /dev/null +++ b/modules/webp/image_loader_webp.cpp @@ -0,0 +1,183 @@ +/*************************************************************************/ +/* image_loader_webp.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "image_loader_webp.h" + +#include "io/marshalls.h" +#include "print_string.h" +#include "os/os.h" + +#include <stdlib.h> +#include <webp/decode.h> +#include <webp/encode.h> + +static DVector<uint8_t> _webp_lossy_pack(const Image& p_image,float p_quality) { + + ERR_FAIL_COND_V(p_image.empty(),DVector<uint8_t>()); + + Image img=p_image; + if (img.detect_alpha()) + img.convert(Image::FORMAT_RGBA); + else + img.convert(Image::FORMAT_RGB); + + Size2 s(img.get_width(),img.get_height()); + DVector<uint8_t> data = img.get_data(); + DVector<uint8_t>::Read r = data.read(); + + uint8_t *dst_buff=NULL; + size_t dst_size=0; + if (img.get_format()==Image::FORMAT_RGB) { + + dst_size = WebPEncodeRGB(r.ptr(),s.width,s.height,3*s.width,CLAMP(p_quality*100.0,0,100.0),&dst_buff); + } else { + dst_size = WebPEncodeRGBA(r.ptr(),s.width,s.height,4*s.width,CLAMP(p_quality*100.0,0,100.0),&dst_buff); + } + + ERR_FAIL_COND_V(dst_size==0,DVector<uint8_t>()); + DVector<uint8_t> dst; + dst.resize(4+dst_size); + DVector<uint8_t>::Write w = dst.write(); + w[0]='W'; + w[1]='E'; + w[2]='B'; + w[3]='P'; + copymem(&w[4],dst_buff,dst_size); + free(dst_buff); + w=DVector<uint8_t>::Write(); + return dst; +} + +static Image _webp_lossy_unpack(const DVector<uint8_t>& p_buffer) { + + int size = p_buffer.size()-4; + ERR_FAIL_COND_V(size<=0,Image()); + DVector<uint8_t>::Read r = p_buffer.read(); + + ERR_FAIL_COND_V(r[0]!='W' || r[1]!='E' || r[2]!='B' || r[3]!='P',Image()); + WebPBitstreamFeatures features; + if (WebPGetFeatures(&r[4],size,&features)!=VP8_STATUS_OK) { + ERR_EXPLAIN("Error unpacking WEBP image:"); + ERR_FAIL_V(Image()); + } + + //print_line("width: "+itos(features.width)); + //print_line("height: "+itos(features.height)); + //print_line("alpha: "+itos(features.has_alpha)); + + DVector<uint8_t> dst_image; + int datasize = features.width*features.height*(features.has_alpha?4:3); + dst_image.resize(datasize); + + DVector<uint8_t>::Write dst_w = dst_image.write(); + + bool errdec=false; + if (features.has_alpha) { + errdec = WebPDecodeRGBAInto(&r[4],size,dst_w.ptr(),datasize,4*features.width)==NULL; + } else { + errdec = WebPDecodeRGBInto(&r[4],size,dst_w.ptr(),datasize,3*features.width)==NULL; + + } + + //ERR_EXPLAIN("Error decoding webp! - "+p_file); + ERR_FAIL_COND_V(errdec,Image()); + + dst_w = DVector<uint8_t>::Write(); + + return Image(features.width,features.height,0,features.has_alpha?Image::FORMAT_RGBA:Image::FORMAT_RGB,dst_image); + +} + + +Error ImageLoaderWEBP::load_image(Image *p_image,FileAccess *f) { + + + uint32_t size = f->get_len(); + DVector<uint8_t> src_image; + src_image.resize(size); + + WebPBitstreamFeatures features; + + DVector<uint8_t>::Write src_w = src_image.write(); + f->get_buffer(src_w.ptr(),size); + ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_EOF); + + if (WebPGetFeatures(src_w.ptr(),size,&features)!=VP8_STATUS_OK) { + f->close(); + //ERR_EXPLAIN("Error decoding WEBP image: "+p_file); + ERR_FAIL_V(ERR_FILE_CORRUPT); + } + + print_line("width: "+itos(features.width)); + print_line("height: "+itos(features.height)); + print_line("alpha: "+itos(features.has_alpha)); + + src_w = DVector<uint8_t>::Write(); + + DVector<uint8_t> dst_image; + int datasize = features.width*features.height*(features.has_alpha?4:3); + dst_image.resize(datasize); + + DVector<uint8_t>::Read src_r = src_image.read(); + DVector<uint8_t>::Write dst_w = dst_image.write(); + + + bool errdec=false; + if (features.has_alpha) { + errdec = WebPDecodeRGBAInto(src_r.ptr(),size,dst_w.ptr(),datasize,4*features.width)==NULL; + } else { + errdec = WebPDecodeRGBInto(src_r.ptr(),size,dst_w.ptr(),datasize,3*features.width)==NULL; + + } + + //ERR_EXPLAIN("Error decoding webp! - "+p_file); + ERR_FAIL_COND_V(errdec,ERR_FILE_CORRUPT); + + src_r = DVector<uint8_t>::Read(); + dst_w = DVector<uint8_t>::Write(); + + *p_image = Image(features.width,features.height,0,features.has_alpha?Image::FORMAT_RGBA:Image::FORMAT_RGB,dst_image); + + + return OK; + +} + +void ImageLoaderWEBP::get_recognized_extensions(List<String> *p_extensions) const { + + p_extensions->push_back("webp"); +} + + +ImageLoaderWEBP::ImageLoaderWEBP() { + + Image::lossy_packer=_webp_lossy_pack; + Image::lossy_unpacker=_webp_lossy_unpack; +} + + diff --git a/drivers/webp/image_loader_webp.h b/modules/webp/image_loader_webp.h index 24f79708db..24f79708db 100644 --- a/drivers/webp/image_loader_webp.h +++ b/modules/webp/image_loader_webp.h diff --git a/modules/webp/register_types.cpp b/modules/webp/register_types.cpp new file mode 100644 index 0000000000..039876bbb9 --- /dev/null +++ b/modules/webp/register_types.cpp @@ -0,0 +1,44 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "register_types.h" + +#include "image_loader_webp.h" + +static ImageLoaderWEBP *image_loader_webp = NULL; + +void register_webp_types() { + + image_loader_webp = memnew( ImageLoaderWEBP ); + ImageLoader::add_image_format_loader(image_loader_webp); +} + +void unregister_webp_types() { + + memdelete( image_loader_webp ); +} diff --git a/modules/webp/register_types.h b/modules/webp/register_types.h new file mode 100644 index 0000000000..a200188e47 --- /dev/null +++ b/modules/webp/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_webp_types(); +void unregister_webp_types(); diff --git a/platform/android/SCsub b/platform/android/SCsub index 60bb4bd613..4f9a9709cb 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + import shutil Import('env') diff --git a/platform/android/build.gradle.template b/platform/android/build.gradle.template index 24951b921b..873eef0566 100644 --- a/platform/android/build.gradle.template +++ b/platform/android/build.gradle.template @@ -67,7 +67,6 @@ android { $$GRADLE_ASSET_DIRS$$ ] jniLibs.srcDirs = [ - 'libs' $$GRADLE_JNI_DIRS$$ ] } diff --git a/platform/android/detect.py b/platform/android/detect.py index 49ffc86658..842036f986 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -34,10 +34,8 @@ def get_flags(): return [ ('tools', 'no'), - ('nedmalloc', 'no'), - ('builtin_zlib', 'no'), - ('openssl','builtin'), #use builtin openssl - ] + ('openssl', 'builtin'), #use builtin openssl + ] def create(env): @@ -98,7 +96,7 @@ def configure(env): if env['android_arch']=='x86': env['NDK_TARGET']=env['NDK_TARGET_X86'] - env["x86_opt_gcc"]=True + env["x86_libtheora_opt_gcc"]=True if env['PLATFORM'] == 'win32': env.Tool('gcc') @@ -124,19 +122,20 @@ def configure(env): gcc_path=env["ANDROID_NDK_ROOT"]+"/toolchains/"+env["NDK_TARGET"]+"/prebuilt/"; - if (sys.platform.find("linux")==0): - if (platform.architecture()[0]=='64bit' or os.path.isdir(gcc_path+"linux-x86_64/bin")): # check was not working + if (sys.platform.startswith("linux")): + if (platform.machine().endswith('64')): gcc_path=gcc_path+"/linux-x86_64/bin" else: gcc_path=gcc_path+"/linux-x86/bin" - elif (sys.platform=="darwin"): - gcc_path=gcc_path+"/darwin-x86_64/bin" #this may be wrong + elif (sys.platform.startswith("darwin")): + gcc_path=gcc_path+"/darwin-x86_64/bin" env['SHLINKFLAGS'][1] = '-shared' env['SHLIBSUFFIX'] = '.so' - elif (os.name=="nt"): - gcc_path=gcc_path+"/windows-x86_64/bin" #this may be wrong - - + elif (sys.platform.startswith('win')): + if (platform.machine().endswith('64')): + gcc_path=gcc_path+"/windows-x86_64/bin" + else: + gcc_path=gcc_path+"/windows-x86/bin" env['ENV']['PATH'] = gcc_path+":"+env['ENV']['PATH'] if env['android_arch']=='x86': @@ -168,11 +167,11 @@ def configure(env): env['neon_enabled']=False if env['android_arch']=='x86': - env['CCFLAGS'] = string.split('-DNO_STATVFS -fpic -ffunction-sections -funwind-tables -fstack-protector -fvisibility=hidden -D__GLIBC__ -Wno-psabi -ftree-vectorize -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED') + env.Append(CCFLAGS=string.split('-DNO_STATVFS -fpic -ffunction-sections -funwind-tables -fstack-protector -fvisibility=hidden -D__GLIBC__ -Wno-psabi -ftree-vectorize -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED')) elif env["android_arch"]=="armv6": - env['CCFLAGS'] = string.split('-DNO_STATVFS -fpic -ffunction-sections -funwind-tables -fstack-protector -fvisibility=hidden -D__ARM_ARCH_6__ -D__GLIBC__ -Wno-psabi -march=armv6 -mfpu=vfp -mfloat-abi=softfp -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED') + env.Append(CCFLAGS=string.split('-DNO_STATVFS -fpic -ffunction-sections -funwind-tables -fstack-protector -fvisibility=hidden -D__ARM_ARCH_6__ -D__GLIBC__ -Wno-psabi -march=armv6 -mfpu=vfp -mfloat-abi=softfp -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED')) elif env["android_arch"]=="armv7": - env['CCFLAGS'] = string.split('-DNO_STATVFS -fpic -ffunction-sections -funwind-tables -fstack-protector -fvisibility=hidden -D__ARM_ARCH_7__ -D__ARM_ARCH_7A__ -D__GLIBC__ -Wno-psabi -march=armv7-a -mfloat-abi=softfp -ftree-vectorize -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED') + env.Append(CCFLAGS=string.split('-DNO_STATVFS -fpic -ffunction-sections -funwind-tables -fstack-protector -fvisibility=hidden -D__ARM_ARCH_7__ -D__ARM_ARCH_7A__ -D__GLIBC__ -Wno-psabi -march=armv7-a -mfloat-abi=softfp -ftree-vectorize -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED')) if env['android_neon']=='yes': env['neon_enabled']=True env.Append(CCFLAGS=['-mfpu=neon','-D__ARM_NEON__']) @@ -204,7 +203,8 @@ def configure(env): env.Append(CPPFLAGS=['-DANDROID_ENABLED', '-DUNIX_ENABLED', '-DNO_FCNTL','-DMPC_FIXED_POINT']) # env.Append(CPPFLAGS=['-DANDROID_ENABLED', '-DUNIX_ENABLED','-DMPC_FIXED_POINT']) - if(env["opus"]=="yes"): + # TODO: Move that to opus module's config + if("module_opus_enabled" in env and env["module_opus_enabled"] != "no"): if (env["android_arch"]=="armv6" or env["android_arch"]=="armv7"): env.Append(CFLAGS=["-DOPUS_ARM_OPT"]) env.opus_fixed_point="yes" diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp index be2ffde2cd..57376f8103 100644 --- a/platform/android/dir_access_jandroid.cpp +++ b/platform/android/dir_access_jandroid.cpp @@ -203,7 +203,6 @@ bool DirAccessJAndroid::dir_exists(String p_dir) { return false; env->CallVoidMethod(io,_dir_close,res); - env->DeleteLocalRef(js); return true; } diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 10d77aba6c..4735a91f43 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -495,7 +495,7 @@ static String _parse_string(const uint8_t *p_bytes,bool p_utf8) { Vector<uint8_t> str8; str8.resize(len+1); - for(int i=0;i<len;i++) { + for(uint32_t i=0;i<len;i++) { str8[i]=p_bytes[offset+i]; } str8[len]=0; @@ -505,7 +505,7 @@ static String _parse_string(const uint8_t *p_bytes,bool p_utf8) { } else { String str; - for(int i=0;i<len;i++) { + for(uint32_t i=0;i<len;i++) { CharType c = decode_uint16(&p_bytes[offset+i*2]); if (c==0) break; @@ -535,7 +535,7 @@ void EditorExportPlatformAndroid::_fix_resources(Vector<uint8_t>& p_manifest) { printf("stirng count: %i\n",string_count); printf("flags: %x\n",string_flags); - for(int i=0;i<string_count;i++) { + for(uint32_t i=0;i<string_count;i++) { uint32_t offset = decode_uint32(&p_manifest[string_table_begins+i*4]); offset+=string_table_begins+string_count*4; @@ -569,7 +569,7 @@ void EditorExportPlatformAndroid::_fix_resources(Vector<uint8_t>& p_manifest) { Vector<uint8_t> ret; ret.resize(string_table_begins+string_table.size()*4); - for(int i=0;i<string_table_begins;i++) { + for(uint32_t i=0;i<string_table_begins;i++) { ret[i]=p_manifest[i]; } @@ -660,7 +660,7 @@ void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest,bool uint32_t filesize = decode_uint32(&p_manifest[ofs+4]); ofs+=8; -// print_line("FILESIZE: "+itos(filesize)+" ACTUAL: "+itos(p_manifest.size())); + //print_line("FILESIZE: "+itos(filesize)+" ACTUAL: "+itos(p_manifest.size())); uint32_t string_count; uint32_t styles_count; @@ -672,7 +672,7 @@ void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest,bool uint32_t string_table_ends; Vector<uint8_t> stable_extra; - while(ofs < p_manifest.size()) { + while(ofs < (uint32_t)p_manifest.size()) { uint32_t chunk = decode_uint32(&p_manifest[ofs]); uint32_t size = decode_uint32(&p_manifest[ofs+4]); @@ -687,7 +687,7 @@ void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest,bool string_count=decode_uint32(&p_manifest[iofs]); styles_count=decode_uint32(&p_manifest[iofs+4]); - uint32_t string_flags=decode_uint32(&p_manifest[iofs+8]); + string_flags=decode_uint32(&p_manifest[iofs+8]); string_data_offset=decode_uint32(&p_manifest[iofs+12]); styles_offset=decode_uint32(&p_manifest[iofs+16]); /* @@ -703,7 +703,7 @@ void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest,bool string_table_begins=st_offset; - for(int i=0;i<string_count;i++) { + for(uint32_t i=0;i<string_count;i++) { uint32_t string_at = decode_uint32(&p_manifest[st_offset+i*4]); string_at+=st_offset+string_count*4; @@ -719,7 +719,7 @@ void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest,bool uint32_t len = decode_uint16(&p_manifest[string_at]); Vector<CharType> ucstring; ucstring.resize(len+1); - for(int j=0;j<len;j++) { + for(uint32_t j=0;j<len;j++) { uint16_t c=decode_uint16(&p_manifest[string_at+2+2*j]); ucstring[j]=c; } @@ -732,7 +732,7 @@ void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest,bool // print_line("String "+itos(i)+": "+string_table[i]); } - for(int i=string_end;i<(ofs+size);i++) { + for(uint32_t i=string_end;i<(ofs+size);i++) { stable_extra.push_back(p_manifest[i]); } @@ -758,7 +758,7 @@ void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest,bool uint32_t attrcount=decode_uint32(&p_manifest[iofs+20]); iofs+=28; //printf("ATTRCOUNT: %x\n",attrcount); - for(int i=0;i<attrcount;i++) { + for(uint32_t i=0;i<attrcount;i++) { uint32_t attr_nspace=decode_uint32(&p_manifest[iofs]); uint32_t attr_name=decode_uint32(&p_manifest[iofs+4]); uint32_t attr_value=decode_uint32(&p_manifest[iofs+8]); @@ -883,7 +883,7 @@ void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest,bool Vector<uint8_t> ret; ret.resize(string_table_begins+string_table.size()*4); - for(int i=0;i<string_table_begins;i++) { + for(uint32_t i=0;i<string_table_begins;i++) { ret[i]=p_manifest[i]; } @@ -913,21 +913,19 @@ void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest,bool } - ret.resize(ret.size()+stable_extra.size()); - while(ret.size()%4) - ret.push_back(0); - for(int i=0;i<stable_extra.size();i++) { - - chars[i]=stable_extra[i]; + ret.push_back(stable_extra[i]); } + while(ret.size()%4) + ret.push_back(0); + uint32_t new_stable_end=ret.size(); uint32_t extra = (p_manifest.size()-string_table_ends); ret.resize(new_stable_end + extra); - for(int i=0;i<extra;i++) + for(uint32_t i=0;i<extra;i++) ret[new_stable_end+i]=p_manifest[string_table_ends+i]; while(ret.size()%4) @@ -1355,7 +1353,7 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d args.push_back(unaligned_path); args.push_back(user); int retval; - int err = OS::get_singleton()->execute(jarsigner,args,true,NULL,NULL,&retval); + OS::get_singleton()->execute(jarsigner,args,true,NULL,NULL,&retval); if (retval) { EditorNode::add_io_error("'jarsigner' returned with error #"+itos(retval)); return ERR_CANT_CREATE; @@ -1368,7 +1366,7 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d args.push_back(unaligned_path); args.push_back("-verbose"); - err = OS::get_singleton()->execute(jarsigner,args,true,NULL,NULL,&retval); + OS::get_singleton()->execute(jarsigner,args,true,NULL,NULL,&retval); if (retval) { EditorNode::add_io_error("'jarsigner' verification of APK failed. Make sure to use jarsigner from Java 6."); return ERR_CANT_CREATE; @@ -1515,7 +1513,7 @@ void EditorExportPlatformAndroid::_device_poll_thread(void *ud) { List<String> args; args.push_back("devices"); int ec; - Error err = OS::get_singleton()->execute(adb,args,true,NULL,&devices,&ec); + OS::get_singleton()->execute(adb,args,true,NULL,&devices,&ec); Vector<String> ds = devices.split("\n"); Vector<String> ldevices; for(int i=1;i<ds.size();i++) { @@ -1574,7 +1572,7 @@ void EditorExportPlatformAndroid::_device_poll_thread(void *ud) { int ec; String dp; - Error err = OS::get_singleton()->execute(adb,args,true,NULL,&dp,&ec); + OS::get_singleton()->execute(adb,args,true,NULL,&dp,&ec); Vector<String> props = dp.split("\n"); String vendor; diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 4e395a6f9f..862709fc7d 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -132,15 +132,10 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_ AudioDriverManagerSW::add_driver(&audio_driver_android); - if (true) { - RasterizerGLES2 *rasterizer_gles22=memnew( RasterizerGLES2(false,use_reload_hooks,false,use_reload_hooks ) ); - if (gl_extensions) - rasterizer_gles22->set_extensions(gl_extensions); - rasterizer = rasterizer_gles22; - } else { - //rasterizer = memnew( RasterizerGLES1(use_reload_hooks, use_reload_hooks) ); - - } + RasterizerGLES2 *rasterizer_gles22=memnew( RasterizerGLES2(false,use_reload_hooks,false,use_reload_hooks ) ); + if (gl_extensions) + rasterizer_gles22->set_extensions(gl_extensions); + rasterizer = rasterizer_gles22; rasterizer->set_force_16_bits_fbo(use_16bits_fbo); diff --git a/platform/bb10/SCsub b/platform/bb10/SCsub index 81f6e726e4..84fff0828b 100644 --- a/platform/bb10/SCsub +++ b/platform/bb10/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') bb10_lib = [ diff --git a/platform/bb10/detect.py b/platform/bb10/detect.py index 9ab94e619a..2b76aa3496 100644 --- a/platform/bb10/detect.py +++ b/platform/bb10/detect.py @@ -32,11 +32,9 @@ def get_opts(): def get_flags(): return [ - ('lua', 'no'), ('tools', 'no'), - ('nedmalloc', 'no'), - ('theora', 'no'), - + ('builtin_zlib', 'yes'), + ('module_theora_enabled', 'no'), ] def configure(env): diff --git a/platform/haiku/SCsub b/platform/haiku/SCsub index 1952e6b59b..b5a584baa4 100644 --- a/platform/haiku/SCsub +++ b/platform/haiku/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') common_haiku = [ diff --git a/platform/haiku/detect.py b/platform/haiku/detect.py index f36b0c567e..af997a5737 100644 --- a/platform/haiku/detect.py +++ b/platform/haiku/detect.py @@ -23,8 +23,6 @@ def get_opts(): def get_flags(): return [ - ('builtin_zlib', 'no'), - ('glew', 'yes'), ] def configure(env): diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub index 5b2e1533da..236630bef4 100644 --- a/platform/iphone/SCsub +++ b/platform/iphone/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') iphone_lib = [ diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index 9cb52d4561..1be63891b1 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -38,6 +38,7 @@ def get_flags(): return [ ('tools', 'no'), ('webp', 'yes'), + ('builtin_zlib', 'yes'), ('openssl','builtin'), #use builtin openssl ] @@ -165,7 +166,8 @@ def configure(env): env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate' env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DMPC_FIXED_POINT']) - if(env["opus"]=="yes"): + # TODO: Move that to opus module's config + if("module_opus_enabled" in env and env["module_opus_enabled"] != "no"): env.opus_fixed_point="yes" if env["arch"]=="x86": pass diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub index fc70d45a04..22af436470 100644 --- a/platform/javascript/SCsub +++ b/platform/javascript/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') javascript_files = [ diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index aeff5a1a34..e1f91cf948 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -25,21 +25,11 @@ def get_opts(): def get_flags(): return [ - ('lua', 'no'), ('tools', 'no'), - ('nedmalloc', 'no'), - ('theora', 'no'), - ('tools', 'no'), - ('nedmalloc', 'no'), - ('musepack', 'no'), - ('squirrel', 'no'), - ('squish', 'no'), - ('speex', 'no'), - ('old_scenes', 'no'), - ('etc1', 'no'), -# ('default_gui_theme', 'no'), - - #('builtin_zlib', 'no'), + ('builtin_zlib', 'yes'), + ('module_etc1_enabled', 'no'), + ('module_mpc_enabled', 'no'), + ('module_theora_enabled', 'no'), ] @@ -80,8 +70,9 @@ def configure(env): #env.Append(CCFLAGS=['-D_DEBUG', '-Wall', '-g4', '-DDEBUG_ENABLED']) env.Append(CPPFLAGS=['-DDEBUG_MEMORY_ALLOC']) - if(env["opus"]=="yes"): - env.opus_fixed_point="yes" + # TODO: Move that to opus module's config + if("module_opus_enabled" in env and env["module_opus_enabled"] != "no"): + env.opus_fixed_point = "yes" env.Append(CPPFLAGS=["-fno-exceptions",'-DNO_SAFE_CAST','-fno-rtti']) env.Append(CPPFLAGS=['-DJAVASCRIPT_ENABLED', '-DUNIX_ENABLED', '-DPTHREAD_NO_RENAME', '-DNO_FCNTL','-DMPC_FIXED_POINT','-DTYPED_METHOD_BIND','-DNO_THREADS']) diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index de57d770c4..f934916aa2 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -195,8 +195,8 @@ void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t>& p_html, const St } CharString cs = strnew.utf8(); - p_html.resize(cs.size()); - for(int i=9;i<cs.size();i++) { + p_html.resize(cs.length()); + for(int i=9;i<cs.length();i++) { p_html[i]=cs[i]; } } diff --git a/platform/osx/SCsub b/platform/osx/SCsub index 3785eb3fb3..217dee81eb 100644 --- a/platform/osx/SCsub +++ b/platform/osx/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') files = [ @@ -7,6 +9,7 @@ files = [ 'sem_osx.cpp', # 'context_gl_osx.cpp', 'dir_access_osx.mm', + 'joystick_osx.cpp', ] env.Program('#bin/godot',files) diff --git a/platform/osx/detect.py b/platform/osx/detect.py index 1982beb10e..4e772e37eb 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -28,9 +28,6 @@ def get_opts(): def get_flags(): return [ - ('legacygl', 'yes'), - ('builtin_zlib', 'no'), - ('glew', 'yes'), ] @@ -83,24 +80,17 @@ def configure(env): env['AS'] = basecmd+"as" -# env.Append(CPPPATH=['#platform/osx/include/freetype2', '#platform/osx/include']) -# env.Append(LIBPATH=['#platform/osx/lib']) - - env.Append(CPPFLAGS=["-DAPPLE_STYLE_KEYS"]) env.Append(CPPFLAGS=['-DUNIX_ENABLED','-DGLES2_ENABLED','-DOSX_ENABLED']) env.Append(LIBS=['pthread']) #env.Append(CPPFLAGS=['-F/Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks', '-isysroot', '/Developer/SDKs/MacOSX10.4u.sdk', '-mmacosx-version-min=10.4']) #env.Append(LINKFLAGS=['-mmacosx-version-min=10.4', '-isysroot', '/Developer/SDKs/MacOSX10.4u.sdk', '-Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk']) - env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit','-lz']) + env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit','-lz', '-framework', 'IOKit', '-framework', 'ForceFeedback']) if (env["CXX"]=="clang++"): env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND']) env["CC"]="clang" env["LD"]="clang++" - if (env["colored"]=="yes"): - if sys.stdout.isatty(): - env.Append(CPPFLAGS=["-fcolor-diagnostics"]) import methods @@ -109,4 +99,4 @@ def configure(env): env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) #env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } ) - env["x86_opt_gcc"]=True + env["x86_libtheora_opt_gcc"]=True diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index 47b0392b25..30f4c58150 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -445,7 +445,7 @@ Error EditorExportPlatformOSX::export_project(const String& p_path, bool p_debug { //write datapack - int err = zipOpenNewFileInZip(dpkg, + zipOpenNewFileInZip(dpkg, (pkg_name+".app/Contents/Resources/data.pck").utf8().get_data(), NULL, NULL, diff --git a/platform/osx/joystick_osx.cpp b/platform/osx/joystick_osx.cpp new file mode 100644 index 0000000000..ffb6ac326b --- /dev/null +++ b/platform/osx/joystick_osx.cpp @@ -0,0 +1,623 @@ +/*************************************************************************/ +/* joystick_osx.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "joystick_osx.h" +#include <machine/endian.h> + +#define GODOT_JOY_LOOP_RUN_MODE CFSTR("GodotJoystick") + +static JoystickOSX* self = NULL; + +joystick::joystick() { + device_ref = NULL; + ff_device = NULL; + ff_axes = NULL; + ff_directions = NULL; + ffservice = 0; + ff_timestamp = 0; + id = 0; + + ff_constant_force.lMagnitude = 10000; + ff_effect.dwDuration = 0; + ff_effect.dwSamplePeriod = 0; + ff_effect.dwGain = 10000; + ff_effect.dwFlags = FFEFF_OBJECTOFFSETS; + ff_effect.dwTriggerButton = FFEB_NOTRIGGER; + ff_effect.dwStartDelay = 0; + ff_effect.dwTriggerRepeatInterval = 0; + ff_effect.lpEnvelope = NULL; + ff_effect.cbTypeSpecificParams = sizeof(FFCONSTANTFORCE); + ff_effect.lpvTypeSpecificParams = &ff_constant_force; + ff_effect.dwSize = sizeof(ff_effect); +} + +void joystick::free() { + if (device_ref) { + IOHIDDeviceUnscheduleFromRunLoop(device_ref, CFRunLoopGetCurrent(), GODOT_JOY_LOOP_RUN_MODE); + } + if (ff_device) { + FFDeviceReleaseEffect(ff_device, ff_object); + FFReleaseDevice(ff_device); + memfree(ff_axes); + memfree(ff_directions); + } +} + +bool joystick::has_element(IOHIDElementCookie p_cookie, Vector<rec_element> *p_list) const { + for (int i = 0; i < p_list->size(); i++) { + if (p_cookie == p_list->get(i).cookie) { + return true; + } + } + return false; +} + +int joystick::get_hid_element_state(rec_element *p_element) const { + int value = 0; + if (p_element && p_element->ref) { + IOHIDValueRef valueRef; + if (IOHIDDeviceGetValue(device_ref, p_element->ref, &valueRef) == kIOReturnSuccess) { + value = (SInt32) IOHIDValueGetIntegerValue(valueRef); + + /* record min and max for auto calibration */ + if (value < p_element->min) { + p_element->min = value; + } + if (value > p_element->max) { + p_element->max = value; + } + } + } + return value; +} +void joystick::add_hid_element(IOHIDElementRef p_element) { + const CFTypeID elementTypeID = p_element ? CFGetTypeID(p_element) : 0; + + if (p_element && (elementTypeID == IOHIDElementGetTypeID())) { + const IOHIDElementCookie cookie = IOHIDElementGetCookie(p_element); + const uint32_t usagePage = IOHIDElementGetUsagePage(p_element); + const uint32_t usage = IOHIDElementGetUsage(p_element); + Vector<rec_element> *list = NULL; + + switch (IOHIDElementGetType(p_element)) { + case kIOHIDElementTypeInput_Misc: + case kIOHIDElementTypeInput_Button: + case kIOHIDElementTypeInput_Axis: { + switch (usagePage) { + case kHIDPage_GenericDesktop: + switch (usage) { + case kHIDUsage_GD_X: + case kHIDUsage_GD_Y: + case kHIDUsage_GD_Z: + case kHIDUsage_GD_Rx: + case kHIDUsage_GD_Ry: + case kHIDUsage_GD_Rz: + case kHIDUsage_GD_Slider: + case kHIDUsage_GD_Dial: + case kHIDUsage_GD_Wheel: + if (!has_element(cookie, &axis_elements)) { + list = &axis_elements; + } + break; + + case kHIDUsage_GD_Hatswitch: + if (!has_element(cookie, &hat_elements)) { + list = &hat_elements; + } + break; + case kHIDUsage_GD_DPadUp: + case kHIDUsage_GD_DPadDown: + case kHIDUsage_GD_DPadRight: + case kHIDUsage_GD_DPadLeft: + case kHIDUsage_GD_Start: + case kHIDUsage_GD_Select: + if (!has_element(cookie, &button_elements)) { + list = &button_elements; + } + break; + } + break; + + case kHIDPage_Simulation: + switch (usage) { + case kHIDUsage_Sim_Rudder: + case kHIDUsage_Sim_Throttle: + if (!has_element(cookie, &axis_elements)) { + list = &axis_elements; + } + break; + + default: + break; + } + break; + + case kHIDPage_Button: + case kHIDPage_Consumer: + if (!has_element(cookie, &button_elements)) { + list = &button_elements; + } + break; + + default: + break; + } + } + break; + + case kIOHIDElementTypeCollection: { + CFArrayRef array = IOHIDElementGetChildren(p_element); + if (array) { + add_hid_elements(array); + } + } + break; + + default: + break; + } + + if (list) { /* add to list */ + rec_element element; + + element.ref = p_element; + element.usage = usage; + + element.min = (SInt32) IOHIDElementGetLogicalMin(p_element); + element.max = (SInt32) IOHIDElementGetLogicalMax(p_element); + element.cookie = IOHIDElementGetCookie(p_element); + list->push_back(element); + list->sort_custom<rec_element::Comparator>(); + } + } +} + +static void hid_element_added(const void *p_value, void *p_parameter) { + joystick *joy = (joystick*) p_parameter; + joy->add_hid_element((IOHIDElementRef) p_value); +} + +void joystick::add_hid_elements(CFArrayRef p_array) { + CFRange range = { 0, CFArrayGetCount(p_array) }; + CFArrayApplyFunction(p_array, range,hid_element_added,this); +} + +static void joystick_removed_callback(void *ctx, IOReturn result, void *sender) { + int id = (intptr_t) ctx; + self->_device_removed(id); +} + + +static void joystick_added_callback(void *ctx, IOReturn res, void *sender, IOHIDDeviceRef ioHIDDeviceObject) { + self->_device_added(res, ioHIDDeviceObject); +} + +static bool is_joystick(IOHIDDeviceRef p_device_ref) { + CFTypeRef refCF = NULL; + int usage_page = 0; + int usage = 0; + refCF = IOHIDDeviceGetProperty(p_device_ref, CFSTR(kIOHIDPrimaryUsagePageKey)); + if (refCF) { + CFNumberGetValue((CFNumberRef) refCF, kCFNumberSInt32Type, &usage_page); + } + if (usage_page != kHIDPage_GenericDesktop) { + return false; + } + + refCF = IOHIDDeviceGetProperty(p_device_ref, CFSTR(kIOHIDPrimaryUsageKey)); + if (refCF) { + CFNumberGetValue((CFNumberRef) refCF, kCFNumberSInt32Type, &usage); + } + if ((usage != kHIDUsage_GD_Joystick && + usage != kHIDUsage_GD_GamePad && + usage != kHIDUsage_GD_MultiAxisController)) { + return false; + } + return true; +} + +void JoystickOSX::_device_added(IOReturn p_res, IOHIDDeviceRef p_device) { + + if (p_res != kIOReturnSuccess || have_device(p_device)) { + return; + } + + joystick new_joystick; + if (is_joystick(p_device)) { + configure_joystick(p_device, &new_joystick); +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + if (IOHIDDeviceGetService != NULL) { +#endif + const io_service_t ioservice = IOHIDDeviceGetService(p_device); + if ((ioservice) && (FFIsForceFeedback(ioservice) == FF_OK) && new_joystick.config_force_feedback(ioservice)) { + new_joystick.ffservice = ioservice; + } +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + } +#endif + device_list.push_back(new_joystick); + } + IOHIDDeviceRegisterRemovalCallback(p_device, joystick_removed_callback, (void*) (intptr_t) new_joystick.id); + IOHIDDeviceScheduleWithRunLoop(p_device, CFRunLoopGetCurrent(), GODOT_JOY_LOOP_RUN_MODE); +} + +void JoystickOSX::_device_removed(int p_id) { + + int device = get_joy_index(p_id); + ERR_FAIL_COND(device == -1); + + input->joy_connection_changed(p_id, false, ""); + device_list[device].free(); + device_list.remove(device); + attached_devices[p_id] = false; +} + +static String _hex_str(uint8_t p_byte) { + + static const char* dict = "0123456789abcdef"; + char ret[3]; + ret[2] = 0; + + ret[0] = dict[p_byte>>4]; + ret[1] = dict[p_byte & 0xF]; + + return ret; +} + +bool JoystickOSX::configure_joystick(IOHIDDeviceRef p_device_ref, joystick* p_joy) { + + CFTypeRef refCF = NULL; + + p_joy->device_ref = p_device_ref; + /* get device name */ + String name; + char c_name[256]; + refCF = IOHIDDeviceGetProperty(p_device_ref, CFSTR(kIOHIDProductKey)); + if (!refCF) { + refCF = IOHIDDeviceGetProperty(p_device_ref, CFSTR(kIOHIDManufacturerKey)); + } + if ((!refCF) || (!CFStringGetCString((CFStringRef) refCF, c_name, sizeof (c_name), kCFStringEncodingUTF8))) { + name = "Unidentified Joystick"; + } + name = c_name; + + int id = get_free_joy_id(); + ERR_FAIL_COND_V(id == -1, false); + p_joy->id = id; + int vendor = 0; + refCF = IOHIDDeviceGetProperty(p_device_ref, CFSTR(kIOHIDVendorIDKey)); + if (refCF) { + CFNumberGetValue((CFNumberRef)refCF, kCFNumberSInt32Type, &vendor); + } + + int product_id = 0; + refCF = IOHIDDeviceGetProperty(p_device_ref, CFSTR(kIOHIDProductIDKey)); + if (refCF) { + CFNumberGetValue((CFNumberRef)refCF, kCFNumberSInt32Type, &product_id); + } + if (vendor && product_id) { + char uid[128]; + sprintf(uid, "%04x%08x%04x%08x", OSSwapHostToBigInt32(vendor),0, OSSwapHostToBigInt32(product_id), 0); + input->joy_connection_changed(id, true, name, uid); + } + else { + //bluetooth device + String guid = "05000000"; + for (int i = 0; i < 12; i++) { + if (i < name.size()) guid += _hex_str(name[i]); + else guid += "00"; + } + input->joy_connection_changed(id, true, name, guid); + } + + CFArrayRef array = NULL; + array = IOHIDDeviceCopyMatchingElements(p_device_ref, NULL, kIOHIDOptionsTypeNone); + if (array) { + p_joy->add_hid_elements(array); + CFRelease(array); + } + return true; +} + +#define FF_ERR() { if (ret != FF_OK) { FFReleaseDevice(ff_device); return false; } } +bool joystick::config_force_feedback(io_service_t p_service) { + + HRESULT ret = FFCreateDevice(p_service, &ff_device); + ERR_FAIL_COND_V(ret != FF_OK, false); + + ret = FFDeviceSendForceFeedbackCommand(ff_device, FFSFFC_RESET); + FF_ERR(); + + ret = FFDeviceSendForceFeedbackCommand(ff_device, FFSFFC_SETACTUATORSON); + FF_ERR(); + + if (check_ff_features()) { + ret = FFDeviceCreateEffect(ff_device, kFFEffectType_ConstantForce_ID, &ff_effect, &ff_object); + FF_ERR(); + return true; + } + FFReleaseDevice(ff_device); + return false; +} +#undef FF_ERR + +#define TEST_FF(ff) (features.supportedEffects & (ff)) +bool joystick::check_ff_features() { + + FFCAPABILITIES features; + HRESULT ret = FFDeviceGetForceFeedbackCapabilities(ff_device, &features); + if (ret == FF_OK && (features.supportedEffects & FFCAP_ET_CONSTANTFORCE)) { + uint32_t val; + ret = FFDeviceGetForceFeedbackProperty(ff_device, FFPROP_FFGAIN, &val, sizeof(val)); + if (ret != FF_OK) return false; + int num_axes = features.numFfAxes; + ff_axes = (DWORD*) memalloc(sizeof(DWORD) * num_axes); + ff_directions = (LONG*) memalloc(sizeof(LONG) * num_axes); + + for (int i = 0; i < num_axes; i++) { + ff_axes[i] = features.ffAxes[i]; + ff_directions[i] = 0; + } + + ff_effect.cAxes = num_axes; + ff_effect.rgdwAxes = ff_axes; + ff_effect.rglDirection = ff_directions; + return true; + } + return false; +} + +static int process_hat_value(int p_min, int p_max, int p_value) { + int range = (p_max - p_min + 1); + int value = p_value - p_min; + int hat_value = InputDefault::HAT_MASK_CENTER; + if (range == 4) { + value *= 2; + } + + switch (value) { + case 0: + hat_value = InputDefault::HAT_MASK_UP; + break; + case 1: + hat_value = InputDefault::HAT_MASK_UP | InputDefault::HAT_MASK_RIGHT; + break; + case 2: + hat_value = InputDefault::HAT_MASK_RIGHT; + break; + case 3: + hat_value = InputDefault::HAT_MASK_DOWN | InputDefault::HAT_MASK_RIGHT; + break; + case 4: + hat_value = InputDefault::HAT_MASK_DOWN; + break; + case 5: + hat_value = InputDefault::HAT_MASK_DOWN | InputDefault::HAT_MASK_LEFT; + break; + case 6: + hat_value = InputDefault::HAT_MASK_LEFT; + break; + case 7: + hat_value = InputDefault::HAT_MASK_UP | InputDefault::HAT_MASK_LEFT; + break; + default: + hat_value = InputDefault::HAT_MASK_CENTER; + break; + } + return hat_value; +} + +void JoystickOSX::poll_joysticks() const { + while (CFRunLoopRunInMode(GODOT_JOY_LOOP_RUN_MODE,0,TRUE) == kCFRunLoopRunHandledSource) { + /* no-op. Pending callbacks will fire. */ + } +} + +static const InputDefault::JoyAxis axis_correct(int p_value, int p_min, int p_max) { + InputDefault::JoyAxis jx; + if (p_min < 0) { + jx.min = -1; + if (p_value < 0) { + jx.value = (float) -p_value / p_min; + } + else jx.value = (float) p_value / p_max; + } + if (p_min == 0) { + jx.min = 0; + jx.value = 0.0f + (float) p_value / p_max; + } + return jx; +} + +uint32_t JoystickOSX::process_joysticks(uint32_t p_last_id){ + poll_joysticks(); + + for (int i = 0; i < device_list.size(); i++) { + joystick &joy = device_list[i]; + + for (int j = 0; j < joy.axis_elements.size(); j++) { + rec_element &elem = joy.axis_elements[j]; + int value = joy.get_hid_element_state(&elem); + p_last_id = input->joy_axis(p_last_id, joy.id, j, axis_correct(value, elem.min, elem.max)); + } + for (int j = 0; j < joy.button_elements.size(); j++) { + int value = joy.get_hid_element_state(&joy.button_elements[j]); + p_last_id = input->joy_button(p_last_id, joy.id, j, (value>=1)); + } + for (int j = 0; j < joy.hat_elements.size(); j++) { + rec_element &elem = joy.hat_elements[j]; + int value = joy.get_hid_element_state(&elem); + int hat_value = process_hat_value(elem.min, elem.max, value); + p_last_id = input->joy_hat(p_last_id, joy.id, hat_value); + } + + if (joy.ffservice) { + uint64_t timestamp = input->get_joy_vibration_timestamp(joy.id); + if (timestamp > joy.ff_timestamp) { + Vector2 strength = input->get_joy_vibration_strength(joy.id); + float duration = input->get_joy_vibration_duration(joy.id); + if (strength.x == 0 && strength.y == 0) { + joystick_vibration_stop(joy.id, timestamp); + } + else { + float gain = MAX(strength.x, strength.y); + joystick_vibration_start(joy.id, gain, duration, timestamp); + } + } + } + } + return p_last_id; +} + +void JoystickOSX::joystick_vibration_start(int p_id, float p_magnitude, float p_duration, uint64_t p_timestamp) { + joystick *joy = &device_list[get_joy_index(p_id)]; + joy->ff_timestamp = p_timestamp; + joy->ff_effect.dwDuration = p_duration * FF_SECONDS; + joy->ff_effect.dwGain = p_magnitude * FF_FFNOMINALMAX; + FFEffectSetParameters(joy->ff_object, &joy->ff_effect, FFEP_DURATION | FFEP_GAIN); + FFEffectStart(joy->ff_object, 1, 0); +} + +void JoystickOSX::joystick_vibration_stop(int p_id, uint64_t p_timestamp) { + joystick* joy = &device_list[get_joy_index(p_id)]; + joy->ff_timestamp = p_timestamp; + FFEffectStop(joy->ff_object); +} + +int JoystickOSX::get_free_joy_id() { + for (int i = 0; i < JOYSTICKS_MAX; i++) { + if (!attached_devices[i]) { + attached_devices[i] = true; + return i; + } + } + return -1; +} + +int JoystickOSX::get_joy_index(int p_id) const { + for (int i = 0; i < device_list.size(); i++) { + if (device_list[i].id == p_id) return i; + } + return -1; +} + +bool JoystickOSX::have_device(IOHIDDeviceRef p_device) const { + for (int i = 0; i < device_list.size(); i++) { + if (device_list[i].device_ref == p_device) { + return true; + } + } + return false; +} + +static CFDictionaryRef create_match_dictionary(const UInt32 page, const UInt32 usage, int *okay) +{ + CFDictionaryRef retval = NULL; + CFNumberRef pageNumRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page); + CFNumberRef usageNumRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage); + const void *keys[2] = { (void *) CFSTR(kIOHIDDeviceUsagePageKey), (void *) CFSTR(kIOHIDDeviceUsageKey) }; + const void *vals[2] = { (void *) pageNumRef, (void *) usageNumRef }; + + if (pageNumRef && usageNumRef) { + retval = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + + if (pageNumRef) { + CFRelease(pageNumRef); + } + if (usageNumRef) { + CFRelease(usageNumRef); + } + + if (!retval) { + *okay = 0; + } + + return retval; +} + +void JoystickOSX::config_hid_manager(CFArrayRef p_matching_array) const { + + CFRunLoopRef runloop = CFRunLoopGetCurrent(); + IOReturn ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone); + ERR_FAIL_COND(ret != kIOReturnSuccess); + + IOHIDManagerSetDeviceMatchingMultiple(hid_manager, p_matching_array); + IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, joystick_added_callback, NULL); + IOHIDManagerScheduleWithRunLoop(hid_manager, runloop, GODOT_JOY_LOOP_RUN_MODE); + + while (CFRunLoopRunInMode(GODOT_JOY_LOOP_RUN_MODE,0,TRUE) == kCFRunLoopRunHandledSource) { + /* no-op. Callback fires once per existing device. */ + } +} + +JoystickOSX::JoystickOSX() +{ + self = this; + input = (InputDefault*)Input::get_singleton(); + + for (int i = 0; i < JOYSTICKS_MAX; i++) { + attached_devices[i] = false; + } + + int okay = 1; + const void *vals[] = { + (void *) create_match_dictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick, &okay), + (void *) create_match_dictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad, &okay), + (void *) create_match_dictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_MultiAxisController, &okay), + }; + const size_t n_elements = sizeof(vals)/sizeof(vals[0]); + CFArrayRef array = okay ? CFArrayCreate(kCFAllocatorDefault, vals, n_elements, &kCFTypeArrayCallBacks) : NULL; + + for (int i = 0; i < n_elements; i++) { + if (vals[i]) { + CFRelease((CFTypeRef) vals[i]); + } + } + + if (array) { + hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (hid_manager != NULL) { + config_hid_manager(array); + } + CFRelease(array); + } +} + +JoystickOSX::~JoystickOSX() { + + for (int i = 0; i < device_list.size(); i++) { + device_list[i].free(); + } + + IOHIDManagerUnscheduleFromRunLoop(hid_manager, CFRunLoopGetCurrent(), GODOT_JOY_LOOP_RUN_MODE); + IOHIDManagerClose(hid_manager, kIOHIDOptionsTypeNone); + CFRelease(hid_manager); + hid_manager = NULL; +} + diff --git a/platform/osx/joystick_osx.h b/platform/osx/joystick_osx.h new file mode 100644 index 0000000000..38a4e3b1d3 --- /dev/null +++ b/platform/osx/joystick_osx.h @@ -0,0 +1,125 @@ +/*************************************************************************/ +/* joystick_osx.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef JOYSTICKOSX_H +#define JOYSTICKOSX_H + +#ifdef MACOS_10_0_4 +#include <IOKit/hidsystem/IOHIDUsageTables.h> +#else +#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h> +#endif +#include <IOKit/hid/IOHIDLib.h> +#include <ForceFeedback/ForceFeedback.h> +#include <ForceFeedback/ForceFeedbackConstants.h> + +#include "main/input_default.h" + +struct rec_element { + IOHIDElementRef ref; + IOHIDElementCookie cookie; + + uint32_t usage; + + int min; + int max; + + struct Comparator { + bool operator()(const rec_element p_a, const rec_element p_b) const { return p_a.usage < p_b.usage; } + }; +}; + +struct joystick { + IOHIDDeviceRef device_ref; + + Vector<rec_element> axis_elements; + Vector<rec_element> button_elements; + Vector<rec_element> hat_elements; + + int id; + + io_service_t ffservice; /* Interface for force feedback, 0 = no ff */ + FFCONSTANTFORCE ff_constant_force; + FFDeviceObjectReference ff_device; + FFEffectObjectReference ff_object; + uint64_t ff_timestamp; + LONG *ff_directions; + FFEFFECT ff_effect; + DWORD *ff_axes; + + void add_hid_elements(CFArrayRef p_array); + void add_hid_element(IOHIDElementRef p_element); + + bool has_element(IOHIDElementCookie p_cookie, Vector<rec_element> *p_list) const; + bool config_force_feedback(io_service_t p_service); + bool check_ff_features(); + + int get_hid_element_state(rec_element *p_element) const; + + void free(); + joystick(); +}; + +class JoystickOSX { + + enum { + JOYSTICKS_MAX = 16, + }; + +private: + InputDefault *input; + IOHIDManagerRef hid_manager; + + bool attached_devices[JOYSTICKS_MAX]; + Vector<joystick> device_list; + + bool have_device(IOHIDDeviceRef p_device) const; + bool configure_joystick(IOHIDDeviceRef p_device_ref, joystick *p_joy); + + + int get_free_joy_id(); + int get_joy_index(int p_id) const; + + void poll_joysticks() const; + void setup_joystick_objects(); + void config_hid_manager(CFArrayRef p_matching_array) const; + + void joystick_vibration_start(int p_id, float p_magnitude, float p_duration, uint64_t p_timestamp); + void joystick_vibration_stop(int p_id, uint64_t p_timestamp); + +public: + uint32_t process_joysticks(uint32_t p_last_id); + + void _device_added(IOReturn p_res, IOHIDDeviceRef p_device); + void _device_removed(int p_id); + + JoystickOSX(); + ~JoystickOSX(); +}; + +#endif // JOYSTICKOSX_H diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 8f89695a68..e23ae49a35 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -31,6 +31,7 @@ #include "os/input.h" +#include "joystick_osx.h" #include "drivers/unix/os_unix.h" #include "main/input_default.h" #include "servers/visual_server.h" @@ -76,6 +77,7 @@ public: SpatialSound2DServerSW *spatial_sound_2d_server; InputDefault *input; + JoystickOSX *joystick_osx; /* objc */ @@ -203,6 +205,7 @@ public: virtual void set_window_maximized(bool p_enabled); virtual bool is_window_maximized() const; virtual void request_attention(); + virtual String get_joy_guid(int p_device) const; void run(); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index b084a08ecc..cc893cc7a0 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1123,6 +1123,7 @@ void OS_OSX::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi physics_2d_server->init(); input = memnew( InputDefault ); + joystick_osx = memnew( JoystickOSX ); _ensure_data_dir(); @@ -1165,7 +1166,7 @@ void OS_OSX::finalize() { spatial_sound_2d_server->finish(); memdelete(spatial_sound_2d_server); - + memdelete(joystick_osx); memdelete(input); memdelete(sample_manager); @@ -1738,7 +1739,7 @@ void OS_OSX::run() { while (!force_quit) { process_events(); // get rid of pending events -// process_joysticks(); + last_id = joystick_osx->process_joysticks(last_id); if (Main::iteration()==true) break; }; @@ -1773,6 +1774,10 @@ OS::MouseMode OS_OSX::get_mouse_mode() const { return mouse_mode; } +String OS_OSX::get_joy_guid(int p_device) const { + return input->get_joy_guid_remapped(p_device); +} + OS_OSX* OS_OSX::singleton=NULL; OS_OSX::OS_OSX() { diff --git a/platform/osx/platform_config.h b/platform/osx/platform_config.h index 86505206ae..f02a4bc444 100644 --- a/platform/osx/platform_config.h +++ b/platform/osx/platform_config.h @@ -27,5 +27,5 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include <alloca.h> -#define GLES2_INCLUDE_H "gl_context/GL/glew.h" +#define GLES2_INCLUDE_H "GL/glew.h" #define PTHREAD_RENAME_SELF diff --git a/platform/server/SCsub b/platform/server/SCsub index 3dda6b4395..12758c5db0 100644 --- a/platform/server/SCsub +++ b/platform/server/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') diff --git a/platform/server/detect.py b/platform/server/detect.py index e6fab2043b..ce14100fd0 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -27,7 +27,6 @@ def get_opts(): def get_flags(): return [ - ('builtin_zlib', 'no'), ] @@ -39,9 +38,6 @@ def configure(env): env["CC"]="clang" env["CXX"]="clang++" env["LD"]="clang++" - if (env["colored"]=="yes"): - if sys.stdout.isatty(): - env.Append(CXXFLAGS=["-fcolor-diagnostics"]) is64=sys.maxsize > 2**32 diff --git a/platform/windows/SCsub b/platform/windows/SCsub index 914cee0fa1..e53eb7af34 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 2414cee57e..7ae0100762 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -1,10 +1,17 @@ # -# tested on | Windows native | Linux cross-compilation -# ------------------------+-------------------+--------------------------- -# MSVS C++ 2010 Express | WORKS | n/a -# Mingw-w64 | WORKS | WORKS -# Mingw-w32 | WORKS | WORKS -# MinGW | WORKS | untested +# tested on | Windows native | Linux cross-compilation +# ----------------------------+-------------------+--------------------------- +# Visual C++ Build Tools 2015 | WORKS | n/a +# MSVS C++ 2010 Express | WORKS | n/a +# Mingw-w64 | WORKS | WORKS +# Mingw-w32 | WORKS | WORKS +# MinGW | WORKS | untested +# +##### +# Note about Visual C++ Build Tools : +# +# - Visual C++ Build Tools is the standalone MSVC compiler : +# http://landinghub.visualstudio.com/visual-cpp-build-tools # ##### # Notes about MSVS C++ : @@ -78,7 +85,7 @@ ##### # TODO : -# +# # - finish to cleanup this script to remove all the remains of previous hacks and workarounds # - make it work with the Windows7 SDK that is supposed to enable 64bits compilation for MSVC2010-Express # - confirm it works well with other Visual Studio versions. @@ -90,6 +97,7 @@ import os import sys +import methods def is_active(): return True @@ -101,7 +109,7 @@ def can_build(): if (os.name=="nt"): #building natively on windows! - if (os.getenv("VSINSTALLDIR")): + if ( os.getenv("VCINSTALLDIR") ): return True else: print("\nMSVC not detected, attempting Mingw.") @@ -168,7 +176,7 @@ def get_opts(): def get_flags(): return [ - ('glew','yes'), + ('builtin_zlib', 'yes'), ('openssl','builtin'), #use builtin openssl ] @@ -196,7 +204,7 @@ def configure(env): env.Append(CPPPATH=['#platform/windows']) env['is_mingw']=False - if (os.name=="nt" and os.getenv("VSINSTALLDIR")!=None): + if (os.name=="nt" and os.getenv("VCINSTALLDIR") ): #build using visual studio env['ENV']['TMP'] = os.environ['TMP'] env.Append(CPPPATH=['#platform/windows/include']) @@ -258,7 +266,7 @@ def configure(env): env['ENV'] = os.environ; # This detection function needs the tools env (that is env['ENV'], not SCons's env), and that is why it's this far bellow in the code - compiler_version_str = detect_visual_c_compiler_version(env['ENV']) + compiler_version_str = methods.detect_visual_c_compiler_version(env['ENV']) # Note: this detection/override code from here onward should be here instead of in SConstruct because it's platform and compiler specific (MSVC/Windows) if(env["bits"] != "default"): @@ -271,20 +279,25 @@ def configure(env): # Forcing bits argument because MSVC does not have a flag to set this through SCons... it's different compilers (cl.exe's) called from the propper command prompt # that decide the architecture that is build for. Scons can only detect the os.getenviron (because vsvarsall.bat sets a lot of stuff for cl.exe to work with) env["bits"]="32" - env["x86_opt_vc"]=True - + env["x86_libtheora_opt_vc"]=True + print "Detected MSVC compiler: "+compiler_version_str # If building for 64bit architecture, disable assembly optimisations for 32 bit builds (theora as of writting)... vc compiler for 64bit can not compile _asm if(compiler_version_str == "amd64" or compiler_version_str == "x86_amd64"): env["bits"]="64" - env["x86_opt_vc"]=False + env["x86_libtheora_opt_vc"]=False print "Compiled program architecture will be a 64 bit executable (forcing bits=64)." elif (compiler_version_str=="x86" or compiler_version_str == "amd64_x86"): print "Compiled program architecture will be a 32 bit executable. (forcing bits=32)." else: - print "Failed to detect MSVC compiler architecture version... Defaulting to 32bit executable settings (forcing bits=32). Compilation attempt will continue, but SCons can not detect for what architecture this build is compiled for. You should check your settings/compilation setup." + print "Failed to detect MSVC compiler architecture version... Defaulting to 32bit executable settings (forcing bits=32). Compilation attempt will continue, but SCons can not detect for what architecture this build is compiled for. You should check your settings/compilation setup." if env["bits"]=="64": env.Append(CCFLAGS=['/D_WIN64']) + + # Incremental linking fix + env['BUILDERS']['ProgramOriginal'] = env['BUILDERS']['Program'] + env['BUILDERS']['Program'] = methods.precious_program + else: # Workaround for MinGW. See: @@ -352,7 +365,7 @@ def configure(env): env['AR'] = mingw_prefix+"ar" env['RANLIB'] = mingw_prefix+"ranlib" env['LD'] = mingw_prefix+"g++" - env["x86_opt_gcc"]=True + env["x86_libtheora_opt_gcc"]=True #env['CC'] = "winegcc" #env['CXX'] = "wineg++" @@ -379,73 +392,7 @@ def configure(env): env['is_mingw']=True env.Append( BUILDERS = { 'RES' : env.Builder(action = build_res_file, suffix = '.o',src_suffix = '.rc') } ) - import methods env.Append( BUILDERS = { 'GLSL120' : env.Builder(action = methods.build_legacygl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) env.Append( BUILDERS = { 'GLSL' : env.Builder(action = methods.build_glsl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } ) env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) - -def detect_visual_c_compiler_version(tools_env): - # tools_env is the variable scons uses to call tools that execute tasks, SCons's env['ENV'] that executes tasks... - # (see the SCons documentation for more information on what it does)... - # in order for this function to be well encapsulated i choose to force it to recieve SCons's TOOLS env (env['ENV'] - # and not scons setup environment (env)... so make sure you call the right environment on it or it will fail to detect - # the propper vc version that will be called - - # These is no flag to give to visual c compilers to set the architecture, ie scons bits argument (32,64,ARM etc) - # There are many different cl.exe files that are run, and each one compiles & links to a different architecture - # As far as I know, the only way to figure out what compiler will be run when Scons calls cl.exe via Program() - # is to check the PATH varaible and figure out which one will be called first. Code bellow does that and returns: - # the following string values: - - # "" Compiler not detected - # "amd64" Native 64 bit compiler - # "amd64_x86" 64 bit Cross Compiler for 32 bit - # "x86" Native 32 bit compiler - # "x86_amd64" 32 bit Cross Compiler for 64 bit - - # There are other architectures, but Godot does not support them currently, so this function does not detect arm/amd64_arm - # and similar architectures/compilers - - # Set chosen compiler to "not detected" - vc_chosen_compiler_index = -1 - vc_chosen_compiler_str = "" - - # find() works with -1 so big ifs bellow are needed... the simplest solution, in fact - # First test if amd64 and amd64_x86 compilers are present in the path - vc_amd64_compiler_detection_index = tools_env["PATH"].find(tools_env["VCINSTALLDIR"]+"BIN\\amd64;") - if(vc_amd64_compiler_detection_index > -1): - vc_chosen_compiler_index = vc_amd64_compiler_detection_index - vc_chosen_compiler_str = "amd64" - - vc_amd64_x86_compiler_detection_index = tools_env["PATH"].find(tools_env["VCINSTALLDIR"]+"BIN\\amd64_x86;") - if(vc_amd64_x86_compiler_detection_index > -1 - and (vc_chosen_compiler_index == -1 - or vc_chosen_compiler_index > vc_amd64_x86_compiler_detection_index)): - vc_chosen_compiler_index = vc_amd64_x86_compiler_detection_index - vc_chosen_compiler_str = "amd64_x86" - - - # Now check the 32 bit compilers - vc_x86_compiler_detection_index = tools_env["PATH"].find(tools_env["VCINSTALLDIR"]+"BIN;") - if(vc_x86_compiler_detection_index > -1 - and (vc_chosen_compiler_index == -1 - or vc_chosen_compiler_index > vc_x86_compiler_detection_index)): - vc_chosen_compiler_index = vc_x86_compiler_detection_index - vc_chosen_compiler_str = "x86" - - vc_x86_amd64_compiler_detection_index = tools_env["PATH"].find(tools_env['VCINSTALLDIR']+"BIN\\x86_amd64;") - if(vc_x86_amd64_compiler_detection_index > -1 - and (vc_chosen_compiler_index == -1 - or vc_chosen_compiler_index > vc_x86_amd64_compiler_detection_index)): - vc_chosen_compiler_index = vc_x86_amd64_compiler_detection_index - vc_chosen_compiler_str = "x86_amd64" - - # debug help - #print vc_amd64_compiler_detection_index - #print vc_amd64_x86_compiler_detection_index - #print vc_x86_compiler_detection_index - #print vc_x86_amd64_compiler_detection_index - #print "chosen "+str(vc_chosen_compiler_index)+ " | "+str(vc_chosen_compiler_str) - - return vc_chosen_compiler_str diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index cebafdabce..286f5fb0b7 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -29,7 +29,6 @@ #include "drivers/gles2/rasterizer_gles2.h" #include "os_windows.h" -#include "drivers/nedmalloc/memory_pool_static_nedmalloc.h" #include "drivers/unix/memory_pool_static_malloc.h" #include "os/memory_pool_dynamic_static.h" #include "drivers/windows/thread_windows.h" @@ -1312,10 +1311,13 @@ void OS_Windows::finalize_core() { void OS_Windows::vprint(const char* p_format, va_list p_list, bool p_stderr) { - char buf[16384+1]; - int len = vsnprintf(buf,16384,p_format,p_list); + const unsigned int BUFFER_SIZE = 16384; + char buf[BUFFER_SIZE+1]; // +1 for the terminating character + int len = vsnprintf(buf,BUFFER_SIZE,p_format,p_list); if (len<=0) return; + if(len >= BUFFER_SIZE) + len = BUFFER_SIZE; // Output is too big, will be truncated buf[len]=0; @@ -1364,13 +1366,16 @@ void OS_Windows::set_mouse_mode(MouseMode p_mode) { POINT pos = { (int) center.x, (int) center.y }; ClientToScreen(hWnd, &pos); SetCursorPos(pos.x, pos.y); - ShowCursor(false); } else { - ShowCursor(true); ReleaseCapture(); ClipCursor(NULL); } + if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_HIDDEN) { + hCursor = SetCursor(NULL); + } else { + SetCursor(hCursor); + } } OS_Windows::MouseMode OS_Windows::get_mouse_mode() const{ @@ -2154,10 +2159,15 @@ String OS_Windows::get_stdin_string(bool p_block) { } +void OS_Windows::enable_for_stealing_focus(ProcessID pid) { + + AllowSetForegroundWindow(pid); + +} + void OS_Windows::move_window_to_foreground() { SetForegroundWindow(hWnd); - BringWindowToTop(hWnd); } @@ -2411,6 +2421,9 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { #ifdef RTAUDIO_ENABLED AudioDriverManagerSW::add_driver(&driver_rtaudio); #endif +#ifdef XAUDIO2_ENABLED + AudioDriverManagerSW::add_driver(&driver_xaudio2); +#endif } diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index e3e037e57b..903dd10c70 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -41,6 +41,9 @@ #include "servers/audio/audio_server_sw.h" #include "servers/audio/sample_manager_sw.h" #include "drivers/rtaudio/audio_driver_rtaudio.h" +#ifdef XAUDIO2_ENABLED +#include "drivers/xaudio2/audio_driver_xaudio2.h" +#endif #include "servers/spatial_sound/spatial_sound_server_sw.h" #include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h" #include "drivers/unix/ip_unix.h" @@ -137,6 +140,9 @@ class OS_Windows : public OS { #ifdef RTAUDIO_ENABLED AudioDriverRtAudio driver_rtaudio; #endif +#ifdef XAUDIO2_ENABLED + AudioDriverXAudio2 driver_xaudio2; +#endif void _drag_event(int p_x, int p_y, int idx); void _touch_event(bool p_pressed, int p_x, int p_y, int idx); @@ -269,6 +275,7 @@ public: virtual String get_locale() const; virtual LatinKeyboardVariant get_latin_keyboard_variant() const; + virtual void enable_for_stealing_focus(ProcessID pid); virtual void move_window_to_foreground(); virtual String get_data_dir() const; virtual String get_system_dir(SystemDir p_dir) const; diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index 2c79365c08..b4cd60979c 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -29,6 +29,9 @@ #include "packet_peer_udp_winsock.h" #include <winsock2.h> +#include <ws2tcpip.h> + +#include "drivers/unix/socket_helpers.h" int PacketPeerUDPWinsock::get_available_packet_count() const { @@ -48,7 +51,15 @@ Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer,int &r_buffer_si return ERR_UNAVAILABLE; uint32_t size; - rb.read((uint8_t*)&packet_ip.host,4,true); + uint8_t type; + rb.read(&type, 1, true); + if (type == IP_Address::TYPE_IPV4) { + rb.read((uint8_t*)&packet_ip.field8,4,true); + packet_ip.type = IP_Address::TYPE_IPV4; + } else { + rb.read((uint8_t*)&packet_ip.field8,16,true); + packet_ip.type = IP_Address::TYPE_IPV6; + }; rb.read((uint8_t*)&packet_port,4,true); rb.read((uint8_t*)&size,4,true); rb.read(packet_buffer,size,true); @@ -60,19 +71,16 @@ Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer,int &r_buffer_si } Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer,int p_buffer_size){ - int sock = _get_socket(); + int sock = _get_socket(peer_addr.type); ERR_FAIL_COND_V( sock == -1, FAILED ); - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(peer_port); - addr.sin_addr = *((struct in_addr*)&peer_addr.host); - + struct sockaddr_storage addr; + size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port); _set_blocking(true); errno = 0; int err; - while ( (err = sendto(sock, (const char*)p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, sizeof(addr))) != p_buffer_size) { + while ( (err = sendto(sock, (const char*)p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, addr_size)) != p_buffer_size) { if (WSAGetLastError() != WSAEWOULDBLOCK) { return FAILED; @@ -104,17 +112,17 @@ void PacketPeerUDPWinsock::_set_blocking(bool p_blocking) { }; } -Error PacketPeerUDPWinsock::listen(int p_port, int p_recv_buffer_size){ +Error PacketPeerUDPWinsock::listen(int p_port, IP_Address::AddrType p_address_type, int p_recv_buffer_size) { close(); - int sock = _get_socket(); + int sock = _get_socket(p_address_type); if (sock == -1 ) return ERR_CANT_CREATE; - sockaddr_in addr = {0}; - addr.sin_family = AF_INET; - addr.sin_port = htons(p_port); - addr.sin_addr.s_addr = INADDR_ANY; - if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_in)) == -1 ) { + + struct sockaddr_storage addr = {0}; + size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_address_type, NULL); + + if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) { close(); return ERR_UNAVAILABLE; } @@ -146,17 +154,41 @@ Error PacketPeerUDPWinsock::_poll(bool p_wait) { _set_blocking(p_wait); - struct sockaddr_in from = {0}; - int len = sizeof(struct sockaddr_in); + struct sockaddr_storage from = {0}; + int len = sizeof(struct sockaddr_storage); int ret; while ( (ret = recvfrom(sockfd, (char*)recv_buffer, MIN((int)sizeof(recv_buffer),MAX(rb.space_left()-12, 0)), 0, (struct sockaddr*)&from, &len)) > 0) { - rb.write((uint8_t*)&from.sin_addr, 4); - uint32_t port = ntohs(from.sin_port); + + uint32_t port = 0; + + if (from.ss_family == AF_INET) { + uint8_t type = (uint8_t)IP_Address::TYPE_IPV4; + rb.write(&type, 1); + struct sockaddr_in* sin_from = (struct sockaddr_in*)&from; + rb.write((uint8_t*)&sin_from->sin_addr, 4); + port = ntohs(sin_from->sin_port); + + } else if (from.ss_family == AF_INET6) { + + uint8_t type = (uint8_t)IP_Address::TYPE_IPV6; + rb.write(&type, 1); + + struct sockaddr_in6* s6_from = (struct sockaddr_in6*)&from; + rb.write((uint8_t*)&s6_from->sin6_addr, 16); + + port = ntohs(s6_from->sin6_port); + + } else { + // WARN_PRINT("Ignoring packet with unknown address family"); + uint8_t type = (uint8_t)IP_Address::TYPE_NONE; + rb.write(&type, 1); + }; + rb.write((uint8_t*)&port, 4); rb.write((uint8_t*)&ret, 4); rb.write(recv_buffer, ret); - len = sizeof(struct sockaddr_in); + len = sizeof(struct sockaddr_storage); ++queue_count; }; @@ -202,12 +234,14 @@ int PacketPeerUDPWinsock::get_packet_port() const{ return packet_port; } -int PacketPeerUDPWinsock::_get_socket() { +int PacketPeerUDPWinsock::_get_socket(IP_Address::AddrType p_type) { if (sockfd != -1) return sockfd; - sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + int family = p_type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; + + sockfd = socket(family, SOCK_DGRAM, IPPROTO_UDP); ERR_FAIL_COND_V( sockfd == -1, -1 ); //fcntl(sockfd, F_SETFL, O_NONBLOCK); diff --git a/platform/windows/packet_peer_udp_winsock.h b/platform/windows/packet_peer_udp_winsock.h index b24dbac592..9837ef6621 100644 --- a/platform/windows/packet_peer_udp_winsock.h +++ b/platform/windows/packet_peer_udp_winsock.h @@ -42,15 +42,15 @@ class PacketPeerUDPWinsock : public PacketPeerUDP { mutable RingBuffer<uint8_t> rb; uint8_t recv_buffer[PACKET_BUFFER_SIZE]; mutable uint8_t packet_buffer[PACKET_BUFFER_SIZE]; - IP_Address packet_ip; - int packet_port; + mutable IP_Address packet_ip; + mutable int packet_port; mutable int queue_count; int sockfd; IP_Address peer_addr; int peer_port; - _FORCE_INLINE_ int _get_socket(); + _FORCE_INLINE_ int _get_socket(IP_Address::AddrType p_type); static PacketPeerUDP* _create(); @@ -67,7 +67,7 @@ public: virtual int get_max_packet_size() const; - virtual Error listen(int p_port,int p_recv_buffer_size=65536); + virtual Error listen(int p_port, IP_Address::AddrType p_address_type, int p_recv_buffer_size=65536); virtual void close(); virtual Error wait(); virtual bool is_listening() const; diff --git a/platform/windows/platform_config.h b/platform/windows/platform_config.h index 9e20750816..31512a1054 100644 --- a/platform/windows/platform_config.h +++ b/platform/windows/platform_config.h @@ -30,6 +30,4 @@ //#else //#include <alloca.h> //#endif -#define GLES2_INCLUDE_H "gl_context/GL/glew.h" - - +#define GLES2_INCLUDE_H "GL/glew.h" diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp index fcf0cb1640..b511e38ecb 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -31,16 +31,11 @@ #include "stream_peer_winsock.h" #include <winsock2.h> +#include <ws2tcpip.h> -int winsock_refcount = 0; - -static void set_addr_in(struct sockaddr_in& their_addr, const IP_Address& p_host, uint16_t p_port) { +#include "drivers/unix/socket_helpers.h" - their_addr.sin_family = AF_INET; // host byte order - their_addr.sin_port = htons(p_port); // short, network byte order - their_addr.sin_addr = *((struct in_addr*)&p_host.host); - memset(&(their_addr.sin_zero), '\0', 8); -}; +int winsock_refcount = 0; StreamPeerTCP* StreamPeerWinsock::_create() { @@ -92,10 +87,10 @@ Error StreamPeerWinsock::_poll_connection(bool p_block) const { _block(sockfd, false, true); }; - struct sockaddr_in their_addr; - set_addr_in(their_addr, peer_host, peer_port); + struct sockaddr_storage their_addr; + size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port); - if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == SOCKET_ERROR) { + if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == SOCKET_ERROR) { int err = WSAGetLastError(); if (err == WSAEISCONN) { @@ -299,9 +294,10 @@ void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port) Error StreamPeerWinsock::connect(const IP_Address& p_host, uint16_t p_port) { - ERR_FAIL_COND_V( p_host.host == 0, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V( p_host.type == IP_Address::TYPE_NONE, ERR_INVALID_PARAMETER); - if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { + int family = p_host.type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; + if ((sockfd = socket(family, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { ERR_PRINT("Socket creation failed!"); disconnect(); //perror("socket"); @@ -315,10 +311,10 @@ Error StreamPeerWinsock::connect(const IP_Address& p_host, uint16_t p_port) { return FAILED; }; - struct sockaddr_in their_addr; - set_addr_in(their_addr, p_host, p_port); + struct sockaddr_storage their_addr; + size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port); - if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == SOCKET_ERROR) { + if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { ERR_PRINT("Connection to remote host failed!"); diff --git a/platform/windows/tcp_server_winsock.cpp b/platform/windows/tcp_server_winsock.cpp index dd1cf43f3b..1aedc52bb9 100644 --- a/platform/windows/tcp_server_winsock.cpp +++ b/platform/windows/tcp_server_winsock.cpp @@ -31,6 +31,9 @@ #include "stream_peer_winsock.h" #include <winsock2.h> +#include <ws2tcpip.h> + +#include "drivers/unix/socket_helpers.h" extern int winsock_refcount; @@ -60,7 +63,7 @@ void TCPServerWinsock::cleanup() { }; -Error TCPServerWinsock::listen(uint16_t p_port,const List<String> *p_accepted_hosts) { +Error TCPServerWinsock::listen(uint16_t p_port, IP_Address::AddrType p_type,const List<String> *p_accepted_hosts) { int sockfd; sockfd = socket(AF_INET, SOCK_STREAM, 0); @@ -73,11 +76,8 @@ Error TCPServerWinsock::listen(uint16_t p_port,const List<String> *p_accepted_ho return FAILED; }; - struct sockaddr_in my_addr; - my_addr.sin_family = AF_INET; // host byte order - my_addr.sin_port = htons(p_port); // short, network byte order - my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP TODO: use p_accepted_hosts - memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero); + struct sockaddr_storage my_addr; + size_t addr_size = _set_listen_sockaddr(&my_addr, p_port, p_type, p_accepted_hosts); int reuse=1; if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) { @@ -86,7 +86,7 @@ Error TCPServerWinsock::listen(uint16_t p_port,const List<String> *p_accepted_ho } - if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) != SOCKET_ERROR) { + if (bind(sockfd, (struct sockaddr *)&my_addr, addr_size) != SOCKET_ERROR) { if (::listen(sockfd, SOMAXCONN) == SOCKET_ERROR) { @@ -140,16 +140,17 @@ Ref<StreamPeerTCP> TCPServerWinsock::take_connection() { return NULL; }; - struct sockaddr_in their_addr; + struct sockaddr_storage their_addr; int sin_size = sizeof(their_addr); int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &sin_size); ERR_FAIL_COND_V(fd == INVALID_SOCKET, NULL); Ref<StreamPeerWinsock> conn = memnew(StreamPeerWinsock); IP_Address ip; - ip.host = (uint32_t)their_addr.sin_addr.s_addr; + int port; + _set_ip_addr_port(ip, port, &their_addr); - conn->set_socket(fd, ip, ntohs(their_addr.sin_port)); + conn->set_socket(fd, ip, port); return conn; }; diff --git a/platform/windows/tcp_server_winsock.h b/platform/windows/tcp_server_winsock.h index bd6a05c74d..94601a2e12 100644 --- a/platform/windows/tcp_server_winsock.h +++ b/platform/windows/tcp_server_winsock.h @@ -39,7 +39,7 @@ class TCPServerWinsock : public TCP_Server { public: - virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL); + virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_IPV4,const List<String> *p_accepted_hosts=NULL); virtual bool is_connection_available() const; virtual Ref<StreamPeerTCP> take_connection(); diff --git a/platform/winrt/SCsub b/platform/winrt/SCsub index 2ea8cbd0de..91a179084d 100644 --- a/platform/winrt/SCsub +++ b/platform/winrt/SCsub @@ -1,11 +1,23 @@ +#!/usr/bin/env python + Import('env') files = [ 'thread_winrt.cpp', -# '#platform/windows/stream_peer_winsock.cpp', + '#platform/windows/tcp_server_winsock.cpp', + '#platform/windows/packet_peer_udp_winsock.cpp', + '#platform/windows/stream_peer_winsock.cpp', + '#platform/windows/key_mapping_win.cpp', + 'joystick_winrt.cpp', 'gl_context_egl.cpp', 'app.cpp', 'os_winrt.cpp', ] -env.Program('#bin/godot', files) +if "build_angle" in env and env["build_angle"]: + cmd = env.AlwaysBuild(env.ANGLE('libANGLE.lib', None)) + +prog = env.Program('#bin/godot', files) + +if "build_angle" in env and env["build_angle"]: + env.Depends(prog, [cmd]) diff --git a/platform/winrt/app.cpp b/platform/winrt/app.cpp index ea7619a64b..c2b7ba0641 100644 --- a/platform/winrt/app.cpp +++ b/platform/winrt/app.cpp @@ -1,4 +1,32 @@ -// +/*************************************************************************/ +/* app.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +// // This file demonstrates how to initialize EGL in a Windows Store app, using ICoreWindow. // @@ -7,17 +35,25 @@ #include "main/main.h" #include "core/os/dir_access.h" #include "core/os/file_access.h" +#include "core/os/keyboard.h" + +#include "platform/windows/key_mapping_win.h" + +#include <collection.h> using namespace Windows::ApplicationModel::Core; using namespace Windows::ApplicationModel::Activation; using namespace Windows::UI::Core; using namespace Windows::UI::Input; +using namespace Windows::Devices::Input; +using namespace Windows::UI::Xaml::Input; using namespace Windows::Foundation; using namespace Windows::Graphics::Display; +using namespace Windows::System; +using namespace Windows::System::Threading::Core; using namespace Microsoft::WRL; -using namespace Platform; -using namespace $ext_safeprojectname$; +using namespace GodotWinRT; // Helper to convert a length in device-independent pixels (DIPs) to a length in physical pixels. inline float ConvertDipsToPixels(float dips, float dpi) @@ -27,7 +63,7 @@ inline float ConvertDipsToPixels(float dips, float dpi) } // Implementation of the IFrameworkViewSource interface, necessary to run our app. -ref class HelloTriangleApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource +ref class GodotWinrtViewSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource { public: virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView() @@ -40,8 +76,8 @@ public: [Platform::MTAThread] int main(Platform::Array<Platform::String^>^) { - auto helloTriangleApplicationSource = ref new HelloTriangleApplicationSource(); - CoreApplication::Run(helloTriangleApplicationSource); + auto godotApplicationSource = ref new GodotWinrtViewSource(); + CoreApplication::Run(godotApplicationSource); return 0; } @@ -52,7 +88,8 @@ App::App() : mWindowHeight(0), mEglDisplay(EGL_NO_DISPLAY), mEglContext(EGL_NO_CONTEXT), - mEglSurface(EGL_NO_SURFACE) + mEglSurface(EGL_NO_SURFACE), + number_of_contacts(0) { } @@ -69,6 +106,7 @@ void App::Initialize(CoreApplicationView^ applicationView) // http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh994930.aspx os = new OSWinrt; + } // Called when the CoreWindow object is created (or re-created). @@ -95,20 +133,31 @@ void App::SetWindow(CoreWindow^ p_window) window->PointerPressed += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerPressed); - window->PointerMoved += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerMoved); - window->PointerReleased += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerReleased); + window->PointerWheelChanged += + ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerWheelChanged); + + mouseChangedNotifier = SignalNotifier::AttachToEvent(L"os_mouse_mode_changed", ref new SignalHandler( + this, &App::OnMouseModeChanged + )); - //window->PointerWheelChanged += - // ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerWheelChanged); + mouseChangedNotifier->Enable(); + window->CharacterReceived += + ref new TypedEventHandler<CoreWindow^, CharacterReceivedEventArgs^>(this, &App::OnCharacterReceived); + window->KeyDown += + ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &App::OnKeyDown); + window->KeyUp += + ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &App::OnKeyUp); - char* args[] = {"-path", "game", NULL}; - Main::setup("winrt", 2, args, false); + unsigned int argc; + char** argv = get_command_line(&argc); + + Main::setup("winrt", argc, argv, false); // The CoreWindow has been created, so EGL can be initialized. ContextEGL* context = memnew(ContextEGL(window)); @@ -217,7 +266,7 @@ static int _get_finger(uint32_t p_touch_id) { return p_touch_id % 31; // for now }; -void App::pointer_event(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args, bool p_pressed) { +void App::pointer_event(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args, bool p_pressed, bool p_is_wheel) { Windows::UI::Input::PointerPoint ^point = args->CurrentPoint; Windows::Foundation::Point pos = _get_pixel_position(window, point->Position, os); @@ -236,7 +285,7 @@ void App::pointer_event(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core last_touch_y[event.screen_touch.index] = pos.Y; os->input_event(event); - if (event.screen_touch.index != 0) + if (number_of_contacts > 1) return; }; // fallthrought of sorts @@ -251,6 +300,14 @@ void App::pointer_event(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core event.mouse_button.global_x = pos.X; event.mouse_button.global_y = pos.Y; + if (p_is_wheel) { + if (point->Properties->MouseWheelDelta > 0) { + event.mouse_button.button_index = point->Properties->IsHorizontalMouseWheel ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_UP; + } else if (point->Properties->MouseWheelDelta < 0) { + event.mouse_button.button_index = point->Properties->IsHorizontalMouseWheel ? BUTTON_WHEEL_LEFT : BUTTON_WHEEL_DOWN; + } + } + last_touch_x[31] = pos.X; last_touch_y[31] = pos.Y; @@ -260,21 +317,56 @@ void App::pointer_event(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core void App::OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) { + number_of_contacts++; pointer_event(sender, args, true); }; void App::OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) { + number_of_contacts--; pointer_event(sender, args, false); }; +void App::OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) { + + pointer_event(sender, args, true, true); +} + +void App::OnMouseModeChanged(Windows::System::Threading::Core::SignalNotifier^ signalNotifier, bool timedOut) { + + OS::MouseMode mode = os->get_mouse_mode(); + SignalNotifier^ notifier = mouseChangedNotifier; + + window->Dispatcher->RunAsync( + CoreDispatcherPriority::High, + ref new DispatchedHandler( + [mode, notifier, this]() { + if (mode == OS::MOUSE_MODE_CAPTURED) { + + this->MouseMovedToken = MouseDevice::GetForCurrentView()->MouseMoved += + ref new TypedEventHandler<MouseDevice^, MouseEventArgs^>(this, &App::OnMouseMoved); + + } else { + + MouseDevice::GetForCurrentView()->MouseMoved -= MouseMovedToken; + + } + + notifier->Enable(); + })); + + ResetEvent(os->mouse_mode_changed); + + +} + void App::OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) { Windows::UI::Input::PointerPoint ^point = args->CurrentPoint; Windows::Foundation::Point pos = _get_pixel_position(window, point->Position, os); - if (_is_touch(point)) { + if (point->IsInContact && _is_touch(point)) { InputEvent event; event.type = InputEvent::SCREEN_DRAG; @@ -286,11 +378,15 @@ void App::OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Cor event.screen_drag.relative_y = event.screen_drag.y - last_touch_y[event.screen_drag.index]; os->input_event(event); - if (event.screen_drag.index != 0) + if (number_of_contacts > 1) return; }; // fallthrought of sorts + // In case the mouse grabbed, MouseMoved will handle this + if (os->get_mouse_mode() == OS::MouseMode::MOUSE_MODE_CAPTURED) + return; + InputEvent event; event.type = InputEvent::MOUSE_MOTION; event.device = 0; @@ -301,16 +397,90 @@ void App::OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Cor event.mouse_motion.relative_x = pos.X - last_touch_x[31]; event.mouse_motion.relative_y = pos.Y - last_touch_y[31]; + last_mouse_pos = pos; + os->input_event(event); -}; +} + +void App::OnMouseMoved(MouseDevice ^ mouse_device, MouseEventArgs ^ args) { + + // In case the mouse isn't grabbed, PointerMoved will handle this + if (os->get_mouse_mode() != OS::MouseMode::MOUSE_MODE_CAPTURED) + return; + + Windows::Foundation::Point pos; + pos.X = last_mouse_pos.X + args->MouseDelta.X; + pos.Y = last_mouse_pos.Y + args->MouseDelta.Y; + + InputEvent event; + event.type = InputEvent::MOUSE_MOTION; + event.device = 0; + event.mouse_motion.x = pos.X; + event.mouse_motion.y = pos.Y; + event.mouse_motion.global_x = pos.X; + event.mouse_motion.global_y = pos.Y; + event.mouse_motion.relative_x = args->MouseDelta.X; + event.mouse_motion.relative_y = args->MouseDelta.Y; + + last_mouse_pos = pos; + + os->input_event(event); +} + +void App::key_event(Windows::UI::Core::CoreWindow^ sender, bool p_pressed, Windows::UI::Core::KeyEventArgs^ key_args, Windows::UI::Core::CharacterReceivedEventArgs^ char_args) +{ + + OSWinrt::KeyEvent ke; + + InputModifierState mod; + mod.meta = false; + mod.command = false; + mod.control = sender->GetAsyncKeyState(VirtualKey::Control) == CoreVirtualKeyStates::Down; + mod.alt = sender->GetAsyncKeyState(VirtualKey::Menu) == CoreVirtualKeyStates::Down; + mod.shift = sender->GetAsyncKeyState(VirtualKey::Shift) == CoreVirtualKeyStates::Down; + ke.mod_state = mod; + + ke.pressed = p_pressed; + + if (key_args != nullptr) { + + ke.type = OSWinrt::KeyEvent::MessageType::KEY_EVENT_MESSAGE; + ke.unicode = 0; + ke.scancode = KeyMappingWindows::get_keysym((unsigned int)key_args->VirtualKey); + ke.echo = (!p_pressed && !key_args->KeyStatus.IsKeyReleased) || (p_pressed && key_args->KeyStatus.WasKeyDown); + + } else { + + ke.type = OSWinrt::KeyEvent::MessageType::CHAR_EVENT_MESSAGE; + ke.unicode = char_args->KeyCode; + ke.scancode = 0; + ke.echo = (!p_pressed && !char_args->KeyStatus.IsKeyReleased) || (p_pressed && char_args->KeyStatus.WasKeyDown); + } + + os->queue_key_event(ke); + +} +void App::OnKeyDown(CoreWindow^ sender, KeyEventArgs^ args) +{ + key_event(sender, true, args); +} + +void App::OnKeyUp(CoreWindow^ sender, KeyEventArgs^ args) +{ + key_event(sender, false, args); +} + +void App::OnCharacterReceived(CoreWindow^ sender, CharacterReceivedEventArgs^ args) +{ + key_event(sender, true, nullptr, args); +} // Initializes scene resources void App::Load(Platform::String^ entryPoint) { - //char* args[] = {"-test", "render", NULL}; - //Main::setup("winrt", 2, args); + } // This method is called after the window becomes active. @@ -383,3 +553,95 @@ void App::UpdateWindowSize(Size size) vm.resizable = false; os->set_video_mode(vm); } + +char** App::get_command_line(unsigned int* out_argc) { + + static char* fail_cl[] = { "-path", "game", NULL }; + *out_argc = 2; + + FILE* f = _wfopen(L"__cl__.cl", L"rb"); + + if (f == NULL) { + + wprintf(L"Couldn't open command line file."); + return fail_cl; + } + +#define READ_LE_4(v) ((int)(##v[3] & 0xFF) << 24) | ((int)(##v[2] & 0xFF) << 16) | ((int)(##v[1] & 0xFF) << 8) | ((int)(##v[0] & 0xFF)) +#define CMD_MAX_LEN 65535 + + uint8_t len[4]; + int r = fread(len, sizeof(uint8_t), 4, f); + + Platform::Collections::Vector<Platform::String^> cl; + + if (r < 4) { + fclose(f); + wprintf(L"Wrong cmdline length."); + return(fail_cl); + } + + int argc = READ_LE_4(len); + + for (int i = 0; i < argc; i++) { + + r = fread(len, sizeof(uint8_t), 4, f); + + if (r < 4) { + fclose(f); + wprintf(L"Wrong cmdline param length."); + return(fail_cl); + } + + int strlen = READ_LE_4(len); + + if (strlen > CMD_MAX_LEN) { + fclose(f); + wprintf(L"Wrong command length."); + return(fail_cl); + } + + char* arg = new char[strlen + 1]; + r = fread(arg, sizeof(char), strlen, f); + arg[strlen] = '\0'; + + if (r == strlen) { + + int warg_size = MultiByteToWideChar(CP_UTF8, 0, arg, -1, NULL, 0); + wchar_t* warg = new wchar_t[warg_size]; + + MultiByteToWideChar(CP_UTF8, 0, arg, -1, warg, warg_size); + + cl.Append(ref new Platform::String(warg, warg_size)); + + } else { + + delete[] arg; + fclose(f); + wprintf(L"Error reading command."); + return(fail_cl); + } + } + +#undef READ_LE_4 +#undef CMD_MAX_LEN + + fclose(f); + + char** ret = new char*[cl.Size + 1]; + + for (int i = 0; i < cl.Size; i++) { + + int arg_size = WideCharToMultiByte(CP_UTF8, 0, cl.GetAt(i)->Data(), -1, NULL, 0, NULL, NULL); + char* arg = new char[arg_size]; + + WideCharToMultiByte(CP_UTF8, 0, cl.GetAt(i)->Data(), -1, arg, arg_size, NULL, NULL); + + ret[i] = arg; + + } + ret[cl.Size] = NULL; + *out_argc = cl.Size; + + return ret; +} diff --git a/platform/winrt/app.h b/platform/winrt/app.h index 25b0d524ae..652ec86e1f 100644 --- a/platform/winrt/app.h +++ b/platform/winrt/app.h @@ -1,4 +1,32 @@ -#pragma once +/*************************************************************************/ +/* app.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#pragma once #include <string> @@ -7,7 +35,7 @@ #include "os_winrt.h" #include "GLES2/gl2.h" -namespace $ext_safeprojectname$ +namespace GodotWinRT { ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView { @@ -21,6 +49,11 @@ namespace $ext_safeprojectname$ virtual void Run(); virtual void Uninitialize(); + property Windows::Foundation::EventRegistrationToken MouseMovedToken { + Windows::Foundation::EventRegistrationToken get() { return this->mouseMovedToken; } + void set(Windows::Foundation::EventRegistrationToken p_token) { this->mouseMovedToken = p_token; } + }; + private: void RecreateRenderer(); @@ -32,16 +65,28 @@ namespace $ext_safeprojectname$ void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args); void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args); - void pointer_event(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args, bool p_pressed); + void pointer_event(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args, bool p_pressed, bool p_is_wheel = false); void OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args); void OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args); void OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args); + void OnMouseMoved(Windows::Devices::Input::MouseDevice^ mouse_device, Windows::Devices::Input::MouseEventArgs^ args); + void OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args); + + Windows::System::Threading::Core::SignalNotifier^ mouseChangedNotifier; + Windows::Foundation::EventRegistrationToken mouseMovedToken; + void OnMouseModeChanged(Windows::System::Threading::Core::SignalNotifier^ signalNotifier, bool timedOut); + void key_event(Windows::UI::Core::CoreWindow^ sender, bool p_pressed, Windows::UI::Core::KeyEventArgs^ key_args = nullptr, Windows::UI::Core::CharacterReceivedEventArgs^ char_args = nullptr); + void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args); + void OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args); + void OnCharacterReceived(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args); void UpdateWindowSize(Windows::Foundation::Size size); void InitializeEGL(Windows::UI::Core::CoreWindow^ window); void CleanupEGL(); + char** get_command_line(unsigned int* out_argc); + bool mWindowClosed; bool mWindowVisible; GLsizei mWindowWidth; @@ -56,6 +101,8 @@ namespace $ext_safeprojectname$ int last_touch_x[32]; // 20 fingers, index 31 reserved for the mouse int last_touch_y[32]; + int number_of_contacts; + Windows::Foundation::Point last_mouse_pos; }; } diff --git a/platform/winrt/detect.py b/platform/winrt/detect.py index 86028d3af8..a7bc62f685 100644 --- a/platform/winrt/detect.py +++ b/platform/winrt/detect.py @@ -1,9 +1,8 @@ - - import os import sys import string +import methods def is_active(): @@ -16,6 +15,10 @@ def can_build(): if (os.name=="nt"): #building natively on windows! if (os.getenv("VSINSTALLDIR")): + + if (os.getenv("ANGLE_SRC_PATH") == None): + return False + return True return False @@ -24,133 +27,140 @@ def get_opts(): def get_flags(): - return [] + return [ + ('tools', 'no'), + ('builtin_zlib', 'yes'), + ('openssl', 'builtin'), + ('xaudio2', 'yes'), + ] def configure(env): - env.Append(CPPPATH=['#platform/winrt', '#platform/winrt/include']) - arch = "" - - if os.getenv('PLATFORM') == "ARM": - - # compiler commandline - # debug: /Yu"pch.h" /MP /GS /analyze- /W3 /wd"4453" /wd"28204" /Zc:wchar_t /I"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\App2\App2.WindowsPhone\" /I"Generated Files\" /I"ARM\Debug\" /I"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\App2\App2.Shared\" /ZW:nostdlib /Zi /Gm- /Od /sdl /Fd"ARM\Debug\vc120.pdb" /fp:precise /D "PSAPI_VERSION=2" /D "WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP" /D "_UITHREADCTXT_SUPPORT=0" /D "_UNICODE" /D "UNICODE" /D "_DEBUG" /errorReport:prompt /WX- /Zc:forScope /RTC1 /ZW /Gd /Oy- /MDd /Fa"ARM\Debug\" /EHsc /nologo /Fo"ARM\Debug\" /Fp"ARM\Debug\App2.WindowsPhone.pch" - # release: /Yu"pch.h" /MP /GS /GL /analyze- /W3 /wd"4453" /wd"28204" /Gy /Zc:wchar_t /I"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\App2\App2.WindowsPhone\" /I"Generated Files\" /I"ARM\Release\" /I"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\App2\App2.Shared\" /ZW:nostdlib /Zi /Gm- /O2 /sdl /Fd"ARM\Release\vc120.pdb" /fp:precise /D "PSAPI_VERSION=2" /D "WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP" /D "_UITHREADCTXT_SUPPORT=0" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /ZW /Gd /Oy- /Oi /MD /Fa"ARM\Release\" /EHsc /nologo /Fo"ARM\Release\" /Fp"ARM\Release\App2.WindowsPhone.pch" - - # linker commandline - # debug: /OUT:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Debug\App2.WindowsPhone\App2.WindowsPhone.exe" /MANIFEST:NO /NXCOMPAT /PDB:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Debug\App2.WindowsPhone\App2.WindowsPhone.pdb" /DYNAMICBASE "WindowsPhoneCore.lib" "RuntimeObject.lib" "PhoneAppModelHost.lib" /DEBUG /MACHINE:ARM /NODEFAULTLIB:"kernel32.lib" /NODEFAULTLIB:"ole32.lib" /WINMD /APPCONTAINER /INCREMENTAL /PGD:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Debug\App2.WindowsPhone\App2.WindowsPhone.pgd" /WINMDFILE:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Debug\App2.WindowsPhone\App2.winmd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:NO /ManifestFile:"ARM\Debug\App2.WindowsPhone.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1 - # release: /OUT:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Release\App2.WindowsPhone\App2.WindowsPhone.exe" /MANIFEST:NO /LTCG /NXCOMPAT /PDB:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Release\App2.WindowsPhone\App2.WindowsPhone.pdb" /DYNAMICBASE "WindowsPhoneCore.lib" "RuntimeObject.lib" "PhoneAppModelHost.lib" /DEBUG /MACHINE:ARM /NODEFAULTLIB:"kernel32.lib" /NODEFAULTLIB:"ole32.lib" /WINMD /APPCONTAINER /OPT:REF /PGD:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Release\App2.WindowsPhone\App2.WindowsPhone.pgd" /WINMDFILE:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Release\App2.WindowsPhone\App2.winmd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:NO /ManifestFile:"ARM\Release\App2.WindowsPhone.exe.intermediate.manifest" /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /TLBID:1 - - arch = "arm" + if(env["bits"] != "default"): + print "Error: bits argument is disabled for MSVC" + print ("Bits argument is not supported for MSVC compilation. Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console (or Visual Studio settings)" + +" that is being used to run SCons. As a consequence, bits argument is disabled. Run scons again without bits argument (example: scons p=winrt) and SCons will attempt to detect what MSVC compiler" + +" will be executed and inform you.") + sys.exit() - env.Append(LINKFLAGS=['/INCREMENTAL:NO', '/MANIFEST:NO', '/NXCOMPAT', '/DYNAMICBASE', "WindowsPhoneCore.lib", "RuntimeObject.lib", "PhoneAppModelHost.lib", "/DEBUG", "/MACHINE:ARM", '/NODEFAULTLIB:"kernel32.lib"', '/NODEFAULTLIB:"ole32.lib"', '/WINMD', '/APPCONTAINER', '/MANIFESTUAC:NO', '/ERRORREPORT:PROMPT', '/NOLOGO', '/TLBID:1']) - env.Append(LIBPATH=['#platform/winrt/ARM/lib']) + arch = "" + env['ENV'] = os.environ; - env.Append(CCFLAGS=string.split('/MP /GS /wd"4453" /wd"28204" /analyze- /Zc:wchar_t /Zi /Gm- /Od /fp:precise /fp:precise /D "PSAPI_VERSION=2" /D "WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP" /DWINDOWSPHONE_ENABLED /D "_UITHREADCTXT_SUPPORT=0" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MD /RTC1 /Gd /EHsc /nologo')) - env.Append(CXXFLAGS=string.split('/ZW')) + # ANGLE + angle_root = os.getenv("ANGLE_SRC_PATH") + env.Append(CPPPATH=[angle_root + '/include']) + jobs = str(env.GetOption("num_jobs")) + angle_build_cmd = "msbuild.exe " + angle_root + "/winrt/10/src/angle.sln /nologo /v:m /m:" + jobs + " /p:Configuration=Release /p:Platform=" - if (env["target"]=="release"): + if os.path.isfile(str(os.getenv("ANGLE_SRC_PATH")) + "/winrt/10/src/angle.sln"): + env["build_angle"] = True - env.Append(CCFLAGS=['/O2']) - env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS']) + if os.getenv('Platform') == "ARM": - elif (env["target"]=="test"): + print "Compiled program architecture will be an ARM executable. (forcing bits=32)." - env.Append(CCFLAGS=['/O2','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO']) - env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) + arch="arm" + env["bits"]="32" + env.Append(LINKFLAGS=['/MACHINE:ARM']) + env.Append(LIBPATH=[os.environ['VCINSTALLDIR'] + 'lib/store/arm']) - elif (env["target"]=="debug"): + angle_build_cmd += "ARM" - env.Append(CCFLAGS=['/Zi','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO']) - env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) - env.Append(LINKFLAGS=['/DEBUG', '/D_DEBUG']) + env.Append(LIBPATH=[angle_root + '/winrt/10/src/Release_ARM/lib']) - elif (env["target"]=="profile"): + else: - env.Append(CCFLAGS=['-g','-pg']) - env.Append(LINKFLAGS=['-pg']) + compiler_version_str = methods.detect_visual_c_compiler_version(env['ENV']) + if(compiler_version_str == "amd64" or compiler_version_str == "x86_amd64"): + env["bits"]="64" + print "Compiled program architecture will be a x64 executable (forcing bits=64)." + elif (compiler_version_str=="x86" or compiler_version_str == "amd64_x86"): + env["bits"]="32" + print "Compiled program architecture will be a x86 executable. (forcing bits=32)." + else: + print "Failed to detect MSVC compiler architecture version... Defaulting to 32bit executable settings (forcing bits=32). Compilation attempt will continue, but SCons can not detect for what architecture this build is compiled for. You should check your settings/compilation setup." + env["bits"]="32" - env['ENV'] = os.environ; - # fix environment for windows phone 8.1 - env['ENV']['WINDOWSPHONEKITDIR'] = env['ENV']['WINDOWSPHONEKITDIR'].replace("8.0", "8.1") # wtf - env['ENV']['INCLUDE'] = env['ENV']['INCLUDE'].replace("8.0", "8.1") - env['ENV']['LIB'] = env['ENV']['LIB'].replace("8.0", "8.1") - env['ENV']['PATH'] = env['ENV']['PATH'].replace("8.0", "8.1") - env['ENV']['LIBPATH'] = env['ENV']['LIBPATH'].replace("8.0\\Windows Metadata", "8.1\\References\\CommonConfiguration\\Neutral") + if (env["bits"] == "32"): + arch = "x86" - else: + angle_build_cmd += "Win32" - arch = "x64" - env.Append(LINKFLAGS=['/MANIFEST:NO', '/NXCOMPAT', '/DYNAMICBASE', "kernel32.lib", '/MACHINE:X64', '/WINMD', '/APPCONTAINER', '/MANIFESTUAC:NO', '/ERRORREPORT:PROMPT', '/NOLOGO', '/TLBID:1']) + env.Append(CPPFLAGS=['/DPNG_ABORT=abort']) + env.Append(LINKFLAGS=['/MACHINE:X86']) + env.Append(LIBPATH=[os.environ['VCINSTALLDIR'] + 'lib/store']) + env.Append(LIBPATH=[angle_root + '/winrt/10/src/Release_Win32/lib']) - env.Append(LIBPATH=['#platform/winrt/x64/lib']) + else: + arch = "x64" + angle_build_cmd += "x64" - if (env["target"]=="release"): + env.Append(LINKFLAGS=['/MACHINE:X64']) + env.Append(LIBPATH=[os.environ['VCINSTALLDIR'] + 'lib/store/amd64']) + env.Append(LIBPATH=[angle_root + '/winrt/10/src/Release_x64/lib']) - env.Append(CCFLAGS=['/O2']) - env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS']) - env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup']) + env.Append(CPPPATH=['#platform/winrt','#drivers/windows']) + env.Append(LINKFLAGS=['/MANIFEST:NO', '/NXCOMPAT', '/DYNAMICBASE', '/WINMD', '/APPCONTAINER', '/ERRORREPORT:PROMPT', '/NOLOGO', '/TLBID:1', '/NODEFAULTLIB:"kernel32.lib"', '/NODEFAULTLIB:"ole32.lib"']) + env.Append(CPPFLAGS=['/D','__WRL_NO_DEFAULT_LIB__','/D','WIN32']) + env.Append(CPPFLAGS=['/FU', os.environ['VCINSTALLDIR'] + 'lib/store/references/platform.winmd']) + env.Append(CPPFLAGS=['/AI', os.environ['VCINSTALLDIR'] + 'lib/store/references']) - elif (env["target"]=="test"): + env.Append(LIBPATH=[os.environ['VCINSTALLDIR'] + 'lib/store/references']) - env.Append(CCFLAGS=['/O2','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO']) - env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) + if (env["target"]=="release"): - elif (env["target"]=="debug"): + env.Append(CPPFLAGS=['/O2', '/GL']) + env.Append(CPPFLAGS=['/MD']) + env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS', '/LTCG']) - env.Append(CCFLAGS=['/Zi','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO']) - env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) - env.Append(LINKFLAGS=['/DEBUG', '/D_DEBUG']) + elif (env["target"]=="release_debug"): - elif (env["target"]=="profile"): + env.Append(CCFLAGS=['/O2','/Zi','/DDEBUG_ENABLED']) + env.Append(CPPFLAGS=['/MD']) + env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) - env.Append(CCFLAGS=['-g','-pg']) - env.Append(LINKFLAGS=['-pg']) + elif (env["target"]=="debug"): + env.Append(CCFLAGS=['/Zi','/DDEBUG_ENABLED','/DDEBUG_MEMORY_ENABLED']) + env.Append(CPPFLAGS=['/MDd']) + env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) + env.Append(LINKFLAGS=['/DEBUG']) - env.Append(CCFLAGS=string.split('/MP /GS /wd"4453" /wd"28204" /Zc:wchar_t /Gm- /Od /fp:precise /D "_UNICODE" /D "UNICODE" /D "WINAPI_FAMILY=WINAPI_FAMILY_APP" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /EHsc /nologo')) - env.Append(CXXFLAGS=string.split('/ZW')) - env.Append(CCFLAGS=['/AI', os.environ['VCINSTALLDIR']+'\\vcpackages', '/AI', os.environ['WINDOWSSDKDIR']+'\\References\\CommonConfiguration\\Neutral']) - env.Append(CCFLAGS=['/DWINAPI_FAMILY=WINAPI_FAMILY_APP', '/D_WIN32_WINNT=0x0603', '/DNTDDI_VERSION=0x06030000']) - env['ENV'] = os.environ; + env.Append(CCFLAGS=string.split('/FS /MP /GS /wd"4453" /wd"28204" /wd"4291" /Zc:wchar_t /Gm- /fp:precise /D "_UNICODE" /D "UNICODE" /D "WINAPI_FAMILY=WINAPI_FAMILY_APP" /errorReport:prompt /WX- /Zc:forScope /Gd /EHsc /nologo')) + env.Append(CXXFLAGS=string.split('/ZW /FS')) + env.Append(CCFLAGS=['/AI', os.environ['VCINSTALLDIR']+'\\vcpackages', '/AI', os.environ['WINDOWSSDKDIR']+'\\References\\CommonConfiguration\\Neutral']) env["PROGSUFFIX"]="."+arch+env["PROGSUFFIX"] env["OBJSUFFIX"]="."+arch+env["OBJSUFFIX"] env["LIBSUFFIX"]="."+arch+env["LIBSUFFIX"] - - #env.Append(CCFLAGS=['/Gd','/GR','/nologo', '/EHsc']) - #env.Append(CXXFLAGS=['/TP', '/ZW']) - #env.Append(CPPFLAGS=['/DMSVC', '/GR', ]) - ##env.Append(CCFLAGS=['/I'+os.getenv("WindowsSdkDir")+"/Include"]) env.Append(CCFLAGS=['/DWINRT_ENABLED']) env.Append(CCFLAGS=['/DWINDOWS_ENABLED']) - env.Append(CCFLAGS=['/DRTAUDIO_ENABLED']) - #env.Append(CCFLAGS=['/DWIN32']) env.Append(CCFLAGS=['/DTYPED_METHOD_BIND']) - env.Append(CCFLAGS=['/DGLES2_ENABLED']) - #env.Append(CCFLAGS=['/DGLES1_ENABLED']) + env.Append(CCFLAGS=['/DGLES2_ENABLED','/DGL_GLEXT_PROTOTYPES','/DEGL_EGLEXT_PROTOTYPES','/DANGLE_ENABLED']) - LIBS=[ - #'winmm', + LIBS = [ + 'WindowsApp', + 'mincore', + 'libANGLE', 'libEGL', 'libGLESv2', - 'libANGLE', - #'kernel32','ole32','user32', 'advapi32' ] env.Append(LINKFLAGS=[p+".lib" for p in LIBS]) - import methods + # Incremental linking fix + env['BUILDERS']['ProgramOriginal'] = env['BUILDERS']['Program'] + env['BUILDERS']['Program'] = methods.precious_program + + env.Append( BUILDERS = { 'ANGLE' : env.Builder(action = angle_build_cmd) } ) + env.Append( BUILDERS = { 'GLSL120' : env.Builder(action = methods.build_legacygl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) env.Append( BUILDERS = { 'GLSL' : env.Builder(action = methods.build_glsl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } ) env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) - - -#/c/Program Files (x86)/Windows Phone Kits/8.1/lib/ARM/WindowsPhoneCore.lib diff --git a/platform/winrt/export/export.cpp b/platform/winrt/export/export.cpp new file mode 100644 index 0000000000..eca9f09de6 --- /dev/null +++ b/platform/winrt/export/export.cpp @@ -0,0 +1,2391 @@ +/*************************************************************************/ +/* export.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/************************************************************************* + * The code for signing the package was ported from fb-util-for-appx + * available at https://github.com/facebook/fb-util-for-appx + * and distributed also under the following license: + +BSD License + +For fb-util-for-appx software + +Copyright (c) 2016, Facebook, Inc. 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 Facebook nor the names of its 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 HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF 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 "version.h" +#include "export.h" +#include "object.h" +#include "tools/editor/editor_import_export.h" +#include "tools/editor/editor_node.h" +#include "platform/winrt/logo.h" +#include "os/file_access.h" +#include "io/zip.h" +#include "io/unzip.h" +#include "io/zip_io.h" +#include "io/sha256.h" +#include "io/base64.h" +#include "bind/core_bind.h" +#include "globals.h" +#include "io/marshalls.h" + +#include <zlib.h> + +// Capabilities +static const char* uwp_capabilities[] = { + "allJoyn", + "codeGeneration", + "internetClient", + "internetClientServer", + "privateNetworkClientServer", + NULL +}; +static const char* uwp_uap_capabilities[] = { + "appointments", + "blockedChatMessages", + "chat", + "contacts", + "enterpriseAuthentication", + "musicLibrary", + "objects3D", + "picturesLibrary", + "phoneCall", + "removableStorage", + "sharedUserCertificates", + "userAccountInformation", + "videosLibrary", + "voipCall", + NULL +}; +static const char* uwp_device_capabilites[] = { + "bluetooth", + "location", + "microphone", + "proximity", + "webcam", + NULL +}; + +#ifdef OPENSSL_ENABLED +#include <openssl/bio.h> +#include <openssl/asn1.h> +#include <openssl/pkcs7.h> +#include <openssl/pkcs12.h> +#include <openssl/err.h> +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include <openssl/ossl_typ.h> + +namespace asn1 { + // https://msdn.microsoft.com/en-us/gg463180.aspx + + struct SPCStatementType { + ASN1_OBJECT *type; + }; + DECLARE_ASN1_FUNCTIONS(SPCStatementType) + + struct SPCSpOpusInfo { + ASN1_TYPE *programName; + ASN1_TYPE *moreInfo; + }; + DECLARE_ASN1_FUNCTIONS(SPCSpOpusInfo) + + struct DigestInfo { + X509_ALGOR *digestAlgorithm; + ASN1_OCTET_STRING *digest; + }; + DECLARE_ASN1_FUNCTIONS(DigestInfo) + + struct SPCAttributeTypeAndOptionalValue { + ASN1_OBJECT *type; + ASN1_TYPE *value; // SPCInfoValue + }; + DECLARE_ASN1_FUNCTIONS(SPCAttributeTypeAndOptionalValue) + + // Undocumented. + struct SPCInfoValue { + ASN1_INTEGER *i1; + ASN1_OCTET_STRING *s1; + ASN1_INTEGER *i2; + ASN1_INTEGER *i3; + ASN1_INTEGER *i4; + ASN1_INTEGER *i5; + ASN1_INTEGER *i6; + }; + DECLARE_ASN1_FUNCTIONS(SPCInfoValue) + + struct SPCIndirectDataContent { + SPCAttributeTypeAndOptionalValue *data; + DigestInfo *messageDigest; + }; + DECLARE_ASN1_FUNCTIONS(SPCIndirectDataContent) + + IMPLEMENT_ASN1_FUNCTIONS(SPCIndirectDataContent) + ASN1_SEQUENCE(SPCIndirectDataContent) = { + ASN1_SIMPLE(SPCIndirectDataContent, data, + SPCAttributeTypeAndOptionalValue), + ASN1_SIMPLE(SPCIndirectDataContent, messageDigest, DigestInfo), + } ASN1_SEQUENCE_END(SPCIndirectDataContent) + + IMPLEMENT_ASN1_FUNCTIONS(SPCAttributeTypeAndOptionalValue) + ASN1_SEQUENCE(SPCAttributeTypeAndOptionalValue) = { + ASN1_SIMPLE(SPCAttributeTypeAndOptionalValue, type, + ASN1_OBJECT), + ASN1_OPT(SPCAttributeTypeAndOptionalValue, value, ASN1_ANY), + } ASN1_SEQUENCE_END(SPCAttributeTypeAndOptionalValue) + + IMPLEMENT_ASN1_FUNCTIONS(SPCInfoValue) + ASN1_SEQUENCE(SPCInfoValue) = { + ASN1_SIMPLE(SPCInfoValue, i1, ASN1_INTEGER), + ASN1_SIMPLE(SPCInfoValue, s1, ASN1_OCTET_STRING), + ASN1_SIMPLE(SPCInfoValue, i2, ASN1_INTEGER), + ASN1_SIMPLE(SPCInfoValue, i3, ASN1_INTEGER), + ASN1_SIMPLE(SPCInfoValue, i4, ASN1_INTEGER), + ASN1_SIMPLE(SPCInfoValue, i5, ASN1_INTEGER), + ASN1_SIMPLE(SPCInfoValue, i6, ASN1_INTEGER), + } ASN1_SEQUENCE_END(SPCInfoValue) + + IMPLEMENT_ASN1_FUNCTIONS(DigestInfo) + ASN1_SEQUENCE(DigestInfo) = { + ASN1_SIMPLE(DigestInfo, digestAlgorithm, X509_ALGOR), + ASN1_SIMPLE(DigestInfo, digest, ASN1_OCTET_STRING), + } ASN1_SEQUENCE_END(DigestInfo) + + ASN1_SEQUENCE(SPCSpOpusInfo) = { + ASN1_OPT(SPCSpOpusInfo, programName, ASN1_ANY), + ASN1_OPT(SPCSpOpusInfo, moreInfo, ASN1_ANY), + } ASN1_SEQUENCE_END(SPCSpOpusInfo) + IMPLEMENT_ASN1_FUNCTIONS(SPCSpOpusInfo) + + ASN1_SEQUENCE(SPCStatementType) = { + ASN1_SIMPLE(SPCStatementType, type, ASN1_OBJECT), + } ASN1_SEQUENCE_END(SPCStatementType) + IMPLEMENT_ASN1_FUNCTIONS(SPCStatementType) +} + +class EncodedASN1 { + + uint8_t* i_data; + size_t i_size; + + EncodedASN1(uint8_t** p_data, size_t p_size) { + + i_data = *p_data; + i_size = p_size; + } + +public: + + template <typename T, int(*TEncode)(T *, uint8_t **)> + static EncodedASN1 FromItem(T *item) { + uint8_t *dataRaw = NULL; + int size = TEncode(item, &dataRaw); + + return EncodedASN1(&dataRaw, size); + } + + const uint8_t *data() const { + return i_data; + } + + size_t size() const { + return i_size; + } + + // Assumes the encoded ASN.1 represents a SEQUENCE and puts it into + // an ASN1_STRING. + // + // The returned object holds a copy of this object's data. + ASN1_STRING* ToSequenceString() { + ASN1_STRING* string = ASN1_STRING_new(); + if (!string) { + return NULL; + } + if (!ASN1_STRING_set(string, i_data, i_size)) { + return NULL; + } + return string; + } + + // Assumes the encoded ASN.1 represents a SEQUENCE and puts it into + // an ASN1_TYPE. + // + // The returned object holds a copy of this object's data. + ASN1_TYPE* ToSequenceType() { + ASN1_STRING* string = ToSequenceString(); + ASN1_TYPE* type = ASN1_TYPE_new(); + if (!type) { + return NULL; + } + type->type = V_ASN1_SEQUENCE; + type->value.sequence = string; + return type; + } + +}; + +#endif // OPENSSL_ENABLED + +class AppxPackager { + + enum { + FILE_HEADER_MAGIC = 0x04034b50, + DATA_DESCRIPTOR_MAGIC = 0x08074b50, + CENTRAL_DIR_MAGIC = 0x02014b50, + END_OF_CENTRAL_DIR_MAGIC = 0x06054b50, + ZIP64_END_OF_CENTRAL_DIR_MAGIC = 0x06064b50, + ZIP64_END_DIR_LOCATOR_MAGIC = 0x07064b50, + P7X_SIGNATURE = 0x58434b50, + ZIP64_HEADER_ID = 0x0001, + ZIP_VERSION = 20, + ZIP_ARCHIVE_VERSION = 45, + GENERAL_PURPOSE = 0x00, + BASE_FILE_HEADER_SIZE = 30, + DATA_DESCRIPTOR_SIZE = 24, + BASE_CENTRAL_DIR_SIZE = 46, + EXTRA_FIELD_LENGTH = 28, + ZIP64_HEADER_SIZE = 24, + ZIP64_END_OF_CENTRAL_DIR_SIZE = (56 - 12), + END_OF_CENTRAL_DIR_SIZE = 42, + BLOCK_SIZE = 65536, + }; + + struct BlockHash { + + String base64_hash; + size_t compressed_size; + }; + + struct FileMeta { + + String name; + int lfh_size; + bool compressed; + size_t compressed_size; + size_t uncompressed_size; + Vector<BlockHash> hashes; + uLong file_crc32; + ZPOS64_T zip_offset; + }; + + String progress_task; + FileAccess *package; + String tmp_blockmap_file_path; + String tmp_content_types_file_path; + + Set<String> mime_types; + + Vector<FileMeta> file_metadata; + + ZPOS64_T central_dir_offset; + ZPOS64_T end_of_central_dir_offset; + Vector<uint8_t> central_dir_data; + + String hash_block(uint8_t* p_block_data, size_t p_block_len); + + void make_block_map(); + void make_content_types(); + + + _FORCE_INLINE_ unsigned int buf_put_int16(uint16_t p_val, uint8_t * p_buf) { + for (int i = 0; i < 2; i++) { + *p_buf++ = (p_val >> (i * 8)) & 0xFF; + } + return 2; + } + + _FORCE_INLINE_ unsigned int buf_put_int32(uint32_t p_val, uint8_t * p_buf) { + for (int i = 0; i < 4; i++) { + *p_buf++ = (p_val >> (i * 8)) & 0xFF; + } + return 4; + } + + _FORCE_INLINE_ unsigned int buf_put_int64(uint64_t p_val, uint8_t * p_buf) { + for (int i = 0; i < 8; i++) { + *p_buf++ = (p_val >> (i * 8)) & 0xFF; + } + return 8; + } + + _FORCE_INLINE_ unsigned int buf_put_string(String p_val, uint8_t * p_buf) { + for (int i = 0; i < p_val.length(); i++) { + *p_buf++ = p_val.utf8().get(i); + } + return p_val.length(); + } + + Vector<uint8_t> make_file_header(FileMeta p_file_meta); + void store_central_dir_header(const FileMeta p_file, bool p_do_hash = true); + Vector<uint8_t> make_end_of_central_record(); + + String content_type(String p_extension); + +#ifdef OPENSSL_ENABLED + + // Signing methods and structs: + + String certificate_path; + String certificate_pass; + bool sign_package; + + struct CertFile { + + EVP_PKEY* private_key; + X509* certificate; + }; + + SHA256_CTX axpc_context; // SHA256 context for ZIP file entries + SHA256_CTX axcd_context; // SHA256 context for ZIP directory entries + + struct AppxDigests { + + uint8_t axpc[SHA256_DIGEST_LENGTH]; // ZIP file entries + uint8_t axcd[SHA256_DIGEST_LENGTH]; // ZIP directory entry + uint8_t axct[SHA256_DIGEST_LENGTH]; // Content types XML + uint8_t axbm[SHA256_DIGEST_LENGTH]; // Block map XML + uint8_t axci[SHA256_DIGEST_LENGTH]; // Code Integrity file (optional) + }; + + CertFile cert_file; + AppxDigests digests; + + void MakeSPCInfoValue(asn1::SPCInfoValue &info); + Error MakeIndirectDataContent(asn1::SPCIndirectDataContent &idc); + Error add_attributes(PKCS7_SIGNER_INFO *signerInfo); + void make_digests(); + void write_digest(Vector<uint8_t> &p_out_buffer); + + Error openssl_error(unsigned long p_err); + Error read_cert_file(const String &p_path, const String &p_password, CertFile* p_out_cf); + Error sign(const CertFile &p_cert, const AppxDigests &digests, PKCS7* p_out_signature); + +#endif // OPENSSL_ENABLED + +public: + + enum SignOption { + + SIGN, + DONT_SIGN, + }; + + void set_progress_task(String p_task) { progress_task = p_task; } + void init(FileAccess* p_fa, SignOption p_sign, String &p_certificate_path, String &p_certificate_password); + void add_file(String p_file_name, const uint8_t* p_buffer, size_t p_len, int p_file_no, int p_total_files, bool p_compress = false); + void finish(); + + AppxPackager(); + ~AppxPackager(); +}; + +class EditorExportPlatformWinrt : public EditorExportPlatform { + + OBJ_TYPE(EditorExportPlatformWinrt, EditorExportPlatform); + + Ref<ImageTexture> logo; + + enum Platform { + ARM, + X86, + X64 + } arch; + + bool is_debug; + + String custom_release_package; + String custom_debug_package; + + String cmdline; + + String display_name; + String short_name; + String unique_name; + String description; + String publisher; + String publisher_display_name; + + String product_guid; + String publisher_guid; + + int version_major; + int version_minor; + int version_build; + int version_revision; + + bool orientation_landscape; + bool orientation_portrait; + bool orientation_landscape_flipped; + bool orientation_portrait_flipped; + + String background_color; + Ref<ImageTexture> store_logo; + Ref<ImageTexture> square44; + Ref<ImageTexture> square71; + Ref<ImageTexture> square150; + Ref<ImageTexture> square310; + Ref<ImageTexture> wide310; + Ref<ImageTexture> splash; + + bool name_on_square150; + bool name_on_square310; + bool name_on_wide; + + Set<String> capabilities; + Set<String> uap_capabilities; + Set<String> device_capabilities; + + bool sign_package; + String certificate_path; + String certificate_pass; + + _FORCE_INLINE_ bool array_has(const char** p_array, const char* p_value) const { + while (*p_array) { + if (String(*p_array) == String(p_value)) return true; + p_array++; + } + return false; + } + + bool _valid_resource_name(const String &p_name) const; + bool _valid_guid(const String &p_guid) const; + bool _valid_bgcolor(const String &p_color) const; + bool _valid_image(const Ref<ImageTexture> p_image, int p_width, int p_height) const; + + Vector<uint8_t> _fix_manifest(const Vector<uint8_t> &p_template, bool p_give_internet) const; + Vector<uint8_t> _get_image_data(const String &p_path); + + static Error save_appx_file(void *p_userdata, const String& p_path, const Vector<uint8_t>& p_data, int p_file, int p_total); + static bool _should_compress_asset(const String& p_path, const Vector<uint8_t>& p_data); + +protected: + + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + +public: + + virtual String get_name() const { return "Windows Universal"; } + virtual ImageCompression get_image_compression() const { return IMAGE_COMPRESSION_ETC1; } + virtual Ref<Texture> get_logo() const { return logo; } + + virtual bool can_export(String *r_error = NULL) const; + virtual String get_binary_extension() const { return "appx"; } + + virtual Error export_project(const String& p_path, bool p_debug, int p_flags = 0); + + EditorExportPlatformWinrt(); + ~EditorExportPlatformWinrt(); +}; + + +/////////////////////////////////////////////////////////////////////////// + +String AppxPackager::hash_block(uint8_t * p_block_data, size_t p_block_len) { + + char hash[32]; + char base64[45]; + + sha256_context ctx; + sha256_init(&ctx); + sha256_hash(&ctx, p_block_data, p_block_len); + sha256_done(&ctx, (uint8_t*)hash); + + base64_encode(base64, hash, 32); + base64[44] = '\0'; + + return String(base64); +} + +void AppxPackager::make_block_map() { + + FileAccess* tmp_file = FileAccess::open(tmp_blockmap_file_path, FileAccess::WRITE); + + tmp_file->store_string("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"); + tmp_file->store_string("<BlockMap xmlns=\"http://schemas.microsoft.com/appx/2010/blockmap\" HashMethod=\"http://www.w3.org/2001/04/xmlenc#sha256\">"); + + for (int i = 0; i < file_metadata.size(); i++) { + + FileMeta file = file_metadata[i]; + + tmp_file->store_string( + "<File Name=\"" + file.name.replace("/", "\\") + + "\" Size=\"" + itos(file.uncompressed_size) + + "\" LfhSize=\"" + itos(file.lfh_size) + "\">"); + + + for (int j = 0; j < file.hashes.size(); j++) { + + tmp_file->store_string("<Block Hash=\"" + + file.hashes[j].base64_hash + "\" "); + if (file.compressed) + tmp_file->store_string("Size=\"" + itos(file.hashes[j].compressed_size) + "\" "); + tmp_file->store_string("/>"); + } + + tmp_file->store_string("</File>"); + } + + tmp_file->store_string("</BlockMap>"); + + tmp_file->close(); + memdelete(tmp_file); + tmp_file = NULL; +} + +String AppxPackager::content_type(String p_extension) { + + if (p_extension == "png") + return "image/png"; + else if (p_extension == "jpg") + return "image/jpg"; + else if (p_extension == "xml") + return "application/xml"; + else if (p_extension == "exe" || p_extension == "dll") + return "application/x-msdownload"; + else + return "application/octet-stream"; +} + +void AppxPackager::make_content_types() { + + FileAccess* tmp_file = FileAccess::open(tmp_content_types_file_path, FileAccess::WRITE); + + tmp_file->store_string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); + tmp_file->store_string("<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">"); + + Map<String, String> types; + + for (int i = 0; i < file_metadata.size(); i++) { + + String ext = file_metadata[i].name.extension(); + + if (types.has(ext)) continue; + + types[ext] = content_type(ext); + + tmp_file->store_string("<Default Extension=\"" + ext + + "\" ContentType=\"" + + types[ext] + "\" />"); + } + + // Appx signature file + tmp_file->store_string("<Default Extension=\"p7x\" ContentType=\"application/octet-stream\" />"); + + // Override for package files + tmp_file->store_string("<Override PartName=\"/AppxManifest.xml\" ContentType=\"application/vnd.ms-appx.manifest+xml\" />"); + tmp_file->store_string("<Override PartName=\"/AppxBlockMap.xml\" ContentType=\"application/vnd.ms-appx.blockmap+xml\" />"); + tmp_file->store_string("<Override PartName=\"/AppxSignature.p7x\" ContentType=\"application/vnd.ms-appx.signature\" />"); + tmp_file->store_string("<Override PartName=\"/AppxMetadata/CodeIntegrity.cat\" ContentType=\"application/vnd.ms-pkiseccat\" />"); + + tmp_file->store_string("</Types>"); + + tmp_file->close(); + memdelete(tmp_file); + tmp_file = NULL; +} + +Vector<uint8_t> AppxPackager::make_file_header(FileMeta p_file_meta) { + + Vector<uint8_t> buf; + buf.resize(BASE_FILE_HEADER_SIZE + p_file_meta.name.length()); + + int offs = 0; + // Write magic + offs += buf_put_int32(FILE_HEADER_MAGIC, &buf[offs]); + + // Version + offs += buf_put_int16(ZIP_VERSION, &buf[offs]); + + // Special flag + offs += buf_put_int16(GENERAL_PURPOSE, &buf[offs]); + + // Compression + offs += buf_put_int16(p_file_meta.compressed ? Z_DEFLATED : 0, &buf[offs]); + + // File date and time + offs += buf_put_int32(0, &buf[offs]); + + // CRC-32 + offs += buf_put_int32(p_file_meta.file_crc32, &buf[offs]); + + // Compressed size + offs += buf_put_int32(p_file_meta.compressed_size, &buf[offs]); + + // Uncompressed size + offs += buf_put_int32(p_file_meta.uncompressed_size, &buf[offs]); + + // File name length + offs += buf_put_int16(p_file_meta.name.length(), &buf[offs]); + + // Extra data length + offs += buf_put_int16(0, &buf[offs]); + + // File name + offs += buf_put_string(p_file_meta.name, &buf[offs]); + + // Done! + return buf; +} + +void AppxPackager::store_central_dir_header(const FileMeta p_file, bool p_do_hash) { + + Vector<uint8_t> &buf = central_dir_data; + int offs = buf.size(); + buf.resize(buf.size() + BASE_CENTRAL_DIR_SIZE + p_file.name.length()); + + + // Write magic + offs += buf_put_int32(CENTRAL_DIR_MAGIC, &buf[offs]); + + // ZIP versions + offs += buf_put_int16(ZIP_ARCHIVE_VERSION, &buf[offs]); + offs += buf_put_int16(ZIP_VERSION, &buf[offs]); + + // General purpose flag + offs += buf_put_int16(GENERAL_PURPOSE, &buf[offs]); + + // Compression + offs += buf_put_int16(p_file.compressed ? Z_DEFLATED : 0, &buf[offs]); + + // Modification date/time + offs += buf_put_int32(0, &buf[offs]); + + // Crc-32 + offs += buf_put_int32(p_file.file_crc32, &buf[offs]); + + // File sizes + offs += buf_put_int32(p_file.compressed_size, &buf[offs]); + offs += buf_put_int32(p_file.uncompressed_size, &buf[offs]); + + // File name length + offs += buf_put_int16(p_file.name.length(), &buf[offs]); + + // Extra field length + offs += buf_put_int16(0, &buf[offs]); + + // Comment length + offs += buf_put_int16(0, &buf[offs]); + + // Disk number start, internal/external file attributes + for (int i = 0; i < 8; i++) { + buf[offs++] = 0; + } + + // Relative offset + offs += buf_put_int32(p_file.zip_offset, &buf[offs]); + + // File name + offs += buf_put_string(p_file.name, &buf[offs]); + +#ifdef OPENSSL_ENABLED + // Calculate the hash for signing + if (p_do_hash) + SHA256_Update(&axcd_context, buf.ptr(), buf.size()); +#endif // OPENSSL_ENABLED + + // Done! +} + +Vector<uint8_t> AppxPackager::make_end_of_central_record() { + + Vector<uint8_t> buf; + buf.resize(ZIP64_END_OF_CENTRAL_DIR_SIZE + 12 + END_OF_CENTRAL_DIR_SIZE); // Size plus magic + + int offs = 0; + + // Write magic + offs += buf_put_int32(ZIP64_END_OF_CENTRAL_DIR_MAGIC, &buf[offs]); + + // Size of this record + offs += buf_put_int64(ZIP64_END_OF_CENTRAL_DIR_SIZE, &buf[offs]); + + // Version (yes, twice) + offs += buf_put_int16(ZIP_ARCHIVE_VERSION, &buf[offs]); + offs += buf_put_int16(ZIP_ARCHIVE_VERSION, &buf[offs]); + + // Disk number + for (int i = 0; i < 8; i++) { + buf[offs++] = 0; + } + + // Number of entries (total and per disk) + offs += buf_put_int64(file_metadata.size(), &buf[offs]); + offs += buf_put_int64(file_metadata.size(), &buf[offs]); + + // Size of central dir + offs += buf_put_int64(central_dir_data.size(), &buf[offs]); + + // Central dir offset + offs += buf_put_int64(central_dir_offset, &buf[offs]); + + ////// ZIP64 locator + + // Write magic for zip64 central dir locator + offs += buf_put_int32(ZIP64_END_DIR_LOCATOR_MAGIC, &buf[offs]); + + // Disk number + for (int i = 0; i < 4; i++) { + buf[offs++] = 0; + } + + // Relative offset + offs += buf_put_int64(end_of_central_dir_offset, &buf[offs]); + + // Number of disks + offs += buf_put_int32(1, &buf[offs]); + + /////// End of zip directory + + // Write magic for end central dir + offs += buf_put_int32(END_OF_CENTRAL_DIR_MAGIC, &buf[offs]); + + // Dummy stuff for Zip64 + for (int i = 0; i < 4; i++) { + buf[offs++] = 0x0; + } + for (int i = 0; i < 12; i++) { + buf[offs++] = 0xFF; + } + + // Size of comments + for (int i = 0; i < 2; i++) { + buf[offs++] = 0; + } + + // Done! + return buf; +} + +void AppxPackager::init(FileAccess * p_fa, SignOption p_sign, String &p_certificate_path, String &p_certificate_password) { + + package = p_fa; + central_dir_offset = 0; + end_of_central_dir_offset = 0; + tmp_blockmap_file_path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmpblockmap.xml"; + tmp_content_types_file_path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmpcontenttypes.xml"; +#ifdef OPENSSL_ENABLED + certificate_path = p_certificate_path; + certificate_pass = p_certificate_password; + sign_package = p_sign == SIGN; + SHA256_Init(&axpc_context); + SHA256_Init(&axcd_context); +#endif // OPENSSL_ENABLED +} + +void AppxPackager::add_file(String p_file_name, const uint8_t * p_buffer, size_t p_len, int p_file_no, int p_total_files, bool p_compress) { + + if (p_file_no >= 1 && p_total_files >= 1) { + EditorNode::progress_task_step(progress_task, "File: " + p_file_name, (p_file_no * 100) / p_total_files); + } + + bool do_hash = p_file_name != "AppxSignature.p7x"; + + FileMeta meta; + meta.name = p_file_name; + meta.uncompressed_size = p_len; + meta.compressed_size = p_len; + meta.compressed = p_compress; + meta.zip_offset = package->get_pos(); + + Vector<uint8_t> file_buffer; + + // Data for compression + z_stream strm; + FileAccess* strm_f = NULL; + Vector<uint8_t> strm_in; + strm_in.resize(BLOCK_SIZE); + Vector<uint8_t> strm_out; + + if (p_compress) { + + strm.zalloc = zipio_alloc; + strm.zfree = zipio_free; + strm.opaque = &strm_f; + + strm_out.resize(BLOCK_SIZE + 8); + + deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); + } + + int step = 0; + + while (p_len - step > 0) { + + size_t block_size = (p_len - step) > BLOCK_SIZE ? BLOCK_SIZE : (p_len - step); + + for (int i = 0; i < block_size; i++) { + strm_in[i] = p_buffer[step + i]; + } + + BlockHash bh; + bh.base64_hash = hash_block(strm_in.ptr(), block_size); + + if (p_compress) { + + strm.avail_in = block_size; + strm.avail_out = strm_out.size(); + strm.next_in = strm_in.ptr(); + strm.next_out = strm_out.ptr(); + + int total_out_before = strm.total_out; + + deflate(&strm, Z_FULL_FLUSH); + bh.compressed_size = strm.total_out - total_out_before; + + //package->store_buffer(strm_out.ptr(), strm.total_out - total_out_before); + int start = file_buffer.size(); + file_buffer.resize(file_buffer.size() + bh.compressed_size); + for (int i = 0; i < bh.compressed_size; i++) + file_buffer[start + i] = strm_out[i]; +#ifdef OPENSSL_ENABLED + if (do_hash) + SHA256_Update(&axpc_context, strm_out.ptr(), strm.total_out - total_out_before); +#endif // OPENSSL_ENABLED + + } else { + bh.compressed_size = block_size; + //package->store_buffer(strm_in.ptr(), block_size); + int start = file_buffer.size(); + file_buffer.resize(file_buffer.size() + block_size); + for (int i = 0; i < bh.compressed_size; i++) + file_buffer[start + i] = strm_in[i]; +#ifdef OPENSSL_ENABLED + if (do_hash) + SHA256_Update(&axpc_context, strm_in.ptr(), block_size); +#endif // OPENSSL_ENABLED + } + + meta.hashes.push_back(bh); + + step += block_size; + } + + if (p_compress) { + + strm.avail_in = 0; + strm.avail_out = strm_out.size(); + strm.next_in = strm_in.ptr(); + strm.next_out = strm_out.ptr(); + + int total_out_before = strm.total_out; + + deflate(&strm, Z_FINISH); + + //package->store_buffer(strm_out.ptr(), strm.total_out - total_out_before); + int start = file_buffer.size(); + file_buffer.resize(file_buffer.size() + (strm.total_out - total_out_before)); + for (int i = 0; i < (strm.total_out - total_out_before); i++) + file_buffer[start + i] = strm_out[i]; +#ifdef OPENSSL_ENABLED + if (do_hash) + SHA256_Update(&axpc_context, strm_out.ptr(), strm.total_out - total_out_before); +#endif // OPENSSL_ENABLED + + deflateEnd(&strm); + meta.compressed_size = strm.total_out; + + } else { + + meta.compressed_size = p_len; + } + + // Calculate file CRC-32 + uLong crc = crc32(0L, Z_NULL, 0); + crc = crc32(crc, p_buffer, p_len); + meta.file_crc32 = crc; + + // Create file header + Vector<uint8_t> file_header = make_file_header(meta); + meta.lfh_size = file_header.size(); + +#ifdef OPENSSL_ENABLED + // Hash the data for signing + if (do_hash) { + SHA256_Update(&axpc_context, file_header.ptr(), file_header.size()); + SHA256_Update(&axpc_context, file_buffer.ptr(), file_buffer.size()); + } +#endif // OPENSSL_ENABLED + + // Store the header and file; + package->store_buffer(file_header.ptr(), file_header.size()); + package->store_buffer(file_buffer.ptr(), file_buffer.size()); + + file_metadata.push_back(meta); +} + +void AppxPackager::finish() { + + // Create and add block map file + EditorNode::progress_task_step("export", "Creating block map...", 4); + + make_block_map(); + FileAccess* blockmap_file = FileAccess::open(tmp_blockmap_file_path, FileAccess::READ); + Vector<uint8_t> blockmap_buffer; + blockmap_buffer.resize(blockmap_file->get_len()); + + blockmap_file->get_buffer(blockmap_buffer.ptr(), blockmap_buffer.size()); + +#ifdef OPENSSL_ENABLED + // Hash the file for signing + if (sign_package) { + SHA256_CTX axbm_context; + SHA256_Init(&axbm_context); + SHA256_Update(&axbm_context, blockmap_buffer.ptr(), blockmap_buffer.size()); + SHA256_Final(digests.axbm, &axbm_context); + } +#endif // OPENSSL_ENABLED + + add_file("AppxBlockMap.xml", blockmap_buffer.ptr(), blockmap_buffer.size(), -1, -1, true); + + blockmap_file->close(); + memdelete(blockmap_file); + blockmap_file = NULL; + + // Add content types + EditorNode::progress_task_step("export", "Setting content types...", 5); + make_content_types(); + + FileAccess* types_file = FileAccess::open(tmp_content_types_file_path, FileAccess::READ); + Vector<uint8_t> types_buffer; + types_buffer.resize(types_file->get_len()); + + types_file->get_buffer(types_buffer.ptr(), types_buffer.size()); + +#ifdef OPENSSL_ENABLED + if (sign_package) { + // Hash the file for signing + SHA256_CTX axct_context; + SHA256_Init(&axct_context); + SHA256_Update(&axct_context, types_buffer.ptr(), types_buffer.size()); + SHA256_Final(digests.axct, &axct_context); + } +#endif // OPENSSL_ENABLED + + add_file("[Content_Types].xml", types_buffer.ptr(), types_buffer.size(), -1, -1, true); + + types_file->close(); + memdelete(types_file); + types_file = NULL; + + // Pre-process central directory before signing + for (int i = 0; i < file_metadata.size(); i++) { + store_central_dir_header(file_metadata[i]); + } + +#ifdef OPENSSL_ENABLED + // Create the signature file + if (sign_package) { + + Error err = read_cert_file(certificate_path, certificate_pass, &cert_file); + + if (err != OK) { + EditorNode::add_io_error(TTR("Couldn't read the certficate file. Are the path and password both correct?")); + package->close(); + memdelete(package); + package = NULL; + return; + } + + + // Make a temp end of the zip for hashing + central_dir_offset = package->get_pos(); + end_of_central_dir_offset = central_dir_offset + central_dir_data.size(); + Vector<uint8_t> zip_end_dir = make_end_of_central_record(); + + // Hash the end directory + SHA256_Update(&axcd_context, zip_end_dir.ptr(), zip_end_dir.size()); + + // Finish the hashes + make_digests(); + + PKCS7* signature = PKCS7_new(); + if (!signature) { + EditorNode::add_io_error(TTR("Error creating the signature object.")); + package->close(); + memdelete(package); + package = NULL; + return; + } + + err = sign(cert_file, digests, signature); + + if (err != OK) { + EditorNode::add_io_error(TTR("Error creating the package signature.")); + package->close(); + memdelete(package); + package = NULL; + return; + } + + // Read the signature as bytes + BIO* bio_out = BIO_new(BIO_s_mem()); + i2d_PKCS7_bio(bio_out, signature); + + BIO_flush(bio_out); + + uint8_t* bio_ptr; + size_t bio_size = BIO_get_mem_data(bio_out, &bio_ptr); + + // Create the signature buffer with magic number + Vector<uint8_t> signature_file; + signature_file.resize(4 + bio_size); + buf_put_int32(P7X_SIGNATURE, signature_file.ptr()); + for (int i = 0; i < bio_size; i++) + signature_file[i + 4] = bio_ptr[i]; + + // Add the signature to the package + add_file("AppxSignature.p7x", signature_file.ptr(), signature_file.size(), -1, -1, true); + + // Add central directory entry + store_central_dir_header(file_metadata[file_metadata.size() - 1], false); + } +#endif // OPENSSL_ENABLED + + + // Write central directory + EditorNode::progress_task_step("export", "Finishing package...", 6); + central_dir_offset = package->get_pos(); + package->store_buffer(central_dir_data.ptr(), central_dir_data.size()); + + // End record + end_of_central_dir_offset = package->get_pos(); + Vector<uint8_t> end_record = make_end_of_central_record(); + package->store_buffer(end_record.ptr(), end_record.size()); + + package->close(); + memdelete(package); + package = NULL; +} + +#ifdef OPENSSL_ENABLED +// https://support.microsoft.com/en-us/kb/287547 +const char SPC_INDIRECT_DATA_OBJID[] = "1.3.6.1.4.1.311.2.1.4"; +const char SPC_STATEMENT_TYPE_OBJID[] = "1.3.6.1.4.1.311.2.1.11"; +const char SPC_SP_OPUS_INFO_OBJID[] = "1.3.6.1.4.1.311.2.1.12"; +const char SPC_SIPINFO_OBJID[] = "1.3.6.1.4.1.311.2.1.30"; +#endif // OPENSSL_ENABLED + +AppxPackager::AppxPackager() {} + +AppxPackager::~AppxPackager() {} + + +//////////////////////////////////////////////////////////////////// + +#ifdef OPENSSL_ENABLED +Error AppxPackager::openssl_error(unsigned long p_err) { + + ERR_load_crypto_strings(); + + char buffer[256]; + ERR_error_string_n(p_err, buffer, sizeof(buffer)); + + String err(buffer); + + ERR_EXPLAIN(err); + ERR_FAIL_V(FAILED); +} + +void AppxPackager::MakeSPCInfoValue(asn1::SPCInfoValue &info) { + + // I have no idea what these numbers mean. + static uint8_t s1Magic[] = { + 0x4B, 0xDF, 0xC5, 0x0A, 0x07, 0xCE, 0xE2, 0x4D, + 0xB7, 0x6E, 0x23, 0xC8, 0x39, 0xA0, 0x9F, 0xD1, + }; + ASN1_INTEGER_set(info.i1, 0x01010000); + ASN1_OCTET_STRING_set(info.s1, s1Magic, sizeof(s1Magic)); + ASN1_INTEGER_set(info.i2, 0x00000000); + ASN1_INTEGER_set(info.i3, 0x00000000); + ASN1_INTEGER_set(info.i4, 0x00000000); + ASN1_INTEGER_set(info.i5, 0x00000000); + ASN1_INTEGER_set(info.i6, 0x00000000); +} + +Error AppxPackager::MakeIndirectDataContent(asn1::SPCIndirectDataContent &idc) { + + using namespace asn1; + + ASN1_TYPE* algorithmParameter = ASN1_TYPE_new(); + if (!algorithmParameter) { + return openssl_error(ERR_peek_last_error()); + } + algorithmParameter->type = V_ASN1_NULL; + + SPCInfoValue* infoValue = SPCInfoValue_new(); + if (!infoValue) { + return openssl_error(ERR_peek_last_error()); + } + MakeSPCInfoValue(*infoValue); + + ASN1_TYPE* value = + EncodedASN1::FromItem<asn1::SPCInfoValue, + asn1::i2d_SPCInfoValue>(infoValue) + .ToSequenceType(); + + { + Vector<uint8_t> digest; + write_digest(digest); + if (!ASN1_OCTET_STRING_set(idc.messageDigest->digest, + digest.ptr(), digest.size())) { + + return openssl_error(ERR_peek_last_error()); + } + } + + idc.data->type = OBJ_txt2obj(SPC_SIPINFO_OBJID, 1); + idc.data->value = value; + idc.messageDigest->digestAlgorithm->algorithm = OBJ_nid2obj(NID_sha256); + idc.messageDigest->digestAlgorithm->parameter = algorithmParameter; + + return OK; +} + +Error AppxPackager::add_attributes(PKCS7_SIGNER_INFO * p_signer_info) { + + // Add opus attribute + asn1::SPCSpOpusInfo* opus = asn1::SPCSpOpusInfo_new(); + if (!opus) return openssl_error(ERR_peek_last_error()); + + ASN1_STRING* opus_value = EncodedASN1::FromItem<asn1::SPCSpOpusInfo, asn1::i2d_SPCSpOpusInfo>(opus) + .ToSequenceString(); + + if (!PKCS7_add_signed_attribute( + p_signer_info, + OBJ_txt2nid(SPC_SP_OPUS_INFO_OBJID), + V_ASN1_SEQUENCE, + opus_value + )) { + + asn1::SPCSpOpusInfo_free(opus); + + ASN1_STRING_free(opus_value); + return openssl_error(ERR_peek_last_error()); + } + + // Add content type attribute + if (!PKCS7_add_signed_attribute( + p_signer_info, + NID_pkcs9_contentType, + V_ASN1_OBJECT, + OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, 1) + )) { + + asn1::SPCSpOpusInfo_free(opus); + ASN1_STRING_free(opus_value); + return openssl_error(ERR_peek_last_error()); + } + + // Add statement type attribute + asn1::SPCStatementType* statement_type = asn1::SPCStatementType_new(); + if (!statement_type) return openssl_error(ERR_peek_last_error()); + + statement_type->type = OBJ_nid2obj(NID_ms_code_ind); + ASN1_STRING* statement_type_value = + EncodedASN1::FromItem<asn1::SPCStatementType, asn1::i2d_SPCStatementType>(statement_type) + .ToSequenceString(); + + if (!PKCS7_add_signed_attribute( + p_signer_info, + OBJ_txt2nid(SPC_STATEMENT_TYPE_OBJID), + V_ASN1_SEQUENCE, + statement_type_value + )) { + + ASN1_STRING_free(opus_value); + asn1::SPCStatementType_free(statement_type); + ASN1_STRING_free(statement_type_value); + + return openssl_error(ERR_peek_last_error()); + } + + return OK; + +} + +void AppxPackager::make_digests() { + + // AXPC + SHA256_Final(digests.axpc, &axpc_context); + + // AXCD + SHA256_Final(digests.axcd, &axcd_context); + + // AXCI + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) + digests.axci[i] = 0; + +} + +void AppxPackager::write_digest(Vector<uint8_t>& p_out_buffer) { + + // Size of digests plus 6 32-bit magic numbers + p_out_buffer.resize((SHA256_DIGEST_LENGTH * 5) + (6 * 4)); + + int offs = 0; + + // APPX + uint32_t sig = 0x58505041; + offs += buf_put_int32(sig, &p_out_buffer[offs]); + + // AXPC + uint32_t axpc_sig = 0x43505841; + offs += buf_put_int32(axpc_sig, &p_out_buffer[offs]); + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + p_out_buffer[offs++] = digests.axpc[i]; + } + + // AXCD + uint32_t axcd_sig = 0x44435841; + offs += buf_put_int32(axcd_sig, &p_out_buffer[offs]); + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + p_out_buffer[offs++] = digests.axcd[i]; + } + + // AXCT + uint32_t axct_sig = 0x54435841; + offs += buf_put_int32(axct_sig, &p_out_buffer[offs]); + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + p_out_buffer[offs++] = digests.axct[i]; + } + + // AXBM + uint32_t axbm_sig = 0x4D425841; + offs += buf_put_int32(axbm_sig, &p_out_buffer[offs]); + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + p_out_buffer[offs++] = digests.axbm[i]; + } + + // AXCI + uint32_t axci_sig = 0x49435841; + offs += buf_put_int32(axci_sig, &p_out_buffer[offs]); + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + p_out_buffer[offs++] = digests.axci[i]; + } + + // Done! +} + +Error AppxPackager::read_cert_file(const String & p_path, const String &p_password, CertFile* p_out_cf) { + + ERR_FAIL_COND_V(!p_out_cf, ERR_INVALID_PARAMETER); + + BIO* bio = BIO_new_file(p_path.utf8().get_data(), "rb"); + if (!bio) { + return openssl_error(ERR_peek_last_error()); + } + + PKCS12* data = d2i_PKCS12_bio(bio, NULL); + if (!data) { + BIO_free(bio); + return openssl_error(ERR_peek_last_error()); + } + + /* Fails to link with GCC, need to solve when implement signing + if (!PKCS12_parse(data, p_password.utf8().get_data(), &p_out_cf->private_key, &p_out_cf->certificate, NULL)) { + PKCS12_free(data); + BIO_free(bio); + return openssl_error(ERR_peek_last_error()); + }*/ + + if (!p_out_cf->private_key) { + PKCS12_free(data); + BIO_free(bio); + return openssl_error(ERR_peek_last_error()); + } + + if (!p_out_cf->certificate) { + PKCS12_free(data); + BIO_free(bio); + return openssl_error(ERR_peek_last_error()); + } + + PKCS12_free(data); + BIO_free(bio); + + return OK; +} + +Error AppxPackager::sign(const CertFile & p_cert, const AppxDigests & digests, PKCS7 * p_out_signature) { + + OpenSSL_add_all_algorithms(); + + // Register object IDs + OBJ_create_and_add_object(SPC_INDIRECT_DATA_OBJID, NULL, NULL); + OBJ_create_and_add_object(SPC_SIPINFO_OBJID, NULL, NULL); + OBJ_create_and_add_object(SPC_SP_OPUS_INFO_OBJID, NULL, NULL); + OBJ_create_and_add_object(SPC_STATEMENT_TYPE_OBJID, NULL, NULL); + + if (!PKCS7_set_type(p_out_signature, NID_pkcs7_signed)) { + + return openssl_error(ERR_peek_last_error()); + } + + PKCS7_SIGNER_INFO *signer_info = PKCS7_add_signature(p_out_signature, p_cert.certificate, p_cert.private_key, EVP_sha256()); + if (!signer_info) return openssl_error(ERR_peek_last_error()); + + add_attributes(signer_info); + + if (!PKCS7_content_new(p_out_signature, NID_pkcs7_data)) { + + return openssl_error(ERR_peek_last_error()); + } + + if (!PKCS7_add_certificate(p_out_signature, p_cert.certificate)) { + + return openssl_error(ERR_peek_last_error()); + } + + asn1::SPCIndirectDataContent* idc = asn1::SPCIndirectDataContent_new(); + + MakeIndirectDataContent(*idc); + EncodedASN1 idc_encoded = + EncodedASN1::FromItem<asn1::SPCIndirectDataContent, asn1::i2d_SPCIndirectDataContent>(idc); + + BIO* signed_data = PKCS7_dataInit(p_out_signature, NULL); + + if (idc_encoded.size() < 2) { + + ERR_EXPLAIN("Invalid encoded size"); + ERR_FAIL_V(FAILED); + } + + if ((idc_encoded.data()[1] & 0x80) == 0x00) { + + ERR_EXPLAIN("Invalid encoded data"); + ERR_FAIL_V(FAILED); + } + + size_t skip = 4; + + if (BIO_write(signed_data, idc_encoded.data() + skip, idc_encoded.size() - skip) + != idc_encoded.size() - skip) { + + return openssl_error(ERR_peek_last_error()); + } + if (BIO_flush(signed_data) != 1) { + + return openssl_error(ERR_peek_last_error()); + } + + if (!PKCS7_dataFinal(p_out_signature, signed_data)) { + + return openssl_error(ERR_peek_last_error()); + } + + PKCS7* content = PKCS7_new(); + if (!content) { + + return openssl_error(ERR_peek_last_error()); + } + + content->type = OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, 1); + + ASN1_TYPE* idc_sequence = idc_encoded.ToSequenceType(); + content->d.other = idc_sequence; + + if (!PKCS7_set_content(p_out_signature, content)) { + + return openssl_error(ERR_peek_last_error()); + } + + return OK; +} + +#endif // OPENSSL_ENABLED + +//////////////////////////////////////////////////////////////////// + + +bool EditorExportPlatformWinrt::_valid_resource_name(const String &p_name) const { + + if (p_name.empty()) return false; + if (p_name.ends_with(".")) return false; + + static const char* invalid_names[] = { + "CON","PRN","AUX","NUL","COM1","COM2","COM3","COM4","COM5","COM6","COM7", + "COM8","COM9","LPT1","LPT2","LPT3","LPT4","LPT5","LPT6","LPT7","LPT8","LPT9", + NULL + }; + + const char** t = invalid_names; + while (*t) { + if (p_name == *t) return false; + t++; + } + + return true; +} + +bool EditorExportPlatformWinrt::_valid_guid(const String & p_guid) const { + + Vector<String> parts = p_guid.split("-"); + + if (parts.size() != 5) return false; + if (parts[0].length() != 8) return false; + for (int i = 1; i < 4; i++) + if (parts[i].length() != 4) return false; + if (parts[4].length() != 12) return false; + + return true; +} + +bool EditorExportPlatformWinrt::_valid_bgcolor(const String & p_color) const { + + if (p_color.empty()) return true; + if (p_color.begins_with("#") && p_color.is_valid_html_color()) return true; + + // Colors from https://msdn.microsoft.com/en-us/library/windows/apps/dn934817.aspx + static const char* valid_colors[] = { + "aliceBlue","antiqueWhite","aqua","aquamarine","azure","beige", + "bisque","black","blanchedAlmond","blue","blueViolet","brown", + "burlyWood","cadetBlue","chartreuse","chocolate","coral","cornflowerBlue", + "cornsilk","crimson","cyan","darkBlue","darkCyan","darkGoldenrod", + "darkGray","darkGreen","darkKhaki","darkMagenta","darkOliveGreen","darkOrange", + "darkOrchid","darkRed","darkSalmon","darkSeaGreen","darkSlateBlue","darkSlateGray", + "darkTurquoise","darkViolet","deepPink","deepSkyBlue","dimGray","dodgerBlue", + "firebrick","floralWhite","forestGreen","fuchsia","gainsboro","ghostWhite", + "gold","goldenrod","gray","green","greenYellow","honeydew", + "hotPink","indianRed","indigo","ivory","khaki","lavender", + "lavenderBlush","lawnGreen","lemonChiffon","lightBlue","lightCoral","lightCyan", + "lightGoldenrodYellow","lightGreen","lightGray","lightPink","lightSalmon","lightSeaGreen", + "lightSkyBlue","lightSlateGray","lightSteelBlue","lightYellow","lime","limeGreen", + "linen","magenta","maroon","mediumAquamarine","mediumBlue","mediumOrchid", + "mediumPurple","mediumSeaGreen","mediumSlateBlue","mediumSpringGreen","mediumTurquoise","mediumVioletRed", + "midnightBlue","mintCream","mistyRose","moccasin","navajoWhite","navy", + "oldLace","olive","oliveDrab","orange","orangeRed","orchid", + "paleGoldenrod","paleGreen","paleTurquoise","paleVioletRed","papayaWhip","peachPuff", + "peru","pink","plum","powderBlue","purple","red", + "rosyBrown","royalBlue","saddleBrown","salmon","sandyBrown","seaGreen", + "seaShell","sienna","silver","skyBlue","slateBlue","slateGray", + "snow","springGreen","steelBlue","tan","teal","thistle", + "tomato","transparent","turquoise","violet","wheat","white", + "whiteSmoke","yellow","yellowGreen", + NULL + }; + + const char** color = valid_colors; + + while(*color) { + if (p_color == *color) return true; + color++; + } + + return false; +} + +bool EditorExportPlatformWinrt::_valid_image(const Ref<ImageTexture> p_image, int p_width, int p_height) const { + + if (!p_image.is_valid()) return false; + + // TODO: Add resource creation or image rescaling to enable other scales: + // 1.25, 1.5, 2.0 + real_t scales[] = { 1.0 }; + bool valid_w = false; + bool valid_h = false; + + for (int i = 0; i < 1; i++) { + + int w = ceil(p_width * scales[i]); + int h = ceil(p_height * scales[i]); + + if (w == p_image->get_width()) + valid_w = true; + if (h == p_image->get_height()) + valid_h = true; + } + + return valid_w && valid_h; +} + +Vector<uint8_t> EditorExportPlatformWinrt::_fix_manifest(const Vector<uint8_t> &p_template, bool p_give_internet) const { + + String result = String::utf8((const char*)p_template.ptr(), p_template.size()); + + result = result.replace("$godot_version$", VERSION_FULL_NAME); + + result = result.replace("$identity_name$", unique_name); + result = result.replace("$publisher$", publisher); + + result = result.replace("$product_guid$", product_guid); + result = result.replace("$publisher_guid$", publisher_guid); + + String version = itos(version_major) + "." + itos(version_minor) + "." + itos(version_build) + "." + itos(version_revision); + result = result.replace("$version_string$", version); + + String architecture = arch == ARM ? "ARM" : arch == X86 ? "x86" : "x64"; + result = result.replace("$architecture$", architecture); + + result = result.replace("$display_name$", display_name.empty() ? (String)Globals::get_singleton()->get("application/name") : display_name); + result = result.replace("$publisher_display_name$", publisher_display_name); + result = result.replace("$app_description$", description); + result = result.replace("$bg_color$", background_color); + result = result.replace("$short_name$", short_name); + + String name_on_tiles = ""; + if (name_on_square150) { + name_on_tiles += " <uap:ShowOn Tile=\"square150x150Logo\" />\n"; + } + if (name_on_wide) { + name_on_tiles += " <uap:ShowOn Tile=\"wide310x150Logo\" />\n"; + } + if (name_on_square310) { + name_on_tiles += " <uap:ShowOn Tile=\"square310x310Logo\" />\n"; + } + + String show_name_on_tiles = ""; + if (!name_on_tiles.empty()) { + show_name_on_tiles = "<uap:ShowNameOnTiles>\n" + name_on_tiles + " </uap:ShowNameOnTiles>"; + } + + result = result.replace("$name_on_tiles$", name_on_tiles); + + String rotations = ""; + if (orientation_landscape) { + rotations += " <uap:Rotation Preference=\"landscape\" />\n"; + } + if (orientation_portrait) { + rotations += " <uap:Rotation Preference=\"portrait\" />\n"; + } + if (orientation_landscape_flipped) { + rotations += " <uap:Rotation Preference=\"landscapeFlipped\" />\n"; + } + if (orientation_portrait_flipped) { + rotations += " <uap:Rotation Preference=\"portraitFlipped\" />\n"; + } + + String rotation_preference = ""; + if (!rotations.empty()) { + rotation_preference = "<uap:InitialRotationPreference>\n" + rotations + " </uap:InitialRotationPreference>"; + } + + result = result.replace("$rotation_preference$", rotation_preference); + + String capabilities_elements = ""; + const char **basic = uwp_capabilities; + while (*basic) { + if (capabilities.has(*basic)) { + capabilities_elements += " <Capability Name=\"" + String(*basic) + "\" />\n"; + } + basic++; + } + const char **uap = uwp_uap_capabilities; + while (*uap) { + if (uap_capabilities.has(*uap)) { + capabilities_elements += " <uap:Capability Name=\"" + String(*uap) + "\" />\n"; + } + uap++; + } + const char **device = uwp_device_capabilites; + while (*device) { + if (uap_capabilities.has(*device)) { + capabilities_elements += " <DeviceCapability Name=\"" + String(*device) + "\" />\n"; + } + device++; + } + + if (!capabilities.has("internetClient") && p_give_internet) { + capabilities_elements += " <Capability Name=\"internetClient\" />\n"; + } + + String capabilities_string = "<Capabilities />"; + if (!capabilities_elements.empty()) { + capabilities_string = "<Capabilities>\n" + capabilities_elements + " </Capabilities>"; + } + + result = result.replace("$capabilities_place$", capabilities_string); + + Vector<uint8_t> r_ret; + r_ret.resize(result.length()); + + for (int i = 0; i < result.length(); i++) + r_ret[i] = result.utf8().get(i); + + return r_ret; +} + +Vector<uint8_t> EditorExportPlatformWinrt::_get_image_data(const String & p_path) { + + Vector<uint8_t> data; + Ref<ImageTexture> ref; + + if (p_path.find("StoreLogo") != -1) { + ref = store_logo; + } else if (p_path.find("Square44x44Logo") != -1) { + ref = square44; + } else if (p_path.find("Square71x71Logo") != -1) { + ref = square71; + } else if (p_path.find("Square150x150Logo") != -1) { + ref = square150; + } else if (p_path.find("Square310x310Logo") != -1) { + ref = square310; + } else if (p_path.find("Wide310x150Logo") != -1) { + ref = wide310; + } else if (p_path.find("SplashScreen") != -1) { + ref = splash; + } + + if (!ref.is_valid()) return data; + + + String tmp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/uwp_tmp_logo.png"); + + Error err = ref->get_data().save_png(tmp_path); + + if (err != OK) { + + String err_string = "Couldn't save temp logo file."; + + EditorNode::add_io_error(err_string); + ERR_EXPLAIN(err_string); + ERR_FAIL_V(data); + } + + FileAccess* f = FileAccess::open(tmp_path, FileAccess::READ, &err); + + if (err != OK) { + + String err_string = "Couldn't open temp logo file."; + + EditorNode::add_io_error(err_string); + ERR_EXPLAIN(err_string); + ERR_FAIL_V(data); + } + + data.resize(f->get_len()); + f->get_buffer(data.ptr(), data.size()); + + f->close(); + memdelete(f); + + // Delete temp file + DirAccess* dir = DirAccess::open(tmp_path.get_base_dir(), &err); + + if (err != OK) { + + String err_string = "Couldn't open temp path to remove temp logo file."; + + EditorNode::add_io_error(err_string); + ERR_EXPLAIN(err_string); + ERR_FAIL_V(data); + } + + err = dir->remove(tmp_path); + + memdelete(dir); + + if (err != OK) { + + String err_string = "Couldn't remove temp logo file."; + + EditorNode::add_io_error(err_string); + ERR_EXPLAIN(err_string); + ERR_FAIL_V(data); + } + + return data; +} + +Error EditorExportPlatformWinrt::save_appx_file(void * p_userdata, const String & p_path, const Vector<uint8_t>& p_data, int p_file, int p_total) { + + AppxPackager *packager = (AppxPackager*)p_userdata; + String dst_path = p_path.replace_first("res://", "game/"); + + packager->add_file(dst_path, p_data.ptr(), p_data.size(), p_file, p_total, _should_compress_asset(p_path, p_data)); + + return OK; +} + +bool EditorExportPlatformWinrt::_should_compress_asset(const String & p_path, const Vector<uint8_t>& p_data) { + + /* TODO: This was copied verbatim from Android export. It should be + * refactored to the parent class and also be used for .zip export. + */ + + /* + * By not compressing files with little or not benefit in doing so, + * a performance gain is expected at runtime. Moreover, if the APK is + * zip-aligned, assets stored as they are can be efficiently read by + * Android by memory-mapping them. + */ + + // -- Unconditional uncompress to mimic AAPT plus some other + + static const char* unconditional_compress_ext[] = { + // From https://github.com/android/platform_frameworks_base/blob/master/tools/aapt/Package.cpp + // These formats are already compressed, or don't compress well: + ".jpg", ".jpeg", ".png", ".gif", + ".wav", ".mp2", ".mp3", ".ogg", ".aac", + ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet", + ".rtttl", ".imy", ".xmf", ".mp4", ".m4a", + ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2", + ".amr", ".awb", ".wma", ".wmv", + // Godot-specific: + ".webp", // Same reasoning as .png + ".cfb", // Don't let small config files slow-down startup + // Trailer for easier processing + NULL + }; + + for (const char** ext = unconditional_compress_ext; *ext; ++ext) { + if (p_path.to_lower().ends_with(String(*ext))) { + return false; + } + } + + // -- Compressed resource? + + if (p_data.size() >= 4 && p_data[0] == 'R' && p_data[1] == 'S' && p_data[2] == 'C' && p_data[3] == 'C') { + // Already compressed + return false; + } + + // --- TODO: Decide on texture resources according to their image compression setting + + return true; +} + +bool EditorExportPlatformWinrt::_set(const StringName& p_name, const Variant& p_value) { + + String n = p_name; + + if (n == "architecture/target") + arch = (Platform)((int)p_value); + else if (n == "custom_package/debug") + custom_debug_package = p_value; + else if (n == "custom_package/release") + custom_release_package = p_value; + else if (n == "command_line/extra_args") + cmdline = p_value; + else if (n == "package/display_name") + display_name = p_value; + else if (n == "package/short_name") + short_name = p_value; + else if (n == "package/unique_name") + unique_name = p_value; + else if (n == "package/description") + description = p_value; + else if (n == "package/publisher") + publisher = p_value; + else if (n == "package/publisher_display_name") + publisher_display_name = p_value; + else if (n == "identity/product_guid") + product_guid = p_value; + else if (n == "identity/publisher_guid") + publisher_guid = p_value; + else if (n == "version/major") + version_major = p_value; + else if (n == "version/minor") + version_minor = p_value; + else if (n == "version/build") + version_build = p_value; + else if (n == "version/revision") + version_revision = p_value; + else if (n == "orientation/landscape") + orientation_landscape = p_value; + else if (n == "orientation/portrait") + orientation_portrait = p_value; + else if (n == "orientation/landscape_flipped") + orientation_landscape_flipped = p_value; + else if (n == "orientation/portrait_flipped") + orientation_portrait_flipped = p_value; + else if (n == "images/background_color") + background_color = p_value; + else if (n == "images/store_logo") + store_logo = p_value; + else if (n == "images/square44x44_logo") + square44 = p_value; + else if (n == "images/square71x71_logo") + square71 = p_value; + else if (n == "images/square150x150_logo") + square150 = p_value; + else if (n == "images/square310x310_logo") + square310 = p_value; + else if (n == "images/wide310x150_logo") + wide310 = p_value; + else if (n == "images/splash_screen") + splash = p_value; + else if (n == "tiles/show_name_on_square150x150") + name_on_square150 = p_value; + else if (n == "tiles/show_name_on_wide310x150") + name_on_wide = p_value; + else if (n == "tiles/show_name_on_square310x310") + name_on_square310 = p_value; + +#if 0 // Signing disabled + else if (n == "signing/sign") + sign_package = p_value; + else if (n == "signing/certificate_file") + certificate_path = p_value; + else if (n == "signing/certificate_password") + certificate_pass = p_value; +#endif + else if (n.begins_with("capabilities/")) { + + String what = n.get_slice("/", 1).replace("_", ""); + bool enable = p_value; + + if (array_has(uwp_capabilities, what.utf8().get_data())) { + + if (enable) + capabilities.insert(what); + else + capabilities.erase(what); + + } else if (array_has(uwp_uap_capabilities, what.utf8().get_data())) { + + if (enable) + uap_capabilities.insert(what); + else + uap_capabilities.erase(what); + + } else if (array_has(uwp_device_capabilites, what.utf8().get_data())) { + + if (enable) + device_capabilities.insert(what); + else + device_capabilities.erase(what); + } + } else return false; + + return true; +} + +bool EditorExportPlatformWinrt::_get(const StringName& p_name, Variant &r_ret) const { + + String n = p_name; + + if (n == "architecture/target") + r_ret = (int)arch; + else if (n == "custom_package/debug") + r_ret = custom_debug_package; + else if (n == "custom_package/release") + r_ret = custom_release_package; + else if (n == "command_line/extra_args") + r_ret = cmdline; + else if (n == "package/display_name") + r_ret = display_name; + else if (n == "package/short_name") + r_ret = short_name; + else if (n == "package/unique_name") + r_ret = unique_name; + else if (n == "package/description") + r_ret = description; + else if (n == "package/publisher") + r_ret = publisher; + else if (n == "package/publisher_display_name") + r_ret = publisher_display_name; + else if (n == "identity/product_guid") + r_ret = product_guid; + else if (n == "identity/publisher_guid") + r_ret = publisher_guid; + else if (n == "version/major") + r_ret = version_major; + else if (n == "version/minor") + r_ret = version_minor; + else if (n == "version/build") + r_ret = version_build; + else if (n == "version/revision") + r_ret = version_revision; + else if (n == "orientation/landscape") + r_ret = orientation_landscape; + else if (n == "orientation/portrait") + r_ret = orientation_portrait; + else if (n == "orientation/landscape_flipped") + r_ret = orientation_landscape_flipped; + else if (n == "orientation/portrait_flipped") + r_ret = orientation_portrait_flipped; + else if (n == "images/background_color") + r_ret = background_color; + else if (n == "images/store_logo") + r_ret = store_logo; + else if (n == "images/square44x44_logo") + r_ret = square44; + else if (n == "images/square71x71_logo") + r_ret = square71; + else if (n == "images/square150x150_logo") + r_ret = square150; + else if (n == "images/square310x310_logo") + r_ret = square310; + else if (n == "images/wide310x150_logo") + r_ret = wide310; + else if (n == "images/splash_screen") + r_ret = splash; + else if (n == "tiles/show_name_on_square150x150") + r_ret = name_on_square150; + else if (n == "tiles/show_name_on_wide310x150") + r_ret = name_on_wide; + else if (n == "tiles/show_name_on_square310x310") + r_ret = name_on_square310; + +#if 0 // Signing disabled + else if (n == "signing/sign") + r_ret = sign_package; + else if (n == "signing/certificate_file") + r_ret = certificate_path; + else if (n == "signing/certificate_password") + r_ret = certificate_pass; +#endif + else if (n.begins_with("capabilities/")) { + + String what = n.get_slice("/", 1).replace("_", ""); + + if (array_has(uwp_capabilities, what.utf8().get_data())) { + + r_ret = capabilities.has(what); + + } else if (array_has(uwp_uap_capabilities, what.utf8().get_data())) { + + r_ret = uap_capabilities.has(what); + + } else if (array_has(uwp_device_capabilites, what.utf8().get_data())) { + + r_ret = device_capabilities.has(what); + } + } else return false; + + return true; +} + +void EditorExportPlatformWinrt::_get_property_list(List<PropertyInfo>* p_list) const { + + p_list->push_back(PropertyInfo(Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE, "appx")); + p_list->push_back(PropertyInfo(Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE, "appx")); + + p_list->push_back(PropertyInfo(Variant::INT, "architecture/target", PROPERTY_HINT_ENUM, "ARM,x86,x64")); + + p_list->push_back(PropertyInfo(Variant::STRING, "command_line/extra_args")); + + p_list->push_back(PropertyInfo(Variant::STRING, "package/display_name")); + p_list->push_back(PropertyInfo(Variant::STRING, "package/short_name")); + p_list->push_back(PropertyInfo(Variant::STRING, "package/unique_name")); + p_list->push_back(PropertyInfo(Variant::STRING, "package/description")); + p_list->push_back(PropertyInfo(Variant::STRING, "package/publisher")); + p_list->push_back(PropertyInfo(Variant::STRING, "package/publisher_display_name")); + + p_list->push_back(PropertyInfo(Variant::STRING, "identity/product_guid")); + p_list->push_back(PropertyInfo(Variant::STRING, "identity/publisher_guid")); + + p_list->push_back(PropertyInfo(Variant::INT, "version/major")); + p_list->push_back(PropertyInfo(Variant::INT, "version/minor")); + p_list->push_back(PropertyInfo(Variant::INT, "version/build")); + p_list->push_back(PropertyInfo(Variant::INT, "version/revision")); + + p_list->push_back(PropertyInfo(Variant::BOOL, "orientation/landscape")); + p_list->push_back(PropertyInfo(Variant::BOOL, "orientation/portrait")); + p_list->push_back(PropertyInfo(Variant::BOOL, "orientation/landscape_flipped")); + p_list->push_back(PropertyInfo(Variant::BOOL, "orientation/portrait_flipped")); + + p_list->push_back(PropertyInfo(Variant::STRING, "images/background_color")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "images/store_logo", PROPERTY_HINT_RESOURCE_TYPE, "ImageTexture")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "images/square44x44_logo", PROPERTY_HINT_RESOURCE_TYPE, "ImageTexture")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "images/square71x71_logo", PROPERTY_HINT_RESOURCE_TYPE, "ImageTexture")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "images/square150x150_logo", PROPERTY_HINT_RESOURCE_TYPE, "ImageTexture")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "images/square310x310_logo", PROPERTY_HINT_RESOURCE_TYPE, "ImageTexture")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "images/wide310x150_logo", PROPERTY_HINT_RESOURCE_TYPE, "ImageTexture")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "images/splash_screen", PROPERTY_HINT_RESOURCE_TYPE, "ImageTexture")); + + p_list->push_back(PropertyInfo(Variant::BOOL, "tiles/show_name_on_square150x150")); + p_list->push_back(PropertyInfo(Variant::BOOL, "tiles/show_name_on_wide310x150")); + p_list->push_back(PropertyInfo(Variant::BOOL, "tiles/show_name_on_square310x310")); + +#if 0 // Signing does not work :( disabling for now + p_list->push_back(PropertyInfo(Variant::BOOL, "signing/sign")); + p_list->push_back(PropertyInfo(Variant::STRING, "signing/certificate_file", PROPERTY_HINT_GLOBAL_FILE, "pfx")); + p_list->push_back(PropertyInfo(Variant::STRING, "signing/certificate_password")); +#endif + + // Capabilites + const char **basic = uwp_capabilities; + while (*basic) { + p_list->push_back(PropertyInfo(Variant::BOOL, "capabilities/" + String(*basic).camelcase_to_underscore(false))); + basic++; + } + + const char **uap = uwp_uap_capabilities; + while (*uap) { + p_list->push_back(PropertyInfo(Variant::BOOL, "capabilities/" + String(*uap).camelcase_to_underscore(false))); + uap++; + } + + const char **device = uwp_device_capabilites; + while (*device) { + p_list->push_back(PropertyInfo(Variant::BOOL, "capabilities/" + String(*device).camelcase_to_underscore(false))); + device++; + } + +} + +bool EditorExportPlatformWinrt::can_export(String * r_error) const { + + String err; + bool valid = true; + + if (!exists_export_template("winrt_x86_debug.zip") || !exists_export_template("winrt_x86_release.zip") + || !exists_export_template("winrt_arm_debug.zip") || !exists_export_template("winrt_arm_release.zip") + || !exists_export_template("winrt_x64_debug.zip") || !exists_export_template("winrt_x64_release.zip")) { + valid = false; + err += TTR("No export templates found.\nDownload and install export templates.") + "\n"; + } + + if (custom_debug_package != "" && !FileAccess::exists(custom_debug_package)) { + valid = false; + err += TTR("Custom debug package not found.") + "\n"; + } + + if (custom_release_package != "" && !FileAccess::exists(custom_release_package)) { + valid = false; + err += TTR("Custom release package not found.") + "\n"; + } + + if (!_valid_resource_name(unique_name)) { + valid = false; + err += TTR("Invalid unique name.") + "\n"; + } + + if (!_valid_guid(product_guid)) { + valid = false; + err += TTR("Invalid product GUID.") + "\n"; + } + + if (!_valid_guid(publisher_guid)) { + valid = false; + err += TTR("Invalid publisher GUID.") + "\n"; + } + + if (!_valid_bgcolor(background_color)) { + valid = false; + err += TTR("Invalid background color.") + "\n"; + } + + if (store_logo.is_valid() && !_valid_image(store_logo, 50, 50)) { + valid = false; + err += TTR("Invalid Store Logo image dimensions (should be 50x50).") + "\n"; + } + + if (square44.is_valid() && !_valid_image(square44, 44, 44)) { + valid = false; + err += TTR("Invalid square 44x44 logo image dimensions (should be 44x44).") + "\n"; + } + + if (square71.is_valid() && !_valid_image(square71, 71, 71)) { + valid = false; + err += TTR("Invalid square 71x71 logo image dimensions (should be 71x71).") + "\n"; + } + + if (square150.is_valid() && !_valid_image(square150, 150, 150)) { + valid = false; + err += TTR("Invalid square 150x150 logo image dimensions (should be 150x150).") + "\n"; + } + + if (square310.is_valid() && !_valid_image(square310, 310, 310)) { + valid = false; + err += TTR("Invalid square 310x310 logo image dimensions (should be 310x310).") + "\n"; + } + + if (wide310.is_valid() && !_valid_image(wide310, 310, 150)) { + valid = false; + err += TTR("Invalid wide 310x150 logo image dimensions (should be 310x150).") + "\n"; + } + + if (splash.is_valid() && !_valid_image(splash, 620, 300)) { + valid = false; + err += TTR("Invalid splash screen image dimensions (should be 620x300).") + "\n"; + } + + if (r_error) + *r_error = err; + + return valid; +} + +Error EditorExportPlatformWinrt::export_project(const String & p_path, bool p_debug, int p_flags) { + + String src_appx; + + EditorProgress ep("export", "Exporting for Windows Universal", 7); + + if (is_debug) + src_appx = custom_debug_package; + else + src_appx = custom_release_package; + + if (src_appx == "") { + String err; + if (p_debug) { + switch (arch) { + case X86: { + src_appx = find_export_template("winrt_x86_debug.zip", &err); + break; + } + case X64: { + src_appx = find_export_template("winrt_x64_debug.zip", &err); + break; + } + case ARM: { + src_appx = find_export_template("winrt_arm_debug.zip", &err); + break; + } + } + } else { + switch (arch) { + case X86: { + src_appx = find_export_template("winrt_x86_release.zip", &err); + break; + } + case X64: { + src_appx = find_export_template("winrt_x64_release.zip", &err); + break; + } + case ARM: { + src_appx = find_export_template("winrt_arm_release.zip", &err); + break; + } + } + } + if (src_appx == "") { + EditorNode::add_io_error(err); + return ERR_FILE_NOT_FOUND; + } + } + + Error err = OK; + + FileAccess *fa_pack = FileAccess::open(p_path, FileAccess::WRITE, &err); + ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE); + + AppxPackager packager; + packager.init(fa_pack, sign_package ? AppxPackager::SIGN : AppxPackager::DONT_SIGN, certificate_path, certificate_pass); + + FileAccess *src_f = NULL; + zlib_filefunc_def io = zipio_create_io_from_file(&src_f); + + ep.step("Creating package...", 0); + + unzFile pkg = unzOpen2(src_appx.utf8().get_data(), &io); + + if (!pkg) { + + EditorNode::add_io_error("Could not find template appx to export:\n" + src_appx); + return ERR_FILE_NOT_FOUND; + } + + int ret = unzGoToFirstFile(pkg); + + ep.step("Copying template files...", 1); + + EditorNode::progress_add_task("template_files", "Template files", 100); + packager.set_progress_task("template_files"); + + int template_files_amount = 9; + int template_file_no = 1; + + while (ret == UNZ_OK) { + + // get file name + unz_file_info info; + char fname[16834]; + ret = unzGetCurrentFileInfo(pkg, &info, fname, 16834, NULL, 0, NULL, 0); + + String path = fname; + + if (path.ends_with("/")) { + // Ignore directories + ret = unzGoToNextFile(pkg); + continue; + } + + Vector<uint8_t> data; + bool do_read = true; + + if (path.begins_with("Assets/")) { + + path = path.replace(".scale-100", ""); + + data = _get_image_data(path); + if (data.size() > 0) do_read = false; + } + + //read + if (do_read) { + data.resize(info.uncompressed_size); + unzOpenCurrentFile(pkg); + unzReadCurrentFile(pkg, data.ptr(), data.size()); + unzCloseCurrentFile(pkg); + } + + if (path == "AppxManifest.xml") { + + data = _fix_manifest(data, p_flags&(EXPORT_DUMB_CLIENT | EXPORT_REMOTE_DEBUG)); + } + + print_line("ADDING: " + path); + + packager.add_file(path, data.ptr(), data.size(), template_file_no++, template_files_amount, _should_compress_asset(path, data)); + + ret = unzGoToNextFile(pkg); + } + + EditorNode::progress_end_task("template_files"); + + ep.step("Creating command line...", 2); + + Vector<String> cl = cmdline.strip_edges().split(" "); + for (int i = 0;i<cl.size();i++) { + if (cl[i].strip_edges().length() == 0) { + cl.remove(i); + i--; + } + } + + if (!(p_flags & EXPORT_DUMB_CLIENT)) { + cl.push_back("-path"); + cl.push_back("game"); + } + + gen_export_flags(cl, p_flags); + + // Command line file + Vector<uint8_t> clf; + + // Argc + clf.resize(4); + encode_uint32(cl.size(), clf.ptr()); + + for (int i = 0; i < cl.size(); i++) { + + CharString txt = cl[i].utf8(); + int base = clf.size(); + clf.resize(base + 4 + txt.length()); + encode_uint32(txt.length(), &clf[base]); + copymem(&clf[base + 4], txt.ptr(), txt.length()); + print_line(itos(i) + " param: " + cl[i]); + } + + packager.add_file("__cl__.cl", clf.ptr(), clf.size(), -1, -1, false); + + ep.step("Adding project files...", 3); + + EditorNode::progress_add_task("project_files", "Project Files", 100); + packager.set_progress_task("project_files"); + + err = export_project_files(save_appx_file, &packager, false); + + EditorNode::progress_end_task("project_files"); + + ep.step("Closing package...", 7); + + unzClose(pkg); + + packager.finish(); + + return OK; +} + +EditorExportPlatformWinrt::EditorExportPlatformWinrt() { + + Image img(_winrt_logo); + logo = Ref<ImageTexture>(memnew(ImageTexture)); + logo->create_from_image(img); + + is_debug = true; + + custom_release_package = ""; + custom_debug_package = ""; + + arch = X86; + + display_name = ""; + short_name = "Godot"; + unique_name = "Godot.Engine"; + description = "Godot Engine"; + publisher = "CN=GodotEngine"; + publisher_display_name = "Godot Engine"; + + product_guid = "00000000-0000-0000-0000-000000000000"; + publisher_guid = "00000000-0000-0000-0000-000000000000"; + + version_major = 1; + version_minor = 0; + version_build = 0; + version_revision = 0; + + orientation_landscape = true; + orientation_portrait = true; + orientation_landscape_flipped = true; + orientation_portrait_flipped = true; + + background_color = "transparent"; + + name_on_square150 = false; + name_on_square310 = false; + name_on_wide = false; + + sign_package = false; + certificate_path = ""; + certificate_pass = ""; +} + +EditorExportPlatformWinrt::~EditorExportPlatformWinrt() {} + + +void register_winrt_exporter() { + + Ref<EditorExportPlatformWinrt> exporter = Ref<EditorExportPlatformWinrt>(memnew(EditorExportPlatformWinrt)); + EditorImportExport::get_singleton()->add_export_platform(exporter); +} diff --git a/platform/winrt/export/export.h b/platform/winrt/export/export.h new file mode 100644 index 0000000000..278d6d23cd --- /dev/null +++ b/platform/winrt/export/export.h @@ -0,0 +1,29 @@ +/*************************************************************************/ +/* export.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_winrt_exporter(); diff --git a/platform/winrt/gl_context_egl.cpp b/platform/winrt/gl_context_egl.cpp index 12ccd404a9..f7b514b3c0 100644 --- a/platform/winrt/gl_context_egl.cpp +++ b/platform/winrt/gl_context_egl.cpp @@ -103,9 +103,22 @@ Error ContextEGL::initialize() { const EGLint displayAttributes[] = { - EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + /*EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9, EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3, + EGL_NONE,*/ + // These are the default display attributes, used to request ANGLE's D3D11 renderer. + // eglInitialize will only succeed with these attributes if the hardware supports D3D11 Feature Level 10_0+. + EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + + // EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that can have large performance benefits on mobile devices. + // Its syntax is subject to change, though. Please update your Visual Studio templates if you experience compilation issues with it. + //EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, + + // EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that enables ANGLE to automatically call + // the IDXGIDevice3::Trim method on behalf of the application when it gets suspended. + // Calling IDXGIDevice3::Trim when an application is suspended is a Windows Store application certification requirement. + EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; diff --git a/platform/winrt/gl_context_egl.h b/platform/winrt/gl_context_egl.h index 68dcdd5035..8124c2903d 100644 --- a/platform/winrt/gl_context_egl.h +++ b/platform/winrt/gl_context_egl.h @@ -49,6 +49,8 @@ class ContextEGL : public ContextGL { EGLint width; EGLint height; + bool vsync; + public: virtual void release_current(); @@ -59,6 +61,9 @@ public: virtual int get_window_height(); virtual void swap_buffers(); + void set_use_vsync(bool use) { vsync = use; } + bool is_using_vsync() const { return vsync; } + virtual Error initialize(); void reset(); diff --git a/platform/winrt/include/EGL/egl.h b/platform/winrt/include/EGL/egl.h deleted file mode 100644 index 12590a0e20..0000000000 --- a/platform/winrt/include/EGL/egl.h +++ /dev/null @@ -1,298 +0,0 @@ -#ifndef __egl_h_ -#define __egl_h_ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* -** Copyright (c) 2013-2014 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ -/* -** This header is generated from the Khronos OpenGL / OpenGL ES XML -** API Registry. The current version of the Registry, generator scripts -** used to make the header, and the header can be found at -** http://www.opengl.org/registry/ -** -** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $ -*/ - -#include <EGL/eglplatform.h> - -/* Generated on date 20140610 */ - -/* Generated C header for: - * API: egl - * Versions considered: .* - * Versions emitted: .* - * Default extensions included: None - * Additional extensions included: _nomatch_^ - * Extensions removed: _nomatch_^ - */ - -#ifndef EGL_VERSION_1_0 -#define EGL_VERSION_1_0 1 -typedef unsigned int EGLBoolean; -typedef void *EGLDisplay; -#include <KHR/khrplatform.h> -#include <EGL/eglplatform.h> -typedef void *EGLConfig; -typedef void *EGLSurface; -typedef void *EGLContext; -typedef void (*__eglMustCastToProperFunctionPointerType)(void); -#define EGL_ALPHA_SIZE 0x3021 -#define EGL_BAD_ACCESS 0x3002 -#define EGL_BAD_ALLOC 0x3003 -#define EGL_BAD_ATTRIBUTE 0x3004 -#define EGL_BAD_CONFIG 0x3005 -#define EGL_BAD_CONTEXT 0x3006 -#define EGL_BAD_CURRENT_SURFACE 0x3007 -#define EGL_BAD_DISPLAY 0x3008 -#define EGL_BAD_MATCH 0x3009 -#define EGL_BAD_NATIVE_PIXMAP 0x300A -#define EGL_BAD_NATIVE_WINDOW 0x300B -#define EGL_BAD_PARAMETER 0x300C -#define EGL_BAD_SURFACE 0x300D -#define EGL_BLUE_SIZE 0x3022 -#define EGL_BUFFER_SIZE 0x3020 -#define EGL_CONFIG_CAVEAT 0x3027 -#define EGL_CONFIG_ID 0x3028 -#define EGL_CORE_NATIVE_ENGINE 0x305B -#define EGL_DEPTH_SIZE 0x3025 -#define EGL_DONT_CARE ((EGLint)-1) -#define EGL_DRAW 0x3059 -#define EGL_EXTENSIONS 0x3055 -#define EGL_FALSE 0 -#define EGL_GREEN_SIZE 0x3023 -#define EGL_HEIGHT 0x3056 -#define EGL_LARGEST_PBUFFER 0x3058 -#define EGL_LEVEL 0x3029 -#define EGL_MAX_PBUFFER_HEIGHT 0x302A -#define EGL_MAX_PBUFFER_PIXELS 0x302B -#define EGL_MAX_PBUFFER_WIDTH 0x302C -#define EGL_NATIVE_RENDERABLE 0x302D -#define EGL_NATIVE_VISUAL_ID 0x302E -#define EGL_NATIVE_VISUAL_TYPE 0x302F -#define EGL_NONE 0x3038 -#define EGL_NON_CONFORMANT_CONFIG 0x3051 -#define EGL_NOT_INITIALIZED 0x3001 -#define EGL_NO_CONTEXT ((EGLContext)0) -#define EGL_NO_DISPLAY ((EGLDisplay)0) -#define EGL_NO_SURFACE ((EGLSurface)0) -#define EGL_PBUFFER_BIT 0x0001 -#define EGL_PIXMAP_BIT 0x0002 -#define EGL_READ 0x305A -#define EGL_RED_SIZE 0x3024 -#define EGL_SAMPLES 0x3031 -#define EGL_SAMPLE_BUFFERS 0x3032 -#define EGL_SLOW_CONFIG 0x3050 -#define EGL_STENCIL_SIZE 0x3026 -#define EGL_SUCCESS 0x3000 -#define EGL_SURFACE_TYPE 0x3033 -#define EGL_TRANSPARENT_BLUE_VALUE 0x3035 -#define EGL_TRANSPARENT_GREEN_VALUE 0x3036 -#define EGL_TRANSPARENT_RED_VALUE 0x3037 -#define EGL_TRANSPARENT_RGB 0x3052 -#define EGL_TRANSPARENT_TYPE 0x3034 -#define EGL_TRUE 1 -#define EGL_VENDOR 0x3053 -#define EGL_VERSION 0x3054 -#define EGL_WIDTH 0x3057 -#define EGL_WINDOW_BIT 0x0004 -EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); -EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers (EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target); -EGLAPI EGLContext EGLAPIENTRY eglCreateContext (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); -EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); -EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface (EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list); -EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext (EGLDisplay dpy, EGLContext ctx); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface (EGLDisplay dpy, EGLSurface surface); -EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); -EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); -EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay (void); -EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface (EGLint readdraw); -EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay (EGLNativeDisplayType display_id); -EGLAPI EGLint EGLAPIENTRY eglGetError (void); -EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress (const char *procname); -EGLAPI EGLBoolean EGLAPIENTRY eglInitialize (EGLDisplay dpy, EGLint *major, EGLint *minor); -EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value); -EGLAPI const char *EGLAPIENTRY eglQueryString (EGLDisplay dpy, EGLint name); -EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value); -EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface); -EGLAPI EGLBoolean EGLAPIENTRY eglTerminate (EGLDisplay dpy); -EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL (void); -EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative (EGLint engine); -#endif /* EGL_VERSION_1_0 */ - -#ifndef EGL_VERSION_1_1 -#define EGL_VERSION_1_1 1 -#define EGL_BACK_BUFFER 0x3084 -#define EGL_BIND_TO_TEXTURE_RGB 0x3039 -#define EGL_BIND_TO_TEXTURE_RGBA 0x303A -#define EGL_CONTEXT_LOST 0x300E -#define EGL_MIN_SWAP_INTERVAL 0x303B -#define EGL_MAX_SWAP_INTERVAL 0x303C -#define EGL_MIPMAP_TEXTURE 0x3082 -#define EGL_MIPMAP_LEVEL 0x3083 -#define EGL_NO_TEXTURE 0x305C -#define EGL_TEXTURE_2D 0x305F -#define EGL_TEXTURE_FORMAT 0x3080 -#define EGL_TEXTURE_RGB 0x305D -#define EGL_TEXTURE_RGBA 0x305E -#define EGL_TEXTURE_TARGET 0x3081 -EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer); -EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer); -EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value); -EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval (EGLDisplay dpy, EGLint interval); -#endif /* EGL_VERSION_1_1 */ - -#ifndef EGL_VERSION_1_2 -#define EGL_VERSION_1_2 1 -typedef unsigned int EGLenum; -typedef void *EGLClientBuffer; -#define EGL_ALPHA_FORMAT 0x3088 -#define EGL_ALPHA_FORMAT_NONPRE 0x308B -#define EGL_ALPHA_FORMAT_PRE 0x308C -#define EGL_ALPHA_MASK_SIZE 0x303E -#define EGL_BUFFER_PRESERVED 0x3094 -#define EGL_BUFFER_DESTROYED 0x3095 -#define EGL_CLIENT_APIS 0x308D -#define EGL_COLORSPACE 0x3087 -#define EGL_COLORSPACE_sRGB 0x3089 -#define EGL_COLORSPACE_LINEAR 0x308A -#define EGL_COLOR_BUFFER_TYPE 0x303F -#define EGL_CONTEXT_CLIENT_TYPE 0x3097 -#define EGL_DISPLAY_SCALING 10000 -#define EGL_HORIZONTAL_RESOLUTION 0x3090 -#define EGL_LUMINANCE_BUFFER 0x308F -#define EGL_LUMINANCE_SIZE 0x303D -#define EGL_OPENGL_ES_BIT 0x0001 -#define EGL_OPENVG_BIT 0x0002 -#define EGL_OPENGL_ES_API 0x30A0 -#define EGL_OPENVG_API 0x30A1 -#define EGL_OPENVG_IMAGE 0x3096 -#define EGL_PIXEL_ASPECT_RATIO 0x3092 -#define EGL_RENDERABLE_TYPE 0x3040 -#define EGL_RENDER_BUFFER 0x3086 -#define EGL_RGB_BUFFER 0x308E -#define EGL_SINGLE_BUFFER 0x3085 -#define EGL_SWAP_BEHAVIOR 0x3093 -#define EGL_UNKNOWN ((EGLint)-1) -#define EGL_VERTICAL_RESOLUTION 0x3091 -EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI (EGLenum api); -EGLAPI EGLenum EGLAPIENTRY eglQueryAPI (void); -EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer (EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread (void); -EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient (void); -#endif /* EGL_VERSION_1_2 */ - -#ifndef EGL_VERSION_1_3 -#define EGL_VERSION_1_3 1 -#define EGL_CONFORMANT 0x3042 -#define EGL_CONTEXT_CLIENT_VERSION 0x3098 -#define EGL_MATCH_NATIVE_PIXMAP 0x3041 -#define EGL_OPENGL_ES2_BIT 0x0004 -#define EGL_VG_ALPHA_FORMAT 0x3088 -#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B -#define EGL_VG_ALPHA_FORMAT_PRE 0x308C -#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040 -#define EGL_VG_COLORSPACE 0x3087 -#define EGL_VG_COLORSPACE_sRGB 0x3089 -#define EGL_VG_COLORSPACE_LINEAR 0x308A -#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020 -#endif /* EGL_VERSION_1_3 */ - -#ifndef EGL_VERSION_1_4 -#define EGL_VERSION_1_4 1 -#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) -#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200 -#define EGL_MULTISAMPLE_RESOLVE 0x3099 -#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A -#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B -#define EGL_OPENGL_API 0x30A2 -#define EGL_OPENGL_BIT 0x0008 -#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400 -EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void); -#endif /* EGL_VERSION_1_4 */ - -#ifndef EGL_VERSION_1_5 -#define EGL_VERSION_1_5 1 -typedef void *EGLSync; -typedef intptr_t EGLAttrib; -typedef khronos_utime_nanoseconds_t EGLTime; -#define EGL_CONTEXT_MAJOR_VERSION 0x3098 -#define EGL_CONTEXT_MINOR_VERSION 0x30FB -#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD -#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD -#define EGL_NO_RESET_NOTIFICATION 0x31BE -#define EGL_LOSE_CONTEXT_ON_RESET 0x31BF -#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001 -#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002 -#define EGL_CONTEXT_OPENGL_DEBUG 0x31B0 -#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1 -#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2 -#define EGL_OPENGL_ES3_BIT 0x00000040 -#define EGL_CL_EVENT_HANDLE 0x309C -#define EGL_SYNC_CL_EVENT 0x30FE -#define EGL_SYNC_CL_EVENT_COMPLETE 0x30FF -#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0 -#define EGL_SYNC_TYPE 0x30F7 -#define EGL_SYNC_STATUS 0x30F1 -#define EGL_SYNC_CONDITION 0x30F8 -#define EGL_SIGNALED 0x30F2 -#define EGL_UNSIGNALED 0x30F3 -#define EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001 -#define EGL_FOREVER 0xFFFFFFFFFFFFFFFFull -#define EGL_TIMEOUT_EXPIRED 0x30F5 -#define EGL_CONDITION_SATISFIED 0x30F6 -#define EGL_NO_SYNC ((EGLSync)0) -#define EGL_SYNC_FENCE 0x30F9 -#define EGL_GL_COLORSPACE 0x309D -#define EGL_GL_COLORSPACE_SRGB 0x3089 -#define EGL_GL_COLORSPACE_LINEAR 0x308A -#define EGL_GL_RENDERBUFFER 0x30B9 -#define EGL_GL_TEXTURE_2D 0x30B1 -#define EGL_GL_TEXTURE_LEVEL 0x30BC -#define EGL_GL_TEXTURE_3D 0x30B2 -#define EGL_GL_TEXTURE_ZOFFSET 0x30BD -#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3 -#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4 -#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5 -#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6 -#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7 -#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8 -EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync); -EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); -EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value); -EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list); -EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list); -EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags); -#endif /* EGL_VERSION_1_5 */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/platform/winrt/include/EGL/eglext.h b/platform/winrt/include/EGL/eglext.h deleted file mode 100644 index 05b2555f31..0000000000 --- a/platform/winrt/include/EGL/eglext.h +++ /dev/null @@ -1,766 +0,0 @@ -#ifndef __eglext_h_ -#define __eglext_h_ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* -** Copyright (c) 2013-2014 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ -/* -** This header is generated from the Khronos OpenGL / OpenGL ES XML -** API Registry. The current version of the Registry, generator scripts -** used to make the header, and the header can be found at -** http://www.opengl.org/registry/ -** -** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $ -*/ - -#include <EGL/eglplatform.h> - -#define EGL_EGLEXT_VERSION 20140610 - -/* Generated C header for: - * API: egl - * Versions considered: .* - * Versions emitted: _nomatch_^ - * Default extensions included: egl - * Additional extensions included: _nomatch_^ - * Extensions removed: _nomatch_^ - */ - -#ifndef EGL_KHR_cl_event -#define EGL_KHR_cl_event 1 -#define EGL_CL_EVENT_HANDLE_KHR 0x309C -#define EGL_SYNC_CL_EVENT_KHR 0x30FE -#define EGL_SYNC_CL_EVENT_COMPLETE_KHR 0x30FF -#endif /* EGL_KHR_cl_event */ - -#ifndef EGL_KHR_cl_event2 -#define EGL_KHR_cl_event2 1 -typedef void *EGLSyncKHR; -typedef intptr_t EGLAttribKHR; -typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); -#endif -#endif /* EGL_KHR_cl_event2 */ - -#ifndef EGL_KHR_client_get_all_proc_addresses -#define EGL_KHR_client_get_all_proc_addresses 1 -#endif /* EGL_KHR_client_get_all_proc_addresses */ - -#ifndef EGL_KHR_config_attribs -#define EGL_KHR_config_attribs 1 -#define EGL_CONFORMANT_KHR 0x3042 -#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020 -#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040 -#endif /* EGL_KHR_config_attribs */ - -#ifndef EGL_KHR_create_context -#define EGL_KHR_create_context 1 -#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098 -#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB -#define EGL_CONTEXT_FLAGS_KHR 0x30FC -#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD -#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD -#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE -#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF -#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 -#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 -#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004 -#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 -#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 -#define EGL_OPENGL_ES3_BIT_KHR 0x00000040 -#endif /* EGL_KHR_create_context */ - -#ifndef EGL_KHR_fence_sync -#define EGL_KHR_fence_sync 1 -#ifdef KHRONOS_SUPPORT_INT64 -#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0 -#define EGL_SYNC_CONDITION_KHR 0x30F8 -#define EGL_SYNC_FENCE_KHR 0x30F9 -#endif /* KHRONOS_SUPPORT_INT64 */ -#endif /* EGL_KHR_fence_sync */ - -#ifndef EGL_KHR_get_all_proc_addresses -#define EGL_KHR_get_all_proc_addresses 1 -#endif /* EGL_KHR_get_all_proc_addresses */ - -#ifndef EGL_KHR_gl_colorspace -#define EGL_KHR_gl_colorspace 1 -#define EGL_GL_COLORSPACE_KHR 0x309D -#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089 -#define EGL_GL_COLORSPACE_LINEAR_KHR 0x308A -#endif /* EGL_KHR_gl_colorspace */ - -#ifndef EGL_KHR_gl_renderbuffer_image -#define EGL_KHR_gl_renderbuffer_image 1 -#define EGL_GL_RENDERBUFFER_KHR 0x30B9 -#endif /* EGL_KHR_gl_renderbuffer_image */ - -#ifndef EGL_KHR_gl_texture_2D_image -#define EGL_KHR_gl_texture_2D_image 1 -#define EGL_GL_TEXTURE_2D_KHR 0x30B1 -#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC -#endif /* EGL_KHR_gl_texture_2D_image */ - -#ifndef EGL_KHR_gl_texture_3D_image -#define EGL_KHR_gl_texture_3D_image 1 -#define EGL_GL_TEXTURE_3D_KHR 0x30B2 -#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD -#endif /* EGL_KHR_gl_texture_3D_image */ - -#ifndef EGL_KHR_gl_texture_cubemap_image -#define EGL_KHR_gl_texture_cubemap_image 1 -#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3 -#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4 -#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5 -#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6 -#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7 -#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8 -#endif /* EGL_KHR_gl_texture_cubemap_image */ - -#ifndef EGL_KHR_image -#define EGL_KHR_image 1 -typedef void *EGLImageKHR; -#define EGL_NATIVE_PIXMAP_KHR 0x30B0 -#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0) -typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image); -#endif -#endif /* EGL_KHR_image */ - -#ifndef EGL_KHR_image_base -#define EGL_KHR_image_base 1 -#define EGL_IMAGE_PRESERVED_KHR 0x30D2 -#endif /* EGL_KHR_image_base */ - -#ifndef EGL_KHR_image_pixmap -#define EGL_KHR_image_pixmap 1 -#endif /* EGL_KHR_image_pixmap */ - -#ifndef EGL_KHR_lock_surface -#define EGL_KHR_lock_surface 1 -#define EGL_READ_SURFACE_BIT_KHR 0x0001 -#define EGL_WRITE_SURFACE_BIT_KHR 0x0002 -#define EGL_LOCK_SURFACE_BIT_KHR 0x0080 -#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100 -#define EGL_MATCH_FORMAT_KHR 0x3043 -#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0 -#define EGL_FORMAT_RGB_565_KHR 0x30C1 -#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2 -#define EGL_FORMAT_RGBA_8888_KHR 0x30C3 -#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4 -#define EGL_LOCK_USAGE_HINT_KHR 0x30C5 -#define EGL_BITMAP_POINTER_KHR 0x30C6 -#define EGL_BITMAP_PITCH_KHR 0x30C7 -#define EGL_BITMAP_ORIGIN_KHR 0x30C8 -#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9 -#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA -#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB -#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC -#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD -#define EGL_LOWER_LEFT_KHR 0x30CE -#define EGL_UPPER_LEFT_KHR 0x30CF -typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay dpy, EGLSurface surface); -#endif -#endif /* EGL_KHR_lock_surface */ - -#ifndef EGL_KHR_lock_surface2 -#define EGL_KHR_lock_surface2 1 -#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110 -#endif /* EGL_KHR_lock_surface2 */ - -#ifndef EGL_KHR_lock_surface3 -#define EGL_KHR_lock_surface3 1 -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACE64KHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value); -#endif -#endif /* EGL_KHR_lock_surface3 */ - -#ifndef EGL_KHR_platform_android -#define EGL_KHR_platform_android 1 -#define EGL_PLATFORM_ANDROID_KHR 0x3141 -#endif /* EGL_KHR_platform_android */ - -#ifndef EGL_KHR_platform_gbm -#define EGL_KHR_platform_gbm 1 -#define EGL_PLATFORM_GBM_KHR 0x31D7 -#endif /* EGL_KHR_platform_gbm */ - -#ifndef EGL_KHR_platform_wayland -#define EGL_KHR_platform_wayland 1 -#define EGL_PLATFORM_WAYLAND_KHR 0x31D8 -#endif /* EGL_KHR_platform_wayland */ - -#ifndef EGL_KHR_platform_x11 -#define EGL_KHR_platform_x11 1 -#define EGL_PLATFORM_X11_KHR 0x31D5 -#define EGL_PLATFORM_X11_SCREEN_KHR 0x31D6 -#endif /* EGL_KHR_platform_x11 */ - -#ifndef EGL_KHR_reusable_sync -#define EGL_KHR_reusable_sync 1 -typedef khronos_utime_nanoseconds_t EGLTimeKHR; -#ifdef KHRONOS_SUPPORT_INT64 -#define EGL_SYNC_STATUS_KHR 0x30F1 -#define EGL_SIGNALED_KHR 0x30F2 -#define EGL_UNSIGNALED_KHR 0x30F3 -#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5 -#define EGL_CONDITION_SATISFIED_KHR 0x30F6 -#define EGL_SYNC_TYPE_KHR 0x30F7 -#define EGL_SYNC_REUSABLE_KHR 0x30FA -#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001 -#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull -#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0) -typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync); -typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync); -EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout); -EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode); -EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value); -#endif -#endif /* KHRONOS_SUPPORT_INT64 */ -#endif /* EGL_KHR_reusable_sync */ - -#ifndef EGL_KHR_stream -#define EGL_KHR_stream 1 -typedef void *EGLStreamKHR; -typedef khronos_uint64_t EGLuint64KHR; -#ifdef KHRONOS_SUPPORT_INT64 -#define EGL_NO_STREAM_KHR ((EGLStreamKHR)0) -#define EGL_CONSUMER_LATENCY_USEC_KHR 0x3210 -#define EGL_PRODUCER_FRAME_KHR 0x3212 -#define EGL_CONSUMER_FRAME_KHR 0x3213 -#define EGL_STREAM_STATE_KHR 0x3214 -#define EGL_STREAM_STATE_CREATED_KHR 0x3215 -#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216 -#define EGL_STREAM_STATE_EMPTY_KHR 0x3217 -#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218 -#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219 -#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A -#define EGL_BAD_STREAM_KHR 0x321B -#define EGL_BAD_STATE_KHR 0x321C -typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR (EGLDisplay dpy, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR (EGLDisplay dpy, EGLStreamKHR stream); -EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value); -#endif -#endif /* KHRONOS_SUPPORT_INT64 */ -#endif /* EGL_KHR_stream */ - -#ifndef EGL_KHR_stream_consumer_gltexture -#define EGL_KHR_stream_consumer_gltexture 1 -#ifdef EGL_KHR_stream -#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR (EGLDisplay dpy, EGLStreamKHR stream); -EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR (EGLDisplay dpy, EGLStreamKHR stream); -EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR (EGLDisplay dpy, EGLStreamKHR stream); -#endif -#endif /* EGL_KHR_stream */ -#endif /* EGL_KHR_stream_consumer_gltexture */ - -#ifndef EGL_KHR_stream_cross_process_fd -#define EGL_KHR_stream_cross_process_fd 1 -typedef int EGLNativeFileDescriptorKHR; -#ifdef EGL_KHR_stream -#define EGL_NO_FILE_DESCRIPTOR_KHR ((EGLNativeFileDescriptorKHR)(-1)) -typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); -typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR (EGLDisplay dpy, EGLStreamKHR stream); -EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor); -#endif -#endif /* EGL_KHR_stream */ -#endif /* EGL_KHR_stream_cross_process_fd */ - -#ifndef EGL_KHR_stream_fifo -#define EGL_KHR_stream_fifo 1 -#ifdef EGL_KHR_stream -#define EGL_STREAM_FIFO_LENGTH_KHR 0x31FC -#define EGL_STREAM_TIME_NOW_KHR 0x31FD -#define EGL_STREAM_TIME_CONSUMER_KHR 0x31FE -#define EGL_STREAM_TIME_PRODUCER_KHR 0x31FF -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value); -#endif -#endif /* EGL_KHR_stream */ -#endif /* EGL_KHR_stream_fifo */ - -#ifndef EGL_KHR_stream_producer_aldatalocator -#define EGL_KHR_stream_producer_aldatalocator 1 -#ifdef EGL_KHR_stream -#endif /* EGL_KHR_stream */ -#endif /* EGL_KHR_stream_producer_aldatalocator */ - -#ifndef EGL_KHR_stream_producer_eglsurface -#define EGL_KHR_stream_producer_eglsurface 1 -#ifdef EGL_KHR_stream -#define EGL_STREAM_BIT_KHR 0x0800 -typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list); -#endif -#endif /* EGL_KHR_stream */ -#endif /* EGL_KHR_stream_producer_eglsurface */ - -#ifndef EGL_KHR_surfaceless_context -#define EGL_KHR_surfaceless_context 1 -#endif /* EGL_KHR_surfaceless_context */ - -#ifndef EGL_KHR_vg_parent_image -#define EGL_KHR_vg_parent_image 1 -#define EGL_VG_PARENT_IMAGE_KHR 0x30BA -#endif /* EGL_KHR_vg_parent_image */ - -#ifndef EGL_KHR_wait_sync -#define EGL_KHR_wait_sync 1 -typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags); -#endif -#endif /* EGL_KHR_wait_sync */ - -#ifndef EGL_ANDROID_blob_cache -#define EGL_ANDROID_blob_cache 1 -typedef khronos_ssize_t EGLsizeiANDROID; -typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize); -typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize); -typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); -#endif -#endif /* EGL_ANDROID_blob_cache */ - -#ifndef EGL_ANDROID_framebuffer_target -#define EGL_ANDROID_framebuffer_target 1 -#define EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147 -#endif /* EGL_ANDROID_framebuffer_target */ - -#ifndef EGL_ANDROID_image_native_buffer -#define EGL_ANDROID_image_native_buffer 1 -#define EGL_NATIVE_BUFFER_ANDROID 0x3140 -#endif /* EGL_ANDROID_image_native_buffer */ - -#ifndef EGL_ANDROID_native_fence_sync -#define EGL_ANDROID_native_fence_sync 1 -#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144 -#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145 -#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146 -#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1 -typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR sync); -#endif -#endif /* EGL_ANDROID_native_fence_sync */ - -#ifndef EGL_ANDROID_recordable -#define EGL_ANDROID_recordable 1 -#define EGL_RECORDABLE_ANDROID 0x3142 -#endif /* EGL_ANDROID_recordable */ - -#ifndef EGL_ANGLE_d3d_share_handle_client_buffer -#define EGL_ANGLE_d3d_share_handle_client_buffer 1 -#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200 -#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */ - -#ifndef EGL_ANGLE_window_fixed_size -#define EGL_ANGLE_window_fixed_size 1 -#define EGL_FIXED_SIZE_ANGLE 0x3201 -#endif /* EGL_ANGLE_window_fixed_size */ - -#ifndef EGL_ANGLE_query_surface_pointer -#define EGL_ANGLE_query_surface_pointer 1 -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); -#endif -#endif /* EGL_ANGLE_query_surface_pointer */ - -#ifndef EGL_ANGLE_software_display -#define EGL_ANGLE_software_display 1 -#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1) -#endif /* EGL_ANGLE_software_display */ - -#ifndef EGL_ANGLE_direct3d_display -#define EGL_ANGLE_direct3d_display 1 -#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2) -#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3) -#endif /* EGL_ANGLE_direct3d_display */ - -#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle -#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1 -#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */ - -#ifndef EGL_ANGLE_surface_d3d_render_to_back_buffer -#define EGL_ANGLE_surface_d3d_render_to_back_buffer 1 -#define EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER 0x320B -#define EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER 0x320C -#endif /* EGL_ANGLE_surface_d3d_render_to_back_buffer */ - -#ifndef EGL_ANGLE_platform_angle -#define EGL_ANGLE_platform_angle 1 -#define EGL_PLATFORM_ANGLE_ANGLE 0x3201 -#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202 -#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3203 -#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204 -#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205 -#endif /* EGL_ANGLE_platform_angle */ - -#ifndef EGL_ANGLE_platform_angle_d3d -#define EGL_ANGLE_platform_angle_d3d 1 -#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3206 -#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207 -#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208 -#endif /* EGL_ANGLE_platform_angle_d3d */ - -#ifndef EGL_ANGLE_platform_angle_opengl -#define EGL_ANGLE_platform_angle_opengl 1 -#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3209 -#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320A -#endif /* EGL_ANGLE_platform_angle_opengl */ - -#ifndef EGL_ARM_pixmap_multisample_discard -#define EGL_ARM_pixmap_multisample_discard 1 -#define EGL_DISCARD_SAMPLES_ARM 0x3286 -#endif /* EGL_ARM_pixmap_multisample_discard */ - -#ifndef EGL_EXT_buffer_age -#define EGL_EXT_buffer_age 1 -#define EGL_BUFFER_AGE_EXT 0x313D -#endif /* EGL_EXT_buffer_age */ - -#ifndef EGL_EXT_client_extensions -#define EGL_EXT_client_extensions 1 -#endif /* EGL_EXT_client_extensions */ - -#ifndef EGL_EXT_create_context_robustness -#define EGL_EXT_create_context_robustness 1 -#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF -#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138 -#define EGL_NO_RESET_NOTIFICATION_EXT 0x31BE -#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF -#endif /* EGL_EXT_create_context_robustness */ - -#ifndef EGL_EXT_device_base -#define EGL_EXT_device_base 1 -typedef void *EGLDeviceEXT; -#define EGL_NO_DEVICE_EXT ((EGLDeviceEXT)(0)) -#define EGL_BAD_DEVICE_EXT 0x322B -#define EGL_DEVICE_EXT 0x322C -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC) (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value); -typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC) (EGLDeviceEXT device, EGLint name); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBEXTPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value); -EGLAPI const char *EGLAPIENTRY eglQueryDeviceStringEXT (EGLDeviceEXT device, EGLint name); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryDevicesEXT (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint attribute, EGLAttrib *value); -#endif -#endif /* EGL_EXT_device_base */ - -#ifndef EGL_EXT_image_dma_buf_import -#define EGL_EXT_image_dma_buf_import 1 -#define EGL_LINUX_DMA_BUF_EXT 0x3270 -#define EGL_LINUX_DRM_FOURCC_EXT 0x3271 -#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272 -#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273 -#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274 -#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275 -#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276 -#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277 -#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278 -#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279 -#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A -#define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B -#define EGL_SAMPLE_RANGE_HINT_EXT 0x327C -#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D -#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E -#define EGL_ITU_REC601_EXT 0x327F -#define EGL_ITU_REC709_EXT 0x3280 -#define EGL_ITU_REC2020_EXT 0x3281 -#define EGL_YUV_FULL_RANGE_EXT 0x3282 -#define EGL_YUV_NARROW_RANGE_EXT 0x3283 -#define EGL_YUV_CHROMA_SITING_0_EXT 0x3284 -#define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285 -#endif /* EGL_EXT_image_dma_buf_import */ - -#ifndef EGL_EXT_multiview_window -#define EGL_EXT_multiview_window 1 -#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134 -#endif /* EGL_EXT_multiview_window */ - -#ifndef EGL_EXT_platform_base -#define EGL_EXT_platform_base 1 -typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list); -typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list); -typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list); -EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list); -EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list); -#endif -#endif /* EGL_EXT_platform_base */ - -#ifndef EGL_EXT_platform_device -#define EGL_EXT_platform_device 1 -#define EGL_PLATFORM_DEVICE_EXT 0x313F -#endif /* EGL_EXT_platform_device */ - -#ifndef EGL_EXT_platform_wayland -#define EGL_EXT_platform_wayland 1 -#define EGL_PLATFORM_WAYLAND_EXT 0x31D8 -#endif /* EGL_EXT_platform_wayland */ - -#ifndef EGL_EXT_platform_x11 -#define EGL_EXT_platform_x11 1 -#define EGL_PLATFORM_X11_EXT 0x31D5 -#define EGL_PLATFORM_X11_SCREEN_EXT 0x31D6 -#endif /* EGL_EXT_platform_x11 */ - -#ifndef EGL_EXT_protected_surface -#define EGL_EXT_protected_surface 1 -#define EGL_PROTECTED_CONTENT_EXT 0x32C0 -#endif /* EGL_EXT_protected_surface */ - -#ifndef EGL_EXT_swap_buffers_with_damage -#define EGL_EXT_swap_buffers_with_damage 1 -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); -#endif -#endif /* EGL_EXT_swap_buffers_with_damage */ - -#ifndef EGL_HI_clientpixmap -#define EGL_HI_clientpixmap 1 -struct EGLClientPixmapHI { - void *pData; - EGLint iWidth; - EGLint iHeight; - EGLint iStride; -}; -#define EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74 -typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap); -#endif -#endif /* EGL_HI_clientpixmap */ - -#ifndef EGL_HI_colorformats -#define EGL_HI_colorformats 1 -#define EGL_COLOR_FORMAT_HI 0x8F70 -#define EGL_COLOR_RGB_HI 0x8F71 -#define EGL_COLOR_RGBA_HI 0x8F72 -#define EGL_COLOR_ARGB_HI 0x8F73 -#endif /* EGL_HI_colorformats */ - -#ifndef EGL_IMG_context_priority -#define EGL_IMG_context_priority 1 -#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100 -#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101 -#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102 -#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103 -#endif /* EGL_IMG_context_priority */ - -#ifndef EGL_MESA_drm_image -#define EGL_MESA_drm_image 1 -#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0 -#define EGL_DRM_BUFFER_USE_MESA 0x31D1 -#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2 -#define EGL_DRM_BUFFER_MESA 0x31D3 -#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4 -#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001 -#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002 -typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride); -#endif -#endif /* EGL_MESA_drm_image */ - -#ifndef EGL_MESA_platform_gbm -#define EGL_MESA_platform_gbm 1 -#define EGL_PLATFORM_GBM_MESA 0x31D7 -#endif /* EGL_MESA_platform_gbm */ - -#ifndef EGL_NOK_swap_region -#define EGL_NOK_swap_region 1 -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegionNOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); -#endif -#endif /* EGL_NOK_swap_region */ - -#ifndef EGL_NOK_swap_region2 -#define EGL_NOK_swap_region2 1 -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGION2NOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); -#endif -#endif /* EGL_NOK_swap_region2 */ - -#ifndef EGL_NOK_texture_from_pixmap -#define EGL_NOK_texture_from_pixmap 1 -#define EGL_Y_INVERTED_NOK 0x307F -#endif /* EGL_NOK_texture_from_pixmap */ - -#ifndef EGL_NV_3dvision_surface -#define EGL_NV_3dvision_surface 1 -#define EGL_AUTO_STEREO_NV 0x3136 -#endif /* EGL_NV_3dvision_surface */ - -#ifndef EGL_NV_coverage_sample -#define EGL_NV_coverage_sample 1 -#define EGL_COVERAGE_BUFFERS_NV 0x30E0 -#define EGL_COVERAGE_SAMPLES_NV 0x30E1 -#endif /* EGL_NV_coverage_sample */ - -#ifndef EGL_NV_coverage_sample_resolve -#define EGL_NV_coverage_sample_resolve 1 -#define EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131 -#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132 -#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133 -#endif /* EGL_NV_coverage_sample_resolve */ - -#ifndef EGL_NV_depth_nonlinear -#define EGL_NV_depth_nonlinear 1 -#define EGL_DEPTH_ENCODING_NV 0x30E2 -#define EGL_DEPTH_ENCODING_NONE_NV 0 -#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3 -#endif /* EGL_NV_depth_nonlinear */ - -#ifndef EGL_NV_native_query -#define EGL_NV_native_query 1 -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV (EGLDisplay dpy, EGLNativeDisplayType *display_id); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap); -#endif -#endif /* EGL_NV_native_query */ - -#ifndef EGL_NV_post_convert_rounding -#define EGL_NV_post_convert_rounding 1 -#endif /* EGL_NV_post_convert_rounding */ - -#ifndef EGL_NV_post_sub_buffer -#define EGL_NV_post_sub_buffer 1 -#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE -typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); -#endif -#endif /* EGL_NV_post_sub_buffer */ - -#ifndef EGL_NV_stream_sync -#define EGL_NV_stream_sync 1 -#define EGL_SYNC_NEW_FRAME_NV 0x321F -typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESTREAMSYNCNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateStreamSyncNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list); -#endif -#endif /* EGL_NV_stream_sync */ - -#ifndef EGL_NV_sync -#define EGL_NV_sync 1 -typedef void *EGLSyncNV; -typedef khronos_utime_nanoseconds_t EGLTimeNV; -#ifdef KHRONOS_SUPPORT_INT64 -#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6 -#define EGL_SYNC_STATUS_NV 0x30E7 -#define EGL_SIGNALED_NV 0x30E8 -#define EGL_UNSIGNALED_NV 0x30E9 -#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001 -#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull -#define EGL_ALREADY_SIGNALED_NV 0x30EA -#define EGL_TIMEOUT_EXPIRED_NV 0x30EB -#define EGL_CONDITION_SATISFIED_NV 0x30EC -#define EGL_SYNC_TYPE_NV 0x30ED -#define EGL_SYNC_CONDITION_NV 0x30EE -#define EGL_SYNC_FENCE_NV 0x30EF -#define EGL_NO_SYNC_NV ((EGLSyncNV)0) -typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync); -typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync); -EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync); -EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout); -EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode); -EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value); -#endif -#endif /* KHRONOS_SUPPORT_INT64 */ -#endif /* EGL_NV_sync */ - -#ifndef EGL_NV_system_time -#define EGL_NV_system_time 1 -typedef khronos_utime_nanoseconds_t EGLuint64NV; -#ifdef KHRONOS_SUPPORT_INT64 -typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void); -typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV (void); -EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void); -#endif -#endif /* KHRONOS_SUPPORT_INT64 */ -#endif /* EGL_NV_system_time */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/platform/winrt/include/EGL/eglplatform.h b/platform/winrt/include/EGL/eglplatform.h deleted file mode 100644 index 71dadc79d5..0000000000 --- a/platform/winrt/include/EGL/eglplatform.h +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef __eglplatform_h_ -#define __eglplatform_h_ - -/* -** Copyright (c) 2007-2013 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ - -/* Platform-specific types and definitions for egl.h - * $Revision: 23432 $ on $Date: 2013-10-09 00:57:24 -0700 (Wed, 09 Oct 2013) $ - * - * Adopters may modify khrplatform.h and this file to suit their platform. - * You are encouraged to submit all modifications to the Khronos group so that - * they can be included in future versions of this file. Please submit changes - * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) - * by filing a bug against product "EGL" component "Registry". - */ - -#include <KHR/khrplatform.h> - -/* Macros used in EGL function prototype declarations. - * - * EGL functions should be prototyped as: - * - * EGLAPI return-type EGLAPIENTRY eglFunction(arguments); - * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments); - * - * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h - */ - -#ifndef EGLAPI -#define EGLAPI KHRONOS_APICALL -#endif - -#ifndef EGLAPIENTRY -#define EGLAPIENTRY KHRONOS_APIENTRY -#endif -#define EGLAPIENTRYP EGLAPIENTRY* - -/* The types NativeDisplayType, NativeWindowType, and NativePixmapType - * are aliases of window-system-dependent types, such as X Display * or - * Windows Device Context. They must be defined in platform-specific - * code below. The EGL-prefixed versions of Native*Type are the same - * types, renamed in EGL 1.3 so all types in the API start with "EGL". - * - * Khronos STRONGLY RECOMMENDS that you use the default definitions - * provided below, since these changes affect both binary and source - * portability of applications using EGL running on different EGL - * implementations. - */ - -#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN 1 -#endif -#include <windows.h> - -typedef HDC EGLNativeDisplayType; -typedef HBITMAP EGLNativePixmapType; - -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */ -#include <inspectable.h> -typedef IInspectable* EGLNativeWindowType; -#else -typedef HWND EGLNativeWindowType; -#endif - -#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */ - -typedef int EGLNativeDisplayType; -typedef void *EGLNativeWindowType; -typedef void *EGLNativePixmapType; - -#elif defined(__ANDROID__) || defined(ANDROID) - -#include <android/native_window.h> - -struct egl_native_pixmap_t; - -typedef struct ANativeWindow* EGLNativeWindowType; -typedef struct egl_native_pixmap_t* EGLNativePixmapType; -typedef void* EGLNativeDisplayType; - -#elif defined(__unix__) - -/* X11 (tentative) */ -#include <X11/Xlib.h> -#include <X11/Xutil.h> - -typedef Display *EGLNativeDisplayType; -typedef Pixmap EGLNativePixmapType; -typedef Window EGLNativeWindowType; - -#else -#error "Platform not recognized" -#endif - -/* EGL 1.2 types, renamed for consistency in EGL 1.3 */ -typedef EGLNativeDisplayType NativeDisplayType; -typedef EGLNativePixmapType NativePixmapType; -typedef EGLNativeWindowType NativeWindowType; - - -/* Define EGLint. This must be a signed integral type large enough to contain - * all legal attribute names and values passed into and out of EGL, whether - * their type is boolean, bitmask, enumerant (symbolic constant), integer, - * handle, or other. While in general a 32-bit integer will suffice, if - * handles are 64 bit types, then EGLint should be defined as a signed 64-bit - * integer type. - */ -typedef khronos_int32_t EGLint; - -#endif /* __eglplatform_h */ diff --git a/platform/winrt/include/GLES2/gl2.h b/platform/winrt/include/GLES2/gl2.h deleted file mode 100644 index c2d8357268..0000000000 --- a/platform/winrt/include/GLES2/gl2.h +++ /dev/null @@ -1,620 +0,0 @@ -#ifndef __gl2_h_ -#define __gl2_h_ - -/* $Revision: 20555 $ on $Date:: 2013-02-12 14:32:47 -0800 #$ */ - -#include <GLES2/gl2platform.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * This document is licensed under the SGI Free Software B License Version - * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . - */ - -/*------------------------------------------------------------------------- - * Data type definitions - *-----------------------------------------------------------------------*/ - -typedef void GLvoid; -typedef char GLchar; -typedef unsigned int GLenum; -typedef unsigned char GLboolean; -typedef unsigned int GLbitfield; -typedef khronos_int8_t GLbyte; -typedef short GLshort; -typedef int GLint; -typedef int GLsizei; -typedef khronos_uint8_t GLubyte; -typedef unsigned short GLushort; -typedef unsigned int GLuint; -typedef khronos_float_t GLfloat; -typedef khronos_float_t GLclampf; -typedef khronos_int32_t GLfixed; - -/* GL types for handling large vertex buffer objects */ -typedef khronos_intptr_t GLintptr; -typedef khronos_ssize_t GLsizeiptr; - -/* OpenGL ES core versions */ -#define GL_ES_VERSION_2_0 1 - -/* ClearBufferMask */ -#define GL_DEPTH_BUFFER_BIT 0x00000100 -#define GL_STENCIL_BUFFER_BIT 0x00000400 -#define GL_COLOR_BUFFER_BIT 0x00004000 - -/* Boolean */ -#define GL_FALSE 0 -#define GL_TRUE 1 - -/* BeginMode */ -#define GL_POINTS 0x0000 -#define GL_LINES 0x0001 -#define GL_LINE_LOOP 0x0002 -#define GL_LINE_STRIP 0x0003 -#define GL_TRIANGLES 0x0004 -#define GL_TRIANGLE_STRIP 0x0005 -#define GL_TRIANGLE_FAN 0x0006 - -/* AlphaFunction (not supported in ES20) */ -/* GL_NEVER */ -/* GL_LESS */ -/* GL_EQUAL */ -/* GL_LEQUAL */ -/* GL_GREATER */ -/* GL_NOTEQUAL */ -/* GL_GEQUAL */ -/* GL_ALWAYS */ - -/* BlendingFactorDest */ -#define GL_ZERO 0 -#define GL_ONE 1 -#define GL_SRC_COLOR 0x0300 -#define GL_ONE_MINUS_SRC_COLOR 0x0301 -#define GL_SRC_ALPHA 0x0302 -#define GL_ONE_MINUS_SRC_ALPHA 0x0303 -#define GL_DST_ALPHA 0x0304 -#define GL_ONE_MINUS_DST_ALPHA 0x0305 - -/* BlendingFactorSrc */ -/* GL_ZERO */ -/* GL_ONE */ -#define GL_DST_COLOR 0x0306 -#define GL_ONE_MINUS_DST_COLOR 0x0307 -#define GL_SRC_ALPHA_SATURATE 0x0308 -/* GL_SRC_ALPHA */ -/* GL_ONE_MINUS_SRC_ALPHA */ -/* GL_DST_ALPHA */ -/* GL_ONE_MINUS_DST_ALPHA */ - -/* BlendEquationSeparate */ -#define GL_FUNC_ADD 0x8006 -#define GL_BLEND_EQUATION 0x8009 -#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */ -#define GL_BLEND_EQUATION_ALPHA 0x883D - -/* BlendSubtract */ -#define GL_FUNC_SUBTRACT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT 0x800B - -/* Separate Blend Functions */ -#define GL_BLEND_DST_RGB 0x80C8 -#define GL_BLEND_SRC_RGB 0x80C9 -#define GL_BLEND_DST_ALPHA 0x80CA -#define GL_BLEND_SRC_ALPHA 0x80CB -#define GL_CONSTANT_COLOR 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 -#define GL_CONSTANT_ALPHA 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 -#define GL_BLEND_COLOR 0x8005 - -/* Buffer Objects */ -#define GL_ARRAY_BUFFER 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER 0x8893 -#define GL_ARRAY_BUFFER_BINDING 0x8894 -#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 - -#define GL_STREAM_DRAW 0x88E0 -#define GL_STATIC_DRAW 0x88E4 -#define GL_DYNAMIC_DRAW 0x88E8 - -#define GL_BUFFER_SIZE 0x8764 -#define GL_BUFFER_USAGE 0x8765 - -#define GL_CURRENT_VERTEX_ATTRIB 0x8626 - -/* CullFaceMode */ -#define GL_FRONT 0x0404 -#define GL_BACK 0x0405 -#define GL_FRONT_AND_BACK 0x0408 - -/* DepthFunction */ -/* GL_NEVER */ -/* GL_LESS */ -/* GL_EQUAL */ -/* GL_LEQUAL */ -/* GL_GREATER */ -/* GL_NOTEQUAL */ -/* GL_GEQUAL */ -/* GL_ALWAYS */ - -/* EnableCap */ -#define GL_TEXTURE_2D 0x0DE1 -#define GL_CULL_FACE 0x0B44 -#define GL_BLEND 0x0BE2 -#define GL_DITHER 0x0BD0 -#define GL_STENCIL_TEST 0x0B90 -#define GL_DEPTH_TEST 0x0B71 -#define GL_SCISSOR_TEST 0x0C11 -#define GL_POLYGON_OFFSET_FILL 0x8037 -#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E -#define GL_SAMPLE_COVERAGE 0x80A0 - -/* ErrorCode */ -#define GL_NO_ERROR 0 -#define GL_INVALID_ENUM 0x0500 -#define GL_INVALID_VALUE 0x0501 -#define GL_INVALID_OPERATION 0x0502 -#define GL_OUT_OF_MEMORY 0x0505 - -/* FrontFaceDirection */ -#define GL_CW 0x0900 -#define GL_CCW 0x0901 - -/* GetPName */ -#define GL_LINE_WIDTH 0x0B21 -#define GL_ALIASED_POINT_SIZE_RANGE 0x846D -#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E -#define GL_CULL_FACE_MODE 0x0B45 -#define GL_FRONT_FACE 0x0B46 -#define GL_DEPTH_RANGE 0x0B70 -#define GL_DEPTH_WRITEMASK 0x0B72 -#define GL_DEPTH_CLEAR_VALUE 0x0B73 -#define GL_DEPTH_FUNC 0x0B74 -#define GL_STENCIL_CLEAR_VALUE 0x0B91 -#define GL_STENCIL_FUNC 0x0B92 -#define GL_STENCIL_FAIL 0x0B94 -#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 -#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 -#define GL_STENCIL_REF 0x0B97 -#define GL_STENCIL_VALUE_MASK 0x0B93 -#define GL_STENCIL_WRITEMASK 0x0B98 -#define GL_STENCIL_BACK_FUNC 0x8800 -#define GL_STENCIL_BACK_FAIL 0x8801 -#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 -#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 -#define GL_STENCIL_BACK_REF 0x8CA3 -#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 -#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 -#define GL_VIEWPORT 0x0BA2 -#define GL_SCISSOR_BOX 0x0C10 -/* GL_SCISSOR_TEST */ -#define GL_COLOR_CLEAR_VALUE 0x0C22 -#define GL_COLOR_WRITEMASK 0x0C23 -#define GL_UNPACK_ALIGNMENT 0x0CF5 -#define GL_PACK_ALIGNMENT 0x0D05 -#define GL_MAX_TEXTURE_SIZE 0x0D33 -#define GL_MAX_VIEWPORT_DIMS 0x0D3A -#define GL_SUBPIXEL_BITS 0x0D50 -#define GL_RED_BITS 0x0D52 -#define GL_GREEN_BITS 0x0D53 -#define GL_BLUE_BITS 0x0D54 -#define GL_ALPHA_BITS 0x0D55 -#define GL_DEPTH_BITS 0x0D56 -#define GL_STENCIL_BITS 0x0D57 -#define GL_POLYGON_OFFSET_UNITS 0x2A00 -/* GL_POLYGON_OFFSET_FILL */ -#define GL_POLYGON_OFFSET_FACTOR 0x8038 -#define GL_TEXTURE_BINDING_2D 0x8069 -#define GL_SAMPLE_BUFFERS 0x80A8 -#define GL_SAMPLES 0x80A9 -#define GL_SAMPLE_COVERAGE_VALUE 0x80AA -#define GL_SAMPLE_COVERAGE_INVERT 0x80AB - -/* GetTextureParameter */ -/* GL_TEXTURE_MAG_FILTER */ -/* GL_TEXTURE_MIN_FILTER */ -/* GL_TEXTURE_WRAP_S */ -/* GL_TEXTURE_WRAP_T */ - -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 - -/* HintMode */ -#define GL_DONT_CARE 0x1100 -#define GL_FASTEST 0x1101 -#define GL_NICEST 0x1102 - -/* HintTarget */ -#define GL_GENERATE_MIPMAP_HINT 0x8192 - -/* DataType */ -#define GL_BYTE 0x1400 -#define GL_UNSIGNED_BYTE 0x1401 -#define GL_SHORT 0x1402 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_INT 0x1404 -#define GL_UNSIGNED_INT 0x1405 -#define GL_FLOAT 0x1406 -#define GL_FIXED 0x140C - -/* PixelFormat */ -#define GL_DEPTH_COMPONENT 0x1902 -#define GL_ALPHA 0x1906 -#define GL_RGB 0x1907 -#define GL_RGBA 0x1908 -#define GL_LUMINANCE 0x1909 -#define GL_LUMINANCE_ALPHA 0x190A - -/* PixelType */ -/* GL_UNSIGNED_BYTE */ -#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 - -/* Shaders */ -#define GL_FRAGMENT_SHADER 0x8B30 -#define GL_VERTEX_SHADER 0x8B31 -#define GL_MAX_VERTEX_ATTRIBS 0x8869 -#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB -#define GL_MAX_VARYING_VECTORS 0x8DFC -#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D -#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C -#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 -#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD -#define GL_SHADER_TYPE 0x8B4F -#define GL_DELETE_STATUS 0x8B80 -#define GL_LINK_STATUS 0x8B82 -#define GL_VALIDATE_STATUS 0x8B83 -#define GL_ATTACHED_SHADERS 0x8B85 -#define GL_ACTIVE_UNIFORMS 0x8B86 -#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 -#define GL_ACTIVE_ATTRIBUTES 0x8B89 -#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A -#define GL_SHADING_LANGUAGE_VERSION 0x8B8C -#define GL_CURRENT_PROGRAM 0x8B8D - -/* StencilFunction */ -#define GL_NEVER 0x0200 -#define GL_LESS 0x0201 -#define GL_EQUAL 0x0202 -#define GL_LEQUAL 0x0203 -#define GL_GREATER 0x0204 -#define GL_NOTEQUAL 0x0205 -#define GL_GEQUAL 0x0206 -#define GL_ALWAYS 0x0207 - -/* StencilOp */ -/* GL_ZERO */ -#define GL_KEEP 0x1E00 -#define GL_REPLACE 0x1E01 -#define GL_INCR 0x1E02 -#define GL_DECR 0x1E03 -#define GL_INVERT 0x150A -#define GL_INCR_WRAP 0x8507 -#define GL_DECR_WRAP 0x8508 - -/* StringName */ -#define GL_VENDOR 0x1F00 -#define GL_RENDERER 0x1F01 -#define GL_VERSION 0x1F02 -#define GL_EXTENSIONS 0x1F03 - -/* TextureMagFilter */ -#define GL_NEAREST 0x2600 -#define GL_LINEAR 0x2601 - -/* TextureMinFilter */ -/* GL_NEAREST */ -/* GL_LINEAR */ -#define GL_NEAREST_MIPMAP_NEAREST 0x2700 -#define GL_LINEAR_MIPMAP_NEAREST 0x2701 -#define GL_NEAREST_MIPMAP_LINEAR 0x2702 -#define GL_LINEAR_MIPMAP_LINEAR 0x2703 - -/* TextureParameterName */ -#define GL_TEXTURE_MAG_FILTER 0x2800 -#define GL_TEXTURE_MIN_FILTER 0x2801 -#define GL_TEXTURE_WRAP_S 0x2802 -#define GL_TEXTURE_WRAP_T 0x2803 - -/* TextureTarget */ -/* GL_TEXTURE_2D */ -#define GL_TEXTURE 0x1702 - -#define GL_TEXTURE_CUBE_MAP 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C - -/* TextureUnit */ -#define GL_TEXTURE0 0x84C0 -#define GL_TEXTURE1 0x84C1 -#define GL_TEXTURE2 0x84C2 -#define GL_TEXTURE3 0x84C3 -#define GL_TEXTURE4 0x84C4 -#define GL_TEXTURE5 0x84C5 -#define GL_TEXTURE6 0x84C6 -#define GL_TEXTURE7 0x84C7 -#define GL_TEXTURE8 0x84C8 -#define GL_TEXTURE9 0x84C9 -#define GL_TEXTURE10 0x84CA -#define GL_TEXTURE11 0x84CB -#define GL_TEXTURE12 0x84CC -#define GL_TEXTURE13 0x84CD -#define GL_TEXTURE14 0x84CE -#define GL_TEXTURE15 0x84CF -#define GL_TEXTURE16 0x84D0 -#define GL_TEXTURE17 0x84D1 -#define GL_TEXTURE18 0x84D2 -#define GL_TEXTURE19 0x84D3 -#define GL_TEXTURE20 0x84D4 -#define GL_TEXTURE21 0x84D5 -#define GL_TEXTURE22 0x84D6 -#define GL_TEXTURE23 0x84D7 -#define GL_TEXTURE24 0x84D8 -#define GL_TEXTURE25 0x84D9 -#define GL_TEXTURE26 0x84DA -#define GL_TEXTURE27 0x84DB -#define GL_TEXTURE28 0x84DC -#define GL_TEXTURE29 0x84DD -#define GL_TEXTURE30 0x84DE -#define GL_TEXTURE31 0x84DF -#define GL_ACTIVE_TEXTURE 0x84E0 - -/* TextureWrapMode */ -#define GL_REPEAT 0x2901 -#define GL_CLAMP_TO_EDGE 0x812F -#define GL_MIRRORED_REPEAT 0x8370 - -/* Uniform Types */ -#define GL_FLOAT_VEC2 0x8B50 -#define GL_FLOAT_VEC3 0x8B51 -#define GL_FLOAT_VEC4 0x8B52 -#define GL_INT_VEC2 0x8B53 -#define GL_INT_VEC3 0x8B54 -#define GL_INT_VEC4 0x8B55 -#define GL_BOOL 0x8B56 -#define GL_BOOL_VEC2 0x8B57 -#define GL_BOOL_VEC3 0x8B58 -#define GL_BOOL_VEC4 0x8B59 -#define GL_FLOAT_MAT2 0x8B5A -#define GL_FLOAT_MAT3 0x8B5B -#define GL_FLOAT_MAT4 0x8B5C -#define GL_SAMPLER_2D 0x8B5E -#define GL_SAMPLER_CUBE 0x8B60 - -/* Vertex Arrays */ -#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 -#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 -#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 -#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 -#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A -#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 -#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F - -/* Read Format */ -#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A -#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B - -/* Shader Source */ -#define GL_COMPILE_STATUS 0x8B81 -#define GL_INFO_LOG_LENGTH 0x8B84 -#define GL_SHADER_SOURCE_LENGTH 0x8B88 -#define GL_SHADER_COMPILER 0x8DFA - -/* Shader Binary */ -#define GL_SHADER_BINARY_FORMATS 0x8DF8 -#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 - -/* Shader Precision-Specified Types */ -#define GL_LOW_FLOAT 0x8DF0 -#define GL_MEDIUM_FLOAT 0x8DF1 -#define GL_HIGH_FLOAT 0x8DF2 -#define GL_LOW_INT 0x8DF3 -#define GL_MEDIUM_INT 0x8DF4 -#define GL_HIGH_INT 0x8DF5 - -/* Framebuffer Object. */ -#define GL_FRAMEBUFFER 0x8D40 -#define GL_RENDERBUFFER 0x8D41 - -#define GL_RGBA4 0x8056 -#define GL_RGB5_A1 0x8057 -#define GL_RGB565 0x8D62 -#define GL_DEPTH_COMPONENT16 0x81A5 -#define GL_STENCIL_INDEX8 0x8D48 - -#define GL_RENDERBUFFER_WIDTH 0x8D42 -#define GL_RENDERBUFFER_HEIGHT 0x8D43 -#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 -#define GL_RENDERBUFFER_RED_SIZE 0x8D50 -#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 -#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 -#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 -#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 -#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 - -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 - -#define GL_COLOR_ATTACHMENT0 0x8CE0 -#define GL_DEPTH_ATTACHMENT 0x8D00 -#define GL_STENCIL_ATTACHMENT 0x8D20 - -#define GL_NONE 0 - -#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 -#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 -#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD - -#define GL_FRAMEBUFFER_BINDING 0x8CA6 -#define GL_RENDERBUFFER_BINDING 0x8CA7 -#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 - -#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 - -/*------------------------------------------------------------------------- - * GL core functions. - *-----------------------------------------------------------------------*/ - -GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture); -GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader); -GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name); -GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); -GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); -GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); -GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); -GL_APICALL void GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -GL_APICALL void GL_APIENTRY glBlendEquation ( GLenum mode ); -GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); -GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); -GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); -GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); -GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target); -GL_APICALL void GL_APIENTRY glClear (GLbitfield mask); -GL_APICALL void GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -GL_APICALL void GL_APIENTRY glClearDepthf (GLclampf depth); -GL_APICALL void GL_APIENTRY glClearStencil (GLint s); -GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader); -GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data); -GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data); -GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL GLuint GL_APIENTRY glCreateProgram (void); -GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type); -GL_APICALL void GL_APIENTRY glCullFace (GLenum mode); -GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers); -GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers); -GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program); -GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers); -GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader); -GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures); -GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func); -GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag); -GL_APICALL void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar); -GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader); -GL_APICALL void GL_APIENTRY glDisable (GLenum cap); -GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index); -GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); -GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices); -GL_APICALL void GL_APIENTRY glEnable (GLenum cap); -GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index); -GL_APICALL void GL_APIENTRY glFinish (void); -GL_APICALL void GL_APIENTRY glFlush (void); -GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode); -GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers); -GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target); -GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers); -GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers); -GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures); -GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); -GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); -GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); -GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name); -GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params); -GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params); -GL_APICALL GLenum GL_APIENTRY glGetError (void); -GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params); -GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog); -GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog); -GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); -GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source); -GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name); -GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params); -GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params); -GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params); -GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name); -GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params); -GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer); -GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode); -GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer); -GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap); -GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer); -GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program); -GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer); -GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader); -GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture); -GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width); -GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program); -GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); -GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); -GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void); -GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert); -GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length); -GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length); -GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask); -GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); -GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass); -GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels); -GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); -GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params); -GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params); -GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels); -GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x); -GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v); -GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x); -GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v); -GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y); -GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v); -GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y); -GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v); -GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z); -GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v); -GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z); -GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v); -GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v); -GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w); -GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v); -GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUseProgram (GLuint program); -GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program); -GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x); -GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values); -GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y); -GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values); -GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z); -GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values); -GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values); -GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr); -GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); - -#ifdef __cplusplus -} -#endif - -#endif /* __gl2_h_ */ diff --git a/platform/winrt/include/GLES2/gl2ext.h b/platform/winrt/include/GLES2/gl2ext.h deleted file mode 100644 index d5a9dd195b..0000000000 --- a/platform/winrt/include/GLES2/gl2ext.h +++ /dev/null @@ -1,2013 +0,0 @@ -#ifndef __gl2ext_h_ -#define __gl2ext_h_ - -/* $Revision: 20795 $ on $Date:: 2013-03-07 01:01:58 -0800 #$ */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * This document is licensed under the SGI Free Software B License Version - * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . - */ - -#ifndef GL_APIENTRYP -# define GL_APIENTRYP GL_APIENTRY* -#endif - -/*------------------------------------------------------------------------* - * OES extension tokens - *------------------------------------------------------------------------*/ - -/* GL_OES_compressed_ETC1_RGB8_texture */ -#ifndef GL_OES_compressed_ETC1_RGB8_texture -#define GL_ETC1_RGB8_OES 0x8D64 -#endif - -/* GL_OES_compressed_paletted_texture */ -#ifndef GL_OES_compressed_paletted_texture -#define GL_PALETTE4_RGB8_OES 0x8B90 -#define GL_PALETTE4_RGBA8_OES 0x8B91 -#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 -#define GL_PALETTE4_RGBA4_OES 0x8B93 -#define GL_PALETTE4_RGB5_A1_OES 0x8B94 -#define GL_PALETTE8_RGB8_OES 0x8B95 -#define GL_PALETTE8_RGBA8_OES 0x8B96 -#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 -#define GL_PALETTE8_RGBA4_OES 0x8B98 -#define GL_PALETTE8_RGB5_A1_OES 0x8B99 -#endif - -/* GL_OES_depth24 */ -#ifndef GL_OES_depth24 -#define GL_DEPTH_COMPONENT24_OES 0x81A6 -#endif - -/* GL_OES_depth32 */ -#ifndef GL_OES_depth32 -#define GL_DEPTH_COMPONENT32_OES 0x81A7 -#endif - -/* GL_OES_depth_texture */ -/* No new tokens introduced by this extension. */ - -/* GL_OES_EGL_image */ -#ifndef GL_OES_EGL_image -typedef void* GLeglImageOES; -#endif - -/* GL_OES_EGL_image_external */ -#ifndef GL_OES_EGL_image_external -/* GLeglImageOES defined in GL_OES_EGL_image already. */ -#define GL_TEXTURE_EXTERNAL_OES 0x8D65 -#define GL_SAMPLER_EXTERNAL_OES 0x8D66 -#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67 -#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68 -#endif - -/* GL_OES_element_index_uint */ -#ifndef GL_OES_element_index_uint -#define GL_UNSIGNED_INT 0x1405 -#endif - -/* GL_OES_get_program_binary */ -#ifndef GL_OES_get_program_binary -#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741 -#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE -#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF -#endif - -/* GL_OES_mapbuffer */ -#ifndef GL_OES_mapbuffer -#define GL_WRITE_ONLY_OES 0x88B9 -#define GL_BUFFER_ACCESS_OES 0x88BB -#define GL_BUFFER_MAPPED_OES 0x88BC -#define GL_BUFFER_MAP_POINTER_OES 0x88BD -#endif - -/* GL_OES_packed_depth_stencil */ -#ifndef GL_OES_packed_depth_stencil -#define GL_DEPTH_STENCIL_OES 0x84F9 -#define GL_UNSIGNED_INT_24_8_OES 0x84FA -#define GL_DEPTH24_STENCIL8_OES 0x88F0 -#endif - -/* GL_OES_required_internalformat */ -#ifndef GL_OES_required_internalformat -#define GL_ALPHA8_OES 0x803C -#define GL_DEPTH_COMPONENT16_OES 0x81A5 -/* reuse GL_DEPTH_COMPONENT24_OES */ -/* reuse GL_DEPTH24_STENCIL8_OES */ -/* reuse GL_DEPTH_COMPONENT32_OES */ -#define GL_LUMINANCE4_ALPHA4_OES 0x8043 -#define GL_LUMINANCE8_ALPHA8_OES 0x8045 -#define GL_LUMINANCE8_OES 0x8040 -#define GL_RGBA4_OES 0x8056 -#define GL_RGB5_A1_OES 0x8057 -#define GL_RGB565_OES 0x8D62 -/* reuse GL_RGB8_OES */ -/* reuse GL_RGBA8_OES */ -/* reuse GL_RGB10_EXT */ -/* reuse GL_RGB10_A2_EXT */ -#endif - -/* GL_OES_rgb8_rgba8 */ -#ifndef GL_OES_rgb8_rgba8 -#define GL_RGB8_OES 0x8051 -#define GL_RGBA8_OES 0x8058 -#endif - -/* GL_OES_standard_derivatives */ -#ifndef GL_OES_standard_derivatives -#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B -#endif - -/* GL_OES_stencil1 */ -#ifndef GL_OES_stencil1 -#define GL_STENCIL_INDEX1_OES 0x8D46 -#endif - -/* GL_OES_stencil4 */ -#ifndef GL_OES_stencil4 -#define GL_STENCIL_INDEX4_OES 0x8D47 -#endif - -#ifndef GL_OES_surfaceless_context -#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219 -#endif - -/* GL_OES_texture_3D */ -#ifndef GL_OES_texture_3D -#define GL_TEXTURE_WRAP_R_OES 0x8072 -#define GL_TEXTURE_3D_OES 0x806F -#define GL_TEXTURE_BINDING_3D_OES 0x806A -#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073 -#define GL_SAMPLER_3D_OES 0x8B5F -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4 -#endif - -/* GL_OES_texture_float */ -/* No new tokens introduced by this extension. */ - -/* GL_OES_texture_float_linear */ -/* No new tokens introduced by this extension. */ - -/* GL_OES_texture_half_float */ -#ifndef GL_OES_texture_half_float -#define GL_HALF_FLOAT_OES 0x8D61 -#endif - -/* GL_OES_texture_half_float_linear */ -/* No new tokens introduced by this extension. */ - -/* GL_OES_texture_npot */ -/* No new tokens introduced by this extension. */ - -/* GL_OES_vertex_array_object */ -#ifndef GL_OES_vertex_array_object -#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5 -#endif - -/* GL_OES_vertex_half_float */ -/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */ - -/* GL_OES_vertex_type_10_10_10_2 */ -#ifndef GL_OES_vertex_type_10_10_10_2 -#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6 -#define GL_INT_10_10_10_2_OES 0x8DF7 -#endif - -/*------------------------------------------------------------------------* - * KHR extension tokens - *------------------------------------------------------------------------*/ - -#ifndef GL_KHR_debug -typedef void (GL_APIENTRYP GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam); -#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 -#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 -#define GL_DEBUG_CALLBACK_FUNCTION 0x8244 -#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245 -#define GL_DEBUG_SOURCE_API 0x8246 -#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 -#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 -#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 -#define GL_DEBUG_SOURCE_APPLICATION 0x824A -#define GL_DEBUG_SOURCE_OTHER 0x824B -#define GL_DEBUG_TYPE_ERROR 0x824C -#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D -#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E -#define GL_DEBUG_TYPE_PORTABILITY 0x824F -#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 -#define GL_DEBUG_TYPE_OTHER 0x8251 -#define GL_DEBUG_TYPE_MARKER 0x8268 -#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 -#define GL_DEBUG_TYPE_POP_GROUP 0x826A -#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B -#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C -#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D -#define GL_BUFFER 0x82E0 -#define GL_SHADER 0x82E1 -#define GL_PROGRAM 0x82E2 -#define GL_QUERY 0x82E3 -/* PROGRAM_PIPELINE only in GL */ -#define GL_SAMPLER 0x82E6 -/* DISPLAY_LIST only in GL */ -#define GL_MAX_LABEL_LENGTH 0x82E8 -#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143 -#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144 -#define GL_DEBUG_LOGGED_MESSAGES 0x9145 -#define GL_DEBUG_SEVERITY_HIGH 0x9146 -#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 -#define GL_DEBUG_SEVERITY_LOW 0x9148 -#define GL_DEBUG_OUTPUT 0x92E0 -#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 -#define GL_STACK_OVERFLOW 0x0503 -#define GL_STACK_UNDERFLOW 0x0504 -#endif - -#ifndef GL_KHR_texture_compression_astc_ldr -#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 -#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 -#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 -#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 -#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 -#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 -#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 -#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 -#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 -#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 -#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA -#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB -#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC -#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD -#endif - -/*------------------------------------------------------------------------* - * AMD extension tokens - *------------------------------------------------------------------------*/ - -/* GL_AMD_compressed_3DC_texture */ -#ifndef GL_AMD_compressed_3DC_texture -#define GL_3DC_X_AMD 0x87F9 -#define GL_3DC_XY_AMD 0x87FA -#endif - -/* GL_AMD_compressed_ATC_texture */ -#ifndef GL_AMD_compressed_ATC_texture -#define GL_ATC_RGB_AMD 0x8C92 -#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93 -#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE -#endif - -/* GL_AMD_performance_monitor */ -#ifndef GL_AMD_performance_monitor -#define GL_COUNTER_TYPE_AMD 0x8BC0 -#define GL_COUNTER_RANGE_AMD 0x8BC1 -#define GL_UNSIGNED_INT64_AMD 0x8BC2 -#define GL_PERCENTAGE_AMD 0x8BC3 -#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 -#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5 -#define GL_PERFMON_RESULT_AMD 0x8BC6 -#endif - -/* GL_AMD_program_binary_Z400 */ -#ifndef GL_AMD_program_binary_Z400 -#define GL_Z400_BINARY_AMD 0x8740 -#endif - -/*------------------------------------------------------------------------* - * ANGLE extension tokens - *------------------------------------------------------------------------*/ - -/* GL_ANGLE_depth_texture */ -#ifndef GL_ANGLE_depth_texture -#define GL_DEPTH_COMPONENT 0x1902 -#define GL_DEPTH_STENCIL_OES 0x84F9 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_UNSIGNED_INT 0x1405 -#define GL_UNSIGNED_INT_24_8_OES 0x84FA -#define GL_DEPTH_COMPONENT16 0x81A5 -#define GL_DEPTH_COMPONENT32_OES 0x81A7 -#define GL_DEPTH24_STENCIL8_OES 0x88F0 -#endif - -/* GL_ANGLE_framebuffer_blit */ -#ifndef GL_ANGLE_framebuffer_blit -#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8 -#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9 -#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6 -#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA -#endif - -/* GL_ANGLE_framebuffer_multisample */ -#ifndef GL_ANGLE_framebuffer_multisample -#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56 -#define GL_MAX_SAMPLES_ANGLE 0x8D57 -#endif - -/* GL_ANGLE_instanced_arrays */ -#ifndef GL_ANGLE_instanced_arrays -#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE -#endif - -/* GL_ANGLE_pack_reverse_row_order */ -#ifndef GL_ANGLE_pack_reverse_row_order -#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4 -#endif - -/* GL_ANGLE_program_binary */ -#ifndef GL_ANGLE_program_binary -#define GL_PROGRAM_BINARY_ANGLE 0x93A6 -#endif - -/* GL_ANGLE_texture_compression_dxt3 */ -#ifndef GL_ANGLE_texture_compression_dxt3 -#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2 -#endif - -/* GL_ANGLE_texture_compression_dxt5 */ -#ifndef GL_ANGLE_texture_compression_dxt5 -#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3 -#endif - -/* GL_ANGLE_texture_usage */ -#ifndef GL_ANGLE_texture_usage -#define GL_TEXTURE_USAGE_ANGLE 0x93A2 -#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3 -#endif - -/* GL_ANGLE_translated_shader_source */ -#ifndef GL_ANGLE_translated_shader_source -#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0 -#endif - -/*------------------------------------------------------------------------* - * APPLE extension tokens - *------------------------------------------------------------------------*/ - -/* GL_APPLE_copy_texture_levels */ -/* No new tokens introduced by this extension. */ - -/* GL_APPLE_framebuffer_multisample */ -#ifndef GL_APPLE_framebuffer_multisample -#define GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56 -#define GL_MAX_SAMPLES_APPLE 0x8D57 -#define GL_READ_FRAMEBUFFER_APPLE 0x8CA8 -#define GL_DRAW_FRAMEBUFFER_APPLE 0x8CA9 -#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6 -#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA -#endif - -/* GL_APPLE_rgb_422 */ -#ifndef GL_APPLE_rgb_422 -#define GL_RGB_422_APPLE 0x8A1F -#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA -#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB -#endif - -/* GL_APPLE_sync */ -#ifndef GL_APPLE_sync - -#ifndef __gl3_h_ -/* These types are defined with reference to <inttypes.h> - * in the Apple extension spec, but here we use the Khronos - * portable types in khrplatform.h, and assume those types - * are always defined. - * If any other extensions using these types are defined, - * the typedefs must move out of this block and be shared. - */ -typedef khronos_int64_t GLint64; -typedef khronos_uint64_t GLuint64; -typedef struct __GLsync *GLsync; -#endif - -#define GL_SYNC_OBJECT_APPLE 0x8A53 -#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE 0x9111 -#define GL_OBJECT_TYPE_APPLE 0x9112 -#define GL_SYNC_CONDITION_APPLE 0x9113 -#define GL_SYNC_STATUS_APPLE 0x9114 -#define GL_SYNC_FLAGS_APPLE 0x9115 -#define GL_SYNC_FENCE_APPLE 0x9116 -#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE 0x9117 -#define GL_UNSIGNALED_APPLE 0x9118 -#define GL_SIGNALED_APPLE 0x9119 -#define GL_ALREADY_SIGNALED_APPLE 0x911A -#define GL_TIMEOUT_EXPIRED_APPLE 0x911B -#define GL_CONDITION_SATISFIED_APPLE 0x911C -#define GL_WAIT_FAILED_APPLE 0x911D -#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE 0x00000001 -#define GL_TIMEOUT_IGNORED_APPLE 0xFFFFFFFFFFFFFFFFull -#endif - -/* GL_APPLE_texture_format_BGRA8888 */ -#ifndef GL_APPLE_texture_format_BGRA8888 -#define GL_BGRA_EXT 0x80E1 -#endif - -/* GL_APPLE_texture_max_level */ -#ifndef GL_APPLE_texture_max_level -#define GL_TEXTURE_MAX_LEVEL_APPLE 0x813D -#endif - -/*------------------------------------------------------------------------* - * ARM extension tokens - *------------------------------------------------------------------------*/ - -/* GL_ARM_mali_program_binary */ -#ifndef GL_ARM_mali_program_binary -#define GL_MALI_PROGRAM_BINARY_ARM 0x8F61 -#endif - -/* GL_ARM_mali_shader_binary */ -#ifndef GL_ARM_mali_shader_binary -#define GL_MALI_SHADER_BINARY_ARM 0x8F60 -#endif - -/* GL_ARM_rgba8 */ -/* No new tokens introduced by this extension. */ - -/*------------------------------------------------------------------------* - * EXT extension tokens - *------------------------------------------------------------------------*/ - -/* GL_EXT_blend_minmax */ -#ifndef GL_EXT_blend_minmax -#define GL_MIN_EXT 0x8007 -#define GL_MAX_EXT 0x8008 -#endif - -/* GL_EXT_color_buffer_half_float */ -#ifndef GL_EXT_color_buffer_half_float -#define GL_RGBA16F_EXT 0x881A -#define GL_RGB16F_EXT 0x881B -#define GL_RG16F_EXT 0x822F -#define GL_R16F_EXT 0x822D -#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211 -#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17 -#endif - -/* GL_EXT_debug_label */ -#ifndef GL_EXT_debug_label -#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F -#define GL_PROGRAM_OBJECT_EXT 0x8B40 -#define GL_SHADER_OBJECT_EXT 0x8B48 -#define GL_BUFFER_OBJECT_EXT 0x9151 -#define GL_QUERY_OBJECT_EXT 0x9153 -#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154 -#endif - -/* GL_EXT_debug_marker */ -/* No new tokens introduced by this extension. */ - -/* GL_EXT_discard_framebuffer */ -#ifndef GL_EXT_discard_framebuffer -#define GL_COLOR_EXT 0x1800 -#define GL_DEPTH_EXT 0x1801 -#define GL_STENCIL_EXT 0x1802 -#endif - -/* GL_EXT_map_buffer_range */ -#ifndef GL_EXT_map_buffer_range -#define GL_MAP_READ_BIT_EXT 0x0001 -#define GL_MAP_WRITE_BIT_EXT 0x0002 -#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004 -#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008 -#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010 -#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020 -#endif - -/* GL_EXT_multisampled_render_to_texture */ -#ifndef GL_EXT_multisampled_render_to_texture -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C -/* reuse values from GL_EXT_framebuffer_multisample (desktop extension) */ -#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 -#define GL_MAX_SAMPLES_EXT 0x8D57 -#endif - -/* GL_EXT_multiview_draw_buffers */ -#ifndef GL_EXT_multiview_draw_buffers -#define GL_COLOR_ATTACHMENT_EXT 0x90F0 -#define GL_MULTIVIEW_EXT 0x90F1 -#define GL_DRAW_BUFFER_EXT 0x0C01 -#define GL_READ_BUFFER_EXT 0x0C02 -#define GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2 -#endif - -/* GL_EXT_multi_draw_arrays */ -/* No new tokens introduced by this extension. */ - -/* GL_EXT_occlusion_query_boolean */ -#ifndef GL_EXT_occlusion_query_boolean -#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F -#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A -#define GL_CURRENT_QUERY_EXT 0x8865 -#define GL_QUERY_RESULT_EXT 0x8866 -#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867 -#endif - -/* GL_EXT_read_format_bgra */ -#ifndef GL_EXT_read_format_bgra -#define GL_BGRA_EXT 0x80E1 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365 -#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366 -#endif - -/* GL_EXT_robustness */ -#ifndef GL_EXT_robustness -/* reuse GL_NO_ERROR */ -#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253 -#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254 -#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255 -#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3 -#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256 -#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252 -#define GL_NO_RESET_NOTIFICATION_EXT 0x8261 -#endif - -/* GL_EXT_separate_shader_objects */ -#ifndef GL_EXT_separate_shader_objects -#define GL_VERTEX_SHADER_BIT_EXT 0x00000001 -#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002 -#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF -#define GL_PROGRAM_SEPARABLE_EXT 0x8258 -#define GL_ACTIVE_PROGRAM_EXT 0x8259 -#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A -#endif - -/* GL_EXT_shader_framebuffer_fetch */ -#ifndef GL_EXT_shader_framebuffer_fetch -#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52 -#endif - -/* GL_EXT_shader_texture_lod */ -/* No new tokens introduced by this extension. */ - -/* GL_EXT_shadow_samplers */ -#ifndef GL_EXT_shadow_samplers -#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C -#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D -#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E -#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62 -#endif - -/* GL_EXT_sRGB */ -#ifndef GL_EXT_sRGB -#define GL_SRGB_EXT 0x8C40 -#define GL_SRGB_ALPHA_EXT 0x8C42 -#define GL_SRGB8_ALPHA8_EXT 0x8C43 -#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210 -#endif - -/* GL_EXT_texture_compression_dxt1 */ -#ifndef GL_EXT_texture_compression_dxt1 -#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 -#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#endif - -/* GL_EXT_texture_filter_anisotropic */ -#ifndef GL_EXT_texture_filter_anisotropic -#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF -#endif - -/* GL_EXT_texture_format_BGRA8888 */ -#ifndef GL_EXT_texture_format_BGRA8888 -#define GL_BGRA_EXT 0x80E1 -#endif - -/* GL_EXT_texture_rg */ -#ifndef GL_EXT_texture_rg -#define GL_RED_EXT 0x1903 -#define GL_RG_EXT 0x8227 -#define GL_R8_EXT 0x8229 -#define GL_RG8_EXT 0x822B -#endif - -/* GL_EXT_texture_storage */ -#ifndef GL_EXT_texture_storage -#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F -#define GL_ALPHA8_EXT 0x803C -#define GL_LUMINANCE8_EXT 0x8040 -#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 -#define GL_RGBA32F_EXT 0x8814 -#define GL_RGB32F_EXT 0x8815 -#define GL_ALPHA32F_EXT 0x8816 -#define GL_LUMINANCE32F_EXT 0x8818 -#define GL_LUMINANCE_ALPHA32F_EXT 0x8819 -/* reuse GL_RGBA16F_EXT */ -/* reuse GL_RGB16F_EXT */ -#define GL_ALPHA16F_EXT 0x881C -#define GL_LUMINANCE16F_EXT 0x881E -#define GL_LUMINANCE_ALPHA16F_EXT 0x881F -#define GL_RGB10_A2_EXT 0x8059 -#define GL_RGB10_EXT 0x8052 -#define GL_BGRA8_EXT 0x93A1 -#define GL_R8_EXT 0x8229 -#define GL_RG8_EXT 0x822B -#define GL_R32F_EXT 0x822E -#define GL_RG32F_EXT 0x8230 -#define GL_R16F_EXT 0x822D -#define GL_RG16F_EXT 0x822F -#endif - -/* GL_EXT_texture_type_2_10_10_10_REV */ -#ifndef GL_EXT_texture_type_2_10_10_10_REV -#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368 -#endif - -/* GL_EXT_unpack_subimage */ -#ifndef GL_EXT_unpack_subimage -#define GL_UNPACK_ROW_LENGTH_EXT 0x0CF2 -#define GL_UNPACK_SKIP_ROWS_EXT 0x0CF3 -#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4 -#endif - -/*------------------------------------------------------------------------* - * DMP extension tokens - *------------------------------------------------------------------------*/ - -/* GL_DMP_shader_binary */ -#ifndef GL_DMP_shader_binary -#define GL_SHADER_BINARY_DMP 0x9250 -#endif - -/*------------------------------------------------------------------------* - * FJ extension tokens - *------------------------------------------------------------------------*/ - -/* GL_FJ_shader_binary_GCCSO */ -#ifndef GL_FJ_shader_binary_GCCSO -#define GL_GCCSO_SHADER_BINARY_F 0x9260 -#endif - -/*------------------------------------------------------------------------* - * IMG extension tokens - *------------------------------------------------------------------------*/ - -/* GL_IMG_program_binary */ -#ifndef GL_IMG_program_binary -#define GL_SGX_PROGRAM_BINARY_IMG 0x9130 -#endif - -/* GL_IMG_read_format */ -#ifndef GL_IMG_read_format -#define GL_BGRA_IMG 0x80E1 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365 -#endif - -/* GL_IMG_shader_binary */ -#ifndef GL_IMG_shader_binary -#define GL_SGX_BINARY_IMG 0x8C0A -#endif - -/* GL_IMG_texture_compression_pvrtc */ -#ifndef GL_IMG_texture_compression_pvrtc -#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 -#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 -#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 -#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 -#endif - -/* GL_IMG_texture_compression_pvrtc2 */ -#ifndef GL_IMG_texture_compression_pvrtc2 -#define GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137 -#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138 -#endif - -/* GL_IMG_multisampled_render_to_texture */ -#ifndef GL_IMG_multisampled_render_to_texture -#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133 -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134 -#define GL_MAX_SAMPLES_IMG 0x9135 -#define GL_TEXTURE_SAMPLES_IMG 0x9136 -#endif - -/*------------------------------------------------------------------------* - * NV extension tokens - *------------------------------------------------------------------------*/ - -/* GL_NV_coverage_sample */ -#ifndef GL_NV_coverage_sample -#define GL_COVERAGE_COMPONENT_NV 0x8ED0 -#define GL_COVERAGE_COMPONENT4_NV 0x8ED1 -#define GL_COVERAGE_ATTACHMENT_NV 0x8ED2 -#define GL_COVERAGE_BUFFERS_NV 0x8ED3 -#define GL_COVERAGE_SAMPLES_NV 0x8ED4 -#define GL_COVERAGE_ALL_FRAGMENTS_NV 0x8ED5 -#define GL_COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6 -#define GL_COVERAGE_AUTOMATIC_NV 0x8ED7 -#define GL_COVERAGE_BUFFER_BIT_NV 0x8000 -#endif - -/* GL_NV_depth_nonlinear */ -#ifndef GL_NV_depth_nonlinear -#define GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C -#endif - -/* GL_NV_draw_buffers */ -#ifndef GL_NV_draw_buffers -#define GL_MAX_DRAW_BUFFERS_NV 0x8824 -#define GL_DRAW_BUFFER0_NV 0x8825 -#define GL_DRAW_BUFFER1_NV 0x8826 -#define GL_DRAW_BUFFER2_NV 0x8827 -#define GL_DRAW_BUFFER3_NV 0x8828 -#define GL_DRAW_BUFFER4_NV 0x8829 -#define GL_DRAW_BUFFER5_NV 0x882A -#define GL_DRAW_BUFFER6_NV 0x882B -#define GL_DRAW_BUFFER7_NV 0x882C -#define GL_DRAW_BUFFER8_NV 0x882D -#define GL_DRAW_BUFFER9_NV 0x882E -#define GL_DRAW_BUFFER10_NV 0x882F -#define GL_DRAW_BUFFER11_NV 0x8830 -#define GL_DRAW_BUFFER12_NV 0x8831 -#define GL_DRAW_BUFFER13_NV 0x8832 -#define GL_DRAW_BUFFER14_NV 0x8833 -#define GL_DRAW_BUFFER15_NV 0x8834 -#define GL_COLOR_ATTACHMENT0_NV 0x8CE0 -#define GL_COLOR_ATTACHMENT1_NV 0x8CE1 -#define GL_COLOR_ATTACHMENT2_NV 0x8CE2 -#define GL_COLOR_ATTACHMENT3_NV 0x8CE3 -#define GL_COLOR_ATTACHMENT4_NV 0x8CE4 -#define GL_COLOR_ATTACHMENT5_NV 0x8CE5 -#define GL_COLOR_ATTACHMENT6_NV 0x8CE6 -#define GL_COLOR_ATTACHMENT7_NV 0x8CE7 -#define GL_COLOR_ATTACHMENT8_NV 0x8CE8 -#define GL_COLOR_ATTACHMENT9_NV 0x8CE9 -#define GL_COLOR_ATTACHMENT10_NV 0x8CEA -#define GL_COLOR_ATTACHMENT11_NV 0x8CEB -#define GL_COLOR_ATTACHMENT12_NV 0x8CEC -#define GL_COLOR_ATTACHMENT13_NV 0x8CED -#define GL_COLOR_ATTACHMENT14_NV 0x8CEE -#define GL_COLOR_ATTACHMENT15_NV 0x8CEF -#endif - -/* GL_EXT_draw_buffers */ -#ifndef GL_EXT_draw_buffers -#define GL_MAX_DRAW_BUFFERS_EXT 0x8824 -#define GL_DRAW_BUFFER0_EXT 0x8825 -#define GL_DRAW_BUFFER1_EXT 0x8826 -#define GL_DRAW_BUFFER2_EXT 0x8827 -#define GL_DRAW_BUFFER3_EXT 0x8828 -#define GL_DRAW_BUFFER4_EXT 0x8829 -#define GL_DRAW_BUFFER5_EXT 0x882A -#define GL_DRAW_BUFFER6_EXT 0x882B -#define GL_DRAW_BUFFER7_EXT 0x882C -#define GL_DRAW_BUFFER8_EXT 0x882D -#define GL_DRAW_BUFFER9_EXT 0x882E -#define GL_DRAW_BUFFER10_EXT 0x882F -#define GL_DRAW_BUFFER11_EXT 0x8830 -#define GL_DRAW_BUFFER12_EXT 0x8831 -#define GL_DRAW_BUFFER13_EXT 0x8832 -#define GL_DRAW_BUFFER14_EXT 0x8833 -#define GL_DRAW_BUFFER15_EXT 0x8834 -#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 -#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 -#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 -#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 -#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 -#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 -#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 -#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 -#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 -#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 -#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA -#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB -#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC -#define GL_COLOR_ATTACHMENT13_EXT 0x8CED -#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE -#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF -#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF -#endif - -/* GL_NV_draw_instanced */ -/* No new tokens introduced by this extension. */ - -/* GL_NV_fbo_color_attachments */ -#ifndef GL_NV_fbo_color_attachments -#define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF -/* GL_COLOR_ATTACHMENT{0-15}_NV defined in GL_NV_draw_buffers already. */ -#endif - -/* GL_NV_fence */ -#ifndef GL_NV_fence -#define GL_ALL_COMPLETED_NV 0x84F2 -#define GL_FENCE_STATUS_NV 0x84F3 -#define GL_FENCE_CONDITION_NV 0x84F4 -#endif - -/* GL_NV_framebuffer_blit */ -#ifndef GL_NV_framebuffer_blit -#define GL_READ_FRAMEBUFFER_NV 0x8CA8 -#define GL_DRAW_FRAMEBUFFER_NV 0x8CA9 -#define GL_DRAW_FRAMEBUFFER_BINDING_NV 0x8CA6 -#define GL_READ_FRAMEBUFFER_BINDING_NV 0x8CAA -#endif - -/* GL_NV_framebuffer_multisample */ -#ifndef GL_NV_framebuffer_multisample -#define GL_RENDERBUFFER_SAMPLES_NV 0x8CAB -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV 0x8D56 -#define GL_MAX_SAMPLES_NV 0x8D57 -#endif - -/* GL_NV_generate_mipmap_sRGB */ -/* No new tokens introduced by this extension. */ - -/* GL_NV_instanced_arrays */ -#ifndef GL_NV_instanced_arrays -#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE -#endif - -/* GL_NV_read_buffer */ -#ifndef GL_NV_read_buffer -#define GL_READ_BUFFER_NV 0x0C02 -#endif - -/* GL_NV_read_buffer_front */ -/* No new tokens introduced by this extension. */ - -/* GL_NV_read_depth */ -/* No new tokens introduced by this extension. */ - -/* GL_NV_read_depth_stencil */ -/* No new tokens introduced by this extension. */ - -/* GL_NV_read_stencil */ -/* No new tokens introduced by this extension. */ - -/* GL_NV_shadow_samplers_array */ -#ifndef GL_NV_shadow_samplers_array -#define GL_SAMPLER_2D_ARRAY_SHADOW_NV 0x8DC4 -#endif - -/* GL_NV_shadow_samplers_cube */ -#ifndef GL_NV_shadow_samplers_cube -#define GL_SAMPLER_CUBE_SHADOW_NV 0x8DC5 -#endif - -/* GL_NV_sRGB_formats */ -#ifndef GL_NV_sRGB_formats -#define GL_SLUMINANCE_NV 0x8C46 -#define GL_SLUMINANCE_ALPHA_NV 0x8C44 -#define GL_SRGB8_NV 0x8C41 -#define GL_SLUMINANCE8_NV 0x8C47 -#define GL_SLUMINANCE8_ALPHA8_NV 0x8C45 -#define GL_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F -#define GL_ETC1_SRGB8_NV 0x88EE -#endif - -/* GL_NV_texture_border_clamp */ -#ifndef GL_NV_texture_border_clamp -#define GL_TEXTURE_BORDER_COLOR_NV 0x1004 -#define GL_CLAMP_TO_BORDER_NV 0x812D -#endif - -/* GL_NV_texture_compression_s3tc_update */ -/* No new tokens introduced by this extension. */ - -/* GL_NV_texture_npot_2D_mipmap */ -/* No new tokens introduced by this extension. */ - -/*------------------------------------------------------------------------* - * QCOM extension tokens - *------------------------------------------------------------------------*/ - -/* GL_QCOM_alpha_test */ -#ifndef GL_QCOM_alpha_test -#define GL_ALPHA_TEST_QCOM 0x0BC0 -#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 -#define GL_ALPHA_TEST_REF_QCOM 0x0BC2 -#endif - -/* GL_QCOM_binning_control */ -#ifndef GL_QCOM_binning_control -#define GL_BINNING_CONTROL_HINT_QCOM 0x8FB0 -#define GL_CPU_OPTIMIZED_QCOM 0x8FB1 -#define GL_GPU_OPTIMIZED_QCOM 0x8FB2 -#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3 -#endif - -/* GL_QCOM_driver_control */ -/* No new tokens introduced by this extension. */ - -/* GL_QCOM_extended_get */ -#ifndef GL_QCOM_extended_get -#define GL_TEXTURE_WIDTH_QCOM 0x8BD2 -#define GL_TEXTURE_HEIGHT_QCOM 0x8BD3 -#define GL_TEXTURE_DEPTH_QCOM 0x8BD4 -#define GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5 -#define GL_TEXTURE_FORMAT_QCOM 0x8BD6 -#define GL_TEXTURE_TYPE_QCOM 0x8BD7 -#define GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8 -#define GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9 -#define GL_TEXTURE_TARGET_QCOM 0x8BDA -#define GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB -#define GL_STATE_RESTORE 0x8BDC -#endif - -/* GL_QCOM_extended_get2 */ -/* No new tokens introduced by this extension. */ - -/* GL_QCOM_perfmon_global_mode */ -#ifndef GL_QCOM_perfmon_global_mode -#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0 -#endif - -/* GL_QCOM_writeonly_rendering */ -#ifndef GL_QCOM_writeonly_rendering -#define GL_WRITEONLY_RENDERING_QCOM 0x8823 -#endif - -/* GL_QCOM_tiled_rendering */ -#ifndef GL_QCOM_tiled_rendering -#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001 -#define GL_COLOR_BUFFER_BIT1_QCOM 0x00000002 -#define GL_COLOR_BUFFER_BIT2_QCOM 0x00000004 -#define GL_COLOR_BUFFER_BIT3_QCOM 0x00000008 -#define GL_COLOR_BUFFER_BIT4_QCOM 0x00000010 -#define GL_COLOR_BUFFER_BIT5_QCOM 0x00000020 -#define GL_COLOR_BUFFER_BIT6_QCOM 0x00000040 -#define GL_COLOR_BUFFER_BIT7_QCOM 0x00000080 -#define GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100 -#define GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200 -#define GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400 -#define GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800 -#define GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000 -#define GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000 -#define GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000 -#define GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000 -#define GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000 -#define GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000 -#define GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000 -#define GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000 -#define GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000 -#define GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000 -#define GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000 -#define GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000 -#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000 -#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000 -#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000 -#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000 -#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000 -#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000 -#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000 -#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000 -#endif - -/*------------------------------------------------------------------------* - * VIV extension tokens - *------------------------------------------------------------------------*/ - -/* GL_VIV_shader_binary */ -#ifndef GL_VIV_shader_binary -#define GL_SHADER_BINARY_VIV 0x8FC4 -#endif - -/*------------------------------------------------------------------------* - * End of extension tokens, start of corresponding extension functions - *------------------------------------------------------------------------*/ - -/*------------------------------------------------------------------------* - * OES extension functions - *------------------------------------------------------------------------*/ - -/* GL_OES_compressed_ETC1_RGB8_texture */ -#ifndef GL_OES_compressed_ETC1_RGB8_texture -#define GL_OES_compressed_ETC1_RGB8_texture 1 -#endif - -/* GL_OES_compressed_paletted_texture */ -#ifndef GL_OES_compressed_paletted_texture -#define GL_OES_compressed_paletted_texture 1 -#endif - -/* GL_OES_depth24 */ -#ifndef GL_OES_depth24 -#define GL_OES_depth24 1 -#endif - -/* GL_OES_depth32 */ -#ifndef GL_OES_depth32 -#define GL_OES_depth32 1 -#endif - -/* GL_OES_depth_texture */ -#ifndef GL_OES_depth_texture -#define GL_OES_depth_texture 1 -#endif - -/* GL_OES_EGL_image */ -#ifndef GL_OES_EGL_image -#define GL_OES_EGL_image 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image); -GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image); -#endif -typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); -typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); -#endif - -/* GL_OES_EGL_image_external */ -#ifndef GL_OES_EGL_image_external -#define GL_OES_EGL_image_external 1 -/* glEGLImageTargetTexture2DOES defined in GL_OES_EGL_image already. */ -#endif - -/* GL_OES_element_index_uint */ -#ifndef GL_OES_element_index_uint -#define GL_OES_element_index_uint 1 -#endif - -/* GL_OES_fbo_render_mipmap */ -#ifndef GL_OES_fbo_render_mipmap -#define GL_OES_fbo_render_mipmap 1 -#endif - -/* GL_OES_fragment_precision_high */ -#ifndef GL_OES_fragment_precision_high -#define GL_OES_fragment_precision_high 1 -#endif - -/* GL_OES_get_program_binary */ -#ifndef GL_OES_get_program_binary -#define GL_OES_get_program_binary 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary); -GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length); -#endif -typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary); -typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length); -#endif - -/* GL_OES_mapbuffer */ -#ifndef GL_OES_mapbuffer -#define GL_OES_mapbuffer 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access); -GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target); -GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, GLvoid** params); -#endif -typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access); -typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target); -typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, GLvoid** params); -#endif - -/* GL_OES_packed_depth_stencil */ -#ifndef GL_OES_packed_depth_stencil -#define GL_OES_packed_depth_stencil 1 -#endif - -/* GL_OES_required_internalformat */ -#ifndef GL_OES_required_internalformat -#define GL_OES_required_internalformat 1 -#endif - -/* GL_OES_rgb8_rgba8 */ -#ifndef GL_OES_rgb8_rgba8 -#define GL_OES_rgb8_rgba8 1 -#endif - -/* GL_OES_standard_derivatives */ -#ifndef GL_OES_standard_derivatives -#define GL_OES_standard_derivatives 1 -#endif - -/* GL_OES_stencil1 */ -#ifndef GL_OES_stencil1 -#define GL_OES_stencil1 1 -#endif - -/* GL_OES_stencil4 */ -#ifndef GL_OES_stencil4 -#define GL_OES_stencil4 1 -#endif - -#ifndef GL_OES_surfaceless_context -#define GL_OES_surfaceless_context 1 -#endif - -/* GL_OES_texture_3D */ -#ifndef GL_OES_texture_3D -#define GL_OES_texture_3D 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); -GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); -GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); -GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); -GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); -#endif -typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); -typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); -typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); -typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); -typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); -#endif - -/* GL_OES_texture_float */ -#ifndef GL_OES_texture_float -#define GL_OES_texture_float 1 -#endif - -/* GL_OES_texture_float_linear */ -#ifndef GL_OES_texture_float_linear -#define GL_OES_texture_float_linear 1 -#endif - -/* GL_OES_texture_half_float */ -#ifndef GL_OES_texture_half_float -#define GL_OES_texture_half_float 1 -#endif - -/* GL_OES_texture_half_float_linear */ -#ifndef GL_OES_texture_half_float_linear -#define GL_OES_texture_half_float_linear 1 -#endif - -/* GL_OES_texture_npot */ -#ifndef GL_OES_texture_npot -#define GL_OES_texture_npot 1 -#endif - -/* GL_OES_vertex_array_object */ -#ifndef GL_OES_vertex_array_object -#define GL_OES_vertex_array_object 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLuint array); -GL_APICALL void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays); -GL_APICALL void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays); -GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array); -#endif -typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array); -typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays); -typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays); -typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array); -#endif - -/* GL_OES_vertex_half_float */ -#ifndef GL_OES_vertex_half_float -#define GL_OES_vertex_half_float 1 -#endif - -/* GL_OES_vertex_type_10_10_10_2 */ -#ifndef GL_OES_vertex_type_10_10_10_2 -#define GL_OES_vertex_type_10_10_10_2 1 -#endif - -/*------------------------------------------------------------------------* - * KHR extension functions - *------------------------------------------------------------------------*/ - -#ifndef GL_KHR_debug -#define GL_KHR_debug 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); -GL_APICALL void GL_APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); -GL_APICALL void GL_APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam); -GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); -GL_APICALL void GL_APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message); -GL_APICALL void GL_APIENTRY glPopDebugGroup (void); -GL_APICALL void GL_APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); -GL_APICALL void GL_APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); -GL_APICALL void GL_APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label); -GL_APICALL void GL_APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); -GL_APICALL void GL_APIENTRY glGetPointerv (GLenum pname, void **params); -#endif -typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); -typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); -typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam); -typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); -typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message); -typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void); -typedef void (GL_APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); -typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); -typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label); -typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); -typedef void (GL_APIENTRYP PFNGLGETPOINTERVPROC) (GLenum pname, void **params); -#endif - -#ifndef GL_KHR_texture_compression_astc_ldr -#define GL_KHR_texture_compression_astc_ldr 1 -#endif - - -/*------------------------------------------------------------------------* - * AMD extension functions - *------------------------------------------------------------------------*/ - -/* GL_AMD_compressed_3DC_texture */ -#ifndef GL_AMD_compressed_3DC_texture -#define GL_AMD_compressed_3DC_texture 1 -#endif - -/* GL_AMD_compressed_ATC_texture */ -#ifndef GL_AMD_compressed_ATC_texture -#define GL_AMD_compressed_ATC_texture 1 -#endif - -/* AMD_performance_monitor */ -#ifndef GL_AMD_performance_monitor -#define GL_AMD_performance_monitor 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups); -GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); -GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); -GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); -GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, GLvoid *data); -GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors); -GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors); -GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList); -GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor); -GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor); -GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); -#endif -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data); -typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); -typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); -typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList); -typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor); -typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); -#endif - -/* GL_AMD_program_binary_Z400 */ -#ifndef GL_AMD_program_binary_Z400 -#define GL_AMD_program_binary_Z400 1 -#endif - -/*------------------------------------------------------------------------* - * ANGLE extension functions - *------------------------------------------------------------------------*/ - -/* GL_ANGLE_depth_texture */ -#ifndef GL_ANGLE_depth_texture -#define GL_ANGLE_depth_texture 1 -#endif - -/* GL_ANGLE_framebuffer_blit */ -#ifndef GL_ANGLE_framebuffer_blit -#define GL_ANGLE_framebuffer_blit 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -#endif -typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -#endif - -/* GL_ANGLE_framebuffer_multisample */ -#ifndef GL_ANGLE_framebuffer_multisample -#define GL_ANGLE_framebuffer_multisample 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -#endif -typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -#endif - -#ifndef GL_ANGLE_instanced_arrays -#define GL_ANGLE_instanced_arrays 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); -GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor); -#endif -typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); -typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor); -#endif - -/* GL_ANGLE_pack_reverse_row_order */ -#ifndef GL_ANGLE_pack_reverse_row_order -#define GL_ANGLE_pack_reverse_row_order 1 -#endif - -/* GL_ANGLE_program_binary */ -#ifndef GL_ANGLE_program_binary -#define GL_ANGLE_program_binary 1 -#endif - -/* GL_ANGLE_texture_compression_dxt3 */ -#ifndef GL_ANGLE_texture_compression_dxt3 -#define GL_ANGLE_texture_compression_dxt3 1 -#endif - -/* GL_ANGLE_texture_compression_dxt5 */ -#ifndef GL_ANGLE_texture_compression_dxt5 -#define GL_ANGLE_texture_compression_dxt5 1 -#endif - -/* GL_ANGLE_texture_usage */ -#ifndef GL_ANGLE_texture_usage -#define GL_ANGLE_texture_usage 1 -#endif - -#ifndef GL_ANGLE_translated_shader_source -#define GL_ANGLE_translated_shader_source 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); -#endif -typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); -#endif - -/*------------------------------------------------------------------------* - * APPLE extension functions - *------------------------------------------------------------------------*/ - -/* GL_APPLE_copy_texture_levels */ -#ifndef GL_APPLE_copy_texture_levels -#define GL_APPLE_copy_texture_levels 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glCopyTextureLevelsAPPLE (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount); -#endif -typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount); -#endif - -/* GL_APPLE_framebuffer_multisample */ -#ifndef GL_APPLE_framebuffer_multisample -#define GL_APPLE_framebuffer_multisample 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum, GLsizei, GLenum, GLsizei, GLsizei); -GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void); -#endif - -/* GL_APPLE_rgb_422 */ -#ifndef GL_APPLE_rgb_422 -#define GL_APPLE_rgb_422 1 -#endif - -/* GL_APPLE_sync */ -#ifndef GL_APPLE_sync -#define GL_APPLE_sync 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL GLsync GL_APIENTRY glFenceSyncAPPLE (GLenum condition, GLbitfield flags); -GL_APICALL GLboolean GL_APIENTRY glIsSyncAPPLE (GLsync sync); -GL_APICALL void GL_APIENTRY glDeleteSyncAPPLE (GLsync sync); -GL_APICALL GLenum GL_APIENTRY glClientWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout); -GL_APICALL void GL_APIENTRY glWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout); -GL_APICALL void GL_APIENTRY glGetInteger64vAPPLE (GLenum pname, GLint64 *params); -GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); -#endif -typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags); -typedef GLboolean (GL_APIENTRYP PFNGLISSYNCAPPLEPROC) (GLsync sync); -typedef void (GL_APIENTRYP PFNGLDELETESYNCAPPLEPROC) (GLsync sync); -typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); -typedef void (GL_APIENTRYP PFNGLWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); -typedef void (GL_APIENTRYP PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64 *params); -typedef void (GL_APIENTRYP PFNGLGETSYNCIVAPPLEPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); -#endif - -/* GL_APPLE_texture_format_BGRA8888 */ -#ifndef GL_APPLE_texture_format_BGRA8888 -#define GL_APPLE_texture_format_BGRA8888 1 -#endif - -/* GL_APPLE_texture_max_level */ -#ifndef GL_APPLE_texture_max_level -#define GL_APPLE_texture_max_level 1 -#endif - -/*------------------------------------------------------------------------* - * ARM extension functions - *------------------------------------------------------------------------*/ - -/* GL_ARM_mali_program_binary */ -#ifndef GL_ARM_mali_program_binary -#define GL_ARM_mali_program_binary 1 -#endif - -/* GL_ARM_mali_shader_binary */ -#ifndef GL_ARM_mali_shader_binary -#define GL_ARM_mali_shader_binary 1 -#endif - -/* GL_ARM_rgba8 */ -#ifndef GL_ARM_rgba8 -#define GL_ARM_rgba8 1 -#endif - -/*------------------------------------------------------------------------* - * EXT extension functions - *------------------------------------------------------------------------*/ - -/* GL_EXT_blend_minmax */ -#ifndef GL_EXT_blend_minmax -#define GL_EXT_blend_minmax 1 -#endif - -/* GL_EXT_color_buffer_half_float */ -#ifndef GL_EXT_color_buffer_half_float -#define GL_EXT_color_buffer_half_float 1 -#endif - -/* GL_EXT_debug_label */ -#ifndef GL_EXT_debug_label -#define GL_EXT_debug_label 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label); -GL_APICALL void GL_APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); -#endif -typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label); -typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); -#endif - -/* GL_EXT_debug_marker */ -#ifndef GL_EXT_debug_marker -#define GL_EXT_debug_marker 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker); -GL_APICALL void GL_APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker); -GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void); -#endif -typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker); -typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker); -typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void); -#endif - -/* GL_EXT_discard_framebuffer */ -#ifndef GL_EXT_discard_framebuffer -#define GL_EXT_discard_framebuffer 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments); -#endif -typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); -#endif - -/* GL_EXT_map_buffer_range */ -#ifndef GL_EXT_map_buffer_range -#define GL_EXT_map_buffer_range 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void* GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); -GL_APICALL void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length); -#endif -typedef void* (GL_APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); -typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length); -#endif - -/* GL_EXT_multisampled_render_to_texture */ -#ifndef GL_EXT_multisampled_render_to_texture -#define GL_EXT_multisampled_render_to_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum, GLsizei, GLenum, GLsizei, GLsizei); -GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei); -#endif -typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); -#endif - -/* GL_EXT_multiview_draw_buffers */ -#ifndef GL_EXT_multiview_draw_buffers -#define GL_EXT_multiview_draw_buffers 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glReadBufferIndexedEXT (GLenum src, GLint index); -GL_APICALL void GL_APIENTRY glDrawBuffersIndexedEXT (GLint n, const GLenum *location, const GLint *indices); -GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLint *data); -#endif -typedef void (GL_APIENTRYP PFNGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index); -typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum *location, const GLint *indices); -typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint *data); -#endif - -#ifndef GL_EXT_multi_draw_arrays -#define GL_EXT_multi_draw_arrays 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum, const GLint *, const GLsizei *, GLsizei); -GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); -typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); -#endif - -/* GL_EXT_occlusion_query_boolean */ -#ifndef GL_EXT_occlusion_query_boolean -#define GL_EXT_occlusion_query_boolean 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizei n, GLuint *ids); -GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizei n, const GLuint *ids); -GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLuint id); -GL_APICALL void GL_APIENTRY glBeginQueryEXT (GLenum target, GLuint id); -GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenum target); -GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenum target, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLuint id, GLenum pname, GLuint *params); -#endif -typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids); -typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids); -typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id); -typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id); -typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target); -typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params); -#endif - -/* GL_EXT_read_format_bgra */ -#ifndef GL_EXT_read_format_bgra -#define GL_EXT_read_format_bgra 1 -#endif - -/* GL_EXT_robustness */ -#ifndef GL_EXT_robustness -#define GL_EXT_robustness 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void); -GL_APICALL void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); -GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, float *params); -GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params); -#endif -typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void); -typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); -typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, float *params); -typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); -#endif - -/* GL_EXT_separate_shader_objects */ -#ifndef GL_EXT_separate_shader_objects -#define GL_EXT_separate_shader_objects 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program); -GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program); -GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings); -GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline); -GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines); -GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines); -GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline); -GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value); -GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint x); -GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint x, GLint y); -GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z); -GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w); -GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat x); -GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat x, GLfloat y); -GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z); -GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline); -GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -#endif -typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program); -typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program); -typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings); -typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline); -typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines); -typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines); -typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline); -typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); -typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint x); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint x, GLint y); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat x); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline); -typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -#endif - -/* GL_EXT_shader_framebuffer_fetch */ -#ifndef GL_EXT_shader_framebuffer_fetch -#define GL_EXT_shader_framebuffer_fetch 1 -#endif - -/* GL_EXT_shader_texture_lod */ -#ifndef GL_EXT_shader_texture_lod -#define GL_EXT_shader_texture_lod 1 -#endif - -/* GL_EXT_shadow_samplers */ -#ifndef GL_EXT_shadow_samplers -#define GL_EXT_shadow_samplers 1 -#endif - -/* GL_EXT_sRGB */ -#ifndef GL_EXT_sRGB -#define GL_EXT_sRGB 1 -#endif - -/* GL_EXT_texture_compression_dxt1 */ -#ifndef GL_EXT_texture_compression_dxt1 -#define GL_EXT_texture_compression_dxt1 1 -#endif - -/* GL_EXT_texture_filter_anisotropic */ -#ifndef GL_EXT_texture_filter_anisotropic -#define GL_EXT_texture_filter_anisotropic 1 -#endif - -/* GL_EXT_texture_format_BGRA8888 */ -#ifndef GL_EXT_texture_format_BGRA8888 -#define GL_EXT_texture_format_BGRA8888 1 -#endif - -/* GL_EXT_texture_rg */ -#ifndef GL_EXT_texture_rg -#define GL_EXT_texture_rg 1 -#endif - -/* GL_EXT_texture_storage */ -#ifndef GL_EXT_texture_storage -#define GL_EXT_texture_storage 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); -GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glTexStorage3DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -GL_APICALL void GL_APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); -GL_APICALL void GL_APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -#endif -typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); -typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); -typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -#endif - -/* GL_EXT_texture_type_2_10_10_10_REV */ -#ifndef GL_EXT_texture_type_2_10_10_10_REV -#define GL_EXT_texture_type_2_10_10_10_REV 1 -#endif - -/* GL_EXT_unpack_subimage */ -#ifndef GL_EXT_unpack_subimage -#define GL_EXT_unpack_subimage 1 -#endif - -/*------------------------------------------------------------------------* - * DMP extension functions - *------------------------------------------------------------------------*/ - -/* GL_DMP_shader_binary */ -#ifndef GL_DMP_shader_binary -#define GL_DMP_shader_binary 1 -#endif - -/*------------------------------------------------------------------------* - * FJ extension functions - *------------------------------------------------------------------------*/ - -/* GL_FJ_shader_binary_GCCSO */ -#ifndef GL_FJ_shader_binary_GCCSO -#define GL_FJ_shader_binary_GCCSO 1 -#endif - -/*------------------------------------------------------------------------* - * IMG extension functions - *------------------------------------------------------------------------*/ - -/* GL_IMG_program_binary */ -#ifndef GL_IMG_program_binary -#define GL_IMG_program_binary 1 -#endif - -/* GL_IMG_read_format */ -#ifndef GL_IMG_read_format -#define GL_IMG_read_format 1 -#endif - -/* GL_IMG_shader_binary */ -#ifndef GL_IMG_shader_binary -#define GL_IMG_shader_binary 1 -#endif - -/* GL_IMG_texture_compression_pvrtc */ -#ifndef GL_IMG_texture_compression_pvrtc -#define GL_IMG_texture_compression_pvrtc 1 -#endif - -/* GL_IMG_texture_compression_pvrtc2 */ -#ifndef GL_IMG_texture_compression_pvrtc2 -#define GL_IMG_texture_compression_pvrtc2 1 -#endif - -/* GL_IMG_multisampled_render_to_texture */ -#ifndef GL_IMG_multisampled_render_to_texture -#define GL_IMG_multisampled_render_to_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum, GLsizei, GLenum, GLsizei, GLsizei); -GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei); -#endif -typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); -#endif - -/*------------------------------------------------------------------------* - * NV extension functions - *------------------------------------------------------------------------*/ - -/* GL_NV_coverage_sample */ -#ifndef GL_NV_coverage_sample -#define GL_NV_coverage_sample 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glCoverageMaskNV (GLboolean mask); -GL_APICALL void GL_APIENTRY glCoverageOperationNV (GLenum operation); -#endif -typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask); -typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation); -#endif - -/* GL_NV_depth_nonlinear */ -#ifndef GL_NV_depth_nonlinear -#define GL_NV_depth_nonlinear 1 -#endif - -/* GL_NV_draw_buffers */ -#ifndef GL_NV_draw_buffers -#define GL_NV_draw_buffers 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs); -#endif -typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs); -#endif - -/* GL_EXT_draw_buffers */ -#ifndef GL_EXT_draw_buffers -#define GL_EXT_draw_buffers 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs); -#endif -typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs); -#endif - -/* GL_NV_draw_instanced */ -#ifndef GL_NV_draw_instanced -#define GL_NV_draw_instanced 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDrawArraysInstancedNV (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -GL_APICALL void GL_APIENTRY glDrawElementsInstancedNV (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); -#endif -typedef void (GL_APIENTRYP PFNDRAWARRAYSINSTANCEDNVPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -typedef void (GL_APIENTRYP PFNDRAWELEMENTSINSTANCEDNVPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); -#endif - -/* GL_NV_fbo_color_attachments */ -#ifndef GL_NV_fbo_color_attachments -#define GL_NV_fbo_color_attachments 1 -#endif - -/* GL_NV_fence */ -#ifndef GL_NV_fence -#define GL_NV_fence 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei, const GLuint *); -GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei, GLuint *); -GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint); -GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint); -GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *); -GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint); -GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint, GLenum); -#endif -typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences); -typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences); -typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence); -typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence); -typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params); -typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence); -typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); -#endif - -/* GL_NV_framebuffer_blit */ -#ifndef GL_NV_framebuffer_blit -#define GL_NV_framebuffer_blit 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glBlitFramebufferNV (int srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -#endif -typedef void (GL_APIENTRYP PFNBLITFRAMEBUFFERNVPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -#endif - -/* GL_NV_framebuffer_multisample */ -#ifndef GL_NV_framebuffer_multisample -#define GL_NV_framebuffer_multisample 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleNV ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -#endif -typedef void (GL_APIENTRYP PFNRENDERBUFFERSTORAGEMULTISAMPLENVPROC) ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -#endif - -/* GL_NV_generate_mipmap_sRGB */ -#ifndef GL_NV_generate_mipmap_sRGB -#define GL_NV_generate_mipmap_sRGB 1 -#endif - -/* GL_NV_instanced_arrays */ -#ifndef GL_NV_instanced_arrays -#define GL_NV_instanced_arrays 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glVertexAttribDivisorNV (GLuint index, GLuint divisor); -#endif -typedef void (GL_APIENTRYP PFNVERTEXATTRIBDIVISORNVPROC) (GLuint index, GLuint divisor); -#endif - -/* GL_NV_read_buffer */ -#ifndef GL_NV_read_buffer -#define GL_NV_read_buffer 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode); -#endif -typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode); -#endif - -/* GL_NV_read_buffer_front */ -#ifndef GL_NV_read_buffer_front -#define GL_NV_read_buffer_front 1 -#endif - -/* GL_NV_read_depth */ -#ifndef GL_NV_read_depth -#define GL_NV_read_depth 1 -#endif - -/* GL_NV_read_depth_stencil */ -#ifndef GL_NV_read_depth_stencil -#define GL_NV_read_depth_stencil 1 -#endif - -/* GL_NV_read_stencil */ -#ifndef GL_NV_read_stencil -#define GL_NV_read_stencil 1 -#endif - -/* GL_NV_shadow_samplers_array */ -#ifndef GL_NV_shadow_samplers_array -#define GL_NV_shadow_samplers_array 1 -#endif - -/* GL_NV_shadow_samplers_cube */ -#ifndef GL_NV_shadow_samplers_cube -#define GL_NV_shadow_samplers_cube 1 -#endif - -/* GL_NV_sRGB_formats */ -#ifndef GL_NV_sRGB_formats -#define GL_NV_sRGB_formats 1 -#endif - -/* GL_NV_texture_border_clamp */ -#ifndef GL_NV_texture_border_clamp -#define GL_NV_texture_border_clamp 1 -#endif - -/* GL_NV_texture_compression_s3tc_update */ -#ifndef GL_NV_texture_compression_s3tc_update -#define GL_NV_texture_compression_s3tc_update 1 -#endif - -/* GL_NV_texture_npot_2D_mipmap */ -#ifndef GL_NV_texture_npot_2D_mipmap -#define GL_NV_texture_npot_2D_mipmap 1 -#endif - -/*------------------------------------------------------------------------* - * QCOM extension functions - *------------------------------------------------------------------------*/ - -/* GL_QCOM_alpha_test */ -#ifndef GL_QCOM_alpha_test -#define GL_QCOM_alpha_test 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref); -#endif -typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); -#endif - -/* GL_QCOM_binning_control */ -#ifndef GL_QCOM_binning_control -#define GL_QCOM_binning_control 1 -#endif - -/* GL_QCOM_driver_control */ -#ifndef GL_QCOM_driver_control -#define GL_QCOM_driver_control 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls); -GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString); -GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl); -GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl); -#endif -typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls); -typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString); -typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl); -typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl); -#endif - -/* GL_QCOM_extended_get */ -#ifndef GL_QCOM_extended_get -#define GL_QCOM_extended_get 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures); -GL_APICALL void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers); -GL_APICALL void GL_APIENTRY glExtGetRenderbuffersQCOM (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers); -GL_APICALL void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers); -GL_APICALL void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels); -GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, GLvoid **params); -#endif -typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures); -typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers); -typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers); -typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers); -typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params); -typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param); -typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels); -typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid **params); -#endif - -/* GL_QCOM_extended_get2 */ -#ifndef GL_QCOM_extended_get2 -#define GL_QCOM_extended_get2 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders); -GL_APICALL void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms); -GL_APICALL GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program); -GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length); -#endif -typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders); -typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms); -typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program); -typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length); -#endif - -/* GL_QCOM_perfmon_global_mode */ -#ifndef GL_QCOM_perfmon_global_mode -#define GL_QCOM_perfmon_global_mode 1 -#endif - -/* GL_QCOM_writeonly_rendering */ -#ifndef GL_QCOM_writeonly_rendering -#define GL_QCOM_writeonly_rendering 1 -#endif - -/* GL_QCOM_tiled_rendering */ -#ifndef GL_QCOM_tiled_rendering -#define GL_QCOM_tiled_rendering 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask); -GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask); -#endif -typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask); -typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask); -#endif - -/*------------------------------------------------------------------------* - * VIV extension tokens - *------------------------------------------------------------------------*/ - -/* GL_VIV_shader_binary */ -#ifndef GL_VIV_shader_binary -#define GL_VIV_shader_binary 1 -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __gl2ext_h_ */ diff --git a/platform/winrt/include/GLES2/gl2platform.h b/platform/winrt/include/GLES2/gl2platform.h deleted file mode 100644 index c9fa3c4d64..0000000000 --- a/platform/winrt/include/GLES2/gl2platform.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __gl2platform_h_ -#define __gl2platform_h_ - -/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */ - -/* - * This document is licensed under the SGI Free Software B License Version - * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . - */ - -/* Platform-specific types and definitions for OpenGL ES 2.X gl2.h - * - * Adopters may modify khrplatform.h and this file to suit their platform. - * You are encouraged to submit all modifications to the Khronos group so that - * they can be included in future versions of this file. Please submit changes - * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) - * by filing a bug against product "OpenGL-ES" component "Registry". - */ - -#include <KHR/khrplatform.h> - -#ifndef GL_APICALL -#define GL_APICALL KHRONOS_APICALL -#endif - -#ifndef GL_APIENTRY -#define GL_APIENTRY KHRONOS_APIENTRY -#endif - -#endif /* __gl2platform_h_ */ diff --git a/platform/winrt/include/GLES3/gl3.h b/platform/winrt/include/GLES3/gl3.h deleted file mode 100644 index b7e91e6881..0000000000 --- a/platform/winrt/include/GLES3/gl3.h +++ /dev/null @@ -1,1061 +0,0 @@ -#ifndef __gl3_h_ -#define __gl3_h_ - -/* - * gl3.h last updated on $Date: 2013-02-12 14:37:24 -0800 (Tue, 12 Feb 2013) $ - */ - -#include <GLES3/gl3platform.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* -** Copyright (c) 2007-2013 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ - -/*------------------------------------------------------------------------- - * Data type definitions - *-----------------------------------------------------------------------*/ - -/* OpenGL ES 2.0 */ - -typedef void GLvoid; -typedef char GLchar; -typedef unsigned int GLenum; -typedef unsigned char GLboolean; -typedef unsigned int GLbitfield; -typedef khronos_int8_t GLbyte; -typedef short GLshort; -typedef int GLint; -typedef int GLsizei; -typedef khronos_uint8_t GLubyte; -typedef unsigned short GLushort; -typedef unsigned int GLuint; -typedef khronos_float_t GLfloat; -typedef khronos_float_t GLclampf; -typedef khronos_int32_t GLfixed; -typedef khronos_intptr_t GLintptr; -typedef khronos_ssize_t GLsizeiptr; - -/* OpenGL ES 3.0 */ - -typedef unsigned short GLhalf; -typedef khronos_int64_t GLint64; -typedef khronos_uint64_t GLuint64; -typedef struct __GLsync *GLsync; - -/*------------------------------------------------------------------------- - * Token definitions - *-----------------------------------------------------------------------*/ - -/* OpenGL ES core versions */ -#define GL_ES_VERSION_3_0 1 -#define GL_ES_VERSION_2_0 1 - -/* OpenGL ES 2.0 */ - -/* ClearBufferMask */ -#define GL_DEPTH_BUFFER_BIT 0x00000100 -#define GL_STENCIL_BUFFER_BIT 0x00000400 -#define GL_COLOR_BUFFER_BIT 0x00004000 - -/* Boolean */ -#define GL_FALSE 0 -#define GL_TRUE 1 - -/* BeginMode */ -#define GL_POINTS 0x0000 -#define GL_LINES 0x0001 -#define GL_LINE_LOOP 0x0002 -#define GL_LINE_STRIP 0x0003 -#define GL_TRIANGLES 0x0004 -#define GL_TRIANGLE_STRIP 0x0005 -#define GL_TRIANGLE_FAN 0x0006 - -/* BlendingFactorDest */ -#define GL_ZERO 0 -#define GL_ONE 1 -#define GL_SRC_COLOR 0x0300 -#define GL_ONE_MINUS_SRC_COLOR 0x0301 -#define GL_SRC_ALPHA 0x0302 -#define GL_ONE_MINUS_SRC_ALPHA 0x0303 -#define GL_DST_ALPHA 0x0304 -#define GL_ONE_MINUS_DST_ALPHA 0x0305 - -/* BlendingFactorSrc */ -/* GL_ZERO */ -/* GL_ONE */ -#define GL_DST_COLOR 0x0306 -#define GL_ONE_MINUS_DST_COLOR 0x0307 -#define GL_SRC_ALPHA_SATURATE 0x0308 -/* GL_SRC_ALPHA */ -/* GL_ONE_MINUS_SRC_ALPHA */ -/* GL_DST_ALPHA */ -/* GL_ONE_MINUS_DST_ALPHA */ - -/* BlendEquationSeparate */ -#define GL_FUNC_ADD 0x8006 -#define GL_BLEND_EQUATION 0x8009 -#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */ -#define GL_BLEND_EQUATION_ALPHA 0x883D - -/* BlendSubtract */ -#define GL_FUNC_SUBTRACT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT 0x800B - -/* Separate Blend Functions */ -#define GL_BLEND_DST_RGB 0x80C8 -#define GL_BLEND_SRC_RGB 0x80C9 -#define GL_BLEND_DST_ALPHA 0x80CA -#define GL_BLEND_SRC_ALPHA 0x80CB -#define GL_CONSTANT_COLOR 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 -#define GL_CONSTANT_ALPHA 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 -#define GL_BLEND_COLOR 0x8005 - -/* Buffer Objects */ -#define GL_ARRAY_BUFFER 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER 0x8893 -#define GL_ARRAY_BUFFER_BINDING 0x8894 -#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 - -#define GL_STREAM_DRAW 0x88E0 -#define GL_STATIC_DRAW 0x88E4 -#define GL_DYNAMIC_DRAW 0x88E8 - -#define GL_BUFFER_SIZE 0x8764 -#define GL_BUFFER_USAGE 0x8765 - -#define GL_CURRENT_VERTEX_ATTRIB 0x8626 - -/* CullFaceMode */ -#define GL_FRONT 0x0404 -#define GL_BACK 0x0405 -#define GL_FRONT_AND_BACK 0x0408 - -/* DepthFunction */ -/* GL_NEVER */ -/* GL_LESS */ -/* GL_EQUAL */ -/* GL_LEQUAL */ -/* GL_GREATER */ -/* GL_NOTEQUAL */ -/* GL_GEQUAL */ -/* GL_ALWAYS */ - -/* EnableCap */ -#define GL_TEXTURE_2D 0x0DE1 -#define GL_CULL_FACE 0x0B44 -#define GL_BLEND 0x0BE2 -#define GL_DITHER 0x0BD0 -#define GL_STENCIL_TEST 0x0B90 -#define GL_DEPTH_TEST 0x0B71 -#define GL_SCISSOR_TEST 0x0C11 -#define GL_POLYGON_OFFSET_FILL 0x8037 -#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E -#define GL_SAMPLE_COVERAGE 0x80A0 - -/* ErrorCode */ -#define GL_NO_ERROR 0 -#define GL_INVALID_ENUM 0x0500 -#define GL_INVALID_VALUE 0x0501 -#define GL_INVALID_OPERATION 0x0502 -#define GL_OUT_OF_MEMORY 0x0505 - -/* FrontFaceDirection */ -#define GL_CW 0x0900 -#define GL_CCW 0x0901 - -/* GetPName */ -#define GL_LINE_WIDTH 0x0B21 -#define GL_ALIASED_POINT_SIZE_RANGE 0x846D -#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E -#define GL_CULL_FACE_MODE 0x0B45 -#define GL_FRONT_FACE 0x0B46 -#define GL_DEPTH_RANGE 0x0B70 -#define GL_DEPTH_WRITEMASK 0x0B72 -#define GL_DEPTH_CLEAR_VALUE 0x0B73 -#define GL_DEPTH_FUNC 0x0B74 -#define GL_STENCIL_CLEAR_VALUE 0x0B91 -#define GL_STENCIL_FUNC 0x0B92 -#define GL_STENCIL_FAIL 0x0B94 -#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 -#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 -#define GL_STENCIL_REF 0x0B97 -#define GL_STENCIL_VALUE_MASK 0x0B93 -#define GL_STENCIL_WRITEMASK 0x0B98 -#define GL_STENCIL_BACK_FUNC 0x8800 -#define GL_STENCIL_BACK_FAIL 0x8801 -#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 -#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 -#define GL_STENCIL_BACK_REF 0x8CA3 -#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 -#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 -#define GL_VIEWPORT 0x0BA2 -#define GL_SCISSOR_BOX 0x0C10 -/* GL_SCISSOR_TEST */ -#define GL_COLOR_CLEAR_VALUE 0x0C22 -#define GL_COLOR_WRITEMASK 0x0C23 -#define GL_UNPACK_ALIGNMENT 0x0CF5 -#define GL_PACK_ALIGNMENT 0x0D05 -#define GL_MAX_TEXTURE_SIZE 0x0D33 -#define GL_MAX_VIEWPORT_DIMS 0x0D3A -#define GL_SUBPIXEL_BITS 0x0D50 -#define GL_RED_BITS 0x0D52 -#define GL_GREEN_BITS 0x0D53 -#define GL_BLUE_BITS 0x0D54 -#define GL_ALPHA_BITS 0x0D55 -#define GL_DEPTH_BITS 0x0D56 -#define GL_STENCIL_BITS 0x0D57 -#define GL_POLYGON_OFFSET_UNITS 0x2A00 -/* GL_POLYGON_OFFSET_FILL */ -#define GL_POLYGON_OFFSET_FACTOR 0x8038 -#define GL_TEXTURE_BINDING_2D 0x8069 -#define GL_SAMPLE_BUFFERS 0x80A8 -#define GL_SAMPLES 0x80A9 -#define GL_SAMPLE_COVERAGE_VALUE 0x80AA -#define GL_SAMPLE_COVERAGE_INVERT 0x80AB - -/* GetTextureParameter */ -/* GL_TEXTURE_MAG_FILTER */ -/* GL_TEXTURE_MIN_FILTER */ -/* GL_TEXTURE_WRAP_S */ -/* GL_TEXTURE_WRAP_T */ - -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 - -/* HintMode */ -#define GL_DONT_CARE 0x1100 -#define GL_FASTEST 0x1101 -#define GL_NICEST 0x1102 - -/* HintTarget */ -#define GL_GENERATE_MIPMAP_HINT 0x8192 - -/* DataType */ -#define GL_BYTE 0x1400 -#define GL_UNSIGNED_BYTE 0x1401 -#define GL_SHORT 0x1402 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_INT 0x1404 -#define GL_UNSIGNED_INT 0x1405 -#define GL_FLOAT 0x1406 -#define GL_FIXED 0x140C - -/* PixelFormat */ -#define GL_DEPTH_COMPONENT 0x1902 -#define GL_ALPHA 0x1906 -#define GL_RGB 0x1907 -#define GL_RGBA 0x1908 -#define GL_LUMINANCE 0x1909 -#define GL_LUMINANCE_ALPHA 0x190A - -/* PixelType */ -/* GL_UNSIGNED_BYTE */ -#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 - -/* Shaders */ -#define GL_FRAGMENT_SHADER 0x8B30 -#define GL_VERTEX_SHADER 0x8B31 -#define GL_MAX_VERTEX_ATTRIBS 0x8869 -#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB -#define GL_MAX_VARYING_VECTORS 0x8DFC -#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D -#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C -#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 -#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD -#define GL_SHADER_TYPE 0x8B4F -#define GL_DELETE_STATUS 0x8B80 -#define GL_LINK_STATUS 0x8B82 -#define GL_VALIDATE_STATUS 0x8B83 -#define GL_ATTACHED_SHADERS 0x8B85 -#define GL_ACTIVE_UNIFORMS 0x8B86 -#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 -#define GL_ACTIVE_ATTRIBUTES 0x8B89 -#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A -#define GL_SHADING_LANGUAGE_VERSION 0x8B8C -#define GL_CURRENT_PROGRAM 0x8B8D - -/* StencilFunction */ -#define GL_NEVER 0x0200 -#define GL_LESS 0x0201 -#define GL_EQUAL 0x0202 -#define GL_LEQUAL 0x0203 -#define GL_GREATER 0x0204 -#define GL_NOTEQUAL 0x0205 -#define GL_GEQUAL 0x0206 -#define GL_ALWAYS 0x0207 - -/* StencilOp */ -/* GL_ZERO */ -#define GL_KEEP 0x1E00 -#define GL_REPLACE 0x1E01 -#define GL_INCR 0x1E02 -#define GL_DECR 0x1E03 -#define GL_INVERT 0x150A -#define GL_INCR_WRAP 0x8507 -#define GL_DECR_WRAP 0x8508 - -/* StringName */ -#define GL_VENDOR 0x1F00 -#define GL_RENDERER 0x1F01 -#define GL_VERSION 0x1F02 -#define GL_EXTENSIONS 0x1F03 - -/* TextureMagFilter */ -#define GL_NEAREST 0x2600 -#define GL_LINEAR 0x2601 - -/* TextureMinFilter */ -/* GL_NEAREST */ -/* GL_LINEAR */ -#define GL_NEAREST_MIPMAP_NEAREST 0x2700 -#define GL_LINEAR_MIPMAP_NEAREST 0x2701 -#define GL_NEAREST_MIPMAP_LINEAR 0x2702 -#define GL_LINEAR_MIPMAP_LINEAR 0x2703 - -/* TextureParameterName */ -#define GL_TEXTURE_MAG_FILTER 0x2800 -#define GL_TEXTURE_MIN_FILTER 0x2801 -#define GL_TEXTURE_WRAP_S 0x2802 -#define GL_TEXTURE_WRAP_T 0x2803 - -/* TextureTarget */ -/* GL_TEXTURE_2D */ -#define GL_TEXTURE 0x1702 - -#define GL_TEXTURE_CUBE_MAP 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C - -/* TextureUnit */ -#define GL_TEXTURE0 0x84C0 -#define GL_TEXTURE1 0x84C1 -#define GL_TEXTURE2 0x84C2 -#define GL_TEXTURE3 0x84C3 -#define GL_TEXTURE4 0x84C4 -#define GL_TEXTURE5 0x84C5 -#define GL_TEXTURE6 0x84C6 -#define GL_TEXTURE7 0x84C7 -#define GL_TEXTURE8 0x84C8 -#define GL_TEXTURE9 0x84C9 -#define GL_TEXTURE10 0x84CA -#define GL_TEXTURE11 0x84CB -#define GL_TEXTURE12 0x84CC -#define GL_TEXTURE13 0x84CD -#define GL_TEXTURE14 0x84CE -#define GL_TEXTURE15 0x84CF -#define GL_TEXTURE16 0x84D0 -#define GL_TEXTURE17 0x84D1 -#define GL_TEXTURE18 0x84D2 -#define GL_TEXTURE19 0x84D3 -#define GL_TEXTURE20 0x84D4 -#define GL_TEXTURE21 0x84D5 -#define GL_TEXTURE22 0x84D6 -#define GL_TEXTURE23 0x84D7 -#define GL_TEXTURE24 0x84D8 -#define GL_TEXTURE25 0x84D9 -#define GL_TEXTURE26 0x84DA -#define GL_TEXTURE27 0x84DB -#define GL_TEXTURE28 0x84DC -#define GL_TEXTURE29 0x84DD -#define GL_TEXTURE30 0x84DE -#define GL_TEXTURE31 0x84DF -#define GL_ACTIVE_TEXTURE 0x84E0 - -/* TextureWrapMode */ -#define GL_REPEAT 0x2901 -#define GL_CLAMP_TO_EDGE 0x812F -#define GL_MIRRORED_REPEAT 0x8370 - -/* Uniform Types */ -#define GL_FLOAT_VEC2 0x8B50 -#define GL_FLOAT_VEC3 0x8B51 -#define GL_FLOAT_VEC4 0x8B52 -#define GL_INT_VEC2 0x8B53 -#define GL_INT_VEC3 0x8B54 -#define GL_INT_VEC4 0x8B55 -#define GL_BOOL 0x8B56 -#define GL_BOOL_VEC2 0x8B57 -#define GL_BOOL_VEC3 0x8B58 -#define GL_BOOL_VEC4 0x8B59 -#define GL_FLOAT_MAT2 0x8B5A -#define GL_FLOAT_MAT3 0x8B5B -#define GL_FLOAT_MAT4 0x8B5C -#define GL_SAMPLER_2D 0x8B5E -#define GL_SAMPLER_CUBE 0x8B60 - -/* Vertex Arrays */ -#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 -#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 -#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 -#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 -#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A -#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 -#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F - -/* Read Format */ -#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A -#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B - -/* Shader Source */ -#define GL_COMPILE_STATUS 0x8B81 -#define GL_INFO_LOG_LENGTH 0x8B84 -#define GL_SHADER_SOURCE_LENGTH 0x8B88 -#define GL_SHADER_COMPILER 0x8DFA - -/* Shader Binary */ -#define GL_SHADER_BINARY_FORMATS 0x8DF8 -#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 - -/* Shader Precision-Specified Types */ -#define GL_LOW_FLOAT 0x8DF0 -#define GL_MEDIUM_FLOAT 0x8DF1 -#define GL_HIGH_FLOAT 0x8DF2 -#define GL_LOW_INT 0x8DF3 -#define GL_MEDIUM_INT 0x8DF4 -#define GL_HIGH_INT 0x8DF5 - -/* Framebuffer Object. */ -#define GL_FRAMEBUFFER 0x8D40 -#define GL_RENDERBUFFER 0x8D41 - -#define GL_RGBA4 0x8056 -#define GL_RGB5_A1 0x8057 -#define GL_RGB565 0x8D62 -#define GL_DEPTH_COMPONENT16 0x81A5 -#define GL_STENCIL_INDEX8 0x8D48 - -#define GL_RENDERBUFFER_WIDTH 0x8D42 -#define GL_RENDERBUFFER_HEIGHT 0x8D43 -#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 -#define GL_RENDERBUFFER_RED_SIZE 0x8D50 -#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 -#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 -#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 -#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 -#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 - -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 - -#define GL_COLOR_ATTACHMENT0 0x8CE0 -#define GL_DEPTH_ATTACHMENT 0x8D00 -#define GL_STENCIL_ATTACHMENT 0x8D20 - -#define GL_NONE 0 - -#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 -#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 -#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD - -#define GL_FRAMEBUFFER_BINDING 0x8CA6 -#define GL_RENDERBUFFER_BINDING 0x8CA7 -#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 - -#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 - -/* OpenGL ES 3.0 */ - -#define GL_READ_BUFFER 0x0C02 -#define GL_UNPACK_ROW_LENGTH 0x0CF2 -#define GL_UNPACK_SKIP_ROWS 0x0CF3 -#define GL_UNPACK_SKIP_PIXELS 0x0CF4 -#define GL_PACK_ROW_LENGTH 0x0D02 -#define GL_PACK_SKIP_ROWS 0x0D03 -#define GL_PACK_SKIP_PIXELS 0x0D04 -#define GL_COLOR 0x1800 -#define GL_DEPTH 0x1801 -#define GL_STENCIL 0x1802 -#define GL_RED 0x1903 -#define GL_RGB8 0x8051 -#define GL_RGBA8 0x8058 -#define GL_RGB10_A2 0x8059 -#define GL_TEXTURE_BINDING_3D 0x806A -#define GL_UNPACK_SKIP_IMAGES 0x806D -#define GL_UNPACK_IMAGE_HEIGHT 0x806E -#define GL_TEXTURE_3D 0x806F -#define GL_TEXTURE_WRAP_R 0x8072 -#define GL_MAX_3D_TEXTURE_SIZE 0x8073 -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#define GL_MAX_ELEMENTS_VERTICES 0x80E8 -#define GL_MAX_ELEMENTS_INDICES 0x80E9 -#define GL_TEXTURE_MIN_LOD 0x813A -#define GL_TEXTURE_MAX_LOD 0x813B -#define GL_TEXTURE_BASE_LEVEL 0x813C -#define GL_TEXTURE_MAX_LEVEL 0x813D -#define GL_MIN 0x8007 -#define GL_MAX 0x8008 -#define GL_DEPTH_COMPONENT24 0x81A6 -#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD -#define GL_TEXTURE_COMPARE_MODE 0x884C -#define GL_TEXTURE_COMPARE_FUNC 0x884D -#define GL_CURRENT_QUERY 0x8865 -#define GL_QUERY_RESULT 0x8866 -#define GL_QUERY_RESULT_AVAILABLE 0x8867 -#define GL_BUFFER_MAPPED 0x88BC -#define GL_BUFFER_MAP_POINTER 0x88BD -#define GL_STREAM_READ 0x88E1 -#define GL_STREAM_COPY 0x88E2 -#define GL_STATIC_READ 0x88E5 -#define GL_STATIC_COPY 0x88E6 -#define GL_DYNAMIC_READ 0x88E9 -#define GL_DYNAMIC_COPY 0x88EA -#define GL_MAX_DRAW_BUFFERS 0x8824 -#define GL_DRAW_BUFFER0 0x8825 -#define GL_DRAW_BUFFER1 0x8826 -#define GL_DRAW_BUFFER2 0x8827 -#define GL_DRAW_BUFFER3 0x8828 -#define GL_DRAW_BUFFER4 0x8829 -#define GL_DRAW_BUFFER5 0x882A -#define GL_DRAW_BUFFER6 0x882B -#define GL_DRAW_BUFFER7 0x882C -#define GL_DRAW_BUFFER8 0x882D -#define GL_DRAW_BUFFER9 0x882E -#define GL_DRAW_BUFFER10 0x882F -#define GL_DRAW_BUFFER11 0x8830 -#define GL_DRAW_BUFFER12 0x8831 -#define GL_DRAW_BUFFER13 0x8832 -#define GL_DRAW_BUFFER14 0x8833 -#define GL_DRAW_BUFFER15 0x8834 -#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 -#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A -#define GL_SAMPLER_3D 0x8B5F -#define GL_SAMPLER_2D_SHADOW 0x8B62 -#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B -#define GL_PIXEL_PACK_BUFFER 0x88EB -#define GL_PIXEL_UNPACK_BUFFER 0x88EC -#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED -#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF -#define GL_FLOAT_MAT2x3 0x8B65 -#define GL_FLOAT_MAT2x4 0x8B66 -#define GL_FLOAT_MAT3x2 0x8B67 -#define GL_FLOAT_MAT3x4 0x8B68 -#define GL_FLOAT_MAT4x2 0x8B69 -#define GL_FLOAT_MAT4x3 0x8B6A -#define GL_SRGB 0x8C40 -#define GL_SRGB8 0x8C41 -#define GL_SRGB8_ALPHA8 0x8C43 -#define GL_COMPARE_REF_TO_TEXTURE 0x884E -#define GL_MAJOR_VERSION 0x821B -#define GL_MINOR_VERSION 0x821C -#define GL_NUM_EXTENSIONS 0x821D -#define GL_RGBA32F 0x8814 -#define GL_RGB32F 0x8815 -#define GL_RGBA16F 0x881A -#define GL_RGB16F 0x881B -#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD -#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF -#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 -#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 -#define GL_MAX_VARYING_COMPONENTS 0x8B4B -#define GL_TEXTURE_2D_ARRAY 0x8C1A -#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D -#define GL_R11F_G11F_B10F 0x8C3A -#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B -#define GL_RGB9_E5 0x8C3D -#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E -#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 -#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 -#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 -#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 -#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 -#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 -#define GL_RASTERIZER_DISCARD 0x8C89 -#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B -#define GL_INTERLEAVED_ATTRIBS 0x8C8C -#define GL_SEPARATE_ATTRIBS 0x8C8D -#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E -#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F -#define GL_RGBA32UI 0x8D70 -#define GL_RGB32UI 0x8D71 -#define GL_RGBA16UI 0x8D76 -#define GL_RGB16UI 0x8D77 -#define GL_RGBA8UI 0x8D7C -#define GL_RGB8UI 0x8D7D -#define GL_RGBA32I 0x8D82 -#define GL_RGB32I 0x8D83 -#define GL_RGBA16I 0x8D88 -#define GL_RGB16I 0x8D89 -#define GL_RGBA8I 0x8D8E -#define GL_RGB8I 0x8D8F -#define GL_RED_INTEGER 0x8D94 -#define GL_RGB_INTEGER 0x8D98 -#define GL_RGBA_INTEGER 0x8D99 -#define GL_SAMPLER_2D_ARRAY 0x8DC1 -#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 -#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 -#define GL_UNSIGNED_INT_VEC2 0x8DC6 -#define GL_UNSIGNED_INT_VEC3 0x8DC7 -#define GL_UNSIGNED_INT_VEC4 0x8DC8 -#define GL_INT_SAMPLER_2D 0x8DCA -#define GL_INT_SAMPLER_3D 0x8DCB -#define GL_INT_SAMPLER_CUBE 0x8DCC -#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF -#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 -#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 -#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 -#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 -#define GL_BUFFER_ACCESS_FLAGS 0x911F -#define GL_BUFFER_MAP_LENGTH 0x9120 -#define GL_BUFFER_MAP_OFFSET 0x9121 -#define GL_DEPTH_COMPONENT32F 0x8CAC -#define GL_DEPTH32F_STENCIL8 0x8CAD -#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD -#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 -#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 -#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 -#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 -#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 -#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 -#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 -#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 -#define GL_FRAMEBUFFER_DEFAULT 0x8218 -#define GL_FRAMEBUFFER_UNDEFINED 0x8219 -#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A -#define GL_DEPTH_STENCIL 0x84F9 -#define GL_UNSIGNED_INT_24_8 0x84FA -#define GL_DEPTH24_STENCIL8 0x88F0 -#define GL_UNSIGNED_NORMALIZED 0x8C17 -#define GL_DRAW_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING -#define GL_READ_FRAMEBUFFER 0x8CA8 -#define GL_DRAW_FRAMEBUFFER 0x8CA9 -#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA -#define GL_RENDERBUFFER_SAMPLES 0x8CAB -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 -#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF -#define GL_COLOR_ATTACHMENT1 0x8CE1 -#define GL_COLOR_ATTACHMENT2 0x8CE2 -#define GL_COLOR_ATTACHMENT3 0x8CE3 -#define GL_COLOR_ATTACHMENT4 0x8CE4 -#define GL_COLOR_ATTACHMENT5 0x8CE5 -#define GL_COLOR_ATTACHMENT6 0x8CE6 -#define GL_COLOR_ATTACHMENT7 0x8CE7 -#define GL_COLOR_ATTACHMENT8 0x8CE8 -#define GL_COLOR_ATTACHMENT9 0x8CE9 -#define GL_COLOR_ATTACHMENT10 0x8CEA -#define GL_COLOR_ATTACHMENT11 0x8CEB -#define GL_COLOR_ATTACHMENT12 0x8CEC -#define GL_COLOR_ATTACHMENT13 0x8CED -#define GL_COLOR_ATTACHMENT14 0x8CEE -#define GL_COLOR_ATTACHMENT15 0x8CEF -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 -#define GL_MAX_SAMPLES 0x8D57 -#define GL_HALF_FLOAT 0x140B -#define GL_MAP_READ_BIT 0x0001 -#define GL_MAP_WRITE_BIT 0x0002 -#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 -#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 -#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 -#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 -#define GL_RG 0x8227 -#define GL_RG_INTEGER 0x8228 -#define GL_R8 0x8229 -#define GL_RG8 0x822B -#define GL_R16F 0x822D -#define GL_R32F 0x822E -#define GL_RG16F 0x822F -#define GL_RG32F 0x8230 -#define GL_R8I 0x8231 -#define GL_R8UI 0x8232 -#define GL_R16I 0x8233 -#define GL_R16UI 0x8234 -#define GL_R32I 0x8235 -#define GL_R32UI 0x8236 -#define GL_RG8I 0x8237 -#define GL_RG8UI 0x8238 -#define GL_RG16I 0x8239 -#define GL_RG16UI 0x823A -#define GL_RG32I 0x823B -#define GL_RG32UI 0x823C -#define GL_VERTEX_ARRAY_BINDING 0x85B5 -#define GL_R8_SNORM 0x8F94 -#define GL_RG8_SNORM 0x8F95 -#define GL_RGB8_SNORM 0x8F96 -#define GL_RGBA8_SNORM 0x8F97 -#define GL_SIGNED_NORMALIZED 0x8F9C -#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 -#define GL_COPY_READ_BUFFER 0x8F36 -#define GL_COPY_WRITE_BUFFER 0x8F37 -#define GL_COPY_READ_BUFFER_BINDING GL_COPY_READ_BUFFER -#define GL_COPY_WRITE_BUFFER_BINDING GL_COPY_WRITE_BUFFER -#define GL_UNIFORM_BUFFER 0x8A11 -#define GL_UNIFORM_BUFFER_BINDING 0x8A28 -#define GL_UNIFORM_BUFFER_START 0x8A29 -#define GL_UNIFORM_BUFFER_SIZE 0x8A2A -#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B -#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D -#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E -#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F -#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 -#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 -#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 -#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 -#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 -#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 -#define GL_UNIFORM_TYPE 0x8A37 -#define GL_UNIFORM_SIZE 0x8A38 -#define GL_UNIFORM_NAME_LENGTH 0x8A39 -#define GL_UNIFORM_BLOCK_INDEX 0x8A3A -#define GL_UNIFORM_OFFSET 0x8A3B -#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C -#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D -#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E -#define GL_UNIFORM_BLOCK_BINDING 0x8A3F -#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 -#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 -#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 -#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 -#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 -#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 -#define GL_INVALID_INDEX 0xFFFFFFFFu -#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 -#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 -#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 -#define GL_OBJECT_TYPE 0x9112 -#define GL_SYNC_CONDITION 0x9113 -#define GL_SYNC_STATUS 0x9114 -#define GL_SYNC_FLAGS 0x9115 -#define GL_SYNC_FENCE 0x9116 -#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 -#define GL_UNSIGNALED 0x9118 -#define GL_SIGNALED 0x9119 -#define GL_ALREADY_SIGNALED 0x911A -#define GL_TIMEOUT_EXPIRED 0x911B -#define GL_CONDITION_SATISFIED 0x911C -#define GL_WAIT_FAILED 0x911D -#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 -#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull -#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE -#define GL_ANY_SAMPLES_PASSED 0x8C2F -#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A -#define GL_SAMPLER_BINDING 0x8919 -#define GL_RGB10_A2UI 0x906F -#define GL_TEXTURE_SWIZZLE_R 0x8E42 -#define GL_TEXTURE_SWIZZLE_G 0x8E43 -#define GL_TEXTURE_SWIZZLE_B 0x8E44 -#define GL_TEXTURE_SWIZZLE_A 0x8E45 -#define GL_GREEN 0x1904 -#define GL_BLUE 0x1905 -#define GL_INT_2_10_10_10_REV 0x8D9F -#define GL_TRANSFORM_FEEDBACK 0x8E22 -#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 -#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 -#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 -#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 -#define GL_PROGRAM_BINARY_LENGTH 0x8741 -#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE -#define GL_PROGRAM_BINARY_FORMATS 0x87FF -#define GL_COMPRESSED_R11_EAC 0x9270 -#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 -#define GL_COMPRESSED_RG11_EAC 0x9272 -#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 -#define GL_COMPRESSED_RGB8_ETC2 0x9274 -#define GL_COMPRESSED_SRGB8_ETC2 0x9275 -#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 -#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 -#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 -#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 -#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F -#define GL_MAX_ELEMENT_INDEX 0x8D6B -#define GL_NUM_SAMPLE_COUNTS 0x9380 -#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF - -/*------------------------------------------------------------------------- - * Entrypoint definitions - *-----------------------------------------------------------------------*/ - -/* OpenGL ES 2.0 */ - -GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture); -GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader); -GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name); -GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); -GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); -GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); -GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); -GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode); -GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); -GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); -GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); -GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); -GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target); -GL_APICALL void GL_APIENTRY glClear (GLbitfield mask); -GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat depth); -GL_APICALL void GL_APIENTRY glClearStencil (GLint s); -GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader); -GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data); -GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data); -GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL GLuint GL_APIENTRY glCreateProgram (void); -GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type); -GL_APICALL void GL_APIENTRY glCullFace (GLenum mode); -GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers); -GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers); -GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program); -GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers); -GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader); -GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures); -GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func); -GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag); -GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f); -GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader); -GL_APICALL void GL_APIENTRY glDisable (GLenum cap); -GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index); -GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); -GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices); -GL_APICALL void GL_APIENTRY glEnable (GLenum cap); -GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index); -GL_APICALL void GL_APIENTRY glFinish (void); -GL_APICALL void GL_APIENTRY glFlush (void); -GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode); -GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers); -GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target); -GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers); -GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers); -GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures); -GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); -GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); -GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); -GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name); -GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params); -GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params); -GL_APICALL GLenum GL_APIENTRY glGetError (void); -GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params); -GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog); -GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog); -GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); -GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source); -GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name); -GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params); -GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params); -GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params); -GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name); -GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params); -GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer); -GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode); -GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer); -GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap); -GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer); -GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program); -GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer); -GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader); -GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture); -GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width); -GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program); -GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); -GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); -GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void); -GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert); -GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length); -GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length); -GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask); -GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); -GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass); -GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels); -GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); -GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params); -GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params); -GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels); -GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x); -GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v); -GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x); -GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v); -GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y); -GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v); -GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y); -GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v); -GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z); -GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v); -GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z); -GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v); -GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v); -GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w); -GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v); -GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUseProgram (GLuint program); -GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program); -GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x); -GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values); -GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y); -GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values); -GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z); -GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values); -GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values); -GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr); -GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); - -/* OpenGL ES 3.0 */ - -GL_APICALL void GL_APIENTRY glReadBuffer (GLenum mode); -GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices); -GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); -GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); -GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); -GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); -GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint* ids); -GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint* ids); -GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id); -GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id); -GL_APICALL void GL_APIENTRY glEndQuery (GLenum target); -GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint* params); -GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target); -GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, GLvoid** params); -GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum* bufs); -GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); -GL_APICALL GLvoid* GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); -GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length); -GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array); -GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint* arrays); -GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint* arrays); -GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array); -GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint* data); -GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode); -GL_APICALL void GL_APIENTRY glEndTransformFeedback (void); -GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); -GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer); -GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode); -GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name); -GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer); -GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint* params); -GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w); -GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint* v); -GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint* v); -GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint* params); -GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name); -GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0); -GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1); -GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2); -GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint* value); -GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint* value); -GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint* value); -GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint* value); -GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint* value); -GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint* value); -GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat* value); -GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); -GL_APICALL const GLubyte* GL_APIENTRY glGetStringi (GLenum name, GLuint index); -GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); -GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices); -GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params); -GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar* uniformBlockName); -GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName); -GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); -GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instanceCount); -GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount); -GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags); -GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync); -GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync); -GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); -GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); -GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64* params); -GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values); -GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64* data); -GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64* params); -GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint* samplers); -GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint* samplers); -GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler); -GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler); -GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint* param); -GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param); -GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat* param); -GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint* params); -GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat* params); -GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor); -GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id); -GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint* ids); -GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint* ids); -GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id); -GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void); -GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void); -GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary); -GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length); -GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value); -GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum* attachments); -GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/platform/winrt/include/GLES3/gl3ext.h b/platform/winrt/include/GLES3/gl3ext.h deleted file mode 100644 index 4d4ea96c4d..0000000000 --- a/platform/winrt/include/GLES3/gl3ext.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef __gl3ext_h_ -#define __gl3ext_h_ - -/* $Revision: 17809 $ on $Date:: 2012-05-14 08:03:36 -0700 #$ */ - -/* - * This document is licensed under the SGI Free Software B License Version - * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . - */ - -/* OpenGL ES 3 Extensions - * - * After an OES extension's interactions with OpenGl ES 3.0 have been documented, - * its tokens and function definitions should be added to this file in a manner - * that does not conflict with gl2ext.h or gl3.h. - * - * Tokens and function definitions for extensions that have become standard - * features in OpenGL ES 3.0 will not be added to this file. - * - * Applications using OpenGL-ES-2-only extensions should include gl2ext.h - */ - -#endif /* __gl3ext_h_ */ - diff --git a/platform/winrt/include/GLES3/gl3platform.h b/platform/winrt/include/GLES3/gl3platform.h deleted file mode 100644 index 1bd1a850fa..0000000000 --- a/platform/winrt/include/GLES3/gl3platform.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __gl3platform_h_ -#define __gl3platform_h_ - -/* $Revision: 18437 $ on $Date:: 2012-07-08 23:31:39 -0700 #$ */ - -/* - * This document is licensed under the SGI Free Software B License Version - * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . - */ - -/* Platform-specific types and definitions for OpenGL ES 3.X gl3.h - * - * Adopters may modify khrplatform.h and this file to suit their platform. - * You are encouraged to submit all modifications to the Khronos group so that - * they can be included in future versions of this file. Please submit changes - * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) - * by filing a bug against product "OpenGL-ES" component "Registry". - */ - -#include <KHR/khrplatform.h> - -#ifndef GL_APICALL -#define GL_APICALL KHRONOS_APICALL -#endif - -#ifndef GL_APIENTRY -#define GL_APIENTRY KHRONOS_APIENTRY -#endif - -#endif /* __gl3platform_h_ */ diff --git a/platform/winrt/include/GLSLANG/ShaderLang.h b/platform/winrt/include/GLSLANG/ShaderLang.h deleted file mode 100644 index e486692482..0000000000 --- a/platform/winrt/include/GLSLANG/ShaderLang.h +++ /dev/null @@ -1,411 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -#ifndef _COMPILER_INTERFACE_INCLUDED_ -#define _COMPILER_INTERFACE_INCLUDED_ - -#if defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC) -#if defined(_WIN32) || defined(_WIN64) - -#if defined(ANGLE_TRANSLATOR_IMPLEMENTATION) -#define COMPILER_EXPORT __declspec(dllexport) -#else -#define COMPILER_EXPORT __declspec(dllimport) -#endif // defined(ANGLE_TRANSLATOR_IMPLEMENTATION) - -#else // defined(_WIN32) || defined(_WIN64) -#define COMPILER_EXPORT __attribute__((visibility("default"))) -#endif - -#else // defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC) -#define COMPILER_EXPORT -#endif - -#include <stddef.h> - -#include "KHR/khrplatform.h" - -#include <map> -#include <string> -#include <vector> - -// -// This is the platform independent interface between an OGL driver -// and the shading language compiler. -// - -namespace sh -{ -// GLenum alias -typedef unsigned int GLenum; -} - -// Must be included after GLenum proxy typedef -// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h -#include "ShaderVars.h" - -// Version number for shader translation API. -// It is incremented every time the API changes. -#define ANGLE_SH_VERSION 132 - -typedef enum { - SH_GLES2_SPEC = 0x8B40, - SH_WEBGL_SPEC = 0x8B41, - - SH_GLES3_SPEC = 0x8B86, - SH_WEBGL2_SPEC = 0x8B87, - - // The CSS Shaders spec is a subset of the WebGL spec. - // - // In both CSS vertex and fragment shaders, ANGLE: - // (1) Reserves the "css_" prefix. - // (2) Renames the main function to css_main. - // (3) Disables the gl_MaxDrawBuffers built-in. - // - // In CSS fragment shaders, ANGLE: - // (1) Disables the gl_FragColor built-in. - // (2) Disables the gl_FragData built-in. - // (3) Enables the css_MixColor built-in. - // (4) Enables the css_ColorMatrix built-in. - // - // After passing a CSS shader through ANGLE, the browser is expected to append - // a new main function to it. - // This new main function will call the css_main function. - // It may also perform additional operations like varying assignment, texture - // access, and gl_FragColor assignment in order to implement the CSS Shaders - // blend modes. - // - SH_CSS_SHADERS_SPEC = 0x8B42 -} ShShaderSpec; - -typedef enum { - SH_ESSL_OUTPUT = 0x8B45, - SH_GLSL_OUTPUT = 0x8B46, - SH_HLSL_OUTPUT = 0x8B47, - SH_HLSL9_OUTPUT = 0x8B47, - SH_HLSL11_OUTPUT = 0x8B48 -} ShShaderOutput; - -// Compile options. -typedef enum { - SH_VALIDATE = 0, - SH_VALIDATE_LOOP_INDEXING = 0x0001, - SH_INTERMEDIATE_TREE = 0x0002, - SH_OBJECT_CODE = 0x0004, - SH_VARIABLES = 0x0008, - SH_LINE_DIRECTIVES = 0x0010, - SH_SOURCE_PATH = 0x0020, - SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX = 0x0040, - // If a sampler array index happens to be a loop index, - // 1) if its type is integer, unroll the loop. - // 2) if its type is float, fail the shader compile. - // This is to work around a mac driver bug. - SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX = 0x0080, - - // This is needed only as a workaround for certain OpenGL driver bugs. - SH_EMULATE_BUILT_IN_FUNCTIONS = 0x0100, - - // This is an experimental flag to enforce restrictions that aim to prevent - // timing attacks. - // It generates compilation errors for shaders that could expose sensitive - // texture information via the timing channel. - // To use this flag, you must compile the shader under the WebGL spec - // (using the SH_WEBGL_SPEC flag). - SH_TIMING_RESTRICTIONS = 0x0200, - - // This flag prints the dependency graph that is used to enforce timing - // restrictions on fragment shaders. - // This flag only has an effect if all of the following are true: - // - The shader spec is SH_WEBGL_SPEC. - // - The compile options contain the SH_TIMING_RESTRICTIONS flag. - // - The shader type is GL_FRAGMENT_SHADER. - SH_DEPENDENCY_GRAPH = 0x0400, - - // Enforce the GLSL 1.017 Appendix A section 7 packing restrictions. - // This flag only enforces (and can only enforce) the packing - // restrictions for uniform variables in both vertex and fragment - // shaders. ShCheckVariablesWithinPackingLimits() lets embedders - // enforce the packing restrictions for varying variables during - // program link time. - SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800, - - // This flag ensures all indirect (expression-based) array indexing - // is clamped to the bounds of the array. This ensures, for example, - // that you cannot read off the end of a uniform, whether an array - // vec234, or mat234 type. The ShArrayIndexClampingStrategy enum, - // specified in the ShBuiltInResources when constructing the - // compiler, selects the strategy for the clamping implementation. - SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000, - - // This flag limits the complexity of an expression. - SH_LIMIT_EXPRESSION_COMPLEXITY = 0x2000, - - // This flag limits the depth of the call stack. - SH_LIMIT_CALL_STACK_DEPTH = 0x4000, - - // This flag initializes gl_Position to vec4(0,0,0,0) at the - // beginning of the vertex shader's main(), and has no effect in the - // fragment shader. It is intended as a workaround for drivers which - // incorrectly fail to link programs if gl_Position is not written. - SH_INIT_GL_POSITION = 0x8000, - - // This flag replaces - // "a && b" with "a ? b : false", - // "a || b" with "a ? true : b". - // This is to work around a MacOSX driver bug that |b| is executed - // independent of |a|'s value. - SH_UNFOLD_SHORT_CIRCUIT = 0x10000, - - // This flag initializes varyings without static use in vertex shader - // at the beginning of main(), and has no effects in the fragment shader. - // It is intended as a workaround for drivers which incorrectly optimize - // out such varyings and cause a link failure. - SH_INIT_VARYINGS_WITHOUT_STATIC_USE = 0x20000, - - // This flag scalarizes vec/ivec/bvec/mat constructor args. - // It is intended as a workaround for Linux/Mac driver bugs. - SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS = 0x40000, - - // This flag overwrites a struct name with a unique prefix. - // It is intended as a workaround for drivers that do not handle - // struct scopes correctly, including all Mac drivers and Linux AMD. - SH_REGENERATE_STRUCT_NAMES = 0x80000, -} ShCompileOptions; - -// Defines alternate strategies for implementing array index clamping. -typedef enum { - // Use the clamp intrinsic for array index clamping. - SH_CLAMP_WITH_CLAMP_INTRINSIC = 1, - - // Use a user-defined function for array index clamping. - SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION -} ShArrayIndexClampingStrategy; - -// -// Driver must call this first, once, before doing any other -// compiler operations. -// If the function succeeds, the return value is true, else false. -// -COMPILER_EXPORT bool ShInitialize(); -// -// Driver should call this at shutdown. -// If the function succeeds, the return value is true, else false. -// -COMPILER_EXPORT bool ShFinalize(); - -// The 64 bits hash function. The first parameter is the input string; the -// second parameter is the string length. -typedef khronos_uint64_t (*ShHashFunction64)(const char*, size_t); - -// -// Implementation dependent built-in resources (constants and extensions). -// The names for these resources has been obtained by stripping gl_/GL_. -// -typedef struct -{ - // Constants. - int MaxVertexAttribs; - int MaxVertexUniformVectors; - int MaxVaryingVectors; - int MaxVertexTextureImageUnits; - int MaxCombinedTextureImageUnits; - int MaxTextureImageUnits; - int MaxFragmentUniformVectors; - int MaxDrawBuffers; - - // Extensions. - // Set to 1 to enable the extension, else 0. - int OES_standard_derivatives; - int OES_EGL_image_external; - int ARB_texture_rectangle; - int EXT_draw_buffers; - int EXT_frag_depth; - int EXT_shader_texture_lod; - - // Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives - // with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate - // EXT_draw_buffers by using it in combination with GLES3.0 glDrawBuffers - // function. This applies to Tegra K1 devices. - int NV_draw_buffers; - - // Set to 1 if highp precision is supported in the fragment language. - // Default is 0. - int FragmentPrecisionHigh; - - // GLSL ES 3.0 constants. - int MaxVertexOutputVectors; - int MaxFragmentInputVectors; - int MinProgramTexelOffset; - int MaxProgramTexelOffset; - - // Name Hashing. - // Set a 64 bit hash function to enable user-defined name hashing. - // Default is NULL. - ShHashFunction64 HashFunction; - - // Selects a strategy to use when implementing array index clamping. - // Default is SH_CLAMP_WITH_CLAMP_INTRINSIC. - ShArrayIndexClampingStrategy ArrayIndexClampingStrategy; - - // The maximum complexity an expression can be. - int MaxExpressionComplexity; - - // The maximum depth a call stack can be. - int MaxCallStackDepth; -} ShBuiltInResources; - -// -// Initialize built-in resources with minimum expected values. -// Parameters: -// resources: The object to initialize. Will be comparable with memcmp. -// -COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources *resources); - -// -// ShHandle held by but opaque to the driver. It is allocated, -// managed, and de-allocated by the compiler. Its contents -// are defined by and used by the compiler. -// -// If handle creation fails, 0 will be returned. -// -typedef void *ShHandle; - -// -// Returns the a concatenated list of the items in ShBuiltInResources as a -// null-terminated string. -// This function must be updated whenever ShBuiltInResources is changed. -// Parameters: -// handle: Specifies the handle of the compiler to be used. -COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle handle); - -// -// Driver calls these to create and destroy compiler objects. -// -// Returns the handle of constructed compiler, null if the requested compiler is -// not supported. -// Parameters: -// type: Specifies the type of shader - GL_FRAGMENT_SHADER or GL_VERTEX_SHADER. -// spec: Specifies the language spec the compiler must conform to - -// SH_GLES2_SPEC or SH_WEBGL_SPEC. -// output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT, -// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. -// resources: Specifies the built-in resources. -COMPILER_EXPORT ShHandle ShConstructCompiler( - sh::GLenum type, - ShShaderSpec spec, - ShShaderOutput output, - const ShBuiltInResources *resources); -COMPILER_EXPORT void ShDestruct(ShHandle handle); - -// -// Compiles the given shader source. -// If the function succeeds, the return value is true, else false. -// Parameters: -// handle: Specifies the handle of compiler to be used. -// shaderStrings: Specifies an array of pointers to null-terminated strings -// containing the shader source code. -// numStrings: Specifies the number of elements in shaderStrings array. -// compileOptions: A mask containing the following parameters: -// SH_VALIDATE: Validates shader to ensure that it conforms to the spec -// specified during compiler construction. -// SH_VALIDATE_LOOP_INDEXING: Validates loop and indexing in the shader to -// ensure that they do not exceed the minimum -// functionality mandated in GLSL 1.0 spec, -// Appendix A, Section 4 and 5. -// There is no need to specify this parameter when -// compiling for WebGL - it is implied. -// SH_INTERMEDIATE_TREE: Writes intermediate tree to info log. -// Can be queried by calling ShGetInfoLog(). -// SH_OBJECT_CODE: Translates intermediate tree to glsl or hlsl shader. -// Can be queried by calling ShGetObjectCode(). -// SH_VARIABLES: Extracts attributes, uniforms, and varyings. -// Can be queried by calling ShGetVariableInfo(). -// -COMPILER_EXPORT bool ShCompile( - const ShHandle handle, - const char * const shaderStrings[], - size_t numStrings, - int compileOptions); - -// Return the version of the shader language. -COMPILER_EXPORT int ShGetShaderVersion(const ShHandle handle); - -// Return the currently set language output type. -COMPILER_EXPORT ShShaderOutput ShGetShaderOutputType( - const ShHandle handle); - -// Returns null-terminated information log for a compiled shader. -// Parameters: -// handle: Specifies the compiler -COMPILER_EXPORT const std::string &ShGetInfoLog(const ShHandle handle); - -// Returns null-terminated object code for a compiled shader. -// Parameters: -// handle: Specifies the compiler -COMPILER_EXPORT const std::string &ShGetObjectCode(const ShHandle handle); - -// Returns a (original_name, hash) map containing all the user defined -// names in the shader, including variable names, function names, struct -// names, and struct field names. -// Parameters: -// handle: Specifies the compiler -COMPILER_EXPORT const std::map<std::string, std::string> *ShGetNameHashingMap( - const ShHandle handle); - -// Shader variable inspection. -// Returns a pointer to a list of variables of the designated type. -// (See ShaderVars.h for type definitions, included above) -// Returns NULL on failure. -// Parameters: -// handle: Specifies the compiler -COMPILER_EXPORT const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle); -COMPILER_EXPORT const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle); -COMPILER_EXPORT const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle); -COMPILER_EXPORT const std::vector<sh::Attribute> *ShGetOutputVariables(const ShHandle handle); -COMPILER_EXPORT const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle); - -typedef struct -{ - sh::GLenum type; - int size; -} ShVariableInfo; - -// Returns true if the passed in variables pack in maxVectors following -// the packing rules from the GLSL 1.017 spec, Appendix A, section 7. -// Returns false otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS -// flag above. -// Parameters: -// maxVectors: the available rows of registers. -// varInfoArray: an array of variable info (types and sizes). -// varInfoArraySize: the size of the variable array. -COMPILER_EXPORT bool ShCheckVariablesWithinPackingLimits( - int maxVectors, - ShVariableInfo *varInfoArray, - size_t varInfoArraySize); - -// Gives the compiler-assigned register for an interface block. -// The method writes the value to the output variable "indexOut". -// Returns true if it found a valid interface block, false otherwise. -// Parameters: -// handle: Specifies the compiler -// interfaceBlockName: Specifies the interface block -// indexOut: output variable that stores the assigned register -COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle, - const std::string &interfaceBlockName, - unsigned int *indexOut); - -// Gives the compiler-assigned register for uniforms in the default -// interface block. -// The method writes the value to the output variable "indexOut". -// Returns true if it found a valid default uniform, false otherwise. -// Parameters: -// handle: Specifies the compiler -// interfaceBlockName: Specifies the uniform -// indexOut: output variable that stores the assigned register -COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle, - const std::string &uniformName, - unsigned int *indexOut); - -#endif // _COMPILER_INTERFACE_INCLUDED_ diff --git a/platform/winrt/include/GLSLANG/ShaderVars.h b/platform/winrt/include/GLSLANG/ShaderVars.h deleted file mode 100644 index da21c3e76e..0000000000 --- a/platform/winrt/include/GLSLANG/ShaderVars.h +++ /dev/null @@ -1,185 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ShaderVars.h: -// Types to represent GL variables (varyings, uniforms, etc) -// - -#ifndef _COMPILER_INTERFACE_VARIABLES_ -#define _COMPILER_INTERFACE_VARIABLES_ - -#include <string> -#include <vector> -#include <algorithm> - -// Assume ShaderLang.h is included before ShaderVars.h, for sh::GLenum -// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h - -namespace sh -{ - -// Varying interpolation qualifier, see section 4.3.9 of the ESSL 3.00.4 spec -enum InterpolationType -{ - INTERPOLATION_SMOOTH, - INTERPOLATION_CENTROID, - INTERPOLATION_FLAT -}; - -// Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec -enum BlockLayoutType -{ - BLOCKLAYOUT_STANDARD, - BLOCKLAYOUT_PACKED, - BLOCKLAYOUT_SHARED -}; - -// Base class for all variables defined in shaders, including Varyings, Uniforms, etc -// Note: we must override the copy constructor and assignment operator so we can -// work around excessive GCC binary bloating: -// See https://code.google.com/p/angleproject/issues/detail?id=697 -struct COMPILER_EXPORT ShaderVariable -{ - ShaderVariable(); - ShaderVariable(GLenum typeIn, unsigned int arraySizeIn); - ~ShaderVariable(); - ShaderVariable(const ShaderVariable &other); - ShaderVariable &operator=(const ShaderVariable &other); - - bool isArray() const { return arraySize > 0; } - unsigned int elementCount() const { return std::max(1u, arraySize); } - bool isStruct() const { return !fields.empty(); } - - // All of the shader's variables are described using nested data - // structures. This is needed in order to disambiguate similar looking - // types, such as two structs containing the same fields, but in - // different orders. "findInfoByMappedName" provides an easy query for - // users to dive into the data structure and fetch the unique variable - // instance corresponding to a dereferencing chain of the top-level - // variable. - // Given a mapped name like 'a[0].b.c[0]', return the ShaderVariable - // that defines 'c' in |leafVar|, and the original name 'A[0].B.C[0]' - // in |originalName|, based on the assumption that |this| defines 'a'. - // If no match is found, return false. - bool findInfoByMappedName(const std::string &mappedFullName, - const ShaderVariable **leafVar, - std::string* originalFullName) const; - - GLenum type; - GLenum precision; - std::string name; - std::string mappedName; - unsigned int arraySize; - bool staticUse; - std::vector<ShaderVariable> fields; - std::string structName; - - protected: - bool isSameVariableAtLinkTime(const ShaderVariable &other, - bool matchPrecision) const; - - bool operator==(const ShaderVariable &other) const; - bool operator!=(const ShaderVariable &other) const - { - return !operator==(other); - } -}; - -struct COMPILER_EXPORT Uniform : public ShaderVariable -{ - Uniform(); - ~Uniform(); - Uniform(const Uniform &other); - Uniform &operator=(const Uniform &other); - bool operator==(const Uniform &other) const; - bool operator!=(const Uniform &other) const - { - return !operator==(other); - } - - // Decide whether two uniforms are the same at shader link time, - // assuming one from vertex shader and the other from fragment shader. - // See GLSL ES Spec 3.00.3, sec 4.3.5. - bool isSameUniformAtLinkTime(const Uniform &other) const; -}; - -struct COMPILER_EXPORT Attribute : public ShaderVariable -{ - Attribute(); - ~Attribute(); - Attribute(const Attribute &other); - Attribute &operator=(const Attribute &other); - bool operator==(const Attribute &other) const; - bool operator!=(const Attribute &other) const - { - return !operator==(other); - } - - int location; -}; - -struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable -{ - InterfaceBlockField(); - ~InterfaceBlockField(); - InterfaceBlockField(const InterfaceBlockField &other); - InterfaceBlockField &operator=(const InterfaceBlockField &other); - bool operator==(const InterfaceBlockField &other) const; - bool operator!=(const InterfaceBlockField &other) const - { - return !operator==(other); - } - - // Decide whether two InterfaceBlock fields are the same at shader - // link time, assuming one from vertex shader and the other from - // fragment shader. - // See GLSL ES Spec 3.00.3, sec 4.3.7. - bool isSameInterfaceBlockFieldAtLinkTime( - const InterfaceBlockField &other) const; - - bool isRowMajorLayout; -}; - -struct COMPILER_EXPORT Varying : public ShaderVariable -{ - Varying(); - ~Varying(); - Varying(const Varying &otherg); - Varying &operator=(const Varying &other); - bool operator==(const Varying &other) const; - bool operator!=(const Varying &other) const - { - return !operator==(other); - } - - // Decide whether two varyings are the same at shader link time, - // assuming one from vertex shader and the other from fragment shader. - // See GLSL ES Spec 3.00.3, sec 4.3.9. - bool isSameVaryingAtLinkTime(const Varying &other) const; - - InterpolationType interpolation; - bool isInvariant; -}; - -struct COMPILER_EXPORT InterfaceBlock -{ - InterfaceBlock(); - ~InterfaceBlock(); - InterfaceBlock(const InterfaceBlock &other); - InterfaceBlock &operator=(const InterfaceBlock &other); - - std::string name; - std::string mappedName; - std::string instanceName; - unsigned int arraySize; - BlockLayoutType layout; - bool isRowMajorLayout; - bool staticUse; - std::vector<InterfaceBlockField> fields; -}; - -} - -#endif // _COMPILER_INTERFACE_VARIABLES_ diff --git a/platform/winrt/include/KHR/khrplatform.h b/platform/winrt/include/KHR/khrplatform.h deleted file mode 100644 index 43aac97a73..0000000000 --- a/platform/winrt/include/KHR/khrplatform.h +++ /dev/null @@ -1,282 +0,0 @@ -#ifndef __khrplatform_h_ -#define __khrplatform_h_ - -/* -** Copyright (c) 2008-2009 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ - -/* Khronos platform-specific types and definitions. - * - * $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $ - * - * Adopters may modify this file to suit their platform. Adopters are - * encouraged to submit platform specific modifications to the Khronos - * group so that they can be included in future versions of this file. - * Please submit changes by sending them to the public Khronos Bugzilla - * (http://khronos.org/bugzilla) by filing a bug against product - * "Khronos (general)" component "Registry". - * - * A predefined template which fills in some of the bug fields can be - * reached using http://tinyurl.com/khrplatform-h-bugreport, but you - * must create a Bugzilla login first. - * - * - * See the Implementer's Guidelines for information about where this file - * should be located on your system and for more details of its use: - * http://www.khronos.org/registry/implementers_guide.pdf - * - * This file should be included as - * #include <KHR/khrplatform.h> - * by Khronos client API header files that use its types and defines. - * - * The types in khrplatform.h should only be used to define API-specific types. - * - * Types defined in khrplatform.h: - * khronos_int8_t signed 8 bit - * khronos_uint8_t unsigned 8 bit - * khronos_int16_t signed 16 bit - * khronos_uint16_t unsigned 16 bit - * khronos_int32_t signed 32 bit - * khronos_uint32_t unsigned 32 bit - * khronos_int64_t signed 64 bit - * khronos_uint64_t unsigned 64 bit - * khronos_intptr_t signed same number of bits as a pointer - * khronos_uintptr_t unsigned same number of bits as a pointer - * khronos_ssize_t signed size - * khronos_usize_t unsigned size - * khronos_float_t signed 32 bit floating point - * khronos_time_ns_t unsigned 64 bit time in nanoseconds - * khronos_utime_nanoseconds_t unsigned time interval or absolute time in - * nanoseconds - * khronos_stime_nanoseconds_t signed time interval in nanoseconds - * khronos_boolean_enum_t enumerated boolean type. This should - * only be used as a base type when a client API's boolean type is - * an enum. Client APIs which use an integer or other type for - * booleans cannot use this as the base type for their boolean. - * - * Tokens defined in khrplatform.h: - * - * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. - * - * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. - * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. - * - * Calling convention macros defined in this file: - * KHRONOS_APICALL - * KHRONOS_APIENTRY - * KHRONOS_APIATTRIBUTES - * - * These may be used in function prototypes as: - * - * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( - * int arg1, - * int arg2) KHRONOS_APIATTRIBUTES; - */ - -/*------------------------------------------------------------------------- - * Definition of KHRONOS_APICALL - *------------------------------------------------------------------------- - * This precedes the return type of the function in the function prototype. - */ -#if defined(_WIN32) && !defined(__SCITECH_SNAP__) -# define KHRONOS_APICALL __declspec(dllimport) -#elif defined (__SYMBIAN32__) -# define KHRONOS_APICALL IMPORT_C -#else -# define KHRONOS_APICALL -#endif - -/*------------------------------------------------------------------------- - * Definition of KHRONOS_APIENTRY - *------------------------------------------------------------------------- - * This follows the return type of the function and precedes the function - * name in the function prototype. - */ -#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) - /* Win32 but not WinCE */ -# define KHRONOS_APIENTRY __stdcall -#else -# define KHRONOS_APIENTRY -#endif - -/*------------------------------------------------------------------------- - * Definition of KHRONOS_APIATTRIBUTES - *------------------------------------------------------------------------- - * This follows the closing parenthesis of the function prototype arguments. - */ -#if defined (__ARMCC_2__) -#define KHRONOS_APIATTRIBUTES __softfp -#else -#define KHRONOS_APIATTRIBUTES -#endif - -/*------------------------------------------------------------------------- - * basic type definitions - *-----------------------------------------------------------------------*/ -#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) - - -/* - * Using <stdint.h> - */ -#include <stdint.h> -typedef int32_t khronos_int32_t; -typedef uint32_t khronos_uint32_t; -typedef int64_t khronos_int64_t; -typedef uint64_t khronos_uint64_t; -#define KHRONOS_SUPPORT_INT64 1 -#define KHRONOS_SUPPORT_FLOAT 1 - -#elif defined(__VMS ) || defined(__sgi) - -/* - * Using <inttypes.h> - */ -#include <inttypes.h> -typedef int32_t khronos_int32_t; -typedef uint32_t khronos_uint32_t; -typedef int64_t khronos_int64_t; -typedef uint64_t khronos_uint64_t; -#define KHRONOS_SUPPORT_INT64 1 -#define KHRONOS_SUPPORT_FLOAT 1 - -#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) - -/* - * Win32 - */ -typedef __int32 khronos_int32_t; -typedef unsigned __int32 khronos_uint32_t; -typedef __int64 khronos_int64_t; -typedef unsigned __int64 khronos_uint64_t; -#define KHRONOS_SUPPORT_INT64 1 -#define KHRONOS_SUPPORT_FLOAT 1 - -#elif defined(__sun__) || defined(__digital__) - -/* - * Sun or Digital - */ -typedef int khronos_int32_t; -typedef unsigned int khronos_uint32_t; -#if defined(__arch64__) || defined(_LP64) -typedef long int khronos_int64_t; -typedef unsigned long int khronos_uint64_t; -#else -typedef long long int khronos_int64_t; -typedef unsigned long long int khronos_uint64_t; -#endif /* __arch64__ */ -#define KHRONOS_SUPPORT_INT64 1 -#define KHRONOS_SUPPORT_FLOAT 1 - -#elif 0 - -/* - * Hypothetical platform with no float or int64 support - */ -typedef int khronos_int32_t; -typedef unsigned int khronos_uint32_t; -#define KHRONOS_SUPPORT_INT64 0 -#define KHRONOS_SUPPORT_FLOAT 0 - -#else - -/* - * Generic fallback - */ -#include <stdint.h> -typedef int32_t khronos_int32_t; -typedef uint32_t khronos_uint32_t; -typedef int64_t khronos_int64_t; -typedef uint64_t khronos_uint64_t; -#define KHRONOS_SUPPORT_INT64 1 -#define KHRONOS_SUPPORT_FLOAT 1 - -#endif - - -/* - * Types that are (so far) the same on all platforms - */ -typedef signed char khronos_int8_t; -typedef unsigned char khronos_uint8_t; -typedef signed short int khronos_int16_t; -typedef unsigned short int khronos_uint16_t; - -/* - * Types that differ between LLP64 and LP64 architectures - in LLP64, - * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears - * to be the only LLP64 architecture in current use. - */ -#ifdef _WIN64 -typedef signed long long int khronos_intptr_t; -typedef unsigned long long int khronos_uintptr_t; -typedef signed long long int khronos_ssize_t; -typedef unsigned long long int khronos_usize_t; -#else -typedef signed long int khronos_intptr_t; -typedef unsigned long int khronos_uintptr_t; -typedef signed long int khronos_ssize_t; -typedef unsigned long int khronos_usize_t; -#endif - -#if KHRONOS_SUPPORT_FLOAT -/* - * Float type - */ -typedef float khronos_float_t; -#endif - -#if KHRONOS_SUPPORT_INT64 -/* Time types - * - * These types can be used to represent a time interval in nanoseconds or - * an absolute Unadjusted System Time. Unadjusted System Time is the number - * of nanoseconds since some arbitrary system event (e.g. since the last - * time the system booted). The Unadjusted System Time is an unsigned - * 64 bit value that wraps back to 0 every 584 years. Time intervals - * may be either signed or unsigned. - */ -typedef khronos_uint64_t khronos_utime_nanoseconds_t; -typedef khronos_int64_t khronos_stime_nanoseconds_t; -#endif - -/* - * Dummy value used to pad enum types to 32 bits. - */ -#ifndef KHRONOS_MAX_ENUM -#define KHRONOS_MAX_ENUM 0x7FFFFFFF -#endif - -/* - * Enumerated boolean type - * - * Values other than zero should be considered to be true. Therefore - * comparisons should not be made against KHRONOS_TRUE. - */ -typedef enum { - KHRONOS_FALSE = 0, - KHRONOS_TRUE = 1, - KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM -} khronos_boolean_enum_t; - -#endif /* __khrplatform_h_ */ diff --git a/platform/winrt/include/LICENSE.ANGLE.txt b/platform/winrt/include/LICENSE.ANGLE.txt deleted file mode 100644 index bdacb32e36..0000000000 --- a/platform/winrt/include/LICENSE.ANGLE.txt +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2002-2013 The ANGLE Project Authors. -// 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 TransGaming Inc., Google Inc., 3DLabs Inc. -// Ltd., nor the names of their 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. diff --git a/platform/winrt/include/angle_gl.h b/platform/winrt/include/angle_gl.h deleted file mode 100644 index d093f75ee2..0000000000 --- a/platform/winrt/include/angle_gl.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// angle_gl.h: -// Includes all necessary GL headers and definitions for ANGLE. -// - -#ifndef ANGLE_GL_H_ -#define ANGLE_GL_H_ - -#include "GLES2/gl2.h" -#include "GLES2/gl2ext.h" -#include "GLES3/gl3.h" -#include "GLES3/gl3ext.h" - -// The following enum is used in ANGLE, but is from desktop GL -#ifndef GL_SAMPLER_2D_RECT_ARB -#define GL_SAMPLER_2D_RECT_ARB 0x8B63 -#endif - -#endif // ANGLE_GL_H_ diff --git a/platform/winrt/include/angle_windowsstore.h b/platform/winrt/include/angle_windowsstore.h deleted file mode 100644 index 53ec93e037..0000000000 --- a/platform/winrt/include/angle_windowsstore.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// angle_windowsstore.h: - -#ifndef ANGLE_WINDOWSSTORE_H_ -#define ANGLE_WINDOWSSTORE_H_ - -// The following properties can be set on the CoreApplication to support additional -// ANGLE configuration options. -// -// The Visual Studio sample templates provided with this version of ANGLE have examples -// of how to set these property values. - -// -// Property: EGLNativeWindowTypeProperty -// Type: IInspectable -// Description: Set this property to specify the window type to use for creating a surface. -// If this property is missing, surface creation will fail. -// -const wchar_t EGLNativeWindowTypeProperty[] = L"EGLNativeWindowTypeProperty"; - -// -// Property: EGLRenderSurfaceSizeProperty -// Type: Size -// Description: Set this property to specify a preferred size in pixels of the render surface. -// The render surface size width and height must be greater than 0. -// If this property is set, then the render surface size is fixed. -// If this property is missing, a default behavior will be provided. -// The default behavior uses the window size if a CoreWindow is specified or -// the size of the SwapChainPanel control if one is specified. -// -const wchar_t EGLRenderSurfaceSizeProperty[] = L"EGLRenderSurfaceSizeProperty"; - -#endif // ANGLE_WINDOWSSTORE_H_ diff --git a/platform/winrt/joystick_winrt.cpp b/platform/winrt/joystick_winrt.cpp new file mode 100644 index 0000000000..9f93c5a26b --- /dev/null +++ b/platform/winrt/joystick_winrt.cpp @@ -0,0 +1,147 @@ +/*************************************************************************/ +/* joystick.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "joystick_winrt.h" + +using namespace Windows::Gaming::Input; +using namespace Windows::Foundation; + +void JoystickWinrt::register_events() { + + Gamepad::GamepadAdded += + ref new EventHandler<Gamepad^>(this, &JoystickWinrt::OnGamepadAdded); + Gamepad::GamepadRemoved += + ref new EventHandler<Gamepad^>(this, &JoystickWinrt::OnGamepadRemoved); +} + +uint32_t JoystickWinrt::process_controllers(uint32_t p_last_id) { + + for (int i = 0; i < MAX_CONTROLLERS; i++) { + + if (!controllers[i].connected) break; + + switch (controllers[i].type) { + + case ControllerType::GAMEPAD_CONTROLLER: { + + GamepadReading reading = ((Gamepad^)controllers[i].controller_reference)->GetCurrentReading(); + + int button_mask = (int)GamepadButtons::Menu; + for (int j = 0; j < 14; j++) { + + p_last_id = input->joy_button(p_last_id, controllers[i].id, j,(int)reading.Buttons & button_mask); + button_mask *= 2; + } + + p_last_id = input->joy_axis(p_last_id, controllers[i].id, JOY_AXIS_0, axis_correct(reading.LeftThumbstickX)); + p_last_id = input->joy_axis(p_last_id, controllers[i].id, JOY_AXIS_1, axis_correct(reading.LeftThumbstickY, true)); + p_last_id = input->joy_axis(p_last_id, controllers[i].id, JOY_AXIS_2, axis_correct(reading.RightThumbstickX)); + p_last_id = input->joy_axis(p_last_id, controllers[i].id, JOY_AXIS_3, axis_correct(reading.RightThumbstickY, true)); + p_last_id = input->joy_axis(p_last_id, controllers[i].id, JOY_AXIS_4, axis_correct(reading.LeftTrigger, false, true)); + p_last_id = input->joy_axis(p_last_id, controllers[i].id, JOY_AXIS_5, axis_correct(reading.RightTrigger, false, true)); + + break; + } + } + } + + return p_last_id; +} + +JoystickWinrt::JoystickWinrt() { + + for (int i = 0; i < MAX_CONTROLLERS; i++) + controllers[i].id = i; +} + +JoystickWinrt::JoystickWinrt(InputDefault * p_input) { + + input = p_input; + + JoystickWinrt(); +} + +void JoystickWinrt::OnGamepadAdded(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ value) { + + short idx = -1; + + for (int i = 0; i < MAX_CONTROLLERS; i++) { + + if (!controllers[i].connected) { + idx = i; + break; + } + } + + ERR_FAIL_COND(idx == -1); + + controllers[idx].connected = true; + controllers[idx].controller_reference = value; + controllers[idx].id = idx; + controllers[idx].type = ControllerType::GAMEPAD_CONTROLLER; + + input->joy_connection_changed(controllers[idx].id, true, "Xbox Controller", "__WINRT_GAMEPAD__"); +} + +void JoystickWinrt::OnGamepadRemoved(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ value) { + + short idx = -1; + + for (int i = 0; i < MAX_CONTROLLERS; i++) { + + if (controllers[i].controller_reference == value) { + idx = i; + break; + } + } + + ERR_FAIL_COND(idx == -1); + + for (int i = idx + 1; i < MAX_CONTROLLERS - 1; i++) { + + if (!controllers[i].connected) { + break; + } + + controllers[i - 1] = controllers[i]; + } + controllers[MAX_CONTROLLERS - 1] = ControllerDevice(); + + input->joy_connection_changed(idx, false, "Xbox Controller"); +} + +InputDefault::JoyAxis JoystickWinrt::axis_correct(double p_val, bool p_negate, bool p_trigger) const { + + InputDefault::JoyAxis jx; + + jx.min = p_trigger ? 0 : -1; + jx.value = (float)(p_negate ? -p_val : p_val); + + return jx; +} diff --git a/platform/winrt/joystick_winrt.h b/platform/winrt/joystick_winrt.h new file mode 100644 index 0000000000..17f9565708 --- /dev/null +++ b/platform/winrt/joystick_winrt.h @@ -0,0 +1,81 @@ +/*************************************************************************/ +/* joystick.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef JOYSTICK_WINRT_H +#define JOYSTICK_WINRT_H + +#include "main/input_default.h" + +ref class JoystickWinrt sealed { + +internal: + + void register_events(); + uint32_t process_controllers(uint32_t p_last_id); + + JoystickWinrt(); + JoystickWinrt(InputDefault* p_input); + +private: + + enum { + MAX_CONTROLLERS = 4, + }; + + enum ControllerType { + GAMEPAD_CONTROLLER, + ARCADE_STICK_CONTROLLER, + RACING_WHEEL_CONTROLLER, + }; + + struct ControllerDevice { + + Windows::Gaming::Input::IGameController^ controller_reference; + + int id; + bool connected; + ControllerType type; + + ControllerDevice() { + id = -1; + connected = false; + type = ControllerType::GAMEPAD_CONTROLLER; + } + }; + + ControllerDevice controllers[MAX_CONTROLLERS]; + + InputDefault* input; + + void OnGamepadAdded(Platform::Object^ sender, Windows::Gaming::Input::Gamepad^ value); + void OnGamepadRemoved(Platform::Object^ sender, Windows::Gaming::Input::Gamepad^ value); + + InputDefault::JoyAxis axis_correct(double p_val, bool p_negate = false, bool p_trigger = false) const; +}; + +#endif diff --git a/platform/winrt/os_winrt.cpp b/platform/winrt/os_winrt.cpp index f045f54bf6..4b23f3960e 100644 --- a/platform/winrt/os_winrt.cpp +++ b/platform/winrt/os_winrt.cpp @@ -28,11 +28,10 @@ /*************************************************************************/ #include "drivers/gles2/rasterizer_gles2.h" #include "os_winrt.h" -#include "drivers/nedmalloc/memory_pool_static_nedmalloc.h" #include "drivers/unix/memory_pool_static_malloc.h" #include "os/memory_pool_dynamic_static.h" #include "thread_winrt.h" -//#include "drivers/windows/semaphore_windows.h" +#include "drivers/windows/semaphore_windows.h" #include "drivers/windows/mutex_windows.h" #include "main/main.h" #include "drivers/windows/file_access_windows.h" @@ -47,15 +46,27 @@ #include "globals.h" #include "io/marshalls.h" +#include "platform/windows/packet_peer_udp_winsock.h" +#include "platform/windows/stream_peer_winsock.h" +#include "platform/windows/tcp_server_winsock.h" +#include "drivers/unix/ip_unix.h" + #include <wrl.h> +#include <ppltasks.h> using namespace Windows::ApplicationModel::Core; using namespace Windows::ApplicationModel::Activation; using namespace Windows::UI::Core; using namespace Windows::UI::Input; +using namespace Windows::UI::Popups; using namespace Windows::Foundation; using namespace Windows::Graphics::Display; using namespace Microsoft::WRL; +using namespace Windows::UI::ViewManagement; +using namespace Windows::Devices::Input; +using namespace Windows::Devices::Sensors; +using namespace Windows::ApplicationModel::DataTransfer; +using namespace concurrency; int OSWinrt::get_video_driver_count() const { @@ -72,6 +83,66 @@ OS::VideoMode OSWinrt::get_default_video_mode() const { return video_mode; } +Size2 OSWinrt::get_window_size() const { + Size2 size; + size.width = video_mode.width; + size.height = video_mode.height; + return size; +} + +void OSWinrt::set_window_size(const Size2 p_size) { + + Windows::Foundation::Size new_size; + new_size.Width = p_size.width; + new_size.Height = p_size.height; + + ApplicationView^ view = ApplicationView::GetForCurrentView(); + + if (view->TryResizeView(new_size)) { + + video_mode.width = p_size.width; + video_mode.height = p_size.height; + } +} + +void OSWinrt::set_window_fullscreen(bool p_enabled) { + + ApplicationView^ view = ApplicationView::GetForCurrentView(); + + video_mode.fullscreen = view->IsFullScreenMode; + + if (video_mode.fullscreen == p_enabled) + return; + + if (p_enabled) { + + video_mode.fullscreen = view->TryEnterFullScreenMode(); + + } else { + + view->ExitFullScreenMode(); + video_mode.fullscreen = false; + + } +} + +bool OSWinrt::is_window_fullscreen() const { + + return ApplicationView::GetForCurrentView()->IsFullScreenMode; +} + +void OSWinrt::set_keep_screen_on(bool p_enabled) { + + if (is_keep_screen_on() == p_enabled) return; + + if (p_enabled) + display_request->RequestActive(); + else + display_request->RequestRelease(); + + OS::set_keep_screen_on(p_enabled); +} + int OSWinrt::get_audio_driver_count() const { return AudioDriverManagerSW::get_driver_count(); @@ -94,7 +165,7 @@ void OSWinrt::initialize_core() { //RedirectIOToConsole(); ThreadWinrt::make_default(); - //SemaphoreWindows::make_default(); + SemaphoreWindows::make_default(); MutexWindows::make_default(); FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES); @@ -108,6 +179,10 @@ void OSWinrt::initialize_core() { //TCPServerWinsock::make_default(); //StreamPeerWinsock::make_default(); + TCPServerWinsock::make_default(); + StreamPeerWinsock::make_default(); + PacketPeerUDPWinsock::make_default(); + mempool_static = new MemoryPoolStaticMalloc; #if 1 mempool_dynamic = memnew( MemoryPoolDynamicStatic ); @@ -126,6 +201,8 @@ void OSWinrt::initialize_core() { ticks_start = 0; ticks_start = get_ticks_usec(); + IP_Unix::make_default(); + cursor_shape=CURSOR_ARROW; } @@ -154,9 +231,38 @@ void OSWinrt::initialize(const VideoMode& p_desired,int p_video_driver,int p_aud VideoMode vm; vm.width = gl_context->get_window_width(); vm.height = gl_context->get_window_height(); - vm.fullscreen = true; vm.resizable = false; + ApplicationView^ view = ApplicationView::GetForCurrentView(); + vm.fullscreen = view->IsFullScreenMode; + + view->SetDesiredBoundsMode(ApplicationViewBoundsMode::UseVisible); + view->PreferredLaunchWindowingMode = ApplicationViewWindowingMode::PreferredLaunchViewSize; + + if (p_desired.fullscreen != view->IsFullScreenMode) { + if (p_desired.fullscreen) { + + vm.fullscreen = view->TryEnterFullScreenMode(); + + } else { + + view->ExitFullScreenMode(); + vm.fullscreen = false; + } + } + + Windows::Foundation::Size desired; + desired.Width = p_desired.width; + desired.Height = p_desired.height; + + view->PreferredLaunchViewSize = desired; + + if (view->TryResizeView(desired)) { + + vm.width = view->VisibleBounds.Width; + vm.height = view->VisibleBounds.Height; + } + set_video_mode(vm); gl_context->make_current(); @@ -179,6 +285,9 @@ void OSWinrt::initialize(const VideoMode& p_desired,int p_video_driver,int p_aud input = memnew( InputDefault ); + joystick = ref new JoystickWinrt(input); + joystick->register_events(); + AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton(); if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) { @@ -196,96 +305,77 @@ void OSWinrt::initialize(const VideoMode& p_desired,int p_video_driver,int p_aud spatial_sound_2d_server = memnew( SpatialSound2DServerSW ); spatial_sound_2d_server->init(); + managed_object->update_clipboard(); - _ensure_data_dir(); -} - -void OSWinrt::set_clipboard(const String& p_text) { - - /* - if (!OpenClipboard(hWnd)) { - ERR_EXPLAIN("Unable to open clipboard."); - ERR_FAIL(); - }; - EmptyClipboard(); - - HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (p_text.length() + 1) * sizeof(CharType)); - if (mem == NULL) { - ERR_EXPLAIN("Unable to allocate memory for clipboard contents."); - ERR_FAIL(); - }; - LPWSTR lptstrCopy = (LPWSTR)GlobalLock(mem); - memcpy(lptstrCopy, p_text.c_str(), (p_text.length() + 1) * sizeof(CharType)); - //memset((lptstrCopy + p_text.length()), 0, sizeof(CharType)); - GlobalUnlock(mem); - - SetClipboardData(CF_UNICODETEXT, mem); - - // set the CF_TEXT version (not needed?) - CharString utf8 = p_text.utf8(); - mem = GlobalAlloc(GMEM_MOVEABLE, utf8.length() + 1); - if (mem == NULL) { - ERR_EXPLAIN("Unable to allocate memory for clipboard contents."); - ERR_FAIL(); - }; - LPTSTR ptr = (LPTSTR)GlobalLock(mem); - memcpy(ptr, utf8.get_data(), utf8.length()); - ptr[utf8.length()] = 0; - GlobalUnlock(mem); - - SetClipboardData(CF_TEXT, mem); - - CloseClipboard(); - */ -}; + Clipboard::ContentChanged += ref new EventHandler<Platform::Object^>(managed_object, &ManagedType::on_clipboard_changed); -String OSWinrt::get_clipboard() const { + accelerometer = Accelerometer::GetDefault(); + if (accelerometer != nullptr) { + // 60 FPS + accelerometer->ReportInterval = (1.0f / 60.0f) * 1000; + accelerometer->ReadingChanged += + ref new TypedEventHandler<Accelerometer^, AccelerometerReadingChangedEventArgs^> + (managed_object, &ManagedType::on_accelerometer_reading_changed); + } - /* - String ret; - if (!OpenClipboard(hWnd)) { - ERR_EXPLAIN("Unable to open clipboard."); - ERR_FAIL_V(""); - }; + magnetometer = Magnetometer::GetDefault(); + if (magnetometer != nullptr) { + // 60 FPS + magnetometer->ReportInterval = (1.0f / 60.0f) * 1000; + magnetometer->ReadingChanged += + ref new TypedEventHandler<Magnetometer^, MagnetometerReadingChangedEventArgs^> + (managed_object, &ManagedType::on_magnetometer_reading_changed); + } - if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { + gyrometer = Gyrometer::GetDefault(); + if (gyrometer != nullptr) { + // 60 FPS + gyrometer->ReportInterval = (1.0f / 60.0f) * 1000; + gyrometer->ReadingChanged += + ref new TypedEventHandler<Gyrometer^, GyrometerReadingChangedEventArgs^> + (managed_object, &ManagedType::on_gyroscope_reading_changed); + } - HGLOBAL mem = GetClipboardData(CF_UNICODETEXT); - if (mem != NULL) { + _ensure_data_dir(); - LPWSTR ptr = (LPWSTR)GlobalLock(mem); - if (ptr != NULL) { + if (is_keep_screen_on()) + display_request->RequestActive(); - ret = String((CharType*)ptr); - GlobalUnlock(mem); - }; - }; + set_keep_screen_on(GLOBAL_DEF("display/keep_screen_on", true)); - } else if (IsClipboardFormatAvailable(CF_TEXT)) { +} - HGLOBAL mem = GetClipboardData(CF_UNICODETEXT); - if (mem != NULL) { +void OSWinrt::set_clipboard(const String& p_text) { - LPTSTR ptr = (LPTSTR)GlobalLock(mem); - if (ptr != NULL) { + DataPackage^ clip = ref new DataPackage(); + clip->RequestedOperation = DataPackageOperation::Copy; + clip->SetText(ref new Platform::String((const wchar_t*)p_text.c_str())); - ret.parse_utf8((const char*)ptr); - GlobalUnlock(mem); - }; - }; - }; + Clipboard::SetContent(clip); +}; - CloseClipboard(); +String OSWinrt::get_clipboard() const { - return ret; - */ - return ""; + if (managed_object->clipboard != nullptr) + return managed_object->clipboard->Data(); + else + return ""; }; void OSWinrt::input_event(InputEvent &p_event) { + p_event.ID = ++last_id; + input->parse_input_event(p_event); + + if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && p_event.mouse_button.button_index>3) { + + //send release for mouse wheel + p_event.mouse_button.pressed = false; + p_event.ID = ++last_id; + input->parse_input_event(p_event); + } }; void OSWinrt::delete_main_loop() { @@ -339,6 +429,8 @@ void OSWinrt::finalize() { physics_2d_server->finish(); memdelete(physics_2d_server); + joystick = nullptr; + } void OSWinrt::finalize_core() { @@ -370,9 +462,6 @@ void OSWinrt::vprint(const char* p_format, va_list p_list, bool p_stderr) { else wprintf(L"%s",wbuf); -#ifdef STDOUT_FILE - //vwfprintf(stdo,p_format,p_list); -#endif free(wbuf); fflush(stdout); @@ -380,11 +469,101 @@ void OSWinrt::vprint(const char* p_format, va_list p_list, bool p_stderr) { void OSWinrt::alert(const String& p_alert,const String& p_title) { - print_line("ALERT: "+p_alert); + Platform::String^ alert = ref new Platform::String(p_alert.c_str()); + Platform::String^ title = ref new Platform::String(p_title.c_str()); + + MessageDialog^ msg = ref new MessageDialog(alert, title); + + UICommand^ close = ref new UICommand("Close", ref new UICommandInvokedHandler(managed_object, &OSWinrt::ManagedType::alert_close)); + msg->Commands->Append(close); + msg->DefaultCommandIndex = 0; + + managed_object->alert_close_handle = true; + + msg->ShowAsync(); +} + +void OSWinrt::ManagedType::alert_close(IUICommand^ command) { + + alert_close_handle = false; +} + +void OSWinrt::ManagedType::on_clipboard_changed(Platform::Object ^ sender, Platform::Object ^ ev) { + + update_clipboard(); +} + +void OSWinrt::ManagedType::update_clipboard() { + + DataPackageView^ data = Clipboard::GetContent(); + + if (data->Contains(StandardDataFormats::Text)) { + + create_task(data->GetTextAsync()).then( + [this](Platform::String^ clipboard_content) { + + this->clipboard = clipboard_content; + }); + } +} + +void OSWinrt::ManagedType::on_accelerometer_reading_changed(Accelerometer ^ sender, AccelerometerReadingChangedEventArgs ^ args) { + + AccelerometerReading^ reading = args->Reading; + + os->input->set_accelerometer(Vector3( + reading->AccelerationX, + reading->AccelerationY, + reading->AccelerationZ + )); +} + +void OSWinrt::ManagedType::on_magnetometer_reading_changed(Magnetometer ^ sender, MagnetometerReadingChangedEventArgs ^ args) { + + MagnetometerReading^ reading = args->Reading; + + os->input->set_magnetometer(Vector3( + reading->MagneticFieldX, + reading->MagneticFieldY, + reading->MagneticFieldZ + )); +} + +void OSWinrt::ManagedType::on_gyroscope_reading_changed(Gyrometer ^ sender, GyrometerReadingChangedEventArgs ^ args) { + + GyrometerReading^ reading = args->Reading; + + os->input->set_magnetometer(Vector3( + reading->AngularVelocityX, + reading->AngularVelocityY, + reading->AngularVelocityZ + )); } void OSWinrt::set_mouse_mode(MouseMode p_mode) { + if (p_mode == MouseMode::MOUSE_MODE_CAPTURED) { + + CoreWindow::GetForCurrentThread()->SetPointerCapture(); + + } else { + + CoreWindow::GetForCurrentThread()->ReleasePointerCapture(); + + } + + if (p_mode == MouseMode::MOUSE_MODE_CAPTURED || p_mode == MouseMode::MOUSE_MODE_HIDDEN) { + + CoreWindow::GetForCurrentThread()->PointerCursor = nullptr; + + } else { + + CoreWindow::GetForCurrentThread()->PointerCursor = ref new CoreCursor(CoreCursorType::Arrow, 0); + } + + mouse_mode = p_mode; + + SetEvent(mouse_mode_changed); } OSWinrt::MouseMode OSWinrt::get_mouse_mode() const{ @@ -482,7 +661,7 @@ OS::Time OSWinrt::get_time(bool utc) const { return time; } -OS::TimeZoneInfo OS_Windows::get_time_zone_info() const { +OS::TimeZoneInfo OSWinrt::get_time_zone_info() const { TIME_ZONE_INFORMATION info; bool daylight = false; if (GetTimeZoneInformation(&info) == TIME_ZONE_ID_DAYLIGHT) @@ -503,7 +682,7 @@ uint64_t OSWinrt::get_unix_time() const { FILETIME ft; SYSTEMTIME st; - GetSystemTime(&systemtime); + GetSystemTime(&st); SystemTimeToFileTime(&st, &ft); SYSTEMTIME ep; @@ -546,10 +725,79 @@ uint64_t OSWinrt::get_ticks_usec() const { void OSWinrt::process_events() { + last_id = joystick->process_controllers(last_id); + process_key_events(); +} + +void OSWinrt::process_key_events() +{ + + for (int i = 0; i < key_event_pos; i++) { + + KeyEvent &kev = key_event_buffer[i]; + InputEvent iev; + + iev.type = InputEvent::KEY; + iev.key.mod = kev.mod_state; + iev.key.echo = kev.echo; + iev.key.scancode = kev.scancode; + iev.key.unicode = kev.unicode; + iev.key.pressed = kev.pressed; + + input_event(iev); + + } + key_event_pos = 0; +} + +void OSWinrt::queue_key_event(KeyEvent & p_event) +{ + // This merges Char events with the previous Key event, so + // the unicode can be retrieved without sending duplicate events. + if (p_event.type == KeyEvent::MessageType::CHAR_EVENT_MESSAGE && key_event_pos > 0) { + + KeyEvent &old = key_event_buffer[key_event_pos - 1]; + ERR_FAIL_COND(old.type != KeyEvent::MessageType::KEY_EVENT_MESSAGE); + + key_event_buffer[key_event_pos - 1].unicode = p_event.unicode; + return; + } + + ERR_FAIL_COND(key_event_pos >= KEY_EVENT_BUFFER_SIZE); + + key_event_buffer[key_event_pos++] = p_event; } void OSWinrt::set_cursor_shape(CursorShape p_shape) { + ERR_FAIL_INDEX(p_shape, CURSOR_MAX); + + if (cursor_shape == p_shape) + return; + + static const CoreCursorType uwp_cursors[CURSOR_MAX] = { + CoreCursorType::Arrow, + CoreCursorType::IBeam, + CoreCursorType::Hand, + CoreCursorType::Cross, + CoreCursorType::Wait, + CoreCursorType::Wait, + CoreCursorType::Arrow, + CoreCursorType::Arrow, + CoreCursorType::UniversalNo, + CoreCursorType::SizeNorthSouth, + CoreCursorType::SizeWestEast, + CoreCursorType::SizeNortheastSouthwest, + CoreCursorType::SizeNorthwestSoutheast, + CoreCursorType::SizeAll, + CoreCursorType::SizeNorthSouth, + CoreCursorType::SizeWestEast, + CoreCursorType::Help + }; + + CoreWindow::GetForCurrentThread()->PointerCursor = ref new CoreCursor(uwp_cursors[p_shape], 0); + + cursor_shape = p_shape; } Error OSWinrt::execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id,String* r_pipe,int *r_exitcode) { @@ -609,7 +857,7 @@ String OSWinrt::get_locale() const { return "en"; #else Platform::String ^language = Windows::Globalization::Language::CurrentInputMethodLanguageTag; - return language->Data(); + return String(language->Data()).replace("-", "_"); #endif } @@ -628,6 +876,29 @@ void OSWinrt::swap_buffers() { gl_context->swap_buffers(); } +bool OSWinrt::has_touchscreen_ui_hint() const { + + TouchCapabilities^ tc = ref new TouchCapabilities(); + return tc->TouchPresent != 0 || UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Touch; +} + +bool OSWinrt::has_virtual_keyboard() const { + + return UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Touch; +} + +void OSWinrt::show_virtual_keyboard(const String & p_existing_text, const Rect2 & p_screen_rect) { + + InputPane^ pane = InputPane::GetForCurrentView(); + pane->TryShow(); +} + +void OSWinrt::hide_virtual_keyboard() { + + InputPane^ pane = InputPane::GetForCurrentView(); + pane->TryHide(); +} + void OSWinrt::run() { @@ -644,6 +915,7 @@ void OSWinrt::run() { while (!force_quit) { CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + if (managed_object->alert_close_handle) continue; process_events(); // get rid of pending events if (Main::iteration()==true) break; @@ -665,7 +937,7 @@ String OSWinrt::get_data_dir() const { Windows::Storage::StorageFolder ^data_folder = Windows::Storage::ApplicationData::Current->LocalFolder; - return data_folder->Path->Data(); + return String(data_folder->Path->Data()).replace("\\", "/"); } @@ -690,6 +962,13 @@ OSWinrt::OSWinrt() { gl_context = NULL; + display_request = ref new Windows::System::Display::DisplayRequest(); + + managed_object = ref new ManagedType; + managed_object->os = this; + + mouse_mode_changed = CreateEvent(NULL, TRUE, FALSE, L"os_mouse_mode_changed"); + AudioDriverManagerSW::add_driver(&audio_driver); } diff --git a/platform/winrt/os_winrt.h b/platform/winrt/os_winrt.h index 145ccf0f7a..a4667f213d 100644 --- a/platform/winrt/os_winrt.h +++ b/platform/winrt/os_winrt.h @@ -40,10 +40,13 @@ #include "servers/spatial_sound/spatial_sound_server_sw.h" #include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h" #include "servers/physics_2d/physics_2d_server_sw.h" -#include "servers/audio/audio_driver_dummy.h" +#include "drivers/xaudio2/audio_driver_xaudio2.h" #include "gl_context_egl.h" +#include "core/math/math_2d.h" +#include "core/ustring.h" + #include <windows.h> #include <io.h> @@ -52,11 +55,35 @@ #include <stdio.h> #include "main/input_default.h" +#include "joystick_winrt.h" + /** @author Juan Linietsky <reduzio@gmail.com> */ class OSWinrt : public OS { +public: + + struct KeyEvent { + + enum MessageType + { + KEY_EVENT_MESSAGE, + CHAR_EVENT_MESSAGE + }; + + InputModifierState mod_state; + MessageType type; + bool pressed; + unsigned int scancode; + unsigned int unicode; + bool echo; + CorePhysicalKeyStatus status; + + }; + +private: + enum { JOYSTICKS_MAX = 8, JOY_AXIS_COUNT = 6, @@ -66,16 +93,6 @@ class OSWinrt : public OS { FILE *stdo; - - struct KeyEvent { - - InputModifierState mod_state; - UINT uMsg; - WPARAM wParam; - LPARAM lParam; - - }; - KeyEvent key_event_buffer[KEY_EVENT_BUFFER_SIZE]; int key_event_pos; @@ -97,37 +114,11 @@ class OSWinrt : public OS { ContextEGL* gl_context; - struct Joystick { - - int id; - bool attached; - - DWORD last_axis[JOY_AXIS_COUNT]; - DWORD last_buttons; - DWORD last_pov; - String name; - - Joystick() { - id = -1; - attached = false; - for (int i=0; i<JOY_AXIS_COUNT; i++) { - - last_axis[i] = 0; - }; - last_buttons = 0; - last_pov = 0; - }; - }; - - List<Joystick> joystick_change_queue; - int joystick_count; - Joystick joysticks[JOYSTICKS_MAX]; - VideoMode video_mode; MainLoop *main_loop; - AudioDriverDummy audio_driver; + AudioDriverXAudio2 audio_driver; AudioServerSW *audio_server; SampleManagerMallocSW *sample_manager; SpatialSoundServerSW *spatial_sound_server; @@ -146,11 +137,34 @@ class OSWinrt : public OS { InputDefault *input; + JoystickWinrt^ joystick; + + Windows::System::Display::DisplayRequest^ display_request; + void _post_dpad(DWORD p_dpad, int p_device, bool p_pressed); void _drag_event(int idx,UINT uMsg, WPARAM wParam, LPARAM lParam); void _touch_event(int idx, UINT uMsg, WPARAM wParam, LPARAM lParam); + ref class ManagedType { + public: + property bool alert_close_handle; + property Platform::String^ clipboard; + void alert_close(Windows::UI::Popups::IUICommand^ command); + void on_clipboard_changed(Platform::Object^ sender, Platform::Object^ ev); + void update_clipboard(); + void on_accelerometer_reading_changed(Windows::Devices::Sensors::Accelerometer^ sender, Windows::Devices::Sensors::AccelerometerReadingChangedEventArgs^ args); + void on_magnetometer_reading_changed(Windows::Devices::Sensors::Magnetometer^ sender, Windows::Devices::Sensors::MagnetometerReadingChangedEventArgs^ args); + void on_gyroscope_reading_changed(Windows::Devices::Sensors::Gyrometer^ sender, Windows::Devices::Sensors::GyrometerReadingChangedEventArgs^ args); + + internal: + ManagedType() { alert_close_handle = false; } + property OSWinrt* os; + }; + ManagedType^ managed_object; + Windows::Devices::Sensors::Accelerometer^ accelerometer; + Windows::Devices::Sensors::Magnetometer^ magnetometer; + Windows::Devices::Sensors::Gyrometer^ gyrometer; // functions used by main to initialize/deintialize the OS protected: @@ -173,12 +187,13 @@ protected: void process_events(); - void probe_joysticks(); - void process_joysticks(); void process_key_events(); public: + // Event to send to the app wrapper + HANDLE mouse_mode_changed; + void print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type); virtual void vprint(const char *p_format, va_list p_list, bool p_stderr=false); @@ -195,6 +210,11 @@ public: virtual void set_video_mode(const VideoMode& p_video_mode,int p_screen=0); virtual VideoMode get_video_mode(int p_screen=0) const; virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const; + virtual Size2 get_window_size() const; + virtual void set_window_size(const Size2 p_size); + virtual void set_window_fullscreen(bool p_enabled); + virtual bool is_window_fullscreen() const; + virtual void set_keep_screen_on(bool p_enabled); virtual MainLoop *get_main_loop() const; @@ -237,7 +257,11 @@ public: virtual void make_rendering_thread(); virtual void swap_buffers(); - virtual bool has_touchscreen_ui_hint() const { return true; }; + virtual bool has_touchscreen_ui_hint() const; + + virtual bool has_virtual_keyboard() const; + virtual void show_virtual_keyboard(const String& p_existing_text, const Rect2& p_screen_rect = Rect2()); + virtual void hide_virtual_keyboard(); virtual Error shell_open(String p_uri); @@ -247,6 +271,8 @@ public: void input_event(InputEvent &p_event); + void queue_key_event(KeyEvent &p_event); + OSWinrt(); ~OSWinrt(); diff --git a/platform/winrt/thread_winrt.cpp b/platform/winrt/thread_winrt.cpp index e7028bd9dc..8e3e0d5bef 100644 --- a/platform/winrt/thread_winrt.cpp +++ b/platform/winrt/thread_winrt.cpp @@ -59,7 +59,9 @@ Thread::ID ThreadWinrt::get_ID() const { }; void ThreadWinrt::make_default() { - + create_func = create_func_winrt; + get_thread_ID_func = get_thread_ID_func_winrt; + wait_to_finish_func = wait_to_finish_func_winrt; }; ThreadWinrt::ThreadWinrt() { diff --git a/platform/x11/SCsub b/platform/x11/SCsub index 80fd347ded..e20bd44f8d 100644 --- a/platform/x11/SCsub +++ b/platform/x11/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 356de7b2bc..917a8a27d7 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -68,13 +68,10 @@ def get_opts(): def get_flags(): return [ - ('builtin_zlib', 'no'), - ('glew', 'yes'), - ("openssl", "yes"), - ('freetype','yes'), #use system freetype - - #("theora","no"), - ] + ("openssl", "system"), + ('freetype', 'system'), + ('libpng', 'system'), + ] @@ -97,10 +94,6 @@ def configure(env): env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND']) env.extra_suffix=".llvm" - if (env["colored"]=="yes"): - if sys.stdout.isatty(): - env.Append(CXXFLAGS=["-fcolor-diagnostics"]) - if (env["use_sanitizer"]=="yes"): env.Append(CXXFLAGS=['-fsanitize=address','-fno-omit-frame-pointer']) env.Append(LINKFLAGS=['-fsanitize=address']) @@ -140,22 +133,54 @@ def configure(env): env.ParseConfig('pkg-config xcursor --cflags --libs') env.ParseConfig('pkg-config xrandr --cflags --libs') - if (env["openssl"]=="yes"): + if (env["openssl"] == "system"): env.ParseConfig('pkg-config openssl --cflags --libs') + if (env["libwebp"] == "system"): + env.ParseConfig('pkg-config libwebp --cflags --libs') - if (env["freetype"]=="yes"): + if (env["freetype"] == "system"): + env["libpng"] = "system" # Freetype links against libpng env.ParseConfig('pkg-config freetype2 --cflags --libs') + if (env["libpng"] == "system"): + env.ParseConfig('pkg-config libpng --cflags --libs') + + if (env["enet"] == "system"): + env.ParseConfig('pkg-config libenet --cflags --libs') + + if (env["squish"] == "system" and env["tools"] == "yes"): + env.ParseConfig('pkg-config libsquish --cflags --libs') + # Sound and video libraries + # Keep the order as it triggers chained dependencies (ogg needed by others, etc.) + + if (env["libtheora"] == "system"): + env["libogg"] = "system" # Needed to link against system libtheora + env["libvorbis"] = "system" # Needed to link against system libtheora + env.ParseConfig('pkg-config theora theoradec --cflags --libs') + + if (env["libvorbis"] == "system"): + env["libogg"] = "system" # Needed to link against system libvorbis + env.ParseConfig('pkg-config vorbis vorbisfile --cflags --libs') + + if (env["opus"] == "system"): + env["libogg"] = "system" # Needed to link against system opus + env.ParseConfig('pkg-config opus opusfile --cflags --libs') + + if (env["libogg"] == "system"): + env.ParseConfig('pkg-config ogg --cflags --libs') env.Append(CPPFLAGS=['-DOPENGL_ENABLED']) + if (env["glew"] == "system"): + env.ParseConfig('pkg-config glew --cflags --libs') + if os.system("pkg-config --exists alsa")==0: print("Enabling ALSA") env.Append(CPPFLAGS=["-DALSA_ENABLED"]) - env.Append(LIBS=['asound']) + env.ParseConfig('pkg-config alsa --cflags --libs') else: print("ALSA libraries not found, disabling driver") @@ -208,5 +233,5 @@ def configure(env): list_of_x86 = ['x86_64', 'x86', 'i386', 'i586'] if any(platform.machine() in s for s in list_of_x86): - env["x86_opt_gcc"]=True + env["x86_libtheora_opt_gcc"]=True diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 9a2d610e78..5f1ab5b4aa 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -1176,6 +1176,19 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { event.key.mod.shift=true; } + //don't set mod state if modifier keys are released by themselves + //else event.is_action() will not work correctly here + if (!event.key.pressed) { + if (event.key.scancode == KEY_SHIFT) + event.key.mod.shift = false; + else if (event.key.scancode == KEY_CONTROL) + event.key.mod.control = false; + else if (event.key.scancode == KEY_ALT) + event.key.mod.alt = false; + else if (event.key.scancode == KEY_META) + event.key.mod.meta = false; + } + //printf("key: %x\n",event.key.scancode); input->parse_input_event( event); } diff --git a/platform/x11/platform_config.h b/platform/x11/platform_config.h index 3b47b2c92d..015953157d 100644 --- a/platform/x11/platform_config.h +++ b/platform/x11/platform_config.h @@ -34,6 +34,4 @@ #define PTHREAD_BSD_SET_NAME #endif -#define GLES2_INCLUDE_H "gl_context/GL/glew.h" - - +#define GLES2_INCLUDE_H "GL/glew.h" diff --git a/scene/2d/SCsub b/scene/2d/SCsub index bbe59b3054..9fa89edbf7 100644 --- a/scene/2d/SCsub +++ b/scene/2d/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.scene_sources,"*.cpp") diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 71728966fd..e8954b7e98 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -650,8 +650,8 @@ void Area2D::_bind_methods() { ADD_SIGNAL( MethodInfo("body_enter",PropertyInfo(Variant::OBJECT,"body",PROPERTY_HINT_RESOURCE_TYPE,"PhysicsBody2D"))); ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body",PROPERTY_HINT_RESOURCE_TYPE,"PhysicsBody2D"))); - ADD_SIGNAL( MethodInfo("area_enter_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"area_shape"))); - ADD_SIGNAL( MethodInfo("area_exit_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"area_shape"))); + ADD_SIGNAL( MethodInfo("area_enter_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"self_shape"))); + ADD_SIGNAL( MethodInfo("area_exit_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"self_shape"))); ADD_SIGNAL( MethodInfo("area_enter",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D"))); ADD_SIGNAL( MethodInfo("area_exit",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D"))); diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index e576aa10e0..f33faaabd8 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -44,6 +44,9 @@ void Camera2D::_update_scroll() { } if (current) { + + ERR_FAIL_COND( custom_viewport && !ObjectDB::get_instance(custom_viewport_id) ); + Matrix32 xform = get_camera_transform(); if (viewport) { @@ -73,8 +76,9 @@ Matrix32 Camera2D::get_camera_transform() { if (!get_tree()) return Matrix32(); - Size2 screen_size = get_viewport_rect().size; - screen_size=get_viewport_rect().size; + ERR_FAIL_COND_V( custom_viewport && !ObjectDB::get_instance(custom_viewport_id), Matrix32() ); + + Size2 screen_size = viewport->get_visible_rect().size; Point2 new_camera_pos = get_global_transform().get_origin(); @@ -240,14 +244,10 @@ void Camera2D::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { - viewport = NULL; - Node *n=this; - while(n){ - - viewport = n->cast_to<Viewport>(); - if (viewport) - break; - n=n->get_parent(); + if (custom_viewport && ObjectDB::get_instance(custom_viewport_id)) { + viewport=custom_viewport; + } else { + viewport=get_viewport(); } canvas = get_canvas(); @@ -270,8 +270,8 @@ void Camera2D::_notification(int p_what) { } break; case NOTIFICATION_EXIT_TREE: { - if (is_current()) { - if (viewport) { + if (is_current()) { + if (viewport && !(custom_viewport && !ObjectDB::get_instance(custom_viewport_id))) { viewport->set_canvas_transform( Matrix32() ); } } @@ -447,8 +447,10 @@ void Camera2D::reset_smoothing() { void Camera2D::align() { - Size2 screen_size = get_viewport_rect().size; - screen_size=get_viewport_rect().size; + ERR_FAIL_COND( custom_viewport && !ObjectDB::get_instance(custom_viewport_id) ); + + Size2 screen_size = viewport->get_visible_rect().size; + Point2 current_camera_pos = get_global_transform().get_origin(); if (anchor_mode==ANCHOR_MODE_DRAG_CENTER) { if (h_ofs<0) { @@ -549,6 +551,42 @@ bool Camera2D::is_follow_smoothing_enabled() const { return smoothing_enabled; } +void Camera2D::set_custom_viewport(Node *p_viewport) { + ERR_FAIL_NULL(p_viewport); + if (is_inside_tree()) { + remove_from_group(group_name); + remove_from_group(canvas_group_name); + } + + custom_viewport=p_viewport->cast_to<Viewport>(); + + if (custom_viewport) { + custom_viewport_id=custom_viewport->get_instance_ID(); + } else { + custom_viewport_id=0; + } + + if (is_inside_tree()) { + + if (custom_viewport) + viewport=custom_viewport; + else + viewport=get_viewport(); + + RID vp = viewport->get_viewport(); + group_name = "__cameras_"+itos(vp.get_id()); + canvas_group_name ="__cameras_c"+itos(canvas.get_id()); + add_to_group(group_name); + add_to_group(canvas_group_name); + } + +} + +Node* Camera2D::get_custom_viewport() const { + + return custom_viewport; +} + void Camera2D::_bind_methods() { @@ -597,6 +635,8 @@ void Camera2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_zoom","zoom"),&Camera2D::set_zoom); ObjectTypeDB::bind_method(_MD("get_zoom"),&Camera2D::get_zoom); + ObjectTypeDB::bind_method(_MD("set_custom_viewport","viewport:Viewport"),&Camera2D::set_custom_viewport); + ObjectTypeDB::bind_method(_MD("get_custom_viewport:Viewport"),&Camera2D::get_custom_viewport); ObjectTypeDB::bind_method(_MD("set_follow_smoothing","follow_smoothing"),&Camera2D::set_follow_smoothing); ObjectTypeDB::bind_method(_MD("get_follow_smoothing"),&Camera2D::get_follow_smoothing); @@ -662,6 +702,8 @@ Camera2D::Camera2D() { first=true; smoothing_enabled=false; limit_smoothing_enabled=false; + custom_viewport=NULL; + custom_viewport_id=0; smoothing=5.0; zoom = Vector2(1, 1); diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h index 9f3e4254bb..a4d6dc5b96 100644 --- a/scene/2d/camera_2d.h +++ b/scene/2d/camera_2d.h @@ -48,6 +48,8 @@ protected: Point2 smoothed_camera_pos; bool first; + ObjectID custom_viewport_id; // to check validity + Viewport *custom_viewport; Viewport *viewport; StringName group_name; @@ -128,6 +130,9 @@ public: Point2 get_camera_screen_center() const; + void set_custom_viewport(Node *p_viewport); + Node* get_custom_viewport() const; + Vector2 get_camera_pos() const; void force_update_scroll(); void reset_smoothing(); diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index f37cef673d..3e548a24b0 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -67,7 +67,23 @@ void Light2D::_update_light_visibility() { if (!is_inside_tree()) return; - VS::get_singleton()->canvas_light_set_enabled(canvas_light,enabled && is_visible()); + bool editor_ok=true; + +#ifdef TOOLS_ENABLED + if (editor_only) { + if (!get_tree()->is_editor_hint()) { + editor_ok=false; + } else { + editor_ok = (get_tree()->get_edited_scene_root() && (this==get_tree()->get_edited_scene_root() || get_owner()==get_tree()->get_edited_scene_root())); + } + } +#else + if (editor_only) { + editor_ok=false; + } +#endif + + VS::get_singleton()->canvas_light_set_enabled(canvas_light,enabled && is_visible() && editor_ok); } void Light2D::set_enabled( bool p_enabled) { @@ -82,6 +98,17 @@ bool Light2D::is_enabled() const { return enabled; } +void Light2D::set_editor_only(bool p_editor_only) { + + editor_only=p_editor_only; + _update_light_visibility(); +} + +bool Light2D::is_editor_only() const{ + + return editor_only; +} + void Light2D::set_texture( const Ref<Texture>& p_texture) { texture=p_texture; @@ -328,6 +355,9 @@ void Light2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_enabled","enabled"),&Light2D::set_enabled); ObjectTypeDB::bind_method(_MD("is_enabled"),&Light2D::is_enabled); + ObjectTypeDB::bind_method(_MD("set_editor_only","editor_only"), &Light2D::set_editor_only ); + ObjectTypeDB::bind_method(_MD("is_editor_only"), &Light2D::is_editor_only ); + ObjectTypeDB::bind_method(_MD("set_texture","texture"),&Light2D::set_texture); ObjectTypeDB::bind_method(_MD("get_texture"),&Light2D::get_texture); @@ -383,6 +413,7 @@ void Light2D::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "editor_only"),_SCS("set_editor_only"),_SCS("is_editor_only")); ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"scale",PROPERTY_HINT_RANGE,"0.01,50,0.01"),_SCS("set_texture_scale"),_SCS("get_texture_scale")); @@ -413,6 +444,7 @@ Light2D::Light2D() { canvas_light=VisualServer::get_singleton()->canvas_light_create(); enabled=true; + editor_only=false; shadow=false; color=Color(1,1,1); height=0; diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index c03ef96eff..57c89b15e7 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -45,6 +45,7 @@ public: private: RID canvas_light; bool enabled; + bool editor_only; bool shadow; Color color; Color shadow_color; @@ -78,6 +79,9 @@ public: void set_enabled( bool p_enabled); bool is_enabled() const; + void set_editor_only(bool p_editor_only); + bool is_editor_only() const; + void set_texture( const Ref<Texture>& p_texture); Ref<Texture> get_texture() const; diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index df43e8e373..b3f925cb14 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -253,7 +253,7 @@ void Node2D::global_translate(const Vector2& p_amount) { set_global_pos( get_global_pos() + p_amount ); } -void Node2D::scale(const Vector2& p_amount) { +void Node2D::scale(const Size2& p_amount) { set_scale( get_scale() * p_amount ); } diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index aa8d0ef33c..b31ee08af6 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -79,7 +79,7 @@ public: void move_y(float p_delta,bool p_scaled=false); void translate(const Vector2& p_amount); void global_translate(const Vector2& p_amount); - void scale(const Vector2& p_amount); + void scale(const Size2& p_amount); Point2 get_pos() const; float get_rot() const; @@ -110,8 +110,6 @@ public: Matrix32 get_relative_transform_to_parent(const Node *p_parent) const; - - Matrix32 get_transform() const; Node2D(); diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index cfb87fb998..12893524d1 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -288,12 +288,12 @@ float Polygon2D::_get_texture_rotationd() const{ } -void Polygon2D::set_texture_scale(const Vector2& p_scale){ +void Polygon2D::set_texture_scale(const Size2& p_scale){ tex_scale=p_scale; update(); } -Vector2 Polygon2D::get_texture_scale() const{ +Size2 Polygon2D::get_texture_scale() const{ return tex_scale; } diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h index 04e8aeb6fd..cecb9081f7 100644 --- a/scene/2d/polygon_2d.h +++ b/scene/2d/polygon_2d.h @@ -40,7 +40,7 @@ class Polygon2D : public Node2D { DVector<Color> vertex_colors; Color color; Ref<Texture> texture; - Vector2 tex_scale; + Size2 tex_scale; Vector2 tex_ofs; bool tex_tile; float tex_rot; @@ -81,8 +81,8 @@ public: void set_texture_rotation(float p_rot); float get_texture_rotation() const; - void set_texture_scale(const Vector2& p_scale); - Vector2 get_texture_scale() const; + void set_texture_scale(const Size2& p_scale); + Size2 get_texture_scale() const; void set_invert(bool p_rot); bool get_invert() const; diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index b5d62adfb4..bd7f4faae5 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -187,39 +187,44 @@ void RayCast2D::_notification(int p_what) { if (!enabled) break; + _update_raycast_state(); - Ref<World2D> w2d = get_world_2d(); - ERR_BREAK( w2d.is_null() ); - - Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(w2d->get_space()); - ERR_BREAK( !dss ); - - Matrix32 gt = get_global_transform(); + } break; + } +} - Vector2 to = cast_to; - if (to==Vector2()) - to=Vector2(0,0.01); +void RayCast2D::_update_raycast_state() { + Ref<World2D> w2d = get_world_2d(); + ERR_FAIL_COND( w2d.is_null() ); - Physics2DDirectSpaceState::RayResult rr; + Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(w2d->get_space()); + ERR_FAIL_COND( !dss ); - if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude,layer_mask,type_mask)) { + Matrix32 gt = get_global_transform(); - collided=true; - against=rr.collider_id; - collision_point=rr.position; - collision_normal=rr.normal; - against_shape=rr.shape; - } else { - collided=false; - } + Vector2 to = cast_to; + if (to==Vector2()) + to=Vector2(0,0.01); + Physics2DDirectSpaceState::RayResult rr; + if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude,layer_mask,type_mask)) { - } break; + collided=true; + against=rr.collider_id; + collision_point=rr.position; + collision_normal=rr.normal; + against_shape=rr.shape; + } else { + collided=false; } } +void RayCast2D::force_raycast_update() { + _update_raycast_state(); +} + void RayCast2D::add_exception_rid(const RID& p_rid) { exclude.insert(p_rid); @@ -265,6 +270,7 @@ void RayCast2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_cast_to"),&RayCast2D::get_cast_to); ObjectTypeDB::bind_method(_MD("is_colliding"),&RayCast2D::is_colliding); + ObjectTypeDB::bind_method(_MD("force_raycast_update"),&RayCast2D::force_raycast_update); ObjectTypeDB::bind_method(_MD("get_collider"),&RayCast2D::get_collider); ObjectTypeDB::bind_method(_MD("get_collider_shape"),&RayCast2D::get_collider_shape); diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h index e1caa8b63e..9bdcc2e199 100644 --- a/scene/2d/ray_cast_2d.h +++ b/scene/2d/ray_cast_2d.h @@ -52,6 +52,7 @@ class RayCast2D : public Node2D { protected: void _notification(int p_what); + void _update_raycast_state(); static void _bind_methods(); public: @@ -70,6 +71,8 @@ public: void set_exclude_parent_body(bool p_exclude_parent_body); bool get_exclude_parent_body() const; + void force_raycast_update(); + bool is_colliding() const; Object *get_collider() const; int get_collider_shape() const; diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index c5b338bf59..8723db95d6 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -214,6 +214,7 @@ void Sprite::set_frame(int p_frame) { frame=p_frame; + _change_notify("frame"); emit_signal(SceneStringNames::get_singleton()->frame_changed); } diff --git a/scene/3d/SCsub b/scene/3d/SCsub index 116e641593..1205deb94a 100644 --- a/scene/3d/SCsub +++ b/scene/3d/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index a8a4122016..c1d0d1a97c 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -640,8 +640,8 @@ void Area::_bind_methods() { ADD_SIGNAL( MethodInfo("body_enter",PropertyInfo(Variant::OBJECT,"body"))); ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body"))); - ADD_SIGNAL( MethodInfo("area_enter_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"area_shape"))); - ADD_SIGNAL( MethodInfo("area_exit_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"area_shape"))); + ADD_SIGNAL( MethodInfo("area_enter_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"self_shape"))); + ADD_SIGNAL( MethodInfo("area_exit_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"self_shape"))); ADD_SIGNAL( MethodInfo("area_enter",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area"))); ADD_SIGNAL( MethodInfo("area_exit",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area"))); diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index e76c0938fb..76543b67c6 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -648,12 +648,16 @@ void Camera::_bind_methods() { ObjectTypeDB::bind_method( _MD("get_zfar"),&Camera::get_zfar ); ObjectTypeDB::bind_method( _MD("get_znear"),&Camera::get_znear ); ObjectTypeDB::bind_method( _MD("get_projection"),&Camera::get_projection ); + ObjectTypeDB::bind_method( _MD("set_h_offset","ofs"),&Camera::set_h_offset ); + ObjectTypeDB::bind_method( _MD("get_h_offset"),&Camera::get_h_offset ); + ObjectTypeDB::bind_method( _MD("set_v_offset","ofs"),&Camera::set_v_offset ); + ObjectTypeDB::bind_method( _MD("get_v_offset"),&Camera::get_v_offset ); ObjectTypeDB::bind_method( _MD("set_visible_layers","mask"),&Camera::set_visible_layers ); ObjectTypeDB::bind_method( _MD("get_visible_layers"),&Camera::get_visible_layers ); - ObjectTypeDB::bind_method(_MD("set_environment","env:Environment"),&Camera::set_environment); - ObjectTypeDB::bind_method(_MD("get_environment:Environment"),&Camera::get_environment); - ObjectTypeDB::bind_method(_MD("set_keep_aspect_mode","mode"),&Camera::set_keep_aspect_mode); - ObjectTypeDB::bind_method(_MD("get_keep_aspect_mode"),&Camera::get_keep_aspect_mode); + ObjectTypeDB::bind_method( _MD("set_environment","env:Environment"),&Camera::set_environment ); + ObjectTypeDB::bind_method( _MD("get_environment:Environment"),&Camera::get_environment ); + ObjectTypeDB::bind_method( _MD("set_keep_aspect_mode","mode"),&Camera::set_keep_aspect_mode ); + ObjectTypeDB::bind_method( _MD("get_keep_aspect_mode"),&Camera::get_keep_aspect_mode ); //ObjectTypeDB::bind_method( _MD("_camera_make_current"),&Camera::_camera_make_current ); BIND_CONSTANT( PROJECTION_PERSPECTIVE ); diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp index e83fa69b4f..99c7fd047f 100644 --- a/scene/3d/immediate_geometry.cpp +++ b/scene/3d/immediate_geometry.cpp @@ -72,6 +72,7 @@ void ImmediateGeometry::add_vertex(const Vector3& p_vertex){ if (empty) { aabb.pos=p_vertex; aabb.size=Vector3(); + empty=false; } else { aabb.expand_to(p_vertex); } @@ -102,7 +103,7 @@ DVector<Face3> ImmediateGeometry::get_faces(uint32_t p_usage_flags) const { -void ImmediateGeometry::add_sphere(int p_lats,int p_lons,float p_radius) { +void ImmediateGeometry::add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv) { for(int i = 1; i <= p_lats; i++) { double lat0 = Math_PI * (-0.5 + (double) (i - 1) / p_lats); @@ -132,6 +133,10 @@ void ImmediateGeometry::add_sphere(int p_lats,int p_lons,float p_radius) { }; #define ADD_POINT(m_idx)\ + if (p_add_uv) {\ + set_uv(Vector2(Math::atan2(v[m_idx].x,v[m_idx].z)/Math_PI * 0.5+0.5,v[m_idx].y*0.5+0.5));\ + set_tangent(Plane(Vector3(-v[m_idx].z,v[m_idx].y,v[m_idx].x),1)); \ + }\ set_normal(v[m_idx]);\ add_vertex(v[m_idx]*p_radius); @@ -156,7 +161,7 @@ void ImmediateGeometry::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_uv","uv"),&ImmediateGeometry::set_uv); ObjectTypeDB::bind_method(_MD("set_uv2","uv"),&ImmediateGeometry::set_uv2); ObjectTypeDB::bind_method(_MD("add_vertex","pos"),&ImmediateGeometry::add_vertex); - ObjectTypeDB::bind_method(_MD("add_sphere","lats","lons","radius"),&ImmediateGeometry::add_sphere); + ObjectTypeDB::bind_method(_MD("add_sphere","lats","lons","radius","add_uv"),&ImmediateGeometry::add_sphere,DEFVAL(true)); ObjectTypeDB::bind_method(_MD("end"),&ImmediateGeometry::end); ObjectTypeDB::bind_method(_MD("clear"),&ImmediateGeometry::clear); diff --git a/scene/3d/immediate_geometry.h b/scene/3d/immediate_geometry.h index c1cc4f87d5..fc7f4de634 100644 --- a/scene/3d/immediate_geometry.h +++ b/scene/3d/immediate_geometry.h @@ -62,7 +62,7 @@ public: void clear(); - void add_sphere(int p_lats,int p_lons,float p_radius); + void add_sphere(int p_lats,int p_lons,float p_radius,bool p_add_uv=true); diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp index 227bb3a59d..5b221d1574 100644 --- a/scene/3d/light.cpp +++ b/scene/3d/light.cpp @@ -446,6 +446,10 @@ bool editor_ok=true; editor_ok = (get_tree()->get_edited_scene_root() && (this==get_tree()->get_edited_scene_root() || get_owner()==get_tree()->get_edited_scene_root())); } } +#else + if (editor_only) { + editor_ok=false; + } #endif VS::get_singleton()->instance_light_set_enabled(get_instance(),is_visible() && enabled && editor_ok); @@ -672,5 +676,3 @@ void SpotLight::_bind_methods() { ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_attenuation", PROPERTY_HINT_EXP_EASING, "spot_attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ATTENUATION ); } - - diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp index 1acda8d1f8..2b8df8265e 100644 --- a/scene/3d/ray_cast.cpp +++ b/scene/3d/ray_cast.cpp @@ -134,39 +134,44 @@ void RayCast::_notification(int p_what) { if (!enabled) break; + _update_raycast_state(); - Ref<World> w3d = get_world(); - ERR_BREAK( w3d.is_null() ); - - PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(w3d->get_space()); - ERR_BREAK( !dss ); - - Transform gt = get_global_transform(); + } break; + } +} - Vector3 to = cast_to; - if (to==Vector3()) - to=Vector3(0,0.01,0); +void RayCast::_update_raycast_state(){ + Ref<World> w3d = get_world(); + ERR_FAIL_COND( w3d.is_null() ); - PhysicsDirectSpaceState::RayResult rr; + PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(w3d->get_space()); + ERR_FAIL_COND( !dss ); - if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude, layer_mask, type_mask)) { + Transform gt = get_global_transform(); - collided=true; - against=rr.collider_id; - collision_point=rr.position; - collision_normal=rr.normal; - against_shape=rr.shape; - } else { - collided=false; - } + Vector3 to = cast_to; + if (to==Vector3()) + to=Vector3(0,0.01,0); + PhysicsDirectSpaceState::RayResult rr; + if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude, layer_mask, type_mask)) { - } break; + collided=true; + against=rr.collider_id; + collision_point=rr.position; + collision_normal=rr.normal; + against_shape=rr.shape; + } else { + collided=false; } } +void RayCast::force_raycast_update() { + _update_raycast_state(); +} + void RayCast::add_exception_rid(const RID& p_rid) { exclude.insert(p_rid); @@ -212,6 +217,7 @@ void RayCast::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_cast_to"),&RayCast::get_cast_to); ObjectTypeDB::bind_method(_MD("is_colliding"),&RayCast::is_colliding); + ObjectTypeDB::bind_method(_MD("force_raycast_update"),&RayCast::force_raycast_update); ObjectTypeDB::bind_method(_MD("get_collider"),&RayCast::get_collider); ObjectTypeDB::bind_method(_MD("get_collider_shape"),&RayCast::get_collider_shape); diff --git a/scene/3d/ray_cast.h b/scene/3d/ray_cast.h index 4f6514e61b..47553f08ed 100644 --- a/scene/3d/ray_cast.h +++ b/scene/3d/ray_cast.h @@ -53,6 +53,7 @@ class RayCast : public Spatial { protected: void _notification(int p_what); + void _update_raycast_state(); static void _bind_methods(); public: @@ -68,6 +69,7 @@ public: void set_type_mask(uint32_t p_mask); uint32_t get_type_mask() const; + void force_raycast_update(); bool is_colliding() const; Object *get_collider() const; int get_collider_shape() const; diff --git a/scene/3d/remote_transform.cpp b/scene/3d/remote_transform.cpp new file mode 100644 index 0000000000..d43870417a --- /dev/null +++ b/scene/3d/remote_transform.cpp @@ -0,0 +1,132 @@ + +/*************************************************************************/ +/* remote_transform.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "remote_transform.h" + +void RemoteTransform::_update_cache() { + cache=0; + if (has_node(remote_node)) { + Node *node = get_node(remote_node); + if (!node || this==node || node->is_a_parent_of(this) || this->is_a_parent_of(node)) { + return; + } + + cache=node->get_instance_ID(); + } +} + +void RemoteTransform::_update_remote() { + + + if (!is_inside_tree()) + return; + + if (!cache) + return; + + Object *obj = ObjectDB::get_instance(cache); + if (!obj) + return; + + Spatial *n = obj->cast_to<Spatial>(); + if (!n) + return; + + if (!n->is_inside_tree()) + return; + + //todo make faster + n->set_global_transform(get_global_transform()); + +} + +void RemoteTransform::_notification(int p_what) { + + switch(p_what) { + + case NOTIFICATION_READY: { + + _update_cache(); + + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + if (!is_inside_tree()) + break; + + if (cache) { + + _update_remote(); + + } + + } break; + + } +} + + +void RemoteTransform::set_remote_node(const NodePath& p_remote_node) { + + remote_node=p_remote_node; + if (is_inside_tree()) + _update_cache(); + + update_configuration_warning(); +} + +NodePath RemoteTransform::get_remote_node() const{ + + return remote_node; +} + + +String RemoteTransform::get_configuration_warning() const { + + if (!has_node(remote_node) || !get_node(remote_node) || !get_node(remote_node)->cast_to<Spatial>()) { + return TTR("Path property must point to a valid Spatial node to work."); + } + + return String(); +} + +void RemoteTransform::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_remote_node","path"),&RemoteTransform::set_remote_node); + ObjectTypeDB::bind_method(_MD("get_remote_node"),&RemoteTransform::get_remote_node); + + ADD_PROPERTY( PropertyInfo(Variant::NODE_PATH,"remote_path"),_SCS("set_remote_node"),_SCS("get_remote_node")); +} + +RemoteTransform::RemoteTransform() { + + cache=0; + +} + diff --git a/scene/3d/remote_transform.h b/scene/3d/remote_transform.h new file mode 100644 index 0000000000..78f0fec1e9 --- /dev/null +++ b/scene/3d/remote_transform.h @@ -0,0 +1,30 @@ +#ifndef REMOTETRANSFORM_H +#define REMOTETRANSFORM_H + +#include "scene/3d/spatial.h" + +class RemoteTransform : public Spatial +{ + OBJ_TYPE(RemoteTransform,Spatial); + + NodePath remote_node; + + ObjectID cache; + + void _update_remote(); + void _update_cache(); + +protected: + static void _bind_methods(); + void _notification(int p_what); +public: + void set_remote_node(const NodePath& p_remote_node); + NodePath get_remote_node() const; + + virtual String get_configuration_warning() const; + + RemoteTransform(); + +}; + +#endif // REMOTETRANSFORM_H diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp index b15226cce3..b4f7a4e5b4 100644 --- a/scene/3d/visual_instance.cpp +++ b/scene/3d/visual_instance.cpp @@ -128,6 +128,8 @@ void VisualInstance::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_layer_mask","mask"), &VisualInstance::set_layer_mask); ObjectTypeDB::bind_method(_MD("get_layer_mask"), &VisualInstance::get_layer_mask); + ObjectTypeDB::bind_method(_MD("get_transformed_aabb"), &VisualInstance::get_transformed_aabb); + ADD_PROPERTY( PropertyInfo( Variant::INT, "layers",PROPERTY_HINT_ALL_FLAGS), _SCS("set_layer_mask"), _SCS("get_layer_mask")); @@ -376,6 +378,8 @@ void GeometryInstance::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_extra_cull_margin","margin"), &GeometryInstance::set_extra_cull_margin); ObjectTypeDB::bind_method(_MD("get_extra_cull_margin"), &GeometryInstance::get_extra_cull_margin); + ObjectTypeDB::bind_method(_MD("get_aabb"),&GeometryInstance::get_aabb); + ObjectTypeDB::bind_method(_MD("_baked_light_changed"), &GeometryInstance::_baked_light_changed); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/visible"), _SCS("set_flag"), _SCS("get_flag"),FLAG_VISIBLE); diff --git a/scene/SCsub b/scene/SCsub index 6d1dd0044f..79da365192 100644 --- a/scene/SCsub +++ b/scene/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.scene_sources=[] diff --git a/scene/animation/SCsub b/scene/animation/SCsub index bbe59b3054..9fa89edbf7 100644 --- a/scene/animation/SCsub +++ b/scene/animation/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.scene_sources,"*.cpp") diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 6f6f5d3aff..156f4956bb 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -199,13 +199,13 @@ void Tween::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_tween_process_mode"),&Tween::get_tween_process_mode); ObjectTypeDB::bind_method(_MD("start"),&Tween::start ); - ObjectTypeDB::bind_method(_MD("reset","object","key"),&Tween::reset ); + ObjectTypeDB::bind_method(_MD("reset","object","key"),&Tween::reset, DEFVAL("") ); ObjectTypeDB::bind_method(_MD("reset_all"),&Tween::reset_all ); - ObjectTypeDB::bind_method(_MD("stop","object","key"),&Tween::stop ); + ObjectTypeDB::bind_method(_MD("stop","object","key"),&Tween::stop, DEFVAL("") ); ObjectTypeDB::bind_method(_MD("stop_all"),&Tween::stop_all ); - ObjectTypeDB::bind_method(_MD("resume","object","key"),&Tween::resume ); + ObjectTypeDB::bind_method(_MD("resume","object","key"),&Tween::resume, DEFVAL("") ); ObjectTypeDB::bind_method(_MD("resume_all"),&Tween::resume_all ); - ObjectTypeDB::bind_method(_MD("remove","object","key"),&Tween::remove ); + ObjectTypeDB::bind_method(_MD("remove","object","key"),&Tween::remove, DEFVAL("") ); ObjectTypeDB::bind_method(_MD("remove_all"),&Tween::remove_all ); ObjectTypeDB::bind_method(_MD("seek","time"),&Tween::seek ); ObjectTypeDB::bind_method(_MD("tell"),&Tween::tell ); @@ -619,6 +619,8 @@ void Tween::_tween_process(float p_delta) { }; object->call(data.key, (const Variant **) arg, data.args, error); } + if (!repeat) + call_deferred("remove", object, data.key); } continue; } @@ -721,7 +723,7 @@ bool Tween::reset(Object *p_object, String p_key) { if(object == NULL) continue; - if(object == p_object && data.key == p_key) { + if(object == p_object && (data.key == p_key || p_key == "")) { data.elapsed = 0; data.finish = false; @@ -757,7 +759,7 @@ bool Tween::stop(Object *p_object, String p_key) { Object *object = ObjectDB::get_instance(data.id); if(object == NULL) continue; - if(object == p_object && data.key == p_key) + if(object == p_object && (data.key == p_key || p_key == "")) data.active = false; } pending_update --; @@ -791,7 +793,7 @@ bool Tween::resume(Object *p_object, String p_key) { Object *object = ObjectDB::get_instance(data.id); if(object == NULL) continue; - if(object == p_object && data.key == p_key) + if(object == p_object && (data.key == p_key || p_key == "")) data.active = true; } pending_update --; @@ -819,17 +821,20 @@ bool Tween::remove(Object *p_object, String p_key) { call_deferred("remove", p_object, p_key); return true; } + List<List<InterpolateData>::Element *> for_removal; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); Object *object = ObjectDB::get_instance(data.id); if(object == NULL) continue; - if(object == p_object && data.key == p_key) { - interpolates.erase(E); - return true; + if(object == p_object && (data.key == p_key || p_key == "")) { + for_removal.push_back(E); } } + for(List<List<InterpolateData>::Element *>::Element *E=for_removal.front();E;E=E->next()) { + interpolates.erase(E->get()); + } return true; } diff --git a/scene/audio/SCsub b/scene/audio/SCsub index bbe59b3054..9fa89edbf7 100644 --- a/scene/audio/SCsub +++ b/scene/audio/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.scene_sources,"*.cpp") diff --git a/scene/gui/SCsub b/scene/gui/SCsub index bbe59b3054..9fa89edbf7 100644 --- a/scene/gui/SCsub +++ b/scene/gui/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.scene_sources,"*.cpp") diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 6479dd2d02..64d68738b2 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -243,12 +243,22 @@ void BaseButton::_notification(int p_what) { update(); } } + + if (p_what==NOTIFICATION_FOCUS_ENTER) { + + status.hovering=true; + update(); + } if (p_what==NOTIFICATION_FOCUS_EXIT) { if (status.pressing_button && status.press_attempt) { status.press_attempt=false; status.pressing_button=0; + status.hovering=false; + update(); + } else if (status.hovering) { + status.hovering=false; update(); } } diff --git a/scene/gui/button_array.cpp b/scene/gui/button_array.cpp index be48296110..df1872380d 100644 --- a/scene/gui/button_array.cpp +++ b/scene/gui/button_array.cpp @@ -60,6 +60,8 @@ bool ButtonArray::_set(const StringName& p_name, const Variant& p_value) { String f = n.get_slicec('/',2); if (f=="text") buttons[idx].text=p_value; + else if (f=="tooltip") + buttons[idx].tooltip=p_value; else if (f=="icon") buttons[idx].icon=p_value; else @@ -95,6 +97,8 @@ bool ButtonArray::_get(const StringName& p_name,Variant &r_ret) const { String f = n.get_slicec('/',2); if (f=="text") r_ret=buttons[idx].text; + else if (f=="tooltip") + r_ret=buttons[idx].tooltip; else if (f=="icon") r_ret=buttons[idx].icon; else @@ -115,6 +119,7 @@ void ButtonArray::_get_property_list( List<PropertyInfo> *p_list) const { for(int i=0;i<buttons.size();i++) { String base="button/"+itos(i)+"/"; p_list->push_back( PropertyInfo( Variant::STRING, base+"text")); + p_list->push_back( PropertyInfo( Variant::STRING, base+"tooltip")); p_list->push_back( PropertyInfo( Variant::OBJECT, base+"icon",PROPERTY_HINT_RESOURCE_TYPE,"Texture")); } if (buttons.size()>0) { @@ -168,8 +173,12 @@ Size2 ButtonArray::get_minimum_size() const { void ButtonArray::_notification(int p_what) { switch(p_what) { + case NOTIFICATION_MOUSE_EXIT:{ + hover=-1; + update(); + }break; case NOTIFICATION_READY:{ - MethodInfo mi; + MethodInfo mi; mi.name="mouse_sub_enter"; add_user_signal(mi); @@ -245,8 +254,12 @@ void ButtonArray::_notification(int p_what) { Ref<Font> f; Color c; + Point2 sbsize; + Point2 sbofs; if (i==selected) { draw_style_box(style_selected,r); + sbsize=style_selected->get_minimum_size(); + sbofs=style_selected->get_offset(); f=font_selected; c=color_selected; if (has_focus()) @@ -256,6 +269,8 @@ void ButtonArray::_notification(int p_what) { draw_style_box(style_hover,r); else draw_style_box(style_normal,r); + sbsize=style_selected->get_minimum_size(); + sbofs=style_normal->get_offset(); f=font_normal; c=color_normal; } @@ -265,7 +280,7 @@ void ButtonArray::_notification(int p_what) { ssize.x+=buttons[i].icon->get_width(); } - Point2 text_ofs=((r.size-ssize)/2.0+Point2(0,f->get_ascent())).floor(); + Point2 text_ofs=((r.size-ssize-sbsize)/2.0+Point2(0,f->get_ascent())).floor()+sbofs; if (buttons[i].icon.is_valid()) { draw_texture(buttons[i].icon,r.pos+Point2(text_ofs.x,Math::floor((r.size.height-buttons[i].icon->get_height())/2.0))); @@ -349,6 +364,18 @@ void ButtonArray::_input_event(const InputEvent& p_event) { } +String ButtonArray::get_tooltip(const Point2& p_pos) const { + + int ofs = orientation==HORIZONTAL ? p_pos.x: p_pos.y; + for(int i=0;i<buttons.size();i++) { + + if (ofs>=buttons[i]._pos_cache && ofs<buttons[i]._pos_cache+buttons[i]._size_cache) + return buttons[i].tooltip; + + } + return Control::get_tooltip(p_pos); +} + void ButtonArray::set_align(Align p_align) { align=p_align; @@ -362,10 +389,11 @@ ButtonArray::Align ButtonArray::get_align() const { } -void ButtonArray::add_button(const String& p_text) { +void ButtonArray::add_button(const String& p_text,const String& p_tooltip) { Button button; button.text=p_text; + button.tooltip=p_tooltip; buttons.push_back(button); update(); @@ -375,11 +403,12 @@ void ButtonArray::add_button(const String& p_text) { minimum_size_changed(); } -void ButtonArray::add_icon_button(const Ref<Texture>& p_icon,const String& p_text) { +void ButtonArray::add_icon_button(const Ref<Texture>& p_icon,const String& p_text,const String& p_tooltip) { Button button; button.text=p_text; button.icon=p_icon; + button.tooltip=p_tooltip; buttons.push_back(button); if (selected==-1) selected=0; @@ -397,6 +426,13 @@ void ButtonArray::set_button_text(int p_button, const String& p_text) { } +void ButtonArray::set_button_tooltip(int p_button, const String& p_text) { + + ERR_FAIL_INDEX(p_button,buttons.size()); + buttons[p_button].tooltip=p_text; + +} + void ButtonArray::set_button_icon(int p_button, const Ref<Texture>& p_icon) { ERR_FAIL_INDEX(p_button,buttons.size()); @@ -411,6 +447,12 @@ String ButtonArray::get_button_text(int p_button) const { return buttons[p_button].text; } +String ButtonArray::get_button_tooltip(int p_button) const { + + ERR_FAIL_INDEX_V(p_button,buttons.size(),""); + return buttons[p_button].tooltip; +} + Ref<Texture> ButtonArray::get_button_icon(int p_button) const { ERR_FAIL_INDEX_V(p_button,buttons.size(),Ref<Texture>()); @@ -465,18 +507,22 @@ int ButtonArray::get_button_count() const { void ButtonArray::get_translatable_strings(List<String> *p_strings) const { - for(int i=0;i<buttons.size();i++) + for(int i=0;i<buttons.size();i++) { p_strings->push_back(buttons[i].text); + p_strings->push_back(buttons[i].tooltip); + } } void ButtonArray::_bind_methods() { - ObjectTypeDB::bind_method(_MD("add_button","text"),&ButtonArray::add_button); - ObjectTypeDB::bind_method(_MD("add_icon_button","icon:Texture","text"),&ButtonArray::add_icon_button,DEFVAL("")); + ObjectTypeDB::bind_method(_MD("add_button","text","tooltip"),&ButtonArray::add_button,DEFVAL("")); + ObjectTypeDB::bind_method(_MD("add_icon_button","icon:Texture","text","tooltip"),&ButtonArray::add_icon_button,DEFVAL(""),DEFVAL("")); ObjectTypeDB::bind_method(_MD("set_button_text","button_idx","text"),&ButtonArray::set_button_text); + ObjectTypeDB::bind_method(_MD("set_button_tooltip","button_idx","text"),&ButtonArray::set_button_tooltip); ObjectTypeDB::bind_method(_MD("set_button_icon","button_idx","icon:Texture"),&ButtonArray::set_button_icon); ObjectTypeDB::bind_method(_MD("get_button_text","button_idx"),&ButtonArray::get_button_text); + ObjectTypeDB::bind_method(_MD("get_button_tooltip","button_idx"),&ButtonArray::get_button_tooltip); ObjectTypeDB::bind_method(_MD("get_button_icon:Texture","button_idx"),&ButtonArray::get_button_icon); ObjectTypeDB::bind_method(_MD("get_button_count"),&ButtonArray::get_button_count); ObjectTypeDB::bind_method(_MD("get_selected"),&ButtonArray::get_selected); diff --git a/scene/gui/button_array.h b/scene/gui/button_array.h index c4b9b0c9e3..62997a8e36 100644 --- a/scene/gui/button_array.h +++ b/scene/gui/button_array.h @@ -50,6 +50,7 @@ private: struct Button { String text; + String tooltip; Ref<Texture> icon; mutable int _ms_cache; mutable int _pos_cache; @@ -78,14 +79,16 @@ public: void set_align(Align p_align); Align get_align() const; - void add_button(const String& p_button); - void add_icon_button(const Ref<Texture>& p_icon,const String& p_button=""); + void add_button(const String& p_button,const String& p_tooltip=""); + void add_icon_button(const Ref<Texture>& p_icon,const String& p_button="",const String& p_tooltip=""); void set_button_text(int p_button, const String& p_text); + void set_button_tooltip(int p_button, const String& p_text); void set_button_icon(int p_button, const Ref<Texture>& p_icon); String get_button_text(int p_button) const; + String get_button_tooltip(int p_button) const; Ref<Texture> get_button_icon(int p_button) const; int get_selected() const; @@ -100,6 +103,7 @@ public: virtual Size2 get_minimum_size() const; virtual void get_translatable_strings(List<String> *p_strings) const; + virtual String get_tooltip(const Point2& p_pos) const; ButtonArray(Orientation p_orientation=HORIZONTAL); diff --git a/scene/gui/button_group.cpp b/scene/gui/button_group.cpp index 04ba5fc06d..5d9f290f78 100644 --- a/scene/gui/button_group.cpp +++ b/scene/gui/button_group.cpp @@ -60,6 +60,9 @@ void ButtonGroup::_pressed(Object *p_button) { BaseButton *bb=E->get(); bb->set_pressed( b==bb ); + if (b==bb){ + emit_signal("button_selected", b); + } } } @@ -153,6 +156,7 @@ void ButtonGroup::_bind_methods() { ObjectTypeDB::bind_method(_MD("_pressed"),&ButtonGroup::_pressed); ObjectTypeDB::bind_method(_MD("set_pressed_button","button:BaseButton"),&ButtonGroup::_pressed); + ADD_SIGNAL( MethodInfo("button_selected",PropertyInfo(Variant::OBJECT,"button",PROPERTY_HINT_RESOURCE_TYPE,"BaseButton"))); } ButtonGroup::ButtonGroup() : BoxContainer(true) diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index b69646432e..5e66544153 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -41,13 +41,13 @@ void update_material(Ref<CanvasItemMaterial>mat,const Color& p_color,float h,flo if (!sdr.is_valid()) return; - mat->set_shader_param("R",p_color.r); - mat->set_shader_param("G",p_color.g); - mat->set_shader_param("B",p_color.b); - mat->set_shader_param("H",h); - mat->set_shader_param("S",s); - mat->set_shader_param("V",v); - mat->set_shader_param("A",p_color.a); + mat->set_shader_param("R",p_color.r); + mat->set_shader_param("G",p_color.g); + mat->set_shader_param("B",p_color.b); + mat->set_shader_param("H",h); + mat->set_shader_param("S",s); + mat->set_shader_param("V",v); + mat->set_shader_param("A",p_color.a); } void ColorPicker::_notification(int p_what) { @@ -397,9 +397,10 @@ void ColorPicker::_screen_input(const InputEvent &ev) if (!r->get_rect().has_point(Point2(mev.global_x,mev.global_y))) return; Image img =r->get_screen_capture(); - if (!img.empty()) + if (!img.empty()) { last_capture=img; r->queue_screen_capture(); + } if (!last_capture.empty()) set_color(last_capture.get_pixel(mev.global_x,mev.global_y)); } diff --git a/scene/gui/color_rect.cpp b/scene/gui/color_rect.cpp new file mode 100644 index 0000000000..a0e4df66b5 --- /dev/null +++ b/scene/gui/color_rect.cpp @@ -0,0 +1,36 @@ +#include "color_rect.h" + + + + +void ColorFrame::set_frame_color(const Color& p_color) { + + color=p_color; + update(); +} + +Color ColorFrame::get_frame_color() const{ + + return color; +} + +void ColorFrame::_notification(int p_what) { + + if (p_what==NOTIFICATION_DRAW) { + draw_rect(Rect2(Point2(),get_size()),color); + } +} + +void ColorFrame::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_frame_color","color"),&ColorFrame::set_frame_color); + ObjectTypeDB::bind_method(_MD("get_frame_color"),&ColorFrame::get_frame_color); + + ADD_PROPERTY(PropertyInfo(Variant::COLOR,"color"),_SCS("set_frame_color"),_SCS("get_frame_color") ); +} + +ColorFrame::ColorFrame() { + + color=Color(1,1,1); +} + diff --git a/scene/gui/color_rect.h b/scene/gui/color_rect.h new file mode 100644 index 0000000000..3816d44052 --- /dev/null +++ b/scene/gui/color_rect.h @@ -0,0 +1,22 @@ +#ifndef COLORRECT_H +#define COLORRECT_H + +#include "scene/gui/control.h" + +class ColorFrame : public Control { + OBJ_TYPE(ColorFrame,Control) + + Color color; +protected: + + void _notification(int p_what); + static void _bind_methods(); +public: + + void set_frame_color(const Color& p_color); + Color get_frame_color() const; + + ColorFrame(); +}; + +#endif // COLORRECT_H diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index bf35fd25bd..97f0db97c2 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -431,8 +431,7 @@ void Control::add_child_notify(Node *p_child) { return; if (child_c->data.theme.is_null() && data.theme_owner) { - child_c->data.theme_owner=data.theme_owner; - child_c->notification(NOTIFICATION_THEME_CHANGED); + _propagate_theme_changed(child_c,data.theme_owner); //need to propagate here, since many controls may require setting up stuff } } @@ -443,8 +442,7 @@ void Control::remove_child_notify(Node *p_child) { return; if (child_c->data.theme_owner && child_c->data.theme.is_null()) { - child_c->data.theme_owner=NULL; - //notification(NOTIFICATION_THEME_CHANGED); + _propagate_theme_changed(child_c,NULL); } } @@ -482,10 +480,10 @@ void Control::_notification(int p_notification) { if (is_set_as_toplevel()) { data.SI=get_viewport()->_gui_add_subwindow_control(this); - if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) { + /*if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) { data.theme_owner=data.parent->data.theme_owner; notification(NOTIFICATION_THEME_CHANGED); - } + }*/ } else { @@ -521,10 +519,10 @@ void Control::_notification(int p_notification) { if (parent_control) { //do nothing, has a parent control - if (data.theme.is_null() && parent_control->data.theme_owner) { + /*if (data.theme.is_null() && parent_control->data.theme_owner) { data.theme_owner=parent_control->data.theme_owner; notification(NOTIFICATION_THEME_CHANGED); - } + }*/ } else if (subwindow) { //is a subwindow (process input before other controls for that canvas) data.SI=get_viewport()->_gui_add_subwindow_control(this); @@ -1727,11 +1725,11 @@ Control *Control::find_next_valid_focus() const { if (next_child==this) // no next control-> return (get_focus_mode()==FOCUS_ALL)?next_child:NULL; - - if (next_child->get_focus_mode()==FOCUS_ALL) - return next_child; - - from = next_child; + if (next_child) { + if (next_child->get_focus_mode()==FOCUS_ALL) + return next_child; + from = next_child; + } else break; } return NULL; @@ -1915,7 +1913,7 @@ void Control::_propagate_theme_changed(CanvasItem *p_at,Control *p_owner,bool p_ CanvasItem *child = p_at->get_child(i)->cast_to<CanvasItem>(); if (child) { - _propagate_theme_changed(child,p_owner); + _propagate_theme_changed(child,p_owner,p_assign); } } @@ -1926,7 +1924,7 @@ void Control::_propagate_theme_changed(CanvasItem *p_at,Control *p_owner,bool p_ if (p_assign) { c->data.theme_owner=p_owner; } - c->_notification(NOTIFICATION_THEME_CHANGED); + c->notification(NOTIFICATION_THEME_CHANGED); c->update(); } } @@ -2408,6 +2406,35 @@ bool Control::is_visibility_clip_disabled() const { return data.disable_visibility_clip; } +void Control::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const { + + Node::get_argument_options(p_function,p_idx,r_options); + + if (p_idx==0) { + List<StringName> sn; + String pf = p_function; + if (pf=="add_color_override" || pf=="has_color" || pf=="has_color_override" || pf=="get_color") { + Theme::get_default()->get_color_list(get_type(),&sn); + } else if (pf=="add_style_override" || pf=="has_style" || pf=="has_style_override" || pf=="get_style") { + Theme::get_default()->get_stylebox_list(get_type(),&sn); + } else if (pf=="add_font_override" || pf=="has_font" || pf=="has_font_override" || pf=="get_font") { + Theme::get_default()->get_font_list(get_type(),&sn); + } else if (pf=="add_constant_override" || pf=="has_constant" || pf=="has_constant_override" || pf=="get_constant") { + Theme::get_default()->get_constant_list(get_type(),&sn); + } else if (pf=="add_color_override" || pf=="has_color" || pf=="has_color_override" || pf=="get_color") { + Theme::get_default()->get_color_list(get_type(),&sn); + } + + sn.sort_custom<StringName::AlphCompare>(); + for (List<StringName>::Element *E=sn.front();E;E=E->next()) { + r_options->push_back("\""+E->get()+"\""); + } + } + + +} + + void Control::_bind_methods() { diff --git a/scene/gui/control.h b/scene/gui/control.h index 558439efbf..37efd80970 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -407,6 +407,8 @@ public: void set_disable_visibility_clip(bool p_ignore); bool is_visibility_clip_disabled() const; + virtual void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const; + Control(); ~Control(); diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 4dbc106834..b8c5f227c6 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -232,6 +232,8 @@ String AcceptDialog::get_text() const { void AcceptDialog::set_text(String p_text) { label->set_text(p_text); + minimum_size_changed(); + _update_child_rect(); } void AcceptDialog::set_hide_on_ok(bool p_hide) { @@ -253,38 +255,51 @@ void AcceptDialog::register_text_enter(Node *p_line_edit) { void AcceptDialog::_update_child_rect() { - int margin = get_constant("margin","Dialogs"); - Size2 size = get_size(); + const int margin = get_constant("margin","Dialogs"); + const Size2 size = get_size(); Size2 hminsize = hbc->get_combined_minimum_size(); - Vector2 cpos(margin,margin); - Vector2 csize(size.x-margin*2,size.y-margin*3-hminsize.y); + const Size2 max_csize( + size.width - margin * 2, + size.height - margin * 3 - hminsize.height); + hminsize.width = max_csize.width; + + Point2 cpos(margin, margin); + Size2 csize = label->get_combined_minimum_size(); + if(label->get_text().empty()) + csize.y = 0; + csize.x = MIN(csize.width, max_csize.width); + csize.y = MIN(csize.height, max_csize.height); label->set_pos(cpos); label->set_size(csize); - if (child) { + if(child) { + const float child_y_offset = csize.height + (csize.height > 0 ? margin : 0); + cpos.y += child_y_offset; + csize = max_csize; + csize.height -= child_y_offset; child->set_pos(cpos); child->set_size(csize); } - cpos.y+=csize.y+margin; - csize.y=hminsize.y; + cpos.y += csize.height + margin; hbc->set_pos(cpos); - hbc->set_size(csize); - + hbc->set_size(hminsize); } Size2 AcceptDialog::get_minimum_size() const { int margin = get_constant("margin","Dialogs"); Size2 minsize = label->get_combined_minimum_size(); + if(label->get_text().empty()) + minsize.y = 0; if (child) { Size2 cminsize = child->get_combined_minimum_size(); minsize.x=MAX(cminsize.x,minsize.x); - minsize.y=MAX(cminsize.y,minsize.y); + minsize.y += cminsize.y + (minsize.y > 0 ? margin : 0); } Size2 hminsize = hbc->get_combined_minimum_size(); @@ -368,6 +383,7 @@ void AcceptDialog::_bind_methods() { ObjectTypeDB::bind_method(_MD("_custom_action"),&AcceptDialog::_custom_action); ObjectTypeDB::bind_method(_MD("set_text","text"),&AcceptDialog::set_text); ObjectTypeDB::bind_method(_MD("get_text"),&AcceptDialog::get_text); + ObjectTypeDB::bind_method(_MD("set_child_rect","child:Control"),&AcceptDialog::set_child_rect); ADD_SIGNAL( MethodInfo("confirmed") ); ADD_SIGNAL( MethodInfo("custom_action",PropertyInfo(Variant::STRING,"action")) ); @@ -399,8 +415,6 @@ AcceptDialog::AcceptDialog() { add_child(label); hbc = memnew( HBoxContainer ); - hbc->set_area_as_parent_rect(margin); - hbc->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,button_margin); add_child(hbc); hbc->add_spacer(); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 8b03dbbc2d..6366b5ee23 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -151,7 +151,7 @@ void GraphEdit::_update_scroll_offset() { } } - connections_layer->set_pos(-Point2(h_scroll->get_val(),v_scroll->get_val())*zoom); + connections_layer->set_pos(-Point2(h_scroll->get_val(),v_scroll->get_val())); set_block_minimum_size_adjust(false); awaiting_scroll_offset_update=false; @@ -254,6 +254,7 @@ void GraphEdit::add_child_notify(Node *p_child) { gn->set_scale(Vector2(zoom,zoom)); gn->connect("offset_changed",this,"_graph_node_moved",varray(gn)); gn->connect("raise_request",this,"_graph_node_raised",varray(gn)); + gn->connect("item_rect_changed",connections_layer,"update"); _graph_node_moved(gn); gn->set_stop_mouse(false); } @@ -360,7 +361,8 @@ bool GraphEdit::_filter_input(const Point2& p_point) { Ref<Texture> port =get_icon("port","GraphNode"); - float grab_r=port->get_width()*0.5; + float grab_r_extend = 2.0; + float grab_r=port->get_width()*0.5*grab_r_extend; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -379,8 +381,9 @@ bool GraphEdit::_filter_input(const Point2& p_point) { for(int j=0;j<gn->get_connection_input_count();j++) { Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos(); - if (pos.distance_to(p_point)<grab_r) + if (pos.distance_to(p_point)<grab_r) { return true; + } } @@ -392,11 +395,13 @@ bool GraphEdit::_filter_input(const Point2& p_point) { void GraphEdit::_top_layer_input(const InputEvent& p_ev) { + + float grab_r_extend = 2.0; if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index==BUTTON_LEFT && p_ev.mouse_button.pressed) { Ref<Texture> port =get_icon("port","GraphNode"); Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y); - float grab_r=port->get_width()*0.5; + float grab_r=port->get_width()*0.5*grab_r_extend; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -517,7 +522,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { Ref<Texture> port =get_icon("port","GraphNode"); Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y); - float grab_r=port->get_width()*0.5; + float grab_r=port->get_width()*0.5*grab_r_extend; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -646,8 +651,8 @@ void GraphEdit::_draw_cos_line(CanvasItem* p_where,const Vector2& p_from, const cp_offset=MAX(MIN(cp_len-diff,cp_neg_len),-diff*0.5); } - Vector2 c1 = Vector2(cp_offset,0); - Vector2 c2 = Vector2(-cp_offset,0); + Vector2 c1 = Vector2(cp_offset*zoom,0); + Vector2 c2 = Vector2(-cp_offset*zoom,0); int lines=0; _bake_segment2d(p_where,0,1,p_from,c1,p_to,c2,0,3,9,8,p_color,p_to_color,lines); @@ -722,9 +727,9 @@ void GraphEdit::_connections_layer_draw() { continue; } - Vector2 frompos=gfrom->get_connection_output_pos(E->get().from_port)+gfrom->get_offset(); + Vector2 frompos=gfrom->get_connection_output_pos(E->get().from_port)+gfrom->get_offset()*zoom; Color color = gfrom->get_connection_output_color(E->get().from_port); - Vector2 topos=gto->get_connection_input_pos(E->get().to_port)+gto->get_offset(); + Vector2 topos=gto->get_connection_input_pos(E->get().to_port)+gto->get_offset()*zoom; Color tocolor = gto->get_connection_input_color(E->get().to_port); _draw_cos_line(connections_layer,frompos,topos,color,tocolor); @@ -908,18 +913,20 @@ void GraphEdit::_input_event(const InputEvent& p_ev) { if (b.button_index==BUTTON_LEFT && b.pressed) { GraphNode *gn = NULL; + GraphNode *gn_selected = NULL; for(int i=get_child_count()-1;i>=0;i--) { - gn=get_child(i)->cast_to<GraphNode>(); + gn_selected=get_child(i)->cast_to<GraphNode>(); - if (gn) { + if (gn_selected) { - if (gn->is_resizing()) + if (gn_selected->is_resizing()) continue; - Rect2 r = gn->get_rect(); + Rect2 r = gn_selected->get_rect(); r.size*=zoom; if (r.has_point(get_local_mouse_pos())) + gn = gn_selected; break; } } @@ -1046,6 +1053,7 @@ void GraphEdit::set_zoom(float p_zoom) { top_layer->update(); _update_scroll(); + connections_layer->update(); if (is_visible()) { diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index da298a795a..eec973ebef 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -745,6 +745,9 @@ void GraphNode::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_resizeable","resizeable"),&GraphNode::set_resizeable); ObjectTypeDB::bind_method(_MD("is_resizeable"),&GraphNode::is_resizeable); + ObjectTypeDB::bind_method(_MD("set_selected","selected"),&GraphNode::set_selected); + ObjectTypeDB::bind_method(_MD("is_selected"),&GraphNode::is_selected); + ObjectTypeDB::bind_method(_MD("get_connection_output_count"),&GraphNode::get_connection_output_count); ObjectTypeDB::bind_method(_MD("get_connection_input_count"),&GraphNode::get_connection_input_count); @@ -766,6 +769,7 @@ void GraphNode::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::STRING,"title"),_SCS("set_title"),_SCS("get_title")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"show_close"),_SCS("set_show_close_button"),_SCS("is_close_button_visible")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"resizeable"),_SCS("set_resizeable"),_SCS("is_resizeable")); ADD_SIGNAL(MethodInfo("offset_changed")); ADD_SIGNAL(MethodInfo("dragged",PropertyInfo(Variant::VECTOR2,"from"),PropertyInfo(Variant::VECTOR2,"to"))); @@ -788,4 +792,5 @@ GraphNode::GraphNode() { comment=false; resizeable=false; resizing=false; + selected=false; } diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 105d919338..f69ad8fa7e 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -40,6 +40,7 @@ void ItemList::add_item(const String& p_item,const Ref<Texture>& p_texture,bool item.selectable=p_selectable; item.selected=false; item.disabled=false; + item.tooltip_enabled=true; item.custom_bg=Color(0,0,0,0); items.push_back(item); @@ -57,6 +58,7 @@ void ItemList::add_icon_item(const Ref<Texture>& p_item,bool p_selectable){ item.selectable=p_selectable; item.selected=false; item.disabled=false; + item.tooltip_enabled=true; item.custom_bg=Color(0,0,0,0); items.push_back(item); @@ -82,6 +84,16 @@ String ItemList::get_item_text(int p_idx) const{ } +void ItemList::set_item_tooltip_enabled(int p_idx, const bool p_enabled) { + ERR_FAIL_INDEX(p_idx,items.size()); + items[p_idx].tooltip_enabled = p_enabled; +} + +bool ItemList::is_item_tooltip_enabled(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx,items.size(), false); + return items[p_idx].tooltip_enabled; +} + void ItemList::set_item_tooltip(int p_idx,const String& p_tooltip){ ERR_FAIL_INDEX(p_idx,items.size()); @@ -947,7 +959,23 @@ void ItemList::_notification(int p_what) { shape_changed=false; } + //ensure_selected_visible needs to be checked before we draw the list. + if (ensure_selected_visible && current>=0 && current <=items.size()) { + Rect2 r = items[current].rect_cache; + int from = scroll_bar->get_val(); + int to = from + scroll_bar->get_page(); + + if (r.pos.y < from) { + scroll_bar->set_val(r.pos.y); + } else if (r.pos.y+r.size.y > to) { + scroll_bar->set_val(r.pos.y+r.size.y - (to-from)); + } + + + } + + ensure_selected_visible=false; Vector2 base_ofs = bg->get_offset(); base_ofs.y-=int(scroll_bar->get_val()); @@ -1135,25 +1163,6 @@ void ItemList::_notification(int p_what) { for(int i=0;i<separators.size();i++) { draw_line(Vector2(bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),Vector2(size.width-bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),guide_color); } - - - if (ensure_selected_visible && current>=0 && current <=items.size()) { - - Rect2 r = items[current].rect_cache; - int from = scroll_bar->get_val(); - int to = from + scroll_bar->get_page(); - - if (r.pos.y < from) { - scroll_bar->set_val(r.pos.y); - } else if (r.pos.y+r.size.y > to) { - scroll_bar->set_val(r.pos.y+r.size.y - (to-from)); - } - - - } - - ensure_selected_visible=false; - } } @@ -1198,6 +1207,9 @@ String ItemList::get_tooltip(const Point2& p_pos) const { int closest = get_item_at_pos(p_pos); if (closest!=-1) { + if (!items[closest].tooltip_enabled) { + return ""; + } if (items[closest].tooltip!="") { return items[closest].tooltip; } @@ -1294,6 +1306,9 @@ void ItemList::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_item_custom_bg_color","idx","custom_bg_color"),&ItemList::set_item_custom_bg_color); ObjectTypeDB::bind_method(_MD("get_item_custom_bg_color","idx"),&ItemList::get_item_custom_bg_color); + ObjectTypeDB::bind_method(_MD("set_item_tooltip_enabled","idx","enable"),&ItemList::set_item_tooltip_enabled); + ObjectTypeDB::bind_method(_MD("is_item_tooltip_enabled","idx"),&ItemList::is_item_tooltip_enabled); + ObjectTypeDB::bind_method(_MD("set_item_tooltip","idx","tooltip"),&ItemList::set_item_tooltip); ObjectTypeDB::bind_method(_MD("get_item_tooltip","idx"),&ItemList::get_item_tooltip); @@ -1340,6 +1355,8 @@ void ItemList::_bind_methods(){ ObjectTypeDB::bind_method(_MD("ensure_current_is_visible"),&ItemList::ensure_current_is_visible); + ObjectTypeDB::bind_method(_MD("get_v_scroll"),&ItemList::get_v_scroll); + ObjectTypeDB::bind_method(_MD("_scroll_changed"),&ItemList::_scroll_changed); ObjectTypeDB::bind_method(_MD("_input_event"),&ItemList::_input_event); diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index e1902d1c1f..cb5908bc79 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -56,6 +56,7 @@ private: bool selectable; bool selected; bool disabled; + bool tooltip_enabled; Variant metadata; String tooltip; Color custom_bg; @@ -135,6 +136,9 @@ public: void set_item_tag_icon(int p_idx,const Ref<Texture>& p_tag_icon); Ref<Texture> get_item_tag_icon(int p_idx) const; + void set_item_tooltip_enabled(int p_idx, const bool p_enabled); + bool is_item_tooltip_enabled(int p_idx) const; + void set_item_tooltip(int p_idx,const String& p_tooltip); String get_item_tooltip(int p_idx) const; @@ -191,6 +195,8 @@ public: void set_icon_scale(real_t p_scale); real_t get_icon_scale() const; + VScrollBar *get_v_scroll() { return scroll_bar; } + ItemList(); ~ItemList(); }; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index fcea12fd6b..f7d74b2b49 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -193,8 +193,8 @@ void LineEdit::_input_event(InputEvent p_event) { } set_cursor_pos(0); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); + } @@ -215,8 +215,7 @@ void LineEdit::_input_event(InputEvent p_event) { selection_clear(); undo_text = text; text = text.substr(0,cursor_pos); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } } break; @@ -475,9 +474,7 @@ void LineEdit::_input_event(InputEvent p_event) { selection_delete(); CharType ucodestr[2]={(CharType)k.unicode,0}; append_at_cursor(ucodestr); - emit_signal("text_changed",text); - _change_notify("text"); - + _text_changed(); accept_event(); } @@ -642,6 +639,7 @@ void LineEdit::_notification(int p_what) { if(text.empty()) font_color.a *= placeholder_alpha; + int caret_height = font->get_height() > y_area ? y_area : font->get_height(); while(true) { //end of string, break! @@ -660,14 +658,14 @@ void LineEdit::_notification(int p_what) { bool selected=selection.enabled && char_ofs>=selection.begin && char_ofs<selection.end; if (selected) - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(char_width, y_area)), selection_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(char_width, caret_height)), selection_color); font->draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, selected ? font_color_selected : font_color); if (char_ofs==cursor_pos && draw_caret) { VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2( - Point2( x_ofs , y_ofs ), Size2( 1, y_area ) ), cursor_color ); + Point2( x_ofs , y_ofs ), Size2( 1, caret_height ) ), cursor_color ); } x_ofs+=char_width; @@ -676,7 +674,7 @@ void LineEdit::_notification(int p_what) { if (char_ofs==cursor_pos && draw_caret) {//may be at the end VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2( - Point2( x_ofs , y_ofs ), Size2( 1, y_area ) ), cursor_color ); + Point2( x_ofs , y_ofs ), Size2( 1, caret_height ) ), cursor_color ); } } break; case NOTIFICATION_FOCUS_ENTER: { @@ -725,8 +723,7 @@ void LineEdit::paste_text() { if(selection.enabled) selection_delete(); append_at_cursor(paste_buffer); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } @@ -750,9 +747,7 @@ void LineEdit::undo() { set_cursor_pos(old_cursor_pos); } - emit_signal("text_changed",text); - _change_notify("text"); - + _text_changed(); } void LineEdit::shift_selection_check_pre(bool p_shift) { @@ -806,16 +801,6 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) { pixel_ofs+=char_w; if (pixel_ofs > p_x) { //found what we look for - - - if ( (pixel_ofs-p_x) < (char_w >> 1 ) ) { - - ofs+=1; - } else if ( (pixel_ofs-p_x) > (char_w >> 1 ) ) { - - ofs-=1; - } - break; } @@ -891,8 +876,7 @@ void LineEdit::delete_char() { // set_window_pos(cursor_pos-get_window_length()); } - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } void LineEdit::delete_text(int p_from_column, int p_to_column) { @@ -924,8 +908,7 @@ void LineEdit::delete_text(int p_from_column, int p_to_column) { window_pos=cursor_pos; } - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } void LineEdit::set_text(String p_text) { @@ -940,8 +923,7 @@ void LineEdit::set_text(String p_text) { void LineEdit::clear() { clear_internal(); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } String LineEdit::get_text() const { @@ -1080,7 +1062,17 @@ Size2 LineEdit::get_minimum_size() const { Size2 min=style->get_minimum_size(); min.height+=font->get_height(); - min.width+=get_constant("minimum_spaces")*font->get_char_size(' ').x; + + //minimum size of text + int space_size = font->get_char_size(' ').x; + int mstext = get_constant("minimum_spaces")*space_size; + + if (expand_to_text_length) { + mstext=MAX(mstext,font->get_string_size(text).x+space_size); //add a spce because some fonts are too exact + } + + min.width+=mstext; + return min; } @@ -1200,24 +1192,28 @@ void LineEdit::menu_option(int p_option) { switch(p_option) { case MENU_CUT: { - cut_text(); + if (editable) { + cut_text(); + } } break; case MENU_COPY: { copy_text(); } break; case MENU_PASTE: { - - paste_text(); + if (editable) { + paste_text(); + } } break; case MENU_CLEAR: { - clear(); + if (editable) { + clear(); + } } break; case MENU_SELECT_ALL: { select_all(); } break; case MENU_UNDO: { - undo(); } break; @@ -1236,6 +1232,29 @@ PopupMenu *LineEdit::get_menu() const { } #endif + +void LineEdit::set_expand_to_text_length(bool p_enabled) { + + expand_to_text_length = p_enabled; + minimum_size_changed(); +} + +bool LineEdit::get_expand_to_text_length() const{ + + return expand_to_text_length; +} + + +void LineEdit::_text_changed() { + + if (expand_to_text_length) + minimum_size_changed(); + + emit_signal("text_changed",text); + _change_notify("text"); + +} + void LineEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("_toggle_draw_caret"),&LineEdit::_toggle_draw_caret); @@ -1258,7 +1277,9 @@ void LineEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_placeholder_alpha"),&LineEdit::get_placeholder_alpha); ObjectTypeDB::bind_method(_MD("set_cursor_pos","pos"),&LineEdit::set_cursor_pos); ObjectTypeDB::bind_method(_MD("get_cursor_pos"),&LineEdit::get_cursor_pos); - ObjectTypeDB::bind_method(_MD("cursor_set_blink_enabled", "enable"),&LineEdit::cursor_set_blink_enabled); + ObjectTypeDB::bind_method(_MD("set_expand_to_text_length","enabled"),&LineEdit::set_expand_to_text_length); + ObjectTypeDB::bind_method(_MD("get_expand_to_text_length"),&LineEdit::get_expand_to_text_length); + ObjectTypeDB::bind_method(_MD("cursor_set_blink_enabled", "enabled"),&LineEdit::cursor_set_blink_enabled); ObjectTypeDB::bind_method(_MD("cursor_get_blink_enabled"),&LineEdit::cursor_get_blink_enabled); ObjectTypeDB::bind_method(_MD("cursor_set_blink_speed", "blink_speed"),&LineEdit::cursor_set_blink_speed); ObjectTypeDB::bind_method(_MD("cursor_get_blink_speed"),&LineEdit::cursor_get_blink_speed); @@ -1296,6 +1317,7 @@ void LineEdit::_bind_methods() { ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "max_length" ), _SCS("set_max_length"),_SCS("get_max_length") ); ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "editable" ), _SCS("set_editable"),_SCS("is_editable") ); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "secret" ), _SCS("set_secret"),_SCS("is_secret") ); + ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "expand_to_len" ), _SCS("set_expand_to_text_length"),_SCS("get_expand_to_text_length") ); ADD_PROPERTY( PropertyInfo( Variant::INT,"focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), _SCS("set_focus_mode"), _SCS("get_focus_mode") ); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret/caret_blink"), _SCS("cursor_set_blink_enabled"), _SCS("cursor_get_blink_enabled"));; ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret/caret_blink_speed",PROPERTY_HINT_RANGE,"0.1,10,0.1"), _SCS("cursor_set_blink_speed"),_SCS("cursor_get_blink_speed") ); @@ -1337,7 +1359,7 @@ LineEdit::LineEdit() { menu->add_separator(); menu->add_item(TTR("Undo"),MENU_UNDO,KEY_MASK_CMD|KEY_Z); menu->connect("item_pressed",this,"menu_option"); - + expand_to_text_length=false; } diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 112e4ad55e..47d5706bbe 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -90,6 +90,11 @@ private: } selection; Timer *caret_blink_timer; + + + void _text_changed(); + bool expand_to_text_length; + bool caret_blink_enabled; bool draw_caret; bool window_has_focus; @@ -169,6 +174,9 @@ public: virtual Size2 get_minimum_size() const; + void set_expand_to_text_length(bool p_len); + bool get_expand_to_text_length() const; + virtual bool is_text_field() const; LineEdit(); ~LineEdit(); diff --git a/scene/gui/panel.h b/scene/gui/panel.h index efa9ebcaa0..9e2e7df7f0 100644 --- a/scene/gui/panel.h +++ b/scene/gui/panel.h @@ -45,4 +45,6 @@ public: }; + + #endif diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index b3f18bf8fa..2fbb093e8e 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -701,6 +701,13 @@ void PopupMenu::set_item_submenu(int p_idx, const String& p_submenu) { update(); } +void PopupMenu::toggle_item_checked(int p_idx) { + + ERR_FAIL_INDEX(p_idx,items.size()); + items[p_idx].checked = !items[p_idx].checked; + update(); +} + String PopupMenu::get_item_text(int p_idx) const { ERR_FAIL_INDEX_V(p_idx,items.size(),""); @@ -1061,33 +1068,40 @@ void PopupMenu::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_icon_check_shortcut","texture","shortcut:ShortCut","id"),&PopupMenu::add_icon_check_shortcut,DEFVAL(-1)); ObjectTypeDB::bind_method(_MD("add_check_shortcut","shortcut:ShortCut","id"),&PopupMenu::add_check_shortcut,DEFVAL(-1)); - ObjectTypeDB::bind_method(_MD("set_item_text","idx","text"),&PopupMenu::set_item_text); ObjectTypeDB::bind_method(_MD("set_item_icon","idx","icon"),&PopupMenu::set_item_icon); + ObjectTypeDB::bind_method(_MD("set_item_checked","idx","checked"),&PopupMenu::set_item_checked); + ObjectTypeDB::bind_method(_MD("set_item_ID","idx","id"),&PopupMenu::set_item_ID); ObjectTypeDB::bind_method(_MD("set_item_accelerator","idx","accel"),&PopupMenu::set_item_accelerator); ObjectTypeDB::bind_method(_MD("set_item_metadata","idx","metadata"),&PopupMenu::set_item_metadata); - ObjectTypeDB::bind_method(_MD("set_item_checked","idx","checked"),&PopupMenu::set_item_checked); ObjectTypeDB::bind_method(_MD("set_item_disabled","idx","disabled"),&PopupMenu::set_item_disabled); - ObjectTypeDB::bind_method(_MD("set_item_shortcut","idx","shortcut:ShortCut"),&PopupMenu::set_item_shortcut); ObjectTypeDB::bind_method(_MD("set_item_submenu","idx","submenu"),&PopupMenu::set_item_submenu); ObjectTypeDB::bind_method(_MD("set_item_as_separator","idx","enable"),&PopupMenu::set_item_as_separator); ObjectTypeDB::bind_method(_MD("set_item_as_checkable","idx","enable"),&PopupMenu::set_item_as_checkable); - ObjectTypeDB::bind_method(_MD("set_item_ID","idx","id"),&PopupMenu::set_item_ID); + ObjectTypeDB::bind_method(_MD("set_item_tooltip","idx","tooltip"),&PopupMenu::set_item_tooltip); + ObjectTypeDB::bind_method(_MD("set_item_shortcut","idx","shortcut:ShortCut"),&PopupMenu::set_item_shortcut); + + ObjectTypeDB::bind_method(_MD("toggle_item_checked","idx"), &PopupMenu::toggle_item_checked); + ObjectTypeDB::bind_method(_MD("get_item_text","idx"),&PopupMenu::get_item_text); ObjectTypeDB::bind_method(_MD("get_item_icon","idx"),&PopupMenu::get_item_icon); - ObjectTypeDB::bind_method(_MD("get_item_metadata","idx"),&PopupMenu::get_item_metadata); + ObjectTypeDB::bind_method(_MD("is_item_checked","idx"),&PopupMenu::is_item_checked); + ObjectTypeDB::bind_method(_MD("get_item_ID","idx"),&PopupMenu::get_item_ID); + ObjectTypeDB::bind_method(_MD("get_item_index","id"),&PopupMenu::get_item_index); ObjectTypeDB::bind_method(_MD("get_item_accelerator","idx"),&PopupMenu::get_item_accelerator); - ObjectTypeDB::bind_method(_MD("get_item_shortcut:ShortCut","idx"),&PopupMenu::get_item_shortcut); + ObjectTypeDB::bind_method(_MD("get_item_metadata","idx"),&PopupMenu::get_item_metadata); + ObjectTypeDB::bind_method(_MD("is_item_disabled","idx"),&PopupMenu::is_item_disabled); ObjectTypeDB::bind_method(_MD("get_item_submenu","idx"),&PopupMenu::get_item_submenu); ObjectTypeDB::bind_method(_MD("is_item_separator","idx"),&PopupMenu::is_item_separator); ObjectTypeDB::bind_method(_MD("is_item_checkable","idx"),&PopupMenu::is_item_checkable); - ObjectTypeDB::bind_method(_MD("is_item_checked","idx"),&PopupMenu::is_item_checked); - ObjectTypeDB::bind_method(_MD("is_item_disabled","idx"),&PopupMenu::is_item_disabled); - ObjectTypeDB::bind_method(_MD("get_item_ID","idx"),&PopupMenu::get_item_ID); - ObjectTypeDB::bind_method(_MD("get_item_index","id"),&PopupMenu::get_item_index); + ObjectTypeDB::bind_method(_MD("get_item_tooltip","idx"),&PopupMenu::get_item_tooltip); + ObjectTypeDB::bind_method(_MD("get_item_shortcut:ShortCut","idx"),&PopupMenu::get_item_shortcut); + ObjectTypeDB::bind_method(_MD("get_item_count"),&PopupMenu::get_item_count); - ObjectTypeDB::bind_method(_MD("add_separator"),&PopupMenu::add_separator); + ObjectTypeDB::bind_method(_MD("remove_item","idx"),&PopupMenu::remove_item); + + ObjectTypeDB::bind_method(_MD("add_separator"),&PopupMenu::add_separator); ObjectTypeDB::bind_method(_MD("clear"),&PopupMenu::clear); ObjectTypeDB::bind_method(_MD("_set_items"),&PopupMenu::_set_items); @@ -1125,5 +1139,3 @@ PopupMenu::PopupMenu() { PopupMenu::~PopupMenu() { } - - diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index f35e91d4e4..b3e8cd2713 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -116,6 +116,8 @@ public: void set_item_tooltip(int p_idx,const String& p_tooltip); void set_item_shortcut(int p_idx, const Ref<ShortCut>& p_shortcut); + void toggle_item_checked(int p_idx); + String get_item_text(int p_idx) const; Ref<Texture> get_item_icon(int p_idx) const; bool is_item_checked(int p_idx) const; diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 190e8e141f..479bb96fe2 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -228,14 +228,14 @@ void ScrollContainer::_notification(int p_what) { child_max_size.y = MAX(child_max_size.y, minsize.y); Rect2 r = Rect2(-scroll,minsize); - if (!scroll_h) { + if (!(scroll_h || h_scroll->is_visible())) { r.pos.x=0; if (c->get_h_size_flags()&SIZE_EXPAND) r.size.width=MAX(size.width,minsize.width); else r.size.width=minsize.width; } - if (!scroll_v) { + if (!(scroll_v || v_scroll->is_visible())) { r.pos.y=0; r.size.height=size.height; if (c->get_v_size_flags()&SIZE_EXPAND) diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 4756fdee26..f1a2823e8f 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -34,6 +34,7 @@ #include "globals.h" #include "message_queue.h" +#include "scene/main/viewport.h" #define TAB_PIXELS @@ -481,6 +482,14 @@ void TextEdit::_notification(int p_what) { Color color = cache.font_color; int in_region=-1; + if (line_length_guideline) { + int x=xmargin_beg+cache.font->get_char_size('0').width*line_length_guideline_col-cursor.x_ofs; + if (x>xmargin_beg && x<xmargin_end) { + Color guideline_color(color.r,color.g,color.b,color.a*0.25f); + VisualServer::get_singleton()->canvas_item_add_line(ci,Point2(x,0),Point2(x,cache.size.height),guideline_color); + } + } + if (syntax_coloring) { if (custom_bg_color.a>0.01) { @@ -684,6 +693,8 @@ void TextEdit::_notification(int p_what) { // get the highlighted words String highlighted_text = get_selection_text(); + String line_num_padding = line_numbers_zero_padded ? "0" : " "; + for (int i=0;i<visible_rows;i++) { int line=i+cursor.line_ofs; @@ -699,6 +710,7 @@ void TextEdit::_notification(int p_what) { bool prev_is_char=false; bool prev_is_number = false; bool in_keyword=false; + bool underlined=false; bool in_word = false; bool in_function_name = false; bool in_member_variable = false; @@ -748,7 +760,7 @@ void TextEdit::_notification(int p_what) { if (cache.line_number_w) { String fc = String::num(line+1); while (fc.length() < line_number_char_count) { - fc="0"+fc; + fc=line_num_padding+fc; } cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT)+cache.breakpoint_gutter_width,ofs_y+cache.font->get_ascent()),fc,cache.line_number_color); @@ -824,8 +836,10 @@ void TextEdit::_notification(int p_what) { } } - if (!is_char) + if (!is_char) { in_keyword=false; + underlined=false; + } if (in_region==-1 && !in_keyword && is_char && !prev_is_char) { @@ -843,6 +857,12 @@ void TextEdit::_notification(int p_what) { in_keyword=true; keyword_color=*col; } + + if (select_identifiers_enabled && hilighted_word!=String()) { + if (hilighted_word==range) { + underlined=true; + } + } } if (!in_function_name && in_word && !in_keyword) { @@ -1023,8 +1043,12 @@ void TextEdit::_notification(int p_what) { color = cache.caret_background_color; } - if (str[j]>=32) - cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),str[j],str[j+1],in_selection?cache.font_selected_color:color); + if (str[j]>=32) { + int w = cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),str[j],str[j+1],in_selection?cache.font_selected_color:color); + if (underlined) { + draw_rect(Rect2( char_ofs+char_margin, ofs_y+ascent+2,w,1),in_selection?cache.font_selected_color:color); + } + } else if (draw_tabs && str[j]=='\t') { int yofs= (get_row_height() - cache.tab_icon->get_height())/2; @@ -1231,15 +1255,19 @@ void TextEdit::_notification(int p_what) { } if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->show_virtual_keyboard(get_text(),get_global_rect()); + if (raised_from_completion) { + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 1); + } } break; case NOTIFICATION_FOCUS_EXIT: { if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->hide_virtual_keyboard(); - + if (raised_from_completion) { + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 0); + } } break; - } } @@ -1500,11 +1528,19 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } if (mb.button_index==BUTTON_LEFT) { + _reset_caret_blink_timer(); int row,col; _get_mouse_pos(Point2i(mb.x,mb.y), row,col); + if (mb.mod.command && hilighted_word!=String()) { + + emit_signal("symbol_lookup",hilighted_word,row,col); + return; + } + + // toggle breakpoint on gutter click if (draw_breakpoint_gutter) { int gutter=cache.style_normal->get_margin(MARGIN_LEFT); @@ -1629,7 +1665,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { update(); } - if (mb.button_index==BUTTON_RIGHT) { + if (mb.button_index==BUTTON_RIGHT && context_menu_enabled) { menu->set_pos(get_global_transform().xform(get_local_mouse_pos())); menu->set_size(Vector2(1,1)); @@ -1651,7 +1687,23 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { const InputEventMouseMotion &mm=p_input_event.mouse_motion; - if (mm.button_mask&BUTTON_MASK_LEFT) { + if (select_identifiers_enabled) { + if (mm.mod.command && mm.button_mask==0) { + + String new_word = get_word_at_pos(Vector2(mm.x,mm.y)); + if (new_word!=hilighted_word) { + hilighted_word=new_word; + update(); + } + } else { + if (hilighted_word!=String()) { + hilighted_word=String(); + update(); + } + } + } + + if (mm.button_mask&BUTTON_MASK_LEFT && get_viewport()->gui_get_drag_data()==Variant()) { //ignore if dragging if (selection.selecting_mode!=Selection::MODE_NONE) { @@ -1678,6 +1730,27 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { InputEventKey k=p_input_event.key; + +#ifdef OSX_ENABLED + if (k.scancode==KEY_META) { +#else + if (k.scancode==KEY_CONTROL) { + +#endif + if (select_identifiers_enabled) { + + if (k.pressed) { + + hilighted_word = get_word_at_pos(get_local_mouse_pos()); + update(); + + } else { + hilighted_word=String(); + update(); + } + } + } + if (!k.pressed) return; @@ -1845,6 +1918,8 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (!k.mod.command) { _reset_caret_blink_timer(); } + + // save here for insert mode, just in case it is cleared in the following section bool had_selection = selection.active; @@ -2481,7 +2556,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } break; case KEY_X: { - + if (readonly) { + break; + } if (!k.mod.command || k.mod.shift || k.mod.alt) { scancode_handled=false; break; @@ -2513,7 +2590,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { undo(); } break; case KEY_V: { - + if (readonly) { + break; + } if (!k.mod.command || k.mod.shift || k.mod.alt) { scancode_handled=false; break; @@ -2558,7 +2637,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } update(); } - break;} + } break; default: { @@ -3222,6 +3301,9 @@ void TextEdit::insert_text_at_cursor(const String& p_text) { } Control::CursorShape TextEdit::get_cursor_shape(const Point2& p_pos) const { + if (hilighted_word!=String()) + return CURSOR_POINTING_HAND; + int gutter=cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w+cache.breakpoint_gutter_width; if((completion_active && completion_rect.has_point(p_pos)) || p_pos.x < gutter) { return CURSOR_ARROW; @@ -3264,6 +3346,36 @@ String TextEdit::get_text() { }; + +String TextEdit::get_text_for_lookup_completion() { + + + int row,col; + _get_mouse_pos(get_local_mouse_pos(), row,col); + + + String longthing; + int len = text.size(); + for (int i=0;i<len;i++) { + + if (i==row) { + longthing+=text[i].substr(0,col); + longthing+=String::chr(0xFFFF); //not unicode, represents the cursor + longthing+=text[i].substr(col,text[i].size()); + } else { + + longthing+=text[i]; + } + + + if (i!=len-1) + longthing+="\n"; + } + + return longthing; + +} + String TextEdit::get_text_for_completion() { String longthing; @@ -4099,12 +4211,17 @@ void TextEdit::_confirm_completion() { void TextEdit::_cancel_code_hint() { + + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 0); + raised_from_completion = false; completion_hint=""; update(); } void TextEdit::_cancel_completion() { + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 0); + raised_from_completion = false; if (!completion_active) return; @@ -4284,6 +4401,8 @@ void TextEdit::query_code_comple() { void TextEdit::set_code_hint(const String& p_hint) { + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 1); + raised_from_completion = true; completion_hint=p_hint; completion_hint_offset=-0xFFFF; update(); @@ -4291,7 +4410,8 @@ void TextEdit::set_code_hint(const String& p_hint) { void TextEdit::code_complete(const Vector<String> &p_strings) { - + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 1); + raised_from_completion = true; completion_strings=p_strings; completion_active=true; completion_current=""; @@ -4301,6 +4421,38 @@ void TextEdit::code_complete(const Vector<String> &p_strings) { } +String TextEdit::get_word_at_pos(const Vector2& p_pos) const { + + int row,col; + _get_mouse_pos(p_pos, row, col); + + String s = text[row]; + if (s.length()==0) + return ""; + int beg=CLAMP(col,0,s.length()); + int end=beg; + + + if (s[beg]>32 || beg==s.length()) { + + bool symbol = beg < s.length() && _is_symbol(s[beg]); //not sure if right but most editors behave like this + + while(beg>0 && s[beg-1]>32 && (symbol==_is_symbol(s[beg-1]))) { + beg--; + } + while(end<s.length() && s[end+1]>32 && (symbol==_is_symbol(s[end+1]))) { + end++; + } + + if (end<s.length()) + end+=1; + + return s.substr(beg,end-beg); + } + + return String(); +} + String TextEdit::get_tooltip(const Point2& p_pos) const { if (!tooltip_obj) @@ -4370,10 +4522,26 @@ void TextEdit::set_show_line_numbers(bool p_show) { update(); } +void TextEdit::set_line_numbers_zero_padded(bool p_zero_padded) { + + line_numbers_zero_padded=p_zero_padded; + update(); +} + bool TextEdit::is_show_line_numbers_enabled() const { return line_numbers; } +void TextEdit::set_show_line_length_guideline(bool p_show) { + line_length_guideline=p_show; + update(); +} + +void TextEdit::set_line_length_guideline_column(int p_column) { + line_length_guideline_col=p_column; + update(); +} + void TextEdit::set_draw_breakpoint_gutter(bool p_draw) { draw_breakpoint_gutter = p_draw; update(); @@ -4401,18 +4569,22 @@ void TextEdit::menu_option(int p_option) { switch( p_option ) { case MENU_CUT: { - - cut(); + if (!readonly) { + cut(); + } } break; case MENU_COPY: { copy(); } break; case MENU_PASTE: { - - paste(); + if (!readonly) { + paste(); + } } break; case MENU_CLEAR: { - clear(); + if (!readonly) { + clear(); + } } break; case MENU_SELECT_ALL: { select_all(); @@ -4424,6 +4596,21 @@ void TextEdit::menu_option(int p_option) { }; } + +void TextEdit::set_select_identifiers_on_hover(bool p_enable) { + + select_identifiers_enabled=p_enable; +} + +bool TextEdit::is_selecting_identifiers_on_hover_enabled() const { + + return select_identifiers_enabled; +} + +void TextEdit::set_context_menu_enabled(bool p_enable) { + context_menu_enabled = p_enable; +} + PopupMenu *TextEdit::get_menu() const { return menu; } @@ -4520,6 +4707,7 @@ void TextEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("text_changed")); ADD_SIGNAL(MethodInfo("request_completion")); ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo( Variant::INT, "row"))); + ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING,"symbol"),PropertyInfo( Variant::INT, "row"),PropertyInfo( Variant::INT, "column"))); BIND_CONSTANT( MENU_CUT ); BIND_CONSTANT( MENU_COPY ); @@ -4631,6 +4819,9 @@ TextEdit::TextEdit() { completion_line_ofs=0; tooltip_obj=NULL; line_numbers=false; + line_numbers_zero_padded=false; + line_length_guideline=false; + line_length_guideline_col=80; draw_breakpoint_gutter=false; next_operation_is_complex=false; scroll_past_end_of_file_enabled=false; @@ -4640,7 +4831,11 @@ TextEdit::TextEdit() { auto_indent=false; insert_mode = false; window_has_focus=true; + select_identifiers_enabled=false; + + raised_from_completion = false; + context_menu_enabled=true; menu = memnew( PopupMenu ); add_child(menu); menu->add_item(TTR("Cut"),MENU_CUT,KEY_MASK_CMD|KEY_X); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index f0301fc250..7820fefdd2 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -232,6 +232,9 @@ class TextEdit : public Control { bool text_changed_dirty; bool undo_enabled; bool line_numbers; + bool line_numbers_zero_padded; + bool line_length_guideline; + int line_length_guideline_col; bool draw_breakpoint_gutter; int breakpoint_gutter_width; @@ -242,6 +245,11 @@ class TextEdit : public Control { bool auto_indent; bool cut_copy_line; bool insert_mode; + bool select_identifiers_enabled; + + bool raised_from_completion; + + String hilighted_word; uint64_t last_dblclk; @@ -266,6 +274,8 @@ class TextEdit : public Control { int search_result_line; int search_result_col; + bool context_menu_enabled; + int get_visible_rows() const; int get_char_count(); @@ -316,8 +326,6 @@ class TextEdit : public Control { void _confirm_completion(); void _update_completion_candidates(); - void _get_mouse_pos(const Point2i& p_mouse, int &r_row, int &r_col) const; - protected: virtual String get_tooltip(const Point2& p_pos) const; @@ -357,6 +365,8 @@ public: virtual CursorShape get_cursor_shape(const Point2& p_pos=Point2i()) const; + void _get_mouse_pos(const Point2i& p_mouse, int &r_row, int &r_col) const; + //void delete_char(); //void delete_line(); @@ -444,6 +454,7 @@ public: String get_selection_text() const; String get_word_under_cursor() const; + String get_word_at_pos(const Vector2& p_pos) const; bool search(const String &p_key,uint32_t p_search_flags, int p_from_line, int p_from_column,int &r_line,int &r_column) const; @@ -479,6 +490,11 @@ public: void set_show_line_numbers(bool p_show); bool is_show_line_numbers_enabled() const; + void set_line_numbers_zero_padded(bool p_zero_padded); + + void set_show_line_length_guideline(bool p_show); + void set_line_length_guideline_column(int p_column); + void set_draw_breakpoint_gutter(bool p_draw); bool is_drawing_breakpoint_gutter() const; @@ -492,9 +508,14 @@ public: void set_code_hint(const String& p_hint); void query_code_comple(); + void set_select_identifiers_on_hover(bool p_enable); + bool is_selecting_identifiers_on_hover_enabled() const; + + void set_context_menu_enabled(bool p_enable); PopupMenu *get_menu() const; String get_text_for_completion(); + String get_text_for_lookup_completion(); virtual bool is_text_field() const; TextEdit(); diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp index 923a35031c..2c576b6ba5 100644 --- a/scene/gui/texture_progress.cpp +++ b/scene/gui/texture_progress.cpp @@ -297,6 +297,7 @@ void TextureProgress::_bind_methods() { TextureProgress::TextureProgress() { mode=FILL_LEFT_TO_RIGHT; + rad_init_angle=0; rad_center_off=Point2(); rad_max_degrees=360; } diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 20794b2faa..ca9c666c01 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -32,6 +32,7 @@ #include "os/keyboard.h" #include "globals.h" #include "os/input.h" +#include "scene/main/viewport.h" @@ -829,6 +830,8 @@ void Tree::update_cache() { cache.guide_width=get_constant("guide_width"); cache.draw_relationship_lines=get_constant("draw_relationship_lines"); cache.relationship_line_color=get_color("relationship_line_color"); + cache.scroll_border=get_constant("scroll_border"); + cache.scroll_speed=get_constant("scroll_speed"); cache.title_button = get_stylebox("title_button_normal"); cache.title_button_pressed = get_stylebox("title_button_pressed"); @@ -1701,16 +1704,11 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ } break; case TreeItem::CELL_MODE_CHECK: { - Ref<Texture> checked = cache.checked; bring_up_editor=false; //checkboxes are not edited with editor - if (x>=0 && x<= checked->get_width()+cache.hseparation ) { - - - p_item->set_checked(col,!c.checked); - item_edited(col,p_item); - click_handled=true; - //p_item->edited_signal.call(col); - } + p_item->set_checked(col, !c.checked); + item_edited(col, p_item); + click_handled = true; + //p_item->edited_signal.call(col); } break; case TreeItem::CELL_MODE_RANGE: @@ -2681,11 +2679,17 @@ void Tree::_notification(int p_what) { if (p_what==NOTIFICATION_DRAG_END) { drop_mode_flags=0; + scrolling = false; + set_fixed_process(false); update(); } if (p_what==NOTIFICATION_DRAG_BEGIN) { single_select_defer=NULL; + if (cache.scroll_speed > 0 && get_rect().has_point(get_viewport()->get_mouse_pos() - get_global_pos())) { + scrolling = true; + set_fixed_process(true); + } } if (p_what==NOTIFICATION_FIXED_PROCESS) { @@ -2731,6 +2735,28 @@ void Tree::_notification(int p_what) { } } + + if (scrolling) { + Point2 point = get_viewport()->get_mouse_pos() - get_global_pos(); + if (point.x < cache.scroll_border) { + point.x -= cache.scroll_border; + } else if (point.x > get_size().width - cache.scroll_border) { + point.x -= get_size().width - cache.scroll_border; + } else { + point.x = 0; + } + if (point.y < cache.scroll_border) { + point.y -= cache.scroll_border; + } else if (point.y > get_size().height - cache.scroll_border) { + point.y -= get_size().height - cache.scroll_border; + } else { + point.y = 0; + } + point *= cache.scroll_speed * get_fixed_process_delta_time(); + point += get_scroll(); + h_scroll->set_val(point.x); + v_scroll->set_val(point.y); + } } if (p_what==NOTIFICATION_DRAW) { diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 2124dce749..6c2f1dae40 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -390,6 +390,8 @@ friend class TreeItem; int button_margin; Point2 offset; int draw_relationship_lines; + int scroll_border; + int scroll_speed; enum ClickType { CLICK_NONE, @@ -448,6 +450,7 @@ friend class TreeItem; bool drag_touching_deaccel; bool click_handled; bool allow_rmb_select; + bool scrolling; bool force_select_on_already_selected; diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp index 1be847929d..335672126c 100644 --- a/scene/gui/video_player.cpp +++ b/scene/gui/video_player.cpp @@ -248,7 +248,7 @@ void VideoPlayer::stop() { playback->stop(); AudioServer::get_singleton()->stream_set_active(stream_rid,false); - resampler.clear(); + resampler.flush(); set_process(false); last_audio_time=0; }; @@ -426,5 +426,6 @@ VideoPlayer::~VideoPlayer() { if (stream_rid.is_valid()) AudioServer::get_singleton()->free(stream_rid); + resampler.clear(); //Not necessary here, but make in consistent with other "stream_player" classes }; diff --git a/scene/io/SCsub b/scene/io/SCsub index bbe59b3054..9fa89edbf7 100644 --- a/scene/io/SCsub +++ b/scene/io/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.scene_sources,"*.cpp") diff --git a/scene/io/resource_format_image.cpp b/scene/io/resource_format_image.cpp index f3a0eaa8c4..55ad23ba93 100644 --- a/scene/io/resource_format_image.cpp +++ b/scene/io/resource_format_image.cpp @@ -136,61 +136,7 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String& p_origin #endif - uint32_t flags=0; - - FileAccess *f2 = FileAccess::open(p_path+".flags",FileAccess::READ); - Map<String,bool> flags_found; - if (f2) { - - while(!f2->eof_reached()) { - String l2 = f2->get_line(); - int eqpos = l2.find("="); - if (eqpos!=-1) { - String flag=l2.substr(0,eqpos).strip_edges(); - String val=l2.substr(eqpos+1,l2.length()).strip_edges().to_lower(); - flags_found[flag]=(val=="true" || val=="1")?true:false; - } - } - memdelete(f2); - } - - - if (flags_found.has("filter")) { - if (flags_found["filter"]) - flags|=Texture::FLAG_FILTER; - } else if (bool(GLOBAL_DEF("image_loader/filter",true))) { - flags|=Texture::FLAG_FILTER; - } - - - if (flags_found.has("gen_mipmaps")) { - if (flags_found["gen_mipmaps"]) - flags|=Texture::FLAG_MIPMAPS; - } else if (bool(GLOBAL_DEF("image_loader/gen_mipmaps",true))) { - flags|=Texture::FLAG_MIPMAPS; - } - - if (flags_found.has("repeat")) { - if (flags_found["repeat"]) - flags|=Texture::FLAG_REPEAT; - } else if (bool(GLOBAL_DEF("image_loader/repeat",true))) { - flags|=Texture::FLAG_REPEAT; - } - - if (flags_found.has("anisotropic")) { - if (flags_found["anisotropic"]) - flags|=Texture::FLAG_ANISOTROPIC_FILTER; - } - - if (flags_found.has("tolinear")) { - if (flags_found["tolinear"]) - flags|=Texture::FLAG_CONVERT_TO_LINEAR; - } - - if (flags_found.has("mirroredrepeat")) { - if (flags_found["mirroredrepeat"]) - flags|=Texture::FLAG_MIRRORED_REPEAT; - } + uint32_t flags=load_image_flags(p_path); if (debug_load_times) begtime=OS::get_singleton()->get_ticks_usec(); @@ -214,6 +160,68 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String& p_origin } +uint32_t ResourceFormatLoaderImage::load_image_flags(const String &p_path) { + + + FileAccess *f2 = FileAccess::open(p_path+".flags",FileAccess::READ); + Map<String,bool> flags_found; + if (f2) { + + while(!f2->eof_reached()) { + String l2 = f2->get_line(); + int eqpos = l2.find("="); + if (eqpos!=-1) { + String flag=l2.substr(0,eqpos).strip_edges(); + String val=l2.substr(eqpos+1,l2.length()).strip_edges().to_lower(); + flags_found[flag]=(val=="true" || val=="1")?true:false; + } + } + memdelete(f2); + } + + + uint32_t flags=0; + + if (flags_found.has("filter")) { + if (flags_found["filter"]) + flags|=Texture::FLAG_FILTER; + } else if (bool(GLOBAL_DEF("image_loader/filter",true))) { + flags|=Texture::FLAG_FILTER; + } + + + if (flags_found.has("gen_mipmaps")) { + if (flags_found["gen_mipmaps"]) + flags|=Texture::FLAG_MIPMAPS; + } else if (bool(GLOBAL_DEF("image_loader/gen_mipmaps",true))) { + flags|=Texture::FLAG_MIPMAPS; + } + + if (flags_found.has("repeat")) { + if (flags_found["repeat"]) + flags|=Texture::FLAG_REPEAT; + } else if (bool(GLOBAL_DEF("image_loader/repeat",true))) { + flags|=Texture::FLAG_REPEAT; + } + + if (flags_found.has("anisotropic")) { + if (flags_found["anisotropic"]) + flags|=Texture::FLAG_ANISOTROPIC_FILTER; + } + + if (flags_found.has("tolinear")) { + if (flags_found["tolinear"]) + flags|=Texture::FLAG_CONVERT_TO_LINEAR; + } + + if (flags_found.has("mirroredrepeat")) { + if (flags_found["mirroredrepeat"]) + flags|=Texture::FLAG_MIRRORED_REPEAT; + } + + return flags; +} + bool ResourceFormatLoaderImage::handles_type(const String& p_type) const { return ObjectTypeDB::is_type(p_type,"Texture") || ObjectTypeDB::is_type(p_type,"CubeMap"); diff --git a/scene/io/resource_format_image.h b/scene/io/resource_format_image.h index 6388aa641f..cce6ffab83 100644 --- a/scene/io/resource_format_image.h +++ b/scene/io/resource_format_image.h @@ -39,8 +39,8 @@ class ResourceFormatLoaderImage : public ResourceFormatLoader { bool debug_load_times; int max_texture_size; public: - virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); + static uint32_t load_image_flags(const String &p_path); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/scene/main/SCsub b/scene/main/SCsub index bbe59b3054..9fa89edbf7 100644 --- a/scene/main/SCsub +++ b/scene/main/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.scene_sources,"*.cpp") diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index c31a57f819..8e238c7d77 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -168,20 +168,13 @@ void CanvasLayer::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { - Node *n = this; - vp=NULL; + if (custom_viewport && ObjectDB::get_instance(custom_viewport_id)) { - while(n) { + vp=custom_viewport; + } else { + vp=Node::get_viewport(); - if (n->cast_to<Viewport>()) { - - vp = n->cast_to<Viewport>(); - break; - } - n=n->get_parent(); } - - ERR_FAIL_COND(!vp); viewport=vp->get_viewport(); @@ -205,6 +198,7 @@ Size2 CanvasLayer::get_viewport_size() const { if (!is_inside_tree()) return Size2(1,1); + Rect2 r = vp->get_visible_rect(); return r.size; } @@ -215,6 +209,43 @@ RID CanvasLayer::get_viewport() const { return viewport; } +void CanvasLayer::set_custom_viewport(Node *p_viewport) { + ERR_FAIL_NULL(p_viewport); + if (is_inside_tree()) { + VisualServer::get_singleton()->viewport_remove_canvas(viewport,canvas->get_canvas()); + viewport=RID(); + } + + custom_viewport=p_viewport->cast_to<Viewport>(); + + if (custom_viewport) { + custom_viewport_id=custom_viewport->get_instance_ID(); + } else { + custom_viewport_id=0; + } + + if (is_inside_tree()) { + + + if (custom_viewport) + vp=custom_viewport; + else + vp=Node::get_viewport(); + + viewport = vp->get_viewport(); + + VisualServer::get_singleton()->viewport_attach_canvas(viewport,canvas->get_canvas()); + VisualServer::get_singleton()->viewport_set_canvas_layer(viewport,canvas->get_canvas(),layer); + VisualServer::get_singleton()->viewport_set_canvas_transform(viewport,canvas->get_canvas(),transform); + } + +} + +Node* CanvasLayer::get_custom_viewport() const { + + return custom_viewport; +} + void CanvasLayer::_bind_methods() { @@ -241,8 +272,11 @@ void CanvasLayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_scale","scale"),&CanvasLayer::set_scale); ObjectTypeDB::bind_method(_MD("get_scale"),&CanvasLayer::get_scale); + ObjectTypeDB::bind_method(_MD("set_custom_viewport","viewport:Viewport"),&CanvasLayer::set_custom_viewport); + ObjectTypeDB::bind_method(_MD("get_custom_viewport:Viewport"),&CanvasLayer::get_custom_viewport); + ObjectTypeDB::bind_method(_MD("get_world_2d:World2D"),&CanvasLayer::get_world_2d); - ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasLayer::get_viewport); +// ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasLayer::get_viewport); ADD_PROPERTY( PropertyInfo(Variant::INT,"layer",PROPERTY_HINT_RANGE,"-128,128,1"),_SCS("set_layer"),_SCS("get_layer") ); //ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"transform",PROPERTY_HINT_RANGE),_SCS("set_transform"),_SCS("get_transform") ); @@ -260,4 +294,6 @@ CanvasLayer::CanvasLayer() { locrotscale_dirty=false; layer=1; canvas = Ref<World2D>( memnew(World2D) ); + custom_viewport=NULL; + custom_viewport_id=0; } diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h index a3e8211a43..a1311390be 100644 --- a/scene/main/canvas_layer.h +++ b/scene/main/canvas_layer.h @@ -40,11 +40,15 @@ class CanvasLayer : public Node { bool locrotscale_dirty; Vector2 ofs; - Vector2 scale; + Size2 scale; real_t rot; int layer; Matrix32 transform; Ref<World2D> canvas; + + ObjectID custom_viewport_id; // to check validity + Viewport *custom_viewport; + RID viewport; Viewport *vp; @@ -55,6 +59,7 @@ class CanvasLayer : public Node { void _update_xform(); void _update_locrotscale(); + protected: void _notification(int p_what); @@ -76,8 +81,8 @@ public: void set_rotationd(real_t p_degrees); real_t get_rotationd() const; - void set_scale(const Vector2& p_scale); - Vector2 get_scale() const; + void set_scale(const Size2& p_scale); + Size2 get_scale() const; Ref<World2D> get_world_2d() const; @@ -85,6 +90,9 @@ public: RID get_viewport() const; + void set_custom_viewport(Node *p_viewport); + Node* get_custom_viewport() const; + CanvasLayer(); }; diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 9b79af32bf..c713b5e4dc 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -96,7 +96,7 @@ Error HTTPRequest::_parse_url(const String& p_url) { return OK; } -Error HTTPRequest::request(const String& p_url, const Vector<String>& p_custom_headers, bool p_ssl_validate_domain) { +Error HTTPRequest::request(const String& p_url, const Vector<String>& p_custom_headers, bool p_ssl_validate_domain, HTTPClient::Method p_method, const String& p_request_data) { ERR_FAIL_COND_V(!is_inside_tree(),ERR_UNCONFIGURED); if ( requesting ) { @@ -104,6 +104,8 @@ Error HTTPRequest::request(const String& p_url, const Vector<String>& p_custom_h ERR_FAIL_V(ERR_BUSY); } + method=p_method; + Error err = _parse_url(p_url); if (err) return err; @@ -114,6 +116,8 @@ Error HTTPRequest::request(const String& p_url, const Vector<String>& p_custom_h bool has_accept=false; headers=p_custom_headers; + request_data = p_request_data; + for(int i=0;i<headers.size();i++) { if (headers[i].findn("user-agent:")==0) @@ -281,7 +285,7 @@ bool HTTPRequest::_update_connection() { switch( client->get_status() ) { case HTTPClient::STATUS_DISCONNECTED: { call_deferred("_request_done",RESULT_CANT_CONNECT,0,StringArray(),ByteArray()); - return true; //end it, since it's doing something + return true; //end it, since it's doing something } break; case HTTPClient::STATUS_RESOLVING: { client->poll(); @@ -334,7 +338,7 @@ bool HTTPRequest::_update_connection() { } else { //did not request yet, do request - Error err = client->request(HTTPClient::METHOD_GET,request_string,headers); + Error err = client->request(method,request_string,headers,request_data); if (err!=OK) { call_deferred("_request_done",RESULT_CONNECTION_ERROR,0,StringArray(),ByteArray()); return true; @@ -531,7 +535,7 @@ int HTTPRequest::get_body_size() const{ void HTTPRequest::_bind_methods() { - ObjectTypeDB::bind_method(_MD("request","url","custom_headers","ssl_validate_domain"),&HTTPRequest::request,DEFVAL(StringArray()),DEFVAL(true)); + ObjectTypeDB::bind_method(_MD("request","url","custom_headers","ssl_validate_domain","method","request_data"),&HTTPRequest::request,DEFVAL(StringArray()),DEFVAL(true),DEFVAL(HTTPClient::METHOD_GET),DEFVAL(String())); ObjectTypeDB::bind_method(_MD("cancel_request"),&HTTPRequest::cancel_request); ObjectTypeDB::bind_method(_MD("get_http_client_status"),&HTTPRequest::get_http_client_status); diff --git a/scene/main/http_request.h b/scene/main/http_request.h index 8dd433982b..705799f044 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -66,6 +66,8 @@ private: Vector<String> headers; bool validate_ssl; bool use_ssl; + HTTPClient::Method method; + String request_data; bool request_sent; Ref<HTTPClient> client; @@ -114,7 +116,7 @@ protected: static void _bind_methods(); public: - Error request(const String& p_url,const Vector<String>& p_custom_headers=Vector<String>(),bool p_ssl_validate_domain=true); //connects to a full url and perform request + Error request(const String& p_url, const Vector<String>& p_custom_headers=Vector<String>(), bool p_ssl_validate_domain=true, HTTPClient::Method p_method=HTTPClient::METHOD_GET, const String& p_request_data=""); //connects to a full url and perform request void cancel_request(); HTTPClient::Status get_http_client_status() const; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 086b69c1c5..6e33dcb4c9 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1249,51 +1249,12 @@ void Node::set_human_readable_collision_renaming(bool p_enabled) { } +#ifdef TOOLS_ENABLED +String Node::validate_child_name(Node* p_child) { -String Node::validate_child_name(const String& p_name) const { - - //this approach to autoset node names is human readable but very slow - //it's turned on while running in the editor - - String basename = p_name; - - if (basename==String()) { - - return String(); - } - - int val=1; - - for(;;) { - - String attempted = val > 1 ? (basename + " " +itos(val) ) : basename; - - bool found=false; - - for (int i=0;i<data.children.size();i++) { - - //if (data.children[i]==p_child) - // continue; - if (data.children[i]->get_name() == attempted) { - found=true; - break; - } - - } - - if (found) { - - val++; - continue; - } - - return attempted; - break; - } - - return basename; - + return _generate_serial_child_name(p_child); } +#endif void Node::_validate_child_name(Node *p_child, bool p_force_human_readable) { @@ -1304,41 +1265,8 @@ void Node::_validate_child_name(Node *p_child, bool p_force_human_readable) { //this approach to autoset node names is human readable but very slow //it's turned on while running in the editor - String basename = p_child->data.name; - - if (basename=="") { - - basename = p_child->get_type(); - } - - int val=1; - - for(;;) { - - String attempted = val > 1 ? (basename + " " +itos(val) ) : basename; - - bool found=false; - - for (int i=0;i<data.children.size();i++) { - - if (data.children[i]==p_child) - continue; - if (data.children[i]->get_name() == attempted) { - found=true; - break; - } - - } - - if (found) { - - val++; - continue; - } + p_child->data.name=_generate_serial_child_name(p_child); - p_child->data.name=attempted; - break; - } } else { //this approach to autoset node names is fast but not as readable @@ -1373,6 +1301,67 @@ void Node::_validate_child_name(Node *p_child, bool p_force_human_readable) { } } +String Node::_generate_serial_child_name(Node *p_child) { + + String name = p_child->data.name; + + if (name=="") { + + name = p_child->get_type(); + } + + // Extract trailing number + String nums; + for(int i=name.length()-1;i>=0;i--) { + CharType n=name[i]; + if (n>='0' && n<='9') { + nums=String::chr(name[i])+nums; + } else { + break; + } + } + + String nnsep=_get_name_num_separator(); + int num=0; + bool explicit_zero=false; + if (nums.length()>0 && name.substr(name.length()-nnsep.length()-nums.length(),nnsep.length()) == nnsep) { + // Base name + Separator + Number + num=nums.to_int(); + name=name.substr(0,name.length()-nnsep.length()-nums.length()); // Keep base name + if (num==0) { + explicit_zero=true; + } + } + + for(;;) { + String attempt = (name + (num > 0 || explicit_zero ? nnsep + itos(num) : "")).strip_edges(); + bool found=false; + for(int i=0;i<data.children.size();i++) { + if (data.children[i]==p_child) + continue; + if (data.children[i]->data.name==attempt) { + found=true; + break; + } + } + if (!found) { + return attempt; + } else { + if (num==0) { + if (explicit_zero) { + // Name ended in separator + 0; user expects to get to separator + 1 + num=1; + } else { + // Name was undecorated so skip to 2 for a more natural result + num=2; + } + } else { + num++; + } + } + } +} + void Node::_add_child_nocheck(Node* p_child,const StringName& p_name) { //add a child node quickly, without name validation @@ -2811,6 +2800,10 @@ bool Node::is_displayed_folded() const { void Node::_bind_methods() { + _GLOBAL_DEF("node/name_num_separator",0); + Globals::get_singleton()->set_custom_property_info("node/name_num_separator",PropertyInfo(Variant::INT,"node/name_num_separator",PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash")); + + ObjectTypeDB::bind_method(_MD("_add_child_below_node","node:Node","child_node:Node","legible_unique_name"),&Node::add_child_below_node,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("set_name","name"),&Node::set_name); @@ -2903,16 +2896,16 @@ void Node::_bind_methods() { mi.name="rpc"; - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"rpc",&Node::_rpc_bind,mi); + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"rpc",&Node::_rpc_bind,mi); mi.name="rpc_unreliable"; - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"rpc_unreliable",&Node::_rpc_unreliable_bind,mi); + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"rpc_unreliable",&Node::_rpc_unreliable_bind,mi); - mi.arguments.push_front( PropertyInfo( Variant::INT, "peer_") ); + mi.arguments.push_front( PropertyInfo( Variant::INT, "peer_id") ); mi.name="rpc_id"; - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"rpc_id",&Node::_rpc_id_bind,mi); + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"rpc_id",&Node::_rpc_id_bind,mi); mi.name="rpc_unreliable_id"; - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"rpc_unreliable_id",&Node::_rpc_unreliable_id_bind,mi); + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"rpc_unreliable_id",&Node::_rpc_unreliable_id_bind,mi); } @@ -2979,6 +2972,17 @@ void Node::_bind_methods() { } +String Node::_get_name_num_separator() { + switch(Globals::get_singleton()->get("node/name_num_separator").operator int()) { + case 0: return ""; + case 1: return " "; + case 2: return "_"; + case 3: return "-"; + } + return " "; +} + + Node::Node() { data.pos=-1; diff --git a/scene/main/node.h b/scene/main/node.h index 3568da2ab0..f18dc81195 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -29,6 +29,7 @@ #ifndef NODE_H #define NODE_H +#include "globals.h" #include "object.h" #include "path_db.h" #include "map.h" @@ -150,7 +151,8 @@ private: void _replace_connections_target(Node* p_new_target); - void _validate_child_name(Node *p_name, bool p_force_human_readable=false); + void _validate_child_name(Node *p_child, bool p_force_human_readable=false); + String _generate_serial_child_name(Node *p_child); void _propagate_reverse_notification(int p_notification); void _propagate_deferred_notification(int p_notification, bool p_reverse); @@ -193,6 +195,7 @@ protected: void _propagate_replace_owner(Node *p_owner,Node* p_by_owner); static void _bind_methods(); + static String _get_name_num_separator(); friend class SceneState; @@ -335,7 +338,9 @@ public: static void print_stray_nodes(); - String validate_child_name(const String& p_name) const; +#ifdef TOOLS_ENABLED + String validate_child_name(Node* p_child); +#endif void queue_delete(); diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp index 4c7b7c1399..e3472c074a 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_main_loop.cpp @@ -2200,13 +2200,9 @@ void SceneTree::_bind_methods() { mi.arguments.push_back( PropertyInfo( Variant::INT, "flags")); mi.arguments.push_back( PropertyInfo( Variant::STRING, "group")); mi.arguments.push_back( PropertyInfo( Variant::STRING, "method")); - Vector<Variant> defargs; - for(int i=0;i<VARIANT_ARG_MAX;i++) { - mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); - defargs.push_back(Variant()); - } - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_group",&SceneTree::_call_group,mi,defargs); + + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_group",&SceneTree::_call_group,mi); ObjectTypeDB::bind_method(_MD("set_current_scene","child_node:Node"),&SceneTree::set_current_scene); ObjectTypeDB::bind_method(_MD("get_current_scene:Node"),&SceneTree::get_current_scene); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 7970229c06..0c243bd473 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -359,13 +359,7 @@ void Viewport::_notification(int p_what) { _update_listener_2d(); _update_rect(); - if (world_2d.is_valid()) { - find_world_2d()->_register_viewport(this,Rect2()); -//best to defer this and not do it here, as it can annoy a lot of setup logic if user -//adds a node and then moves it, will get enter/exit screen/viewport notifications -//unnecesarily -// update_worlds(); - } + find_world_2d()->_register_viewport(this,Rect2()); add_to_group("_viewports"); if (get_tree()->is_debugging_collisions_hint()) { @@ -1001,19 +995,34 @@ bool Viewport::has_transparent_background() const { return transparent_bg; } -#if 0 void Viewport::set_world_2d(const Ref<World2D>& p_world_2d) { + if (world_2d==p_world_2d) + return; + + if (parent && parent->find_world_2d()==p_world_2d) { + WARN_PRINT("Unable to use parent world as world_2d"); + return; + } + + if (is_inside_tree()) { + find_world_2d()->_remove_viewport(this); + VisualServer::get_singleton()->viewport_remove_canvas(viewport,current_canvas); + } + + if (p_world_2d.is_valid()) + world_2d=p_world_2d; + else { + WARN_PRINT("Invalid world"); + world_2d=Ref<World2D>( memnew( World2D )); + } - world_2d=p_world_2d; _update_listener_2d(); - if (is_inside_scene()) { - if (current_canvas.is_valid()) - VisualServer::get_singleton()->viewport_remove_canvas(viewport,current_canvas); + if (is_inside_tree()) { current_canvas=find_world_2d()->get_canvas(); VisualServer::get_singleton()->viewport_attach_canvas(viewport,current_canvas); + find_world_2d()->_register_viewport(this,Rect2()); } - } Ref<World2D> Viewport::find_world_2d() const{ @@ -1025,13 +1034,6 @@ Ref<World2D> Viewport::find_world_2d() const{ else return Ref<World2D>(); } -#endif - -Ref<World2D> Viewport::find_world_2d() const{ - - return world_2d; -} - void Viewport::_propagate_enter_world(Node *p_node) { @@ -1141,6 +1143,11 @@ Ref<World> Viewport::get_world() const{ return world; } +Ref<World2D> Viewport::get_world_2d() const{ + + return world_2d; +} + Ref<World> Viewport::find_world() const{ if (own_world.is_valid()) @@ -1303,6 +1310,9 @@ void Viewport::render_target_clear() { void Viewport::set_render_target_filter(bool p_enable) { + if(!render_target) + return; + render_target_texture->set_flags(p_enable?int(Texture::FLAG_FILTER):int(0)); } @@ -1344,6 +1354,15 @@ Matrix32 Viewport::_get_input_pre_xform() const { return pre_xf; } +Vector2 Viewport::_get_window_offset() const { + + if (parent_control) { + return (parent_control->get_viewport()->get_final_transform() * parent_control->get_global_transform_with_canvas()).get_origin(); + } + + return Vector2(); +} + void Viewport::_make_input_local(InputEvent& ev) { @@ -1351,10 +1370,7 @@ void Viewport::_make_input_local(InputEvent& ev) { case InputEvent::MOUSE_BUTTON: { - Vector2 vp_ofs; - if (parent_control) { - vp_ofs = (parent_control->get_viewport()->get_final_transform() * parent_control->get_global_transform_with_canvas()).get_origin(); - } + Vector2 vp_ofs = _get_window_offset(); Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); Vector2 g = ai.xform(Vector2(ev.mouse_button.global_x,ev.mouse_button.global_y)); @@ -1369,10 +1385,7 @@ void Viewport::_make_input_local(InputEvent& ev) { } break; case InputEvent::MOUSE_MOTION: { - Vector2 vp_ofs; - if (parent_control) { - vp_ofs = (parent_control->get_viewport()->get_final_transform() * parent_control->get_global_transform_with_canvas()).get_origin(); - } + Vector2 vp_ofs = _get_window_offset(); Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); Vector2 g = ai.xform(Vector2(ev.mouse_motion.global_x,ev.mouse_motion.global_y)); @@ -1393,10 +1406,7 @@ void Viewport::_make_input_local(InputEvent& ev) { } break; case InputEvent::SCREEN_TOUCH: { - Vector2 vp_ofs; - if (parent_control) { - vp_ofs = (parent_control->get_viewport()->get_final_transform() * parent_control->get_global_transform_with_canvas()).get_origin(); - } + Vector2 vp_ofs = _get_window_offset(); Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); Vector2 t = ai.xform(Vector2(ev.screen_touch.x,ev.screen_touch.y)-vp_ofs); @@ -1408,10 +1418,7 @@ void Viewport::_make_input_local(InputEvent& ev) { } break; case InputEvent::SCREEN_DRAG: { - Vector2 vp_ofs; - if (parent_control) { - vp_ofs = (parent_control->get_viewport()->get_final_transform() * parent_control->get_global_transform_with_canvas()).get_origin(); - } + Vector2 vp_ofs = _get_window_offset(); Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); Vector2 t = ai.xform(Vector2(ev.screen_drag.x,ev.screen_drag.y)-vp_ofs); @@ -1490,7 +1497,7 @@ void Viewport::_vp_unhandled_input(const InputEvent& p_ev) { Vector2 Viewport::get_mouse_pos() const { - return (get_final_transform().affine_inverse() * _get_input_pre_xform()).xform(Input::get_singleton()->get_mouse_pos()); + return (get_final_transform().affine_inverse() * _get_input_pre_xform()).xform(Input::get_singleton()->get_mouse_pos() - _get_window_offset()); } void Viewport::warp_mouse(const Vector2& p_pos) { @@ -1708,6 +1715,9 @@ Control* Viewport::_gui_find_control_at_pos(CanvasItem* p_node,const Point2& p_g } Matrix32 matrix = p_xform * p_node->get_transform(); + // matrix.basis_determinant() == 0.0f implies that node does not exist on scene + if(matrix.basis_determinant() == 0.0f) + return NULL; if (!c || !c->clips_input() || c->has_point(matrix.affine_inverse().xform(p_global))) { @@ -2590,8 +2600,8 @@ void Viewport::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_rect","rect"), &Viewport::set_rect); ObjectTypeDB::bind_method(_MD("get_rect"), &Viewport::get_rect); - //ObjectTypeDB::bind_method(_MD("set_world_2d","world_2d:World2D"), &Viewport::set_world_2d); - //ObjectTypeDB::bind_method(_MD("get_world_2d:World2D"), &Viewport::get_world_2d); + ObjectTypeDB::bind_method(_MD("set_world_2d","world_2d:World2D"), &Viewport::set_world_2d); + ObjectTypeDB::bind_method(_MD("get_world_2d:World2D"), &Viewport::get_world_2d); ObjectTypeDB::bind_method(_MD("find_world_2d:World2D"), &Viewport::find_world_2d); ObjectTypeDB::bind_method(_MD("set_world","world:World"), &Viewport::set_world); ObjectTypeDB::bind_method(_MD("get_world:World"), &Viewport::get_world); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 22a97a9888..f657f0507d 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -268,6 +268,8 @@ friend class Control; Control *_gui_get_focus_owner(); + Vector2 _get_window_offset() const; + friend class Listener; void _listener_transform_changed_notify(); void _listener_set(Listener* p_listener); @@ -303,9 +305,11 @@ public: RID get_viewport() const; void set_world(const Ref<World>& p_world); + void set_world_2d(const Ref<World2D>& p_world_2d); Ref<World> get_world() const; Ref<World> find_world() const; + Ref<World2D> get_world_2d() const; Ref<World2D> find_world_2d() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index be2c12d63a..104aeb2b5e 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -55,6 +55,7 @@ #include "scene/gui/option_button.h" #include "scene/gui/color_picker.h" #include "scene/gui/texture_frame.h" +#include "scene/gui/color_rect.h" #include "scene/gui/patch_9_frame.h" #include "scene/gui/menu_button.h" #include "scene/gui/check_box.h" @@ -182,6 +183,7 @@ #include "scene/3d/spatial.h" +#include "scene/3d/remote_transform.h" #include "scene/3d/skeleton.h" #include "scene/3d/bone_attachment.h" #include "scene/3d/room_instance.h" @@ -338,6 +340,7 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init ObjectTypeDB::register_type<TextureFrame>(); + ObjectTypeDB::register_type<ColorFrame>(); ObjectTypeDB::register_type<Patch9Frame>(); ObjectTypeDB::register_type<TabContainer>(); ObjectTypeDB::register_type<Tabs>(); @@ -453,6 +456,7 @@ void register_scene_types() { ObjectTypeDB::register_type<BakedLightInstance>(); ObjectTypeDB::register_type<BakedLightSampler>(); ObjectTypeDB::register_type<WorldEnvironment>(); + ObjectTypeDB::register_type<RemoteTransform>(); ObjectTypeDB::register_virtual_type<Joint>(); ObjectTypeDB::register_type<PinJoint>(); diff --git a/scene/resources/SCsub b/scene/resources/SCsub index bb9766e1ca..702ed1a9bf 100644 --- a/scene/resources/SCsub +++ b/scene/resources/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.scene_sources,"*.cpp") diff --git a/scene/resources/default_theme/SCsub b/scene/resources/default_theme/SCsub index bbe59b3054..9fa89edbf7 100644 --- a/scene/resources/default_theme/SCsub +++ b/scene/resources/default_theme/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.scene_sources,"*.cpp") diff --git a/scene/resources/default_theme/button_pressed.png b/scene/resources/default_theme/button_pressed.png Binary files differindex 4a807544ed..19a7e237aa 100644 --- a/scene/resources/default_theme/button_pressed.png +++ b/scene/resources/default_theme/button_pressed.png diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 03f28bef08..0740b591c4 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -40,7 +40,7 @@ typedef Map<const void*,Ref<ImageTexture> > TexCacheMap; static TexCacheMap *tex_cache; -static int scale=1; +static float scale=1; template<class T> static Ref<StyleBoxTexture> make_stylebox(T p_src,float p_left, float p_top, float p_right, float p_botton,float p_margin_left=-1, float p_margin_top=-1, float p_margin_right=-1, float p_margin_botton=-1, bool p_draw_center=true) { @@ -54,10 +54,21 @@ static Ref<StyleBoxTexture> make_stylebox(T p_src,float p_left, float p_top, flo texture = Ref<ImageTexture>( memnew( ImageTexture ) ); Image img(p_src); + if (scale>1) { + Size2 orig_size = Size2(img.get_width(),img.get_height()); + img.convert(Image::FORMAT_RGBA); img.expand_x2_hq2x(); + if (scale!=2.0) { + img.resize(orig_size.x*scale,orig_size.y*scale); + } + } else if (scale<1) { + Size2 orig_size = Size2(img.get_width(),img.get_height()); + img.convert(Image::FORMAT_RGBA); + img.resize(orig_size.x*scale,orig_size.y*scale); } + texture->create_from_image( img,ImageTexture::FLAG_FILTER ); (*tex_cache)[p_src]=texture; } @@ -95,8 +106,17 @@ static Ref<Texture> make_icon(T p_src) { Ref<ImageTexture> texture( memnew( ImageTexture ) ); Image img = Image(p_src); if (scale>1) { + Size2 orig_size = Size2(img.get_width(),img.get_height()); + img.convert(Image::FORMAT_RGBA); img.expand_x2_hq2x(); + if (scale!=2.0) { + img.resize(orig_size.x*scale,orig_size.y*scale); + } + } else if (scale<1) { + Size2 orig_size = Size2(img.get_width(),img.get_height()); + img.convert(Image::FORMAT_RGBA); + img.resize(orig_size.x*scale,orig_size.y*scale); } texture->create_from_image( img,ImageTexture::FLAG_FILTER ); @@ -194,12 +214,9 @@ static Ref<StyleBox> make_empty_stylebox(float p_margin_left=-1, float p_margin_ return style; } -void fill_default_theme(Ref<Theme>& t,const Ref<Font> & default_font,const Ref<Font> & large_font,Ref<Texture>& default_icon, Ref<StyleBox>& default_style,bool p_hidpi) { +void fill_default_theme(Ref<Theme>& t, const Ref<Font> & default_font, const Ref<Font> & large_font, Ref<Texture>& default_icon, Ref<StyleBox>& default_style, float p_scale) { - if (p_hidpi) - scale=2; - else - scale=1; + scale=p_scale; tex_cache = memnew( TexCacheMap ); @@ -697,6 +714,8 @@ void fill_default_theme(Ref<Theme>& t,const Ref<Font> & default_font,const Ref<F t->set_constant("item_margin","Tree",12 *scale); t->set_constant("button_margin","Tree",4 *scale); t->set_constant("draw_relationship_lines", "Tree", 0); + t->set_constant("scroll_border", "Tree", 4); + t->set_constant("scroll_speed", "Tree", 12); // ItemList @@ -969,7 +988,7 @@ void make_default_theme(bool p_hidpi,Ref<Font> p_font) { default_font=make_font2(_lodpi_font_height,_lodpi_font_ascent,_lodpi_font_charcount,&_lodpi_font_charrects[0][0],_lodpi_font_kerning_pair_count,&_lodpi_font_kerning_pairs[0][0],_lodpi_font_img_width,_lodpi_font_img_height,_lodpi_font_img_data); } Ref<BitmapFont> large_font=default_font; - fill_default_theme(t,default_font,large_font,default_icon,default_style,p_hidpi); + fill_default_theme(t,default_font,large_font,default_icon,default_style,p_hidpi?2.0:1.0); Theme::set_default( t ); Theme::set_default_icon( default_icon ); diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h index a2a45ac004..3312b2d812 100644 --- a/scene/resources/default_theme/default_theme.h +++ b/scene/resources/default_theme/default_theme.h @@ -35,7 +35,7 @@ @author Juan Linietsky <reduzio@gmail.com> */ -void fill_default_theme(Ref<Theme>& theme,const Ref<Font> & default_font,const Ref<Font> & large_font,Ref<Texture>& default_icon, Ref<StyleBox>& default_style,bool p_hidpi); +void fill_default_theme(Ref<Theme>& theme,const Ref<Font> & default_font,const Ref<Font> & large_font,Ref<Texture>& default_icon, Ref<StyleBox>& default_style,float p_scale); void make_default_theme(bool p_hidpi, Ref<Font> p_font); void clear_default_theme(); diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp index 40ae26ba5d..02faa9425d 100644 --- a/scene/resources/shader_graph.cpp +++ b/scene/resources/shader_graph.cpp @@ -1483,6 +1483,8 @@ const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightColor","LIGHT_COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN}, {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightAlpha","LIGHT_COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN}, {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightHeight","LIGHT_HEIGHT","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"ShadowColor","LIGHT_SHADOW.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"ShadowAlpha","LIGHT_SHADOW.a","",SLOT_TYPE_SCALAR,SLOT_IN}, {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"TexPixelSize","vec3(TEXTURE_PIXEL_SIZE,0)","",SLOT_TYPE_VEC,SLOT_IN}, {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_IN}, {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_IN}, @@ -1490,6 +1492,8 @@ const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={ //canvas item light out {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightColor","LIGHT.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightAlpha","LIGHT.a","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"ShadowColor","SHADOW.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"ShadowAlpha","SHADOW.a","",SLOT_TYPE_SCALAR,SLOT_OUT}, //end {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,NULL,NULL,NULL,SLOT_TYPE_SCALAR,SLOT_OUT}, diff --git a/scene/resources/world.cpp b/scene/resources/world.cpp index 0a88abf252..1aeea5fa43 100644 --- a/scene/resources/world.cpp +++ b/scene/resources/world.cpp @@ -332,6 +332,10 @@ World::World() { sound_space = SpatialSoundServer::get_singleton()->space_create(); PhysicsServer::get_singleton()->space_set_active(space,true); + PhysicsServer::get_singleton()->area_set_param(space,PhysicsServer::AREA_PARAM_GRAVITY,GLOBAL_DEF("physics/default_gravity",9.8)); + PhysicsServer::get_singleton()->area_set_param(space,PhysicsServer::AREA_PARAM_GRAVITY_VECTOR,GLOBAL_DEF("physics/default_gravity_vector",Vector3(0,-1,0))); + PhysicsServer::get_singleton()->area_set_param(space,PhysicsServer::AREA_PARAM_LINEAR_DAMP,GLOBAL_DEF("physics/default_linear_damp",0.1)); + PhysicsServer::get_singleton()->area_set_param(space,PhysicsServer::AREA_PARAM_ANGULAR_DAMP,GLOBAL_DEF("physics/default_angular_damp",0.1)); #ifdef _3D_DISABLED indexer = NULL; diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index 4c963da5b4..df3a374fc9 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -416,12 +416,6 @@ World2D::World2D() { } Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_LINEAR_DAMP,GLOBAL_DEF("physics_2d/default_linear_damp",0.1)); Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_ANGULAR_DAMP,GLOBAL_DEF("physics_2d/default_angular_damp",1)); - Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_CONTACT_RECYCLE_RADIUS,1.0); - Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_CONTACT_MAX_SEPARATION,1.5); - Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION,0.3); - Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_TRESHOLD,2); - Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS,0.2); - indexer = memnew( SpatialIndexer2D ); } diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h index a939d935c4..d52189bcd4 100644 --- a/scene/resources/world_2d.h +++ b/scene/resources/world_2d.h @@ -31,6 +31,7 @@ #include "resource.h" #include "servers/physics_2d_server.h" +#include "globals.h" class SpatialIndexer2D; class VisibilityNotifier2D; diff --git a/servers/SCsub b/servers/SCsub index d861847101..57b5b36758 100644 --- a/servers/SCsub +++ b/servers/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.servers_sources=[] diff --git a/servers/audio/SCsub b/servers/audio/SCsub index d31af2c1c4..4684bd6cf3 100644 --- a/servers/audio/SCsub +++ b/servers/audio/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.servers_sources,"*.cpp") diff --git a/servers/physics/SCsub b/servers/physics/SCsub index 95296eadbe..b527f38ceb 100644 --- a/servers/physics/SCsub +++ b/servers/physics/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.servers_sources,"*.cpp") diff --git a/servers/physics/joints/SCsub b/servers/physics/joints/SCsub index d31af2c1c4..4684bd6cf3 100644 --- a/servers/physics/joints/SCsub +++ b/servers/physics/joints/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.servers_sources,"*.cpp") diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp index 7077146420..9755c49e2d 100644 --- a/servers/physics/space_sw.cpp +++ b/servers/physics/space_sw.cpp @@ -721,7 +721,7 @@ SpaceSW::SpaceSW() { constraint_bias = 0.01; body_linear_velocity_sleep_threshold=GLOBAL_DEF("physics/sleep_threshold_linear",0.1); body_angular_velocity_sleep_threshold=GLOBAL_DEF("physics/sleep_threshold_angular", (8.0 / 180.0 * Math_PI) ); - body_time_to_sleep=0.5; + body_time_to_sleep=GLOBAL_DEF("physics/time_before_sleep",0.5); body_angular_velocity_damp_ratio=10; diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h index 3fdef7e62b..29eca2690a 100644 --- a/servers/physics/space_sw.h +++ b/servers/physics/space_sw.h @@ -37,6 +37,7 @@ #include "area_pair_sw.h" #include "broad_phase_sw.h" #include "collision_object_sw.h" +#include "globals.h" class PhysicsDirectSpaceStateSW : public PhysicsDirectSpaceState { diff --git a/servers/physics_2d/SCsub b/servers/physics_2d/SCsub index ebb7f8be00..2114782faa 100644 --- a/servers/physics_2d/SCsub +++ b/servers/physics_2d/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.servers_sources,"*.cpp") diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp index 9291aa6c17..77245c687d 100644 --- a/servers/physics_2d/shape_2d_sw.cpp +++ b/servers/physics_2d/shape_2d_sw.cpp @@ -136,7 +136,7 @@ bool LineShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_en return true; } -real_t LineShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { +real_t LineShape2DSW::get_moment_of_inertia(float p_mass, const Size2 &p_scale) const { return 0; } @@ -191,7 +191,7 @@ bool RayShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end } -real_t RayShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { +real_t RayShape2DSW::get_moment_of_inertia(float p_mass, const Size2 &p_scale) const { return 0; //rays are mass-less } @@ -252,7 +252,7 @@ bool SegmentShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p return true; } -real_t SegmentShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { +real_t SegmentShape2DSW::get_moment_of_inertia(float p_mass, const Size2 &p_scale) const { Vector2 s[2]={a*p_scale,b*p_scale}; @@ -336,7 +336,7 @@ bool CircleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_ return true; } -real_t CircleShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { +real_t CircleShape2DSW::get_moment_of_inertia(float p_mass, const Size2 &p_scale) const { return (radius*radius)*(p_scale.x*0.5+p_scale.y*0.5); @@ -407,7 +407,7 @@ bool RectangleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& return get_aabb().intersects_segment(p_begin,p_end,&r_point,&r_normal); } -real_t RectangleShape2DSW::get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { +real_t RectangleShape2DSW::get_moment_of_inertia(float p_mass,const Size2& p_scale) const { Vector2 he2=half_extents*2*p_scale; return p_mass*he2.dot(he2)/12.0f; @@ -540,7 +540,7 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p return collided; //todo } -real_t CapsuleShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { +real_t CapsuleShape2DSW::get_moment_of_inertia(float p_mass, const Size2 &p_scale) const { Vector2 he2=Vector2(radius*2,height+radius*2)*p_scale; return p_mass*he2.dot(he2)/12.0f; @@ -670,7 +670,7 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vect return inters; //todo } -real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { +real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass,const Size2& p_scale) const { Rect2 aabb; aabb.pos=points[0].pos*p_scale; diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h index 4164896696..b90c36bc04 100644 --- a/servers/physics_2d/shape_2d_sw.h +++ b/servers/physics_2d/shape_2d_sw.h @@ -86,7 +86,7 @@ public: virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const=0; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const=0; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const=0; + virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const=0; virtual void set_data(const Variant& p_data)=0; virtual Variant get_data() const=0; @@ -175,7 +175,7 @@ public: virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; + virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -218,7 +218,7 @@ public: virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; + virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -266,7 +266,7 @@ public: virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; + virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -304,7 +304,7 @@ public: virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; + virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -344,7 +344,7 @@ public: virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; + virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -432,7 +432,7 @@ public: virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; + virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -495,7 +495,7 @@ public: virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; + virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -584,7 +584,7 @@ public: virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { return 0; } + virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const { return 0; } virtual void set_data(const Variant& p_data); virtual Variant get_data() const; diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index d0dcee7763..56bee8b0c5 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -81,6 +81,9 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2& p_point,ShapeRes if (!shape->contains_point(local_point)) continue; + if (cc>=p_result_max) + continue; + r_results[cc].collider_id=col_obj->get_instance_id(); if (r_results[cc].collider_id!=0) r_results[cc].collider=ObjectDB::get_instance(r_results[cc].collider_id); @@ -1321,14 +1324,14 @@ Space2DSW::Space2DSW() { contact_debug_count=0; locked=false; - contact_recycle_radius=0.01; - contact_max_separation=0.05; - contact_max_allowed_penetration= 0.01; - - constraint_bias = 0.01; - body_linear_velocity_sleep_treshold=0.01; - body_angular_velocity_sleep_treshold=(8.0 / 180.0 * Math_PI); - body_time_to_sleep=0.5; + contact_recycle_radius=1.0; + contact_max_separation=1.5; + contact_max_allowed_penetration= 0.3; + + constraint_bias = 0.2; + body_linear_velocity_sleep_treshold=GLOBAL_DEF("physics_2d/sleep_threashold_linear",2.0); + body_angular_velocity_sleep_treshold=GLOBAL_DEF("physics_2d/sleep_threshold_angular",(8.0 / 180.0 * Math_PI)); + body_time_to_sleep=GLOBAL_DEF("physics_2d/time_before_sleep",0.5); broadphase = BroadPhase2DSW::create_func(); diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index f58e8c3fe7..45a3e4ca8f 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -37,6 +37,7 @@ #include "area_pair_2d_sw.h" #include "broad_phase_2d_sw.h" #include "collision_object_2d_sw.h" +#include "globals.h" class Physics2DDirectSpaceStateSW : public Physics2DDirectSpaceState { diff --git a/servers/spatial_sound/SCsub b/servers/spatial_sound/SCsub index d31af2c1c4..4684bd6cf3 100644 --- a/servers/spatial_sound/SCsub +++ b/servers/spatial_sound/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.servers_sources,"*.cpp") diff --git a/servers/spatial_sound_2d/SCsub b/servers/spatial_sound_2d/SCsub index d31af2c1c4..4684bd6cf3 100644 --- a/servers/spatial_sound_2d/SCsub +++ b/servers/spatial_sound_2d/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.servers_sources,"*.cpp") diff --git a/servers/visual/SCsub b/servers/visual/SCsub index d31af2c1c4..4684bd6cf3 100644 --- a/servers/visual/SCsub +++ b/servers/visual/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.servers_sources,"*.cpp") diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp index 32f5b80e55..a4b91e17fe 100644 --- a/servers/visual/rasterizer.cpp +++ b/servers/visual/rasterizer.cpp @@ -290,9 +290,6 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { //print_line("**VERTEX SHADER GENERATED code: \n"+vcode); - double tf = (OS::get_singleton()->get_ticks_usec()-t)/1000.0; -// print_line("generate: "+rtos(tf)); - shader_set_code(fms.shader,vcode,code,lcode,0,0); fixed_material_shaders[p_key]=fms; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 09b3ada509..fdf3cb622d 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -1180,6 +1180,7 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_light_builtins_defs[]={ { "LIGHT_HEIGHT", TYPE_FLOAT}, { "LIGHT_COLOR", TYPE_VEC4}, { "LIGHT_UV", TYPE_VEC2}, + { "LIGHT_SHADOW", TYPE_VEC4}, { "LIGHT", TYPE_VEC4}, { "SHADOW", TYPE_VEC4}, { "POINT_COORD", TYPE_VEC2}, diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index f7614ac080..1df0aafb23 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -7534,10 +7534,10 @@ void VisualServerRaster::_draw_cursors_and_margins() { ERR_CONTINUE( !tex ); if (cursors[i].region.has_no_area()) { Point2 size(texture_get_width(tex), texture_get_height(tex)); - rasterizer->canvas_draw_rect(Rect2(cursors[i].pos, size), 0, Rect2(), tex, Color(1, 1, 1, 1)); + rasterizer->canvas_draw_rect(Rect2(cursors[i].pos-cursors[i].center, size), 0, Rect2(), tex, Color(1, 1, 1, 1)); } else { Point2 size = cursors[i].region.size; - rasterizer->canvas_draw_rect(Rect2(cursors[i].pos, size), Rasterizer::CANVAS_RECT_REGION, cursors[i].region, tex, Color(1, 1, 1, 1)); + rasterizer->canvas_draw_rect(Rect2(cursors[i].pos-cursors[i].center, size), Rasterizer::CANVAS_RECT_REGION, cursors[i].region, tex, Color(1, 1, 1, 1)); } }; @@ -7612,6 +7612,11 @@ void VisualServerRaster::set_default_clear_color(const Color& p_color) { clear_color=p_color; } +Color VisualServerRaster::get_default_clear_color() const { + + return clear_color; +} + void VisualServerRaster::set_boot_image(const Image& p_image, const Color& p_color,bool p_scale) { if (p_image.empty()) diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 496820f4a8..1f22e31ab0 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -1283,6 +1283,7 @@ public: virtual void set_boot_image(const Image& p_image, const Color& p_color, bool p_scale); virtual void set_default_clear_color(const Color& p_color); + virtual Color get_default_clear_color() const; VisualServerRaster(Rasterizer *p_rasterizer); ~VisualServerRaster(); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index b4e374dd6f..f0fe80d100 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -718,6 +718,7 @@ public: FUNC3(set_boot_image,const Image& , const Color&,bool ); FUNC1(set_default_clear_color,const Color& ); + FUNC0RC(Color,get_default_clear_color ); FUNC0R(RID,get_test_cube ); diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index f69580254c..6099a86b96 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -382,7 +382,7 @@ void VisualServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("mesh_create"),&VisualServer::mesh_create); - ObjectTypeDB::bind_method(_MD("mesh_add_surface"),&VisualServer::mesh_add_surface, DEFVAL(NO_INDEX_ARRAY)); + ObjectTypeDB::bind_method(_MD("mesh_add_surface"),&VisualServer::mesh_add_surface, DEFVAL(Array()), DEFVAL(false)); ObjectTypeDB::bind_method(_MD("mesh_surface_set_material"),&VisualServer::mesh_surface_set_material,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("mesh_surface_get_material"),&VisualServer::mesh_surface_get_material); @@ -531,6 +531,7 @@ void VisualServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("canvas_item_set_self_opacity"),&VisualServer::canvas_item_set_self_opacity); ObjectTypeDB::bind_method(_MD("canvas_item_get_self_opacity"),&VisualServer::canvas_item_get_self_opacity); ObjectTypeDB::bind_method(_MD("canvas_item_set_z"),&VisualServer::canvas_item_set_z); + ObjectTypeDB::bind_method(_MD("canvas_item_set_sort_children_by_y"),&VisualServer::canvas_item_set_sort_children_by_y); ObjectTypeDB::bind_method(_MD("canvas_item_add_line"),&VisualServer::canvas_item_add_line, DEFVAL(1.0), DEFVAL(false)); ObjectTypeDB::bind_method(_MD("canvas_item_add_rect"),&VisualServer::canvas_item_add_rect); @@ -563,6 +564,7 @@ void VisualServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("free_rid"),&VisualServer::free); ObjectTypeDB::bind_method(_MD("set_default_clear_color"),&VisualServer::set_default_clear_color); + ObjectTypeDB::bind_method(_MD("get_default_clear_color"),&VisualServer::get_default_clear_color); ObjectTypeDB::bind_method(_MD("get_render_info"),&VisualServer::get_render_info); diff --git a/servers/visual_server.h b/servers/visual_server.h index 2f3d8371f6..844da2d245 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -1181,6 +1181,7 @@ public: virtual void set_boot_image(const Image& p_image, const Color& p_color,bool p_scale)=0; virtual void set_default_clear_color(const Color& p_color)=0; + virtual Color get_default_clear_color() const=0; enum Features { FEATURE_SHADERS, diff --git a/thirdparty/README.md b/thirdparty/README.md new file mode 100644 index 0000000000..f073bef8ec --- /dev/null +++ b/thirdparty/README.md @@ -0,0 +1,218 @@ +# Third party libraries + + +## enet + +- Upstream: http://enet.bespin.org +- Version: 1.3.13 +- License: MIT + +Files extracted from upstream source: + +- all .c files in the main directory +- the include/enet/ folder as enet/ +- LICENSE file + +Important: Some files have been modified by Godot developers so that they work +for all platforms (especially WinRT). Check the diff with the 1.3.13 tarball +before the next update. + + +## freetype + +- Upstream: https://www.freetype.org +- Version: 2.6.5 +- License: FreeType License (BSD-like) + +Files extracted from upstream source: + +- the src/ folder, stripped of the `Jamfile` files +- the include/ folder +- `docs/{FTL.TXT,LICENSE.TXT}` + + +## glew + +- Upstream: http://glew.sourceforge.net +- Version: 1.13.0 +- License: BSD-3-Clause + +Files extracted from upstream source: + +- `src/glew.c` +- include/GL/ as GL/ +- LICENSE.txt + + +## jpeg-compressor + +- Upstream: https://github.com/richgel999/jpeg-compressor +- Version: 1.04 +- License: Public domain + +Files extracted from upstream source: + +- `jpgd.{c,h}` + + +## libmpcdec + +- Upstream: https://www.musepack.net +- Version: SVN somewhere between SV7 and SV8 (r475) +- License: BSD-3-Clause + +Files extracted from upstream source: + +- all .c and .h files in libmpcdec/ +- include/mpc as mpc/ +- COPYING from libmpcdec/ + + +## libogg + +- Upstream: https://www.xiph.org/ogg +- Version: 1.3.2 +- License: BSD-3-Clause + +Files extracted from upstream source: + +- `src/*.c` +- `include/ogg/*.h` in ogg/ +- COPYING + + +## libpng + +- Upstream: http://libpng.org/pub/png/libpng.html +- Version: 1.6.23 +- License: libpng/zlib + +Files extracted from upstream source: + +- all .c and .h files of the main directory, except from + `example.c` and `pngtest.c` +- the arm/ folder +- `scripts/pnglibconf.h.prebuilt` as `pnglibconf.h` + + +## libvorbis + +- Upstream: https://www.xiph.org/vorbis +- Version: 1.3.5 +- License: BSD-3-Clause + +Files extracted from upstream source: + +- `src/*` except from: `lookups.pl`, `Makefile.*` +- `include/vorbis/*.h` as vorbis/ +- COPYING + + +## libwebp + +- Upstream: https://chromium.googlesource.com/webm/libwebp/ +- Version: 0.5.1 +- License: BSD-3-Clause + +Files extracted from upstream source: + +- `src/*` except from: .am and .in, files, extras/, `webp/extras.h` +- AUTHORS, COPYING, PATENTS + +Important: The files `utils/bit_reader.{c,h}` have Godot-made +changes to ensure they build for Javascript/HTML5. Those +changes are marked with `// -- GODOT --` comments. + + +## openssl + +- Upstream: https://www.openssl.org +- Version: 1.2.0h +- License: OpenSSL license / BSD-like + +Files extracted from the upstream source: + +TODO. + + +## opus + +- Upstream: https://opus-codec.org +- Version: 1.1.2 (opus) and 0.7 (opusfile) +- License: BSD-3-Clause + +Files extracted from upstream source: + +- all .c and .h files in src/ (both opus and opusfile), + except `opus_demo.c` +- all .h files in include/ (both opus and opusfile) +- COPYING + + +## pvrtccompressor + +- Upstream: https://bitbucket.org/jthlim/pvrtccompressor +- Version: hg commit cf71777 - 2015-01-08 +- License: BSD-3-Clause + +Files extracted from upstream source: + +- all .cpp and .h files apart from `main.cpp` +- LICENSE.TXT + + +## rg-etc1 + +- Upstream: https://github.com/richgel999/rg-etc1 +- Version: 1.04 +- License: zlib + +Files extracted from upstream source: + +- `rg_etc1.{cpp,h}` + + +## rtaudio + +- Upstream: http://www.music.mcgill.ca/~gary/rtaudio/ +- Version: 4.1.2 +- License: MIT-like + +Files extracted from upstream source: + +- `RtAudio.{cpp,h}` + + +## squish + +- Upstream: https://sourceforge.net/projects/libsquish +- Version: 1.14 +- License: MIT + +Files extracted from upstream source: + +- all .cpp, .h and .inl files + + +## theora + +- Upstream: https://www.theora.org +- Version: 1.1.1 +- License: BSD-3-Clause + +Files extracted from upstream source: + +- all .c, .h in lib/ +- all .h files in include/theora/ as theora/ +- COPYING and LICENSE + + +## zlib + +- Upstream: http://www.zlib.net/ +- Version: 1.2.8 +- License: zlib + +Files extracted from upstream source: + +- all .c and .h files apart from `gz*` diff --git a/thirdparty/enet/LICENSE b/thirdparty/enet/LICENSE new file mode 100644 index 0000000000..39af84a8f6 --- /dev/null +++ b/thirdparty/enet/LICENSE @@ -0,0 +1,7 @@ +Copyright (c) 2002-2016 Lee Salzman + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/modules/enet/callbacks.c b/thirdparty/enet/callbacks.c index b3990af1fb..b3990af1fb 100644 --- a/modules/enet/callbacks.c +++ b/thirdparty/enet/callbacks.c diff --git a/modules/enet/compress.c b/thirdparty/enet/compress.c index 784489a787..784489a787 100644 --- a/modules/enet/compress.c +++ b/thirdparty/enet/compress.c diff --git a/modules/enet/enet/callbacks.h b/thirdparty/enet/enet/callbacks.h index 340a4a9896..340a4a9896 100644 --- a/modules/enet/enet/callbacks.h +++ b/thirdparty/enet/enet/callbacks.h diff --git a/modules/enet/enet/enet.h b/thirdparty/enet/enet/enet.h index 650b199ee5..650b199ee5 100644 --- a/modules/enet/enet/enet.h +++ b/thirdparty/enet/enet/enet.h diff --git a/modules/enet/enet/list.h b/thirdparty/enet/enet/list.h index d7b2600848..d7b2600848 100644 --- a/modules/enet/enet/list.h +++ b/thirdparty/enet/enet/list.h diff --git a/modules/enet/enet/protocol.h b/thirdparty/enet/enet/protocol.h index f8c73d8a66..f8c73d8a66 100644 --- a/modules/enet/enet/protocol.h +++ b/thirdparty/enet/enet/protocol.h diff --git a/modules/enet/enet/time.h b/thirdparty/enet/enet/time.h index c82a546035..c82a546035 100644 --- a/modules/enet/enet/time.h +++ b/thirdparty/enet/enet/time.h diff --git a/modules/enet/enet/types.h b/thirdparty/enet/enet/types.h index ab010a4b13..ab010a4b13 100644 --- a/modules/enet/enet/types.h +++ b/thirdparty/enet/enet/types.h diff --git a/modules/enet/enet/unix.h b/thirdparty/enet/enet/unix.h index a59e340606..a59e340606 100644 --- a/modules/enet/enet/unix.h +++ b/thirdparty/enet/enet/unix.h diff --git a/modules/enet/enet/utility.h b/thirdparty/enet/enet/utility.h index e48a476be3..e48a476be3 100644 --- a/modules/enet/enet/utility.h +++ b/thirdparty/enet/enet/utility.h diff --git a/modules/enet/enet/win32.h b/thirdparty/enet/enet/win32.h index e73ca9d052..e73ca9d052 100644 --- a/modules/enet/enet/win32.h +++ b/thirdparty/enet/enet/win32.h diff --git a/modules/enet/host.c b/thirdparty/enet/host.c index 3be6c0922c..3be6c0922c 100644 --- a/modules/enet/host.c +++ b/thirdparty/enet/host.c diff --git a/modules/enet/list.c b/thirdparty/enet/list.c index 1c1a8dfaaf..1c1a8dfaaf 100644 --- a/modules/enet/list.c +++ b/thirdparty/enet/list.c diff --git a/modules/enet/packet.c b/thirdparty/enet/packet.c index 5fa78b28ae..5fa78b28ae 100644 --- a/modules/enet/packet.c +++ b/thirdparty/enet/packet.c diff --git a/modules/enet/peer.c b/thirdparty/enet/peer.c index e2d0872bd3..e2d0872bd3 100644 --- a/modules/enet/peer.c +++ b/thirdparty/enet/peer.c diff --git a/modules/enet/protocol.c b/thirdparty/enet/protocol.c index 4a2a4ed185..4a2a4ed185 100644 --- a/modules/enet/protocol.c +++ b/thirdparty/enet/protocol.c diff --git a/modules/enet/unix.c b/thirdparty/enet/unix.c index 3138cc04b6..3138cc04b6 100644 --- a/modules/enet/unix.c +++ b/thirdparty/enet/unix.c diff --git a/thirdparty/enet/win32.c b/thirdparty/enet/win32.c new file mode 100644 index 0000000000..15edd7acbb --- /dev/null +++ b/thirdparty/enet/win32.c @@ -0,0 +1,435 @@ +/** + @file win32.c + @brief ENet Win32 system specific functions +*/ +#ifdef _WIN32 + +#define ENET_BUILDING_LIB 0 +#include "enet/enet.h" +#include <windows.h> +#include <mmsystem.h> + +static enet_uint32 timeBase = 0; + +int +enet_initialize (void) +{ + WORD versionRequested = MAKEWORD (1, 1); + WSADATA wsaData; + + if (WSAStartup (versionRequested, & wsaData)) + return -1; + + if (LOBYTE (wsaData.wVersion) != 1|| + HIBYTE (wsaData.wVersion) != 1) + { + WSACleanup (); + + return -1; + } + +#ifndef WINRT_ENABLED + timeBeginPeriod (1); +#endif + + return 0; +} + +void +enet_deinitialize (void) +{ +#ifndef WINRT_ENABLED + timeEndPeriod (1); +#endif + + WSACleanup (); +} + +#ifdef WINRT_ENABLED +enet_uint32 +timeGetTime() { + ULONGLONG ticks = GetTickCount64(); + return (enet_uint32)ticks; +} +#endif + + +enet_uint32 +enet_host_random_seed (void) +{ + return (enet_uint32) timeGetTime (); +} + +enet_uint32 +enet_time_get (void) +{ + return (enet_uint32) timeGetTime () - timeBase; +} + +void +enet_time_set (enet_uint32 newTimeBase) +{ + timeBase = (enet_uint32) timeGetTime () - newTimeBase; +} + +int +enet_address_set_host (ENetAddress * address, const char * name) +{ + struct hostent * hostEntry; + + hostEntry = gethostbyname (name); + if (hostEntry == NULL || + hostEntry -> h_addrtype != AF_INET) + { + unsigned long host = inet_addr (name); + if (host == INADDR_NONE) + return -1; + address -> host = host; + return 0; + } + + address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0]; + + return 0; +} + +int +enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength) +{ + char * addr = inet_ntoa (* (struct in_addr *) & address -> host); + if (addr == NULL) + return -1; + else + { + size_t addrLen = strlen(addr); + if (addrLen >= nameLength) + return -1; + memcpy (name, addr, addrLen + 1); + } + return 0; +} + +int +enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength) +{ + struct in_addr in; + struct hostent * hostEntry; + + in.s_addr = address -> host; + + hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET); + if (hostEntry == NULL) + return enet_address_get_host_ip (address, name, nameLength); + else + { + size_t hostLen = strlen (hostEntry -> h_name); + if (hostLen >= nameLength) + return -1; + memcpy (name, hostEntry -> h_name, hostLen + 1); + } + + return 0; +} + +int +enet_socket_bind (ENetSocket socket, const ENetAddress * address) +{ + struct sockaddr_in sin; + + memset (& sin, 0, sizeof (struct sockaddr_in)); + + sin.sin_family = AF_INET; + + if (address != NULL) + { + sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); + sin.sin_addr.s_addr = address -> host; + } + else + { + sin.sin_port = 0; + sin.sin_addr.s_addr = INADDR_ANY; + } + + return bind (socket, + (struct sockaddr *) & sin, + sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0; +} + +int +enet_socket_get_address (ENetSocket socket, ENetAddress * address) +{ + struct sockaddr_in sin; + int sinLength = sizeof (struct sockaddr_in); + + if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1) + return -1; + + address -> host = (enet_uint32) sin.sin_addr.s_addr; + address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); + + return 0; +} + +int +enet_socket_listen (ENetSocket socket, int backlog) +{ + return listen (socket, backlog < 0 ? SOMAXCONN : backlog) == SOCKET_ERROR ? -1 : 0; +} + +ENetSocket +enet_socket_create (ENetSocketType type) +{ + return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); +} + +int +enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) +{ + int result = SOCKET_ERROR; + switch (option) + { + case ENET_SOCKOPT_NONBLOCK: + { + u_long nonBlocking = (u_long) value; + result = ioctlsocket (socket, FIONBIO, & nonBlocking); + break; + } + + case ENET_SOCKOPT_BROADCAST: + result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int)); + break; + + case ENET_SOCKOPT_REUSEADDR: + result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int)); + break; + + case ENET_SOCKOPT_RCVBUF: + result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int)); + break; + + case ENET_SOCKOPT_SNDBUF: + result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int)); + break; + + case ENET_SOCKOPT_RCVTIMEO: + result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & value, sizeof (int)); + break; + + case ENET_SOCKOPT_SNDTIMEO: + result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & value, sizeof (int)); + break; + + case ENET_SOCKOPT_NODELAY: + result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int)); + break; + + default: + break; + } + return result == SOCKET_ERROR ? -1 : 0; +} + +int +enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value) +{ + int result = SOCKET_ERROR, len; + switch (option) + { + case ENET_SOCKOPT_ERROR: + len = sizeof(int); + result = getsockopt (socket, SOL_SOCKET, SO_ERROR, (char *) value, & len); + break; + + default: + break; + } + return result == SOCKET_ERROR ? -1 : 0; +} + +int +enet_socket_connect (ENetSocket socket, const ENetAddress * address) +{ + struct sockaddr_in sin; + int result; + + memset (& sin, 0, sizeof (struct sockaddr_in)); + + sin.sin_family = AF_INET; + sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); + sin.sin_addr.s_addr = address -> host; + + result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); + if (result == SOCKET_ERROR && WSAGetLastError () != WSAEWOULDBLOCK) + return -1; + + return 0; +} + +ENetSocket +enet_socket_accept (ENetSocket socket, ENetAddress * address) +{ + SOCKET result; + struct sockaddr_in sin; + int sinLength = sizeof (struct sockaddr_in); + + result = accept (socket, + address != NULL ? (struct sockaddr *) & sin : NULL, + address != NULL ? & sinLength : NULL); + + if (result == INVALID_SOCKET) + return ENET_SOCKET_NULL; + + if (address != NULL) + { + address -> host = (enet_uint32) sin.sin_addr.s_addr; + address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); + } + + return result; +} + +int +enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how) +{ + return shutdown (socket, (int) how) == SOCKET_ERROR ? -1 : 0; +} + +void +enet_socket_destroy (ENetSocket socket) +{ + if (socket != INVALID_SOCKET) + closesocket (socket); +} + +int +enet_socket_send (ENetSocket socket, + const ENetAddress * address, + const ENetBuffer * buffers, + size_t bufferCount) +{ + struct sockaddr_in sin; + DWORD sentLength; + + if (address != NULL) + { + memset (& sin, 0, sizeof (struct sockaddr_in)); + + sin.sin_family = AF_INET; + sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); + sin.sin_addr.s_addr = address -> host; + } + + if (WSASendTo (socket, + (LPWSABUF) buffers, + (DWORD) bufferCount, + & sentLength, + 0, + address != NULL ? (struct sockaddr *) & sin : NULL, + address != NULL ? sizeof (struct sockaddr_in) : 0, + NULL, + NULL) == SOCKET_ERROR) + { + if (WSAGetLastError () == WSAEWOULDBLOCK) + return 0; + + return -1; + } + + return (int) sentLength; +} + +int +enet_socket_receive (ENetSocket socket, + ENetAddress * address, + ENetBuffer * buffers, + size_t bufferCount) +{ + INT sinLength = sizeof (struct sockaddr_in); + DWORD flags = 0, + recvLength; + struct sockaddr_in sin; + + if (WSARecvFrom (socket, + (LPWSABUF) buffers, + (DWORD) bufferCount, + & recvLength, + & flags, + address != NULL ? (struct sockaddr *) & sin : NULL, + address != NULL ? & sinLength : NULL, + NULL, + NULL) == SOCKET_ERROR) + { + switch (WSAGetLastError ()) + { + case WSAEWOULDBLOCK: + case WSAECONNRESET: + return 0; + } + + return -1; + } + + if (flags & MSG_PARTIAL) + return -1; + + if (address != NULL) + { + address -> host = (enet_uint32) sin.sin_addr.s_addr; + address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); + } + + return (int) recvLength; +} + +int +enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout) +{ + struct timeval timeVal; + + timeVal.tv_sec = timeout / 1000; + timeVal.tv_usec = (timeout % 1000) * 1000; + + return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal); +} + +int +enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout) +{ + fd_set readSet, writeSet; + struct timeval timeVal; + int selectCount; + + timeVal.tv_sec = timeout / 1000; + timeVal.tv_usec = (timeout % 1000) * 1000; + + FD_ZERO (& readSet); + FD_ZERO (& writeSet); + + if (* condition & ENET_SOCKET_WAIT_SEND) + FD_SET (socket, & writeSet); + + if (* condition & ENET_SOCKET_WAIT_RECEIVE) + FD_SET (socket, & readSet); + + selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal); + + if (selectCount < 0) + return -1; + + * condition = ENET_SOCKET_WAIT_NONE; + + if (selectCount == 0) + return 0; + + if (FD_ISSET (socket, & writeSet)) + * condition |= ENET_SOCKET_WAIT_SEND; + + if (FD_ISSET (socket, & readSet)) + * condition |= ENET_SOCKET_WAIT_RECEIVE; + + return 0; +} + +#endif + diff --git a/drivers/freetype/FTL.TXT b/thirdparty/freetype/FTL.TXT index 433ab060e3..433ab060e3 100644 --- a/drivers/freetype/FTL.TXT +++ b/thirdparty/freetype/FTL.TXT diff --git a/drivers/freetype/LICENSE.TXT b/thirdparty/freetype/LICENSE.TXT index af5a1c50f6..af5a1c50f6 100644 --- a/drivers/freetype/LICENSE.TXT +++ b/thirdparty/freetype/LICENSE.TXT diff --git a/drivers/freetype/include/freetype/config/ftconfig.h b/thirdparty/freetype/include/freetype/config/ftconfig.h index 157a704fa8..157a704fa8 100644 --- a/drivers/freetype/include/freetype/config/ftconfig.h +++ b/thirdparty/freetype/include/freetype/config/ftconfig.h diff --git a/drivers/freetype/include/freetype/config/ftheader.h b/thirdparty/freetype/include/freetype/config/ftheader.h index 68e14834d4..68e14834d4 100644 --- a/drivers/freetype/include/freetype/config/ftheader.h +++ b/thirdparty/freetype/include/freetype/config/ftheader.h diff --git a/drivers/freetype/include/freetype/config/ftmodule.h b/thirdparty/freetype/include/freetype/config/ftmodule.h index 76d271a74b..76d271a74b 100644 --- a/drivers/freetype/include/freetype/config/ftmodule.h +++ b/thirdparty/freetype/include/freetype/config/ftmodule.h diff --git a/drivers/freetype/include/freetype/config/ftoption.h b/thirdparty/freetype/include/freetype/config/ftoption.h index afd32f1cda..afd32f1cda 100644 --- a/drivers/freetype/include/freetype/config/ftoption.h +++ b/thirdparty/freetype/include/freetype/config/ftoption.h diff --git a/drivers/freetype/include/freetype/config/ftstdlib.h b/thirdparty/freetype/include/freetype/config/ftstdlib.h index 562e255810..562e255810 100644 --- a/drivers/freetype/include/freetype/config/ftstdlib.h +++ b/thirdparty/freetype/include/freetype/config/ftstdlib.h diff --git a/drivers/freetype/include/freetype/freetype.h b/thirdparty/freetype/include/freetype/freetype.h index 45e10c48a2..45e10c48a2 100644 --- a/drivers/freetype/include/freetype/freetype.h +++ b/thirdparty/freetype/include/freetype/freetype.h diff --git a/drivers/freetype/include/freetype/ftadvanc.h b/thirdparty/freetype/include/freetype/ftadvanc.h index 023dd84b7a..023dd84b7a 100644 --- a/drivers/freetype/include/freetype/ftadvanc.h +++ b/thirdparty/freetype/include/freetype/ftadvanc.h diff --git a/drivers/freetype/include/freetype/ftautoh.h b/thirdparty/freetype/include/freetype/ftautoh.h index 40c8003c4a..40c8003c4a 100644 --- a/drivers/freetype/include/freetype/ftautoh.h +++ b/thirdparty/freetype/include/freetype/ftautoh.h diff --git a/drivers/freetype/include/freetype/ftbbox.h b/thirdparty/freetype/include/freetype/ftbbox.h index 2a4d214416..2a4d214416 100644 --- a/drivers/freetype/include/freetype/ftbbox.h +++ b/thirdparty/freetype/include/freetype/ftbbox.h diff --git a/drivers/freetype/include/freetype/ftbdf.h b/thirdparty/freetype/include/freetype/ftbdf.h index 016dba086d..016dba086d 100644 --- a/drivers/freetype/include/freetype/ftbdf.h +++ b/thirdparty/freetype/include/freetype/ftbdf.h diff --git a/drivers/freetype/include/freetype/ftbitmap.h b/thirdparty/freetype/include/freetype/ftbitmap.h index 0eac7b9d7d..0eac7b9d7d 100644 --- a/drivers/freetype/include/freetype/ftbitmap.h +++ b/thirdparty/freetype/include/freetype/ftbitmap.h diff --git a/drivers/freetype/include/freetype/ftbzip2.h b/thirdparty/freetype/include/freetype/ftbzip2.h index b7f2eee87d..b7f2eee87d 100644 --- a/drivers/freetype/include/freetype/ftbzip2.h +++ b/thirdparty/freetype/include/freetype/ftbzip2.h diff --git a/drivers/freetype/include/freetype/ftcache.h b/thirdparty/freetype/include/freetype/ftcache.h index 883c88d5d2..883c88d5d2 100644 --- a/drivers/freetype/include/freetype/ftcache.h +++ b/thirdparty/freetype/include/freetype/ftcache.h diff --git a/drivers/freetype/include/freetype/ftcffdrv.h b/thirdparty/freetype/include/freetype/ftcffdrv.h index ad34541fdb..ad34541fdb 100644 --- a/drivers/freetype/include/freetype/ftcffdrv.h +++ b/thirdparty/freetype/include/freetype/ftcffdrv.h diff --git a/drivers/freetype/include/freetype/ftchapters.h b/thirdparty/freetype/include/freetype/ftchapters.h index ab4389530e..ab4389530e 100644 --- a/drivers/freetype/include/freetype/ftchapters.h +++ b/thirdparty/freetype/include/freetype/ftchapters.h diff --git a/drivers/freetype/include/freetype/ftcid.h b/thirdparty/freetype/include/freetype/ftcid.h index e1bc9fe015..e1bc9fe015 100644 --- a/drivers/freetype/include/freetype/ftcid.h +++ b/thirdparty/freetype/include/freetype/ftcid.h diff --git a/drivers/freetype/include/freetype/fterrdef.h b/thirdparty/freetype/include/freetype/fterrdef.h index 3f53dd5820..3f53dd5820 100644 --- a/drivers/freetype/include/freetype/fterrdef.h +++ b/thirdparty/freetype/include/freetype/fterrdef.h diff --git a/drivers/freetype/include/freetype/fterrors.h b/thirdparty/freetype/include/freetype/fterrors.h index e15bfb001e..e15bfb001e 100644 --- a/drivers/freetype/include/freetype/fterrors.h +++ b/thirdparty/freetype/include/freetype/fterrors.h diff --git a/drivers/freetype/include/freetype/ftfntfmt.h b/thirdparty/freetype/include/freetype/ftfntfmt.h index bd423247bb..bd423247bb 100644 --- a/drivers/freetype/include/freetype/ftfntfmt.h +++ b/thirdparty/freetype/include/freetype/ftfntfmt.h diff --git a/drivers/freetype/include/freetype/ftgasp.h b/thirdparty/freetype/include/freetype/ftgasp.h index 3f5b3bc695..3f5b3bc695 100644 --- a/drivers/freetype/include/freetype/ftgasp.h +++ b/thirdparty/freetype/include/freetype/ftgasp.h diff --git a/drivers/freetype/include/freetype/ftglyph.h b/thirdparty/freetype/include/freetype/ftglyph.h index d9840a81fc..d9840a81fc 100644 --- a/drivers/freetype/include/freetype/ftglyph.h +++ b/thirdparty/freetype/include/freetype/ftglyph.h diff --git a/drivers/freetype/include/freetype/ftgxval.h b/thirdparty/freetype/include/freetype/ftgxval.h index a58e86a040..a58e86a040 100644 --- a/drivers/freetype/include/freetype/ftgxval.h +++ b/thirdparty/freetype/include/freetype/ftgxval.h diff --git a/drivers/freetype/include/freetype/ftgzip.h b/thirdparty/freetype/include/freetype/ftgzip.h index 3932ce6887..3932ce6887 100644 --- a/drivers/freetype/include/freetype/ftgzip.h +++ b/thirdparty/freetype/include/freetype/ftgzip.h diff --git a/drivers/freetype/include/freetype/ftimage.h b/thirdparty/freetype/include/freetype/ftimage.h index 28b2704e80..28b2704e80 100644 --- a/drivers/freetype/include/freetype/ftimage.h +++ b/thirdparty/freetype/include/freetype/ftimage.h diff --git a/drivers/freetype/include/freetype/ftincrem.h b/thirdparty/freetype/include/freetype/ftincrem.h index 46b58b7917..46b58b7917 100644 --- a/drivers/freetype/include/freetype/ftincrem.h +++ b/thirdparty/freetype/include/freetype/ftincrem.h diff --git a/drivers/freetype/include/freetype/ftlcdfil.h b/thirdparty/freetype/include/freetype/ftlcdfil.h index e06a8957f5..e06a8957f5 100644 --- a/drivers/freetype/include/freetype/ftlcdfil.h +++ b/thirdparty/freetype/include/freetype/ftlcdfil.h diff --git a/drivers/freetype/include/freetype/ftlist.h b/thirdparty/freetype/include/freetype/ftlist.h index 82f437ac61..82f437ac61 100644 --- a/drivers/freetype/include/freetype/ftlist.h +++ b/thirdparty/freetype/include/freetype/ftlist.h diff --git a/drivers/freetype/include/freetype/ftlzw.h b/thirdparty/freetype/include/freetype/ftlzw.h index 582e2c1465..582e2c1465 100644 --- a/drivers/freetype/include/freetype/ftlzw.h +++ b/thirdparty/freetype/include/freetype/ftlzw.h diff --git a/drivers/freetype/include/freetype/ftmac.h b/thirdparty/freetype/include/freetype/ftmac.h index adb15cadf3..adb15cadf3 100644 --- a/drivers/freetype/include/freetype/ftmac.h +++ b/thirdparty/freetype/include/freetype/ftmac.h diff --git a/drivers/freetype/include/freetype/ftmm.h b/thirdparty/freetype/include/freetype/ftmm.h index 6c05f0c390..6c05f0c390 100644 --- a/drivers/freetype/include/freetype/ftmm.h +++ b/thirdparty/freetype/include/freetype/ftmm.h diff --git a/drivers/freetype/include/freetype/ftmodapi.h b/thirdparty/freetype/include/freetype/ftmodapi.h index b4d2758efa..b4d2758efa 100644 --- a/drivers/freetype/include/freetype/ftmodapi.h +++ b/thirdparty/freetype/include/freetype/ftmodapi.h diff --git a/drivers/freetype/include/freetype/ftmoderr.h b/thirdparty/freetype/include/freetype/ftmoderr.h index 2a7671c816..2a7671c816 100644 --- a/drivers/freetype/include/freetype/ftmoderr.h +++ b/thirdparty/freetype/include/freetype/ftmoderr.h diff --git a/drivers/freetype/include/freetype/ftotval.h b/thirdparty/freetype/include/freetype/ftotval.h index 3e6e18d8a6..3e6e18d8a6 100644 --- a/drivers/freetype/include/freetype/ftotval.h +++ b/thirdparty/freetype/include/freetype/ftotval.h diff --git a/drivers/freetype/include/freetype/ftoutln.h b/thirdparty/freetype/include/freetype/ftoutln.h index 6a6451207c..6a6451207c 100644 --- a/drivers/freetype/include/freetype/ftoutln.h +++ b/thirdparty/freetype/include/freetype/ftoutln.h diff --git a/drivers/freetype/include/freetype/ftpfr.h b/thirdparty/freetype/include/freetype/ftpfr.h index 2e1bff2f67..2e1bff2f67 100644 --- a/drivers/freetype/include/freetype/ftpfr.h +++ b/thirdparty/freetype/include/freetype/ftpfr.h diff --git a/drivers/freetype/include/freetype/ftrender.h b/thirdparty/freetype/include/freetype/ftrender.h index 9f7ed9e9d9..9f7ed9e9d9 100644 --- a/drivers/freetype/include/freetype/ftrender.h +++ b/thirdparty/freetype/include/freetype/ftrender.h diff --git a/drivers/freetype/include/freetype/ftsizes.h b/thirdparty/freetype/include/freetype/ftsizes.h index 55e0d5ccfd..55e0d5ccfd 100644 --- a/drivers/freetype/include/freetype/ftsizes.h +++ b/thirdparty/freetype/include/freetype/ftsizes.h diff --git a/drivers/freetype/include/freetype/ftsnames.h b/thirdparty/freetype/include/freetype/ftsnames.h index a7b51c2cba..a7b51c2cba 100644 --- a/drivers/freetype/include/freetype/ftsnames.h +++ b/thirdparty/freetype/include/freetype/ftsnames.h diff --git a/drivers/freetype/include/freetype/ftstroke.h b/thirdparty/freetype/include/freetype/ftstroke.h index b3b9922dad..b3b9922dad 100644 --- a/drivers/freetype/include/freetype/ftstroke.h +++ b/thirdparty/freetype/include/freetype/ftstroke.h diff --git a/drivers/freetype/include/freetype/ftsynth.h b/thirdparty/freetype/include/freetype/ftsynth.h index fdfcb6912b..fdfcb6912b 100644 --- a/drivers/freetype/include/freetype/ftsynth.h +++ b/thirdparty/freetype/include/freetype/ftsynth.h diff --git a/drivers/freetype/include/freetype/ftsystem.h b/thirdparty/freetype/include/freetype/ftsystem.h index a75f958022..a75f958022 100644 --- a/drivers/freetype/include/freetype/ftsystem.h +++ b/thirdparty/freetype/include/freetype/ftsystem.h diff --git a/drivers/freetype/include/freetype/fttrigon.h b/thirdparty/freetype/include/freetype/fttrigon.h index f789b524cb..f789b524cb 100644 --- a/drivers/freetype/include/freetype/fttrigon.h +++ b/thirdparty/freetype/include/freetype/fttrigon.h diff --git a/drivers/freetype/include/freetype/ftttdrv.h b/thirdparty/freetype/include/freetype/ftttdrv.h index 0d868bc259..0d868bc259 100644 --- a/drivers/freetype/include/freetype/ftttdrv.h +++ b/thirdparty/freetype/include/freetype/ftttdrv.h diff --git a/drivers/freetype/include/freetype/fttypes.h b/thirdparty/freetype/include/freetype/fttypes.h index 2673e79c3c..2673e79c3c 100644 --- a/drivers/freetype/include/freetype/fttypes.h +++ b/thirdparty/freetype/include/freetype/fttypes.h diff --git a/drivers/freetype/include/freetype/ftwinfnt.h b/thirdparty/freetype/include/freetype/ftwinfnt.h index a1a715baa1..a1a715baa1 100644 --- a/drivers/freetype/include/freetype/ftwinfnt.h +++ b/thirdparty/freetype/include/freetype/ftwinfnt.h diff --git a/drivers/freetype/include/freetype/internal/autohint.h b/thirdparty/freetype/include/freetype/internal/autohint.h index 7ef82b8f3c..7ef82b8f3c 100644 --- a/drivers/freetype/include/freetype/internal/autohint.h +++ b/thirdparty/freetype/include/freetype/internal/autohint.h diff --git a/drivers/freetype/include/freetype/internal/ftcalc.h b/thirdparty/freetype/include/freetype/internal/ftcalc.h index 8a884f680a..8a884f680a 100644 --- a/drivers/freetype/include/freetype/internal/ftcalc.h +++ b/thirdparty/freetype/include/freetype/internal/ftcalc.h diff --git a/drivers/freetype/include/freetype/internal/ftdebug.h b/thirdparty/freetype/include/freetype/internal/ftdebug.h index d110457157..d110457157 100644 --- a/drivers/freetype/include/freetype/internal/ftdebug.h +++ b/thirdparty/freetype/include/freetype/internal/ftdebug.h diff --git a/drivers/freetype/include/freetype/internal/ftdriver.h b/thirdparty/freetype/include/freetype/internal/ftdriver.h index 3e1e66e979..3e1e66e979 100644 --- a/drivers/freetype/include/freetype/internal/ftdriver.h +++ b/thirdparty/freetype/include/freetype/internal/ftdriver.h diff --git a/drivers/freetype/include/freetype/internal/ftgloadr.h b/thirdparty/freetype/include/freetype/internal/ftgloadr.h index bebf5dbba2..bebf5dbba2 100644 --- a/drivers/freetype/include/freetype/internal/ftgloadr.h +++ b/thirdparty/freetype/include/freetype/internal/ftgloadr.h diff --git a/drivers/freetype/include/freetype/internal/fthash.h b/thirdparty/freetype/include/freetype/internal/fthash.h index f22f9d5d39..f22f9d5d39 100644 --- a/drivers/freetype/include/freetype/internal/fthash.h +++ b/thirdparty/freetype/include/freetype/internal/fthash.h diff --git a/drivers/freetype/include/freetype/internal/ftmemory.h b/thirdparty/freetype/include/freetype/internal/ftmemory.h index 8c06fc21a5..8c06fc21a5 100644 --- a/drivers/freetype/include/freetype/internal/ftmemory.h +++ b/thirdparty/freetype/include/freetype/internal/ftmemory.h diff --git a/drivers/freetype/include/freetype/internal/ftobjs.h b/thirdparty/freetype/include/freetype/internal/ftobjs.h index e3fa32083b..e3fa32083b 100644 --- a/drivers/freetype/include/freetype/internal/ftobjs.h +++ b/thirdparty/freetype/include/freetype/internal/ftobjs.h diff --git a/drivers/freetype/include/freetype/internal/ftpic.h b/thirdparty/freetype/include/freetype/internal/ftpic.h index 6d800a08a1..6d800a08a1 100644 --- a/drivers/freetype/include/freetype/internal/ftpic.h +++ b/thirdparty/freetype/include/freetype/internal/ftpic.h diff --git a/drivers/freetype/include/freetype/internal/ftrfork.h b/thirdparty/freetype/include/freetype/internal/ftrfork.h index b923401e68..b923401e68 100644 --- a/drivers/freetype/include/freetype/internal/ftrfork.h +++ b/thirdparty/freetype/include/freetype/internal/ftrfork.h diff --git a/drivers/freetype/include/freetype/internal/ftserv.h b/thirdparty/freetype/include/freetype/internal/ftserv.h index 91897177ba..91897177ba 100644 --- a/drivers/freetype/include/freetype/internal/ftserv.h +++ b/thirdparty/freetype/include/freetype/internal/ftserv.h diff --git a/drivers/freetype/include/freetype/internal/ftstream.h b/thirdparty/freetype/include/freetype/internal/ftstream.h index 6d04875657..6d04875657 100644 --- a/drivers/freetype/include/freetype/internal/ftstream.h +++ b/thirdparty/freetype/include/freetype/internal/ftstream.h diff --git a/drivers/freetype/include/freetype/internal/fttrace.h b/thirdparty/freetype/include/freetype/internal/fttrace.h index efb3355954..efb3355954 100644 --- a/drivers/freetype/include/freetype/internal/fttrace.h +++ b/thirdparty/freetype/include/freetype/internal/fttrace.h diff --git a/drivers/freetype/include/freetype/internal/ftvalid.h b/thirdparty/freetype/include/freetype/internal/ftvalid.h index aac92c9af8..aac92c9af8 100644 --- a/drivers/freetype/include/freetype/internal/ftvalid.h +++ b/thirdparty/freetype/include/freetype/internal/ftvalid.h diff --git a/drivers/freetype/include/freetype/internal/internal.h b/thirdparty/freetype/include/freetype/internal/internal.h index 8c3c14c12a..8c3c14c12a 100644 --- a/drivers/freetype/include/freetype/internal/internal.h +++ b/thirdparty/freetype/include/freetype/internal/internal.h diff --git a/drivers/freetype/include/freetype/internal/psaux.h b/thirdparty/freetype/include/freetype/internal/psaux.h index 15dedfd28e..15dedfd28e 100644 --- a/drivers/freetype/include/freetype/internal/psaux.h +++ b/thirdparty/freetype/include/freetype/internal/psaux.h diff --git a/drivers/freetype/include/freetype/internal/pshints.h b/thirdparty/freetype/include/freetype/internal/pshints.h index e60dc9cd55..e60dc9cd55 100644 --- a/drivers/freetype/include/freetype/internal/pshints.h +++ b/thirdparty/freetype/include/freetype/internal/pshints.h diff --git a/drivers/freetype/include/freetype/internal/services/svbdf.h b/thirdparty/freetype/include/freetype/internal/services/svbdf.h index c24475fc20..c24475fc20 100644 --- a/drivers/freetype/include/freetype/internal/services/svbdf.h +++ b/thirdparty/freetype/include/freetype/internal/services/svbdf.h diff --git a/drivers/freetype/include/freetype/internal/services/svcid.h b/thirdparty/freetype/include/freetype/internal/services/svcid.h index dbbe6044a4..dbbe6044a4 100644 --- a/drivers/freetype/include/freetype/internal/services/svcid.h +++ b/thirdparty/freetype/include/freetype/internal/services/svcid.h diff --git a/drivers/freetype/include/freetype/internal/services/svfntfmt.h b/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h index bd295c9c6b..bd295c9c6b 100644 --- a/drivers/freetype/include/freetype/internal/services/svfntfmt.h +++ b/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h diff --git a/drivers/freetype/include/freetype/internal/services/svgldict.h b/thirdparty/freetype/include/freetype/internal/services/svgldict.h index fff29bc40c..fff29bc40c 100644 --- a/drivers/freetype/include/freetype/internal/services/svgldict.h +++ b/thirdparty/freetype/include/freetype/internal/services/svgldict.h diff --git a/drivers/freetype/include/freetype/internal/services/svgxval.h b/thirdparty/freetype/include/freetype/internal/services/svgxval.h index fb8ffba83c..fb8ffba83c 100644 --- a/drivers/freetype/include/freetype/internal/services/svgxval.h +++ b/thirdparty/freetype/include/freetype/internal/services/svgxval.h diff --git a/drivers/freetype/include/freetype/internal/services/svkern.h b/thirdparty/freetype/include/freetype/internal/services/svkern.h index a636f1af1c..a636f1af1c 100644 --- a/drivers/freetype/include/freetype/internal/services/svkern.h +++ b/thirdparty/freetype/include/freetype/internal/services/svkern.h diff --git a/drivers/freetype/include/freetype/internal/services/svmm.h b/thirdparty/freetype/include/freetype/internal/services/svmm.h index b78a19f8e0..b78a19f8e0 100644 --- a/drivers/freetype/include/freetype/internal/services/svmm.h +++ b/thirdparty/freetype/include/freetype/internal/services/svmm.h diff --git a/drivers/freetype/include/freetype/internal/services/svotval.h b/thirdparty/freetype/include/freetype/internal/services/svotval.h index bc929d4bd9..bc929d4bd9 100644 --- a/drivers/freetype/include/freetype/internal/services/svotval.h +++ b/thirdparty/freetype/include/freetype/internal/services/svotval.h diff --git a/drivers/freetype/include/freetype/internal/services/svpfr.h b/thirdparty/freetype/include/freetype/internal/services/svpfr.h index d0f7c4df95..d0f7c4df95 100644 --- a/drivers/freetype/include/freetype/internal/services/svpfr.h +++ b/thirdparty/freetype/include/freetype/internal/services/svpfr.h diff --git a/drivers/freetype/include/freetype/internal/services/svpostnm.h b/thirdparty/freetype/include/freetype/internal/services/svpostnm.h index f124380050..f124380050 100644 --- a/drivers/freetype/include/freetype/internal/services/svpostnm.h +++ b/thirdparty/freetype/include/freetype/internal/services/svpostnm.h diff --git a/drivers/freetype/include/freetype/internal/services/svprop.h b/thirdparty/freetype/include/freetype/internal/services/svprop.h index 870e90ed7c..870e90ed7c 100644 --- a/drivers/freetype/include/freetype/internal/services/svprop.h +++ b/thirdparty/freetype/include/freetype/internal/services/svprop.h diff --git a/drivers/freetype/include/freetype/internal/services/svpscmap.h b/thirdparty/freetype/include/freetype/internal/services/svpscmap.h index 9acc21690f..9acc21690f 100644 --- a/drivers/freetype/include/freetype/internal/services/svpscmap.h +++ b/thirdparty/freetype/include/freetype/internal/services/svpscmap.h diff --git a/drivers/freetype/include/freetype/internal/services/svpsinfo.h b/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h index f2c8060440..f2c8060440 100644 --- a/drivers/freetype/include/freetype/internal/services/svpsinfo.h +++ b/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h diff --git a/drivers/freetype/include/freetype/internal/services/svsfnt.h b/thirdparty/freetype/include/freetype/internal/services/svsfnt.h index 0f38cf195f..0f38cf195f 100644 --- a/drivers/freetype/include/freetype/internal/services/svsfnt.h +++ b/thirdparty/freetype/include/freetype/internal/services/svsfnt.h diff --git a/drivers/freetype/include/freetype/internal/services/svttcmap.h b/thirdparty/freetype/include/freetype/internal/services/svttcmap.h index 772c72189e..772c72189e 100644 --- a/drivers/freetype/include/freetype/internal/services/svttcmap.h +++ b/thirdparty/freetype/include/freetype/internal/services/svttcmap.h diff --git a/drivers/freetype/include/freetype/internal/services/svtteng.h b/thirdparty/freetype/include/freetype/internal/services/svtteng.h index c55061a034..c55061a034 100644 --- a/drivers/freetype/include/freetype/internal/services/svtteng.h +++ b/thirdparty/freetype/include/freetype/internal/services/svtteng.h diff --git a/drivers/freetype/include/freetype/internal/services/svttglyf.h b/thirdparty/freetype/include/freetype/internal/services/svttglyf.h index c33edd46de..c33edd46de 100644 --- a/drivers/freetype/include/freetype/internal/services/svttglyf.h +++ b/thirdparty/freetype/include/freetype/internal/services/svttglyf.h diff --git a/drivers/freetype/include/freetype/internal/services/svwinfnt.h b/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h index c2f6d4c6d3..c2f6d4c6d3 100644 --- a/drivers/freetype/include/freetype/internal/services/svwinfnt.h +++ b/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h diff --git a/drivers/freetype/include/freetype/internal/sfnt.h b/thirdparty/freetype/include/freetype/internal/sfnt.h index e139315a1f..e139315a1f 100644 --- a/drivers/freetype/include/freetype/internal/sfnt.h +++ b/thirdparty/freetype/include/freetype/internal/sfnt.h diff --git a/drivers/freetype/include/freetype/internal/t1types.h b/thirdparty/freetype/include/freetype/internal/t1types.h index 494c011fc7..494c011fc7 100644 --- a/drivers/freetype/include/freetype/internal/t1types.h +++ b/thirdparty/freetype/include/freetype/internal/t1types.h diff --git a/drivers/freetype/include/freetype/internal/tttypes.h b/thirdparty/freetype/include/freetype/internal/tttypes.h index 4110d50285..4110d50285 100644 --- a/drivers/freetype/include/freetype/internal/tttypes.h +++ b/thirdparty/freetype/include/freetype/internal/tttypes.h diff --git a/drivers/freetype/include/freetype/t1tables.h b/thirdparty/freetype/include/freetype/t1tables.h index e272324ba2..e272324ba2 100644 --- a/drivers/freetype/include/freetype/t1tables.h +++ b/thirdparty/freetype/include/freetype/t1tables.h diff --git a/drivers/freetype/include/freetype/ttnameid.h b/thirdparty/freetype/include/freetype/ttnameid.h index ce707f1645..ce707f1645 100644 --- a/drivers/freetype/include/freetype/ttnameid.h +++ b/thirdparty/freetype/include/freetype/ttnameid.h diff --git a/drivers/freetype/include/freetype/tttables.h b/thirdparty/freetype/include/freetype/tttables.h index 1c075dcf66..1c075dcf66 100644 --- a/drivers/freetype/include/freetype/tttables.h +++ b/thirdparty/freetype/include/freetype/tttables.h diff --git a/drivers/freetype/include/freetype/tttags.h b/thirdparty/freetype/include/freetype/tttags.h index f3c9aa5fc7..f3c9aa5fc7 100644 --- a/drivers/freetype/include/freetype/tttags.h +++ b/thirdparty/freetype/include/freetype/tttags.h diff --git a/drivers/freetype/include/freetype/ttunpat.h b/thirdparty/freetype/include/freetype/ttunpat.h index ca4676baf8..ca4676baf8 100644 --- a/drivers/freetype/include/freetype/ttunpat.h +++ b/thirdparty/freetype/include/freetype/ttunpat.h diff --git a/drivers/freetype/include/ft2build.h b/thirdparty/freetype/include/ft2build.h index 1e8a9b4994..1e8a9b4994 100644 --- a/drivers/freetype/include/ft2build.h +++ b/thirdparty/freetype/include/ft2build.h diff --git a/drivers/freetype/src/autofit/afangles.c b/thirdparty/freetype/src/autofit/afangles.c index b856e57a8b..b856e57a8b 100644 --- a/drivers/freetype/src/autofit/afangles.c +++ b/thirdparty/freetype/src/autofit/afangles.c diff --git a/drivers/freetype/src/autofit/afangles.h b/thirdparty/freetype/src/autofit/afangles.h index f33f9e108e..f33f9e108e 100644 --- a/drivers/freetype/src/autofit/afangles.h +++ b/thirdparty/freetype/src/autofit/afangles.h diff --git a/drivers/freetype/src/autofit/afblue.c b/thirdparty/freetype/src/autofit/afblue.c index 95786ed6f2..95786ed6f2 100644 --- a/drivers/freetype/src/autofit/afblue.c +++ b/thirdparty/freetype/src/autofit/afblue.c diff --git a/drivers/freetype/src/autofit/afblue.cin b/thirdparty/freetype/src/autofit/afblue.cin index 0c3cae818f..0c3cae818f 100644 --- a/drivers/freetype/src/autofit/afblue.cin +++ b/thirdparty/freetype/src/autofit/afblue.cin diff --git a/drivers/freetype/src/autofit/afblue.dat b/thirdparty/freetype/src/autofit/afblue.dat index 0734ec71f0..0734ec71f0 100644 --- a/drivers/freetype/src/autofit/afblue.dat +++ b/thirdparty/freetype/src/autofit/afblue.dat diff --git a/drivers/freetype/src/autofit/afblue.h b/thirdparty/freetype/src/autofit/afblue.h index 41f838e457..41f838e457 100644 --- a/drivers/freetype/src/autofit/afblue.h +++ b/thirdparty/freetype/src/autofit/afblue.h diff --git a/drivers/freetype/src/autofit/afblue.hin b/thirdparty/freetype/src/autofit/afblue.hin index dd44e77254..dd44e77254 100644 --- a/drivers/freetype/src/autofit/afblue.hin +++ b/thirdparty/freetype/src/autofit/afblue.hin diff --git a/drivers/freetype/src/autofit/afcjk.c b/thirdparty/freetype/src/autofit/afcjk.c index 4823c1d7f8..4823c1d7f8 100644 --- a/drivers/freetype/src/autofit/afcjk.c +++ b/thirdparty/freetype/src/autofit/afcjk.c diff --git a/drivers/freetype/src/autofit/afcjk.h b/thirdparty/freetype/src/autofit/afcjk.h index 40d1184386..40d1184386 100644 --- a/drivers/freetype/src/autofit/afcjk.h +++ b/thirdparty/freetype/src/autofit/afcjk.h diff --git a/drivers/freetype/src/autofit/afcover.h b/thirdparty/freetype/src/autofit/afcover.h index 1c39a707ef..1c39a707ef 100644 --- a/drivers/freetype/src/autofit/afcover.h +++ b/thirdparty/freetype/src/autofit/afcover.h diff --git a/drivers/freetype/src/autofit/afdummy.c b/thirdparty/freetype/src/autofit/afdummy.c index f3960c85fd..f3960c85fd 100644 --- a/drivers/freetype/src/autofit/afdummy.c +++ b/thirdparty/freetype/src/autofit/afdummy.c diff --git a/drivers/freetype/src/autofit/afdummy.h b/thirdparty/freetype/src/autofit/afdummy.h index 7e58d1a9a5..7e58d1a9a5 100644 --- a/drivers/freetype/src/autofit/afdummy.h +++ b/thirdparty/freetype/src/autofit/afdummy.h diff --git a/drivers/freetype/src/autofit/aferrors.h b/thirdparty/freetype/src/autofit/aferrors.h index 53c01f64dd..53c01f64dd 100644 --- a/drivers/freetype/src/autofit/aferrors.h +++ b/thirdparty/freetype/src/autofit/aferrors.h diff --git a/drivers/freetype/src/autofit/afglobal.c b/thirdparty/freetype/src/autofit/afglobal.c index ac6dcafc0f..ac6dcafc0f 100644 --- a/drivers/freetype/src/autofit/afglobal.c +++ b/thirdparty/freetype/src/autofit/afglobal.c diff --git a/drivers/freetype/src/autofit/afglobal.h b/thirdparty/freetype/src/autofit/afglobal.h index ce6b9e8f26..ce6b9e8f26 100644 --- a/drivers/freetype/src/autofit/afglobal.h +++ b/thirdparty/freetype/src/autofit/afglobal.h diff --git a/drivers/freetype/src/autofit/afhints.c b/thirdparty/freetype/src/autofit/afhints.c index 6c3d032d1c..6c3d032d1c 100644 --- a/drivers/freetype/src/autofit/afhints.c +++ b/thirdparty/freetype/src/autofit/afhints.c diff --git a/drivers/freetype/src/autofit/afhints.h b/thirdparty/freetype/src/autofit/afhints.h index 5142e6ed21..5142e6ed21 100644 --- a/drivers/freetype/src/autofit/afhints.h +++ b/thirdparty/freetype/src/autofit/afhints.h diff --git a/drivers/freetype/src/autofit/afindic.c b/thirdparty/freetype/src/autofit/afindic.c index 097a2b2995..097a2b2995 100644 --- a/drivers/freetype/src/autofit/afindic.c +++ b/thirdparty/freetype/src/autofit/afindic.c diff --git a/drivers/freetype/src/autofit/afindic.h b/thirdparty/freetype/src/autofit/afindic.h index 0772e07a29..0772e07a29 100644 --- a/drivers/freetype/src/autofit/afindic.h +++ b/thirdparty/freetype/src/autofit/afindic.h diff --git a/drivers/freetype/src/autofit/aflatin.c b/thirdparty/freetype/src/autofit/aflatin.c index 7ccf3f6e37..7ccf3f6e37 100644 --- a/drivers/freetype/src/autofit/aflatin.c +++ b/thirdparty/freetype/src/autofit/aflatin.c diff --git a/drivers/freetype/src/autofit/aflatin.h b/thirdparty/freetype/src/autofit/aflatin.h index fe6bbd801a..fe6bbd801a 100644 --- a/drivers/freetype/src/autofit/aflatin.h +++ b/thirdparty/freetype/src/autofit/aflatin.h diff --git a/drivers/freetype/src/autofit/aflatin2.c b/thirdparty/freetype/src/autofit/aflatin2.c index 5db4a41141..5db4a41141 100644 --- a/drivers/freetype/src/autofit/aflatin2.c +++ b/thirdparty/freetype/src/autofit/aflatin2.c diff --git a/drivers/freetype/src/autofit/aflatin2.h b/thirdparty/freetype/src/autofit/aflatin2.h index f83f704289..f83f704289 100644 --- a/drivers/freetype/src/autofit/aflatin2.h +++ b/thirdparty/freetype/src/autofit/aflatin2.h diff --git a/drivers/freetype/src/autofit/afloader.c b/thirdparty/freetype/src/autofit/afloader.c index 26bba065bb..26bba065bb 100644 --- a/drivers/freetype/src/autofit/afloader.c +++ b/thirdparty/freetype/src/autofit/afloader.c diff --git a/drivers/freetype/src/autofit/afloader.h b/thirdparty/freetype/src/autofit/afloader.h index 0062eb9b07..0062eb9b07 100644 --- a/drivers/freetype/src/autofit/afloader.h +++ b/thirdparty/freetype/src/autofit/afloader.h diff --git a/drivers/freetype/src/autofit/afmodule.c b/thirdparty/freetype/src/autofit/afmodule.c index 4127382c00..4127382c00 100644 --- a/drivers/freetype/src/autofit/afmodule.c +++ b/thirdparty/freetype/src/autofit/afmodule.c diff --git a/drivers/freetype/src/autofit/afmodule.h b/thirdparty/freetype/src/autofit/afmodule.h index e65db5f5cb..e65db5f5cb 100644 --- a/drivers/freetype/src/autofit/afmodule.h +++ b/thirdparty/freetype/src/autofit/afmodule.h diff --git a/drivers/freetype/src/autofit/afpic.c b/thirdparty/freetype/src/autofit/afpic.c index 3cbd9168e3..3cbd9168e3 100644 --- a/drivers/freetype/src/autofit/afpic.c +++ b/thirdparty/freetype/src/autofit/afpic.c diff --git a/drivers/freetype/src/autofit/afpic.h b/thirdparty/freetype/src/autofit/afpic.h index 98a45a26ba..98a45a26ba 100644 --- a/drivers/freetype/src/autofit/afpic.h +++ b/thirdparty/freetype/src/autofit/afpic.h diff --git a/drivers/freetype/src/autofit/afranges.c b/thirdparty/freetype/src/autofit/afranges.c index 732f3d1629..732f3d1629 100644 --- a/drivers/freetype/src/autofit/afranges.c +++ b/thirdparty/freetype/src/autofit/afranges.c diff --git a/drivers/freetype/src/autofit/afranges.h b/thirdparty/freetype/src/autofit/afranges.h index 1a0e4b1535..1a0e4b1535 100644 --- a/drivers/freetype/src/autofit/afranges.h +++ b/thirdparty/freetype/src/autofit/afranges.h diff --git a/drivers/freetype/src/autofit/afscript.h b/thirdparty/freetype/src/autofit/afscript.h index 33c3012981..33c3012981 100644 --- a/drivers/freetype/src/autofit/afscript.h +++ b/thirdparty/freetype/src/autofit/afscript.h diff --git a/drivers/freetype/src/autofit/afshaper.c b/thirdparty/freetype/src/autofit/afshaper.c index 6d13b65859..6d13b65859 100644 --- a/drivers/freetype/src/autofit/afshaper.c +++ b/thirdparty/freetype/src/autofit/afshaper.c diff --git a/drivers/freetype/src/autofit/afshaper.h b/thirdparty/freetype/src/autofit/afshaper.h index 0d41f78762..0d41f78762 100644 --- a/drivers/freetype/src/autofit/afshaper.h +++ b/thirdparty/freetype/src/autofit/afshaper.h diff --git a/drivers/freetype/src/autofit/afstyles.h b/thirdparty/freetype/src/autofit/afstyles.h index e83a95bb59..e83a95bb59 100644 --- a/drivers/freetype/src/autofit/afstyles.h +++ b/thirdparty/freetype/src/autofit/afstyles.h diff --git a/drivers/freetype/src/autofit/aftypes.h b/thirdparty/freetype/src/autofit/aftypes.h index ef62043c8a..ef62043c8a 100644 --- a/drivers/freetype/src/autofit/aftypes.h +++ b/thirdparty/freetype/src/autofit/aftypes.h diff --git a/drivers/freetype/src/autofit/afwarp.c b/thirdparty/freetype/src/autofit/afwarp.c index ce1806c9d3..ce1806c9d3 100644 --- a/drivers/freetype/src/autofit/afwarp.c +++ b/thirdparty/freetype/src/autofit/afwarp.c diff --git a/drivers/freetype/src/autofit/afwarp.h b/thirdparty/freetype/src/autofit/afwarp.h index 6d96f86d73..6d96f86d73 100644 --- a/drivers/freetype/src/autofit/afwarp.h +++ b/thirdparty/freetype/src/autofit/afwarp.h diff --git a/drivers/freetype/src/autofit/afwrtsys.h b/thirdparty/freetype/src/autofit/afwrtsys.h index 842f4921a4..842f4921a4 100644 --- a/drivers/freetype/src/autofit/afwrtsys.h +++ b/thirdparty/freetype/src/autofit/afwrtsys.h diff --git a/drivers/freetype/src/autofit/autofit.c b/thirdparty/freetype/src/autofit/autofit.c index dda9aeb6d7..dda9aeb6d7 100644 --- a/drivers/freetype/src/autofit/autofit.c +++ b/thirdparty/freetype/src/autofit/autofit.c diff --git a/drivers/freetype/src/autofit/module.mk b/thirdparty/freetype/src/autofit/module.mk index 98f0612b99..98f0612b99 100644 --- a/drivers/freetype/src/autofit/module.mk +++ b/thirdparty/freetype/src/autofit/module.mk diff --git a/drivers/freetype/src/autofit/rules.mk b/thirdparty/freetype/src/autofit/rules.mk index 1ef4704649..1ef4704649 100644 --- a/drivers/freetype/src/autofit/rules.mk +++ b/thirdparty/freetype/src/autofit/rules.mk diff --git a/drivers/freetype/src/base/basepic.c b/thirdparty/freetype/src/base/basepic.c index f2cea90d7c..f2cea90d7c 100644 --- a/drivers/freetype/src/base/basepic.c +++ b/thirdparty/freetype/src/base/basepic.c diff --git a/drivers/freetype/src/base/basepic.h b/thirdparty/freetype/src/base/basepic.h index a1a75a0bad..a1a75a0bad 100644 --- a/drivers/freetype/src/base/basepic.h +++ b/thirdparty/freetype/src/base/basepic.h diff --git a/drivers/freetype/src/base/ftadvanc.c b/thirdparty/freetype/src/base/ftadvanc.c index 9e2ab89845..9e2ab89845 100644 --- a/drivers/freetype/src/base/ftadvanc.c +++ b/thirdparty/freetype/src/base/ftadvanc.c diff --git a/drivers/freetype/src/base/ftapi.c b/thirdparty/freetype/src/base/ftapi.c index b94c3eb9fb..b94c3eb9fb 100644 --- a/drivers/freetype/src/base/ftapi.c +++ b/thirdparty/freetype/src/base/ftapi.c diff --git a/drivers/freetype/src/base/ftbase.c b/thirdparty/freetype/src/base/ftbase.c index ab1af6f9f3..ab1af6f9f3 100644 --- a/drivers/freetype/src/base/ftbase.c +++ b/thirdparty/freetype/src/base/ftbase.c diff --git a/drivers/freetype/src/base/ftbase.h b/thirdparty/freetype/src/base/ftbase.h index 717fdaae24..717fdaae24 100644 --- a/drivers/freetype/src/base/ftbase.h +++ b/thirdparty/freetype/src/base/ftbase.h diff --git a/drivers/freetype/src/base/ftbbox.c b/thirdparty/freetype/src/base/ftbbox.c index d3e45ffa0d..d3e45ffa0d 100644 --- a/drivers/freetype/src/base/ftbbox.c +++ b/thirdparty/freetype/src/base/ftbbox.c diff --git a/drivers/freetype/src/base/ftbdf.c b/thirdparty/freetype/src/base/ftbdf.c index 4aafc2b98e..4aafc2b98e 100644 --- a/drivers/freetype/src/base/ftbdf.c +++ b/thirdparty/freetype/src/base/ftbdf.c diff --git a/drivers/freetype/src/base/ftbitmap.c b/thirdparty/freetype/src/base/ftbitmap.c index 24fead3e15..24fead3e15 100644 --- a/drivers/freetype/src/base/ftbitmap.c +++ b/thirdparty/freetype/src/base/ftbitmap.c diff --git a/drivers/freetype/src/base/ftcalc.c b/thirdparty/freetype/src/base/ftcalc.c index 67549d0c43..67549d0c43 100644 --- a/drivers/freetype/src/base/ftcalc.c +++ b/thirdparty/freetype/src/base/ftcalc.c diff --git a/drivers/freetype/src/base/ftcid.c b/thirdparty/freetype/src/base/ftcid.c index 251bbd009a..251bbd009a 100644 --- a/drivers/freetype/src/base/ftcid.c +++ b/thirdparty/freetype/src/base/ftcid.c diff --git a/drivers/freetype/src/base/ftdbgmem.c b/thirdparty/freetype/src/base/ftdbgmem.c index 6ab5072748..6ab5072748 100644 --- a/drivers/freetype/src/base/ftdbgmem.c +++ b/thirdparty/freetype/src/base/ftdbgmem.c diff --git a/drivers/freetype/src/base/ftdebug.c b/thirdparty/freetype/src/base/ftdebug.c index 40925d14a0..40925d14a0 100644 --- a/drivers/freetype/src/base/ftdebug.c +++ b/thirdparty/freetype/src/base/ftdebug.c diff --git a/drivers/freetype/src/base/ftfntfmt.c b/thirdparty/freetype/src/base/ftfntfmt.c index c6eb3190c6..c6eb3190c6 100644 --- a/drivers/freetype/src/base/ftfntfmt.c +++ b/thirdparty/freetype/src/base/ftfntfmt.c diff --git a/drivers/freetype/src/base/ftfstype.c b/thirdparty/freetype/src/base/ftfstype.c index ae56c8fc8d..ae56c8fc8d 100644 --- a/drivers/freetype/src/base/ftfstype.c +++ b/thirdparty/freetype/src/base/ftfstype.c diff --git a/drivers/freetype/src/base/ftgasp.c b/thirdparty/freetype/src/base/ftgasp.c index e38e55b6c0..e38e55b6c0 100644 --- a/drivers/freetype/src/base/ftgasp.c +++ b/thirdparty/freetype/src/base/ftgasp.c diff --git a/drivers/freetype/src/base/ftgloadr.c b/thirdparty/freetype/src/base/ftgloadr.c index c4f0ff70f4..c4f0ff70f4 100644 --- a/drivers/freetype/src/base/ftgloadr.c +++ b/thirdparty/freetype/src/base/ftgloadr.c diff --git a/drivers/freetype/src/base/ftglyph.c b/thirdparty/freetype/src/base/ftglyph.c index c2376dd03a..c2376dd03a 100644 --- a/drivers/freetype/src/base/ftglyph.c +++ b/thirdparty/freetype/src/base/ftglyph.c diff --git a/drivers/freetype/src/base/ftgxval.c b/thirdparty/freetype/src/base/ftgxval.c index 6667b371a1..6667b371a1 100644 --- a/drivers/freetype/src/base/ftgxval.c +++ b/thirdparty/freetype/src/base/ftgxval.c diff --git a/drivers/freetype/src/base/fthash.c b/thirdparty/freetype/src/base/fthash.c index 21bc8dd5b4..21bc8dd5b4 100644 --- a/drivers/freetype/src/base/fthash.c +++ b/thirdparty/freetype/src/base/fthash.c diff --git a/drivers/freetype/src/base/ftinit.c b/thirdparty/freetype/src/base/ftinit.c index c2dd0a7b37..c2dd0a7b37 100644 --- a/drivers/freetype/src/base/ftinit.c +++ b/thirdparty/freetype/src/base/ftinit.c diff --git a/drivers/freetype/src/base/ftlcdfil.c b/thirdparty/freetype/src/base/ftlcdfil.c index 8bcbed7aab..8bcbed7aab 100644 --- a/drivers/freetype/src/base/ftlcdfil.c +++ b/thirdparty/freetype/src/base/ftlcdfil.c diff --git a/drivers/freetype/src/base/ftmac.c b/thirdparty/freetype/src/base/ftmac.c index e97fdbfc22..e97fdbfc22 100644 --- a/drivers/freetype/src/base/ftmac.c +++ b/thirdparty/freetype/src/base/ftmac.c diff --git a/drivers/freetype/src/base/ftmm.c b/thirdparty/freetype/src/base/ftmm.c index 6b759ca467..6b759ca467 100644 --- a/drivers/freetype/src/base/ftmm.c +++ b/thirdparty/freetype/src/base/ftmm.c diff --git a/drivers/freetype/src/base/ftobjs.c b/thirdparty/freetype/src/base/ftobjs.c index c2dc6183b0..c2dc6183b0 100644 --- a/drivers/freetype/src/base/ftobjs.c +++ b/thirdparty/freetype/src/base/ftobjs.c diff --git a/drivers/freetype/src/base/ftotval.c b/thirdparty/freetype/src/base/ftotval.c index fe54e0228a..fe54e0228a 100644 --- a/drivers/freetype/src/base/ftotval.c +++ b/thirdparty/freetype/src/base/ftotval.c diff --git a/drivers/freetype/src/base/ftoutln.c b/thirdparty/freetype/src/base/ftoutln.c index fc28225c6a..fc28225c6a 100644 --- a/drivers/freetype/src/base/ftoutln.c +++ b/thirdparty/freetype/src/base/ftoutln.c diff --git a/drivers/freetype/src/base/ftpatent.c b/thirdparty/freetype/src/base/ftpatent.c index 4861be130e..4861be130e 100644 --- a/drivers/freetype/src/base/ftpatent.c +++ b/thirdparty/freetype/src/base/ftpatent.c diff --git a/drivers/freetype/src/base/ftpfr.c b/thirdparty/freetype/src/base/ftpfr.c index 81faa529c3..81faa529c3 100644 --- a/drivers/freetype/src/base/ftpfr.c +++ b/thirdparty/freetype/src/base/ftpfr.c diff --git a/drivers/freetype/src/base/ftpic.c b/thirdparty/freetype/src/base/ftpic.c index 03769dba22..03769dba22 100644 --- a/drivers/freetype/src/base/ftpic.c +++ b/thirdparty/freetype/src/base/ftpic.c diff --git a/drivers/freetype/src/base/ftrfork.c b/thirdparty/freetype/src/base/ftrfork.c index 4660c971cf..4660c971cf 100644 --- a/drivers/freetype/src/base/ftrfork.c +++ b/thirdparty/freetype/src/base/ftrfork.c diff --git a/drivers/freetype/src/base/ftsnames.c b/thirdparty/freetype/src/base/ftsnames.c index ce7964118c..ce7964118c 100644 --- a/drivers/freetype/src/base/ftsnames.c +++ b/thirdparty/freetype/src/base/ftsnames.c diff --git a/drivers/freetype/src/base/ftstream.c b/thirdparty/freetype/src/base/ftstream.c index bb512a7ccb..bb512a7ccb 100644 --- a/drivers/freetype/src/base/ftstream.c +++ b/thirdparty/freetype/src/base/ftstream.c diff --git a/drivers/freetype/src/base/ftstroke.c b/thirdparty/freetype/src/base/ftstroke.c index 4f3c4937b5..4f3c4937b5 100644 --- a/drivers/freetype/src/base/ftstroke.c +++ b/thirdparty/freetype/src/base/ftstroke.c diff --git a/drivers/freetype/src/base/ftsynth.c b/thirdparty/freetype/src/base/ftsynth.c index 4b66a33c3f..4b66a33c3f 100644 --- a/drivers/freetype/src/base/ftsynth.c +++ b/thirdparty/freetype/src/base/ftsynth.c diff --git a/drivers/freetype/src/base/ftsystem.c b/thirdparty/freetype/src/base/ftsystem.c index ac1f01c8bc..ac1f01c8bc 100644 --- a/drivers/freetype/src/base/ftsystem.c +++ b/thirdparty/freetype/src/base/ftsystem.c diff --git a/drivers/freetype/src/base/fttrigon.c b/thirdparty/freetype/src/base/fttrigon.c index 7b582c8a3d..7b582c8a3d 100644 --- a/drivers/freetype/src/base/fttrigon.c +++ b/thirdparty/freetype/src/base/fttrigon.c diff --git a/drivers/freetype/src/base/fttype1.c b/thirdparty/freetype/src/base/fttype1.c index 5c0fce8686..5c0fce8686 100644 --- a/drivers/freetype/src/base/fttype1.c +++ b/thirdparty/freetype/src/base/fttype1.c diff --git a/drivers/freetype/src/base/ftutil.c b/thirdparty/freetype/src/base/ftutil.c index fad7d1a5fb..fad7d1a5fb 100644 --- a/drivers/freetype/src/base/ftutil.c +++ b/thirdparty/freetype/src/base/ftutil.c diff --git a/drivers/freetype/src/base/ftwinfnt.c b/thirdparty/freetype/src/base/ftwinfnt.c index 89e9155098..89e9155098 100644 --- a/drivers/freetype/src/base/ftwinfnt.c +++ b/thirdparty/freetype/src/base/ftwinfnt.c diff --git a/drivers/freetype/src/base/md5.c b/thirdparty/freetype/src/base/md5.c index b235e17a56..b235e17a56 100644 --- a/drivers/freetype/src/base/md5.c +++ b/thirdparty/freetype/src/base/md5.c diff --git a/drivers/freetype/src/base/md5.h b/thirdparty/freetype/src/base/md5.h index 2da44bf355..2da44bf355 100644 --- a/drivers/freetype/src/base/md5.h +++ b/thirdparty/freetype/src/base/md5.h diff --git a/drivers/freetype/src/base/rules.mk b/thirdparty/freetype/src/base/rules.mk index aa424c5463..aa424c5463 100644 --- a/drivers/freetype/src/base/rules.mk +++ b/thirdparty/freetype/src/base/rules.mk diff --git a/drivers/freetype/src/bdf/README b/thirdparty/freetype/src/bdf/README index b761aba2b2..b761aba2b2 100644 --- a/drivers/freetype/src/bdf/README +++ b/thirdparty/freetype/src/bdf/README diff --git a/drivers/freetype/src/bdf/bdf.c b/thirdparty/freetype/src/bdf/bdf.c index f95fb76225..f95fb76225 100644 --- a/drivers/freetype/src/bdf/bdf.c +++ b/thirdparty/freetype/src/bdf/bdf.c diff --git a/drivers/freetype/src/bdf/bdf.h b/thirdparty/freetype/src/bdf/bdf.h index 9012727c7e..9012727c7e 100644 --- a/drivers/freetype/src/bdf/bdf.h +++ b/thirdparty/freetype/src/bdf/bdf.h diff --git a/drivers/freetype/src/bdf/bdfdrivr.c b/thirdparty/freetype/src/bdf/bdfdrivr.c index a381cf68f5..a381cf68f5 100644 --- a/drivers/freetype/src/bdf/bdfdrivr.c +++ b/thirdparty/freetype/src/bdf/bdfdrivr.c diff --git a/drivers/freetype/src/bdf/bdfdrivr.h b/thirdparty/freetype/src/bdf/bdfdrivr.h index 94550818c1..94550818c1 100644 --- a/drivers/freetype/src/bdf/bdfdrivr.h +++ b/thirdparty/freetype/src/bdf/bdfdrivr.h diff --git a/drivers/freetype/src/bdf/bdferror.h b/thirdparty/freetype/src/bdf/bdferror.h index b462c7d3b5..b462c7d3b5 100644 --- a/drivers/freetype/src/bdf/bdferror.h +++ b/thirdparty/freetype/src/bdf/bdferror.h diff --git a/drivers/freetype/src/bdf/bdflib.c b/thirdparty/freetype/src/bdf/bdflib.c index e1dce954ff..e1dce954ff 100644 --- a/drivers/freetype/src/bdf/bdflib.c +++ b/thirdparty/freetype/src/bdf/bdflib.c diff --git a/drivers/freetype/src/bdf/module.mk b/thirdparty/freetype/src/bdf/module.mk index fe06ae8e06..fe06ae8e06 100644 --- a/drivers/freetype/src/bdf/module.mk +++ b/thirdparty/freetype/src/bdf/module.mk diff --git a/drivers/freetype/src/bdf/rules.mk b/thirdparty/freetype/src/bdf/rules.mk index d1dd76b1c3..d1dd76b1c3 100644 --- a/drivers/freetype/src/bdf/rules.mk +++ b/thirdparty/freetype/src/bdf/rules.mk diff --git a/drivers/freetype/src/cache/ftcache.c b/thirdparty/freetype/src/cache/ftcache.c index 50941df4c4..50941df4c4 100644 --- a/drivers/freetype/src/cache/ftcache.c +++ b/thirdparty/freetype/src/cache/ftcache.c diff --git a/drivers/freetype/src/cache/ftcbasic.c b/thirdparty/freetype/src/cache/ftcbasic.c index 8e6de8c41c..8e6de8c41c 100644 --- a/drivers/freetype/src/cache/ftcbasic.c +++ b/thirdparty/freetype/src/cache/ftcbasic.c diff --git a/drivers/freetype/src/cache/ftccache.c b/thirdparty/freetype/src/cache/ftccache.c index 3b1a4bc7e4..3b1a4bc7e4 100644 --- a/drivers/freetype/src/cache/ftccache.c +++ b/thirdparty/freetype/src/cache/ftccache.c diff --git a/drivers/freetype/src/cache/ftccache.h b/thirdparty/freetype/src/cache/ftccache.h index 1b1295951f..1b1295951f 100644 --- a/drivers/freetype/src/cache/ftccache.h +++ b/thirdparty/freetype/src/cache/ftccache.h diff --git a/drivers/freetype/src/cache/ftccback.h b/thirdparty/freetype/src/cache/ftccback.h index 279e94d923..279e94d923 100644 --- a/drivers/freetype/src/cache/ftccback.h +++ b/thirdparty/freetype/src/cache/ftccback.h diff --git a/drivers/freetype/src/cache/ftccmap.c b/thirdparty/freetype/src/cache/ftccmap.c index 41a0ce97dd..41a0ce97dd 100644 --- a/drivers/freetype/src/cache/ftccmap.c +++ b/thirdparty/freetype/src/cache/ftccmap.c diff --git a/drivers/freetype/src/cache/ftcerror.h b/thirdparty/freetype/src/cache/ftcerror.h index 1fd7357a8b..1fd7357a8b 100644 --- a/drivers/freetype/src/cache/ftcerror.h +++ b/thirdparty/freetype/src/cache/ftcerror.h diff --git a/drivers/freetype/src/cache/ftcglyph.c b/thirdparty/freetype/src/cache/ftcglyph.c index c4046812dd..c4046812dd 100644 --- a/drivers/freetype/src/cache/ftcglyph.c +++ b/thirdparty/freetype/src/cache/ftcglyph.c diff --git a/drivers/freetype/src/cache/ftcglyph.h b/thirdparty/freetype/src/cache/ftcglyph.h index dc7be06f03..dc7be06f03 100644 --- a/drivers/freetype/src/cache/ftcglyph.h +++ b/thirdparty/freetype/src/cache/ftcglyph.h diff --git a/drivers/freetype/src/cache/ftcimage.c b/thirdparty/freetype/src/cache/ftcimage.c index 74040aa745..74040aa745 100644 --- a/drivers/freetype/src/cache/ftcimage.c +++ b/thirdparty/freetype/src/cache/ftcimage.c diff --git a/drivers/freetype/src/cache/ftcimage.h b/thirdparty/freetype/src/cache/ftcimage.h index 25aa43b97e..25aa43b97e 100644 --- a/drivers/freetype/src/cache/ftcimage.h +++ b/thirdparty/freetype/src/cache/ftcimage.h diff --git a/drivers/freetype/src/cache/ftcmanag.c b/thirdparty/freetype/src/cache/ftcmanag.c index 661a32af5b..661a32af5b 100644 --- a/drivers/freetype/src/cache/ftcmanag.c +++ b/thirdparty/freetype/src/cache/ftcmanag.c diff --git a/drivers/freetype/src/cache/ftcmanag.h b/thirdparty/freetype/src/cache/ftcmanag.h index f2c434a135..f2c434a135 100644 --- a/drivers/freetype/src/cache/ftcmanag.h +++ b/thirdparty/freetype/src/cache/ftcmanag.h diff --git a/drivers/freetype/src/cache/ftcmru.c b/thirdparty/freetype/src/cache/ftcmru.c index d107584a19..d107584a19 100644 --- a/drivers/freetype/src/cache/ftcmru.c +++ b/thirdparty/freetype/src/cache/ftcmru.c diff --git a/drivers/freetype/src/cache/ftcmru.h b/thirdparty/freetype/src/cache/ftcmru.h index ae3c4ce23a..ae3c4ce23a 100644 --- a/drivers/freetype/src/cache/ftcmru.h +++ b/thirdparty/freetype/src/cache/ftcmru.h diff --git a/drivers/freetype/src/cache/ftcsbits.c b/thirdparty/freetype/src/cache/ftcsbits.c index d6f1ddcd4e..d6f1ddcd4e 100644 --- a/drivers/freetype/src/cache/ftcsbits.c +++ b/thirdparty/freetype/src/cache/ftcsbits.c diff --git a/drivers/freetype/src/cache/ftcsbits.h b/thirdparty/freetype/src/cache/ftcsbits.h index a0600ede09..a0600ede09 100644 --- a/drivers/freetype/src/cache/ftcsbits.h +++ b/thirdparty/freetype/src/cache/ftcsbits.h diff --git a/drivers/freetype/src/cache/rules.mk b/thirdparty/freetype/src/cache/rules.mk index 827e259f90..827e259f90 100644 --- a/drivers/freetype/src/cache/rules.mk +++ b/thirdparty/freetype/src/cache/rules.mk diff --git a/drivers/freetype/src/cff/cf2arrst.c b/thirdparty/freetype/src/cff/cf2arrst.c index 89f3e9f1d7..89f3e9f1d7 100644 --- a/drivers/freetype/src/cff/cf2arrst.c +++ b/thirdparty/freetype/src/cff/cf2arrst.c diff --git a/drivers/freetype/src/cff/cf2arrst.h b/thirdparty/freetype/src/cff/cf2arrst.h index 3c21a3b672..3c21a3b672 100644 --- a/drivers/freetype/src/cff/cf2arrst.h +++ b/thirdparty/freetype/src/cff/cf2arrst.h diff --git a/drivers/freetype/src/cff/cf2blues.c b/thirdparty/freetype/src/cff/cf2blues.c index 250f89e0df..250f89e0df 100644 --- a/drivers/freetype/src/cff/cf2blues.c +++ b/thirdparty/freetype/src/cff/cf2blues.c diff --git a/drivers/freetype/src/cff/cf2blues.h b/thirdparty/freetype/src/cff/cf2blues.h index 96fb60f38d..96fb60f38d 100644 --- a/drivers/freetype/src/cff/cf2blues.h +++ b/thirdparty/freetype/src/cff/cf2blues.h diff --git a/drivers/freetype/src/cff/cf2error.c b/thirdparty/freetype/src/cff/cf2error.c index b5595a3d1f..b5595a3d1f 100644 --- a/drivers/freetype/src/cff/cf2error.c +++ b/thirdparty/freetype/src/cff/cf2error.c diff --git a/drivers/freetype/src/cff/cf2error.h b/thirdparty/freetype/src/cff/cf2error.h index 512edd1d21..512edd1d21 100644 --- a/drivers/freetype/src/cff/cf2error.h +++ b/thirdparty/freetype/src/cff/cf2error.h diff --git a/drivers/freetype/src/cff/cf2fixed.h b/thirdparty/freetype/src/cff/cf2fixed.h index 74af37708b..74af37708b 100644 --- a/drivers/freetype/src/cff/cf2fixed.h +++ b/thirdparty/freetype/src/cff/cf2fixed.h diff --git a/drivers/freetype/src/cff/cf2font.c b/thirdparty/freetype/src/cff/cf2font.c index 83fd348f2d..83fd348f2d 100644 --- a/drivers/freetype/src/cff/cf2font.c +++ b/thirdparty/freetype/src/cff/cf2font.c diff --git a/drivers/freetype/src/cff/cf2font.h b/thirdparty/freetype/src/cff/cf2font.h index bd05e69e7b..bd05e69e7b 100644 --- a/drivers/freetype/src/cff/cf2font.h +++ b/thirdparty/freetype/src/cff/cf2font.h diff --git a/drivers/freetype/src/cff/cf2ft.c b/thirdparty/freetype/src/cff/cf2ft.c index 55f3206ac2..55f3206ac2 100644 --- a/drivers/freetype/src/cff/cf2ft.c +++ b/thirdparty/freetype/src/cff/cf2ft.c diff --git a/drivers/freetype/src/cff/cf2ft.h b/thirdparty/freetype/src/cff/cf2ft.h index 8e55e841a0..8e55e841a0 100644 --- a/drivers/freetype/src/cff/cf2ft.h +++ b/thirdparty/freetype/src/cff/cf2ft.h diff --git a/drivers/freetype/src/cff/cf2glue.h b/thirdparty/freetype/src/cff/cf2glue.h index 56a7c248f4..56a7c248f4 100644 --- a/drivers/freetype/src/cff/cf2glue.h +++ b/thirdparty/freetype/src/cff/cf2glue.h diff --git a/drivers/freetype/src/cff/cf2hints.c b/thirdparty/freetype/src/cff/cf2hints.c index bbbe8e3c32..bbbe8e3c32 100644 --- a/drivers/freetype/src/cff/cf2hints.c +++ b/thirdparty/freetype/src/cff/cf2hints.c diff --git a/drivers/freetype/src/cff/cf2hints.h b/thirdparty/freetype/src/cff/cf2hints.h index a8984542a0..a8984542a0 100644 --- a/drivers/freetype/src/cff/cf2hints.h +++ b/thirdparty/freetype/src/cff/cf2hints.h diff --git a/drivers/freetype/src/cff/cf2intrp.c b/thirdparty/freetype/src/cff/cf2intrp.c index 7d663dd0ec..7d663dd0ec 100644 --- a/drivers/freetype/src/cff/cf2intrp.c +++ b/thirdparty/freetype/src/cff/cf2intrp.c diff --git a/drivers/freetype/src/cff/cf2intrp.h b/thirdparty/freetype/src/cff/cf2intrp.h index ec030e8944..ec030e8944 100644 --- a/drivers/freetype/src/cff/cf2intrp.h +++ b/thirdparty/freetype/src/cff/cf2intrp.h diff --git a/drivers/freetype/src/cff/cf2read.c b/thirdparty/freetype/src/cff/cf2read.c index 2b429e3eeb..2b429e3eeb 100644 --- a/drivers/freetype/src/cff/cf2read.c +++ b/thirdparty/freetype/src/cff/cf2read.c diff --git a/drivers/freetype/src/cff/cf2read.h b/thirdparty/freetype/src/cff/cf2read.h index b0b0db803a..b0b0db803a 100644 --- a/drivers/freetype/src/cff/cf2read.h +++ b/thirdparty/freetype/src/cff/cf2read.h diff --git a/drivers/freetype/src/cff/cf2stack.c b/thirdparty/freetype/src/cff/cf2stack.c index 6fafd901f3..6fafd901f3 100644 --- a/drivers/freetype/src/cff/cf2stack.c +++ b/thirdparty/freetype/src/cff/cf2stack.c diff --git a/drivers/freetype/src/cff/cf2stack.h b/thirdparty/freetype/src/cff/cf2stack.h index e740a7ac41..e740a7ac41 100644 --- a/drivers/freetype/src/cff/cf2stack.h +++ b/thirdparty/freetype/src/cff/cf2stack.h diff --git a/drivers/freetype/src/cff/cf2types.h b/thirdparty/freetype/src/cff/cf2types.h index 5b7e1239af..5b7e1239af 100644 --- a/drivers/freetype/src/cff/cf2types.h +++ b/thirdparty/freetype/src/cff/cf2types.h diff --git a/drivers/freetype/src/cff/cff.c b/thirdparty/freetype/src/cff/cff.c index 86ca1be040..86ca1be040 100644 --- a/drivers/freetype/src/cff/cff.c +++ b/thirdparty/freetype/src/cff/cff.c diff --git a/drivers/freetype/src/cff/cffcmap.c b/thirdparty/freetype/src/cff/cffcmap.c index 3ef48328c5..3ef48328c5 100644 --- a/drivers/freetype/src/cff/cffcmap.c +++ b/thirdparty/freetype/src/cff/cffcmap.c diff --git a/drivers/freetype/src/cff/cffcmap.h b/thirdparty/freetype/src/cff/cffcmap.h index 23795d5090..23795d5090 100644 --- a/drivers/freetype/src/cff/cffcmap.h +++ b/thirdparty/freetype/src/cff/cffcmap.h diff --git a/drivers/freetype/src/cff/cffdrivr.c b/thirdparty/freetype/src/cff/cffdrivr.c index 950a9605c3..950a9605c3 100644 --- a/drivers/freetype/src/cff/cffdrivr.c +++ b/thirdparty/freetype/src/cff/cffdrivr.c diff --git a/drivers/freetype/src/cff/cffdrivr.h b/thirdparty/freetype/src/cff/cffdrivr.h index d7b0598374..d7b0598374 100644 --- a/drivers/freetype/src/cff/cffdrivr.h +++ b/thirdparty/freetype/src/cff/cffdrivr.h diff --git a/drivers/freetype/src/cff/cfferrs.h b/thirdparty/freetype/src/cff/cfferrs.h index e7fc6eb71c..e7fc6eb71c 100644 --- a/drivers/freetype/src/cff/cfferrs.h +++ b/thirdparty/freetype/src/cff/cfferrs.h diff --git a/drivers/freetype/src/cff/cffgload.c b/thirdparty/freetype/src/cff/cffgload.c index 752c18ed92..752c18ed92 100644 --- a/drivers/freetype/src/cff/cffgload.c +++ b/thirdparty/freetype/src/cff/cffgload.c diff --git a/drivers/freetype/src/cff/cffgload.h b/thirdparty/freetype/src/cff/cffgload.h index b875fbed90..b875fbed90 100644 --- a/drivers/freetype/src/cff/cffgload.h +++ b/thirdparty/freetype/src/cff/cffgload.h diff --git a/drivers/freetype/src/cff/cffload.c b/thirdparty/freetype/src/cff/cffload.c index 3d1bda97b9..3d1bda97b9 100644 --- a/drivers/freetype/src/cff/cffload.c +++ b/thirdparty/freetype/src/cff/cffload.c diff --git a/drivers/freetype/src/cff/cffload.h b/thirdparty/freetype/src/cff/cffload.h index 1dd07baf11..1dd07baf11 100644 --- a/drivers/freetype/src/cff/cffload.h +++ b/thirdparty/freetype/src/cff/cffload.h diff --git a/drivers/freetype/src/cff/cffobjs.c b/thirdparty/freetype/src/cff/cffobjs.c index 0f0769677f..0f0769677f 100644 --- a/drivers/freetype/src/cff/cffobjs.c +++ b/thirdparty/freetype/src/cff/cffobjs.c diff --git a/drivers/freetype/src/cff/cffobjs.h b/thirdparty/freetype/src/cff/cffobjs.h index 9dc77536bd..9dc77536bd 100644 --- a/drivers/freetype/src/cff/cffobjs.h +++ b/thirdparty/freetype/src/cff/cffobjs.h diff --git a/drivers/freetype/src/cff/cffparse.c b/thirdparty/freetype/src/cff/cffparse.c index a4f986b67c..a4f986b67c 100644 --- a/drivers/freetype/src/cff/cffparse.c +++ b/thirdparty/freetype/src/cff/cffparse.c diff --git a/drivers/freetype/src/cff/cffparse.h b/thirdparty/freetype/src/cff/cffparse.h index a95970edcb..a95970edcb 100644 --- a/drivers/freetype/src/cff/cffparse.h +++ b/thirdparty/freetype/src/cff/cffparse.h diff --git a/drivers/freetype/src/cff/cffpic.c b/thirdparty/freetype/src/cff/cffpic.c index a0bc34fd5f..a0bc34fd5f 100644 --- a/drivers/freetype/src/cff/cffpic.c +++ b/thirdparty/freetype/src/cff/cffpic.c diff --git a/drivers/freetype/src/cff/cffpic.h b/thirdparty/freetype/src/cff/cffpic.h index bed6b35a86..bed6b35a86 100644 --- a/drivers/freetype/src/cff/cffpic.h +++ b/thirdparty/freetype/src/cff/cffpic.h diff --git a/drivers/freetype/src/cff/cfftoken.h b/thirdparty/freetype/src/cff/cfftoken.h index 22637c780b..22637c780b 100644 --- a/drivers/freetype/src/cff/cfftoken.h +++ b/thirdparty/freetype/src/cff/cfftoken.h diff --git a/drivers/freetype/src/cff/cfftypes.h b/thirdparty/freetype/src/cff/cfftypes.h index 4426c7e4f1..4426c7e4f1 100644 --- a/drivers/freetype/src/cff/cfftypes.h +++ b/thirdparty/freetype/src/cff/cfftypes.h diff --git a/drivers/freetype/src/cff/module.mk b/thirdparty/freetype/src/cff/module.mk index 1b4781afed..1b4781afed 100644 --- a/drivers/freetype/src/cff/module.mk +++ b/thirdparty/freetype/src/cff/module.mk diff --git a/drivers/freetype/src/cff/rules.mk b/thirdparty/freetype/src/cff/rules.mk index 92f68b1ede..92f68b1ede 100644 --- a/drivers/freetype/src/cff/rules.mk +++ b/thirdparty/freetype/src/cff/rules.mk diff --git a/drivers/freetype/src/cid/ciderrs.h b/thirdparty/freetype/src/cid/ciderrs.h index 1dc98c7cdd..1dc98c7cdd 100644 --- a/drivers/freetype/src/cid/ciderrs.h +++ b/thirdparty/freetype/src/cid/ciderrs.h diff --git a/drivers/freetype/src/cid/cidgload.c b/thirdparty/freetype/src/cid/cidgload.c index c7b95593ee..c7b95593ee 100644 --- a/drivers/freetype/src/cid/cidgload.c +++ b/thirdparty/freetype/src/cid/cidgload.c diff --git a/drivers/freetype/src/cid/cidgload.h b/thirdparty/freetype/src/cid/cidgload.h index 62d664b3af..62d664b3af 100644 --- a/drivers/freetype/src/cid/cidgload.h +++ b/thirdparty/freetype/src/cid/cidgload.h diff --git a/drivers/freetype/src/cid/cidload.c b/thirdparty/freetype/src/cid/cidload.c index d4f1ad1a7f..d4f1ad1a7f 100644 --- a/drivers/freetype/src/cid/cidload.c +++ b/thirdparty/freetype/src/cid/cidload.c diff --git a/drivers/freetype/src/cid/cidload.h b/thirdparty/freetype/src/cid/cidload.h index 680f0d8fc5..680f0d8fc5 100644 --- a/drivers/freetype/src/cid/cidload.h +++ b/thirdparty/freetype/src/cid/cidload.h diff --git a/drivers/freetype/src/cid/cidobjs.c b/thirdparty/freetype/src/cid/cidobjs.c index 2d2600fd4c..2d2600fd4c 100644 --- a/drivers/freetype/src/cid/cidobjs.c +++ b/thirdparty/freetype/src/cid/cidobjs.c diff --git a/drivers/freetype/src/cid/cidobjs.h b/thirdparty/freetype/src/cid/cidobjs.h index 5dd377a9f8..5dd377a9f8 100644 --- a/drivers/freetype/src/cid/cidobjs.h +++ b/thirdparty/freetype/src/cid/cidobjs.h diff --git a/drivers/freetype/src/cid/cidparse.c b/thirdparty/freetype/src/cid/cidparse.c index 73aca2ac6a..73aca2ac6a 100644 --- a/drivers/freetype/src/cid/cidparse.c +++ b/thirdparty/freetype/src/cid/cidparse.c diff --git a/drivers/freetype/src/cid/cidparse.h b/thirdparty/freetype/src/cid/cidparse.h index 7268dc6ae8..7268dc6ae8 100644 --- a/drivers/freetype/src/cid/cidparse.h +++ b/thirdparty/freetype/src/cid/cidparse.h diff --git a/drivers/freetype/src/cid/cidriver.c b/thirdparty/freetype/src/cid/cidriver.c index 64141ab6b1..64141ab6b1 100644 --- a/drivers/freetype/src/cid/cidriver.c +++ b/thirdparty/freetype/src/cid/cidriver.c diff --git a/drivers/freetype/src/cid/cidriver.h b/thirdparty/freetype/src/cid/cidriver.h index a359a78907..a359a78907 100644 --- a/drivers/freetype/src/cid/cidriver.h +++ b/thirdparty/freetype/src/cid/cidriver.h diff --git a/drivers/freetype/src/cid/cidtoken.h b/thirdparty/freetype/src/cid/cidtoken.h index 9c773fd094..9c773fd094 100644 --- a/drivers/freetype/src/cid/cidtoken.h +++ b/thirdparty/freetype/src/cid/cidtoken.h diff --git a/drivers/freetype/src/cid/module.mk b/thirdparty/freetype/src/cid/module.mk index d9585d7816..d9585d7816 100644 --- a/drivers/freetype/src/cid/module.mk +++ b/thirdparty/freetype/src/cid/module.mk diff --git a/drivers/freetype/src/cid/rules.mk b/thirdparty/freetype/src/cid/rules.mk index f33aab00d6..f33aab00d6 100644 --- a/drivers/freetype/src/cid/rules.mk +++ b/thirdparty/freetype/src/cid/rules.mk diff --git a/drivers/freetype/src/cid/type1cid.c b/thirdparty/freetype/src/cid/type1cid.c index de3bdf7705..de3bdf7705 100644 --- a/drivers/freetype/src/cid/type1cid.c +++ b/thirdparty/freetype/src/cid/type1cid.c diff --git a/drivers/freetype/src/gxvalid/README b/thirdparty/freetype/src/gxvalid/README index d3ac49c3e2..d3ac49c3e2 100644 --- a/drivers/freetype/src/gxvalid/README +++ b/thirdparty/freetype/src/gxvalid/README diff --git a/drivers/freetype/src/gxvalid/gxvalid.c b/thirdparty/freetype/src/gxvalid/gxvalid.c index 7fb868cad1..7fb868cad1 100644 --- a/drivers/freetype/src/gxvalid/gxvalid.c +++ b/thirdparty/freetype/src/gxvalid/gxvalid.c diff --git a/drivers/freetype/src/gxvalid/gxvalid.h b/thirdparty/freetype/src/gxvalid/gxvalid.h index 7a3ab795ef..7a3ab795ef 100644 --- a/drivers/freetype/src/gxvalid/gxvalid.h +++ b/thirdparty/freetype/src/gxvalid/gxvalid.h diff --git a/drivers/freetype/src/gxvalid/gxvbsln.c b/thirdparty/freetype/src/gxvalid/gxvbsln.c index 493b20c31a..493b20c31a 100644 --- a/drivers/freetype/src/gxvalid/gxvbsln.c +++ b/thirdparty/freetype/src/gxvalid/gxvbsln.c diff --git a/drivers/freetype/src/gxvalid/gxvcommn.c b/thirdparty/freetype/src/gxvalid/gxvcommn.c index 4b5e41539a..4b5e41539a 100644 --- a/drivers/freetype/src/gxvalid/gxvcommn.c +++ b/thirdparty/freetype/src/gxvalid/gxvcommn.c diff --git a/drivers/freetype/src/gxvalid/gxvcommn.h b/thirdparty/freetype/src/gxvalid/gxvcommn.h index 9470c8412b..9470c8412b 100644 --- a/drivers/freetype/src/gxvalid/gxvcommn.h +++ b/thirdparty/freetype/src/gxvalid/gxvcommn.h diff --git a/drivers/freetype/src/gxvalid/gxverror.h b/thirdparty/freetype/src/gxvalid/gxverror.h index 2e53355ce4..2e53355ce4 100644 --- a/drivers/freetype/src/gxvalid/gxverror.h +++ b/thirdparty/freetype/src/gxvalid/gxverror.h diff --git a/drivers/freetype/src/gxvalid/gxvfeat.c b/thirdparty/freetype/src/gxvalid/gxvfeat.c index 5bff7c261d..5bff7c261d 100644 --- a/drivers/freetype/src/gxvalid/gxvfeat.c +++ b/thirdparty/freetype/src/gxvalid/gxvfeat.c diff --git a/drivers/freetype/src/gxvalid/gxvfeat.h b/thirdparty/freetype/src/gxvalid/gxvfeat.h index 284bada891..284bada891 100644 --- a/drivers/freetype/src/gxvalid/gxvfeat.h +++ b/thirdparty/freetype/src/gxvalid/gxvfeat.h diff --git a/drivers/freetype/src/gxvalid/gxvfgen.c b/thirdparty/freetype/src/gxvalid/gxvfgen.c index 667dac3cde..667dac3cde 100644 --- a/drivers/freetype/src/gxvalid/gxvfgen.c +++ b/thirdparty/freetype/src/gxvalid/gxvfgen.c diff --git a/drivers/freetype/src/gxvalid/gxvjust.c b/thirdparty/freetype/src/gxvalid/gxvjust.c index 20d29bfbc8..20d29bfbc8 100644 --- a/drivers/freetype/src/gxvalid/gxvjust.c +++ b/thirdparty/freetype/src/gxvalid/gxvjust.c diff --git a/drivers/freetype/src/gxvalid/gxvkern.c b/thirdparty/freetype/src/gxvalid/gxvkern.c index ee1ab36f70..ee1ab36f70 100644 --- a/drivers/freetype/src/gxvalid/gxvkern.c +++ b/thirdparty/freetype/src/gxvalid/gxvkern.c diff --git a/drivers/freetype/src/gxvalid/gxvlcar.c b/thirdparty/freetype/src/gxvalid/gxvlcar.c index d31b6410bd..d31b6410bd 100644 --- a/drivers/freetype/src/gxvalid/gxvlcar.c +++ b/thirdparty/freetype/src/gxvalid/gxvlcar.c diff --git a/drivers/freetype/src/gxvalid/gxvmod.c b/thirdparty/freetype/src/gxvalid/gxvmod.c index e589a7fb79..e589a7fb79 100644 --- a/drivers/freetype/src/gxvalid/gxvmod.c +++ b/thirdparty/freetype/src/gxvalid/gxvmod.c diff --git a/drivers/freetype/src/gxvalid/gxvmod.h b/thirdparty/freetype/src/gxvalid/gxvmod.h index 8b82e91070..8b82e91070 100644 --- a/drivers/freetype/src/gxvalid/gxvmod.h +++ b/thirdparty/freetype/src/gxvalid/gxvmod.h diff --git a/drivers/freetype/src/gxvalid/gxvmort.c b/thirdparty/freetype/src/gxvalid/gxvmort.c index b83a2b2c0f..b83a2b2c0f 100644 --- a/drivers/freetype/src/gxvalid/gxvmort.c +++ b/thirdparty/freetype/src/gxvalid/gxvmort.c diff --git a/drivers/freetype/src/gxvalid/gxvmort.h b/thirdparty/freetype/src/gxvalid/gxvmort.h index 5fd228212a..5fd228212a 100644 --- a/drivers/freetype/src/gxvalid/gxvmort.h +++ b/thirdparty/freetype/src/gxvalid/gxvmort.h diff --git a/drivers/freetype/src/gxvalid/gxvmort0.c b/thirdparty/freetype/src/gxvalid/gxvmort0.c index e11f5ddc49..e11f5ddc49 100644 --- a/drivers/freetype/src/gxvalid/gxvmort0.c +++ b/thirdparty/freetype/src/gxvalid/gxvmort0.c diff --git a/drivers/freetype/src/gxvalid/gxvmort1.c b/thirdparty/freetype/src/gxvalid/gxvmort1.c index fd761d0692..fd761d0692 100644 --- a/drivers/freetype/src/gxvalid/gxvmort1.c +++ b/thirdparty/freetype/src/gxvalid/gxvmort1.c diff --git a/drivers/freetype/src/gxvalid/gxvmort2.c b/thirdparty/freetype/src/gxvalid/gxvmort2.c index 08455dec6b..08455dec6b 100644 --- a/drivers/freetype/src/gxvalid/gxvmort2.c +++ b/thirdparty/freetype/src/gxvalid/gxvmort2.c diff --git a/drivers/freetype/src/gxvalid/gxvmort4.c b/thirdparty/freetype/src/gxvalid/gxvmort4.c index 6f7bbb8710..6f7bbb8710 100644 --- a/drivers/freetype/src/gxvalid/gxvmort4.c +++ b/thirdparty/freetype/src/gxvalid/gxvmort4.c diff --git a/drivers/freetype/src/gxvalid/gxvmort5.c b/thirdparty/freetype/src/gxvalid/gxvmort5.c index 54ddbe2b15..54ddbe2b15 100644 --- a/drivers/freetype/src/gxvalid/gxvmort5.c +++ b/thirdparty/freetype/src/gxvalid/gxvmort5.c diff --git a/drivers/freetype/src/gxvalid/gxvmorx.c b/thirdparty/freetype/src/gxvalid/gxvmorx.c index a3abe435a6..a3abe435a6 100644 --- a/drivers/freetype/src/gxvalid/gxvmorx.c +++ b/thirdparty/freetype/src/gxvalid/gxvmorx.c diff --git a/drivers/freetype/src/gxvalid/gxvmorx.h b/thirdparty/freetype/src/gxvalid/gxvmorx.h index 9ba25c14a4..9ba25c14a4 100644 --- a/drivers/freetype/src/gxvalid/gxvmorx.h +++ b/thirdparty/freetype/src/gxvalid/gxvmorx.h diff --git a/drivers/freetype/src/gxvalid/gxvmorx0.c b/thirdparty/freetype/src/gxvalid/gxvmorx0.c index 4abb7368f2..4abb7368f2 100644 --- a/drivers/freetype/src/gxvalid/gxvmorx0.c +++ b/thirdparty/freetype/src/gxvalid/gxvmorx0.c diff --git a/drivers/freetype/src/gxvalid/gxvmorx1.c b/thirdparty/freetype/src/gxvalid/gxvmorx1.c index e581848c2b..e581848c2b 100644 --- a/drivers/freetype/src/gxvalid/gxvmorx1.c +++ b/thirdparty/freetype/src/gxvalid/gxvmorx1.c diff --git a/drivers/freetype/src/gxvalid/gxvmorx2.c b/thirdparty/freetype/src/gxvalid/gxvmorx2.c index 9495cca489..9495cca489 100644 --- a/drivers/freetype/src/gxvalid/gxvmorx2.c +++ b/thirdparty/freetype/src/gxvalid/gxvmorx2.c diff --git a/drivers/freetype/src/gxvalid/gxvmorx4.c b/thirdparty/freetype/src/gxvalid/gxvmorx4.c index 3b7731bbce..3b7731bbce 100644 --- a/drivers/freetype/src/gxvalid/gxvmorx4.c +++ b/thirdparty/freetype/src/gxvalid/gxvmorx4.c diff --git a/drivers/freetype/src/gxvalid/gxvmorx5.c b/thirdparty/freetype/src/gxvalid/gxvmorx5.c index 0e96166c02..0e96166c02 100644 --- a/drivers/freetype/src/gxvalid/gxvmorx5.c +++ b/thirdparty/freetype/src/gxvalid/gxvmorx5.c diff --git a/drivers/freetype/src/gxvalid/gxvopbd.c b/thirdparty/freetype/src/gxvalid/gxvopbd.c index e3ba082e16..e3ba082e16 100644 --- a/drivers/freetype/src/gxvalid/gxvopbd.c +++ b/thirdparty/freetype/src/gxvalid/gxvopbd.c diff --git a/drivers/freetype/src/gxvalid/gxvprop.c b/thirdparty/freetype/src/gxvalid/gxvprop.c index 61b3aeee30..61b3aeee30 100644 --- a/drivers/freetype/src/gxvalid/gxvprop.c +++ b/thirdparty/freetype/src/gxvalid/gxvprop.c diff --git a/drivers/freetype/src/gxvalid/gxvtrak.c b/thirdparty/freetype/src/gxvalid/gxvtrak.c index 0f07c04e2a..0f07c04e2a 100644 --- a/drivers/freetype/src/gxvalid/gxvtrak.c +++ b/thirdparty/freetype/src/gxvalid/gxvtrak.c diff --git a/drivers/freetype/src/gxvalid/module.mk b/thirdparty/freetype/src/gxvalid/module.mk index b431384a5c..b431384a5c 100644 --- a/drivers/freetype/src/gxvalid/module.mk +++ b/thirdparty/freetype/src/gxvalid/module.mk diff --git a/drivers/freetype/src/gxvalid/rules.mk b/thirdparty/freetype/src/gxvalid/rules.mk index 424f2a6377..424f2a6377 100644 --- a/drivers/freetype/src/gxvalid/rules.mk +++ b/thirdparty/freetype/src/gxvalid/rules.mk diff --git a/drivers/freetype/src/otvalid/module.mk b/thirdparty/freetype/src/otvalid/module.mk index b929cdbab0..b929cdbab0 100644 --- a/drivers/freetype/src/otvalid/module.mk +++ b/thirdparty/freetype/src/otvalid/module.mk diff --git a/drivers/freetype/src/otvalid/otvalid.c b/thirdparty/freetype/src/otvalid/otvalid.c index 932a974a31..932a974a31 100644 --- a/drivers/freetype/src/otvalid/otvalid.c +++ b/thirdparty/freetype/src/otvalid/otvalid.c diff --git a/drivers/freetype/src/otvalid/otvalid.h b/thirdparty/freetype/src/otvalid/otvalid.h index 93438a0639..93438a0639 100644 --- a/drivers/freetype/src/otvalid/otvalid.h +++ b/thirdparty/freetype/src/otvalid/otvalid.h diff --git a/drivers/freetype/src/otvalid/otvbase.c b/thirdparty/freetype/src/otvalid/otvbase.c index e86e8bb2f0..e86e8bb2f0 100644 --- a/drivers/freetype/src/otvalid/otvbase.c +++ b/thirdparty/freetype/src/otvalid/otvbase.c diff --git a/drivers/freetype/src/otvalid/otvcommn.c b/thirdparty/freetype/src/otvalid/otvcommn.c index 2e88e102be..2e88e102be 100644 --- a/drivers/freetype/src/otvalid/otvcommn.c +++ b/thirdparty/freetype/src/otvalid/otvcommn.c diff --git a/drivers/freetype/src/otvalid/otvcommn.h b/thirdparty/freetype/src/otvalid/otvcommn.h index 44e0c63793..44e0c63793 100644 --- a/drivers/freetype/src/otvalid/otvcommn.h +++ b/thirdparty/freetype/src/otvalid/otvcommn.h diff --git a/drivers/freetype/src/otvalid/otverror.h b/thirdparty/freetype/src/otvalid/otverror.h index e7c8db0d58..e7c8db0d58 100644 --- a/drivers/freetype/src/otvalid/otverror.h +++ b/thirdparty/freetype/src/otvalid/otverror.h diff --git a/drivers/freetype/src/otvalid/otvgdef.c b/thirdparty/freetype/src/otvalid/otvgdef.c index f19e300e51..f19e300e51 100644 --- a/drivers/freetype/src/otvalid/otvgdef.c +++ b/thirdparty/freetype/src/otvalid/otvgdef.c diff --git a/drivers/freetype/src/otvalid/otvgpos.c b/thirdparty/freetype/src/otvalid/otvgpos.c index e904ea5d6c..e904ea5d6c 100644 --- a/drivers/freetype/src/otvalid/otvgpos.c +++ b/thirdparty/freetype/src/otvalid/otvgpos.c diff --git a/drivers/freetype/src/otvalid/otvgpos.h b/thirdparty/freetype/src/otvalid/otvgpos.h index 2c09e64f97..2c09e64f97 100644 --- a/drivers/freetype/src/otvalid/otvgpos.h +++ b/thirdparty/freetype/src/otvalid/otvgpos.h diff --git a/drivers/freetype/src/otvalid/otvgsub.c b/thirdparty/freetype/src/otvalid/otvgsub.c index c2b28569f1..c2b28569f1 100644 --- a/drivers/freetype/src/otvalid/otvgsub.c +++ b/thirdparty/freetype/src/otvalid/otvgsub.c diff --git a/drivers/freetype/src/otvalid/otvjstf.c b/thirdparty/freetype/src/otvalid/otvjstf.c index e19c1c1213..e19c1c1213 100644 --- a/drivers/freetype/src/otvalid/otvjstf.c +++ b/thirdparty/freetype/src/otvalid/otvjstf.c diff --git a/drivers/freetype/src/otvalid/otvmath.c b/thirdparty/freetype/src/otvalid/otvmath.c index 6c785b6fda..6c785b6fda 100644 --- a/drivers/freetype/src/otvalid/otvmath.c +++ b/thirdparty/freetype/src/otvalid/otvmath.c diff --git a/drivers/freetype/src/otvalid/otvmod.c b/thirdparty/freetype/src/otvalid/otvmod.c index 972bd1baac..972bd1baac 100644 --- a/drivers/freetype/src/otvalid/otvmod.c +++ b/thirdparty/freetype/src/otvalid/otvmod.c diff --git a/drivers/freetype/src/otvalid/otvmod.h b/thirdparty/freetype/src/otvalid/otvmod.h index e464030ab0..e464030ab0 100644 --- a/drivers/freetype/src/otvalid/otvmod.h +++ b/thirdparty/freetype/src/otvalid/otvmod.h diff --git a/drivers/freetype/src/otvalid/rules.mk b/thirdparty/freetype/src/otvalid/rules.mk index 077447fcb6..077447fcb6 100644 --- a/drivers/freetype/src/otvalid/rules.mk +++ b/thirdparty/freetype/src/otvalid/rules.mk diff --git a/drivers/freetype/src/pcf/README b/thirdparty/freetype/src/pcf/README index 10eff15fbe..10eff15fbe 100644 --- a/drivers/freetype/src/pcf/README +++ b/thirdparty/freetype/src/pcf/README diff --git a/drivers/freetype/src/pcf/module.mk b/thirdparty/freetype/src/pcf/module.mk index df383ff0fb..df383ff0fb 100644 --- a/drivers/freetype/src/pcf/module.mk +++ b/thirdparty/freetype/src/pcf/module.mk diff --git a/drivers/freetype/src/pcf/pcf.c b/thirdparty/freetype/src/pcf/pcf.c index 11d5b7b2a0..11d5b7b2a0 100644 --- a/drivers/freetype/src/pcf/pcf.c +++ b/thirdparty/freetype/src/pcf/pcf.c diff --git a/drivers/freetype/src/pcf/pcf.h b/thirdparty/freetype/src/pcf/pcf.h index c726e5ec6b..c726e5ec6b 100644 --- a/drivers/freetype/src/pcf/pcf.h +++ b/thirdparty/freetype/src/pcf/pcf.h diff --git a/drivers/freetype/src/pcf/pcfdrivr.c b/thirdparty/freetype/src/pcf/pcfdrivr.c index 0996d10793..0996d10793 100644 --- a/drivers/freetype/src/pcf/pcfdrivr.c +++ b/thirdparty/freetype/src/pcf/pcfdrivr.c diff --git a/drivers/freetype/src/pcf/pcfdrivr.h b/thirdparty/freetype/src/pcf/pcfdrivr.h index 29d30497cd..29d30497cd 100644 --- a/drivers/freetype/src/pcf/pcfdrivr.h +++ b/thirdparty/freetype/src/pcf/pcfdrivr.h diff --git a/drivers/freetype/src/pcf/pcferror.h b/thirdparty/freetype/src/pcf/pcferror.h index add8ef2230..add8ef2230 100644 --- a/drivers/freetype/src/pcf/pcferror.h +++ b/thirdparty/freetype/src/pcf/pcferror.h diff --git a/drivers/freetype/src/pcf/pcfread.c b/thirdparty/freetype/src/pcf/pcfread.c index a86b45d6bf..a86b45d6bf 100644 --- a/drivers/freetype/src/pcf/pcfread.c +++ b/thirdparty/freetype/src/pcf/pcfread.c diff --git a/drivers/freetype/src/pcf/pcfread.h b/thirdparty/freetype/src/pcf/pcfread.h index bed30e5030..bed30e5030 100644 --- a/drivers/freetype/src/pcf/pcfread.h +++ b/thirdparty/freetype/src/pcf/pcfread.h diff --git a/drivers/freetype/src/pcf/pcfutil.c b/thirdparty/freetype/src/pcf/pcfutil.c index 0451ee8def..0451ee8def 100644 --- a/drivers/freetype/src/pcf/pcfutil.c +++ b/thirdparty/freetype/src/pcf/pcfutil.c diff --git a/drivers/freetype/src/pcf/pcfutil.h b/thirdparty/freetype/src/pcf/pcfutil.h index be986e756b..be986e756b 100644 --- a/drivers/freetype/src/pcf/pcfutil.h +++ b/thirdparty/freetype/src/pcf/pcfutil.h diff --git a/drivers/freetype/src/pcf/rules.mk b/thirdparty/freetype/src/pcf/rules.mk index 1b55daf4f4..1b55daf4f4 100644 --- a/drivers/freetype/src/pcf/rules.mk +++ b/thirdparty/freetype/src/pcf/rules.mk diff --git a/drivers/freetype/src/pfr/module.mk b/thirdparty/freetype/src/pfr/module.mk index bf7808c72f..bf7808c72f 100644 --- a/drivers/freetype/src/pfr/module.mk +++ b/thirdparty/freetype/src/pfr/module.mk diff --git a/drivers/freetype/src/pfr/pfr.c b/thirdparty/freetype/src/pfr/pfr.c index 1a433960a5..1a433960a5 100644 --- a/drivers/freetype/src/pfr/pfr.c +++ b/thirdparty/freetype/src/pfr/pfr.c diff --git a/drivers/freetype/src/pfr/pfrcmap.c b/thirdparty/freetype/src/pfr/pfrcmap.c index a1439c2e9f..a1439c2e9f 100644 --- a/drivers/freetype/src/pfr/pfrcmap.c +++ b/thirdparty/freetype/src/pfr/pfrcmap.c diff --git a/drivers/freetype/src/pfr/pfrcmap.h b/thirdparty/freetype/src/pfr/pfrcmap.h index 4a8a4d0a67..4a8a4d0a67 100644 --- a/drivers/freetype/src/pfr/pfrcmap.h +++ b/thirdparty/freetype/src/pfr/pfrcmap.h diff --git a/drivers/freetype/src/pfr/pfrdrivr.c b/thirdparty/freetype/src/pfr/pfrdrivr.c index b81c15e560..b81c15e560 100644 --- a/drivers/freetype/src/pfr/pfrdrivr.c +++ b/thirdparty/freetype/src/pfr/pfrdrivr.c diff --git a/drivers/freetype/src/pfr/pfrdrivr.h b/thirdparty/freetype/src/pfr/pfrdrivr.h index 32b2d9eab3..32b2d9eab3 100644 --- a/drivers/freetype/src/pfr/pfrdrivr.h +++ b/thirdparty/freetype/src/pfr/pfrdrivr.h diff --git a/drivers/freetype/src/pfr/pfrerror.h b/thirdparty/freetype/src/pfr/pfrerror.h index 9305f8fb58..9305f8fb58 100644 --- a/drivers/freetype/src/pfr/pfrerror.h +++ b/thirdparty/freetype/src/pfr/pfrerror.h diff --git a/drivers/freetype/src/pfr/pfrgload.c b/thirdparty/freetype/src/pfr/pfrgload.c index f9cd1f63bb..f9cd1f63bb 100644 --- a/drivers/freetype/src/pfr/pfrgload.c +++ b/thirdparty/freetype/src/pfr/pfrgload.c diff --git a/drivers/freetype/src/pfr/pfrgload.h b/thirdparty/freetype/src/pfr/pfrgload.h index 908d4378a4..908d4378a4 100644 --- a/drivers/freetype/src/pfr/pfrgload.h +++ b/thirdparty/freetype/src/pfr/pfrgload.h diff --git a/drivers/freetype/src/pfr/pfrload.c b/thirdparty/freetype/src/pfr/pfrload.c index e509e70b5d..e509e70b5d 100644 --- a/drivers/freetype/src/pfr/pfrload.c +++ b/thirdparty/freetype/src/pfr/pfrload.c diff --git a/drivers/freetype/src/pfr/pfrload.h b/thirdparty/freetype/src/pfr/pfrload.h index 0f7a2bb239..0f7a2bb239 100644 --- a/drivers/freetype/src/pfr/pfrload.h +++ b/thirdparty/freetype/src/pfr/pfrload.h diff --git a/drivers/freetype/src/pfr/pfrobjs.c b/thirdparty/freetype/src/pfr/pfrobjs.c index 769a3b6164..769a3b6164 100644 --- a/drivers/freetype/src/pfr/pfrobjs.c +++ b/thirdparty/freetype/src/pfr/pfrobjs.c diff --git a/drivers/freetype/src/pfr/pfrobjs.h b/thirdparty/freetype/src/pfr/pfrobjs.h index 335aca8854..335aca8854 100644 --- a/drivers/freetype/src/pfr/pfrobjs.h +++ b/thirdparty/freetype/src/pfr/pfrobjs.h diff --git a/drivers/freetype/src/pfr/pfrsbit.c b/thirdparty/freetype/src/pfr/pfrsbit.c index 144f50c0b3..144f50c0b3 100644 --- a/drivers/freetype/src/pfr/pfrsbit.c +++ b/thirdparty/freetype/src/pfr/pfrsbit.c diff --git a/drivers/freetype/src/pfr/pfrsbit.h b/thirdparty/freetype/src/pfr/pfrsbit.h index 94ead28ca7..94ead28ca7 100644 --- a/drivers/freetype/src/pfr/pfrsbit.h +++ b/thirdparty/freetype/src/pfr/pfrsbit.h diff --git a/drivers/freetype/src/pfr/pfrtypes.h b/thirdparty/freetype/src/pfr/pfrtypes.h index bd6c2cd30c..bd6c2cd30c 100644 --- a/drivers/freetype/src/pfr/pfrtypes.h +++ b/thirdparty/freetype/src/pfr/pfrtypes.h diff --git a/drivers/freetype/src/pfr/rules.mk b/thirdparty/freetype/src/pfr/rules.mk index 39bb9e941a..39bb9e941a 100644 --- a/drivers/freetype/src/pfr/rules.mk +++ b/thirdparty/freetype/src/pfr/rules.mk diff --git a/drivers/freetype/src/psaux/afmparse.c b/thirdparty/freetype/src/psaux/afmparse.c index 9fb0ac0e2b..9fb0ac0e2b 100644 --- a/drivers/freetype/src/psaux/afmparse.c +++ b/thirdparty/freetype/src/psaux/afmparse.c diff --git a/drivers/freetype/src/psaux/afmparse.h b/thirdparty/freetype/src/psaux/afmparse.h index 6d8b193ffc..6d8b193ffc 100644 --- a/drivers/freetype/src/psaux/afmparse.h +++ b/thirdparty/freetype/src/psaux/afmparse.h diff --git a/drivers/freetype/src/psaux/module.mk b/thirdparty/freetype/src/psaux/module.mk index 630c4f39dd..630c4f39dd 100644 --- a/drivers/freetype/src/psaux/module.mk +++ b/thirdparty/freetype/src/psaux/module.mk diff --git a/drivers/freetype/src/psaux/psaux.c b/thirdparty/freetype/src/psaux/psaux.c index 33b462ef15..33b462ef15 100644 --- a/drivers/freetype/src/psaux/psaux.c +++ b/thirdparty/freetype/src/psaux/psaux.c diff --git a/drivers/freetype/src/psaux/psauxerr.h b/thirdparty/freetype/src/psaux/psauxerr.h index 9739157fc4..9739157fc4 100644 --- a/drivers/freetype/src/psaux/psauxerr.h +++ b/thirdparty/freetype/src/psaux/psauxerr.h diff --git a/drivers/freetype/src/psaux/psauxmod.c b/thirdparty/freetype/src/psaux/psauxmod.c index 80805e6951..80805e6951 100644 --- a/drivers/freetype/src/psaux/psauxmod.c +++ b/thirdparty/freetype/src/psaux/psauxmod.c diff --git a/drivers/freetype/src/psaux/psauxmod.h b/thirdparty/freetype/src/psaux/psauxmod.h index b1dbb06904..b1dbb06904 100644 --- a/drivers/freetype/src/psaux/psauxmod.h +++ b/thirdparty/freetype/src/psaux/psauxmod.h diff --git a/drivers/freetype/src/psaux/psconv.c b/thirdparty/freetype/src/psaux/psconv.c index fdaca7fb5d..fdaca7fb5d 100644 --- a/drivers/freetype/src/psaux/psconv.c +++ b/thirdparty/freetype/src/psaux/psconv.c diff --git a/drivers/freetype/src/psaux/psconv.h b/thirdparty/freetype/src/psaux/psconv.h index 062de36413..062de36413 100644 --- a/drivers/freetype/src/psaux/psconv.h +++ b/thirdparty/freetype/src/psaux/psconv.h diff --git a/drivers/freetype/src/psaux/psobjs.c b/thirdparty/freetype/src/psaux/psobjs.c index f208b5fc63..f208b5fc63 100644 --- a/drivers/freetype/src/psaux/psobjs.c +++ b/thirdparty/freetype/src/psaux/psobjs.c diff --git a/drivers/freetype/src/psaux/psobjs.h b/thirdparty/freetype/src/psaux/psobjs.h index 4c7178e79f..4c7178e79f 100644 --- a/drivers/freetype/src/psaux/psobjs.h +++ b/thirdparty/freetype/src/psaux/psobjs.h diff --git a/drivers/freetype/src/psaux/rules.mk b/thirdparty/freetype/src/psaux/rules.mk index 19787b5f82..19787b5f82 100644 --- a/drivers/freetype/src/psaux/rules.mk +++ b/thirdparty/freetype/src/psaux/rules.mk diff --git a/drivers/freetype/src/psaux/t1cmap.c b/thirdparty/freetype/src/psaux/t1cmap.c index 43abb98615..43abb98615 100644 --- a/drivers/freetype/src/psaux/t1cmap.c +++ b/thirdparty/freetype/src/psaux/t1cmap.c diff --git a/drivers/freetype/src/psaux/t1cmap.h b/thirdparty/freetype/src/psaux/t1cmap.h index 5e1277dc63..5e1277dc63 100644 --- a/drivers/freetype/src/psaux/t1cmap.h +++ b/thirdparty/freetype/src/psaux/t1cmap.h diff --git a/drivers/freetype/src/psaux/t1decode.c b/thirdparty/freetype/src/psaux/t1decode.c index 98f6ce1c87..98f6ce1c87 100644 --- a/drivers/freetype/src/psaux/t1decode.c +++ b/thirdparty/freetype/src/psaux/t1decode.c diff --git a/drivers/freetype/src/psaux/t1decode.h b/thirdparty/freetype/src/psaux/t1decode.h index 0f5adfa156..0f5adfa156 100644 --- a/drivers/freetype/src/psaux/t1decode.h +++ b/thirdparty/freetype/src/psaux/t1decode.h diff --git a/drivers/freetype/src/pshinter/module.mk b/thirdparty/freetype/src/pshinter/module.mk index 63110c46a6..63110c46a6 100644 --- a/drivers/freetype/src/pshinter/module.mk +++ b/thirdparty/freetype/src/pshinter/module.mk diff --git a/drivers/freetype/src/pshinter/pshalgo.c b/thirdparty/freetype/src/pshinter/pshalgo.c index 8f131be759..8f131be759 100644 --- a/drivers/freetype/src/pshinter/pshalgo.c +++ b/thirdparty/freetype/src/pshinter/pshalgo.c diff --git a/drivers/freetype/src/pshinter/pshalgo.h b/thirdparty/freetype/src/pshinter/pshalgo.h index f1bda65013..f1bda65013 100644 --- a/drivers/freetype/src/pshinter/pshalgo.h +++ b/thirdparty/freetype/src/pshinter/pshalgo.h diff --git a/drivers/freetype/src/pshinter/pshglob.c b/thirdparty/freetype/src/pshinter/pshglob.c index 2ac5ef1558..2ac5ef1558 100644 --- a/drivers/freetype/src/pshinter/pshglob.c +++ b/thirdparty/freetype/src/pshinter/pshglob.c diff --git a/drivers/freetype/src/pshinter/pshglob.h b/thirdparty/freetype/src/pshinter/pshglob.h index 45c957b6ef..45c957b6ef 100644 --- a/drivers/freetype/src/pshinter/pshglob.h +++ b/thirdparty/freetype/src/pshinter/pshglob.h diff --git a/drivers/freetype/src/pshinter/pshinter.c b/thirdparty/freetype/src/pshinter/pshinter.c index 614e0bb3d8..614e0bb3d8 100644 --- a/drivers/freetype/src/pshinter/pshinter.c +++ b/thirdparty/freetype/src/pshinter/pshinter.c diff --git a/drivers/freetype/src/pshinter/pshmod.c b/thirdparty/freetype/src/pshinter/pshmod.c index fa4ad1f564..fa4ad1f564 100644 --- a/drivers/freetype/src/pshinter/pshmod.c +++ b/thirdparty/freetype/src/pshinter/pshmod.c diff --git a/drivers/freetype/src/pshinter/pshmod.h b/thirdparty/freetype/src/pshinter/pshmod.h index 39112a9561..39112a9561 100644 --- a/drivers/freetype/src/pshinter/pshmod.h +++ b/thirdparty/freetype/src/pshinter/pshmod.h diff --git a/drivers/freetype/src/pshinter/pshnterr.h b/thirdparty/freetype/src/pshinter/pshnterr.h index 7a94588b87..7a94588b87 100644 --- a/drivers/freetype/src/pshinter/pshnterr.h +++ b/thirdparty/freetype/src/pshinter/pshnterr.h diff --git a/drivers/freetype/src/pshinter/pshpic.c b/thirdparty/freetype/src/pshinter/pshpic.c index d0a3d8ebc9..d0a3d8ebc9 100644 --- a/drivers/freetype/src/pshinter/pshpic.c +++ b/thirdparty/freetype/src/pshinter/pshpic.c diff --git a/drivers/freetype/src/pshinter/pshpic.h b/thirdparty/freetype/src/pshinter/pshpic.h index 75ee573544..75ee573544 100644 --- a/drivers/freetype/src/pshinter/pshpic.h +++ b/thirdparty/freetype/src/pshinter/pshpic.h diff --git a/drivers/freetype/src/pshinter/pshrec.c b/thirdparty/freetype/src/pshinter/pshrec.c index d7cc4a0d21..d7cc4a0d21 100644 --- a/drivers/freetype/src/pshinter/pshrec.c +++ b/thirdparty/freetype/src/pshinter/pshrec.c diff --git a/drivers/freetype/src/pshinter/pshrec.h b/thirdparty/freetype/src/pshinter/pshrec.h index 97e6f0ed51..97e6f0ed51 100644 --- a/drivers/freetype/src/pshinter/pshrec.h +++ b/thirdparty/freetype/src/pshinter/pshrec.h diff --git a/drivers/freetype/src/pshinter/rules.mk b/thirdparty/freetype/src/pshinter/rules.mk index 67ecf7862f..67ecf7862f 100644 --- a/drivers/freetype/src/pshinter/rules.mk +++ b/thirdparty/freetype/src/pshinter/rules.mk diff --git a/drivers/freetype/src/psnames/module.mk b/thirdparty/freetype/src/psnames/module.mk index ba29af813c..ba29af813c 100644 --- a/drivers/freetype/src/psnames/module.mk +++ b/thirdparty/freetype/src/psnames/module.mk diff --git a/drivers/freetype/src/psnames/psmodule.c b/thirdparty/freetype/src/psnames/psmodule.c index 345402d7cc..345402d7cc 100644 --- a/drivers/freetype/src/psnames/psmodule.c +++ b/thirdparty/freetype/src/psnames/psmodule.c diff --git a/drivers/freetype/src/psnames/psmodule.h b/thirdparty/freetype/src/psnames/psmodule.h index ee3c6cb631..ee3c6cb631 100644 --- a/drivers/freetype/src/psnames/psmodule.h +++ b/thirdparty/freetype/src/psnames/psmodule.h diff --git a/drivers/freetype/src/psnames/psnamerr.h b/thirdparty/freetype/src/psnames/psnamerr.h index 3a9f65323b..3a9f65323b 100644 --- a/drivers/freetype/src/psnames/psnamerr.h +++ b/thirdparty/freetype/src/psnames/psnamerr.h diff --git a/drivers/freetype/src/psnames/psnames.c b/thirdparty/freetype/src/psnames/psnames.c index e7b2c0b5ef..e7b2c0b5ef 100644 --- a/drivers/freetype/src/psnames/psnames.c +++ b/thirdparty/freetype/src/psnames/psnames.c diff --git a/drivers/freetype/src/psnames/pspic.c b/thirdparty/freetype/src/psnames/pspic.c index a78ec5aa81..a78ec5aa81 100644 --- a/drivers/freetype/src/psnames/pspic.c +++ b/thirdparty/freetype/src/psnames/pspic.c diff --git a/drivers/freetype/src/psnames/pspic.h b/thirdparty/freetype/src/psnames/pspic.h index 48348765cf..48348765cf 100644 --- a/drivers/freetype/src/psnames/pspic.h +++ b/thirdparty/freetype/src/psnames/pspic.h diff --git a/drivers/freetype/src/psnames/pstables.h b/thirdparty/freetype/src/psnames/pstables.h index eb827fa5ea..eb827fa5ea 100644 --- a/drivers/freetype/src/psnames/pstables.h +++ b/thirdparty/freetype/src/psnames/pstables.h diff --git a/drivers/freetype/src/psnames/rules.mk b/thirdparty/freetype/src/psnames/rules.mk index 9849f4053a..9849f4053a 100644 --- a/drivers/freetype/src/psnames/rules.mk +++ b/thirdparty/freetype/src/psnames/rules.mk diff --git a/drivers/freetype/src/raster/ftmisc.h b/thirdparty/freetype/src/raster/ftmisc.h index 981ce32279..981ce32279 100644 --- a/drivers/freetype/src/raster/ftmisc.h +++ b/thirdparty/freetype/src/raster/ftmisc.h diff --git a/drivers/freetype/src/raster/ftraster.c b/thirdparty/freetype/src/raster/ftraster.c index 0fa2f2687f..0fa2f2687f 100644 --- a/drivers/freetype/src/raster/ftraster.c +++ b/thirdparty/freetype/src/raster/ftraster.c diff --git a/drivers/freetype/src/raster/ftraster.h b/thirdparty/freetype/src/raster/ftraster.h index 65cd5f9609..65cd5f9609 100644 --- a/drivers/freetype/src/raster/ftraster.h +++ b/thirdparty/freetype/src/raster/ftraster.h diff --git a/drivers/freetype/src/raster/ftrend1.c b/thirdparty/freetype/src/raster/ftrend1.c index 494f112234..494f112234 100644 --- a/drivers/freetype/src/raster/ftrend1.c +++ b/thirdparty/freetype/src/raster/ftrend1.c diff --git a/drivers/freetype/src/raster/ftrend1.h b/thirdparty/freetype/src/raster/ftrend1.h index a431f185d2..a431f185d2 100644 --- a/drivers/freetype/src/raster/ftrend1.h +++ b/thirdparty/freetype/src/raster/ftrend1.h diff --git a/drivers/freetype/src/raster/module.mk b/thirdparty/freetype/src/raster/module.mk index f4a5f8e838..f4a5f8e838 100644 --- a/drivers/freetype/src/raster/module.mk +++ b/thirdparty/freetype/src/raster/module.mk diff --git a/drivers/freetype/src/raster/raster.c b/thirdparty/freetype/src/raster/raster.c index 5b21dcbc6a..5b21dcbc6a 100644 --- a/drivers/freetype/src/raster/raster.c +++ b/thirdparty/freetype/src/raster/raster.c diff --git a/drivers/freetype/src/raster/rasterrs.h b/thirdparty/freetype/src/raster/rasterrs.h index 44da7fca56..44da7fca56 100644 --- a/drivers/freetype/src/raster/rasterrs.h +++ b/thirdparty/freetype/src/raster/rasterrs.h diff --git a/drivers/freetype/src/raster/rastpic.c b/thirdparty/freetype/src/raster/rastpic.c index dcfa92eef7..dcfa92eef7 100644 --- a/drivers/freetype/src/raster/rastpic.c +++ b/thirdparty/freetype/src/raster/rastpic.c diff --git a/drivers/freetype/src/raster/rastpic.h b/thirdparty/freetype/src/raster/rastpic.h index 7815876383..7815876383 100644 --- a/drivers/freetype/src/raster/rastpic.h +++ b/thirdparty/freetype/src/raster/rastpic.h diff --git a/drivers/freetype/src/raster/rules.mk b/thirdparty/freetype/src/raster/rules.mk index 929faa3a95..929faa3a95 100644 --- a/drivers/freetype/src/raster/rules.mk +++ b/thirdparty/freetype/src/raster/rules.mk diff --git a/drivers/freetype/src/sfnt/module.mk b/thirdparty/freetype/src/sfnt/module.mk index ca19e096a3..ca19e096a3 100644 --- a/drivers/freetype/src/sfnt/module.mk +++ b/thirdparty/freetype/src/sfnt/module.mk diff --git a/drivers/freetype/src/sfnt/pngshim.c b/thirdparty/freetype/src/sfnt/pngshim.c index 2815759ccb..2815759ccb 100644 --- a/drivers/freetype/src/sfnt/pngshim.c +++ b/thirdparty/freetype/src/sfnt/pngshim.c diff --git a/drivers/freetype/src/sfnt/pngshim.h b/thirdparty/freetype/src/sfnt/pngshim.h index ff05871332..ff05871332 100644 --- a/drivers/freetype/src/sfnt/pngshim.h +++ b/thirdparty/freetype/src/sfnt/pngshim.h diff --git a/drivers/freetype/src/sfnt/rules.mk b/thirdparty/freetype/src/sfnt/rules.mk index e9fc421567..e9fc421567 100644 --- a/drivers/freetype/src/sfnt/rules.mk +++ b/thirdparty/freetype/src/sfnt/rules.mk diff --git a/drivers/freetype/src/sfnt/sfdriver.c b/thirdparty/freetype/src/sfnt/sfdriver.c index 47e8967752..47e8967752 100644 --- a/drivers/freetype/src/sfnt/sfdriver.c +++ b/thirdparty/freetype/src/sfnt/sfdriver.c diff --git a/drivers/freetype/src/sfnt/sfdriver.h b/thirdparty/freetype/src/sfnt/sfdriver.h index 2694488e20..2694488e20 100644 --- a/drivers/freetype/src/sfnt/sfdriver.h +++ b/thirdparty/freetype/src/sfnt/sfdriver.h diff --git a/drivers/freetype/src/sfnt/sferrors.h b/thirdparty/freetype/src/sfnt/sferrors.h index c2f9fdfead..c2f9fdfead 100644 --- a/drivers/freetype/src/sfnt/sferrors.h +++ b/thirdparty/freetype/src/sfnt/sferrors.h diff --git a/drivers/freetype/src/sfnt/sfnt.c b/thirdparty/freetype/src/sfnt/sfnt.c index 952d6d425a..952d6d425a 100644 --- a/drivers/freetype/src/sfnt/sfnt.c +++ b/thirdparty/freetype/src/sfnt/sfnt.c diff --git a/drivers/freetype/src/sfnt/sfntpic.c b/thirdparty/freetype/src/sfnt/sfntpic.c index 1f596c0936..1f596c0936 100644 --- a/drivers/freetype/src/sfnt/sfntpic.c +++ b/thirdparty/freetype/src/sfnt/sfntpic.c diff --git a/drivers/freetype/src/sfnt/sfntpic.h b/thirdparty/freetype/src/sfnt/sfntpic.h index 5ce96d3938..5ce96d3938 100644 --- a/drivers/freetype/src/sfnt/sfntpic.h +++ b/thirdparty/freetype/src/sfnt/sfntpic.h diff --git a/drivers/freetype/src/sfnt/sfobjs.c b/thirdparty/freetype/src/sfnt/sfobjs.c index 2e8c1ecde6..2e8c1ecde6 100644 --- a/drivers/freetype/src/sfnt/sfobjs.c +++ b/thirdparty/freetype/src/sfnt/sfobjs.c diff --git a/drivers/freetype/src/sfnt/sfobjs.h b/thirdparty/freetype/src/sfnt/sfobjs.h index 60b5698edd..60b5698edd 100644 --- a/drivers/freetype/src/sfnt/sfobjs.h +++ b/thirdparty/freetype/src/sfnt/sfobjs.h diff --git a/drivers/freetype/src/sfnt/ttbdf.c b/thirdparty/freetype/src/sfnt/ttbdf.c index f891691118..f891691118 100644 --- a/drivers/freetype/src/sfnt/ttbdf.c +++ b/thirdparty/freetype/src/sfnt/ttbdf.c diff --git a/drivers/freetype/src/sfnt/ttbdf.h b/thirdparty/freetype/src/sfnt/ttbdf.h index ae521c60b6..ae521c60b6 100644 --- a/drivers/freetype/src/sfnt/ttbdf.h +++ b/thirdparty/freetype/src/sfnt/ttbdf.h diff --git a/drivers/freetype/src/sfnt/ttcmap.c b/thirdparty/freetype/src/sfnt/ttcmap.c index 01255a887e..01255a887e 100644 --- a/drivers/freetype/src/sfnt/ttcmap.c +++ b/thirdparty/freetype/src/sfnt/ttcmap.c diff --git a/drivers/freetype/src/sfnt/ttcmap.h b/thirdparty/freetype/src/sfnt/ttcmap.h index 2273cbd961..2273cbd961 100644 --- a/drivers/freetype/src/sfnt/ttcmap.h +++ b/thirdparty/freetype/src/sfnt/ttcmap.h diff --git a/drivers/freetype/src/sfnt/ttcmapc.h b/thirdparty/freetype/src/sfnt/ttcmapc.h index 7c732fbd36..7c732fbd36 100644 --- a/drivers/freetype/src/sfnt/ttcmapc.h +++ b/thirdparty/freetype/src/sfnt/ttcmapc.h diff --git a/drivers/freetype/src/sfnt/ttkern.c b/thirdparty/freetype/src/sfnt/ttkern.c index 6f9fa522d5..6f9fa522d5 100644 --- a/drivers/freetype/src/sfnt/ttkern.c +++ b/thirdparty/freetype/src/sfnt/ttkern.c diff --git a/drivers/freetype/src/sfnt/ttkern.h b/thirdparty/freetype/src/sfnt/ttkern.h index 85dd5c31ae..85dd5c31ae 100644 --- a/drivers/freetype/src/sfnt/ttkern.h +++ b/thirdparty/freetype/src/sfnt/ttkern.h diff --git a/drivers/freetype/src/sfnt/ttload.c b/thirdparty/freetype/src/sfnt/ttload.c index 2f5b2c3843..2f5b2c3843 100644 --- a/drivers/freetype/src/sfnt/ttload.c +++ b/thirdparty/freetype/src/sfnt/ttload.c diff --git a/drivers/freetype/src/sfnt/ttload.h b/thirdparty/freetype/src/sfnt/ttload.h index bec42b94b4..bec42b94b4 100644 --- a/drivers/freetype/src/sfnt/ttload.h +++ b/thirdparty/freetype/src/sfnt/ttload.h diff --git a/drivers/freetype/src/sfnt/ttmtx.c b/thirdparty/freetype/src/sfnt/ttmtx.c index 186f873dae..186f873dae 100644 --- a/drivers/freetype/src/sfnt/ttmtx.c +++ b/thirdparty/freetype/src/sfnt/ttmtx.c diff --git a/drivers/freetype/src/sfnt/ttmtx.h b/thirdparty/freetype/src/sfnt/ttmtx.h index 78395def33..78395def33 100644 --- a/drivers/freetype/src/sfnt/ttmtx.h +++ b/thirdparty/freetype/src/sfnt/ttmtx.h diff --git a/drivers/freetype/src/sfnt/ttpost.c b/thirdparty/freetype/src/sfnt/ttpost.c index 3277f1ec4f..3277f1ec4f 100644 --- a/drivers/freetype/src/sfnt/ttpost.c +++ b/thirdparty/freetype/src/sfnt/ttpost.c diff --git a/drivers/freetype/src/sfnt/ttpost.h b/thirdparty/freetype/src/sfnt/ttpost.h index ede45fd84c..ede45fd84c 100644 --- a/drivers/freetype/src/sfnt/ttpost.h +++ b/thirdparty/freetype/src/sfnt/ttpost.h diff --git a/drivers/freetype/src/sfnt/ttsbit.c b/thirdparty/freetype/src/sfnt/ttsbit.c index e24e7d6cdd..e24e7d6cdd 100644 --- a/drivers/freetype/src/sfnt/ttsbit.c +++ b/thirdparty/freetype/src/sfnt/ttsbit.c diff --git a/drivers/freetype/src/sfnt/ttsbit.h b/thirdparty/freetype/src/sfnt/ttsbit.h index d8a8167083..d8a8167083 100644 --- a/drivers/freetype/src/sfnt/ttsbit.h +++ b/thirdparty/freetype/src/sfnt/ttsbit.h diff --git a/drivers/freetype/src/smooth/ftgrays.c b/thirdparty/freetype/src/smooth/ftgrays.c index 0bf3ac6ffb..0bf3ac6ffb 100644 --- a/drivers/freetype/src/smooth/ftgrays.c +++ b/thirdparty/freetype/src/smooth/ftgrays.c diff --git a/drivers/freetype/src/smooth/ftgrays.h b/thirdparty/freetype/src/smooth/ftgrays.h index 21c2badcaf..21c2badcaf 100644 --- a/drivers/freetype/src/smooth/ftgrays.h +++ b/thirdparty/freetype/src/smooth/ftgrays.h diff --git a/drivers/freetype/src/smooth/ftsmerrs.h b/thirdparty/freetype/src/smooth/ftsmerrs.h index a759b91c17..a759b91c17 100644 --- a/drivers/freetype/src/smooth/ftsmerrs.h +++ b/thirdparty/freetype/src/smooth/ftsmerrs.h diff --git a/drivers/freetype/src/smooth/ftsmooth.c b/thirdparty/freetype/src/smooth/ftsmooth.c index 79276765b1..79276765b1 100644 --- a/drivers/freetype/src/smooth/ftsmooth.c +++ b/thirdparty/freetype/src/smooth/ftsmooth.c diff --git a/drivers/freetype/src/smooth/ftsmooth.h b/thirdparty/freetype/src/smooth/ftsmooth.h index c7c28c244c..c7c28c244c 100644 --- a/drivers/freetype/src/smooth/ftsmooth.h +++ b/thirdparty/freetype/src/smooth/ftsmooth.h diff --git a/drivers/freetype/src/smooth/ftspic.c b/thirdparty/freetype/src/smooth/ftspic.c index 6c2b2329b3..6c2b2329b3 100644 --- a/drivers/freetype/src/smooth/ftspic.c +++ b/thirdparty/freetype/src/smooth/ftspic.c diff --git a/drivers/freetype/src/smooth/ftspic.h b/thirdparty/freetype/src/smooth/ftspic.h index fe76152770..fe76152770 100644 --- a/drivers/freetype/src/smooth/ftspic.h +++ b/thirdparty/freetype/src/smooth/ftspic.h diff --git a/drivers/freetype/src/smooth/module.mk b/thirdparty/freetype/src/smooth/module.mk index f3cb044039..f3cb044039 100644 --- a/drivers/freetype/src/smooth/module.mk +++ b/thirdparty/freetype/src/smooth/module.mk diff --git a/drivers/freetype/src/smooth/rules.mk b/thirdparty/freetype/src/smooth/rules.mk index 5e94f73519..5e94f73519 100644 --- a/drivers/freetype/src/smooth/rules.mk +++ b/thirdparty/freetype/src/smooth/rules.mk diff --git a/drivers/freetype/src/smooth/smooth.c b/thirdparty/freetype/src/smooth/smooth.c index 97ca3e5995..97ca3e5995 100644 --- a/drivers/freetype/src/smooth/smooth.c +++ b/thirdparty/freetype/src/smooth/smooth.c diff --git a/drivers/freetype/src/truetype/module.mk b/thirdparty/freetype/src/truetype/module.mk index 80c9832b2c..80c9832b2c 100644 --- a/drivers/freetype/src/truetype/module.mk +++ b/thirdparty/freetype/src/truetype/module.mk diff --git a/drivers/freetype/src/truetype/rules.mk b/thirdparty/freetype/src/truetype/rules.mk index 3bf7cf770d..3bf7cf770d 100644 --- a/drivers/freetype/src/truetype/rules.mk +++ b/thirdparty/freetype/src/truetype/rules.mk diff --git a/drivers/freetype/src/truetype/truetype.c b/thirdparty/freetype/src/truetype/truetype.c index 23e2ea00a7..23e2ea00a7 100644 --- a/drivers/freetype/src/truetype/truetype.c +++ b/thirdparty/freetype/src/truetype/truetype.c diff --git a/drivers/freetype/src/truetype/ttdriver.c b/thirdparty/freetype/src/truetype/ttdriver.c index c9d4081efe..c9d4081efe 100644 --- a/drivers/freetype/src/truetype/ttdriver.c +++ b/thirdparty/freetype/src/truetype/ttdriver.c diff --git a/drivers/freetype/src/truetype/ttdriver.h b/thirdparty/freetype/src/truetype/ttdriver.h index 74392bbd02..74392bbd02 100644 --- a/drivers/freetype/src/truetype/ttdriver.h +++ b/thirdparty/freetype/src/truetype/ttdriver.h diff --git a/drivers/freetype/src/truetype/tterrors.h b/thirdparty/freetype/src/truetype/tterrors.h index 895989f5fd..895989f5fd 100644 --- a/drivers/freetype/src/truetype/tterrors.h +++ b/thirdparty/freetype/src/truetype/tterrors.h diff --git a/drivers/freetype/src/truetype/ttgload.c b/thirdparty/freetype/src/truetype/ttgload.c index 8be9b6ae65..8be9b6ae65 100644 --- a/drivers/freetype/src/truetype/ttgload.c +++ b/thirdparty/freetype/src/truetype/ttgload.c diff --git a/drivers/freetype/src/truetype/ttgload.h b/thirdparty/freetype/src/truetype/ttgload.h index bfa29e4ff8..bfa29e4ff8 100644 --- a/drivers/freetype/src/truetype/ttgload.h +++ b/thirdparty/freetype/src/truetype/ttgload.h diff --git a/drivers/freetype/src/truetype/ttgxvar.c b/thirdparty/freetype/src/truetype/ttgxvar.c index 9a02c5a8c1..9a02c5a8c1 100644 --- a/drivers/freetype/src/truetype/ttgxvar.c +++ b/thirdparty/freetype/src/truetype/ttgxvar.c diff --git a/drivers/freetype/src/truetype/ttgxvar.h b/thirdparty/freetype/src/truetype/ttgxvar.h index aa8f6ea592..aa8f6ea592 100644 --- a/drivers/freetype/src/truetype/ttgxvar.h +++ b/thirdparty/freetype/src/truetype/ttgxvar.h diff --git a/drivers/freetype/src/truetype/ttinterp.c b/thirdparty/freetype/src/truetype/ttinterp.c index 8fe83c5ea8..8fe83c5ea8 100644 --- a/drivers/freetype/src/truetype/ttinterp.c +++ b/thirdparty/freetype/src/truetype/ttinterp.c diff --git a/drivers/freetype/src/truetype/ttinterp.h b/thirdparty/freetype/src/truetype/ttinterp.h index df7ce51f1c..df7ce51f1c 100644 --- a/drivers/freetype/src/truetype/ttinterp.h +++ b/thirdparty/freetype/src/truetype/ttinterp.h diff --git a/drivers/freetype/src/truetype/ttobjs.c b/thirdparty/freetype/src/truetype/ttobjs.c index ed3be2dbee..ed3be2dbee 100644 --- a/drivers/freetype/src/truetype/ttobjs.c +++ b/thirdparty/freetype/src/truetype/ttobjs.c diff --git a/drivers/freetype/src/truetype/ttobjs.h b/thirdparty/freetype/src/truetype/ttobjs.h index ed61a7d517..ed61a7d517 100644 --- a/drivers/freetype/src/truetype/ttobjs.h +++ b/thirdparty/freetype/src/truetype/ttobjs.h diff --git a/drivers/freetype/src/truetype/ttpic.c b/thirdparty/freetype/src/truetype/ttpic.c index 54a5b8bed6..54a5b8bed6 100644 --- a/drivers/freetype/src/truetype/ttpic.c +++ b/thirdparty/freetype/src/truetype/ttpic.c diff --git a/drivers/freetype/src/truetype/ttpic.h b/thirdparty/freetype/src/truetype/ttpic.h index f725865c5c..f725865c5c 100644 --- a/drivers/freetype/src/truetype/ttpic.h +++ b/thirdparty/freetype/src/truetype/ttpic.h diff --git a/drivers/freetype/src/truetype/ttpload.c b/thirdparty/freetype/src/truetype/ttpload.c index ca158ac50b..ca158ac50b 100644 --- a/drivers/freetype/src/truetype/ttpload.c +++ b/thirdparty/freetype/src/truetype/ttpload.c diff --git a/drivers/freetype/src/truetype/ttpload.h b/thirdparty/freetype/src/truetype/ttpload.h index aa2e38e6e7..aa2e38e6e7 100644 --- a/drivers/freetype/src/truetype/ttpload.h +++ b/thirdparty/freetype/src/truetype/ttpload.h diff --git a/drivers/freetype/src/truetype/ttsubpix.c b/thirdparty/freetype/src/truetype/ttsubpix.c index 03950960a4..03950960a4 100644 --- a/drivers/freetype/src/truetype/ttsubpix.c +++ b/thirdparty/freetype/src/truetype/ttsubpix.c diff --git a/drivers/freetype/src/truetype/ttsubpix.h b/thirdparty/freetype/src/truetype/ttsubpix.h index 86844da666..86844da666 100644 --- a/drivers/freetype/src/truetype/ttsubpix.h +++ b/thirdparty/freetype/src/truetype/ttsubpix.h diff --git a/drivers/freetype/src/type1/module.mk b/thirdparty/freetype/src/type1/module.mk index d7ab520c74..d7ab520c74 100644 --- a/drivers/freetype/src/type1/module.mk +++ b/thirdparty/freetype/src/type1/module.mk diff --git a/drivers/freetype/src/type1/rules.mk b/thirdparty/freetype/src/type1/rules.mk index bdec29479f..bdec29479f 100644 --- a/drivers/freetype/src/type1/rules.mk +++ b/thirdparty/freetype/src/type1/rules.mk diff --git a/drivers/freetype/src/type1/t1afm.c b/thirdparty/freetype/src/type1/t1afm.c index bbd843c1c3..bbd843c1c3 100644 --- a/drivers/freetype/src/type1/t1afm.c +++ b/thirdparty/freetype/src/type1/t1afm.c diff --git a/drivers/freetype/src/type1/t1afm.h b/thirdparty/freetype/src/type1/t1afm.h index 3a864f2379..3a864f2379 100644 --- a/drivers/freetype/src/type1/t1afm.h +++ b/thirdparty/freetype/src/type1/t1afm.h diff --git a/drivers/freetype/src/type1/t1driver.c b/thirdparty/freetype/src/type1/t1driver.c index f1e60d4523..f1e60d4523 100644 --- a/drivers/freetype/src/type1/t1driver.c +++ b/thirdparty/freetype/src/type1/t1driver.c diff --git a/drivers/freetype/src/type1/t1driver.h b/thirdparty/freetype/src/type1/t1driver.h index 78d8e38aa9..78d8e38aa9 100644 --- a/drivers/freetype/src/type1/t1driver.h +++ b/thirdparty/freetype/src/type1/t1driver.h diff --git a/drivers/freetype/src/type1/t1errors.h b/thirdparty/freetype/src/type1/t1errors.h index 9ba470ed6c..9ba470ed6c 100644 --- a/drivers/freetype/src/type1/t1errors.h +++ b/thirdparty/freetype/src/type1/t1errors.h diff --git a/drivers/freetype/src/type1/t1gload.c b/thirdparty/freetype/src/type1/t1gload.c index ea36f64142..ea36f64142 100644 --- a/drivers/freetype/src/type1/t1gload.c +++ b/thirdparty/freetype/src/type1/t1gload.c diff --git a/drivers/freetype/src/type1/t1gload.h b/thirdparty/freetype/src/type1/t1gload.h index 975f227853..975f227853 100644 --- a/drivers/freetype/src/type1/t1gload.h +++ b/thirdparty/freetype/src/type1/t1gload.h diff --git a/drivers/freetype/src/type1/t1load.c b/thirdparty/freetype/src/type1/t1load.c index c981adcf2c..c981adcf2c 100644 --- a/drivers/freetype/src/type1/t1load.c +++ b/thirdparty/freetype/src/type1/t1load.c diff --git a/drivers/freetype/src/type1/t1load.h b/thirdparty/freetype/src/type1/t1load.h index b96fe5a746..b96fe5a746 100644 --- a/drivers/freetype/src/type1/t1load.h +++ b/thirdparty/freetype/src/type1/t1load.h diff --git a/drivers/freetype/src/type1/t1objs.c b/thirdparty/freetype/src/type1/t1objs.c index a009117133..a009117133 100644 --- a/drivers/freetype/src/type1/t1objs.c +++ b/thirdparty/freetype/src/type1/t1objs.c diff --git a/drivers/freetype/src/type1/t1objs.h b/thirdparty/freetype/src/type1/t1objs.h index 94fbdee9ae..94fbdee9ae 100644 --- a/drivers/freetype/src/type1/t1objs.h +++ b/thirdparty/freetype/src/type1/t1objs.h diff --git a/drivers/freetype/src/type1/t1parse.c b/thirdparty/freetype/src/type1/t1parse.c index 563d9f37bb..563d9f37bb 100644 --- a/drivers/freetype/src/type1/t1parse.c +++ b/thirdparty/freetype/src/type1/t1parse.c diff --git a/drivers/freetype/src/type1/t1parse.h b/thirdparty/freetype/src/type1/t1parse.h index affa818e63..affa818e63 100644 --- a/drivers/freetype/src/type1/t1parse.h +++ b/thirdparty/freetype/src/type1/t1parse.h diff --git a/drivers/freetype/src/type1/t1tokens.h b/thirdparty/freetype/src/type1/t1tokens.h index a84f291a6b..a84f291a6b 100644 --- a/drivers/freetype/src/type1/t1tokens.h +++ b/thirdparty/freetype/src/type1/t1tokens.h diff --git a/drivers/freetype/src/type1/type1.c b/thirdparty/freetype/src/type1/type1.c index bb8aca97f9..bb8aca97f9 100644 --- a/drivers/freetype/src/type1/type1.c +++ b/thirdparty/freetype/src/type1/type1.c diff --git a/drivers/freetype/src/type42/module.mk b/thirdparty/freetype/src/type42/module.mk index a7e27b7236..a7e27b7236 100644 --- a/drivers/freetype/src/type42/module.mk +++ b/thirdparty/freetype/src/type42/module.mk diff --git a/drivers/freetype/src/type42/rules.mk b/thirdparty/freetype/src/type42/rules.mk index 80710eff67..80710eff67 100644 --- a/drivers/freetype/src/type42/rules.mk +++ b/thirdparty/freetype/src/type42/rules.mk diff --git a/drivers/freetype/src/type42/t42drivr.c b/thirdparty/freetype/src/type42/t42drivr.c index c63ed0c812..c63ed0c812 100644 --- a/drivers/freetype/src/type42/t42drivr.c +++ b/thirdparty/freetype/src/type42/t42drivr.c diff --git a/drivers/freetype/src/type42/t42drivr.h b/thirdparty/freetype/src/type42/t42drivr.h index 6ddfb639d5..6ddfb639d5 100644 --- a/drivers/freetype/src/type42/t42drivr.h +++ b/thirdparty/freetype/src/type42/t42drivr.h diff --git a/drivers/freetype/src/type42/t42error.h b/thirdparty/freetype/src/type42/t42error.h index e1097cc81e..e1097cc81e 100644 --- a/drivers/freetype/src/type42/t42error.h +++ b/thirdparty/freetype/src/type42/t42error.h diff --git a/drivers/freetype/src/type42/t42objs.c b/thirdparty/freetype/src/type42/t42objs.c index 4672c6e164..4672c6e164 100644 --- a/drivers/freetype/src/type42/t42objs.c +++ b/thirdparty/freetype/src/type42/t42objs.c diff --git a/drivers/freetype/src/type42/t42objs.h b/thirdparty/freetype/src/type42/t42objs.h index 87a40452f4..87a40452f4 100644 --- a/drivers/freetype/src/type42/t42objs.h +++ b/thirdparty/freetype/src/type42/t42objs.h diff --git a/drivers/freetype/src/type42/t42parse.c b/thirdparty/freetype/src/type42/t42parse.c index f948916afa..f948916afa 100644 --- a/drivers/freetype/src/type42/t42parse.c +++ b/thirdparty/freetype/src/type42/t42parse.c diff --git a/drivers/freetype/src/type42/t42parse.h b/thirdparty/freetype/src/type42/t42parse.h index ba9e857190..ba9e857190 100644 --- a/drivers/freetype/src/type42/t42parse.h +++ b/thirdparty/freetype/src/type42/t42parse.h diff --git a/drivers/freetype/src/type42/t42types.h b/thirdparty/freetype/src/type42/t42types.h index 850a156e45..850a156e45 100644 --- a/drivers/freetype/src/type42/t42types.h +++ b/thirdparty/freetype/src/type42/t42types.h diff --git a/drivers/freetype/src/type42/type42.c b/thirdparty/freetype/src/type42/type42.c index 0d17a9b1dc..0d17a9b1dc 100644 --- a/drivers/freetype/src/type42/type42.c +++ b/thirdparty/freetype/src/type42/type42.c diff --git a/drivers/freetype/src/winfonts/fnterrs.h b/thirdparty/freetype/src/winfonts/fnterrs.h index 6835d3e64f..6835d3e64f 100644 --- a/drivers/freetype/src/winfonts/fnterrs.h +++ b/thirdparty/freetype/src/winfonts/fnterrs.h diff --git a/drivers/freetype/src/winfonts/module.mk b/thirdparty/freetype/src/winfonts/module.mk index 83da5732f1..83da5732f1 100644 --- a/drivers/freetype/src/winfonts/module.mk +++ b/thirdparty/freetype/src/winfonts/module.mk diff --git a/drivers/freetype/src/winfonts/rules.mk b/thirdparty/freetype/src/winfonts/rules.mk index 2fd7b822a2..2fd7b822a2 100644 --- a/drivers/freetype/src/winfonts/rules.mk +++ b/thirdparty/freetype/src/winfonts/rules.mk diff --git a/drivers/freetype/src/winfonts/winfnt.c b/thirdparty/freetype/src/winfonts/winfnt.c index 1c74ccd5ab..1c74ccd5ab 100644 --- a/drivers/freetype/src/winfonts/winfnt.c +++ b/thirdparty/freetype/src/winfonts/winfnt.c diff --git a/drivers/freetype/src/winfonts/winfnt.h b/thirdparty/freetype/src/winfonts/winfnt.h index 9a4f32d5b0..9a4f32d5b0 100644 --- a/drivers/freetype/src/winfonts/winfnt.h +++ b/thirdparty/freetype/src/winfonts/winfnt.h diff --git a/drivers/gl_context/GL/glew.h b/thirdparty/glew/GL/glew.h index 702265c38b..702265c38b 100644 --- a/drivers/gl_context/GL/glew.h +++ b/thirdparty/glew/GL/glew.h diff --git a/drivers/gl_context/GL/glxew.h b/thirdparty/glew/GL/glxew.h index d803d260b3..d803d260b3 100644 --- a/drivers/gl_context/GL/glxew.h +++ b/thirdparty/glew/GL/glxew.h diff --git a/drivers/gl_context/GL/wglew.h b/thirdparty/glew/GL/wglew.h index 23e4d3fbab..23e4d3fbab 100644 --- a/drivers/gl_context/GL/wglew.h +++ b/thirdparty/glew/GL/wglew.h diff --git a/thirdparty/glew/LICENSE.txt b/thirdparty/glew/LICENSE.txt new file mode 100644 index 0000000000..f7078042e9 --- /dev/null +++ b/thirdparty/glew/LICENSE.txt @@ -0,0 +1,73 @@ +The OpenGL Extension Wrangler Library +Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org> +Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org> +Copyright (C) 2002, Lev Povalahev +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. +* The name of the author 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. + + +Mesa 3-D graphics library +Version: 7.0 + +Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +Copyright (c) 2007 The Khronos Group Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and/or associated documentation files (the +"Materials"), to deal in the Materials without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Materials, and to +permit persons to whom the Materials are furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Materials. + +THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. diff --git a/drivers/gl_context/glew.c b/thirdparty/glew/glew.c index 0ed5520dae..0ed5520dae 100644 --- a/drivers/gl_context/glew.c +++ b/thirdparty/glew/glew.c diff --git a/drivers/jpegd/jpgd.cpp b/thirdparty/jpeg-compressor/jpgd.cpp index fad9a37a9a..fad9a37a9a 100644 --- a/drivers/jpegd/jpgd.cpp +++ b/thirdparty/jpeg-compressor/jpgd.cpp diff --git a/drivers/jpegd/jpgd.h b/thirdparty/jpeg-compressor/jpgd.h index 150b9a0b26..150b9a0b26 100644 --- a/drivers/jpegd/jpgd.h +++ b/thirdparty/jpeg-compressor/jpgd.h diff --git a/thirdparty/libmpcdec/COPYING b/thirdparty/libmpcdec/COPYING new file mode 100644 index 0000000000..10190c014a --- /dev/null +++ b/thirdparty/libmpcdec/COPYING @@ -0,0 +1,31 @@ +Copyright (c) 2005, The Musepack Development Team +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 the The Musepack Development Team nor the + names of its 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. diff --git a/drivers/mpc/decoder.h b/thirdparty/libmpcdec/decoder.h index 3813fc02ea..3813fc02ea 100644 --- a/drivers/mpc/decoder.h +++ b/thirdparty/libmpcdec/decoder.h diff --git a/drivers/mpc/huffman.c b/thirdparty/libmpcdec/huffman.c index 52cdfd92c4..52cdfd92c4 100644 --- a/drivers/mpc/huffman.c +++ b/thirdparty/libmpcdec/huffman.c diff --git a/drivers/mpc/huffman.h b/thirdparty/libmpcdec/huffman.h index 5b12bff931..5b12bff931 100644 --- a/drivers/mpc/huffman.h +++ b/thirdparty/libmpcdec/huffman.h diff --git a/drivers/mpc/internal.h b/thirdparty/libmpcdec/internal.h index 7810bcc25d..7810bcc25d 100644 --- a/drivers/mpc/internal.h +++ b/thirdparty/libmpcdec/internal.h diff --git a/drivers/mpc/datatypes.h b/thirdparty/libmpcdec/mpc/datatypes.h index 608ecfa2f2..608ecfa2f2 100644 --- a/drivers/mpc/datatypes.h +++ b/thirdparty/libmpcdec/mpc/datatypes.h diff --git a/drivers/mpc/minimax.h b/thirdparty/libmpcdec/mpc/minimax.h index 1192626567..1192626567 100644 --- a/drivers/mpc/minimax.h +++ b/thirdparty/libmpcdec/mpc/minimax.h diff --git a/drivers/mpc/mpc_types.h b/thirdparty/libmpcdec/mpc/mpc_types.h index a827d15725..a827d15725 100644 --- a/drivers/mpc/mpc_types.h +++ b/thirdparty/libmpcdec/mpc/mpc_types.h diff --git a/drivers/mpc/mpcdec.h b/thirdparty/libmpcdec/mpc/mpcdec.h index c72359516c..c72359516c 100644 --- a/drivers/mpc/mpcdec.h +++ b/thirdparty/libmpcdec/mpc/mpcdec.h diff --git a/drivers/mpc/mpcmath.h b/thirdparty/libmpcdec/mpc/mpcmath.h index fa83cf8374..fa83cf8374 100644 --- a/drivers/mpc/mpcmath.h +++ b/thirdparty/libmpcdec/mpc/mpcmath.h diff --git a/drivers/mpc/reader.h b/thirdparty/libmpcdec/mpc/reader.h index 1a93e06706..1a93e06706 100644 --- a/drivers/mpc/reader.h +++ b/thirdparty/libmpcdec/mpc/reader.h diff --git a/drivers/mpc/streaminfo.h b/thirdparty/libmpcdec/mpc/streaminfo.h index a0a9470be1..a0a9470be1 100644 --- a/drivers/mpc/streaminfo.h +++ b/thirdparty/libmpcdec/mpc/streaminfo.h diff --git a/drivers/mpc/mpc_bits_reader.c b/thirdparty/libmpcdec/mpc_bits_reader.c index 5281288d25..5281288d25 100644 --- a/drivers/mpc/mpc_bits_reader.c +++ b/thirdparty/libmpcdec/mpc_bits_reader.c diff --git a/drivers/mpc/mpc_bits_reader.h b/thirdparty/libmpcdec/mpc_bits_reader.h index a7d8d66905..a7d8d66905 100644 --- a/drivers/mpc/mpc_bits_reader.h +++ b/thirdparty/libmpcdec/mpc_bits_reader.h diff --git a/drivers/mpc/mpc_decoder.c b/thirdparty/libmpcdec/mpc_decoder.c index 45596c6015..45596c6015 100644 --- a/drivers/mpc/mpc_decoder.c +++ b/thirdparty/libmpcdec/mpc_decoder.c diff --git a/drivers/mpc/mpc_demux.c b/thirdparty/libmpcdec/mpc_demux.c index 03bca9c36e..03bca9c36e 100644 --- a/drivers/mpc/mpc_demux.c +++ b/thirdparty/libmpcdec/mpc_demux.c diff --git a/drivers/mpc/mpc_reader.c b/thirdparty/libmpcdec/mpc_reader.c index 550c5ecb54..550c5ecb54 100644 --- a/drivers/mpc/mpc_reader.c +++ b/thirdparty/libmpcdec/mpc_reader.c diff --git a/drivers/mpc/mpcdec_math.h b/thirdparty/libmpcdec/mpcdec_math.h index 35a5ac5a57..35a5ac5a57 100644 --- a/drivers/mpc/mpcdec_math.h +++ b/thirdparty/libmpcdec/mpcdec_math.h diff --git a/drivers/mpc/requant.c b/thirdparty/libmpcdec/requant.c index ebc89a10f0..ebc89a10f0 100644 --- a/drivers/mpc/requant.c +++ b/thirdparty/libmpcdec/requant.c diff --git a/drivers/mpc/requant.h b/thirdparty/libmpcdec/requant.h index 014e2ebab7..014e2ebab7 100644 --- a/drivers/mpc/requant.h +++ b/thirdparty/libmpcdec/requant.h diff --git a/drivers/mpc/streaminfo.c b/thirdparty/libmpcdec/streaminfo.c index d9b76bb5e6..d9b76bb5e6 100644 --- a/drivers/mpc/streaminfo.c +++ b/thirdparty/libmpcdec/streaminfo.c diff --git a/drivers/mpc/synth_filter.c b/thirdparty/libmpcdec/synth_filter.c index 0d0c345340..0d0c345340 100644 --- a/drivers/mpc/synth_filter.c +++ b/thirdparty/libmpcdec/synth_filter.c diff --git a/drivers/ogg/COPYING b/thirdparty/libogg/COPYING index 6111c6c5a6..6111c6c5a6 100644 --- a/drivers/ogg/COPYING +++ b/thirdparty/libogg/COPYING diff --git a/drivers/ogg/bitwise.c b/thirdparty/libogg/bitwise.c index 145901d185..145901d185 100644 --- a/drivers/ogg/bitwise.c +++ b/thirdparty/libogg/bitwise.c diff --git a/drivers/ogg/framing.c b/thirdparty/libogg/framing.c index 3a2f0a6058..3a2f0a6058 100644 --- a/drivers/ogg/framing.c +++ b/thirdparty/libogg/framing.c diff --git a/drivers/ogg/config_types.h b/thirdparty/libogg/ogg/config_types.h index 5ea49b8abd..5ea49b8abd 100644 --- a/drivers/ogg/config_types.h +++ b/thirdparty/libogg/ogg/config_types.h diff --git a/drivers/ogg/ogg.h b/thirdparty/libogg/ogg/ogg.h index cea4ebed75..cea4ebed75 100644 --- a/drivers/ogg/ogg.h +++ b/thirdparty/libogg/ogg/ogg.h diff --git a/drivers/ogg/os_types.h b/thirdparty/libogg/ogg/os_types.h index 8bf82107e5..8bf82107e5 100644 --- a/drivers/ogg/os_types.h +++ b/thirdparty/libogg/ogg/os_types.h diff --git a/thirdparty/libpng/LICENSE b/thirdparty/libpng/LICENSE new file mode 100644 index 0000000000..b7ad4b9eaf --- /dev/null +++ b/thirdparty/libpng/LICENSE @@ -0,0 +1,130 @@ + +This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail. + +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +If you modify libpng you may insert additional notices immediately following +this sentence. + +This code is released under the libpng license. + +libpng versions 1.0.7, July 1, 2000 through 1.6.23, June 9, 2016 are +Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are +derived from libpng-1.0.6, and are distributed according to the same +disclaimer and license as libpng-1.0.6 with the following individuals +added to the list of Contributing Authors: + + Simon-Pierre Cadieux + Eric S. Raymond + Mans Rullgard + Cosmin Truta + Gilles Vollant + James Yu + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of the + library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is with + the user. + +Some files in the "contrib" directory and some configure-generated +files that are distributed with libpng have other copyright owners and +are released under other open source licenses. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from +libpng-0.96, and are distributed according to the same disclaimer and +license as libpng-0.96, with the following individuals added to the list +of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, +and are distributed according to the same disclaimer and license as +libpng-0.88, with the following individuals added to the list of +Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +Some files in the "scripts" directory have other copyright owners +but are released under this license. + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + + 1. The origin of this source code must not be misrepresented. + + 2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + + 3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + +END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. + +TRADEMARK: + +The name "libpng" has not been registered by the Copyright owner +as a trademark in any jurisdiction. However, because libpng has +been distributed and maintained world-wide, continually since 1995, +the Copyright owner claims "common-law trademark protection" in any +jurisdiction where common-law trademark is recognized. + +OSI CERTIFICATION: + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is +a certification mark of the Open Source Initiative. OSI has not addressed +the additional disclaimers inserted at version 1.0.7. + +EXPORT CONTROL: + +The Copyright owner believes that the Export Control Classification +Number (ECCN) for libpng is EAR99, which means not subject to export +controls or International Traffic in Arms Regulations (ITAR) because +it is open source, publicly available software, that does not contain +any encryption software. See the EAR, paragraphs 734.3(b)(3) and +734.7(b). + +Glenn Randers-Pehrson +glennrp at users.sourceforge.net +June 9, 2016 diff --git a/drivers/png/arm/arm_init.c b/thirdparty/libpng/arm/arm_init.c index 52c3f31fed..52c3f31fed 100644 --- a/drivers/png/arm/arm_init.c +++ b/thirdparty/libpng/arm/arm_init.c diff --git a/drivers/png/arm/filter_neon.S b/thirdparty/libpng/arm/filter_neon.S index 3b061d6bbf..3b061d6bbf 100644 --- a/drivers/png/arm/filter_neon.S +++ b/thirdparty/libpng/arm/filter_neon.S diff --git a/drivers/png/arm/filter_neon_intrinsics.c b/thirdparty/libpng/arm/filter_neon_intrinsics.c index be5ccc7107..be5ccc7107 100644 --- a/drivers/png/arm/filter_neon_intrinsics.c +++ b/thirdparty/libpng/arm/filter_neon_intrinsics.c diff --git a/drivers/png/png.c b/thirdparty/libpng/png.c index 1720ca0eae..1720ca0eae 100644 --- a/drivers/png/png.c +++ b/thirdparty/libpng/png.c diff --git a/drivers/png/png.h b/thirdparty/libpng/png.h index 1efb0b02a9..1efb0b02a9 100644 --- a/drivers/png/png.h +++ b/thirdparty/libpng/png.h diff --git a/drivers/png/pngconf.h b/thirdparty/libpng/pngconf.h index b0ccc8c25e..b0ccc8c25e 100644 --- a/drivers/png/pngconf.h +++ b/thirdparty/libpng/pngconf.h diff --git a/drivers/png/pngdebug.h b/thirdparty/libpng/pngdebug.h index 15a7ed0c95..15a7ed0c95 100644 --- a/drivers/png/pngdebug.h +++ b/thirdparty/libpng/pngdebug.h diff --git a/drivers/png/pngerror.c b/thirdparty/libpng/pngerror.c index 3fc8092fa6..3fc8092fa6 100644 --- a/drivers/png/pngerror.c +++ b/thirdparty/libpng/pngerror.c diff --git a/drivers/png/pngget.c b/thirdparty/libpng/pngget.c index 14fc7be520..14fc7be520 100644 --- a/drivers/png/pngget.c +++ b/thirdparty/libpng/pngget.c diff --git a/drivers/png/pnginfo.h b/thirdparty/libpng/pnginfo.h index 361ed8be70..361ed8be70 100644 --- a/drivers/png/pnginfo.h +++ b/thirdparty/libpng/pnginfo.h diff --git a/drivers/png/pnglibconf.h b/thirdparty/libpng/pnglibconf.h index 3e70aa1170..3e70aa1170 100644 --- a/drivers/png/pnglibconf.h +++ b/thirdparty/libpng/pnglibconf.h diff --git a/drivers/png/pngmem.c b/thirdparty/libpng/pngmem.c index 7bcfd00507..7bcfd00507 100644 --- a/drivers/png/pngmem.c +++ b/thirdparty/libpng/pngmem.c diff --git a/drivers/png/pngpread.c b/thirdparty/libpng/pngpread.c index ca300e7f16..ca300e7f16 100644 --- a/drivers/png/pngpread.c +++ b/thirdparty/libpng/pngpread.c diff --git a/drivers/png/pngpriv.h b/thirdparty/libpng/pngpriv.h index 9338df3144..9338df3144 100644 --- a/drivers/png/pngpriv.h +++ b/thirdparty/libpng/pngpriv.h diff --git a/drivers/png/pngread.c b/thirdparty/libpng/pngread.c index 0ff6238023..0ff6238023 100644 --- a/drivers/png/pngread.c +++ b/thirdparty/libpng/pngread.c diff --git a/drivers/png/pngrio.c b/thirdparty/libpng/pngrio.c index 5101d54a62..5101d54a62 100644 --- a/drivers/png/pngrio.c +++ b/thirdparty/libpng/pngrio.c diff --git a/drivers/png/pngrtran.c b/thirdparty/libpng/pngrtran.c index 3138147aff..3138147aff 100644 --- a/drivers/png/pngrtran.c +++ b/thirdparty/libpng/pngrtran.c diff --git a/drivers/png/pngrutil.c b/thirdparty/libpng/pngrutil.c index c9747fc27d..c9747fc27d 100644 --- a/drivers/png/pngrutil.c +++ b/thirdparty/libpng/pngrutil.c diff --git a/drivers/png/pngset.c b/thirdparty/libpng/pngset.c index 43456b729d..43456b729d 100644 --- a/drivers/png/pngset.c +++ b/thirdparty/libpng/pngset.c diff --git a/drivers/png/pngstruct.h b/thirdparty/libpng/pngstruct.h index c1f35edef5..c1f35edef5 100644 --- a/drivers/png/pngstruct.h +++ b/thirdparty/libpng/pngstruct.h diff --git a/drivers/png/pngtrans.c b/thirdparty/libpng/pngtrans.c index 7f8cc455d3..7f8cc455d3 100644 --- a/drivers/png/pngtrans.c +++ b/thirdparty/libpng/pngtrans.c diff --git a/drivers/png/pngwio.c b/thirdparty/libpng/pngwio.c index 586c03b721..586c03b721 100644 --- a/drivers/png/pngwio.c +++ b/thirdparty/libpng/pngwio.c diff --git a/drivers/png/pngwrite.c b/thirdparty/libpng/pngwrite.c index 181a899438..181a899438 100644 --- a/drivers/png/pngwrite.c +++ b/thirdparty/libpng/pngwrite.c diff --git a/drivers/png/pngwtran.c b/thirdparty/libpng/pngwtran.c index 038a2ef5dc..038a2ef5dc 100644 --- a/drivers/png/pngwtran.c +++ b/thirdparty/libpng/pngwtran.c diff --git a/drivers/png/pngwutil.c b/thirdparty/libpng/pngwutil.c index b47f119d22..b47f119d22 100644 --- a/drivers/png/pngwutil.c +++ b/thirdparty/libpng/pngwutil.c diff --git a/drivers/theora/COPYING b/thirdparty/libtheora/COPYING index c8ccce4ffb..c8ccce4ffb 100644 --- a/drivers/theora/COPYING +++ b/thirdparty/libtheora/COPYING diff --git a/drivers/theora/LICENSE b/thirdparty/libtheora/LICENSE index 5e5ec08469..5e5ec08469 100644 --- a/drivers/theora/LICENSE +++ b/thirdparty/libtheora/LICENSE diff --git a/drivers/theora/analyze.c b/thirdparty/libtheora/analyze.c index af01b60dff..af01b60dff 100644 --- a/drivers/theora/analyze.c +++ b/thirdparty/libtheora/analyze.c diff --git a/drivers/theora/apiwrapper.c b/thirdparty/libtheora/apiwrapper.c index dc959b8d13..dc959b8d13 100644 --- a/drivers/theora/apiwrapper.c +++ b/thirdparty/libtheora/apiwrapper.c diff --git a/drivers/theora/apiwrapper.h b/thirdparty/libtheora/apiwrapper.h index 93454d7bda..93454d7bda 100644 --- a/drivers/theora/apiwrapper.h +++ b/thirdparty/libtheora/apiwrapper.h diff --git a/drivers/theora/bitpack.c b/thirdparty/libtheora/bitpack.c index 8195003bad..8195003bad 100644 --- a/drivers/theora/bitpack.c +++ b/thirdparty/libtheora/bitpack.c diff --git a/drivers/theora/bitpack.h b/thirdparty/libtheora/bitpack.h index a020a292f5..a020a292f5 100644 --- a/drivers/theora/bitpack.h +++ b/thirdparty/libtheora/bitpack.h diff --git a/drivers/theora/cpu.c b/thirdparty/libtheora/cpu.c index a863aad7f3..a863aad7f3 100644 --- a/drivers/theora/cpu.c +++ b/thirdparty/libtheora/cpu.c diff --git a/drivers/theora/cpu.h b/thirdparty/libtheora/cpu.h index a43c957a39..a43c957a39 100644 --- a/drivers/theora/cpu.h +++ b/thirdparty/libtheora/cpu.h diff --git a/drivers/theora/dct.h b/thirdparty/libtheora/dct.h index 24ba6f111a..24ba6f111a 100644 --- a/drivers/theora/dct.h +++ b/thirdparty/libtheora/dct.h diff --git a/drivers/theora/decapiwrapper.c b/thirdparty/libtheora/decapiwrapper.c index 12ea475d17..12ea475d17 100644 --- a/drivers/theora/decapiwrapper.c +++ b/thirdparty/libtheora/decapiwrapper.c diff --git a/drivers/theora/decinfo.c b/thirdparty/libtheora/decinfo.c index 845eb1361c..845eb1361c 100644 --- a/drivers/theora/decinfo.c +++ b/thirdparty/libtheora/decinfo.c diff --git a/drivers/theora/decint.h b/thirdparty/libtheora/decint.h index 261b67631a..261b67631a 100644 --- a/drivers/theora/decint.h +++ b/thirdparty/libtheora/decint.h diff --git a/drivers/theora/decode.c b/thirdparty/libtheora/decode.c index 7be66463d8..7be66463d8 100644 --- a/drivers/theora/decode.c +++ b/thirdparty/libtheora/decode.c diff --git a/drivers/theora/dequant.c b/thirdparty/libtheora/dequant.c index e554872d4e..e554872d4e 100644 --- a/drivers/theora/dequant.c +++ b/thirdparty/libtheora/dequant.c diff --git a/drivers/theora/dequant.h b/thirdparty/libtheora/dequant.h index ef25838e35..ef25838e35 100644 --- a/drivers/theora/dequant.h +++ b/thirdparty/libtheora/dequant.h diff --git a/drivers/theora/encapiwrapper.c b/thirdparty/libtheora/encapiwrapper.c index 874f12442d..874f12442d 100644 --- a/drivers/theora/encapiwrapper.c +++ b/thirdparty/libtheora/encapiwrapper.c diff --git a/drivers/theora/encfrag.c b/thirdparty/libtheora/encfrag.c index bb814c8e4a..bb814c8e4a 100644 --- a/drivers/theora/encfrag.c +++ b/thirdparty/libtheora/encfrag.c diff --git a/drivers/theora/encinfo.c b/thirdparty/libtheora/encinfo.c index 83be1dae72..83be1dae72 100644 --- a/drivers/theora/encinfo.c +++ b/thirdparty/libtheora/encinfo.c diff --git a/drivers/theora/encint.h b/thirdparty/libtheora/encint.h index 97897d5a04..97897d5a04 100644 --- a/drivers/theora/encint.h +++ b/thirdparty/libtheora/encint.h diff --git a/drivers/theora/encode.c b/thirdparty/libtheora/encode.c index 0c5ea6a172..0c5ea6a172 100644 --- a/drivers/theora/encode.c +++ b/thirdparty/libtheora/encode.c diff --git a/drivers/theora/encoder_disabled.c b/thirdparty/libtheora/encoder_disabled.c index 0cbf6645ac..0cbf6645ac 100644 --- a/drivers/theora/encoder_disabled.c +++ b/thirdparty/libtheora/encoder_disabled.c diff --git a/drivers/theora/enquant.c b/thirdparty/libtheora/enquant.c index 3372fed221..3372fed221 100644 --- a/drivers/theora/enquant.c +++ b/thirdparty/libtheora/enquant.c diff --git a/drivers/theora/enquant.h b/thirdparty/libtheora/enquant.h index d62df10d1a..d62df10d1a 100644 --- a/drivers/theora/enquant.h +++ b/thirdparty/libtheora/enquant.h diff --git a/drivers/theora/fdct.c b/thirdparty/libtheora/fdct.c index dc3a66f245..dc3a66f245 100644 --- a/drivers/theora/fdct.c +++ b/thirdparty/libtheora/fdct.c diff --git a/drivers/theora/fragment.c b/thirdparty/libtheora/fragment.c index 15372e9d9f..15372e9d9f 100644 --- a/drivers/theora/fragment.c +++ b/thirdparty/libtheora/fragment.c diff --git a/drivers/theora/huffdec.c b/thirdparty/libtheora/huffdec.c index 8cf27f0341..8cf27f0341 100644 --- a/drivers/theora/huffdec.c +++ b/thirdparty/libtheora/huffdec.c diff --git a/drivers/theora/huffdec.h b/thirdparty/libtheora/huffdec.h index d7ffa0e99b..d7ffa0e99b 100644 --- a/drivers/theora/huffdec.h +++ b/thirdparty/libtheora/huffdec.h diff --git a/drivers/theora/huffenc.c b/thirdparty/libtheora/huffenc.c index bf624e0523..bf624e0523 100644 --- a/drivers/theora/huffenc.c +++ b/thirdparty/libtheora/huffenc.c diff --git a/drivers/theora/huffenc.h b/thirdparty/libtheora/huffenc.h index c5a3956f1f..c5a3956f1f 100644 --- a/drivers/theora/huffenc.h +++ b/thirdparty/libtheora/huffenc.h diff --git a/drivers/theora/huffman.h b/thirdparty/libtheora/huffman.h index 36cf7572e5..36cf7572e5 100644 --- a/drivers/theora/huffman.h +++ b/thirdparty/libtheora/huffman.h diff --git a/drivers/theora/idct.c b/thirdparty/libtheora/idct.c index 0e68ac7658..0e68ac7658 100644 --- a/drivers/theora/idct.c +++ b/thirdparty/libtheora/idct.c diff --git a/drivers/theora/info.c b/thirdparty/libtheora/info.c index 6b9762978b..6b9762978b 100644 --- a/drivers/theora/info.c +++ b/thirdparty/libtheora/info.c diff --git a/drivers/theora/internal.c b/thirdparty/libtheora/internal.c index 0fe4f63e72..0fe4f63e72 100644 --- a/drivers/theora/internal.c +++ b/thirdparty/libtheora/internal.c diff --git a/drivers/theora/internal.h b/thirdparty/libtheora/internal.h index d81263e13e..d81263e13e 100644 --- a/drivers/theora/internal.h +++ b/thirdparty/libtheora/internal.h diff --git a/drivers/theora/mathops.c b/thirdparty/libtheora/mathops.c index d3fb909194..d3fb909194 100644 --- a/drivers/theora/mathops.c +++ b/thirdparty/libtheora/mathops.c diff --git a/drivers/theora/mathops.h b/thirdparty/libtheora/mathops.h index efbc5377b0..efbc5377b0 100644 --- a/drivers/theora/mathops.h +++ b/thirdparty/libtheora/mathops.h diff --git a/drivers/theora/mcenc.c b/thirdparty/libtheora/mcenc.c index 797e81f4f9..797e81f4f9 100644 --- a/drivers/theora/mcenc.c +++ b/thirdparty/libtheora/mcenc.c diff --git a/drivers/theora/modedec.h b/thirdparty/libtheora/modedec.h index ea12c64afd..ea12c64afd 100644 --- a/drivers/theora/modedec.h +++ b/thirdparty/libtheora/modedec.h diff --git a/drivers/theora/ocintrin.h b/thirdparty/libtheora/ocintrin.h index d49ebb2159..d49ebb2159 100644 --- a/drivers/theora/ocintrin.h +++ b/thirdparty/libtheora/ocintrin.h diff --git a/drivers/theora/quant.c b/thirdparty/libtheora/quant.c index 8359f5abea..8359f5abea 100644 --- a/drivers/theora/quant.c +++ b/thirdparty/libtheora/quant.c diff --git a/drivers/theora/quant.h b/thirdparty/libtheora/quant.h index 49ce13a65c..49ce13a65c 100644 --- a/drivers/theora/quant.h +++ b/thirdparty/libtheora/quant.h diff --git a/drivers/theora/rate.c b/thirdparty/libtheora/rate.c index 4f43bb2e5f..4f43bb2e5f 100644 --- a/drivers/theora/rate.c +++ b/thirdparty/libtheora/rate.c diff --git a/drivers/theora/state.c b/thirdparty/libtheora/state.c index 42ed33a9a3..42ed33a9a3 100644 --- a/drivers/theora/state.c +++ b/thirdparty/libtheora/state.c diff --git a/drivers/theora/codec.h b/thirdparty/libtheora/theora/codec.h index 5c2669630c..5c2669630c 100644 --- a/drivers/theora/codec.h +++ b/thirdparty/libtheora/theora/codec.h diff --git a/drivers/theora/theora.h b/thirdparty/libtheora/theora/theora.h index af6eb6f380..af6eb6f380 100644 --- a/drivers/theora/theora.h +++ b/thirdparty/libtheora/theora/theora.h diff --git a/drivers/theora/theoradec.h b/thirdparty/libtheora/theora/theoradec.h index b20f0e3a64..b20f0e3a64 100644 --- a/drivers/theora/theoradec.h +++ b/thirdparty/libtheora/theora/theoradec.h diff --git a/drivers/theora/theoraenc.h b/thirdparty/libtheora/theora/theoraenc.h index fdf2ab21e2..fdf2ab21e2 100644 --- a/drivers/theora/theoraenc.h +++ b/thirdparty/libtheora/theora/theoraenc.h diff --git a/drivers/theora/tokenize.c b/thirdparty/libtheora/tokenize.c index 60574c3594..60574c3594 100644 --- a/drivers/theora/tokenize.c +++ b/thirdparty/libtheora/tokenize.c diff --git a/drivers/theora/x86/mmxencfrag.c b/thirdparty/libtheora/x86/mmxencfrag.c index c79ff01fcc..c79ff01fcc 100644 --- a/drivers/theora/x86/mmxencfrag.c +++ b/thirdparty/libtheora/x86/mmxencfrag.c diff --git a/drivers/theora/x86/mmxfdct.c b/thirdparty/libtheora/x86/mmxfdct.c index 211875255e..211875255e 100644 --- a/drivers/theora/x86/mmxfdct.c +++ b/thirdparty/libtheora/x86/mmxfdct.c diff --git a/drivers/theora/x86/mmxfrag.c b/thirdparty/libtheora/x86/mmxfrag.c index 2c732939c3..2c732939c3 100644 --- a/drivers/theora/x86/mmxfrag.c +++ b/thirdparty/libtheora/x86/mmxfrag.c diff --git a/drivers/theora/x86/mmxfrag.h b/thirdparty/libtheora/x86/mmxfrag.h index a398427629..a398427629 100644 --- a/drivers/theora/x86/mmxfrag.h +++ b/thirdparty/libtheora/x86/mmxfrag.h diff --git a/drivers/theora/x86/mmxidct.c b/thirdparty/libtheora/x86/mmxidct.c index 76424e6364..76424e6364 100644 --- a/drivers/theora/x86/mmxidct.c +++ b/thirdparty/libtheora/x86/mmxidct.c diff --git a/drivers/theora/x86/mmxloop.h b/thirdparty/libtheora/x86/mmxloop.h index 2e870c795d..2e870c795d 100644 --- a/drivers/theora/x86/mmxloop.h +++ b/thirdparty/libtheora/x86/mmxloop.h diff --git a/drivers/theora/x86/mmxstate.c b/thirdparty/libtheora/x86/mmxstate.c index 808b0a789b..808b0a789b 100644 --- a/drivers/theora/x86/mmxstate.c +++ b/thirdparty/libtheora/x86/mmxstate.c diff --git a/drivers/theora/x86/sse2fdct.c b/thirdparty/libtheora/x86/sse2fdct.c index 86c17d68b1..86c17d68b1 100644 --- a/drivers/theora/x86/sse2fdct.c +++ b/thirdparty/libtheora/x86/sse2fdct.c diff --git a/drivers/theora/x86/x86enc.c b/thirdparty/libtheora/x86/x86enc.c index 43b7be3ea3..43b7be3ea3 100644 --- a/drivers/theora/x86/x86enc.c +++ b/thirdparty/libtheora/x86/x86enc.c diff --git a/drivers/theora/x86/x86enc.h b/thirdparty/libtheora/x86/x86enc.h index 06c3908bcd..06c3908bcd 100644 --- a/drivers/theora/x86/x86enc.h +++ b/thirdparty/libtheora/x86/x86enc.h diff --git a/drivers/theora/x86/x86int.h b/thirdparty/libtheora/x86/x86int.h index ede724f5aa..ede724f5aa 100644 --- a/drivers/theora/x86/x86int.h +++ b/thirdparty/libtheora/x86/x86int.h diff --git a/drivers/theora/x86/x86state.c b/thirdparty/libtheora/x86/x86state.c index a786bec284..a786bec284 100644 --- a/drivers/theora/x86/x86state.c +++ b/thirdparty/libtheora/x86/x86state.c diff --git a/drivers/theora/x86_vc/mmxencfrag.c b/thirdparty/libtheora/x86_vc/mmxencfrag.c index ac9dacf377..ac9dacf377 100644 --- a/drivers/theora/x86_vc/mmxencfrag.c +++ b/thirdparty/libtheora/x86_vc/mmxencfrag.c diff --git a/drivers/theora/x86_vc/mmxfdct.c b/thirdparty/libtheora/x86_vc/mmxfdct.c index dcf17c9fa7..dcf17c9fa7 100644 --- a/drivers/theora/x86_vc/mmxfdct.c +++ b/thirdparty/libtheora/x86_vc/mmxfdct.c diff --git a/drivers/theora/x86_vc/mmxfrag.c b/thirdparty/libtheora/x86_vc/mmxfrag.c index 4eb2084dc6..4eb2084dc6 100644 --- a/drivers/theora/x86_vc/mmxfrag.c +++ b/thirdparty/libtheora/x86_vc/mmxfrag.c diff --git a/drivers/theora/x86_vc/mmxfrag.h b/thirdparty/libtheora/x86_vc/mmxfrag.h index 45ee93e777..45ee93e777 100644 --- a/drivers/theora/x86_vc/mmxfrag.h +++ b/thirdparty/libtheora/x86_vc/mmxfrag.h diff --git a/drivers/theora/x86_vc/mmxidct.c b/thirdparty/libtheora/x86_vc/mmxidct.c index 8f5ff6803c..8f5ff6803c 100644 --- a/drivers/theora/x86_vc/mmxidct.c +++ b/thirdparty/libtheora/x86_vc/mmxidct.c diff --git a/drivers/theora/x86_vc/mmxloop.h b/thirdparty/libtheora/x86_vc/mmxloop.h index 2561fca2ae..2561fca2ae 100644 --- a/drivers/theora/x86_vc/mmxloop.h +++ b/thirdparty/libtheora/x86_vc/mmxloop.h diff --git a/drivers/theora/x86_vc/mmxstate.c b/thirdparty/libtheora/x86_vc/mmxstate.c index 73bd1981cf..73bd1981cf 100644 --- a/drivers/theora/x86_vc/mmxstate.c +++ b/thirdparty/libtheora/x86_vc/mmxstate.c diff --git a/drivers/theora/x86_vc/x86enc.c b/thirdparty/libtheora/x86_vc/x86enc.c index e1960e1f0b..e1960e1f0b 100644 --- a/drivers/theora/x86_vc/x86enc.c +++ b/thirdparty/libtheora/x86_vc/x86enc.c diff --git a/drivers/theora/x86_vc/x86enc.h b/thirdparty/libtheora/x86_vc/x86enc.h index 581484641f..581484641f 100644 --- a/drivers/theora/x86_vc/x86enc.h +++ b/thirdparty/libtheora/x86_vc/x86enc.h diff --git a/drivers/theora/x86_vc/x86int.h b/thirdparty/libtheora/x86_vc/x86int.h index 4cca485311..4cca485311 100644 --- a/drivers/theora/x86_vc/x86int.h +++ b/thirdparty/libtheora/x86_vc/x86int.h diff --git a/drivers/theora/x86_vc/x86state.c b/thirdparty/libtheora/x86_vc/x86state.c index a786bec284..a786bec284 100644 --- a/drivers/theora/x86_vc/x86state.c +++ b/thirdparty/libtheora/x86_vc/x86state.c diff --git a/drivers/vorbis/COPYING b/thirdparty/libvorbis/COPYING index 8f1d18cc2b..8f1d18cc2b 100644 --- a/drivers/vorbis/COPYING +++ b/thirdparty/libvorbis/COPYING diff --git a/drivers/vorbis/analysis.c b/thirdparty/libvorbis/analysis.c index 01aa6f30db..01aa6f30db 100644 --- a/drivers/vorbis/analysis.c +++ b/thirdparty/libvorbis/analysis.c diff --git a/drivers/vorbis/backends.h b/thirdparty/libvorbis/backends.h index ff5bcc95fe..ff5bcc95fe 100644 --- a/drivers/vorbis/backends.h +++ b/thirdparty/libvorbis/backends.h diff --git a/drivers/vorbis/barkmel.c b/thirdparty/libvorbis/barkmel.c index 37b6c4c7ba..37b6c4c7ba 100644 --- a/drivers/vorbis/barkmel.c +++ b/thirdparty/libvorbis/barkmel.c diff --git a/drivers/vorbis/bitrate.c b/thirdparty/libvorbis/bitrate.c index 3a71b1dc23..3a71b1dc23 100644 --- a/drivers/vorbis/bitrate.c +++ b/thirdparty/libvorbis/bitrate.c diff --git a/drivers/vorbis/bitrate.h b/thirdparty/libvorbis/bitrate.h index db48fcb645..db48fcb645 100644 --- a/drivers/vorbis/bitrate.h +++ b/thirdparty/libvorbis/bitrate.h diff --git a/drivers/vorbis/block.c b/thirdparty/libvorbis/block.c index 345c042769..345c042769 100644 --- a/drivers/vorbis/block.c +++ b/thirdparty/libvorbis/block.c diff --git a/drivers/vorbis/books/coupled/res_books_51.h b/thirdparty/libvorbis/books/coupled/res_books_51.h index 93910ff481..93910ff481 100644 --- a/drivers/vorbis/books/coupled/res_books_51.h +++ b/thirdparty/libvorbis/books/coupled/res_books_51.h diff --git a/drivers/vorbis/books/coupled/res_books_stereo.h b/thirdparty/libvorbis/books/coupled/res_books_stereo.h index 9a9049f6ed..9a9049f6ed 100644 --- a/drivers/vorbis/books/coupled/res_books_stereo.h +++ b/thirdparty/libvorbis/books/coupled/res_books_stereo.h diff --git a/drivers/vorbis/books/floor/floor_books.h b/thirdparty/libvorbis/books/floor/floor_books.h index e925313f7b..e925313f7b 100644 --- a/drivers/vorbis/books/floor/floor_books.h +++ b/thirdparty/libvorbis/books/floor/floor_books.h diff --git a/drivers/vorbis/books/uncoupled/res_books_uncoupled.h b/thirdparty/libvorbis/books/uncoupled/res_books_uncoupled.h index 736353b675..736353b675 100644 --- a/drivers/vorbis/books/uncoupled/res_books_uncoupled.h +++ b/thirdparty/libvorbis/books/uncoupled/res_books_uncoupled.h diff --git a/drivers/vorbis/codebook.c b/thirdparty/libvorbis/codebook.c index 72f8a17a35..72f8a17a35 100644 --- a/drivers/vorbis/codebook.c +++ b/thirdparty/libvorbis/codebook.c diff --git a/drivers/vorbis/codebook.h b/thirdparty/libvorbis/codebook.h index 537d6c12d3..537d6c12d3 100644 --- a/drivers/vorbis/codebook.h +++ b/thirdparty/libvorbis/codebook.h diff --git a/drivers/vorbis/codec_internal.h b/thirdparty/libvorbis/codec_internal.h index de1bccaedf..de1bccaedf 100644 --- a/drivers/vorbis/codec_internal.h +++ b/thirdparty/libvorbis/codec_internal.h diff --git a/drivers/vorbis/envelope.c b/thirdparty/libvorbis/envelope.c index 010c66e2d6..010c66e2d6 100644 --- a/drivers/vorbis/envelope.c +++ b/thirdparty/libvorbis/envelope.c diff --git a/drivers/vorbis/envelope.h b/thirdparty/libvorbis/envelope.h index fd15fb32a7..fd15fb32a7 100644 --- a/drivers/vorbis/envelope.h +++ b/thirdparty/libvorbis/envelope.h diff --git a/drivers/vorbis/floor0.c b/thirdparty/libvorbis/floor0.c index 213cce4ec8..213cce4ec8 100644 --- a/drivers/vorbis/floor0.c +++ b/thirdparty/libvorbis/floor0.c diff --git a/drivers/vorbis/floor1.c b/thirdparty/libvorbis/floor1.c index d8bd4645c1..d8bd4645c1 100644 --- a/drivers/vorbis/floor1.c +++ b/thirdparty/libvorbis/floor1.c diff --git a/drivers/vorbis/highlevel.h b/thirdparty/libvorbis/highlevel.h index e38f370fd6..e38f370fd6 100644 --- a/drivers/vorbis/highlevel.h +++ b/thirdparty/libvorbis/highlevel.h diff --git a/drivers/vorbis/info.c b/thirdparty/libvorbis/info.c index 8a2a001f99..8a2a001f99 100644 --- a/drivers/vorbis/info.c +++ b/thirdparty/libvorbis/info.c diff --git a/drivers/vorbis/lookup.c b/thirdparty/libvorbis/lookup.c index 3321ed3dbc..3321ed3dbc 100644 --- a/drivers/vorbis/lookup.c +++ b/thirdparty/libvorbis/lookup.c diff --git a/drivers/vorbis/lookup.h b/thirdparty/libvorbis/lookup.h index f8b5b82730..f8b5b82730 100644 --- a/drivers/vorbis/lookup.h +++ b/thirdparty/libvorbis/lookup.h diff --git a/drivers/vorbis/lookup_data.h b/thirdparty/libvorbis/lookup_data.h index 2424a1b386..2424a1b386 100644 --- a/drivers/vorbis/lookup_data.h +++ b/thirdparty/libvorbis/lookup_data.h diff --git a/drivers/vorbis/lpc.c b/thirdparty/libvorbis/lpc.c index f5199ec235..f5199ec235 100644 --- a/drivers/vorbis/lpc.c +++ b/thirdparty/libvorbis/lpc.c diff --git a/drivers/vorbis/lpc.h b/thirdparty/libvorbis/lpc.h index 39d237601b..39d237601b 100644 --- a/drivers/vorbis/lpc.h +++ b/thirdparty/libvorbis/lpc.h diff --git a/drivers/vorbis/lsp.c b/thirdparty/libvorbis/lsp.c index 6a619f7b0c..6a619f7b0c 100644 --- a/drivers/vorbis/lsp.c +++ b/thirdparty/libvorbis/lsp.c diff --git a/drivers/vorbis/lsp.h b/thirdparty/libvorbis/lsp.h index bacfb0971f..bacfb0971f 100644 --- a/drivers/vorbis/lsp.h +++ b/thirdparty/libvorbis/lsp.h diff --git a/drivers/vorbis/mapping0.c b/thirdparty/libvorbis/mapping0.c index 85c7d22d83..85c7d22d83 100644 --- a/drivers/vorbis/mapping0.c +++ b/thirdparty/libvorbis/mapping0.c diff --git a/drivers/vorbis/masking.h b/thirdparty/libvorbis/masking.h index 3576ab7885..3576ab7885 100644 --- a/drivers/vorbis/masking.h +++ b/thirdparty/libvorbis/masking.h diff --git a/drivers/vorbis/mdct.c b/thirdparty/libvorbis/mdct.c index 0816331805..0816331805 100644 --- a/drivers/vorbis/mdct.c +++ b/thirdparty/libvorbis/mdct.c diff --git a/drivers/vorbis/mdct.h b/thirdparty/libvorbis/mdct.h index 3ed94333c5..3ed94333c5 100644 --- a/drivers/vorbis/mdct.h +++ b/thirdparty/libvorbis/mdct.h diff --git a/drivers/vorbis/misc.h b/thirdparty/libvorbis/misc.h index 73b4519898..73b4519898 100644 --- a/drivers/vorbis/misc.h +++ b/thirdparty/libvorbis/misc.h diff --git a/drivers/vorbis/modes/floor_all.h b/thirdparty/libvorbis/modes/floor_all.h index 4292be326e..4292be326e 100644 --- a/drivers/vorbis/modes/floor_all.h +++ b/thirdparty/libvorbis/modes/floor_all.h diff --git a/drivers/vorbis/modes/psych_11.h b/thirdparty/libvorbis/modes/psych_11.h index 844a8ed3cd..844a8ed3cd 100644 --- a/drivers/vorbis/modes/psych_11.h +++ b/thirdparty/libvorbis/modes/psych_11.h diff --git a/drivers/vorbis/modes/psych_16.h b/thirdparty/libvorbis/modes/psych_16.h index 1c10b3954e..1c10b3954e 100644 --- a/drivers/vorbis/modes/psych_16.h +++ b/thirdparty/libvorbis/modes/psych_16.h diff --git a/drivers/vorbis/modes/psych_44.h b/thirdparty/libvorbis/modes/psych_44.h index f05c032653..f05c032653 100644 --- a/drivers/vorbis/modes/psych_44.h +++ b/thirdparty/libvorbis/modes/psych_44.h diff --git a/drivers/vorbis/modes/psych_8.h b/thirdparty/libvorbis/modes/psych_8.h index 0e2dd57371..0e2dd57371 100644 --- a/drivers/vorbis/modes/psych_8.h +++ b/thirdparty/libvorbis/modes/psych_8.h diff --git a/drivers/vorbis/modes/residue_16.h b/thirdparty/libvorbis/modes/residue_16.h index dcaca5451e..dcaca5451e 100644 --- a/drivers/vorbis/modes/residue_16.h +++ b/thirdparty/libvorbis/modes/residue_16.h diff --git a/drivers/vorbis/modes/residue_44.h b/thirdparty/libvorbis/modes/residue_44.h index 236c18341b..236c18341b 100644 --- a/drivers/vorbis/modes/residue_44.h +++ b/thirdparty/libvorbis/modes/residue_44.h diff --git a/drivers/vorbis/modes/residue_44p51.h b/thirdparty/libvorbis/modes/residue_44p51.h index a52cc5245e..a52cc5245e 100644 --- a/drivers/vorbis/modes/residue_44p51.h +++ b/thirdparty/libvorbis/modes/residue_44p51.h diff --git a/drivers/vorbis/modes/residue_44u.h b/thirdparty/libvorbis/modes/residue_44u.h index 92c4a09ce3..92c4a09ce3 100644 --- a/drivers/vorbis/modes/residue_44u.h +++ b/thirdparty/libvorbis/modes/residue_44u.h diff --git a/drivers/vorbis/modes/residue_8.h b/thirdparty/libvorbis/modes/residue_8.h index 94c6d84c44..94c6d84c44 100644 --- a/drivers/vorbis/modes/residue_8.h +++ b/thirdparty/libvorbis/modes/residue_8.h diff --git a/drivers/vorbis/modes/setup_11.h b/thirdparty/libvorbis/modes/setup_11.h index 4c2d619ca2..4c2d619ca2 100644 --- a/drivers/vorbis/modes/setup_11.h +++ b/thirdparty/libvorbis/modes/setup_11.h diff --git a/drivers/vorbis/modes/setup_16.h b/thirdparty/libvorbis/modes/setup_16.h index 336007f98e..336007f98e 100644 --- a/drivers/vorbis/modes/setup_16.h +++ b/thirdparty/libvorbis/modes/setup_16.h diff --git a/drivers/vorbis/modes/setup_22.h b/thirdparty/libvorbis/modes/setup_22.h index 4fd5e57111..4fd5e57111 100644 --- a/drivers/vorbis/modes/setup_22.h +++ b/thirdparty/libvorbis/modes/setup_22.h diff --git a/drivers/vorbis/modes/setup_32.h b/thirdparty/libvorbis/modes/setup_32.h index 2275ac9615..2275ac9615 100644 --- a/drivers/vorbis/modes/setup_32.h +++ b/thirdparty/libvorbis/modes/setup_32.h diff --git a/drivers/vorbis/modes/setup_44.h b/thirdparty/libvorbis/modes/setup_44.h index 3b88a89ac5..3b88a89ac5 100644 --- a/drivers/vorbis/modes/setup_44.h +++ b/thirdparty/libvorbis/modes/setup_44.h diff --git a/drivers/vorbis/modes/setup_44p51.h b/thirdparty/libvorbis/modes/setup_44p51.h index 67d9979608..67d9979608 100644 --- a/drivers/vorbis/modes/setup_44p51.h +++ b/thirdparty/libvorbis/modes/setup_44p51.h diff --git a/drivers/vorbis/modes/setup_44u.h b/thirdparty/libvorbis/modes/setup_44u.h index 568b5f8959..568b5f8959 100644 --- a/drivers/vorbis/modes/setup_44u.h +++ b/thirdparty/libvorbis/modes/setup_44u.h diff --git a/drivers/vorbis/modes/setup_8.h b/thirdparty/libvorbis/modes/setup_8.h index 14c48374fa..14c48374fa 100644 --- a/drivers/vorbis/modes/setup_8.h +++ b/thirdparty/libvorbis/modes/setup_8.h diff --git a/drivers/vorbis/modes/setup_X.h b/thirdparty/libvorbis/modes/setup_X.h index a69f5d40a2..a69f5d40a2 100644 --- a/drivers/vorbis/modes/setup_X.h +++ b/thirdparty/libvorbis/modes/setup_X.h diff --git a/drivers/vorbis/os.h b/thirdparty/libvorbis/os.h index 8bc3e5fe9c..8bc3e5fe9c 100644 --- a/drivers/vorbis/os.h +++ b/thirdparty/libvorbis/os.h diff --git a/drivers/vorbis/psy.c b/thirdparty/libvorbis/psy.c index f7a44c6d00..f7a44c6d00 100644 --- a/drivers/vorbis/psy.c +++ b/thirdparty/libvorbis/psy.c diff --git a/drivers/vorbis/psy.h b/thirdparty/libvorbis/psy.h index c1ea824401..c1ea824401 100644 --- a/drivers/vorbis/psy.h +++ b/thirdparty/libvorbis/psy.h diff --git a/drivers/vorbis/psytune.c b/thirdparty/libvorbis/psytune.c index 64c13171f7..64c13171f7 100644 --- a/drivers/vorbis/psytune.c +++ b/thirdparty/libvorbis/psytune.c diff --git a/drivers/vorbis/registry.c b/thirdparty/libvorbis/registry.c index 3961ed1403..3961ed1403 100644 --- a/drivers/vorbis/registry.c +++ b/thirdparty/libvorbis/registry.c diff --git a/drivers/vorbis/registry.h b/thirdparty/libvorbis/registry.h index 3ae04776d8..3ae04776d8 100644 --- a/drivers/vorbis/registry.h +++ b/thirdparty/libvorbis/registry.h diff --git a/drivers/vorbis/res0.c b/thirdparty/libvorbis/res0.c index ec11488c2f..ec11488c2f 100644 --- a/drivers/vorbis/res0.c +++ b/thirdparty/libvorbis/res0.c diff --git a/drivers/vorbis/scales.h b/thirdparty/libvorbis/scales.h index 613f796e77..613f796e77 100644 --- a/drivers/vorbis/scales.h +++ b/thirdparty/libvorbis/scales.h diff --git a/drivers/vorbis/sharedbook.c b/thirdparty/libvorbis/sharedbook.c index 6bfdf7311e..6bfdf7311e 100644 --- a/drivers/vorbis/sharedbook.c +++ b/thirdparty/libvorbis/sharedbook.c diff --git a/drivers/vorbis/smallft.c b/thirdparty/libvorbis/smallft.c index ae2bc41b6b..ae2bc41b6b 100644 --- a/drivers/vorbis/smallft.c +++ b/thirdparty/libvorbis/smallft.c diff --git a/drivers/vorbis/smallft.h b/thirdparty/libvorbis/smallft.h index 456497326c..456497326c 100644 --- a/drivers/vorbis/smallft.h +++ b/thirdparty/libvorbis/smallft.h diff --git a/drivers/vorbis/synthesis.c b/thirdparty/libvorbis/synthesis.c index 932d271a63..932d271a63 100644 --- a/drivers/vorbis/synthesis.c +++ b/thirdparty/libvorbis/synthesis.c diff --git a/drivers/vorbis/tone.c b/thirdparty/libvorbis/tone.c index 73afc67d4c..73afc67d4c 100644 --- a/drivers/vorbis/tone.c +++ b/thirdparty/libvorbis/tone.c diff --git a/drivers/vorbis/codec.h b/thirdparty/libvorbis/vorbis/codec.h index 999aa33510..999aa33510 100644 --- a/drivers/vorbis/codec.h +++ b/thirdparty/libvorbis/vorbis/codec.h diff --git a/drivers/vorbis/vorbisenc.h b/thirdparty/libvorbis/vorbis/vorbisenc.h index 02332b50ca..02332b50ca 100644 --- a/drivers/vorbis/vorbisenc.h +++ b/thirdparty/libvorbis/vorbis/vorbisenc.h diff --git a/drivers/vorbis/vorbisfile.h b/thirdparty/libvorbis/vorbis/vorbisfile.h index 9271331e72..9271331e72 100644 --- a/drivers/vorbis/vorbisfile.h +++ b/thirdparty/libvorbis/vorbis/vorbisfile.h diff --git a/drivers/vorbis/vorbisenc.c b/thirdparty/libvorbis/vorbisenc.c index b5d621e900..b5d621e900 100644 --- a/drivers/vorbis/vorbisenc.c +++ b/thirdparty/libvorbis/vorbisenc.c diff --git a/drivers/vorbis/vorbisfile.c b/thirdparty/libvorbis/vorbisfile.c index fc0c86ff11..fc0c86ff11 100644 --- a/drivers/vorbis/vorbisfile.c +++ b/thirdparty/libvorbis/vorbisfile.c diff --git a/drivers/vorbis/window.c b/thirdparty/libvorbis/window.c index 0305b79297..0305b79297 100644 --- a/drivers/vorbis/window.c +++ b/thirdparty/libvorbis/window.c diff --git a/drivers/vorbis/window.h b/thirdparty/libvorbis/window.h index 51f97599f5..51f97599f5 100644 --- a/drivers/vorbis/window.h +++ b/thirdparty/libvorbis/window.h diff --git a/drivers/webp/AUTHORS b/thirdparty/libwebp/AUTHORS index 70423cb4dd..70423cb4dd 100644 --- a/drivers/webp/AUTHORS +++ b/thirdparty/libwebp/AUTHORS diff --git a/drivers/webp/COPYING b/thirdparty/libwebp/COPYING index 7a6f99547d..7a6f99547d 100644 --- a/drivers/webp/COPYING +++ b/thirdparty/libwebp/COPYING diff --git a/drivers/webp/PATENTS b/thirdparty/libwebp/PATENTS index caedf607e9..caedf607e9 100644 --- a/drivers/webp/PATENTS +++ b/thirdparty/libwebp/PATENTS diff --git a/thirdparty/libwebp/dec/alpha.c b/thirdparty/libwebp/dec/alpha.c new file mode 100644 index 0000000000..028eb3d50b --- /dev/null +++ b/thirdparty/libwebp/dec/alpha.c @@ -0,0 +1,232 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha-plane decompression. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include <stdlib.h> +#include "./alphai.h" +#include "./vp8i.h" +#include "./vp8li.h" +#include "../dsp/dsp.h" +#include "../utils/quant_levels_dec.h" +#include "../utils/utils.h" +#include "../webp/format_constants.h" + +//------------------------------------------------------------------------------ +// ALPHDecoder object. + +// Allocates a new alpha decoder instance. +static ALPHDecoder* ALPHNew(void) { + ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); + return dec; +} + +// Clears and deallocates an alpha decoder instance. +static void ALPHDelete(ALPHDecoder* const dec) { + if (dec != NULL) { + VP8LDelete(dec->vp8l_dec_); + dec->vp8l_dec_ = NULL; + WebPSafeFree(dec); + } +} + +//------------------------------------------------------------------------------ +// Decoding. + +// Initialize alpha decoding by parsing the alpha header and decoding the image +// header for alpha data stored using lossless compression. +// Returns false in case of error in alpha header (data too short, invalid +// compression method or filter, error in lossless header data etc). +static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, + size_t data_size, const VP8Io* const src_io, + uint8_t* output) { + int ok = 0; + const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; + const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; + int rsrv; + VP8Io* const io = &dec->io_; + + assert(data != NULL && output != NULL && src_io != NULL); + + VP8FiltersInit(); + dec->output_ = output; + dec->width_ = src_io->width; + dec->height_ = src_io->height; + assert(dec->width_ > 0 && dec->height_ > 0); + + if (data_size <= ALPHA_HEADER_LEN) { + return 0; + } + + dec->method_ = (data[0] >> 0) & 0x03; + dec->filter_ = (data[0] >> 2) & 0x03; + dec->pre_processing_ = (data[0] >> 4) & 0x03; + rsrv = (data[0] >> 6) & 0x03; + if (dec->method_ < ALPHA_NO_COMPRESSION || + dec->method_ > ALPHA_LOSSLESS_COMPRESSION || + dec->filter_ >= WEBP_FILTER_LAST || + dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS || + rsrv != 0) { + return 0; + } + + // Copy the necessary parameters from src_io to io + VP8InitIo(io); + WebPInitCustomIo(NULL, io); + io->opaque = dec; + io->width = src_io->width; + io->height = src_io->height; + + io->use_cropping = src_io->use_cropping; + io->crop_left = src_io->crop_left; + io->crop_right = src_io->crop_right; + io->crop_top = src_io->crop_top; + io->crop_bottom = src_io->crop_bottom; + // No need to copy the scaling parameters. + + if (dec->method_ == ALPHA_NO_COMPRESSION) { + const size_t alpha_decoded_size = dec->width_ * dec->height_; + ok = (alpha_data_size >= alpha_decoded_size); + } else { + assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION); + ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size); + } + + return ok; +} + +// Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha +// starting from row number 'row'. It assumes that rows up to (row - 1) have +// already been decoded. +// Returns false in case of bitstream error. +static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) { + ALPHDecoder* const alph_dec = dec->alph_dec_; + const int width = alph_dec->width_; + const int height = alph_dec->io_.crop_bottom; + if (alph_dec->method_ == ALPHA_NO_COMPRESSION) { + int y; + const uint8_t* prev_line = dec->alpha_prev_line_; + const uint8_t* deltas = dec->alpha_data_ + ALPHA_HEADER_LEN + row * width; + uint8_t* dst = dec->alpha_plane_ + row * width; + assert(deltas <= &dec->alpha_data_[dec->alpha_data_size_]); + if (alph_dec->filter_ != WEBP_FILTER_NONE) { + assert(WebPUnfilters[alph_dec->filter_] != NULL); + for (y = 0; y < num_rows; ++y) { + WebPUnfilters[alph_dec->filter_](prev_line, deltas, dst, width); + prev_line = dst; + dst += width; + deltas += width; + } + } else { + for (y = 0; y < num_rows; ++y) { + memcpy(dst, deltas, width * sizeof(*dst)); + prev_line = dst; + dst += width; + deltas += width; + } + } + dec->alpha_prev_line_ = prev_line; + } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION + assert(alph_dec->vp8l_dec_ != NULL); + if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) { + return 0; + } + } + + if (row + num_rows >= height) { + dec->is_alpha_decoded_ = 1; + } + return 1; +} + +static int AllocateAlphaPlane(VP8Decoder* const dec, const VP8Io* const io) { + const int stride = io->width; + const int height = io->crop_bottom; + const uint64_t alpha_size = (uint64_t)stride * height; + assert(dec->alpha_plane_mem_ == NULL); + dec->alpha_plane_mem_ = + (uint8_t*)WebPSafeMalloc(alpha_size, sizeof(*dec->alpha_plane_)); + if (dec->alpha_plane_mem_ == NULL) { + return 0; + } + dec->alpha_plane_ = dec->alpha_plane_mem_; + dec->alpha_prev_line_ = NULL; + return 1; +} + +void WebPDeallocateAlphaMemory(VP8Decoder* const dec) { + assert(dec != NULL); + WebPSafeFree(dec->alpha_plane_mem_); + dec->alpha_plane_mem_ = NULL; + dec->alpha_plane_ = NULL; + ALPHDelete(dec->alph_dec_); + dec->alph_dec_ = NULL; +} + +//------------------------------------------------------------------------------ +// Main entry point. + +const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, + const VP8Io* const io, + int row, int num_rows) { + const int width = io->width; + const int height = io->crop_bottom; + + assert(dec != NULL && io != NULL); + + if (row < 0 || num_rows <= 0 || row + num_rows > height) { + return NULL; // sanity check. + } + + if (!dec->is_alpha_decoded_) { + if (dec->alph_dec_ == NULL) { // Initialize decoder. + dec->alph_dec_ = ALPHNew(); + if (dec->alph_dec_ == NULL) return NULL; + if (!AllocateAlphaPlane(dec, io)) goto Error; + if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_, + io, dec->alpha_plane_)) { + goto Error; + } + // if we allowed use of alpha dithering, check whether it's needed at all + if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) { + dec->alpha_dithering_ = 0; // disable dithering + } else { + num_rows = height - row; // decode everything in one pass + } + } + + assert(dec->alph_dec_ != NULL); + assert(row + num_rows <= height); + if (!ALPHDecode(dec, row, num_rows)) goto Error; + + if (dec->is_alpha_decoded_) { // finished? + ALPHDelete(dec->alph_dec_); + dec->alph_dec_ = NULL; + if (dec->alpha_dithering_ > 0) { + uint8_t* const alpha = dec->alpha_plane_ + io->crop_top * width + + io->crop_left; + if (!WebPDequantizeLevels(alpha, + io->crop_right - io->crop_left, + io->crop_bottom - io->crop_top, + width, dec->alpha_dithering_)) { + goto Error; + } + } + } + } + + // Return a pointer to the current decoded row. + return dec->alpha_plane_ + row * width; + + Error: + WebPDeallocateAlphaMemory(dec); + return NULL; +} diff --git a/drivers/webp/dec/alphai.h b/thirdparty/libwebp/dec/alphai.h index 69dd7c0f5d..69dd7c0f5d 100644 --- a/drivers/webp/dec/alphai.h +++ b/thirdparty/libwebp/dec/alphai.h diff --git a/drivers/webp/dec/buffer.c b/thirdparty/libwebp/dec/buffer.c index 547e69b434..547e69b434 100644 --- a/drivers/webp/dec/buffer.c +++ b/thirdparty/libwebp/dec/buffer.c diff --git a/drivers/webp/dec/common.h b/thirdparty/libwebp/dec/common.h index 6961e22470..6961e22470 100644 --- a/drivers/webp/dec/common.h +++ b/thirdparty/libwebp/dec/common.h diff --git a/thirdparty/libwebp/dec/decode_vp8.h b/thirdparty/libwebp/dec/decode_vp8.h new file mode 100644 index 0000000000..b9337bbec0 --- /dev/null +++ b/thirdparty/libwebp/dec/decode_vp8.h @@ -0,0 +1,185 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Low-level API for VP8 decoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_WEBP_DECODE_VP8_H_ +#define WEBP_WEBP_DECODE_VP8_H_ + +#include "../webp/decode.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Lower-level API +// +// These functions provide fine-grained control of the decoding process. +// The call flow should resemble: +// +// VP8Io io; +// VP8InitIo(&io); +// io.data = data; +// io.data_size = size; +// /* customize io's functions (setup()/put()/teardown()) if needed. */ +// +// VP8Decoder* dec = VP8New(); +// bool ok = VP8Decode(dec); +// if (!ok) printf("Error: %s\n", VP8StatusMessage(dec)); +// VP8Delete(dec); +// return ok; + +// Input / Output +typedef struct VP8Io VP8Io; +typedef int (*VP8IoPutHook)(const VP8Io* io); +typedef int (*VP8IoSetupHook)(VP8Io* io); +typedef void (*VP8IoTeardownHook)(const VP8Io* io); + +struct VP8Io { + // set by VP8GetHeaders() + int width, height; // picture dimensions, in pixels (invariable). + // These are the original, uncropped dimensions. + // The actual area passed to put() is stored + // in mb_w / mb_h fields. + + // set before calling put() + int mb_y; // position of the current rows (in pixels) + int mb_w; // number of columns in the sample + int mb_h; // number of rows in the sample + const uint8_t* y, *u, *v; // rows to copy (in yuv420 format) + int y_stride; // row stride for luma + int uv_stride; // row stride for chroma + + void* opaque; // user data + + // called when fresh samples are available. Currently, samples are in + // YUV420 format, and can be up to width x 24 in size (depending on the + // in-loop filtering level, e.g.). Should return false in case of error + // or abort request. The actual size of the area to update is mb_w x mb_h + // in size, taking cropping into account. + VP8IoPutHook put; + + // called just before starting to decode the blocks. + // Must return false in case of setup error, true otherwise. If false is + // returned, teardown() will NOT be called. But if the setup succeeded + // and true is returned, then teardown() will always be called afterward. + VP8IoSetupHook setup; + + // Called just after block decoding is finished (or when an error occurred + // during put()). Is NOT called if setup() failed. + VP8IoTeardownHook teardown; + + // this is a recommendation for the user-side yuv->rgb converter. This flag + // is set when calling setup() hook and can be overwritten by it. It then + // can be taken into consideration during the put() method. + int fancy_upsampling; + + // Input buffer. + size_t data_size; + const uint8_t* data; + + // If true, in-loop filtering will not be performed even if present in the + // bitstream. Switching off filtering may speed up decoding at the expense + // of more visible blocking. Note that output will also be non-compliant + // with the VP8 specifications. + int bypass_filtering; + + // Cropping parameters. + int use_cropping; + int crop_left, crop_right, crop_top, crop_bottom; + + // Scaling parameters. + int use_scaling; + int scaled_width, scaled_height; + + // If non NULL, pointer to the alpha data (if present) corresponding to the + // start of the current row (That is: it is pre-offset by mb_y and takes + // cropping into account). + const uint8_t* a; +}; + +// Internal, version-checked, entry point +int VP8InitIoInternal(VP8Io* const, int); + +// Set the custom IO function pointers and user-data. The setter for IO hooks +// should be called before initiating incremental decoding. Returns true if +// WebPIDecoder object is successfully modified, false otherwise. +int WebPISetIOHooks(WebPIDecoder* const idec, + VP8IoPutHook put, + VP8IoSetupHook setup, + VP8IoTeardownHook teardown, + void* user_data); + +// Main decoding object. This is an opaque structure. +typedef struct VP8Decoder VP8Decoder; + +// Create a new decoder object. +VP8Decoder* VP8New(void); + +// Must be called to make sure 'io' is initialized properly. +// Returns false in case of version mismatch. Upon such failure, no other +// decoding function should be called (VP8Decode, VP8GetHeaders, ...) +static WEBP_INLINE int VP8InitIo(VP8Io* const io) { + return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION); +} + +// Decode the VP8 frame header. Returns true if ok. +// Note: 'io->data' must be pointing to the start of the VP8 frame header. +int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io); + +// Decode a picture. Will call VP8GetHeaders() if it wasn't done already. +// Returns false in case of error. +int VP8Decode(VP8Decoder* const dec, VP8Io* const io); + +// Return current status of the decoder: +VP8StatusCode VP8Status(VP8Decoder* const dec); + +// return readable string corresponding to the last status. +const char* VP8StatusMessage(VP8Decoder* const dec); + +// Resets the decoder in its initial state, reclaiming memory. +// Not a mandatory call between calls to VP8Decode(). +void VP8Clear(VP8Decoder* const dec); + +// Destroy the decoder object. +void VP8Delete(VP8Decoder* const dec); + +//------------------------------------------------------------------------------ +// Miscellaneous VP8/VP8L bitstream probing functions. + +// Returns true if the next 3 bytes in data contain the VP8 signature. +WEBP_EXTERN(int) VP8CheckSignature(const uint8_t* const data, size_t data_size); + +// Validates the VP8 data-header and retrieves basic header information viz +// width and height. Returns 0 in case of formatting error. *width/*height +// can be passed NULL. +WEBP_EXTERN(int) VP8GetInfo( + const uint8_t* data, + size_t data_size, // data available so far + size_t chunk_size, // total data size expected in the chunk + int* const width, int* const height); + +// Returns true if the next byte(s) in data is a VP8L signature. +WEBP_EXTERN(int) VP8LCheckSignature(const uint8_t* const data, size_t size); + +// Validates the VP8L data-header and retrieves basic header information viz +// width, height and alpha. Returns 0 in case of formatting error. +// width/height/has_alpha can be passed NULL. +WEBP_EXTERN(int) VP8LGetInfo( + const uint8_t* data, size_t data_size, // data available so far + int* const width, int* const height, int* const has_alpha); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_WEBP_DECODE_VP8_H_ */ diff --git a/drivers/webp/dec/frame.c b/thirdparty/libwebp/dec/frame.c index 22d291d2cd..22d291d2cd 100644 --- a/drivers/webp/dec/frame.c +++ b/thirdparty/libwebp/dec/frame.c diff --git a/drivers/webp/dec/idec.c b/thirdparty/libwebp/dec/idec.c index 8de131916e..8de131916e 100644 --- a/drivers/webp/dec/idec.c +++ b/thirdparty/libwebp/dec/idec.c diff --git a/drivers/webp/dec/io.c b/thirdparty/libwebp/dec/io.c index 8d5c43f325..8d5c43f325 100644 --- a/drivers/webp/dec/io.c +++ b/thirdparty/libwebp/dec/io.c diff --git a/drivers/webp/dec/quant.c b/thirdparty/libwebp/dec/quant.c index 5b648f942c..5b648f942c 100644 --- a/drivers/webp/dec/quant.c +++ b/thirdparty/libwebp/dec/quant.c diff --git a/drivers/webp/dec/tree.c b/thirdparty/libwebp/dec/tree.c index c2007ea733..c2007ea733 100644 --- a/drivers/webp/dec/tree.c +++ b/thirdparty/libwebp/dec/tree.c diff --git a/drivers/webp/dec/vp8.c b/thirdparty/libwebp/dec/vp8.c index 336680c38c..336680c38c 100644 --- a/drivers/webp/dec/vp8.c +++ b/thirdparty/libwebp/dec/vp8.c diff --git a/drivers/webp/dec/vp8i.h b/thirdparty/libwebp/dec/vp8i.h index 00da02badc..00da02badc 100644 --- a/drivers/webp/dec/vp8i.h +++ b/thirdparty/libwebp/dec/vp8i.h diff --git a/drivers/webp/dec/vp8l.c b/thirdparty/libwebp/dec/vp8l.c index cb2e3176b6..cb2e3176b6 100644 --- a/drivers/webp/dec/vp8l.c +++ b/thirdparty/libwebp/dec/vp8l.c diff --git a/drivers/webp/dec/vp8li.h b/thirdparty/libwebp/dec/vp8li.h index 9313bdc0af..9313bdc0af 100644 --- a/drivers/webp/dec/vp8li.h +++ b/thirdparty/libwebp/dec/vp8li.h diff --git a/thirdparty/libwebp/dec/webp.c b/thirdparty/libwebp/dec/webp.c new file mode 100644 index 0000000000..d0b912f02f --- /dev/null +++ b/thirdparty/libwebp/dec/webp.c @@ -0,0 +1,846 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Main decoding functions for WEBP images. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include <stdlib.h> + +#include "./vp8i.h" +#include "./vp8li.h" +#include "./webpi.h" +#include "../utils/utils.h" +#include "../webp/mux_types.h" // ALPHA_FLAG + +//------------------------------------------------------------------------------ +// RIFF layout is: +// Offset tag +// 0...3 "RIFF" 4-byte tag +// 4...7 size of image data (including metadata) starting at offset 8 +// 8...11 "WEBP" our form-type signature +// The RIFF container (12 bytes) is followed by appropriate chunks: +// 12..15 "VP8 ": 4-bytes tags, signaling the use of VP8 video format +// 16..19 size of the raw VP8 image data, starting at offset 20 +// 20.... the VP8 bytes +// Or, +// 12..15 "VP8L": 4-bytes tags, signaling the use of VP8L lossless format +// 16..19 size of the raw VP8L image data, starting at offset 20 +// 20.... the VP8L bytes +// Or, +// 12..15 "VP8X": 4-bytes tags, describing the extended-VP8 chunk. +// 16..19 size of the VP8X chunk starting at offset 20. +// 20..23 VP8X flags bit-map corresponding to the chunk-types present. +// 24..26 Width of the Canvas Image. +// 27..29 Height of the Canvas Image. +// There can be extra chunks after the "VP8X" chunk (ICCP, FRGM, ANMF, VP8, +// VP8L, XMP, EXIF ...) +// All sizes are in little-endian order. +// Note: chunk data size must be padded to multiple of 2 when written. + +// Validates the RIFF container (if detected) and skips over it. +// If a RIFF container is detected, returns: +// VP8_STATUS_BITSTREAM_ERROR for invalid header, +// VP8_STATUS_NOT_ENOUGH_DATA for truncated data if have_all_data is true, +// and VP8_STATUS_OK otherwise. +// In case there are not enough bytes (partial RIFF container), return 0 for +// *riff_size. Else return the RIFF size extracted from the header. +static VP8StatusCode ParseRIFF(const uint8_t** const data, + size_t* const data_size, int have_all_data, + size_t* const riff_size) { + assert(data != NULL); + assert(data_size != NULL); + assert(riff_size != NULL); + + *riff_size = 0; // Default: no RIFF present. + if (*data_size >= RIFF_HEADER_SIZE && !memcmp(*data, "RIFF", TAG_SIZE)) { + if (memcmp(*data + 8, "WEBP", TAG_SIZE)) { + return VP8_STATUS_BITSTREAM_ERROR; // Wrong image file signature. + } else { + const uint32_t size = GetLE32(*data + TAG_SIZE); + // Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn"). + if (size < TAG_SIZE + CHUNK_HEADER_SIZE) { + return VP8_STATUS_BITSTREAM_ERROR; + } + if (size > MAX_CHUNK_PAYLOAD) { + return VP8_STATUS_BITSTREAM_ERROR; + } + if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. + } + // We have a RIFF container. Skip it. + *riff_size = size; + *data += RIFF_HEADER_SIZE; + *data_size -= RIFF_HEADER_SIZE; + } + } + return VP8_STATUS_OK; +} + +// Validates the VP8X header and skips over it. +// Returns VP8_STATUS_BITSTREAM_ERROR for invalid VP8X header, +// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and +// VP8_STATUS_OK otherwise. +// If a VP8X chunk is found, found_vp8x is set to true and *width_ptr, +// *height_ptr and *flags_ptr are set to the corresponding values extracted +// from the VP8X chunk. +static VP8StatusCode ParseVP8X(const uint8_t** const data, + size_t* const data_size, + int* const found_vp8x, + int* const width_ptr, int* const height_ptr, + uint32_t* const flags_ptr) { + const uint32_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; + assert(data != NULL); + assert(data_size != NULL); + assert(found_vp8x != NULL); + + *found_vp8x = 0; + + if (*data_size < CHUNK_HEADER_SIZE) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. + } + + if (!memcmp(*data, "VP8X", TAG_SIZE)) { + int width, height; + uint32_t flags; + const uint32_t chunk_size = GetLE32(*data + TAG_SIZE); + if (chunk_size != VP8X_CHUNK_SIZE) { + return VP8_STATUS_BITSTREAM_ERROR; // Wrong chunk size. + } + + // Verify if enough data is available to validate the VP8X chunk. + if (*data_size < vp8x_size) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. + } + flags = GetLE32(*data + 8); + width = 1 + GetLE24(*data + 12); + height = 1 + GetLE24(*data + 15); + if (width * (uint64_t)height >= MAX_IMAGE_AREA) { + return VP8_STATUS_BITSTREAM_ERROR; // image is too large + } + + if (flags_ptr != NULL) *flags_ptr = flags; + if (width_ptr != NULL) *width_ptr = width; + if (height_ptr != NULL) *height_ptr = height; + // Skip over VP8X header bytes. + *data += vp8x_size; + *data_size -= vp8x_size; + *found_vp8x = 1; + } + return VP8_STATUS_OK; +} + +// Skips to the next VP8/VP8L chunk header in the data given the size of the +// RIFF chunk 'riff_size'. +// Returns VP8_STATUS_BITSTREAM_ERROR if any invalid chunk size is encountered, +// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and +// VP8_STATUS_OK otherwise. +// If an alpha chunk is found, *alpha_data and *alpha_size are set +// appropriately. +static VP8StatusCode ParseOptionalChunks(const uint8_t** const data, + size_t* const data_size, + size_t const riff_size, + const uint8_t** const alpha_data, + size_t* const alpha_size) { + const uint8_t* buf; + size_t buf_size; + uint32_t total_size = TAG_SIZE + // "WEBP". + CHUNK_HEADER_SIZE + // "VP8Xnnnn". + VP8X_CHUNK_SIZE; // data. + assert(data != NULL); + assert(data_size != NULL); + buf = *data; + buf_size = *data_size; + + assert(alpha_data != NULL); + assert(alpha_size != NULL); + *alpha_data = NULL; + *alpha_size = 0; + + while (1) { + uint32_t chunk_size; + uint32_t disk_chunk_size; // chunk_size with padding + + *data = buf; + *data_size = buf_size; + + if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data. + return VP8_STATUS_NOT_ENOUGH_DATA; + } + + chunk_size = GetLE32(buf + TAG_SIZE); + if (chunk_size > MAX_CHUNK_PAYLOAD) { + return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. + } + // For odd-sized chunk-payload, there's one byte padding at the end. + disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1; + total_size += disk_chunk_size; + + // Check that total bytes skipped so far does not exceed riff_size. + if (riff_size > 0 && (total_size > riff_size)) { + return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. + } + + // Start of a (possibly incomplete) VP8/VP8L chunk implies that we have + // parsed all the optional chunks. + // Note: This check must occur before the check 'buf_size < disk_chunk_size' + // below to allow incomplete VP8/VP8L chunks. + if (!memcmp(buf, "VP8 ", TAG_SIZE) || + !memcmp(buf, "VP8L", TAG_SIZE)) { + return VP8_STATUS_OK; + } + + if (buf_size < disk_chunk_size) { // Insufficient data. + return VP8_STATUS_NOT_ENOUGH_DATA; + } + + if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header. + *alpha_data = buf + CHUNK_HEADER_SIZE; + *alpha_size = chunk_size; + } + + // We have a full and valid chunk; skip it. + buf += disk_chunk_size; + buf_size -= disk_chunk_size; + } +} + +// Validates the VP8/VP8L Header ("VP8 nnnn" or "VP8L nnnn") and skips over it. +// Returns VP8_STATUS_BITSTREAM_ERROR for invalid (chunk larger than +// riff_size) VP8/VP8L header, +// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and +// VP8_STATUS_OK otherwise. +// If a VP8/VP8L chunk is found, *chunk_size is set to the total number of bytes +// extracted from the VP8/VP8L chunk header. +// The flag '*is_lossless' is set to 1 in case of VP8L chunk / raw VP8L data. +static VP8StatusCode ParseVP8Header(const uint8_t** const data_ptr, + size_t* const data_size, int have_all_data, + size_t riff_size, size_t* const chunk_size, + int* const is_lossless) { + const uint8_t* const data = *data_ptr; + const int is_vp8 = !memcmp(data, "VP8 ", TAG_SIZE); + const int is_vp8l = !memcmp(data, "VP8L", TAG_SIZE); + const uint32_t minimal_size = + TAG_SIZE + CHUNK_HEADER_SIZE; // "WEBP" + "VP8 nnnn" OR + // "WEBP" + "VP8Lnnnn" + assert(data != NULL); + assert(data_size != NULL); + assert(chunk_size != NULL); + assert(is_lossless != NULL); + + if (*data_size < CHUNK_HEADER_SIZE) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. + } + + if (is_vp8 || is_vp8l) { + // Bitstream contains VP8/VP8L header. + const uint32_t size = GetLE32(data + TAG_SIZE); + if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) { + return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information. + } + if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. + } + // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header. + *chunk_size = size; + *data_ptr += CHUNK_HEADER_SIZE; + *data_size -= CHUNK_HEADER_SIZE; + *is_lossless = is_vp8l; + } else { + // Raw VP8/VP8L bitstream (no header). + *is_lossless = VP8LCheckSignature(data, *data_size); + *chunk_size = *data_size; + } + + return VP8_STATUS_OK; +} + +//------------------------------------------------------------------------------ + +// Fetch '*width', '*height', '*has_alpha' and fill out 'headers' based on +// 'data'. All the output parameters may be NULL. If 'headers' is NULL only the +// minimal amount will be read to fetch the remaining parameters. +// If 'headers' is non-NULL this function will attempt to locate both alpha +// data (with or without a VP8X chunk) and the bitstream chunk (VP8/VP8L). +// Note: The following chunk sequences (before the raw VP8/VP8L data) are +// considered valid by this function: +// RIFF + VP8(L) +// RIFF + VP8X + (optional chunks) + VP8(L) +// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. +// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. +static VP8StatusCode ParseHeadersInternal(const uint8_t* data, + size_t data_size, + int* const width, + int* const height, + int* const has_alpha, + int* const has_animation, + int* const format, + WebPHeaderStructure* const headers) { + int canvas_width = 0; + int canvas_height = 0; + int image_width = 0; + int image_height = 0; + int found_riff = 0; + int found_vp8x = 0; + int animation_present = 0; + int fragments_present = 0; + const int have_all_data = (headers != NULL) ? headers->have_all_data : 0; + + VP8StatusCode status; + WebPHeaderStructure hdrs; + + if (data == NULL || data_size < RIFF_HEADER_SIZE) { + return VP8_STATUS_NOT_ENOUGH_DATA; + } + memset(&hdrs, 0, sizeof(hdrs)); + hdrs.data = data; + hdrs.data_size = data_size; + + // Skip over RIFF header. + status = ParseRIFF(&data, &data_size, have_all_data, &hdrs.riff_size); + if (status != VP8_STATUS_OK) { + return status; // Wrong RIFF header / insufficient data. + } + found_riff = (hdrs.riff_size > 0); + + // Skip over VP8X. + { + uint32_t flags = 0; + status = ParseVP8X(&data, &data_size, &found_vp8x, + &canvas_width, &canvas_height, &flags); + if (status != VP8_STATUS_OK) { + return status; // Wrong VP8X / insufficient data. + } + animation_present = !!(flags & ANIMATION_FLAG); + fragments_present = !!(flags & FRAGMENTS_FLAG); + if (!found_riff && found_vp8x) { + // Note: This restriction may be removed in the future, if it becomes + // necessary to send VP8X chunk to the decoder. + return VP8_STATUS_BITSTREAM_ERROR; + } + if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG); + if (has_animation != NULL) *has_animation = animation_present; + if (format != NULL) *format = 0; // default = undefined + + image_width = canvas_width; + image_height = canvas_height; + if (found_vp8x && (animation_present || fragments_present) && + headers == NULL) { + status = VP8_STATUS_OK; + goto ReturnWidthHeight; // Just return features from VP8X header. + } + } + + if (data_size < TAG_SIZE) { + status = VP8_STATUS_NOT_ENOUGH_DATA; + goto ReturnWidthHeight; + } + + // Skip over optional chunks if data started with "RIFF + VP8X" or "ALPH". + if ((found_riff && found_vp8x) || + (!found_riff && !found_vp8x && !memcmp(data, "ALPH", TAG_SIZE))) { + status = ParseOptionalChunks(&data, &data_size, hdrs.riff_size, + &hdrs.alpha_data, &hdrs.alpha_data_size); + if (status != VP8_STATUS_OK) { + goto ReturnWidthHeight; // Invalid chunk size / insufficient data. + } + } + + // Skip over VP8/VP8L header. + status = ParseVP8Header(&data, &data_size, have_all_data, hdrs.riff_size, + &hdrs.compressed_size, &hdrs.is_lossless); + if (status != VP8_STATUS_OK) { + goto ReturnWidthHeight; // Wrong VP8/VP8L chunk-header / insufficient data. + } + if (hdrs.compressed_size > MAX_CHUNK_PAYLOAD) { + return VP8_STATUS_BITSTREAM_ERROR; + } + + if (format != NULL && !(animation_present || fragments_present)) { + *format = hdrs.is_lossless ? 2 : 1; + } + + if (!hdrs.is_lossless) { + if (data_size < VP8_FRAME_HEADER_SIZE) { + status = VP8_STATUS_NOT_ENOUGH_DATA; + goto ReturnWidthHeight; + } + // Validates raw VP8 data. + if (!VP8GetInfo(data, data_size, (uint32_t)hdrs.compressed_size, + &image_width, &image_height)) { + return VP8_STATUS_BITSTREAM_ERROR; + } + } else { + if (data_size < VP8L_FRAME_HEADER_SIZE) { + status = VP8_STATUS_NOT_ENOUGH_DATA; + goto ReturnWidthHeight; + } + // Validates raw VP8L data. + if (!VP8LGetInfo(data, data_size, &image_width, &image_height, has_alpha)) { + return VP8_STATUS_BITSTREAM_ERROR; + } + } + // Validates image size coherency. + if (found_vp8x) { + if (canvas_width != image_width || canvas_height != image_height) { + return VP8_STATUS_BITSTREAM_ERROR; + } + } + if (headers != NULL) { + *headers = hdrs; + headers->offset = data - headers->data; + assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD); + assert(headers->offset == headers->data_size - data_size); + } + ReturnWidthHeight: + if (status == VP8_STATUS_OK || + (status == VP8_STATUS_NOT_ENOUGH_DATA && found_vp8x && headers == NULL)) { + if (has_alpha != NULL) { + // If the data did not contain a VP8X/VP8L chunk the only definitive way + // to set this is by looking for alpha data (from an ALPH chunk). + *has_alpha |= (hdrs.alpha_data != NULL); + } + if (width != NULL) *width = image_width; + if (height != NULL) *height = image_height; + return VP8_STATUS_OK; + } else { + return status; + } +} + +VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) { + // status is marked volatile as a workaround for a clang-3.8 (aarch64) bug + volatile VP8StatusCode status; + int has_animation = 0; + assert(headers != NULL); + // fill out headers, ignore width/height/has_alpha. + status = ParseHeadersInternal(headers->data, headers->data_size, + NULL, NULL, NULL, &has_animation, + NULL, headers); + if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) { + // TODO(jzern): full support of animation frames will require API additions. + if (has_animation) { + status = VP8_STATUS_UNSUPPORTED_FEATURE; + } + } + return status; +} + +//------------------------------------------------------------------------------ +// WebPDecParams + +void WebPResetDecParams(WebPDecParams* const params) { + if (params != NULL) { + memset(params, 0, sizeof(*params)); + } +} + +//------------------------------------------------------------------------------ +// "Into" decoding variants + +// Main flow +static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size, + WebPDecParams* const params) { + VP8StatusCode status; + VP8Io io; + WebPHeaderStructure headers; + + headers.data = data; + headers.data_size = data_size; + headers.have_all_data = 1; + status = WebPParseHeaders(&headers); // Process Pre-VP8 chunks. + if (status != VP8_STATUS_OK) { + return status; + } + + assert(params != NULL); + VP8InitIo(&io); + io.data = headers.data + headers.offset; + io.data_size = headers.data_size - headers.offset; + WebPInitCustomIo(params, &io); // Plug the I/O functions. + + if (!headers.is_lossless) { + VP8Decoder* const dec = VP8New(); + if (dec == NULL) { + return VP8_STATUS_OUT_OF_MEMORY; + } + dec->alpha_data_ = headers.alpha_data; + dec->alpha_data_size_ = headers.alpha_data_size; + + // Decode bitstream header, update io->width/io->height. + if (!VP8GetHeaders(dec, &io)) { + status = dec->status_; // An error occurred. Grab error status. + } else { + // Allocate/check output buffers. + status = WebPAllocateDecBuffer(io.width, io.height, params->options, + params->output); + if (status == VP8_STATUS_OK) { // Decode + // This change must be done before calling VP8Decode() + dec->mt_method_ = VP8GetThreadMethod(params->options, &headers, + io.width, io.height); + VP8InitDithering(params->options, dec); + if (!VP8Decode(dec, &io)) { + status = dec->status_; + } + } + } + VP8Delete(dec); + } else { + VP8LDecoder* const dec = VP8LNew(); + if (dec == NULL) { + return VP8_STATUS_OUT_OF_MEMORY; + } + if (!VP8LDecodeHeader(dec, &io)) { + status = dec->status_; // An error occurred. Grab error status. + } else { + // Allocate/check output buffers. + status = WebPAllocateDecBuffer(io.width, io.height, params->options, + params->output); + if (status == VP8_STATUS_OK) { // Decode + if (!VP8LDecodeImage(dec)) { + status = dec->status_; + } + } + } + VP8LDelete(dec); + } + + if (status != VP8_STATUS_OK) { + WebPFreeDecBuffer(params->output); + } else { + if (params->options != NULL && params->options->flip) { + // This restores the original stride values if options->flip was used + // during the call to WebPAllocateDecBuffer above. + status = WebPFlipBuffer(params->output); + } + } + return status; +} + +// Helpers +static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace, + const uint8_t* const data, + size_t data_size, + uint8_t* const rgba, + int stride, size_t size) { + WebPDecParams params; + WebPDecBuffer buf; + if (rgba == NULL) { + return NULL; + } + WebPInitDecBuffer(&buf); + WebPResetDecParams(¶ms); + params.output = &buf; + buf.colorspace = colorspace; + buf.u.RGBA.rgba = rgba; + buf.u.RGBA.stride = stride; + buf.u.RGBA.size = size; + buf.is_external_memory = 1; + if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { + return NULL; + } + return rgba; +} + +uint8_t* WebPDecodeRGBInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_RGB, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeRGBAInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_RGBA, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeARGBInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_ARGB, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeBGRInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_BGR, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeBGRAInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_BGRA, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size, + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride) { + WebPDecParams params; + WebPDecBuffer output; + if (luma == NULL) return NULL; + WebPInitDecBuffer(&output); + WebPResetDecParams(¶ms); + params.output = &output; + output.colorspace = MODE_YUV; + output.u.YUVA.y = luma; + output.u.YUVA.y_stride = luma_stride; + output.u.YUVA.y_size = luma_size; + output.u.YUVA.u = u; + output.u.YUVA.u_stride = u_stride; + output.u.YUVA.u_size = u_size; + output.u.YUVA.v = v; + output.u.YUVA.v_stride = v_stride; + output.u.YUVA.v_size = v_size; + output.is_external_memory = 1; + if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { + return NULL; + } + return luma; +} + +//------------------------------------------------------------------------------ + +static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data, + size_t data_size, int* const width, int* const height, + WebPDecBuffer* const keep_info) { + WebPDecParams params; + WebPDecBuffer output; + + WebPInitDecBuffer(&output); + WebPResetDecParams(¶ms); + params.output = &output; + output.colorspace = mode; + + // Retrieve (and report back) the required dimensions from bitstream. + if (!WebPGetInfo(data, data_size, &output.width, &output.height)) { + return NULL; + } + if (width != NULL) *width = output.width; + if (height != NULL) *height = output.height; + + // Decode + if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { + return NULL; + } + if (keep_info != NULL) { // keep track of the side-info + WebPCopyDecBuffer(&output, keep_info); + } + // return decoded samples (don't clear 'output'!) + return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y; +} + +uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_RGB, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_RGBA, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_ARGB, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_BGR, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_BGRA, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, + int* width, int* height, uint8_t** u, uint8_t** v, + int* stride, int* uv_stride) { + WebPDecBuffer output; // only to preserve the side-infos + uint8_t* const out = Decode(MODE_YUV, data, data_size, + width, height, &output); + + if (out != NULL) { + const WebPYUVABuffer* const buf = &output.u.YUVA; + *u = buf->u; + *v = buf->v; + *stride = buf->y_stride; + *uv_stride = buf->u_stride; + assert(buf->u_stride == buf->v_stride); + } + return out; +} + +static void DefaultFeatures(WebPBitstreamFeatures* const features) { + assert(features != NULL); + memset(features, 0, sizeof(*features)); +} + +static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size, + WebPBitstreamFeatures* const features) { + if (features == NULL || data == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + DefaultFeatures(features); + + // Only parse enough of the data to retrieve the features. + return ParseHeadersInternal(data, data_size, + &features->width, &features->height, + &features->has_alpha, &features->has_animation, + &features->format, NULL); +} + +//------------------------------------------------------------------------------ +// WebPGetInfo() + +int WebPGetInfo(const uint8_t* data, size_t data_size, + int* width, int* height) { + WebPBitstreamFeatures features; + + if (GetFeatures(data, data_size, &features) != VP8_STATUS_OK) { + return 0; + } + + if (width != NULL) { + *width = features.width; + } + if (height != NULL) { + *height = features.height; + } + + return 1; +} + +//------------------------------------------------------------------------------ +// Advance decoding API + +int WebPInitDecoderConfigInternal(WebPDecoderConfig* config, + int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { + return 0; // version mismatch + } + if (config == NULL) { + return 0; + } + memset(config, 0, sizeof(*config)); + DefaultFeatures(&config->input); + WebPInitDecBuffer(&config->output); + return 1; +} + +VP8StatusCode WebPGetFeaturesInternal(const uint8_t* data, size_t data_size, + WebPBitstreamFeatures* features, + int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { + return VP8_STATUS_INVALID_PARAM; // version mismatch + } + if (features == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + return GetFeatures(data, data_size, features); +} + +VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config) { + WebPDecParams params; + VP8StatusCode status; + + if (config == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + + status = GetFeatures(data, data_size, &config->input); + if (status != VP8_STATUS_OK) { + if (status == VP8_STATUS_NOT_ENOUGH_DATA) { + return VP8_STATUS_BITSTREAM_ERROR; // Not-enough-data treated as error. + } + return status; + } + + WebPResetDecParams(¶ms); + params.options = &config->options; + params.output = &config->output; + if (WebPAvoidSlowMemory(params.output, &config->input)) { + // decoding to slow memory: use a temporary in-mem buffer to decode into. + WebPDecBuffer in_mem_buffer; + WebPInitDecBuffer(&in_mem_buffer); + in_mem_buffer.colorspace = config->output.colorspace; + in_mem_buffer.width = config->input.width; + in_mem_buffer.height = config->input.height; + params.output = &in_mem_buffer; + status = DecodeInto(data, data_size, ¶ms); + if (status == VP8_STATUS_OK) { // do the slow-copy + status = WebPCopyDecBufferPixels(&in_mem_buffer, &config->output); + } + WebPFreeDecBuffer(&in_mem_buffer); + } else { + status = DecodeInto(data, data_size, ¶ms); + } + + return status; +} + +//------------------------------------------------------------------------------ +// Cropping and rescaling. + +int WebPIoInitFromOptions(const WebPDecoderOptions* const options, + VP8Io* const io, WEBP_CSP_MODE src_colorspace) { + const int W = io->width; + const int H = io->height; + int x = 0, y = 0, w = W, h = H; + + // Cropping + io->use_cropping = (options != NULL) && (options->use_cropping > 0); + if (io->use_cropping) { + w = options->crop_width; + h = options->crop_height; + x = options->crop_left; + y = options->crop_top; + if (!WebPIsRGBMode(src_colorspace)) { // only snap for YUV420 + x &= ~1; + y &= ~1; + } + if (x < 0 || y < 0 || w <= 0 || h <= 0 || x + w > W || y + h > H) { + return 0; // out of frame boundary error + } + } + io->crop_left = x; + io->crop_top = y; + io->crop_right = x + w; + io->crop_bottom = y + h; + io->mb_w = w; + io->mb_h = h; + + // Scaling + io->use_scaling = (options != NULL) && (options->use_scaling > 0); + if (io->use_scaling) { + int scaled_width = options->scaled_width; + int scaled_height = options->scaled_height; + if (!WebPRescalerGetScaledDimensions(w, h, &scaled_width, &scaled_height)) { + return 0; + } + io->scaled_width = scaled_width; + io->scaled_height = scaled_height; + } + + // Filter + io->bypass_filtering = (options != NULL) && options->bypass_filtering; + + // Fancy upsampler +#ifdef FANCY_UPSAMPLING + io->fancy_upsampling = (options == NULL) || (!options->no_fancy_upsampling); +#endif + + if (io->use_scaling) { + // disable filter (only for large downscaling ratio). + io->bypass_filtering = (io->scaled_width < W * 3 / 4) && + (io->scaled_height < H * 3 / 4); + io->fancy_upsampling = 0; + } + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/drivers/webp/dec/webpi.h b/thirdparty/libwebp/dec/webpi.h index 991b194c22..991b194c22 100644 --- a/drivers/webp/dec/webpi.h +++ b/thirdparty/libwebp/dec/webpi.h diff --git a/thirdparty/libwebp/demux/anim_decode.c b/thirdparty/libwebp/demux/anim_decode.c new file mode 100644 index 0000000000..1989eb4ab4 --- /dev/null +++ b/thirdparty/libwebp/demux/anim_decode.c @@ -0,0 +1,442 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// AnimDecoder implementation. +// + +#ifdef HAVE_CONFIG_H +#include "../webp/config.h" +#endif + +#include <assert.h> +#include <string.h> + +#include "../utils/utils.h" +#include "../webp/decode.h" +#include "../webp/demux.h" + +#define NUM_CHANNELS 4 + +typedef void (*BlendRowFunc)(uint32_t* const, const uint32_t* const, int); +static void BlendPixelRowNonPremult(uint32_t* const src, + const uint32_t* const dst, int num_pixels); +static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst, + int num_pixels); + +struct WebPAnimDecoder { + WebPDemuxer* demux_; // Demuxer created from given WebP bitstream. + WebPDecoderConfig config_; // Decoder config. + // Note: we use a pointer to a function blending multiple pixels at a time to + // allow possible inlining of per-pixel blending function. + BlendRowFunc blend_func_; // Pointer to the chose blend row function. + WebPAnimInfo info_; // Global info about the animation. + uint8_t* curr_frame_; // Current canvas (not disposed). + uint8_t* prev_frame_disposed_; // Previous canvas (properly disposed). + int prev_frame_timestamp_; // Previous frame timestamp (milliseconds). + WebPIterator prev_iter_; // Iterator object for previous frame. + int prev_frame_was_keyframe_; // True if previous frame was a keyframe. + int next_frame_; // Index of the next frame to be decoded + // (starting from 1). +}; + +static void DefaultDecoderOptions(WebPAnimDecoderOptions* const dec_options) { + dec_options->color_mode = MODE_RGBA; + dec_options->use_threads = 0; +} + +int WebPAnimDecoderOptionsInitInternal(WebPAnimDecoderOptions* dec_options, + int abi_version) { + if (dec_options == NULL || + WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) { + return 0; + } + DefaultDecoderOptions(dec_options); + return 1; +} + +static int ApplyDecoderOptions(const WebPAnimDecoderOptions* const dec_options, + WebPAnimDecoder* const dec) { + WEBP_CSP_MODE mode; + WebPDecoderConfig* config = &dec->config_; + assert(dec_options != NULL); + + mode = dec_options->color_mode; + if (mode != MODE_RGBA && mode != MODE_BGRA && + mode != MODE_rgbA && mode != MODE_bgrA) { + return 0; + } + dec->blend_func_ = (mode == MODE_RGBA || mode == MODE_BGRA) + ? &BlendPixelRowNonPremult + : &BlendPixelRowPremult; + WebPInitDecoderConfig(config); + config->output.colorspace = mode; + config->output.is_external_memory = 1; + config->options.use_threads = dec_options->use_threads; + // Note: config->output.u.RGBA is set at the time of decoding each frame. + return 1; +} + +WebPAnimDecoder* WebPAnimDecoderNewInternal( + const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options, + int abi_version) { + WebPAnimDecoderOptions options; + WebPAnimDecoder* dec = NULL; + if (webp_data == NULL || + WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) { + return NULL; + } + + // Note: calloc() so that the pointer members are initialized to NULL. + dec = (WebPAnimDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); + if (dec == NULL) goto Error; + + if (dec_options != NULL) { + options = *dec_options; + } else { + DefaultDecoderOptions(&options); + } + if (!ApplyDecoderOptions(&options, dec)) goto Error; + + dec->demux_ = WebPDemux(webp_data); + if (dec->demux_ == NULL) goto Error; + + dec->info_.canvas_width = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_WIDTH); + dec->info_.canvas_height = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_HEIGHT); + dec->info_.loop_count = WebPDemuxGetI(dec->demux_, WEBP_FF_LOOP_COUNT); + dec->info_.bgcolor = WebPDemuxGetI(dec->demux_, WEBP_FF_BACKGROUND_COLOR); + dec->info_.frame_count = WebPDemuxGetI(dec->demux_, WEBP_FF_FRAME_COUNT); + + { + const int canvas_bytes = + dec->info_.canvas_width * NUM_CHANNELS * dec->info_.canvas_height; + // Note: calloc() because we fill frame with zeroes as well. + dec->curr_frame_ = WebPSafeCalloc(1ULL, canvas_bytes); + if (dec->curr_frame_ == NULL) goto Error; + dec->prev_frame_disposed_ = WebPSafeCalloc(1ULL, canvas_bytes); + if (dec->prev_frame_disposed_ == NULL) goto Error; + } + + WebPAnimDecoderReset(dec); + + return dec; + + Error: + WebPAnimDecoderDelete(dec); + return NULL; +} + +int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, WebPAnimInfo* info) { + if (dec == NULL || info == NULL) return 0; + *info = dec->info_; + return 1; +} + +// Returns true if the frame covers the full canvas. +static int IsFullFrame(int width, int height, int canvas_width, + int canvas_height) { + return (width == canvas_width && height == canvas_height); +} + +// Clear the canvas to transparent. +static void ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width, + uint32_t canvas_height) { + memset(buf, 0, canvas_width * NUM_CHANNELS * canvas_height); +} + +// Clear given frame rectangle to transparent. +static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset, + int y_offset, int width, int height) { + int j; + assert(width * NUM_CHANNELS <= buf_stride); + buf += y_offset * buf_stride + x_offset * NUM_CHANNELS; + for (j = 0; j < height; ++j) { + memset(buf, 0, width * NUM_CHANNELS); + buf += buf_stride; + } +} + +// Copy width * height pixels from 'src' to 'dst'. +static void CopyCanvas(const uint8_t* src, uint8_t* dst, + uint32_t width, uint32_t height) { + assert(src != NULL && dst != NULL); + memcpy(dst, src, width * NUM_CHANNELS * height); +} + +// Returns true if the current frame is a key-frame. +static int IsKeyFrame(const WebPIterator* const curr, + const WebPIterator* const prev, + int prev_frame_was_key_frame, + int canvas_width, int canvas_height) { + if (curr->frame_num == 1) { + return 1; + } else if ((!curr->has_alpha || curr->blend_method == WEBP_MUX_NO_BLEND) && + IsFullFrame(curr->width, curr->height, + canvas_width, canvas_height)) { + return 1; + } else { + return (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) && + (IsFullFrame(prev->width, prev->height, canvas_width, + canvas_height) || + prev_frame_was_key_frame); + } +} + + +// Blend a single channel of 'src' over 'dst', given their alpha channel values. +// 'src' and 'dst' are assumed to be NOT pre-multiplied by alpha. +static uint8_t BlendChannelNonPremult(uint32_t src, uint8_t src_a, + uint32_t dst, uint8_t dst_a, + uint32_t scale, int shift) { + const uint8_t src_channel = (src >> shift) & 0xff; + const uint8_t dst_channel = (dst >> shift) & 0xff; + const uint32_t blend_unscaled = src_channel * src_a + dst_channel * dst_a; + assert(blend_unscaled < (1ULL << 32) / scale); + return (blend_unscaled * scale) >> 24; +} + +// Blend 'src' over 'dst' assuming they are NOT pre-multiplied by alpha. +static uint32_t BlendPixelNonPremult(uint32_t src, uint32_t dst) { + const uint8_t src_a = (src >> 24) & 0xff; + + if (src_a == 0) { + return dst; + } else { + const uint8_t dst_a = (dst >> 24) & 0xff; + // This is the approximate integer arithmetic for the actual formula: + // dst_factor_a = (dst_a * (255 - src_a)) / 255. + const uint8_t dst_factor_a = (dst_a * (256 - src_a)) >> 8; + const uint8_t blend_a = src_a + dst_factor_a; + const uint32_t scale = (1UL << 24) / blend_a; + + const uint8_t blend_r = + BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 0); + const uint8_t blend_g = + BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 8); + const uint8_t blend_b = + BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 16); + assert(src_a + dst_factor_a < 256); + + return (blend_r << 0) | + (blend_g << 8) | + (blend_b << 16) | + ((uint32_t)blend_a << 24); + } +} + +// Blend 'num_pixels' in 'src' over 'dst' assuming they are NOT pre-multiplied +// by alpha. +static void BlendPixelRowNonPremult(uint32_t* const src, + const uint32_t* const dst, int num_pixels) { + int i; + for (i = 0; i < num_pixels; ++i) { + const uint8_t src_alpha = (src[i] >> 24) & 0xff; + if (src_alpha != 0xff) { + src[i] = BlendPixelNonPremult(src[i], dst[i]); + } + } +} + +// Individually multiply each channel in 'pix' by 'scale'. +static WEBP_INLINE uint32_t ChannelwiseMultiply(uint32_t pix, uint32_t scale) { + uint32_t mask = 0x00FF00FF; + uint32_t rb = ((pix & mask) * scale) >> 8; + uint32_t ag = ((pix >> 8) & mask) * scale; + return (rb & mask) | (ag & ~mask); +} + +// Blend 'src' over 'dst' assuming they are pre-multiplied by alpha. +static uint32_t BlendPixelPremult(uint32_t src, uint32_t dst) { + const uint8_t src_a = (src >> 24) & 0xff; + return src + ChannelwiseMultiply(dst, 256 - src_a); +} + +// Blend 'num_pixels' in 'src' over 'dst' assuming they are pre-multiplied by +// alpha. +static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst, + int num_pixels) { + int i; + for (i = 0; i < num_pixels; ++i) { + const uint8_t src_alpha = (src[i] >> 24) & 0xff; + if (src_alpha != 0xff) { + src[i] = BlendPixelPremult(src[i], dst[i]); + } + } +} + +// Returns two ranges (<left, width> pairs) at row 'canvas_y', that belong to +// 'src' but not 'dst'. A point range is empty if the corresponding width is 0. +static void FindBlendRangeAtRow(const WebPIterator* const src, + const WebPIterator* const dst, int canvas_y, + int* const left1, int* const width1, + int* const left2, int* const width2) { + const int src_max_x = src->x_offset + src->width; + const int dst_max_x = dst->x_offset + dst->width; + const int dst_max_y = dst->y_offset + dst->height; + assert(canvas_y >= src->y_offset && canvas_y < (src->y_offset + src->height)); + *left1 = -1; + *width1 = 0; + *left2 = -1; + *width2 = 0; + + if (canvas_y < dst->y_offset || canvas_y >= dst_max_y || + src->x_offset >= dst_max_x || src_max_x <= dst->x_offset) { + *left1 = src->x_offset; + *width1 = src->width; + return; + } + + if (src->x_offset < dst->x_offset) { + *left1 = src->x_offset; + *width1 = dst->x_offset - src->x_offset; + } + + if (src_max_x > dst_max_x) { + *left2 = dst_max_x; + *width2 = src_max_x - dst_max_x; + } +} + +int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, + uint8_t** buf_ptr, int* timestamp_ptr) { + WebPIterator iter; + uint32_t width; + uint32_t height; + int is_key_frame; + int timestamp; + BlendRowFunc blend_row; + + if (dec == NULL || buf_ptr == NULL || timestamp_ptr == NULL) return 0; + if (!WebPAnimDecoderHasMoreFrames(dec)) return 0; + + width = dec->info_.canvas_width; + height = dec->info_.canvas_height; + blend_row = dec->blend_func_; + + // Get compressed frame. + if (!WebPDemuxGetFrame(dec->demux_, dec->next_frame_, &iter)) { + return 0; + } + timestamp = dec->prev_frame_timestamp_ + iter.duration; + + // Initialize. + is_key_frame = IsKeyFrame(&iter, &dec->prev_iter_, + dec->prev_frame_was_keyframe_, width, height); + if (is_key_frame) { + ZeroFillCanvas(dec->curr_frame_, width, height); + } else { + CopyCanvas(dec->prev_frame_disposed_, dec->curr_frame_, width, height); + } + + // Decode. + { + const uint8_t* in = iter.fragment.bytes; + const size_t in_size = iter.fragment.size; + const size_t out_offset = + (iter.y_offset * width + iter.x_offset) * NUM_CHANNELS; + WebPDecoderConfig* const config = &dec->config_; + WebPRGBABuffer* const buf = &config->output.u.RGBA; + buf->stride = NUM_CHANNELS * width; + buf->size = buf->stride * iter.height; + buf->rgba = dec->curr_frame_ + out_offset; + + if (WebPDecode(in, in_size, config) != VP8_STATUS_OK) { + goto Error; + } + } + + // During the decoding of current frame, we may have set some pixels to be + // transparent (i.e. alpha < 255). However, the value of each of these + // pixels should have been determined by blending it against the value of + // that pixel in the previous frame if blending method of is WEBP_MUX_BLEND. + if (iter.frame_num > 1 && iter.blend_method == WEBP_MUX_BLEND && + !is_key_frame) { + if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_NONE) { + int y; + // Blend transparent pixels with pixels in previous canvas. + for (y = 0; y < iter.height; ++y) { + const size_t offset = + (iter.y_offset + y) * width + iter.x_offset; + blend_row((uint32_t*)dec->curr_frame_ + offset, + (uint32_t*)dec->prev_frame_disposed_ + offset, iter.width); + } + } else { + int y; + assert(dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND); + // We need to blend a transparent pixel with its value just after + // initialization. That is, blend it with: + // * Fully transparent pixel if it belongs to prevRect <-- No-op. + // * The pixel in the previous canvas otherwise <-- Need alpha-blending. + for (y = 0; y < iter.height; ++y) { + const int canvas_y = iter.y_offset + y; + int left1, width1, left2, width2; + FindBlendRangeAtRow(&iter, &dec->prev_iter_, canvas_y, &left1, &width1, + &left2, &width2); + if (width1 > 0) { + const size_t offset1 = canvas_y * width + left1; + blend_row((uint32_t*)dec->curr_frame_ + offset1, + (uint32_t*)dec->prev_frame_disposed_ + offset1, width1); + } + if (width2 > 0) { + const size_t offset2 = canvas_y * width + left2; + blend_row((uint32_t*)dec->curr_frame_ + offset2, + (uint32_t*)dec->prev_frame_disposed_ + offset2, width2); + } + } + } + } + + // Update info of the previous frame and dispose it for the next iteration. + dec->prev_frame_timestamp_ = timestamp; + dec->prev_iter_ = iter; + dec->prev_frame_was_keyframe_ = is_key_frame; + CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height); + if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { + ZeroFillFrameRect(dec->prev_frame_disposed_, width * NUM_CHANNELS, + dec->prev_iter_.x_offset, dec->prev_iter_.y_offset, + dec->prev_iter_.width, dec->prev_iter_.height); + } + ++dec->next_frame_; + + // All OK, fill in the values. + *buf_ptr = dec->curr_frame_; + *timestamp_ptr = timestamp; + return 1; + + Error: + WebPDemuxReleaseIterator(&iter); + return 0; +} + +int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec) { + if (dec == NULL) return 0; + return (dec->next_frame_ <= (int)dec->info_.frame_count); +} + +void WebPAnimDecoderReset(WebPAnimDecoder* dec) { + if (dec != NULL) { + dec->prev_frame_timestamp_ = 0; + memset(&dec->prev_iter_, 0, sizeof(dec->prev_iter_)); + dec->prev_frame_was_keyframe_ = 0; + dec->next_frame_ = 1; + } +} + +const WebPDemuxer* WebPAnimDecoderGetDemuxer(const WebPAnimDecoder* dec) { + if (dec == NULL) return NULL; + return dec->demux_; +} + +void WebPAnimDecoderDelete(WebPAnimDecoder* dec) { + if (dec != NULL) { + WebPDemuxDelete(dec->demux_); + WebPSafeFree(dec->curr_frame_); + WebPSafeFree(dec->prev_frame_disposed_); + WebPSafeFree(dec); + } +} diff --git a/thirdparty/libwebp/demux/demux.c b/thirdparty/libwebp/demux/demux.c new file mode 100644 index 0000000000..0d2989f6f4 --- /dev/null +++ b/thirdparty/libwebp/demux/demux.c @@ -0,0 +1,966 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP container demux. +// + +#ifdef HAVE_CONFIG_H +#include "../webp/config.h" +#endif + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#include "../utils/utils.h" +#include "../webp/decode.h" // WebPGetFeatures +#include "../webp/demux.h" +#include "../webp/format_constants.h" + +#define DMUX_MAJ_VERSION 0 +#define DMUX_MIN_VERSION 3 +#define DMUX_REV_VERSION 0 + +typedef struct { + size_t start_; // start location of the data + size_t end_; // end location + size_t riff_end_; // riff chunk end location, can be > end_. + size_t buf_size_; // size of the buffer + const uint8_t* buf_; +} MemBuffer; + +typedef struct { + size_t offset_; + size_t size_; +} ChunkData; + +typedef struct Frame { + int x_offset_, y_offset_; + int width_, height_; + int has_alpha_; + int duration_; + WebPMuxAnimDispose dispose_method_; + WebPMuxAnimBlend blend_method_; + int frame_num_; + int complete_; // img_components_ contains a full image. + ChunkData img_components_[2]; // 0=VP8{,L} 1=ALPH + struct Frame* next_; +} Frame; + +typedef struct Chunk { + ChunkData data_; + struct Chunk* next_; +} Chunk; + +struct WebPDemuxer { + MemBuffer mem_; + WebPDemuxState state_; + int is_ext_format_; + uint32_t feature_flags_; + int canvas_width_, canvas_height_; + int loop_count_; + uint32_t bgcolor_; + int num_frames_; + Frame* frames_; + Frame** frames_tail_; + Chunk* chunks_; // non-image chunks + Chunk** chunks_tail_; +}; + +typedef enum { + PARSE_OK, + PARSE_NEED_MORE_DATA, + PARSE_ERROR +} ParseStatus; + +typedef struct ChunkParser { + uint8_t id[4]; + ParseStatus (*parse)(WebPDemuxer* const dmux); + int (*valid)(const WebPDemuxer* const dmux); +} ChunkParser; + +static ParseStatus ParseSingleImage(WebPDemuxer* const dmux); +static ParseStatus ParseVP8X(WebPDemuxer* const dmux); +static int IsValidSimpleFormat(const WebPDemuxer* const dmux); +static int IsValidExtendedFormat(const WebPDemuxer* const dmux); + +static const ChunkParser kMasterChunks[] = { + { { 'V', 'P', '8', ' ' }, ParseSingleImage, IsValidSimpleFormat }, + { { 'V', 'P', '8', 'L' }, ParseSingleImage, IsValidSimpleFormat }, + { { 'V', 'P', '8', 'X' }, ParseVP8X, IsValidExtendedFormat }, + { { '0', '0', '0', '0' }, NULL, NULL }, +}; + +//------------------------------------------------------------------------------ + +int WebPGetDemuxVersion(void) { + return (DMUX_MAJ_VERSION << 16) | (DMUX_MIN_VERSION << 8) | DMUX_REV_VERSION; +} + +// ----------------------------------------------------------------------------- +// MemBuffer + +static int RemapMemBuffer(MemBuffer* const mem, + const uint8_t* data, size_t size) { + if (size < mem->buf_size_) return 0; // can't remap to a shorter buffer! + + mem->buf_ = data; + mem->end_ = mem->buf_size_ = size; + return 1; +} + +static int InitMemBuffer(MemBuffer* const mem, + const uint8_t* data, size_t size) { + memset(mem, 0, sizeof(*mem)); + return RemapMemBuffer(mem, data, size); +} + +// Return the remaining data size available in 'mem'. +static WEBP_INLINE size_t MemDataSize(const MemBuffer* const mem) { + return (mem->end_ - mem->start_); +} + +// Return true if 'size' exceeds the end of the RIFF chunk. +static WEBP_INLINE int SizeIsInvalid(const MemBuffer* const mem, size_t size) { + return (size > mem->riff_end_ - mem->start_); +} + +static WEBP_INLINE void Skip(MemBuffer* const mem, size_t size) { + mem->start_ += size; +} + +static WEBP_INLINE void Rewind(MemBuffer* const mem, size_t size) { + mem->start_ -= size; +} + +static WEBP_INLINE const uint8_t* GetBuffer(MemBuffer* const mem) { + return mem->buf_ + mem->start_; +} + +// Read from 'mem' and skip the read bytes. +static WEBP_INLINE uint8_t ReadByte(MemBuffer* const mem) { + const uint8_t byte = mem->buf_[mem->start_]; + Skip(mem, 1); + return byte; +} + +static WEBP_INLINE int ReadLE16s(MemBuffer* const mem) { + const uint8_t* const data = mem->buf_ + mem->start_; + const int val = GetLE16(data); + Skip(mem, 2); + return val; +} + +static WEBP_INLINE int ReadLE24s(MemBuffer* const mem) { + const uint8_t* const data = mem->buf_ + mem->start_; + const int val = GetLE24(data); + Skip(mem, 3); + return val; +} + +static WEBP_INLINE uint32_t ReadLE32(MemBuffer* const mem) { + const uint8_t* const data = mem->buf_ + mem->start_; + const uint32_t val = GetLE32(data); + Skip(mem, 4); + return val; +} + +// ----------------------------------------------------------------------------- +// Secondary chunk parsing + +static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) { + *dmux->chunks_tail_ = chunk; + chunk->next_ = NULL; + dmux->chunks_tail_ = &chunk->next_; +} + +// Add a frame to the end of the list, ensuring the last frame is complete. +// Returns true on success, false otherwise. +static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) { + const Frame* const last_frame = *dmux->frames_tail_; + if (last_frame != NULL && !last_frame->complete_) return 0; + + *dmux->frames_tail_ = frame; + frame->next_ = NULL; + dmux->frames_tail_ = &frame->next_; + return 1; +} + +static void SetFrameInfo(size_t start_offset, size_t size, + int frame_num, int complete, + const WebPBitstreamFeatures* const features, + Frame* const frame) { + frame->img_components_[0].offset_ = start_offset; + frame->img_components_[0].size_ = size; + frame->width_ = features->width; + frame->height_ = features->height; + frame->has_alpha_ |= features->has_alpha; + frame->frame_num_ = frame_num; + frame->complete_ = complete; +} + +// Store image bearing chunks to 'frame'. +static ParseStatus StoreFrame(int frame_num, uint32_t min_size, + MemBuffer* const mem, Frame* const frame) { + int alpha_chunks = 0; + int image_chunks = 0; + int done = (MemDataSize(mem) < min_size); + ParseStatus status = PARSE_OK; + + if (done) return PARSE_NEED_MORE_DATA; + + do { + const size_t chunk_start_offset = mem->start_; + const uint32_t fourcc = ReadLE32(mem); + const uint32_t payload_size = ReadLE32(mem); + const uint32_t payload_size_padded = payload_size + (payload_size & 1); + const size_t payload_available = (payload_size_padded > MemDataSize(mem)) + ? MemDataSize(mem) : payload_size_padded; + const size_t chunk_size = CHUNK_HEADER_SIZE + payload_available; + + if (payload_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; + if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR; + if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA; + + switch (fourcc) { + case MKFOURCC('A', 'L', 'P', 'H'): + if (alpha_chunks == 0) { + ++alpha_chunks; + frame->img_components_[1].offset_ = chunk_start_offset; + frame->img_components_[1].size_ = chunk_size; + frame->has_alpha_ = 1; + frame->frame_num_ = frame_num; + Skip(mem, payload_available); + } else { + goto Done; + } + break; + case MKFOURCC('V', 'P', '8', 'L'): + if (alpha_chunks > 0) return PARSE_ERROR; // VP8L has its own alpha + // fall through + case MKFOURCC('V', 'P', '8', ' '): + if (image_chunks == 0) { + // Extract the bitstream features, tolerating failures when the data + // is incomplete. + WebPBitstreamFeatures features; + const VP8StatusCode vp8_status = + WebPGetFeatures(mem->buf_ + chunk_start_offset, chunk_size, + &features); + if (status == PARSE_NEED_MORE_DATA && + vp8_status == VP8_STATUS_NOT_ENOUGH_DATA) { + return PARSE_NEED_MORE_DATA; + } else if (vp8_status != VP8_STATUS_OK) { + // We have enough data, and yet WebPGetFeatures() failed. + return PARSE_ERROR; + } + ++image_chunks; + SetFrameInfo(chunk_start_offset, chunk_size, frame_num, + status == PARSE_OK, &features, frame); + Skip(mem, payload_available); + } else { + goto Done; + } + break; + Done: + default: + // Restore fourcc/size when moving up one level in parsing. + Rewind(mem, CHUNK_HEADER_SIZE); + done = 1; + break; + } + + if (mem->start_ == mem->riff_end_) { + done = 1; + } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) { + status = PARSE_NEED_MORE_DATA; + } + } while (!done && status == PARSE_OK); + + return status; +} + +// Creates a new Frame if 'actual_size' is within bounds and 'mem' contains +// enough data ('min_size') to parse the payload. +// Returns PARSE_OK on success with *frame pointing to the new Frame. +// Returns PARSE_NEED_MORE_DATA with insufficient data, PARSE_ERROR otherwise. +static ParseStatus NewFrame(const MemBuffer* const mem, + uint32_t min_size, uint32_t actual_size, + Frame** frame) { + if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR; + if (actual_size < min_size) return PARSE_ERROR; + if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; + + *frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(**frame)); + return (*frame == NULL) ? PARSE_ERROR : PARSE_OK; +} + +// Parse a 'ANMF' chunk and any image bearing chunks that immediately follow. +// 'frame_chunk_size' is the previously validated, padded chunk size. +static ParseStatus ParseAnimationFrame( + WebPDemuxer* const dmux, uint32_t frame_chunk_size) { + const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); + const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE; + int added_frame = 0; + int bits; + MemBuffer* const mem = &dmux->mem_; + Frame* frame; + ParseStatus status = + NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame); + if (status != PARSE_OK) return status; + + frame->x_offset_ = 2 * ReadLE24s(mem); + frame->y_offset_ = 2 * ReadLE24s(mem); + frame->width_ = 1 + ReadLE24s(mem); + frame->height_ = 1 + ReadLE24s(mem); + frame->duration_ = ReadLE24s(mem); + bits = ReadByte(mem); + frame->dispose_method_ = + (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE; + frame->blend_method_ = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND; + if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) { + WebPSafeFree(frame); + return PARSE_ERROR; + } + + // Store a frame only if the animation flag is set there is some data for + // this frame is available. + status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame); + if (status != PARSE_ERROR && is_animation && frame->frame_num_ > 0) { + added_frame = AddFrame(dmux, frame); + if (added_frame) { + ++dmux->num_frames_; + } else { + status = PARSE_ERROR; + } + } + + if (!added_frame) WebPSafeFree(frame); + return status; +} + +// General chunk storage, starting with the header at 'start_offset', allowing +// the user to request the payload via a fourcc string. 'size' includes the +// header and the unpadded payload size. +// Returns true on success, false otherwise. +static int StoreChunk(WebPDemuxer* const dmux, + size_t start_offset, uint32_t size) { + Chunk* const chunk = (Chunk*)WebPSafeCalloc(1ULL, sizeof(*chunk)); + if (chunk == NULL) return 0; + + chunk->data_.offset_ = start_offset; + chunk->data_.size_ = size; + AddChunk(dmux, chunk); + return 1; +} + +// ----------------------------------------------------------------------------- +// Primary chunk parsing + +static ParseStatus ReadHeader(MemBuffer* const mem) { + const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE; + uint32_t riff_size; + + // Basic file level validation. + if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; + if (memcmp(GetBuffer(mem), "RIFF", CHUNK_SIZE_BYTES) || + memcmp(GetBuffer(mem) + CHUNK_HEADER_SIZE, "WEBP", CHUNK_SIZE_BYTES)) { + return PARSE_ERROR; + } + + riff_size = GetLE32(GetBuffer(mem) + TAG_SIZE); + if (riff_size < CHUNK_HEADER_SIZE) return PARSE_ERROR; + if (riff_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; + + // There's no point in reading past the end of the RIFF chunk + mem->riff_end_ = riff_size + CHUNK_HEADER_SIZE; + if (mem->buf_size_ > mem->riff_end_) { + mem->buf_size_ = mem->end_ = mem->riff_end_; + } + + Skip(mem, RIFF_HEADER_SIZE); + return PARSE_OK; +} + +static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) { + const size_t min_size = CHUNK_HEADER_SIZE; + MemBuffer* const mem = &dmux->mem_; + Frame* frame; + ParseStatus status; + int image_added = 0; + + if (dmux->frames_ != NULL) return PARSE_ERROR; + if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR; + if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; + + frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); + if (frame == NULL) return PARSE_ERROR; + + // For the single image case we allow parsing of a partial frame, but we need + // at least CHUNK_HEADER_SIZE for parsing. + status = StoreFrame(1, CHUNK_HEADER_SIZE, &dmux->mem_, frame); + if (status != PARSE_ERROR) { + const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG); + // Clear any alpha when the alpha flag is missing. + if (!has_alpha && frame->img_components_[1].size_ > 0) { + frame->img_components_[1].offset_ = 0; + frame->img_components_[1].size_ = 0; + frame->has_alpha_ = 0; + } + + // Use the frame width/height as the canvas values for non-vp8x files. + // Also, set ALPHA_FLAG if this is a lossless image with alpha. + if (!dmux->is_ext_format_ && frame->width_ > 0 && frame->height_ > 0) { + dmux->state_ = WEBP_DEMUX_PARSED_HEADER; + dmux->canvas_width_ = frame->width_; + dmux->canvas_height_ = frame->height_; + dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0; + } + if (!AddFrame(dmux, frame)) { + status = PARSE_ERROR; // last frame was left incomplete + } else { + image_added = 1; + dmux->num_frames_ = 1; + } + } + + if (!image_added) WebPSafeFree(frame); + return status; +} + +static ParseStatus ParseVP8XChunks(WebPDemuxer* const dmux) { + const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); + MemBuffer* const mem = &dmux->mem_; + int anim_chunks = 0; + ParseStatus status = PARSE_OK; + + do { + int store_chunk = 1; + const size_t chunk_start_offset = mem->start_; + const uint32_t fourcc = ReadLE32(mem); + const uint32_t chunk_size = ReadLE32(mem); + const uint32_t chunk_size_padded = chunk_size + (chunk_size & 1); + + if (chunk_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; + if (SizeIsInvalid(mem, chunk_size_padded)) return PARSE_ERROR; + + switch (fourcc) { + case MKFOURCC('V', 'P', '8', 'X'): { + return PARSE_ERROR; + } + case MKFOURCC('A', 'L', 'P', 'H'): + case MKFOURCC('V', 'P', '8', ' '): + case MKFOURCC('V', 'P', '8', 'L'): { + // check that this isn't an animation (all frames should be in an ANMF). + if (anim_chunks > 0 || is_animation) return PARSE_ERROR; + + Rewind(mem, CHUNK_HEADER_SIZE); + status = ParseSingleImage(dmux); + break; + } + case MKFOURCC('A', 'N', 'I', 'M'): { + if (chunk_size_padded < ANIM_CHUNK_SIZE) return PARSE_ERROR; + + if (MemDataSize(mem) < chunk_size_padded) { + status = PARSE_NEED_MORE_DATA; + } else if (anim_chunks == 0) { + ++anim_chunks; + dmux->bgcolor_ = ReadLE32(mem); + dmux->loop_count_ = ReadLE16s(mem); + Skip(mem, chunk_size_padded - ANIM_CHUNK_SIZE); + } else { + store_chunk = 0; + goto Skip; + } + break; + } + case MKFOURCC('A', 'N', 'M', 'F'): { + if (anim_chunks == 0) return PARSE_ERROR; // 'ANIM' precedes frames. + status = ParseAnimationFrame(dmux, chunk_size_padded); + break; + } + case MKFOURCC('I', 'C', 'C', 'P'): { + store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG); + goto Skip; + } + case MKFOURCC('E', 'X', 'I', 'F'): { + store_chunk = !!(dmux->feature_flags_ & EXIF_FLAG); + goto Skip; + } + case MKFOURCC('X', 'M', 'P', ' '): { + store_chunk = !!(dmux->feature_flags_ & XMP_FLAG); + goto Skip; + } + Skip: + default: { + if (chunk_size_padded <= MemDataSize(mem)) { + if (store_chunk) { + // Store only the chunk header and unpadded size as only the payload + // will be returned to the user. + if (!StoreChunk(dmux, chunk_start_offset, + CHUNK_HEADER_SIZE + chunk_size)) { + return PARSE_ERROR; + } + } + Skip(mem, chunk_size_padded); + } else { + status = PARSE_NEED_MORE_DATA; + } + } + } + + if (mem->start_ == mem->riff_end_) { + break; + } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) { + status = PARSE_NEED_MORE_DATA; + } + } while (status == PARSE_OK); + + return status; +} + +static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { + MemBuffer* const mem = &dmux->mem_; + uint32_t vp8x_size; + + if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; + + dmux->is_ext_format_ = 1; + Skip(mem, TAG_SIZE); // VP8X + vp8x_size = ReadLE32(mem); + if (vp8x_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; + if (vp8x_size < VP8X_CHUNK_SIZE) return PARSE_ERROR; + vp8x_size += vp8x_size & 1; + if (SizeIsInvalid(mem, vp8x_size)) return PARSE_ERROR; + if (MemDataSize(mem) < vp8x_size) return PARSE_NEED_MORE_DATA; + + dmux->feature_flags_ = ReadByte(mem); + Skip(mem, 3); // Reserved. + dmux->canvas_width_ = 1 + ReadLE24s(mem); + dmux->canvas_height_ = 1 + ReadLE24s(mem); + if (dmux->canvas_width_ * (uint64_t)dmux->canvas_height_ >= MAX_IMAGE_AREA) { + return PARSE_ERROR; // image final dimension is too large + } + Skip(mem, vp8x_size - VP8X_CHUNK_SIZE); // skip any trailing data. + dmux->state_ = WEBP_DEMUX_PARSED_HEADER; + + if (SizeIsInvalid(mem, CHUNK_HEADER_SIZE)) return PARSE_ERROR; + if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; + + return ParseVP8XChunks(dmux); +} + +// ----------------------------------------------------------------------------- +// Format validation + +static int IsValidSimpleFormat(const WebPDemuxer* const dmux) { + const Frame* const frame = dmux->frames_; + if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1; + + if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0; + if (dmux->state_ == WEBP_DEMUX_DONE && frame == NULL) return 0; + + if (frame->width_ <= 0 || frame->height_ <= 0) return 0; + return 1; +} + +// If 'exact' is true, check that the image resolution matches the canvas. +// If 'exact' is false, check that the x/y offsets do not exceed the canvas. +static int CheckFrameBounds(const Frame* const frame, int exact, + int canvas_width, int canvas_height) { + if (exact) { + if (frame->x_offset_ != 0 || frame->y_offset_ != 0) { + return 0; + } + if (frame->width_ != canvas_width || frame->height_ != canvas_height) { + return 0; + } + } else { + if (frame->x_offset_ < 0 || frame->y_offset_ < 0) return 0; + if (frame->width_ + frame->x_offset_ > canvas_width) return 0; + if (frame->height_ + frame->y_offset_ > canvas_height) return 0; + } + return 1; +} + +static int IsValidExtendedFormat(const WebPDemuxer* const dmux) { + const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); + const int is_fragmented = !!(dmux->feature_flags_ & FRAGMENTS_FLAG); + const Frame* f = dmux->frames_; + + if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1; + + if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0; + if (dmux->loop_count_ < 0) return 0; + if (dmux->state_ == WEBP_DEMUX_DONE && dmux->frames_ == NULL) return 0; + if (is_fragmented) return 0; + + while (f != NULL) { + const int cur_frame_set = f->frame_num_; + int frame_count = 0; + + // Check frame properties. + for (; f != NULL && f->frame_num_ == cur_frame_set; f = f->next_) { + const ChunkData* const image = f->img_components_; + const ChunkData* const alpha = f->img_components_ + 1; + + if (!is_animation && f->frame_num_ > 1) return 0; + + if (f->complete_) { + if (alpha->size_ == 0 && image->size_ == 0) return 0; + // Ensure alpha precedes image bitstream. + if (alpha->size_ > 0 && alpha->offset_ > image->offset_) { + return 0; + } + + if (f->width_ <= 0 || f->height_ <= 0) return 0; + } else { + // There shouldn't be a partial frame in a complete file. + if (dmux->state_ == WEBP_DEMUX_DONE) return 0; + + // Ensure alpha precedes image bitstream. + if (alpha->size_ > 0 && image->size_ > 0 && + alpha->offset_ > image->offset_) { + return 0; + } + // There shouldn't be any frames after an incomplete one. + if (f->next_ != NULL) return 0; + } + + if (f->width_ > 0 && f->height_ > 0 && + !CheckFrameBounds(f, !is_animation, + dmux->canvas_width_, dmux->canvas_height_)) { + return 0; + } + + ++frame_count; + } + } + return 1; +} + +// ----------------------------------------------------------------------------- +// WebPDemuxer object + +static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) { + dmux->state_ = WEBP_DEMUX_PARSING_HEADER; + dmux->loop_count_ = 1; + dmux->bgcolor_ = 0xFFFFFFFF; // White background by default. + dmux->canvas_width_ = -1; + dmux->canvas_height_ = -1; + dmux->frames_tail_ = &dmux->frames_; + dmux->chunks_tail_ = &dmux->chunks_; + dmux->mem_ = *mem; +} + +static ParseStatus CreateRawImageDemuxer(MemBuffer* const mem, + WebPDemuxer** demuxer) { + WebPBitstreamFeatures features; + const VP8StatusCode status = + WebPGetFeatures(mem->buf_, mem->buf_size_, &features); + *demuxer = NULL; + if (status != VP8_STATUS_OK) { + return (status == VP8_STATUS_NOT_ENOUGH_DATA) ? PARSE_NEED_MORE_DATA + : PARSE_ERROR; + } + + { + WebPDemuxer* const dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux)); + Frame* const frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); + if (dmux == NULL || frame == NULL) goto Error; + InitDemux(dmux, mem); + SetFrameInfo(0, mem->buf_size_, 1 /*frame_num*/, 1 /*complete*/, &features, + frame); + if (!AddFrame(dmux, frame)) goto Error; + dmux->state_ = WEBP_DEMUX_DONE; + dmux->canvas_width_ = frame->width_; + dmux->canvas_height_ = frame->height_; + dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0; + dmux->num_frames_ = 1; + assert(IsValidSimpleFormat(dmux)); + *demuxer = dmux; + return PARSE_OK; + + Error: + WebPSafeFree(dmux); + WebPSafeFree(frame); + return PARSE_ERROR; + } +} + +WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial, + WebPDemuxState* state, int version) { + const ChunkParser* parser; + int partial; + ParseStatus status = PARSE_ERROR; + MemBuffer mem; + WebPDemuxer* dmux; + + if (state != NULL) *state = WEBP_DEMUX_PARSE_ERROR; + + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DEMUX_ABI_VERSION)) return NULL; + if (data == NULL || data->bytes == NULL || data->size == 0) return NULL; + + if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL; + status = ReadHeader(&mem); + if (status != PARSE_OK) { + // If parsing of the webp file header fails attempt to handle a raw + // VP8/VP8L frame. Note 'allow_partial' is ignored in this case. + if (status == PARSE_ERROR) { + status = CreateRawImageDemuxer(&mem, &dmux); + if (status == PARSE_OK) { + if (state != NULL) *state = WEBP_DEMUX_DONE; + return dmux; + } + } + if (state != NULL) { + *state = (status == PARSE_NEED_MORE_DATA) ? WEBP_DEMUX_PARSING_HEADER + : WEBP_DEMUX_PARSE_ERROR; + } + return NULL; + } + + partial = (mem.buf_size_ < mem.riff_end_); + if (!allow_partial && partial) return NULL; + + dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux)); + if (dmux == NULL) return NULL; + InitDemux(dmux, &mem); + + status = PARSE_ERROR; + for (parser = kMasterChunks; parser->parse != NULL; ++parser) { + if (!memcmp(parser->id, GetBuffer(&dmux->mem_), TAG_SIZE)) { + status = parser->parse(dmux); + if (status == PARSE_OK) dmux->state_ = WEBP_DEMUX_DONE; + if (status == PARSE_NEED_MORE_DATA && !partial) status = PARSE_ERROR; + if (status != PARSE_ERROR && !parser->valid(dmux)) status = PARSE_ERROR; + if (status == PARSE_ERROR) dmux->state_ = WEBP_DEMUX_PARSE_ERROR; + break; + } + } + if (state != NULL) *state = dmux->state_; + + if (status == PARSE_ERROR) { + WebPDemuxDelete(dmux); + return NULL; + } + return dmux; +} + +void WebPDemuxDelete(WebPDemuxer* dmux) { + Chunk* c; + Frame* f; + if (dmux == NULL) return; + + for (f = dmux->frames_; f != NULL;) { + Frame* const cur_frame = f; + f = f->next_; + WebPSafeFree(cur_frame); + } + for (c = dmux->chunks_; c != NULL;) { + Chunk* const cur_chunk = c; + c = c->next_; + WebPSafeFree(cur_chunk); + } + WebPSafeFree(dmux); +} + +// ----------------------------------------------------------------------------- + +uint32_t WebPDemuxGetI(const WebPDemuxer* dmux, WebPFormatFeature feature) { + if (dmux == NULL) return 0; + + switch (feature) { + case WEBP_FF_FORMAT_FLAGS: return dmux->feature_flags_; + case WEBP_FF_CANVAS_WIDTH: return (uint32_t)dmux->canvas_width_; + case WEBP_FF_CANVAS_HEIGHT: return (uint32_t)dmux->canvas_height_; + case WEBP_FF_LOOP_COUNT: return (uint32_t)dmux->loop_count_; + case WEBP_FF_BACKGROUND_COLOR: return dmux->bgcolor_; + case WEBP_FF_FRAME_COUNT: return (uint32_t)dmux->num_frames_; + } + return 0; +} + +// ----------------------------------------------------------------------------- +// Frame iteration + +static const Frame* GetFrame(const WebPDemuxer* const dmux, int frame_num) { + const Frame* f; + for (f = dmux->frames_; f != NULL; f = f->next_) { + if (frame_num == f->frame_num_) break; + } + return f; +} + +static const uint8_t* GetFramePayload(const uint8_t* const mem_buf, + const Frame* const frame, + size_t* const data_size) { + *data_size = 0; + if (frame != NULL) { + const ChunkData* const image = frame->img_components_; + const ChunkData* const alpha = frame->img_components_ + 1; + size_t start_offset = image->offset_; + *data_size = image->size_; + + // if alpha exists it precedes image, update the size allowing for + // intervening chunks. + if (alpha->size_ > 0) { + const size_t inter_size = (image->offset_ > 0) + ? image->offset_ - (alpha->offset_ + alpha->size_) + : 0; + start_offset = alpha->offset_; + *data_size += alpha->size_ + inter_size; + } + return mem_buf + start_offset; + } + return NULL; +} + +// Create a whole 'frame' from VP8 (+ alpha) or lossless. +static int SynthesizeFrame(const WebPDemuxer* const dmux, + const Frame* const frame, + WebPIterator* const iter) { + const uint8_t* const mem_buf = dmux->mem_.buf_; + size_t payload_size = 0; + const uint8_t* const payload = GetFramePayload(mem_buf, frame, &payload_size); + if (payload == NULL) return 0; + assert(frame != NULL); + + iter->frame_num = frame->frame_num_; + iter->num_frames = dmux->num_frames_; + iter->x_offset = frame->x_offset_; + iter->y_offset = frame->y_offset_; + iter->width = frame->width_; + iter->height = frame->height_; + iter->has_alpha = frame->has_alpha_; + iter->duration = frame->duration_; + iter->dispose_method = frame->dispose_method_; + iter->blend_method = frame->blend_method_; + iter->complete = frame->complete_; + iter->fragment.bytes = payload; + iter->fragment.size = payload_size; + return 1; +} + +static int SetFrame(int frame_num, WebPIterator* const iter) { + const Frame* frame; + const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_; + if (dmux == NULL || frame_num < 0) return 0; + if (frame_num > dmux->num_frames_) return 0; + if (frame_num == 0) frame_num = dmux->num_frames_; + + frame = GetFrame(dmux, frame_num); + if (frame == NULL) return 0; + + return SynthesizeFrame(dmux, frame, iter); +} + +int WebPDemuxGetFrame(const WebPDemuxer* dmux, int frame, WebPIterator* iter) { + if (iter == NULL) return 0; + + memset(iter, 0, sizeof(*iter)); + iter->private_ = (void*)dmux; + return SetFrame(frame, iter); +} + +int WebPDemuxNextFrame(WebPIterator* iter) { + if (iter == NULL) return 0; + return SetFrame(iter->frame_num + 1, iter); +} + +int WebPDemuxPrevFrame(WebPIterator* iter) { + if (iter == NULL) return 0; + if (iter->frame_num <= 1) return 0; + return SetFrame(iter->frame_num - 1, iter); +} + +void WebPDemuxReleaseIterator(WebPIterator* iter) { + (void)iter; +} + +// ----------------------------------------------------------------------------- +// Chunk iteration + +static int ChunkCount(const WebPDemuxer* const dmux, const char fourcc[4]) { + const uint8_t* const mem_buf = dmux->mem_.buf_; + const Chunk* c; + int count = 0; + for (c = dmux->chunks_; c != NULL; c = c->next_) { + const uint8_t* const header = mem_buf + c->data_.offset_; + if (!memcmp(header, fourcc, TAG_SIZE)) ++count; + } + return count; +} + +static const Chunk* GetChunk(const WebPDemuxer* const dmux, + const char fourcc[4], int chunk_num) { + const uint8_t* const mem_buf = dmux->mem_.buf_; + const Chunk* c; + int count = 0; + for (c = dmux->chunks_; c != NULL; c = c->next_) { + const uint8_t* const header = mem_buf + c->data_.offset_; + if (!memcmp(header, fourcc, TAG_SIZE)) ++count; + if (count == chunk_num) break; + } + return c; +} + +static int SetChunk(const char fourcc[4], int chunk_num, + WebPChunkIterator* const iter) { + const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_; + int count; + + if (dmux == NULL || fourcc == NULL || chunk_num < 0) return 0; + count = ChunkCount(dmux, fourcc); + if (count == 0) return 0; + if (chunk_num == 0) chunk_num = count; + + if (chunk_num <= count) { + const uint8_t* const mem_buf = dmux->mem_.buf_; + const Chunk* const chunk = GetChunk(dmux, fourcc, chunk_num); + iter->chunk.bytes = mem_buf + chunk->data_.offset_ + CHUNK_HEADER_SIZE; + iter->chunk.size = chunk->data_.size_ - CHUNK_HEADER_SIZE; + iter->num_chunks = count; + iter->chunk_num = chunk_num; + return 1; + } + return 0; +} + +int WebPDemuxGetChunk(const WebPDemuxer* dmux, + const char fourcc[4], int chunk_num, + WebPChunkIterator* iter) { + if (iter == NULL) return 0; + + memset(iter, 0, sizeof(*iter)); + iter->private_ = (void*)dmux; + return SetChunk(fourcc, chunk_num, iter); +} + +int WebPDemuxNextChunk(WebPChunkIterator* iter) { + if (iter != NULL) { + const char* const fourcc = + (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE; + return SetChunk(fourcc, iter->chunk_num + 1, iter); + } + return 0; +} + +int WebPDemuxPrevChunk(WebPChunkIterator* iter) { + if (iter != NULL && iter->chunk_num > 1) { + const char* const fourcc = + (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE; + return SetChunk(fourcc, iter->chunk_num - 1, iter); + } + return 0; +} + +void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter) { + (void)iter; +} + diff --git a/drivers/webp/dsp/alpha_processing.c b/thirdparty/libwebp/dsp/alpha_processing.c index 1716cace8d..1716cace8d 100644 --- a/drivers/webp/dsp/alpha_processing.c +++ b/thirdparty/libwebp/dsp/alpha_processing.c diff --git a/drivers/webp/dsp/alpha_processing_mips_dsp_r2.c b/thirdparty/libwebp/dsp/alpha_processing_mips_dsp_r2.c index c631d78905..c631d78905 100644 --- a/drivers/webp/dsp/alpha_processing_mips_dsp_r2.c +++ b/thirdparty/libwebp/dsp/alpha_processing_mips_dsp_r2.c diff --git a/drivers/webp/dsp/alpha_processing_sse2.c b/thirdparty/libwebp/dsp/alpha_processing_sse2.c index 5acb481dcd..5acb481dcd 100644 --- a/drivers/webp/dsp/alpha_processing_sse2.c +++ b/thirdparty/libwebp/dsp/alpha_processing_sse2.c diff --git a/drivers/webp/dsp/alpha_processing_sse41.c b/thirdparty/libwebp/dsp/alpha_processing_sse41.c index 986fde94ed..986fde94ed 100644 --- a/drivers/webp/dsp/alpha_processing_sse41.c +++ b/thirdparty/libwebp/dsp/alpha_processing_sse41.c diff --git a/drivers/webp/dsp/argb.c b/thirdparty/libwebp/dsp/argb.c index cc1f9a96c3..cc1f9a96c3 100644 --- a/drivers/webp/dsp/argb.c +++ b/thirdparty/libwebp/dsp/argb.c diff --git a/drivers/webp/dsp/argb_mips_dsp_r2.c b/thirdparty/libwebp/dsp/argb_mips_dsp_r2.c index af65acb8ff..af65acb8ff 100644 --- a/drivers/webp/dsp/argb_mips_dsp_r2.c +++ b/thirdparty/libwebp/dsp/argb_mips_dsp_r2.c diff --git a/drivers/webp/dsp/argb_sse2.c b/thirdparty/libwebp/dsp/argb_sse2.c index afcb1957e7..afcb1957e7 100644 --- a/drivers/webp/dsp/argb_sse2.c +++ b/thirdparty/libwebp/dsp/argb_sse2.c diff --git a/drivers/webp/dsp/common_sse2.h b/thirdparty/libwebp/dsp/common_sse2.h index 7cea13fb3c..7cea13fb3c 100644 --- a/drivers/webp/dsp/common_sse2.h +++ b/thirdparty/libwebp/dsp/common_sse2.h diff --git a/drivers/webp/dsp/cost.c b/thirdparty/libwebp/dsp/cost.c index fe72d26e79..fe72d26e79 100644 --- a/drivers/webp/dsp/cost.c +++ b/thirdparty/libwebp/dsp/cost.c diff --git a/drivers/webp/dsp/cost_mips32.c b/thirdparty/libwebp/dsp/cost_mips32.c index d1e240e191..d1e240e191 100644 --- a/drivers/webp/dsp/cost_mips32.c +++ b/thirdparty/libwebp/dsp/cost_mips32.c diff --git a/drivers/webp/dsp/cost_mips_dsp_r2.c b/thirdparty/libwebp/dsp/cost_mips_dsp_r2.c index ce64067756..ce64067756 100644 --- a/drivers/webp/dsp/cost_mips_dsp_r2.c +++ b/thirdparty/libwebp/dsp/cost_mips_dsp_r2.c diff --git a/drivers/webp/dsp/cost_sse2.c b/thirdparty/libwebp/dsp/cost_sse2.c index 0cb1c1fa04..0cb1c1fa04 100644 --- a/drivers/webp/dsp/cost_sse2.c +++ b/thirdparty/libwebp/dsp/cost_sse2.c diff --git a/drivers/webp/dsp/cpu.c b/thirdparty/libwebp/dsp/cpu.c index cbb08db90a..cbb08db90a 100644 --- a/drivers/webp/dsp/cpu.c +++ b/thirdparty/libwebp/dsp/cpu.c diff --git a/drivers/webp/dsp/dec.c b/thirdparty/libwebp/dsp/dec.c index e92d693362..e92d693362 100644 --- a/drivers/webp/dsp/dec.c +++ b/thirdparty/libwebp/dsp/dec.c diff --git a/drivers/webp/dsp/dec_clip_tables.c b/thirdparty/libwebp/dsp/dec_clip_tables.c index 3b6dde86ba..3b6dde86ba 100644 --- a/drivers/webp/dsp/dec_clip_tables.c +++ b/thirdparty/libwebp/dsp/dec_clip_tables.c diff --git a/drivers/webp/dsp/dec_mips32.c b/thirdparty/libwebp/dsp/dec_mips32.c index 4e9ef42605..4e9ef42605 100644 --- a/drivers/webp/dsp/dec_mips32.c +++ b/thirdparty/libwebp/dsp/dec_mips32.c diff --git a/drivers/webp/dsp/dec_mips_dsp_r2.c b/thirdparty/libwebp/dsp/dec_mips_dsp_r2.c index db5c657228..db5c657228 100644 --- a/drivers/webp/dsp/dec_mips_dsp_r2.c +++ b/thirdparty/libwebp/dsp/dec_mips_dsp_r2.c diff --git a/drivers/webp/dsp/dec_msa.c b/thirdparty/libwebp/dsp/dec_msa.c index f76055cab0..f76055cab0 100644 --- a/drivers/webp/dsp/dec_msa.c +++ b/thirdparty/libwebp/dsp/dec_msa.c diff --git a/drivers/webp/dsp/dec_neon.c b/thirdparty/libwebp/dsp/dec_neon.c index a63f43fe17..a63f43fe17 100644 --- a/drivers/webp/dsp/dec_neon.c +++ b/thirdparty/libwebp/dsp/dec_neon.c diff --git a/drivers/webp/dsp/dec_sse2.c b/thirdparty/libwebp/dsp/dec_sse2.c index f0a8ddcaf3..f0a8ddcaf3 100644 --- a/drivers/webp/dsp/dec_sse2.c +++ b/thirdparty/libwebp/dsp/dec_sse2.c diff --git a/drivers/webp/dsp/dec_sse41.c b/thirdparty/libwebp/dsp/dec_sse41.c index 8d6aed13e6..8d6aed13e6 100644 --- a/drivers/webp/dsp/dec_sse41.c +++ b/thirdparty/libwebp/dsp/dec_sse41.c diff --git a/thirdparty/libwebp/dsp/dsp.h b/thirdparty/libwebp/dsp/dsp.h new file mode 100644 index 0000000000..1faac27b2b --- /dev/null +++ b/thirdparty/libwebp/dsp/dsp.h @@ -0,0 +1,569 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_DSP_DSP_H_ +#define WEBP_DSP_DSP_H_ + +#ifdef HAVE_CONFIG_H +#include "../webp/config.h" +#endif + +#include "../webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BPS 32 // this is the common stride for enc/dec + +//------------------------------------------------------------------------------ +// CPU detection + +#if defined(__GNUC__) +# define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__) +# define LOCAL_GCC_PREREQ(maj, min) \ + (LOCAL_GCC_VERSION >= (((maj) << 8) | (min))) +#else +# define LOCAL_GCC_VERSION 0 +# define LOCAL_GCC_PREREQ(maj, min) 0 +#endif + +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +#if defined(_MSC_VER) && _MSC_VER > 1310 && \ + (defined(_M_X64) || defined(_M_IX86)) +#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1500 && \ + (defined(_M_X64) || defined(_M_IX86)) +#define WEBP_MSC_SSE41 // Visual C++ SSE4.1 targets +#endif + +// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp +// files without intrinsics, allowing the corresponding Init() to be called. +// Files containing intrinsics will need to be built targeting the instruction +// set so should succeed on one of the earlier tests. +#if defined(__SSE2__) || defined(WEBP_MSC_SSE2) || defined(WEBP_HAVE_SSE2) +#define WEBP_USE_SSE2 +#endif + +#if defined(__SSE4_1__) || defined(WEBP_MSC_SSE41) || defined(WEBP_HAVE_SSE41) +#define WEBP_USE_SSE41 +#endif + +#if defined(__AVX2__) || defined(WEBP_HAVE_AVX2) +#define WEBP_USE_AVX2 +#endif + +#if defined(__ANDROID__) && defined(__ARM_ARCH_7A__) +#define WEBP_ANDROID_NEON // Android targets that might support NEON +#endif + +// The intrinsics currently cause compiler errors with arm-nacl-gcc and the +// inline assembly would need to be modified for use with Native Client. +#if (defined(__ARM_NEON__) || defined(WEBP_ANDROID_NEON) || \ + defined(__aarch64__) || defined(WEBP_HAVE_NEON)) && \ + !defined(__native_client__) +#define WEBP_USE_NEON +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM) +#define WEBP_USE_NEON +#define WEBP_USE_INTRINSICS +#endif + +#if defined(__mips__) && !defined(__mips64) && \ + defined(__mips_isa_rev) && (__mips_isa_rev >= 1) && (__mips_isa_rev < 6) +#define WEBP_USE_MIPS32 +#if (__mips_isa_rev >= 2) +#define WEBP_USE_MIPS32_R2 +#if defined(__mips_dspr2) || (__mips_dsp_rev >= 2) +#define WEBP_USE_MIPS_DSP_R2 +#endif +#endif +#endif + +#if defined(__mips_msa) && defined(__mips_isa_rev) && (__mips_isa_rev >= 5) +#define WEBP_USE_MSA +#endif + +// This macro prevents thread_sanitizer from reporting known concurrent writes. +#define WEBP_TSAN_IGNORE_FUNCTION +#if defined(__has_feature) +#if __has_feature(thread_sanitizer) +#undef WEBP_TSAN_IGNORE_FUNCTION +#define WEBP_TSAN_IGNORE_FUNCTION __attribute__((no_sanitize_thread)) +#endif +#endif + +#define WEBP_UBSAN_IGNORE_UNDEF +#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW +#if !defined(WEBP_FORCE_ALIGNED) && defined(__clang__) && \ + defined(__has_attribute) +#if __has_attribute(no_sanitize) +// This macro prevents the undefined behavior sanitizer from reporting +// failures. This is only meant to silence unaligned loads on platforms that +// are known to support them. +#undef WEBP_UBSAN_IGNORE_UNDEF +#define WEBP_UBSAN_IGNORE_UNDEF \ + __attribute__((no_sanitize("undefined"))) + +// This macro prevents the undefined behavior sanitizer from reporting +// failures related to unsigned integer overflows. This is only meant to +// silence cases where this well defined behavior is expected. +#undef WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW +#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW \ + __attribute__((no_sanitize("unsigned-integer-overflow"))) +#endif +#endif + +typedef enum { + kSSE2, + kSSE3, + kSSE4_1, + kAVX, + kAVX2, + kNEON, + kMIPS32, + kMIPSdspR2, + kMSA +} CPUFeature; +// returns true if the CPU supports the feature. +typedef int (*VP8CPUInfo)(CPUFeature feature); +WEBP_EXTERN(VP8CPUInfo) VP8GetCPUInfo; + +//------------------------------------------------------------------------------ +// Init stub generator + +// Defines an init function stub to ensure each module exposes a symbol, +// avoiding a compiler warning. +#define WEBP_DSP_INIT_STUB(func) \ + extern void func(void); \ + WEBP_TSAN_IGNORE_FUNCTION void func(void) {} + +//------------------------------------------------------------------------------ +// Encoding + +// Transforms +// VP8Idct: Does one of two inverse transforms. If do_two is set, the transforms +// will be done for (ref, in, dst) and (ref + 4, in + 16, dst + 4). +typedef void (*VP8Idct)(const uint8_t* ref, const int16_t* in, uint8_t* dst, + int do_two); +typedef void (*VP8Fdct)(const uint8_t* src, const uint8_t* ref, int16_t* out); +typedef void (*VP8WHT)(const int16_t* in, int16_t* out); +extern VP8Idct VP8ITransform; +extern VP8Fdct VP8FTransform; +extern VP8Fdct VP8FTransform2; // performs two transforms at a time +extern VP8WHT VP8FTransformWHT; +// Predictions +// *dst is the destination block. *top and *left can be NULL. +typedef void (*VP8IntraPreds)(uint8_t *dst, const uint8_t* left, + const uint8_t* top); +typedef void (*VP8Intra4Preds)(uint8_t *dst, const uint8_t* top); +extern VP8Intra4Preds VP8EncPredLuma4; +extern VP8IntraPreds VP8EncPredLuma16; +extern VP8IntraPreds VP8EncPredChroma8; + +typedef int (*VP8Metric)(const uint8_t* pix, const uint8_t* ref); +extern VP8Metric VP8SSE16x16, VP8SSE16x8, VP8SSE8x8, VP8SSE4x4; +typedef int (*VP8WMetric)(const uint8_t* pix, const uint8_t* ref, + const uint16_t* const weights); +// The weights for VP8TDisto4x4 and VP8TDisto16x16 contain a row-major +// 4 by 4 symmetric matrix. +extern VP8WMetric VP8TDisto4x4, VP8TDisto16x16; + +typedef void (*VP8BlockCopy)(const uint8_t* src, uint8_t* dst); +extern VP8BlockCopy VP8Copy4x4; +extern VP8BlockCopy VP8Copy16x8; +// Quantization +struct VP8Matrix; // forward declaration +typedef int (*VP8QuantizeBlock)(int16_t in[16], int16_t out[16], + const struct VP8Matrix* const mtx); +// Same as VP8QuantizeBlock, but quantizes two consecutive blocks. +typedef int (*VP8Quantize2Blocks)(int16_t in[32], int16_t out[32], + const struct VP8Matrix* const mtx); + +extern VP8QuantizeBlock VP8EncQuantizeBlock; +extern VP8Quantize2Blocks VP8EncQuantize2Blocks; + +// specific to 2nd transform: +typedef int (*VP8QuantizeBlockWHT)(int16_t in[16], int16_t out[16], + const struct VP8Matrix* const mtx); +extern VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT; + +extern const int VP8DspScan[16 + 4 + 4]; + +// Collect histogram for susceptibility calculation. +#define MAX_COEFF_THRESH 31 // size of histogram used by CollectHistogram. +typedef struct { + // We only need to store max_value and last_non_zero, not the distribution. + int max_value; + int last_non_zero; +} VP8Histogram; +typedef void (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo); +extern VP8CHisto VP8CollectHistogram; +// General-purpose util function to help VP8CollectHistogram(). +void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1], + VP8Histogram* const histo); + +// must be called before using any of the above +void VP8EncDspInit(void); + +//------------------------------------------------------------------------------ +// cost functions (encoding) + +extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p) +// approximate cost per level: +extern const uint16_t VP8LevelFixedCosts[2047 /*MAX_LEVEL*/ + 1]; +extern const uint8_t VP8EncBands[16 + 1]; + +struct VP8Residual; +typedef void (*VP8SetResidualCoeffsFunc)(const int16_t* const coeffs, + struct VP8Residual* const res); +extern VP8SetResidualCoeffsFunc VP8SetResidualCoeffs; + +// Cost calculation function. +typedef int (*VP8GetResidualCostFunc)(int ctx0, + const struct VP8Residual* const res); +extern VP8GetResidualCostFunc VP8GetResidualCost; + +// must be called before anything using the above +void VP8EncDspCostInit(void); + +//------------------------------------------------------------------------------ +// SSIM utils + +// struct for accumulating statistical moments +typedef struct { + double w; // sum(w_i) : sum of weights + double xm, ym; // sum(w_i * x_i), sum(w_i * y_i) + double xxm, xym, yym; // sum(w_i * x_i * x_i), etc. +} VP8DistoStats; + +#define VP8_SSIM_KERNEL 3 // total size of the kernel: 2 * VP8_SSIM_KERNEL + 1 +typedef void (*VP8SSIMAccumulateClippedFunc)(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2, + int xo, int yo, // center position + int W, int H, // plane dimension + VP8DistoStats* const stats); + +// This version is called with the guarantee that you can load 8 bytes and +// 8 rows at offset src1 and src2 +typedef void (*VP8SSIMAccumulateFunc)(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2, + VP8DistoStats* const stats); + +extern VP8SSIMAccumulateFunc VP8SSIMAccumulate; // unclipped / unchecked +extern VP8SSIMAccumulateClippedFunc VP8SSIMAccumulateClipped; // with clipping + +// must be called before using any of the above directly +void VP8SSIMDspInit(void); + +//------------------------------------------------------------------------------ +// Decoding + +typedef void (*VP8DecIdct)(const int16_t* coeffs, uint8_t* dst); +// when doing two transforms, coeffs is actually int16_t[2][16]. +typedef void (*VP8DecIdct2)(const int16_t* coeffs, uint8_t* dst, int do_two); +extern VP8DecIdct2 VP8Transform; +extern VP8DecIdct VP8TransformAC3; +extern VP8DecIdct VP8TransformUV; +extern VP8DecIdct VP8TransformDC; +extern VP8DecIdct VP8TransformDCUV; +extern VP8WHT VP8TransformWHT; + +// *dst is the destination block, with stride BPS. Boundary samples are +// assumed accessible when needed. +typedef void (*VP8PredFunc)(uint8_t* dst); +extern VP8PredFunc VP8PredLuma16[/* NUM_B_DC_MODES */]; +extern VP8PredFunc VP8PredChroma8[/* NUM_B_DC_MODES */]; +extern VP8PredFunc VP8PredLuma4[/* NUM_BMODES */]; + +// clipping tables (for filtering) +extern const int8_t* const VP8ksclip1; // clips [-1020, 1020] to [-128, 127] +extern const int8_t* const VP8ksclip2; // clips [-112, 112] to [-16, 15] +extern const uint8_t* const VP8kclip1; // clips [-255,511] to [0,255] +extern const uint8_t* const VP8kabs0; // abs(x) for x in [-255,255] +// must be called first +void VP8InitClipTables(void); + +// simple filter (only for luma) +typedef void (*VP8SimpleFilterFunc)(uint8_t* p, int stride, int thresh); +extern VP8SimpleFilterFunc VP8SimpleVFilter16; +extern VP8SimpleFilterFunc VP8SimpleHFilter16; +extern VP8SimpleFilterFunc VP8SimpleVFilter16i; // filter 3 inner edges +extern VP8SimpleFilterFunc VP8SimpleHFilter16i; + +// regular filter (on both macroblock edges and inner edges) +typedef void (*VP8LumaFilterFunc)(uint8_t* luma, int stride, + int thresh, int ithresh, int hev_t); +typedef void (*VP8ChromaFilterFunc)(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_t); +// on outer edge +extern VP8LumaFilterFunc VP8VFilter16; +extern VP8LumaFilterFunc VP8HFilter16; +extern VP8ChromaFilterFunc VP8VFilter8; +extern VP8ChromaFilterFunc VP8HFilter8; + +// on inner edge +extern VP8LumaFilterFunc VP8VFilter16i; // filtering 3 inner edges altogether +extern VP8LumaFilterFunc VP8HFilter16i; +extern VP8ChromaFilterFunc VP8VFilter8i; // filtering u and v altogether +extern VP8ChromaFilterFunc VP8HFilter8i; + +// Dithering. Combines dithering values (centered around 128) with dst[], +// according to: dst[] = clip(dst[] + (((dither[]-128) + 8) >> 4) +#define VP8_DITHER_DESCALE 4 +#define VP8_DITHER_DESCALE_ROUNDER (1 << (VP8_DITHER_DESCALE - 1)) +#define VP8_DITHER_AMP_BITS 7 +#define VP8_DITHER_AMP_CENTER (1 << VP8_DITHER_AMP_BITS) +extern void (*VP8DitherCombine8x8)(const uint8_t* dither, uint8_t* dst, + int dst_stride); + +// must be called before anything using the above +void VP8DspInit(void); + +//------------------------------------------------------------------------------ +// WebP I/O + +#define FANCY_UPSAMPLING // undefined to remove fancy upsampling support + +// Convert a pair of y/u/v lines together to the output rgb/a colorspace. +// bottom_y can be NULL if only one line of output is needed (at top/bottom). +typedef void (*WebPUpsampleLinePairFunc)( + const uint8_t* top_y, const uint8_t* bottom_y, + const uint8_t* top_u, const uint8_t* top_v, + const uint8_t* cur_u, const uint8_t* cur_v, + uint8_t* top_dst, uint8_t* bottom_dst, int len); + +#ifdef FANCY_UPSAMPLING + +// Fancy upsampling functions to convert YUV to RGB(A) modes +extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; + +#endif // FANCY_UPSAMPLING + +// Per-row point-sampling methods. +typedef void (*WebPSamplerRowFunc)(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len); +// Generic function to apply 'WebPSamplerRowFunc' to the whole plane: +void WebPSamplerProcessPlane(const uint8_t* y, int y_stride, + const uint8_t* u, const uint8_t* v, int uv_stride, + uint8_t* dst, int dst_stride, + int width, int height, WebPSamplerRowFunc func); + +// Sampling functions to convert rows of YUV to RGB(A) +extern WebPSamplerRowFunc WebPSamplers[/* MODE_LAST */]; + +// General function for converting two lines of ARGB or RGBA. +// 'alpha_is_last' should be true if 0xff000000 is stored in memory as +// as 0x00, 0x00, 0x00, 0xff (little endian). +WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last); + +// YUV444->RGB converters +typedef void (*WebPYUV444Converter)(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len); + +extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */]; + +// Must be called before using the WebPUpsamplers[] (and for premultiplied +// colorspaces like rgbA, rgbA4444, etc) +void WebPInitUpsamplers(void); +// Must be called before using WebPSamplers[] +void WebPInitSamplers(void); +// Must be called before using WebPYUV444Converters[] +void WebPInitYUV444Converters(void); + +//------------------------------------------------------------------------------ +// ARGB -> YUV converters + +// Convert ARGB samples to luma Y. +extern void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width); +// Convert ARGB samples to U/V with downsampling. do_store should be '1' for +// even lines and '0' for odd ones. 'src_width' is the original width, not +// the U/V one. +extern void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v, + int src_width, int do_store); + +// Convert a row of accumulated (four-values) of rgba32 toward U/V +extern void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width); + +// Convert RGB or BGR to Y +extern void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width); +extern void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width); + +// used for plain-C fallback. +extern void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v, + int src_width, int do_store); +extern void WebPConvertRGBA32ToUV_C(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width); + +// Must be called before using the above. +void WebPInitConvertARGBToYUV(void); + +//------------------------------------------------------------------------------ +// Rescaler + +struct WebPRescaler; + +// Import a row of data and save its contribution in the rescaler. +// 'channel' denotes the channel number to be imported. 'Expand' corresponds to +// the wrk->x_expand case. Otherwise, 'Shrink' is to be used. +typedef void (*WebPRescalerImportRowFunc)(struct WebPRescaler* const wrk, + const uint8_t* src); + +extern WebPRescalerImportRowFunc WebPRescalerImportRowExpand; +extern WebPRescalerImportRowFunc WebPRescalerImportRowShrink; + +// Export one row (starting at x_out position) from rescaler. +// 'Expand' corresponds to the wrk->y_expand case. +// Otherwise 'Shrink' is to be used +typedef void (*WebPRescalerExportRowFunc)(struct WebPRescaler* const wrk); +extern WebPRescalerExportRowFunc WebPRescalerExportRowExpand; +extern WebPRescalerExportRowFunc WebPRescalerExportRowShrink; + +// Plain-C implementation, as fall-back. +extern void WebPRescalerImportRowExpandC(struct WebPRescaler* const wrk, + const uint8_t* src); +extern void WebPRescalerImportRowShrinkC(struct WebPRescaler* const wrk, + const uint8_t* src); +extern void WebPRescalerExportRowExpandC(struct WebPRescaler* const wrk); +extern void WebPRescalerExportRowShrinkC(struct WebPRescaler* const wrk); + +// Main entry calls: +extern void WebPRescalerImportRow(struct WebPRescaler* const wrk, + const uint8_t* src); +// Export one row (starting at x_out position) from rescaler. +extern void WebPRescalerExportRow(struct WebPRescaler* const wrk); + +// Must be called first before using the above. +void WebPRescalerDspInit(void); + +//------------------------------------------------------------------------------ +// Utilities for processing transparent channel. + +// Apply alpha pre-multiply on an rgba, bgra or argb plane of size w * h. +// alpha_first should be 0 for argb, 1 for rgba or bgra (where alpha is last). +extern void (*WebPApplyAlphaMultiply)( + uint8_t* rgba, int alpha_first, int w, int h, int stride); + +// Same, buf specifically for RGBA4444 format +extern void (*WebPApplyAlphaMultiply4444)( + uint8_t* rgba4444, int w, int h, int stride); + +// Dispatch the values from alpha[] plane to the ARGB destination 'dst'. +// Returns true if alpha[] plane has non-trivial values different from 0xff. +extern int (*WebPDispatchAlpha)(const uint8_t* alpha, int alpha_stride, + int width, int height, + uint8_t* dst, int dst_stride); + +// Transfer packed 8b alpha[] values to green channel in dst[], zero'ing the +// A/R/B values. 'dst_stride' is the stride for dst[] in uint32_t units. +extern void (*WebPDispatchAlphaToGreen)(const uint8_t* alpha, int alpha_stride, + int width, int height, + uint32_t* dst, int dst_stride); + +// Extract the alpha values from 32b values in argb[] and pack them into alpha[] +// (this is the opposite of WebPDispatchAlpha). +// Returns true if there's only trivial 0xff alpha values. +extern int (*WebPExtractAlpha)(const uint8_t* argb, int argb_stride, + int width, int height, + uint8_t* alpha, int alpha_stride); + +// Pre-Multiply operation transforms x into x * A / 255 (where x=Y,R,G or B). +// Un-Multiply operation transforms x into x * 255 / A. + +// Pre-Multiply or Un-Multiply (if 'inverse' is true) argb values in a row. +extern void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse); + +// Same a WebPMultARGBRow(), but for several rows. +void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, + int inverse); + +// Same for a row of single values, with side alpha values. +extern void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha, + int width, int inverse); + +// Same a WebPMultRow(), but for several 'num_rows' rows. +void WebPMultRows(uint8_t* ptr, int stride, + const uint8_t* alpha, int alpha_stride, + int width, int num_rows, int inverse); + +// Plain-C versions, used as fallback by some implementations. +void WebPMultRowC(uint8_t* const ptr, const uint8_t* const alpha, + int width, int inverse); +void WebPMultARGBRowC(uint32_t* const ptr, int width, int inverse); + +// To be called first before using the above. +void WebPInitAlphaProcessing(void); + +// ARGB packing function: a/r/g/b input is rgba or bgra order. +extern void (*VP8PackARGB)(const uint8_t* a, const uint8_t* r, + const uint8_t* g, const uint8_t* b, int len, + uint32_t* out); + +// RGB packing function. 'step' can be 3 or 4. r/g/b input is rgb or bgr order. +extern void (*VP8PackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b, + int len, int step, uint32_t* out); + +// To be called first before using the above. +void VP8EncDspARGBInit(void); + +//------------------------------------------------------------------------------ +// Filter functions + +typedef enum { // Filter types. + WEBP_FILTER_NONE = 0, + WEBP_FILTER_HORIZONTAL, + WEBP_FILTER_VERTICAL, + WEBP_FILTER_GRADIENT, + WEBP_FILTER_LAST = WEBP_FILTER_GRADIENT + 1, // end marker + WEBP_FILTER_BEST, // meta-types + WEBP_FILTER_FAST +} WEBP_FILTER_TYPE; + +typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height, + int stride, uint8_t* out); +// In-place un-filtering. +// Warning! 'prev_line' pointer can be equal to 'cur_line' or 'preds'. +typedef void (*WebPUnfilterFunc)(const uint8_t* prev_line, const uint8_t* preds, + uint8_t* cur_line, int width); + +// Filter the given data using the given predictor. +// 'in' corresponds to a 2-dimensional pixel array of size (stride * height) +// in raster order. +// 'stride' is number of bytes per scan line (with possible padding). +// 'out' should be pre-allocated. +extern WebPFilterFunc WebPFilters[WEBP_FILTER_LAST]; + +// In-place reconstruct the original data from the given filtered data. +// The reconstruction will be done for 'num_rows' rows starting from 'row' +// (assuming rows upto 'row - 1' are already reconstructed). +extern WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST]; + +// To be called first before using the above. +void VP8FiltersInit(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_DSP_DSP_H_ */ diff --git a/drivers/webp/dsp/enc.c b/thirdparty/libwebp/dsp/enc.c index f639f5570c..f639f5570c 100644 --- a/drivers/webp/dsp/enc.c +++ b/thirdparty/libwebp/dsp/enc.c diff --git a/drivers/webp/dsp/enc_avx2.c b/thirdparty/libwebp/dsp/enc_avx2.c index 93efb30b10..93efb30b10 100644 --- a/drivers/webp/dsp/enc_avx2.c +++ b/thirdparty/libwebp/dsp/enc_avx2.c diff --git a/drivers/webp/dsp/enc_mips32.c b/thirdparty/libwebp/dsp/enc_mips32.c index fd10143de9..fd10143de9 100644 --- a/drivers/webp/dsp/enc_mips32.c +++ b/thirdparty/libwebp/dsp/enc_mips32.c diff --git a/drivers/webp/dsp/enc_mips_dsp_r2.c b/thirdparty/libwebp/dsp/enc_mips_dsp_r2.c index 7ab96f6800..7ab96f6800 100644 --- a/drivers/webp/dsp/enc_mips_dsp_r2.c +++ b/thirdparty/libwebp/dsp/enc_mips_dsp_r2.c diff --git a/drivers/webp/dsp/enc_neon.c b/thirdparty/libwebp/dsp/enc_neon.c index 46f6bf9a33..46f6bf9a33 100644 --- a/drivers/webp/dsp/enc_neon.c +++ b/thirdparty/libwebp/dsp/enc_neon.c diff --git a/drivers/webp/dsp/enc_sse2.c b/thirdparty/libwebp/dsp/enc_sse2.c index 4a2e3ce14f..4a2e3ce14f 100644 --- a/drivers/webp/dsp/enc_sse2.c +++ b/thirdparty/libwebp/dsp/enc_sse2.c diff --git a/drivers/webp/dsp/enc_sse41.c b/thirdparty/libwebp/dsp/enc_sse41.c index a1783901a6..a1783901a6 100644 --- a/drivers/webp/dsp/enc_sse41.c +++ b/thirdparty/libwebp/dsp/enc_sse41.c diff --git a/drivers/webp/dsp/filters.c b/thirdparty/libwebp/dsp/filters.c index 9f04faf0cb..9f04faf0cb 100644 --- a/drivers/webp/dsp/filters.c +++ b/thirdparty/libwebp/dsp/filters.c diff --git a/drivers/webp/dsp/filters_mips_dsp_r2.c b/thirdparty/libwebp/dsp/filters_mips_dsp_r2.c index 1d82e3c2e1..1d82e3c2e1 100644 --- a/drivers/webp/dsp/filters_mips_dsp_r2.c +++ b/thirdparty/libwebp/dsp/filters_mips_dsp_r2.c diff --git a/drivers/webp/dsp/filters_sse2.c b/thirdparty/libwebp/dsp/filters_sse2.c index 67f77999e6..67f77999e6 100644 --- a/drivers/webp/dsp/filters_sse2.c +++ b/thirdparty/libwebp/dsp/filters_sse2.c diff --git a/drivers/webp/dsp/lossless.c b/thirdparty/libwebp/dsp/lossless.c index af913efccb..af913efccb 100644 --- a/drivers/webp/dsp/lossless.c +++ b/thirdparty/libwebp/dsp/lossless.c diff --git a/thirdparty/libwebp/dsp/lossless.h b/thirdparty/libwebp/dsp/lossless.h new file mode 100644 index 0000000000..9f0d7a25b7 --- /dev/null +++ b/thirdparty/libwebp/dsp/lossless.h @@ -0,0 +1,372 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transforms and color space conversion methods for lossless decoder. +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) + +#ifndef WEBP_DSP_LOSSLESS_H_ +#define WEBP_DSP_LOSSLESS_H_ + +#include "../webp/types.h" +#include "../webp/decode.h" + +#include "../enc/histogram.h" +#include "../utils/utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WEBP_EXPERIMENTAL_FEATURES +#include "../enc/delta_palettization.h" +#endif // WEBP_EXPERIMENTAL_FEATURES + +//------------------------------------------------------------------------------ +// Decoding + +typedef uint32_t (*VP8LPredictorFunc)(uint32_t left, const uint32_t* const top); +extern VP8LPredictorFunc VP8LPredictors[16]; + +typedef void (*VP8LProcessBlueAndRedFunc)(uint32_t* argb_data, int num_pixels); +extern VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed; + +typedef struct { + // Note: the members are uint8_t, so that any negative values are + // automatically converted to "mod 256" values. + uint8_t green_to_red_; + uint8_t green_to_blue_; + uint8_t red_to_blue_; +} VP8LMultipliers; +typedef void (*VP8LTransformColorFunc)(const VP8LMultipliers* const m, + uint32_t* argb_data, int num_pixels); +extern VP8LTransformColorFunc VP8LTransformColorInverse; + +struct VP8LTransform; // Defined in dec/vp8li.h. + +// Performs inverse transform of data given transform information, start and end +// rows. Transform will be applied to rows [row_start, row_end[. +// The *in and *out pointers refer to source and destination data respectively +// corresponding to the intermediate row (row_start). +void VP8LInverseTransform(const struct VP8LTransform* const transform, + int row_start, int row_end, + const uint32_t* const in, uint32_t* const out); + +// Color space conversion. +typedef void (*VP8LConvertFunc)(const uint32_t* src, int num_pixels, + uint8_t* dst); +extern VP8LConvertFunc VP8LConvertBGRAToRGB; +extern VP8LConvertFunc VP8LConvertBGRAToRGBA; +extern VP8LConvertFunc VP8LConvertBGRAToRGBA4444; +extern VP8LConvertFunc VP8LConvertBGRAToRGB565; +extern VP8LConvertFunc VP8LConvertBGRAToBGR; + +// Converts from BGRA to other color spaces. +void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels, + WEBP_CSP_MODE out_colorspace, uint8_t* const rgba); + +// color mapping related functions. +static WEBP_INLINE uint32_t VP8GetARGBIndex(uint32_t idx) { + return (idx >> 8) & 0xff; +} + +static WEBP_INLINE uint8_t VP8GetAlphaIndex(uint8_t idx) { + return idx; +} + +static WEBP_INLINE uint32_t VP8GetARGBValue(uint32_t val) { + return val; +} + +static WEBP_INLINE uint8_t VP8GetAlphaValue(uint32_t val) { + return (val >> 8) & 0xff; +} + +typedef void (*VP8LMapARGBFunc)(const uint32_t* src, + const uint32_t* const color_map, + uint32_t* dst, int y_start, + int y_end, int width); +typedef void (*VP8LMapAlphaFunc)(const uint8_t* src, + const uint32_t* const color_map, + uint8_t* dst, int y_start, + int y_end, int width); + +extern VP8LMapARGBFunc VP8LMapColor32b; +extern VP8LMapAlphaFunc VP8LMapColor8b; + +// Similar to the static method ColorIndexInverseTransform() that is part of +// lossless.c, but used only for alpha decoding. It takes uint8_t (rather than +// uint32_t) arguments for 'src' and 'dst'. +void VP8LColorIndexInverseTransformAlpha( + const struct VP8LTransform* const transform, int y_start, int y_end, + const uint8_t* src, uint8_t* dst); + +// Expose some C-only fallback functions +void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, + uint32_t* data, int num_pixels); + +void VP8LConvertBGRAToRGB_C(const uint32_t* src, int num_pixels, uint8_t* dst); +void VP8LConvertBGRAToRGBA_C(const uint32_t* src, int num_pixels, uint8_t* dst); +void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src, + int num_pixels, uint8_t* dst); +void VP8LConvertBGRAToRGB565_C(const uint32_t* src, + int num_pixels, uint8_t* dst); +void VP8LConvertBGRAToBGR_C(const uint32_t* src, int num_pixels, uint8_t* dst); +void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels); + +// Must be called before calling any of the above methods. +void VP8LDspInit(void); + +//------------------------------------------------------------------------------ +// Encoding + +extern VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed; +extern VP8LTransformColorFunc VP8LTransformColor; +typedef void (*VP8LCollectColorBlueTransformsFunc)( + const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_blue, int red_to_blue, int histo[]); +extern VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms; + +typedef void (*VP8LCollectColorRedTransformsFunc)( + const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_red, int histo[]); +extern VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms; + +// Expose some C-only fallback functions +void VP8LTransformColor_C(const VP8LMultipliers* const m, + uint32_t* data, int num_pixels); +void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels); +void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_red, int histo[]); +void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_blue, int red_to_blue, + int histo[]); + +//------------------------------------------------------------------------------ +// Image transforms. + +void VP8LResidualImage(int width, int height, int bits, int low_effort, + uint32_t* const argb, uint32_t* const argb_scratch, + uint32_t* const image, int near_lossless, int exact, + int used_subtract_green); + +void VP8LColorSpaceTransform(int width, int height, int bits, int quality, + uint32_t* const argb, uint32_t* image); + +//------------------------------------------------------------------------------ +// Misc methods. + +// Computes sampled size of 'size' when sampling using 'sampling bits'. +static WEBP_INLINE uint32_t VP8LSubSampleSize(uint32_t size, + uint32_t sampling_bits) { + return (size + (1 << sampling_bits) - 1) >> sampling_bits; +} + +// Converts near lossless quality into max number of bits shaved off. +static WEBP_INLINE int VP8LNearLosslessBits(int near_lossless_quality) { + // 100 -> 0 + // 80..99 -> 1 + // 60..79 -> 2 + // 40..59 -> 3 + // 20..39 -> 4 + // 0..19 -> 5 + return 5 - near_lossless_quality / 20; +} + +// ----------------------------------------------------------------------------- +// Faster logarithm for integers. Small values use a look-up table. + +// The threshold till approximate version of log_2 can be used. +// Practically, we can get rid of the call to log() as the two values match to +// very high degree (the ratio of these two is 0.99999x). +// Keeping a high threshold for now. +#define APPROX_LOG_WITH_CORRECTION_MAX 65536 +#define APPROX_LOG_MAX 4096 +#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086 +#define LOG_LOOKUP_IDX_MAX 256 +extern const float kLog2Table[LOG_LOOKUP_IDX_MAX]; +extern const float kSLog2Table[LOG_LOOKUP_IDX_MAX]; +typedef float (*VP8LFastLog2SlowFunc)(uint32_t v); + +extern VP8LFastLog2SlowFunc VP8LFastLog2Slow; +extern VP8LFastLog2SlowFunc VP8LFastSLog2Slow; + +static WEBP_INLINE float VP8LFastLog2(uint32_t v) { + return (v < LOG_LOOKUP_IDX_MAX) ? kLog2Table[v] : VP8LFastLog2Slow(v); +} +// Fast calculation of v * log2(v) for integer input. +static WEBP_INLINE float VP8LFastSLog2(uint32_t v) { + return (v < LOG_LOOKUP_IDX_MAX) ? kSLog2Table[v] : VP8LFastSLog2Slow(v); +} + +// ----------------------------------------------------------------------------- +// Huffman-cost related functions. + +typedef double (*VP8LCostFunc)(const uint32_t* population, int length); +typedef double (*VP8LCostCombinedFunc)(const uint32_t* X, const uint32_t* Y, + int length); +typedef float (*VP8LCombinedShannonEntropyFunc)(const int X[256], + const int Y[256]); + +extern VP8LCostFunc VP8LExtraCost; +extern VP8LCostCombinedFunc VP8LExtraCostCombined; +extern VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy; + +typedef struct { // small struct to hold counters + int counts[2]; // index: 0=zero steak, 1=non-zero streak + int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3] +} VP8LStreaks; + +typedef VP8LStreaks (*VP8LCostCombinedCountFunc)(const uint32_t* X, + const uint32_t* Y, int length); + +extern VP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount; + +typedef struct { // small struct to hold bit entropy results + double entropy; // entropy + uint32_t sum; // sum of the population + int nonzeros; // number of non-zero elements in the population + uint32_t max_val; // maximum value in the population + uint32_t nonzero_code; // index of the last non-zero in the population +} VP8LBitEntropy; + +void VP8LBitEntropyInit(VP8LBitEntropy* const entropy); + +// Get the combined symbol bit entropy and Huffman cost stats for the +// distributions 'X' and 'Y'. Those results can then be refined according to +// codec specific heuristics. +void VP8LGetCombinedEntropyUnrefined(const uint32_t* const X, + const uint32_t* const Y, int length, + VP8LBitEntropy* const bit_entropy, + VP8LStreaks* const stats); +// Get the entropy for the distribution 'X'. +void VP8LGetEntropyUnrefined(const uint32_t* const X, int length, + VP8LBitEntropy* const bit_entropy, + VP8LStreaks* const stats); + +void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n, + VP8LBitEntropy* const entropy); + +typedef void (*GetEntropyUnrefinedHelperFunc)(uint32_t val, int i, + uint32_t* const val_prev, + int* const i_prev, + VP8LBitEntropy* const bit_entropy, + VP8LStreaks* const stats); +// Internal function used by VP8LGet*EntropyUnrefined. +extern GetEntropyUnrefinedHelperFunc VP8LGetEntropyUnrefinedHelper; + +typedef void (*VP8LHistogramAddFunc)(const VP8LHistogram* const a, + const VP8LHistogram* const b, + VP8LHistogram* const out); +extern VP8LHistogramAddFunc VP8LHistogramAdd; + +// ----------------------------------------------------------------------------- +// PrefixEncode() + +typedef int (*VP8LVectorMismatchFunc)(const uint32_t* const array1, + const uint32_t* const array2, int length); +// Returns the first index where array1 and array2 are different. +extern VP8LVectorMismatchFunc VP8LVectorMismatch; + +static WEBP_INLINE int VP8LBitsLog2Ceiling(uint32_t n) { + const int log_floor = BitsLog2Floor(n); + if (n == (n & ~(n - 1))) // zero or a power of two. + return log_floor; + else + return log_floor + 1; +} + +// Splitting of distance and length codes into prefixes and +// extra bits. The prefixes are encoded with an entropy code +// while the extra bits are stored just as normal bits. +static WEBP_INLINE void VP8LPrefixEncodeBitsNoLUT(int distance, int* const code, + int* const extra_bits) { + const int highest_bit = BitsLog2Floor(--distance); + const int second_highest_bit = (distance >> (highest_bit - 1)) & 1; + *extra_bits = highest_bit - 1; + *code = 2 * highest_bit + second_highest_bit; +} + +static WEBP_INLINE void VP8LPrefixEncodeNoLUT(int distance, int* const code, + int* const extra_bits, + int* const extra_bits_value) { + const int highest_bit = BitsLog2Floor(--distance); + const int second_highest_bit = (distance >> (highest_bit - 1)) & 1; + *extra_bits = highest_bit - 1; + *extra_bits_value = distance & ((1 << *extra_bits) - 1); + *code = 2 * highest_bit + second_highest_bit; +} + +#define PREFIX_LOOKUP_IDX_MAX 512 +typedef struct { + int8_t code_; + int8_t extra_bits_; +} VP8LPrefixCode; + +// These tables are derived using VP8LPrefixEncodeNoLUT. +extern const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX]; +extern const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX]; +static WEBP_INLINE void VP8LPrefixEncodeBits(int distance, int* const code, + int* const extra_bits) { + if (distance < PREFIX_LOOKUP_IDX_MAX) { + const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance]; + *code = prefix_code.code_; + *extra_bits = prefix_code.extra_bits_; + } else { + VP8LPrefixEncodeBitsNoLUT(distance, code, extra_bits); + } +} + +static WEBP_INLINE void VP8LPrefixEncode(int distance, int* const code, + int* const extra_bits, + int* const extra_bits_value) { + if (distance < PREFIX_LOOKUP_IDX_MAX) { + const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance]; + *code = prefix_code.code_; + *extra_bits = prefix_code.extra_bits_; + *extra_bits_value = kPrefixEncodeExtraBitsValue[distance]; + } else { + VP8LPrefixEncodeNoLUT(distance, code, extra_bits, extra_bits_value); + } +} + +// Sum of each component, mod 256. +static WEBP_INLINE uint32_t VP8LAddPixels(uint32_t a, uint32_t b) { + const uint32_t alpha_and_green = (a & 0xff00ff00u) + (b & 0xff00ff00u); + const uint32_t red_and_blue = (a & 0x00ff00ffu) + (b & 0x00ff00ffu); + return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); +} + +// Difference of each component, mod 256. +static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) { + const uint32_t alpha_and_green = + 0x00ff00ffu + (a & 0xff00ff00u) - (b & 0xff00ff00u); + const uint32_t red_and_blue = + 0xff00ff00u + (a & 0x00ff00ffu) - (b & 0x00ff00ffu); + return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); +} + +void VP8LBundleColorMap(const uint8_t* const row, int width, + int xbits, uint32_t* const dst); + +// Must be called before calling any of the above methods. +void VP8LEncDspInit(void); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DSP_LOSSLESS_H_ diff --git a/drivers/webp/dsp/lossless_enc.c b/thirdparty/libwebp/dsp/lossless_enc.c index 256f6f5f8b..256f6f5f8b 100644 --- a/drivers/webp/dsp/lossless_enc.c +++ b/thirdparty/libwebp/dsp/lossless_enc.c diff --git a/drivers/webp/dsp/lossless_enc_mips32.c b/thirdparty/libwebp/dsp/lossless_enc_mips32.c index 49c666d4fd..49c666d4fd 100644 --- a/drivers/webp/dsp/lossless_enc_mips32.c +++ b/thirdparty/libwebp/dsp/lossless_enc_mips32.c diff --git a/drivers/webp/dsp/lossless_enc_mips_dsp_r2.c b/thirdparty/libwebp/dsp/lossless_enc_mips_dsp_r2.c index 0abf3c4f36..0abf3c4f36 100644 --- a/drivers/webp/dsp/lossless_enc_mips_dsp_r2.c +++ b/thirdparty/libwebp/dsp/lossless_enc_mips_dsp_r2.c diff --git a/drivers/webp/dsp/lossless_enc_neon.c b/thirdparty/libwebp/dsp/lossless_enc_neon.c index 4c56f2594b..4c56f2594b 100644 --- a/drivers/webp/dsp/lossless_enc_neon.c +++ b/thirdparty/libwebp/dsp/lossless_enc_neon.c diff --git a/drivers/webp/dsp/lossless_enc_sse2.c b/thirdparty/libwebp/dsp/lossless_enc_sse2.c index 7c894e7ca4..7c894e7ca4 100644 --- a/drivers/webp/dsp/lossless_enc_sse2.c +++ b/thirdparty/libwebp/dsp/lossless_enc_sse2.c diff --git a/drivers/webp/dsp/lossless_enc_sse41.c b/thirdparty/libwebp/dsp/lossless_enc_sse41.c index 3e493198db..3e493198db 100644 --- a/drivers/webp/dsp/lossless_enc_sse41.c +++ b/thirdparty/libwebp/dsp/lossless_enc_sse41.c diff --git a/drivers/webp/dsp/lossless_mips_dsp_r2.c b/thirdparty/libwebp/dsp/lossless_mips_dsp_r2.c index 90aed7f151..90aed7f151 100644 --- a/drivers/webp/dsp/lossless_mips_dsp_r2.c +++ b/thirdparty/libwebp/dsp/lossless_mips_dsp_r2.c diff --git a/drivers/webp/dsp/lossless_neon.c b/thirdparty/libwebp/dsp/lossless_neon.c index 6faccb8f97..6faccb8f97 100644 --- a/drivers/webp/dsp/lossless_neon.c +++ b/thirdparty/libwebp/dsp/lossless_neon.c diff --git a/drivers/webp/dsp/lossless_sse2.c b/thirdparty/libwebp/dsp/lossless_sse2.c index 2d016c2911..2d016c2911 100644 --- a/drivers/webp/dsp/lossless_sse2.c +++ b/thirdparty/libwebp/dsp/lossless_sse2.c diff --git a/drivers/webp/dsp/mips_macro.h b/thirdparty/libwebp/dsp/mips_macro.h index 44aba9b71d..44aba9b71d 100644 --- a/drivers/webp/dsp/mips_macro.h +++ b/thirdparty/libwebp/dsp/mips_macro.h diff --git a/drivers/webp/dsp/msa_macro.h b/thirdparty/libwebp/dsp/msa_macro.h index 5c707f476a..5c707f476a 100644 --- a/drivers/webp/dsp/msa_macro.h +++ b/thirdparty/libwebp/dsp/msa_macro.h diff --git a/drivers/webp/dsp/neon.h b/thirdparty/libwebp/dsp/neon.h index 0a06266848..0a06266848 100644 --- a/drivers/webp/dsp/neon.h +++ b/thirdparty/libwebp/dsp/neon.h diff --git a/drivers/webp/dsp/rescaler.c b/thirdparty/libwebp/dsp/rescaler.c index bc743d5dc5..bc743d5dc5 100644 --- a/drivers/webp/dsp/rescaler.c +++ b/thirdparty/libwebp/dsp/rescaler.c diff --git a/drivers/webp/dsp/rescaler_mips32.c b/thirdparty/libwebp/dsp/rescaler_mips32.c index ddaa391336..ddaa391336 100644 --- a/drivers/webp/dsp/rescaler_mips32.c +++ b/thirdparty/libwebp/dsp/rescaler_mips32.c diff --git a/drivers/webp/dsp/rescaler_mips_dsp_r2.c b/thirdparty/libwebp/dsp/rescaler_mips_dsp_r2.c index b457d0a30a..b457d0a30a 100644 --- a/drivers/webp/dsp/rescaler_mips_dsp_r2.c +++ b/thirdparty/libwebp/dsp/rescaler_mips_dsp_r2.c diff --git a/drivers/webp/dsp/rescaler_neon.c b/thirdparty/libwebp/dsp/rescaler_neon.c index 16fd450ea3..16fd450ea3 100644 --- a/drivers/webp/dsp/rescaler_neon.c +++ b/thirdparty/libwebp/dsp/rescaler_neon.c diff --git a/drivers/webp/dsp/rescaler_sse2.c b/thirdparty/libwebp/dsp/rescaler_sse2.c index 5b9702817c..5b9702817c 100644 --- a/drivers/webp/dsp/rescaler_sse2.c +++ b/thirdparty/libwebp/dsp/rescaler_sse2.c diff --git a/drivers/webp/dsp/upsampling.c b/thirdparty/libwebp/dsp/upsampling.c index 651274fcee..651274fcee 100644 --- a/drivers/webp/dsp/upsampling.c +++ b/thirdparty/libwebp/dsp/upsampling.c diff --git a/drivers/webp/dsp/upsampling_mips_dsp_r2.c b/thirdparty/libwebp/dsp/upsampling_mips_dsp_r2.c index ed2eb74825..ed2eb74825 100644 --- a/drivers/webp/dsp/upsampling_mips_dsp_r2.c +++ b/thirdparty/libwebp/dsp/upsampling_mips_dsp_r2.c diff --git a/drivers/webp/dsp/upsampling_neon.c b/thirdparty/libwebp/dsp/upsampling_neon.c index 2b0c99bddb..2b0c99bddb 100644 --- a/drivers/webp/dsp/upsampling_neon.c +++ b/thirdparty/libwebp/dsp/upsampling_neon.c diff --git a/drivers/webp/dsp/upsampling_sse2.c b/thirdparty/libwebp/dsp/upsampling_sse2.c index b5b668900f..b5b668900f 100644 --- a/drivers/webp/dsp/upsampling_sse2.c +++ b/thirdparty/libwebp/dsp/upsampling_sse2.c diff --git a/drivers/webp/dsp/yuv.c b/thirdparty/libwebp/dsp/yuv.c index f50a253168..f50a253168 100644 --- a/drivers/webp/dsp/yuv.c +++ b/thirdparty/libwebp/dsp/yuv.c diff --git a/drivers/webp/dsp/yuv.h b/thirdparty/libwebp/dsp/yuv.h index 01c40fcb84..01c40fcb84 100644 --- a/drivers/webp/dsp/yuv.h +++ b/thirdparty/libwebp/dsp/yuv.h diff --git a/drivers/webp/dsp/yuv_mips32.c b/thirdparty/libwebp/dsp/yuv_mips32.c index e61aac571f..e61aac571f 100644 --- a/drivers/webp/dsp/yuv_mips32.c +++ b/thirdparty/libwebp/dsp/yuv_mips32.c diff --git a/drivers/webp/dsp/yuv_mips_dsp_r2.c b/thirdparty/libwebp/dsp/yuv_mips_dsp_r2.c index 1720d4190f..1720d4190f 100644 --- a/drivers/webp/dsp/yuv_mips_dsp_r2.c +++ b/thirdparty/libwebp/dsp/yuv_mips_dsp_r2.c diff --git a/drivers/webp/dsp/yuv_sse2.c b/thirdparty/libwebp/dsp/yuv_sse2.c index e19bddff6c..e19bddff6c 100644 --- a/drivers/webp/dsp/yuv_sse2.c +++ b/thirdparty/libwebp/dsp/yuv_sse2.c diff --git a/drivers/webp/dsp/yuv_tables_sse2.h b/thirdparty/libwebp/dsp/yuv_tables_sse2.h index 2b0f057518..2b0f057518 100644 --- a/drivers/webp/dsp/yuv_tables_sse2.h +++ b/thirdparty/libwebp/dsp/yuv_tables_sse2.h diff --git a/thirdparty/libwebp/enc/alpha.c b/thirdparty/libwebp/enc/alpha.c new file mode 100644 index 0000000000..03e3ad07f5 --- /dev/null +++ b/thirdparty/libwebp/enc/alpha.c @@ -0,0 +1,433 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha-plane compression. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include <assert.h> +#include <stdlib.h> + +#include "./vp8enci.h" +#include "../dsp/dsp.h" +#include "../utils/filters.h" +#include "../utils/quant_levels.h" +#include "../utils/utils.h" +#include "../webp/format_constants.h" + +// ----------------------------------------------------------------------------- +// Encodes the given alpha data via specified compression method 'method'. +// The pre-processing (quantization) is performed if 'quality' is less than 100. +// For such cases, the encoding is lossy. The valid range is [0, 100] for +// 'quality' and [0, 1] for 'method': +// 'method = 0' - No compression; +// 'method = 1' - Use lossless coder on the alpha plane only +// 'filter' values [0, 4] correspond to prediction modes none, horizontal, +// vertical & gradient filters. The prediction mode 4 will try all the +// prediction modes 0 to 3 and pick the best one. +// 'effort_level': specifies how much effort must be spent to try and reduce +// the compressed output size. In range 0 (quick) to 6 (slow). +// +// 'output' corresponds to the buffer containing compressed alpha data. +// This buffer is allocated by this method and caller should call +// WebPSafeFree(*output) when done. +// 'output_size' corresponds to size of this compressed alpha buffer. +// +// Returns 1 on successfully encoding the alpha and +// 0 if either: +// invalid quality or method, or +// memory allocation for the compressed data fails. + +#include "../enc/vp8li.h" + +static int EncodeLossless(const uint8_t* const data, int width, int height, + int effort_level, // in [0..6] range + VP8LBitWriter* const bw, + WebPAuxStats* const stats) { + int ok = 0; + WebPConfig config; + WebPPicture picture; + + WebPPictureInit(&picture); + picture.width = width; + picture.height = height; + picture.use_argb = 1; + picture.stats = stats; + if (!WebPPictureAlloc(&picture)) return 0; + + // Transfer the alpha values to the green channel. + WebPDispatchAlphaToGreen(data, width, picture.width, picture.height, + picture.argb, picture.argb_stride); + + WebPConfigInit(&config); + config.lossless = 1; + // Enable exact, or it would alter RGB values of transparent alpha, which is + // normally OK but not here since we are not encoding the input image but an + // internal encoding-related image containing necessary exact information in + // RGB channels. + config.exact = 1; + config.method = effort_level; // impact is very small + // Set a low default quality for encoding alpha. Ensure that Alpha quality at + // lower methods (3 and below) is less than the threshold for triggering + // costly 'BackwardReferencesTraceBackwards'. + config.quality = 8.f * effort_level; + assert(config.quality >= 0 && config.quality <= 100.f); + + // TODO(urvang): Temporary fix to avoid generating images that trigger + // a decoder bug related to alpha with color cache. + // See: https://code.google.com/p/webp/issues/detail?id=239 + // Need to re-enable this later. + ok = (VP8LEncodeStream(&config, &picture, bw, 0 /*use_cache*/) == VP8_ENC_OK); + WebPPictureFree(&picture); + ok = ok && !bw->error_; + if (!ok) { + VP8LBitWriterWipeOut(bw); + return 0; + } + return 1; +} + +// ----------------------------------------------------------------------------- + +// Small struct to hold the result of a filter mode compression attempt. +typedef struct { + size_t score; + VP8BitWriter bw; + WebPAuxStats stats; +} FilterTrial; + +// This function always returns an initialized 'bw' object, even upon error. +static int EncodeAlphaInternal(const uint8_t* const data, int width, int height, + int method, int filter, int reduce_levels, + int effort_level, // in [0..6] range + uint8_t* const tmp_alpha, + FilterTrial* result) { + int ok = 0; + const uint8_t* alpha_src; + WebPFilterFunc filter_func; + uint8_t header; + const size_t data_size = width * height; + const uint8_t* output = NULL; + size_t output_size = 0; + VP8LBitWriter tmp_bw; + + assert((uint64_t)data_size == (uint64_t)width * height); // as per spec + assert(filter >= 0 && filter < WEBP_FILTER_LAST); + assert(method >= ALPHA_NO_COMPRESSION); + assert(method <= ALPHA_LOSSLESS_COMPRESSION); + assert(sizeof(header) == ALPHA_HEADER_LEN); + + filter_func = WebPFilters[filter]; + if (filter_func != NULL) { + filter_func(data, width, height, width, tmp_alpha); + alpha_src = tmp_alpha; + } else { + alpha_src = data; + } + + if (method != ALPHA_NO_COMPRESSION) { + ok = VP8LBitWriterInit(&tmp_bw, data_size >> 3); + ok = ok && EncodeLossless(alpha_src, width, height, effort_level, + &tmp_bw, &result->stats); + if (ok) { + output = VP8LBitWriterFinish(&tmp_bw); + output_size = VP8LBitWriterNumBytes(&tmp_bw); + if (output_size > data_size) { + // compressed size is larger than source! Revert to uncompressed mode. + method = ALPHA_NO_COMPRESSION; + VP8LBitWriterWipeOut(&tmp_bw); + } + } else { + VP8LBitWriterWipeOut(&tmp_bw); + return 0; + } + } + + if (method == ALPHA_NO_COMPRESSION) { + output = alpha_src; + output_size = data_size; + ok = 1; + } + + // Emit final result. + header = method | (filter << 2); + if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4; + + VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size); + ok = ok && VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN); + ok = ok && VP8BitWriterAppend(&result->bw, output, output_size); + + if (method != ALPHA_NO_COMPRESSION) { + VP8LBitWriterWipeOut(&tmp_bw); + } + ok = ok && !result->bw.error_; + result->score = VP8BitWriterSize(&result->bw); + return ok; +} + +// ----------------------------------------------------------------------------- + +static int GetNumColors(const uint8_t* data, int width, int height, + int stride) { + int j; + int colors = 0; + uint8_t color[256] = { 0 }; + + for (j = 0; j < height; ++j) { + int i; + const uint8_t* const p = data + j * stride; + for (i = 0; i < width; ++i) { + color[p[i]] = 1; + } + } + for (j = 0; j < 256; ++j) { + if (color[j] > 0) ++colors; + } + return colors; +} + +#define FILTER_TRY_NONE (1 << WEBP_FILTER_NONE) +#define FILTER_TRY_ALL ((1 << WEBP_FILTER_LAST) - 1) + +// Given the input 'filter' option, return an OR'd bit-set of filters to try. +static uint32_t GetFilterMap(const uint8_t* alpha, int width, int height, + int filter, int effort_level) { + uint32_t bit_map = 0U; + if (filter == WEBP_FILTER_FAST) { + // Quick estimate of the best candidate. + int try_filter_none = (effort_level > 3); + const int kMinColorsForFilterNone = 16; + const int kMaxColorsForFilterNone = 192; + const int num_colors = GetNumColors(alpha, width, height, width); + // For low number of colors, NONE yields better compression. + filter = (num_colors <= kMinColorsForFilterNone) + ? WEBP_FILTER_NONE + : WebPEstimateBestFilter(alpha, width, height, width); + bit_map |= 1 << filter; + // For large number of colors, try FILTER_NONE in addition to the best + // filter as well. + if (try_filter_none || num_colors > kMaxColorsForFilterNone) { + bit_map |= FILTER_TRY_NONE; + } + } else if (filter == WEBP_FILTER_NONE) { + bit_map = FILTER_TRY_NONE; + } else { // WEBP_FILTER_BEST -> try all + bit_map = FILTER_TRY_ALL; + } + return bit_map; +} + +static void InitFilterTrial(FilterTrial* const score) { + score->score = (size_t)~0U; + VP8BitWriterInit(&score->bw, 0); +} + +static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height, + size_t data_size, int method, int filter, + int reduce_levels, int effort_level, + uint8_t** const output, + size_t* const output_size, + WebPAuxStats* const stats) { + int ok = 1; + FilterTrial best; + uint32_t try_map = + GetFilterMap(alpha, width, height, filter, effort_level); + InitFilterTrial(&best); + + if (try_map != FILTER_TRY_NONE) { + uint8_t* filtered_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size); + if (filtered_alpha == NULL) return 0; + + for (filter = WEBP_FILTER_NONE; ok && try_map; ++filter, try_map >>= 1) { + if (try_map & 1) { + FilterTrial trial; + ok = EncodeAlphaInternal(alpha, width, height, method, filter, + reduce_levels, effort_level, filtered_alpha, + &trial); + if (ok && trial.score < best.score) { + VP8BitWriterWipeOut(&best.bw); + best = trial; + } else { + VP8BitWriterWipeOut(&trial.bw); + } + } + } + WebPSafeFree(filtered_alpha); + } else { + ok = EncodeAlphaInternal(alpha, width, height, method, WEBP_FILTER_NONE, + reduce_levels, effort_level, NULL, &best); + } + if (ok) { + if (stats != NULL) { + stats->lossless_features = best.stats.lossless_features; + stats->histogram_bits = best.stats.histogram_bits; + stats->transform_bits = best.stats.transform_bits; + stats->cache_bits = best.stats.cache_bits; + stats->palette_size = best.stats.palette_size; + stats->lossless_size = best.stats.lossless_size; + stats->lossless_hdr_size = best.stats.lossless_hdr_size; + stats->lossless_data_size = best.stats.lossless_data_size; + } + *output_size = VP8BitWriterSize(&best.bw); + *output = VP8BitWriterBuf(&best.bw); + } else { + VP8BitWriterWipeOut(&best.bw); + } + return ok; +} + +static int EncodeAlpha(VP8Encoder* const enc, + int quality, int method, int filter, + int effort_level, + uint8_t** const output, size_t* const output_size) { + const WebPPicture* const pic = enc->pic_; + const int width = pic->width; + const int height = pic->height; + + uint8_t* quant_alpha = NULL; + const size_t data_size = width * height; + uint64_t sse = 0; + int ok = 1; + const int reduce_levels = (quality < 100); + + // quick sanity checks + assert((uint64_t)data_size == (uint64_t)width * height); // as per spec + assert(enc != NULL && pic != NULL && pic->a != NULL); + assert(output != NULL && output_size != NULL); + assert(width > 0 && height > 0); + assert(pic->a_stride >= width); + assert(filter >= WEBP_FILTER_NONE && filter <= WEBP_FILTER_FAST); + + if (quality < 0 || quality > 100) { + return 0; + } + + if (method < ALPHA_NO_COMPRESSION || method > ALPHA_LOSSLESS_COMPRESSION) { + return 0; + } + + if (method == ALPHA_NO_COMPRESSION) { + // Don't filter, as filtering will make no impact on compressed size. + filter = WEBP_FILTER_NONE; + } + + quant_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size); + if (quant_alpha == NULL) { + return 0; + } + + // Extract alpha data (width x height) from raw_data (stride x height). + WebPCopyPlane(pic->a, pic->a_stride, quant_alpha, width, width, height); + + if (reduce_levels) { // No Quantization required for 'quality = 100'. + // 16 alpha levels gives quite a low MSE w.r.t original alpha plane hence + // mapped to moderate quality 70. Hence Quality:[0, 70] -> Levels:[2, 16] + // and Quality:]70, 100] -> Levels:]16, 256]. + const int alpha_levels = (quality <= 70) ? (2 + quality / 5) + : (16 + (quality - 70) * 8); + ok = QuantizeLevels(quant_alpha, width, height, alpha_levels, &sse); + } + + if (ok) { + VP8FiltersInit(); + ok = ApplyFiltersAndEncode(quant_alpha, width, height, data_size, method, + filter, reduce_levels, effort_level, output, + output_size, pic->stats); + if (pic->stats != NULL) { // need stats? + pic->stats->coded_size += (int)(*output_size); + enc->sse_[3] = sse; + } + } + + WebPSafeFree(quant_alpha); + return ok; +} + +//------------------------------------------------------------------------------ +// Main calls + +static int CompressAlphaJob(VP8Encoder* const enc, void* dummy) { + const WebPConfig* config = enc->config_; + uint8_t* alpha_data = NULL; + size_t alpha_size = 0; + const int effort_level = config->method; // maps to [0..6] + const WEBP_FILTER_TYPE filter = + (config->alpha_filtering == 0) ? WEBP_FILTER_NONE : + (config->alpha_filtering == 1) ? WEBP_FILTER_FAST : + WEBP_FILTER_BEST; + if (!EncodeAlpha(enc, config->alpha_quality, config->alpha_compression, + filter, effort_level, &alpha_data, &alpha_size)) { + return 0; + } + if (alpha_size != (uint32_t)alpha_size) { // Sanity check. + WebPSafeFree(alpha_data); + return 0; + } + enc->alpha_data_size_ = (uint32_t)alpha_size; + enc->alpha_data_ = alpha_data; + (void)dummy; + return 1; +} + +void VP8EncInitAlpha(VP8Encoder* const enc) { + WebPInitAlphaProcessing(); + enc->has_alpha_ = WebPPictureHasTransparency(enc->pic_); + enc->alpha_data_ = NULL; + enc->alpha_data_size_ = 0; + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + WebPGetWorkerInterface()->Init(worker); + worker->data1 = enc; + worker->data2 = NULL; + worker->hook = (WebPWorkerHook)CompressAlphaJob; + } +} + +int VP8EncStartAlpha(VP8Encoder* const enc) { + if (enc->has_alpha_) { + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + // Makes sure worker is good to go. + if (!WebPGetWorkerInterface()->Reset(worker)) { + return 0; + } + WebPGetWorkerInterface()->Launch(worker); + return 1; + } else { + return CompressAlphaJob(enc, NULL); // just do the job right away + } + } + return 1; +} + +int VP8EncFinishAlpha(VP8Encoder* const enc) { + if (enc->has_alpha_) { + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + if (!WebPGetWorkerInterface()->Sync(worker)) return 0; // error + } + } + return WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); +} + +int VP8EncDeleteAlpha(VP8Encoder* const enc) { + int ok = 1; + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + // finish anything left in flight + ok = WebPGetWorkerInterface()->Sync(worker); + // still need to end the worker, even if !ok + WebPGetWorkerInterface()->End(worker); + } + WebPSafeFree(enc->alpha_data_); + enc->alpha_data_ = NULL; + enc->alpha_data_size_ = 0; + enc->has_alpha_ = 0; + return ok; +} diff --git a/drivers/webp/enc/analysis.c b/thirdparty/libwebp/enc/analysis.c index b55128fd48..b55128fd48 100644 --- a/drivers/webp/enc/analysis.c +++ b/thirdparty/libwebp/enc/analysis.c diff --git a/drivers/webp/enc/backward_references.c b/thirdparty/libwebp/enc/backward_references.c index 136a24a8c3..136a24a8c3 100644 --- a/drivers/webp/enc/backward_references.c +++ b/thirdparty/libwebp/enc/backward_references.c diff --git a/thirdparty/libwebp/enc/backward_references.h b/thirdparty/libwebp/enc/backward_references.h new file mode 100644 index 0000000000..0cadb11e11 --- /dev/null +++ b/thirdparty/libwebp/enc/backward_references.h @@ -0,0 +1,206 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// + +#ifndef WEBP_ENC_BACKWARD_REFERENCES_H_ +#define WEBP_ENC_BACKWARD_REFERENCES_H_ + +#include <assert.h> +#include <stdlib.h> +#include "../webp/types.h" +#include "../webp/format_constants.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// The maximum allowed limit is 11. +#define MAX_COLOR_CACHE_BITS 10 + +// ----------------------------------------------------------------------------- +// PixOrCopy + +enum Mode { + kLiteral, + kCacheIdx, + kCopy, + kNone +}; + +typedef struct { + // mode as uint8_t to make the memory layout to be exactly 8 bytes. + uint8_t mode; + uint16_t len; + uint32_t argb_or_distance; +} PixOrCopy; + +static WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance, + uint16_t len) { + PixOrCopy retval; + retval.mode = kCopy; + retval.argb_or_distance = distance; + retval.len = len; + return retval; +} + +static WEBP_INLINE PixOrCopy PixOrCopyCreateCacheIdx(int idx) { + PixOrCopy retval; + assert(idx >= 0); + assert(idx < (1 << MAX_COLOR_CACHE_BITS)); + retval.mode = kCacheIdx; + retval.argb_or_distance = idx; + retval.len = 1; + return retval; +} + +static WEBP_INLINE PixOrCopy PixOrCopyCreateLiteral(uint32_t argb) { + PixOrCopy retval; + retval.mode = kLiteral; + retval.argb_or_distance = argb; + retval.len = 1; + return retval; +} + +static WEBP_INLINE int PixOrCopyIsLiteral(const PixOrCopy* const p) { + return (p->mode == kLiteral); +} + +static WEBP_INLINE int PixOrCopyIsCacheIdx(const PixOrCopy* const p) { + return (p->mode == kCacheIdx); +} + +static WEBP_INLINE int PixOrCopyIsCopy(const PixOrCopy* const p) { + return (p->mode == kCopy); +} + +static WEBP_INLINE uint32_t PixOrCopyLiteral(const PixOrCopy* const p, + int component) { + assert(p->mode == kLiteral); + return (p->argb_or_distance >> (component * 8)) & 0xff; +} + +static WEBP_INLINE uint32_t PixOrCopyLength(const PixOrCopy* const p) { + return p->len; +} + +static WEBP_INLINE uint32_t PixOrCopyArgb(const PixOrCopy* const p) { + assert(p->mode == kLiteral); + return p->argb_or_distance; +} + +static WEBP_INLINE uint32_t PixOrCopyCacheIdx(const PixOrCopy* const p) { + assert(p->mode == kCacheIdx); + assert(p->argb_or_distance < (1U << MAX_COLOR_CACHE_BITS)); + return p->argb_or_distance; +} + +static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) { + assert(p->mode == kCopy); + return p->argb_or_distance; +} + +// ----------------------------------------------------------------------------- +// VP8LHashChain + +#define HASH_BITS 18 +#define HASH_SIZE (1 << HASH_BITS) + +typedef struct VP8LHashChain VP8LHashChain; +struct VP8LHashChain { + // The 20 most significant bits contain the offset at which the best match + // is found. These 20 bits are the limit defined by GetWindowSizeForHashChain + // (through WINDOW_SIZE = 1<<20). + // The lower 12 bits contain the length of the match. The 12 bit limit is + // defined in MaxFindCopyLength with MAX_LENGTH=4096. + uint32_t* offset_length_; + // This is the maximum size of the hash_chain that can be constructed. + // Typically this is the pixel count (width x height) for a given image. + int size_; +}; + +// Must be called first, to set size. +int VP8LHashChainInit(VP8LHashChain* const p, int size); +// Pre-compute the best matches for argb. +int VP8LHashChainFill(VP8LHashChain* const p, int quality, + const uint32_t* const argb, int xsize, int ysize); +void VP8LHashChainClear(VP8LHashChain* const p); // release memory + +// ----------------------------------------------------------------------------- +// VP8LBackwardRefs (block-based backward-references storage) + +// maximum number of reference blocks the image will be segmented into +#define MAX_REFS_BLOCK_PER_IMAGE 16 + +typedef struct PixOrCopyBlock PixOrCopyBlock; // forward declaration +typedef struct VP8LBackwardRefs VP8LBackwardRefs; + +// Container for blocks chain +struct VP8LBackwardRefs { + int block_size_; // common block-size + int error_; // set to true if some memory error occurred + PixOrCopyBlock* refs_; // list of currently used blocks + PixOrCopyBlock** tail_; // for list recycling + PixOrCopyBlock* free_blocks_; // free-list + PixOrCopyBlock* last_block_; // used for adding new refs (internal) +}; + +// Initialize the object. 'block_size' is the common block size to store +// references (typically, width * height / MAX_REFS_BLOCK_PER_IMAGE). +void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size); +// Release memory for backward references. +void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs); +// Copies the 'src' backward refs to the 'dst'. Returns 0 in case of error. +int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src, + VP8LBackwardRefs* const dst); + +// Cursor for iterating on references content +typedef struct { + // public: + PixOrCopy* cur_pos; // current position + // private: + PixOrCopyBlock* cur_block_; // current block in the refs list + const PixOrCopy* last_pos_; // sentinel for switching to next block +} VP8LRefsCursor; + +// Returns a cursor positioned at the beginning of the references list. +VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs); +// Returns true if cursor is pointing at a valid position. +static WEBP_INLINE int VP8LRefsCursorOk(const VP8LRefsCursor* const c) { + return (c->cur_pos != NULL); +} +// Move to next block of references. Internal, not to be called directly. +void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c); +// Move to next position, or NULL. Should not be called if !VP8LRefsCursorOk(). +static WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) { + assert(c != NULL); + assert(VP8LRefsCursorOk(c)); + if (++c->cur_pos == c->last_pos_) VP8LRefsCursorNextBlock(c); +} + +// ----------------------------------------------------------------------------- +// Main entry points + +// Evaluates best possible backward references for specified quality. +// The input cache_bits to 'VP8LGetBackwardReferences' sets the maximum cache +// bits to use (passing 0 implies disabling the local color cache). +// The optimal cache bits is evaluated and set for the *cache_bits parameter. +// The return value is the pointer to the best of the two backward refs viz, +// refs[0] or refs[1]. +VP8LBackwardRefs* VP8LGetBackwardReferences( + int width, int height, const uint32_t* const argb, int quality, + int low_effort, int* const cache_bits, + const VP8LHashChain* const hash_chain, VP8LBackwardRefs refs[2]); + +#ifdef __cplusplus +} +#endif + +#endif // WEBP_ENC_BACKWARD_REFERENCES_H_ diff --git a/thirdparty/libwebp/enc/config.c b/thirdparty/libwebp/enc/config.c new file mode 100644 index 0000000000..f9f7961d58 --- /dev/null +++ b/thirdparty/libwebp/enc/config.c @@ -0,0 +1,173 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Coding tools configuration +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "../webp/encode.h" + +//------------------------------------------------------------------------------ +// WebPConfig +//------------------------------------------------------------------------------ + +int WebPConfigInitInternal(WebPConfig* config, + WebPPreset preset, float quality, int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) { + return 0; // caller/system version mismatch! + } + if (config == NULL) return 0; + + config->quality = quality; + config->target_size = 0; + config->target_PSNR = 0.; + config->method = 4; + config->sns_strength = 50; + config->filter_strength = 60; // mid-filtering + config->filter_sharpness = 0; + config->filter_type = 1; // default: strong (so U/V is filtered too) + config->partitions = 0; + config->segments = 4; + config->pass = 1; + config->show_compressed = 0; + config->preprocessing = 0; + config->autofilter = 0; + config->partition_limit = 0; + config->alpha_compression = 1; + config->alpha_filtering = 1; + config->alpha_quality = 100; + config->lossless = 0; + config->exact = 0; + config->image_hint = WEBP_HINT_DEFAULT; + config->emulate_jpeg_size = 0; + config->thread_level = 0; + config->low_memory = 0; + config->near_lossless = 100; +#ifdef WEBP_EXPERIMENTAL_FEATURES + config->delta_palettization = 0; +#endif // WEBP_EXPERIMENTAL_FEATURES + + // TODO(skal): tune. + switch (preset) { + case WEBP_PRESET_PICTURE: + config->sns_strength = 80; + config->filter_sharpness = 4; + config->filter_strength = 35; + config->preprocessing &= ~2; // no dithering + break; + case WEBP_PRESET_PHOTO: + config->sns_strength = 80; + config->filter_sharpness = 3; + config->filter_strength = 30; + config->preprocessing |= 2; + break; + case WEBP_PRESET_DRAWING: + config->sns_strength = 25; + config->filter_sharpness = 6; + config->filter_strength = 10; + break; + case WEBP_PRESET_ICON: + config->sns_strength = 0; + config->filter_strength = 0; // disable filtering to retain sharpness + config->preprocessing &= ~2; // no dithering + break; + case WEBP_PRESET_TEXT: + config->sns_strength = 0; + config->filter_strength = 0; // disable filtering to retain sharpness + config->preprocessing &= ~2; // no dithering + config->segments = 2; + break; + case WEBP_PRESET_DEFAULT: + default: + break; + } + return WebPValidateConfig(config); +} + +int WebPValidateConfig(const WebPConfig* config) { + if (config == NULL) return 0; + if (config->quality < 0 || config->quality > 100) + return 0; + if (config->target_size < 0) + return 0; + if (config->target_PSNR < 0) + return 0; + if (config->method < 0 || config->method > 6) + return 0; + if (config->segments < 1 || config->segments > 4) + return 0; + if (config->sns_strength < 0 || config->sns_strength > 100) + return 0; + if (config->filter_strength < 0 || config->filter_strength > 100) + return 0; + if (config->filter_sharpness < 0 || config->filter_sharpness > 7) + return 0; + if (config->filter_type < 0 || config->filter_type > 1) + return 0; + if (config->autofilter < 0 || config->autofilter > 1) + return 0; + if (config->pass < 1 || config->pass > 10) + return 0; + if (config->show_compressed < 0 || config->show_compressed > 1) + return 0; + if (config->preprocessing < 0 || config->preprocessing > 7) + return 0; + if (config->partitions < 0 || config->partitions > 3) + return 0; + if (config->partition_limit < 0 || config->partition_limit > 100) + return 0; + if (config->alpha_compression < 0) + return 0; + if (config->alpha_filtering < 0) + return 0; + if (config->alpha_quality < 0 || config->alpha_quality > 100) + return 0; + if (config->lossless < 0 || config->lossless > 1) + return 0; + if (config->near_lossless < 0 || config->near_lossless > 100) + return 0; + if (config->image_hint >= WEBP_HINT_LAST) + return 0; + if (config->emulate_jpeg_size < 0 || config->emulate_jpeg_size > 1) + return 0; + if (config->thread_level < 0 || config->thread_level > 1) + return 0; + if (config->low_memory < 0 || config->low_memory > 1) + return 0; + if (config->exact < 0 || config->exact > 1) + return 0; +#ifdef WEBP_EXPERIMENTAL_FEATURES + if (config->delta_palettization < 0 || config->delta_palettization > 1) + return 0; +#endif // WEBP_EXPERIMENTAL_FEATURES + return 1; +} + +//------------------------------------------------------------------------------ + +#define MAX_LEVEL 9 + +// Mapping between -z level and -m / -q parameter settings. +static const struct { + uint8_t method_; + uint8_t quality_; +} kLosslessPresets[MAX_LEVEL + 1] = { + { 0, 0 }, { 1, 20 }, { 2, 25 }, { 3, 30 }, { 3, 50 }, + { 4, 50 }, { 4, 75 }, { 4, 90 }, { 5, 90 }, { 6, 100 } +}; + +int WebPConfigLosslessPreset(WebPConfig* config, int level) { + if (config == NULL || level < 0 || level > MAX_LEVEL) return 0; + config->lossless = 1; + config->method = kLosslessPresets[level].method_; + config->quality = kLosslessPresets[level].quality_; + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/drivers/webp/enc/cost.c b/thirdparty/libwebp/enc/cost.c index ae7fe01388..ae7fe01388 100644 --- a/drivers/webp/enc/cost.c +++ b/thirdparty/libwebp/enc/cost.c diff --git a/drivers/webp/enc/cost.h b/thirdparty/libwebp/enc/cost.h index 20960d6d74..20960d6d74 100644 --- a/drivers/webp/enc/cost.h +++ b/thirdparty/libwebp/enc/cost.h diff --git a/thirdparty/libwebp/enc/delta_palettization.c b/thirdparty/libwebp/enc/delta_palettization.c new file mode 100644 index 0000000000..062e588d79 --- /dev/null +++ b/thirdparty/libwebp/enc/delta_palettization.c @@ -0,0 +1,455 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Mislav Bradac (mislavm@google.com) +// + +#include "./delta_palettization.h" + +#ifdef WEBP_EXPERIMENTAL_FEATURES +#include "../webp/types.h" +#include "../dsp/lossless.h" + +#define MK_COL(r, g, b) (((r) << 16) + ((g) << 8) + (b)) + +// Format allows palette up to 256 entries, but more palette entries produce +// bigger entropy. In the future it will probably be useful to add more entries +// that are far from the origin of the palette or choose remaining entries +// dynamically. +#define DELTA_PALETTE_SIZE 226 + +// Palette used for delta_palettization. Entries are roughly sorted by distance +// of their signed equivalents from the origin. +static const uint32_t kDeltaPalette[DELTA_PALETTE_SIZE] = { + MK_COL(0u, 0u, 0u), + MK_COL(255u, 255u, 255u), + MK_COL(1u, 1u, 1u), + MK_COL(254u, 254u, 254u), + MK_COL(2u, 2u, 2u), + MK_COL(4u, 4u, 4u), + MK_COL(252u, 252u, 252u), + MK_COL(250u, 0u, 0u), + MK_COL(0u, 250u, 0u), + MK_COL(0u, 0u, 250u), + MK_COL(6u, 0u, 0u), + MK_COL(0u, 6u, 0u), + MK_COL(0u, 0u, 6u), + MK_COL(0u, 0u, 248u), + MK_COL(0u, 0u, 8u), + MK_COL(0u, 248u, 0u), + MK_COL(0u, 248u, 248u), + MK_COL(0u, 248u, 8u), + MK_COL(0u, 8u, 0u), + MK_COL(0u, 8u, 248u), + MK_COL(0u, 8u, 8u), + MK_COL(8u, 8u, 8u), + MK_COL(248u, 0u, 0u), + MK_COL(248u, 0u, 248u), + MK_COL(248u, 0u, 8u), + MK_COL(248u, 248u, 0u), + MK_COL(248u, 8u, 0u), + MK_COL(8u, 0u, 0u), + MK_COL(8u, 0u, 248u), + MK_COL(8u, 0u, 8u), + MK_COL(8u, 248u, 0u), + MK_COL(8u, 8u, 0u), + MK_COL(23u, 23u, 23u), + MK_COL(13u, 13u, 13u), + MK_COL(232u, 232u, 232u), + MK_COL(244u, 244u, 244u), + MK_COL(245u, 245u, 250u), + MK_COL(50u, 50u, 50u), + MK_COL(204u, 204u, 204u), + MK_COL(236u, 236u, 236u), + MK_COL(16u, 16u, 16u), + MK_COL(240u, 16u, 16u), + MK_COL(16u, 240u, 16u), + MK_COL(240u, 240u, 16u), + MK_COL(16u, 16u, 240u), + MK_COL(240u, 16u, 240u), + MK_COL(16u, 240u, 240u), + MK_COL(240u, 240u, 240u), + MK_COL(0u, 0u, 232u), + MK_COL(0u, 232u, 0u), + MK_COL(232u, 0u, 0u), + MK_COL(0u, 0u, 24u), + MK_COL(0u, 24u, 0u), + MK_COL(24u, 0u, 0u), + MK_COL(32u, 32u, 32u), + MK_COL(224u, 32u, 32u), + MK_COL(32u, 224u, 32u), + MK_COL(224u, 224u, 32u), + MK_COL(32u, 32u, 224u), + MK_COL(224u, 32u, 224u), + MK_COL(32u, 224u, 224u), + MK_COL(224u, 224u, 224u), + MK_COL(0u, 0u, 176u), + MK_COL(0u, 0u, 80u), + MK_COL(0u, 176u, 0u), + MK_COL(0u, 176u, 176u), + MK_COL(0u, 176u, 80u), + MK_COL(0u, 80u, 0u), + MK_COL(0u, 80u, 176u), + MK_COL(0u, 80u, 80u), + MK_COL(176u, 0u, 0u), + MK_COL(176u, 0u, 176u), + MK_COL(176u, 0u, 80u), + MK_COL(176u, 176u, 0u), + MK_COL(176u, 80u, 0u), + MK_COL(80u, 0u, 0u), + MK_COL(80u, 0u, 176u), + MK_COL(80u, 0u, 80u), + MK_COL(80u, 176u, 0u), + MK_COL(80u, 80u, 0u), + MK_COL(0u, 0u, 152u), + MK_COL(0u, 0u, 104u), + MK_COL(0u, 152u, 0u), + MK_COL(0u, 152u, 152u), + MK_COL(0u, 152u, 104u), + MK_COL(0u, 104u, 0u), + MK_COL(0u, 104u, 152u), + MK_COL(0u, 104u, 104u), + MK_COL(152u, 0u, 0u), + MK_COL(152u, 0u, 152u), + MK_COL(152u, 0u, 104u), + MK_COL(152u, 152u, 0u), + MK_COL(152u, 104u, 0u), + MK_COL(104u, 0u, 0u), + MK_COL(104u, 0u, 152u), + MK_COL(104u, 0u, 104u), + MK_COL(104u, 152u, 0u), + MK_COL(104u, 104u, 0u), + MK_COL(216u, 216u, 216u), + MK_COL(216u, 216u, 40u), + MK_COL(216u, 216u, 176u), + MK_COL(216u, 216u, 80u), + MK_COL(216u, 40u, 216u), + MK_COL(216u, 40u, 40u), + MK_COL(216u, 40u, 176u), + MK_COL(216u, 40u, 80u), + MK_COL(216u, 176u, 216u), + MK_COL(216u, 176u, 40u), + MK_COL(216u, 176u, 176u), + MK_COL(216u, 176u, 80u), + MK_COL(216u, 80u, 216u), + MK_COL(216u, 80u, 40u), + MK_COL(216u, 80u, 176u), + MK_COL(216u, 80u, 80u), + MK_COL(40u, 216u, 216u), + MK_COL(40u, 216u, 40u), + MK_COL(40u, 216u, 176u), + MK_COL(40u, 216u, 80u), + MK_COL(40u, 40u, 216u), + MK_COL(40u, 40u, 40u), + MK_COL(40u, 40u, 176u), + MK_COL(40u, 40u, 80u), + MK_COL(40u, 176u, 216u), + MK_COL(40u, 176u, 40u), + MK_COL(40u, 176u, 176u), + MK_COL(40u, 176u, 80u), + MK_COL(40u, 80u, 216u), + MK_COL(40u, 80u, 40u), + MK_COL(40u, 80u, 176u), + MK_COL(40u, 80u, 80u), + MK_COL(80u, 216u, 216u), + MK_COL(80u, 216u, 40u), + MK_COL(80u, 216u, 176u), + MK_COL(80u, 216u, 80u), + MK_COL(80u, 40u, 216u), + MK_COL(80u, 40u, 40u), + MK_COL(80u, 40u, 176u), + MK_COL(80u, 40u, 80u), + MK_COL(80u, 176u, 216u), + MK_COL(80u, 176u, 40u), + MK_COL(80u, 176u, 176u), + MK_COL(80u, 176u, 80u), + MK_COL(80u, 80u, 216u), + MK_COL(80u, 80u, 40u), + MK_COL(80u, 80u, 176u), + MK_COL(80u, 80u, 80u), + MK_COL(0u, 0u, 192u), + MK_COL(0u, 0u, 64u), + MK_COL(0u, 0u, 128u), + MK_COL(0u, 192u, 0u), + MK_COL(0u, 192u, 192u), + MK_COL(0u, 192u, 64u), + MK_COL(0u, 192u, 128u), + MK_COL(0u, 64u, 0u), + MK_COL(0u, 64u, 192u), + MK_COL(0u, 64u, 64u), + MK_COL(0u, 64u, 128u), + MK_COL(0u, 128u, 0u), + MK_COL(0u, 128u, 192u), + MK_COL(0u, 128u, 64u), + MK_COL(0u, 128u, 128u), + MK_COL(176u, 216u, 216u), + MK_COL(176u, 216u, 40u), + MK_COL(176u, 216u, 176u), + MK_COL(176u, 216u, 80u), + MK_COL(176u, 40u, 216u), + MK_COL(176u, 40u, 40u), + MK_COL(176u, 40u, 176u), + MK_COL(176u, 40u, 80u), + MK_COL(176u, 176u, 216u), + MK_COL(176u, 176u, 40u), + MK_COL(176u, 176u, 176u), + MK_COL(176u, 176u, 80u), + MK_COL(176u, 80u, 216u), + MK_COL(176u, 80u, 40u), + MK_COL(176u, 80u, 176u), + MK_COL(176u, 80u, 80u), + MK_COL(192u, 0u, 0u), + MK_COL(192u, 0u, 192u), + MK_COL(192u, 0u, 64u), + MK_COL(192u, 0u, 128u), + MK_COL(192u, 192u, 0u), + MK_COL(192u, 192u, 192u), + MK_COL(192u, 192u, 64u), + MK_COL(192u, 192u, 128u), + MK_COL(192u, 64u, 0u), + MK_COL(192u, 64u, 192u), + MK_COL(192u, 64u, 64u), + MK_COL(192u, 64u, 128u), + MK_COL(192u, 128u, 0u), + MK_COL(192u, 128u, 192u), + MK_COL(192u, 128u, 64u), + MK_COL(192u, 128u, 128u), + MK_COL(64u, 0u, 0u), + MK_COL(64u, 0u, 192u), + MK_COL(64u, 0u, 64u), + MK_COL(64u, 0u, 128u), + MK_COL(64u, 192u, 0u), + MK_COL(64u, 192u, 192u), + MK_COL(64u, 192u, 64u), + MK_COL(64u, 192u, 128u), + MK_COL(64u, 64u, 0u), + MK_COL(64u, 64u, 192u), + MK_COL(64u, 64u, 64u), + MK_COL(64u, 64u, 128u), + MK_COL(64u, 128u, 0u), + MK_COL(64u, 128u, 192u), + MK_COL(64u, 128u, 64u), + MK_COL(64u, 128u, 128u), + MK_COL(128u, 0u, 0u), + MK_COL(128u, 0u, 192u), + MK_COL(128u, 0u, 64u), + MK_COL(128u, 0u, 128u), + MK_COL(128u, 192u, 0u), + MK_COL(128u, 192u, 192u), + MK_COL(128u, 192u, 64u), + MK_COL(128u, 192u, 128u), + MK_COL(128u, 64u, 0u), + MK_COL(128u, 64u, 192u), + MK_COL(128u, 64u, 64u), + MK_COL(128u, 64u, 128u), + MK_COL(128u, 128u, 0u), + MK_COL(128u, 128u, 192u), + MK_COL(128u, 128u, 64u), + MK_COL(128u, 128u, 128u), +}; + +#undef MK_COL + +//------------------------------------------------------------------------------ +// TODO(skal): move the functions to dsp/lossless.c when the correct +// granularity is found. For now, we'll just copy-paste some useful bits +// here instead. + +// In-place sum of each component with mod 256. +static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) { + const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u); + const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu); + *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); +} + +static WEBP_INLINE uint32_t Clip255(uint32_t a) { + if (a < 256) { + return a; + } + // return 0, when a is a negative integer. + // return 255, when a is positive. + return ~a >> 24; +} + +// Delta palettization functions. +static WEBP_INLINE int Square(int x) { + return x * x; +} + +static WEBP_INLINE uint32_t Intensity(uint32_t a) { + return + 30 * ((a >> 16) & 0xff) + + 59 * ((a >> 8) & 0xff) + + 11 * ((a >> 0) & 0xff); +} + +static uint32_t CalcDist(uint32_t predicted_value, uint32_t actual_value, + uint32_t palette_entry) { + int i; + uint32_t distance = 0; + AddPixelsEq(&predicted_value, palette_entry); + for (i = 0; i < 32; i += 8) { + const int32_t av = (actual_value >> i) & 0xff; + const int32_t pv = (predicted_value >> i) & 0xff; + distance += Square(pv - av); + } + // We sum square of intensity difference with factor 10, but because Intensity + // returns 100 times real intensity we need to multiply differences of colors + // by 1000. + distance *= 1000u; + distance += Square(Intensity(predicted_value) + - Intensity(actual_value)); + return distance; +} + +static uint32_t Predict(int x, int y, uint32_t* image) { + const uint32_t t = (y == 0) ? ARGB_BLACK : image[x]; + const uint32_t l = (x == 0) ? ARGB_BLACK : image[x - 1]; + const uint32_t p = + (((((t >> 24) & 0xff) + ((l >> 24) & 0xff)) / 2) << 24) + + (((((t >> 16) & 0xff) + ((l >> 16) & 0xff)) / 2) << 16) + + (((((t >> 8) & 0xff) + ((l >> 8) & 0xff)) / 2) << 8) + + (((((t >> 0) & 0xff) + ((l >> 0) & 0xff)) / 2) << 0); + if (x == 0 && y == 0) return ARGB_BLACK; + if (x == 0) return t; + if (y == 0) return l; + return p; +} + +static WEBP_INLINE int AddSubtractComponentFullWithCoefficient( + int a, int b, int c) { + return Clip255(a + ((b - c) >> 2)); +} + +static WEBP_INLINE uint32_t ClampedAddSubtractFullWithCoefficient( + uint32_t c0, uint32_t c1, uint32_t c2) { + const int a = AddSubtractComponentFullWithCoefficient( + c0 >> 24, c1 >> 24, c2 >> 24); + const int r = AddSubtractComponentFullWithCoefficient((c0 >> 16) & 0xff, + (c1 >> 16) & 0xff, + (c2 >> 16) & 0xff); + const int g = AddSubtractComponentFullWithCoefficient((c0 >> 8) & 0xff, + (c1 >> 8) & 0xff, + (c2 >> 8) & 0xff); + const int b = AddSubtractComponentFullWithCoefficient( + c0 & 0xff, c1 & 0xff, c2 & 0xff); + return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; +} + +//------------------------------------------------------------------------------ + +// Find palette entry with minimum error from difference of actual pixel value +// and predicted pixel value. Propagate error of pixel to its top and left pixel +// in src array. Write predicted_value + palette_entry to new_image. Return +// index of best palette entry. +static int FindBestPaletteEntry(uint32_t src, uint32_t predicted_value, + const uint32_t palette[], int palette_size) { + int i; + int idx = 0; + uint32_t best_distance = CalcDist(predicted_value, src, palette[0]); + for (i = 1; i < palette_size; ++i) { + const uint32_t distance = CalcDist(predicted_value, src, palette[i]); + if (distance < best_distance) { + best_distance = distance; + idx = i; + } + } + return idx; +} + +static void ApplyBestPaletteEntry(int x, int y, + uint32_t new_value, uint32_t palette_value, + uint32_t* src, int src_stride, + uint32_t* new_image) { + AddPixelsEq(&new_value, palette_value); + if (x > 0) { + src[x - 1] = ClampedAddSubtractFullWithCoefficient(src[x - 1], + new_value, src[x]); + } + if (y > 0) { + src[x - src_stride] = + ClampedAddSubtractFullWithCoefficient(src[x - src_stride], + new_value, src[x]); + } + new_image[x] = new_value; +} + +//------------------------------------------------------------------------------ +// Main entry point + +static WebPEncodingError ApplyDeltaPalette(uint32_t* src, uint32_t* dst, + uint32_t src_stride, + uint32_t dst_stride, + const uint32_t* palette, + int palette_size, + int width, int height, + int num_passes) { + int x, y; + WebPEncodingError err = VP8_ENC_OK; + uint32_t* new_image = (uint32_t*)WebPSafeMalloc(width, sizeof(*new_image)); + uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row)); + if (new_image == NULL || tmp_row == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + while (num_passes--) { + uint32_t* cur_src = src; + uint32_t* cur_dst = dst; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + const uint32_t predicted_value = Predict(x, y, new_image); + tmp_row[x] = FindBestPaletteEntry(cur_src[x], predicted_value, + palette, palette_size); + ApplyBestPaletteEntry(x, y, predicted_value, palette[tmp_row[x]], + cur_src, src_stride, new_image); + } + for (x = 0; x < width; ++x) { + cur_dst[x] = palette[tmp_row[x]]; + } + cur_src += src_stride; + cur_dst += dst_stride; + } + } + Error: + WebPSafeFree(new_image); + WebPSafeFree(tmp_row); + return err; +} + +// replaces enc->argb_ by a palettizable approximation of it, +// and generates optimal enc->palette_[] +WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) { + const WebPPicture* const pic = enc->pic_; + uint32_t* src = pic->argb; + uint32_t* dst = enc->argb_; + const int width = pic->width; + const int height = pic->height; + + WebPEncodingError err = VP8_ENC_OK; + memcpy(enc->palette_, kDeltaPalette, sizeof(kDeltaPalette)); + enc->palette_[DELTA_PALETTE_SIZE - 1] = src[0] - 0xff000000u; + enc->palette_size_ = DELTA_PALETTE_SIZE; + err = ApplyDeltaPalette(src, dst, pic->argb_stride, enc->current_width_, + enc->palette_, enc->palette_size_, + width, height, 2); + if (err != VP8_ENC_OK) goto Error; + + Error: + return err; +} + +#else // !WEBP_EXPERIMENTAL_FEATURES + +WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) { + (void)enc; + return VP8_ENC_ERROR_INVALID_CONFIGURATION; +} + +#endif // WEBP_EXPERIMENTAL_FEATURES diff --git a/thirdparty/libwebp/enc/delta_palettization.h b/thirdparty/libwebp/enc/delta_palettization.h new file mode 100644 index 0000000000..e41c0c5ab5 --- /dev/null +++ b/thirdparty/libwebp/enc/delta_palettization.h @@ -0,0 +1,25 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Mislav Bradac (mislavm@google.com) +// + +#ifndef WEBP_ENC_DELTA_PALETTIZATION_H_ +#define WEBP_ENC_DELTA_PALETTIZATION_H_ + +#include "../webp/encode.h" +#include "../enc/vp8li.h" + +// Replaces enc->argb_[] input by a palettizable approximation of it, +// and generates optimal enc->palette_[]. +// This function can revert enc->use_palette_ / enc->use_predict_ flag +// if delta-palettization is not producing expected saving. +WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc); + +#endif // WEBP_ENC_DELTA_PALETTIZATION_H_ diff --git a/drivers/webp/enc/filter.c b/thirdparty/libwebp/enc/filter.c index e8ea8b4ff2..e8ea8b4ff2 100644 --- a/drivers/webp/enc/filter.c +++ b/thirdparty/libwebp/enc/filter.c diff --git a/thirdparty/libwebp/enc/frame.c b/thirdparty/libwebp/enc/frame.c new file mode 100644 index 0000000000..5b7a40b9ad --- /dev/null +++ b/thirdparty/libwebp/enc/frame.c @@ -0,0 +1,850 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// frame coding and analysis +// +// Author: Skal (pascal.massimino@gmail.com) + +#include <string.h> +#include <math.h> + +#include "./cost.h" +#include "./vp8enci.h" +#include "../dsp/dsp.h" +#include "../webp/format_constants.h" // RIFF constants + +#define SEGMENT_VISU 0 +#define DEBUG_SEARCH 0 // useful to track search convergence + +//------------------------------------------------------------------------------ +// multi-pass convergence + +#define HEADER_SIZE_ESTIMATE (RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + \ + VP8_FRAME_HEADER_SIZE) +#define DQ_LIMIT 0.4 // convergence is considered reached if dq < DQ_LIMIT +// we allow 2k of extra head-room in PARTITION0 limit. +#define PARTITION0_SIZE_LIMIT ((VP8_MAX_PARTITION0_SIZE - 2048ULL) << 11) + +typedef struct { // struct for organizing convergence in either size or PSNR + int is_first; + float dq; + float q, last_q; + double value, last_value; // PSNR or size + double target; + int do_size_search; +} PassStats; + +static int InitPassStats(const VP8Encoder* const enc, PassStats* const s) { + const uint64_t target_size = (uint64_t)enc->config_->target_size; + const int do_size_search = (target_size != 0); + const float target_PSNR = enc->config_->target_PSNR; + + s->is_first = 1; + s->dq = 10.f; + s->q = s->last_q = enc->config_->quality; + s->target = do_size_search ? (double)target_size + : (target_PSNR > 0.) ? target_PSNR + : 40.; // default, just in case + s->value = s->last_value = 0.; + s->do_size_search = do_size_search; + return do_size_search; +} + +static float Clamp(float v, float min, float max) { + return (v < min) ? min : (v > max) ? max : v; +} + +static float ComputeNextQ(PassStats* const s) { + float dq; + if (s->is_first) { + dq = (s->value > s->target) ? -s->dq : s->dq; + s->is_first = 0; + } else if (s->value != s->last_value) { + const double slope = (s->target - s->value) / (s->last_value - s->value); + dq = (float)(slope * (s->last_q - s->q)); + } else { + dq = 0.; // we're done?! + } + // Limit variable to avoid large swings. + s->dq = Clamp(dq, -30.f, 30.f); + s->last_q = s->q; + s->last_value = s->value; + s->q = Clamp(s->q + s->dq, 0.f, 100.f); + return s->q; +} + +//------------------------------------------------------------------------------ +// Tables for level coding + +const uint8_t VP8Cat3[] = { 173, 148, 140 }; +const uint8_t VP8Cat4[] = { 176, 155, 140, 135 }; +const uint8_t VP8Cat5[] = { 180, 157, 141, 134, 130 }; +const uint8_t VP8Cat6[] = + { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 }; + +//------------------------------------------------------------------------------ +// Reset the statistics about: number of skips, token proba, level cost,... + +static void ResetStats(VP8Encoder* const enc) { + VP8EncProba* const proba = &enc->proba_; + VP8CalculateLevelCosts(proba); + proba->nb_skip_ = 0; +} + +//------------------------------------------------------------------------------ +// Skip decision probability + +#define SKIP_PROBA_THRESHOLD 250 // value below which using skip_proba is OK. + +static int CalcSkipProba(uint64_t nb, uint64_t total) { + return (int)(total ? (total - nb) * 255 / total : 255); +} + +// Returns the bit-cost for coding the skip probability. +static int FinalizeSkipProba(VP8Encoder* const enc) { + VP8EncProba* const proba = &enc->proba_; + const int nb_mbs = enc->mb_w_ * enc->mb_h_; + const int nb_events = proba->nb_skip_; + int size; + proba->skip_proba_ = CalcSkipProba(nb_events, nb_mbs); + proba->use_skip_proba_ = (proba->skip_proba_ < SKIP_PROBA_THRESHOLD); + size = 256; // 'use_skip_proba' bit + if (proba->use_skip_proba_) { + size += nb_events * VP8BitCost(1, proba->skip_proba_) + + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba_); + size += 8 * 256; // cost of signaling the skip_proba_ itself. + } + return size; +} + +// Collect statistics and deduce probabilities for next coding pass. +// Return the total bit-cost for coding the probability updates. +static int CalcTokenProba(int nb, int total) { + assert(nb <= total); + return nb ? (255 - nb * 255 / total) : 255; +} + +// Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability. +static int BranchCost(int nb, int total, int proba) { + return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba); +} + +static void ResetTokenStats(VP8Encoder* const enc) { + VP8EncProba* const proba = &enc->proba_; + memset(proba->stats_, 0, sizeof(proba->stats_)); +} + +static int FinalizeTokenProbas(VP8EncProba* const proba) { + int has_changed = 0; + int size = 0; + int t, b, c, p; + for (t = 0; t < NUM_TYPES; ++t) { + for (b = 0; b < NUM_BANDS; ++b) { + for (c = 0; c < NUM_CTX; ++c) { + for (p = 0; p < NUM_PROBAS; ++p) { + const proba_t stats = proba->stats_[t][b][c][p]; + const int nb = (stats >> 0) & 0xffff; + const int total = (stats >> 16) & 0xffff; + const int update_proba = VP8CoeffsUpdateProba[t][b][c][p]; + const int old_p = VP8CoeffsProba0[t][b][c][p]; + const int new_p = CalcTokenProba(nb, total); + const int old_cost = BranchCost(nb, total, old_p) + + VP8BitCost(0, update_proba); + const int new_cost = BranchCost(nb, total, new_p) + + VP8BitCost(1, update_proba) + + 8 * 256; + const int use_new_p = (old_cost > new_cost); + size += VP8BitCost(use_new_p, update_proba); + if (use_new_p) { // only use proba that seem meaningful enough. + proba->coeffs_[t][b][c][p] = new_p; + has_changed |= (new_p != old_p); + size += 8 * 256; + } else { + proba->coeffs_[t][b][c][p] = old_p; + } + } + } + } + } + proba->dirty_ = has_changed; + return size; +} + +//------------------------------------------------------------------------------ +// Finalize Segment probability based on the coding tree + +static int GetProba(int a, int b) { + const int total = a + b; + return (total == 0) ? 255 // that's the default probability. + : (255 * a + total / 2) / total; // rounded proba +} + +static void SetSegmentProbas(VP8Encoder* const enc) { + int p[NUM_MB_SEGMENTS] = { 0 }; + int n; + + for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { + const VP8MBInfo* const mb = &enc->mb_info_[n]; + p[mb->segment_]++; + } + if (enc->pic_->stats != NULL) { + for (n = 0; n < NUM_MB_SEGMENTS; ++n) { + enc->pic_->stats->segment_size[n] = p[n]; + } + } + if (enc->segment_hdr_.num_segments_ > 1) { + uint8_t* const probas = enc->proba_.segments_; + probas[0] = GetProba(p[0] + p[1], p[2] + p[3]); + probas[1] = GetProba(p[0], p[1]); + probas[2] = GetProba(p[2], p[3]); + + enc->segment_hdr_.update_map_ = + (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); + enc->segment_hdr_.size_ = + p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) + + p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) + + p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) + + p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2])); + } else { + enc->segment_hdr_.update_map_ = 0; + enc->segment_hdr_.size_ = 0; + } +} + +//------------------------------------------------------------------------------ +// Coefficient coding + +static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) { + int n = res->first; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + const uint8_t* p = res->prob[n][ctx]; + if (!VP8PutBit(bw, res->last >= 0, p[0])) { + return 0; + } + + while (n < 16) { + const int c = res->coeffs[n++]; + const int sign = c < 0; + int v = sign ? -c : c; + if (!VP8PutBit(bw, v != 0, p[1])) { + p = res->prob[VP8EncBands[n]][0]; + continue; + } + if (!VP8PutBit(bw, v > 1, p[2])) { + p = res->prob[VP8EncBands[n]][1]; + } else { + if (!VP8PutBit(bw, v > 4, p[3])) { + if (VP8PutBit(bw, v != 2, p[4])) + VP8PutBit(bw, v == 4, p[5]); + } else if (!VP8PutBit(bw, v > 10, p[6])) { + if (!VP8PutBit(bw, v > 6, p[7])) { + VP8PutBit(bw, v == 6, 159); + } else { + VP8PutBit(bw, v >= 9, 165); + VP8PutBit(bw, !(v & 1), 145); + } + } else { + int mask; + const uint8_t* tab; + if (v < 3 + (8 << 1)) { // VP8Cat3 (3b) + VP8PutBit(bw, 0, p[8]); + VP8PutBit(bw, 0, p[9]); + v -= 3 + (8 << 0); + mask = 1 << 2; + tab = VP8Cat3; + } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b) + VP8PutBit(bw, 0, p[8]); + VP8PutBit(bw, 1, p[9]); + v -= 3 + (8 << 1); + mask = 1 << 3; + tab = VP8Cat4; + } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b) + VP8PutBit(bw, 1, p[8]); + VP8PutBit(bw, 0, p[10]); + v -= 3 + (8 << 2); + mask = 1 << 4; + tab = VP8Cat5; + } else { // VP8Cat6 (11b) + VP8PutBit(bw, 1, p[8]); + VP8PutBit(bw, 1, p[10]); + v -= 3 + (8 << 3); + mask = 1 << 10; + tab = VP8Cat6; + } + while (mask) { + VP8PutBit(bw, !!(v & mask), *tab++); + mask >>= 1; + } + } + p = res->prob[VP8EncBands[n]][2]; + } + VP8PutBitUniform(bw, sign); + if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) { + return 1; // EOB + } + } + return 1; +} + +static void CodeResiduals(VP8BitWriter* const bw, VP8EncIterator* const it, + const VP8ModeScore* const rd) { + int x, y, ch; + VP8Residual res; + uint64_t pos1, pos2, pos3; + const int i16 = (it->mb_->type_ == 1); + const int segment = it->mb_->segment_; + VP8Encoder* const enc = it->enc_; + + VP8IteratorNzToBytes(it); + + pos1 = VP8BitWriterPos(bw); + if (i16) { + VP8InitResidual(0, 1, enc, &res); + VP8SetResidualCoeffs(rd->y_dc_levels, &res); + it->top_nz_[8] = it->left_nz_[8] = + PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res); + VP8InitResidual(1, 0, enc, &res); + } else { + VP8InitResidual(0, 3, enc, &res); + } + + // luma-AC + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); + it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res); + } + } + pos2 = VP8BitWriterPos(bw); + + // U/V + VP8InitResidual(0, 2, enc, &res); + for (ch = 0; ch <= 2; ch += 2) { + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x) { + const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; + VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); + it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = + PutCoeffs(bw, ctx, &res); + } + } + } + pos3 = VP8BitWriterPos(bw); + it->luma_bits_ = pos2 - pos1; + it->uv_bits_ = pos3 - pos2; + it->bit_count_[segment][i16] += it->luma_bits_; + it->bit_count_[segment][2] += it->uv_bits_; + VP8IteratorBytesToNz(it); +} + +// Same as CodeResiduals, but doesn't actually write anything. +// Instead, it just records the event distribution. +static void RecordResiduals(VP8EncIterator* const it, + const VP8ModeScore* const rd) { + int x, y, ch; + VP8Residual res; + VP8Encoder* const enc = it->enc_; + + VP8IteratorNzToBytes(it); + + if (it->mb_->type_ == 1) { // i16x16 + VP8InitResidual(0, 1, enc, &res); + VP8SetResidualCoeffs(rd->y_dc_levels, &res); + it->top_nz_[8] = it->left_nz_[8] = + VP8RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res); + VP8InitResidual(1, 0, enc, &res); + } else { + VP8InitResidual(0, 3, enc, &res); + } + + // luma-AC + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); + it->top_nz_[x] = it->left_nz_[y] = VP8RecordCoeffs(ctx, &res); + } + } + + // U/V + VP8InitResidual(0, 2, enc, &res); + for (ch = 0; ch <= 2; ch += 2) { + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x) { + const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; + VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); + it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = + VP8RecordCoeffs(ctx, &res); + } + } + } + + VP8IteratorBytesToNz(it); +} + +//------------------------------------------------------------------------------ +// Token buffer + +#if !defined(DISABLE_TOKEN_BUFFER) + +static int RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd, + VP8TBuffer* const tokens) { + int x, y, ch; + VP8Residual res; + VP8Encoder* const enc = it->enc_; + + VP8IteratorNzToBytes(it); + if (it->mb_->type_ == 1) { // i16x16 + const int ctx = it->top_nz_[8] + it->left_nz_[8]; + VP8InitResidual(0, 1, enc, &res); + VP8SetResidualCoeffs(rd->y_dc_levels, &res); + it->top_nz_[8] = it->left_nz_[8] = + VP8RecordCoeffTokens(ctx, 1, + res.first, res.last, res.coeffs, tokens); + VP8RecordCoeffs(ctx, &res); + VP8InitResidual(1, 0, enc, &res); + } else { + VP8InitResidual(0, 3, enc, &res); + } + + // luma-AC + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); + it->top_nz_[x] = it->left_nz_[y] = + VP8RecordCoeffTokens(ctx, res.coeff_type, + res.first, res.last, res.coeffs, tokens); + VP8RecordCoeffs(ctx, &res); + } + } + + // U/V + VP8InitResidual(0, 2, enc, &res); + for (ch = 0; ch <= 2; ch += 2) { + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x) { + const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; + VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); + it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = + VP8RecordCoeffTokens(ctx, 2, + res.first, res.last, res.coeffs, tokens); + VP8RecordCoeffs(ctx, &res); + } + } + } + VP8IteratorBytesToNz(it); + return !tokens->error_; +} + +#endif // !DISABLE_TOKEN_BUFFER + +//------------------------------------------------------------------------------ +// ExtraInfo map / Debug function + +#if SEGMENT_VISU +static void SetBlock(uint8_t* p, int value, int size) { + int y; + for (y = 0; y < size; ++y) { + memset(p, value, size); + p += BPS; + } +} +#endif + +static void ResetSSE(VP8Encoder* const enc) { + enc->sse_[0] = 0; + enc->sse_[1] = 0; + enc->sse_[2] = 0; + // Note: enc->sse_[3] is managed by alpha.c + enc->sse_count_ = 0; +} + +static void StoreSSE(const VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + const uint8_t* const in = it->yuv_in_; + const uint8_t* const out = it->yuv_out_; + // Note: not totally accurate at boundary. And doesn't include in-loop filter. + enc->sse_[0] += VP8SSE16x16(in + Y_OFF_ENC, out + Y_OFF_ENC); + enc->sse_[1] += VP8SSE8x8(in + U_OFF_ENC, out + U_OFF_ENC); + enc->sse_[2] += VP8SSE8x8(in + V_OFF_ENC, out + V_OFF_ENC); + enc->sse_count_ += 16 * 16; +} + +static void StoreSideInfo(const VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + const VP8MBInfo* const mb = it->mb_; + WebPPicture* const pic = enc->pic_; + + if (pic->stats != NULL) { + StoreSSE(it); + enc->block_count_[0] += (mb->type_ == 0); + enc->block_count_[1] += (mb->type_ == 1); + enc->block_count_[2] += (mb->skip_ != 0); + } + + if (pic->extra_info != NULL) { + uint8_t* const info = &pic->extra_info[it->x_ + it->y_ * enc->mb_w_]; + switch (pic->extra_info_type) { + case 1: *info = mb->type_; break; + case 2: *info = mb->segment_; break; + case 3: *info = enc->dqm_[mb->segment_].quant_; break; + case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break; + case 5: *info = mb->uv_mode_; break; + case 6: { + const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3); + *info = (b > 255) ? 255 : b; break; + } + case 7: *info = mb->alpha_; break; + default: *info = 0; break; + } + } +#if SEGMENT_VISU // visualize segments and prediction modes + SetBlock(it->yuv_out_ + Y_OFF_ENC, mb->segment_ * 64, 16); + SetBlock(it->yuv_out_ + U_OFF_ENC, it->preds_[0] * 64, 8); + SetBlock(it->yuv_out_ + V_OFF_ENC, mb->uv_mode_ * 64, 8); +#endif +} + +static double GetPSNR(uint64_t mse, uint64_t size) { + return (mse > 0 && size > 0) ? 10. * log10(255. * 255. * size / mse) : 99; +} + +//------------------------------------------------------------------------------ +// StatLoop(): only collect statistics (number of skips, token usage, ...). +// This is used for deciding optimal probabilities. It also modifies the +// quantizer value if some target (size, PSNR) was specified. + +static void SetLoopParams(VP8Encoder* const enc, float q) { + // Make sure the quality parameter is inside valid bounds + q = Clamp(q, 0.f, 100.f); + + VP8SetSegmentParams(enc, q); // setup segment quantizations and filters + SetSegmentProbas(enc); // compute segment probabilities + + ResetStats(enc); + ResetSSE(enc); +} + +static uint64_t OneStatPass(VP8Encoder* const enc, VP8RDLevel rd_opt, + int nb_mbs, int percent_delta, + PassStats* const s) { + VP8EncIterator it; + uint64_t size = 0; + uint64_t size_p0 = 0; + uint64_t distortion = 0; + const uint64_t pixel_count = nb_mbs * 384; + + VP8IteratorInit(enc, &it); + SetLoopParams(enc, s->q); + do { + VP8ModeScore info; + VP8IteratorImport(&it, NULL); + if (VP8Decimate(&it, &info, rd_opt)) { + // Just record the number of skips and act like skip_proba is not used. + enc->proba_.nb_skip_++; + } + RecordResiduals(&it, &info); + size += info.R + info.H; + size_p0 += info.H; + distortion += info.D; + if (percent_delta && !VP8IteratorProgress(&it, percent_delta)) + return 0; + VP8IteratorSaveBoundary(&it); + } while (VP8IteratorNext(&it) && --nb_mbs > 0); + + size_p0 += enc->segment_hdr_.size_; + if (s->do_size_search) { + size += FinalizeSkipProba(enc); + size += FinalizeTokenProbas(&enc->proba_); + size = ((size + size_p0 + 1024) >> 11) + HEADER_SIZE_ESTIMATE; + s->value = (double)size; + } else { + s->value = GetPSNR(distortion, pixel_count); + } + return size_p0; +} + +static int StatLoop(VP8Encoder* const enc) { + const int method = enc->method_; + const int do_search = enc->do_search_; + const int fast_probe = ((method == 0 || method == 3) && !do_search); + int num_pass_left = enc->config_->pass; + const int task_percent = 20; + const int percent_per_pass = + (task_percent + num_pass_left / 2) / num_pass_left; + const int final_percent = enc->percent_ + task_percent; + const VP8RDLevel rd_opt = + (method >= 3 || do_search) ? RD_OPT_BASIC : RD_OPT_NONE; + int nb_mbs = enc->mb_w_ * enc->mb_h_; + PassStats stats; + + InitPassStats(enc, &stats); + ResetTokenStats(enc); + + // Fast mode: quick analysis pass over few mbs. Better than nothing. + if (fast_probe) { + if (method == 3) { // we need more stats for method 3 to be reliable. + nb_mbs = (nb_mbs > 200) ? nb_mbs >> 1 : 100; + } else { + nb_mbs = (nb_mbs > 200) ? nb_mbs >> 2 : 50; + } + } + + while (num_pass_left-- > 0) { + const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || + (num_pass_left == 0) || + (enc->max_i4_header_bits_ == 0); + const uint64_t size_p0 = + OneStatPass(enc, rd_opt, nb_mbs, percent_per_pass, &stats); + if (size_p0 == 0) return 0; +#if (DEBUG_SEARCH > 0) + printf("#%d value:%.1lf -> %.1lf q:%.2f -> %.2f\n", + num_pass_left, stats.last_value, stats.value, stats.last_q, stats.q); +#endif + if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) { + ++num_pass_left; + enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... + continue; // ...and start over + } + if (is_last_pass) { + break; + } + // If no target size: just do several pass without changing 'q' + if (do_search) { + ComputeNextQ(&stats); + if (fabs(stats.dq) <= DQ_LIMIT) break; + } + } + if (!do_search || !stats.do_size_search) { + // Need to finalize probas now, since it wasn't done during the search. + FinalizeSkipProba(enc); + FinalizeTokenProbas(&enc->proba_); + } + VP8CalculateLevelCosts(&enc->proba_); // finalize costs + return WebPReportProgress(enc->pic_, final_percent, &enc->percent_); +} + +//------------------------------------------------------------------------------ +// Main loops +// + +static const int kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 }; + +static int PreLoopInitialize(VP8Encoder* const enc) { + int p; + int ok = 1; + const int average_bytes_per_MB = kAverageBytesPerMB[enc->base_quant_ >> 4]; + const int bytes_per_parts = + enc->mb_w_ * enc->mb_h_ * average_bytes_per_MB / enc->num_parts_; + // Initialize the bit-writers + for (p = 0; ok && p < enc->num_parts_; ++p) { + ok = VP8BitWriterInit(enc->parts_ + p, bytes_per_parts); + } + if (!ok) { + VP8EncFreeBitWriters(enc); // malloc error occurred + WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + return ok; +} + +static int PostLoopFinalize(VP8EncIterator* const it, int ok) { + VP8Encoder* const enc = it->enc_; + if (ok) { // Finalize the partitions, check for extra errors. + int p; + for (p = 0; p < enc->num_parts_; ++p) { + VP8BitWriterFinish(enc->parts_ + p); + ok &= !enc->parts_[p].error_; + } + } + + if (ok) { // All good. Finish up. + if (enc->pic_->stats != NULL) { // finalize byte counters... + int i, s; + for (i = 0; i <= 2; ++i) { + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + enc->residual_bytes_[i][s] = (int)((it->bit_count_[s][i] + 7) >> 3); + } + } + } + VP8AdjustFilterStrength(it); // ...and store filter stats. + } else { + // Something bad happened -> need to do some memory cleanup. + VP8EncFreeBitWriters(enc); + } + return ok; +} + +//------------------------------------------------------------------------------ +// VP8EncLoop(): does the final bitstream coding. + +static void ResetAfterSkip(VP8EncIterator* const it) { + if (it->mb_->type_ == 1) { + *it->nz_ = 0; // reset all predictors + it->left_nz_[8] = 0; + } else { + *it->nz_ &= (1 << 24); // preserve the dc_nz bit + } +} + +int VP8EncLoop(VP8Encoder* const enc) { + VP8EncIterator it; + int ok = PreLoopInitialize(enc); + if (!ok) return 0; + + StatLoop(enc); // stats-collection loop + + VP8IteratorInit(enc, &it); + VP8InitFilter(&it); + do { + VP8ModeScore info; + const int dont_use_skip = !enc->proba_.use_skip_proba_; + const VP8RDLevel rd_opt = enc->rd_opt_level_; + + VP8IteratorImport(&it, NULL); + // Warning! order is important: first call VP8Decimate() and + // *then* decide how to code the skip decision if there's one. + if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) { + CodeResiduals(it.bw_, &it, &info); + } else { // reset predictors after a skip + ResetAfterSkip(&it); + } + StoreSideInfo(&it); + VP8StoreFilterStats(&it); + VP8IteratorExport(&it); + ok = VP8IteratorProgress(&it, 20); + VP8IteratorSaveBoundary(&it); + } while (ok && VP8IteratorNext(&it)); + + return PostLoopFinalize(&it, ok); +} + +//------------------------------------------------------------------------------ +// Single pass using Token Buffer. + +#if !defined(DISABLE_TOKEN_BUFFER) + +#define MIN_COUNT 96 // minimum number of macroblocks before updating stats + +int VP8EncTokenLoop(VP8Encoder* const enc) { + // Roughly refresh the proba eight times per pass + int max_count = (enc->mb_w_ * enc->mb_h_) >> 3; + int num_pass_left = enc->config_->pass; + const int do_search = enc->do_search_; + VP8EncIterator it; + VP8EncProba* const proba = &enc->proba_; + const VP8RDLevel rd_opt = enc->rd_opt_level_; + const uint64_t pixel_count = enc->mb_w_ * enc->mb_h_ * 384; + PassStats stats; + int ok; + + InitPassStats(enc, &stats); + ok = PreLoopInitialize(enc); + if (!ok) return 0; + + if (max_count < MIN_COUNT) max_count = MIN_COUNT; + + assert(enc->num_parts_ == 1); + assert(enc->use_tokens_); + assert(proba->use_skip_proba_ == 0); + assert(rd_opt >= RD_OPT_BASIC); // otherwise, token-buffer won't be useful + assert(num_pass_left > 0); + + while (ok && num_pass_left-- > 0) { + const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || + (num_pass_left == 0) || + (enc->max_i4_header_bits_ == 0); + uint64_t size_p0 = 0; + uint64_t distortion = 0; + int cnt = max_count; + VP8IteratorInit(enc, &it); + SetLoopParams(enc, stats.q); + if (is_last_pass) { + ResetTokenStats(enc); + VP8InitFilter(&it); // don't collect stats until last pass (too costly) + } + VP8TBufferClear(&enc->tokens_); + do { + VP8ModeScore info; + VP8IteratorImport(&it, NULL); + if (--cnt < 0) { + FinalizeTokenProbas(proba); + VP8CalculateLevelCosts(proba); // refresh cost tables for rd-opt + cnt = max_count; + } + VP8Decimate(&it, &info, rd_opt); + ok = RecordTokens(&it, &info, &enc->tokens_); + if (!ok) { + WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + break; + } + size_p0 += info.H; + distortion += info.D; + if (is_last_pass) { + StoreSideInfo(&it); + VP8StoreFilterStats(&it); + VP8IteratorExport(&it); + ok = VP8IteratorProgress(&it, 20); + } + VP8IteratorSaveBoundary(&it); + } while (ok && VP8IteratorNext(&it)); + if (!ok) break; + + size_p0 += enc->segment_hdr_.size_; + if (stats.do_size_search) { + uint64_t size = FinalizeTokenProbas(&enc->proba_); + size += VP8EstimateTokenSize(&enc->tokens_, + (const uint8_t*)proba->coeffs_); + size = (size + size_p0 + 1024) >> 11; // -> size in bytes + size += HEADER_SIZE_ESTIMATE; + stats.value = (double)size; + } else { // compute and store PSNR + stats.value = GetPSNR(distortion, pixel_count); + } + +#if (DEBUG_SEARCH > 0) + printf("#%2d metric:%.1lf -> %.1lf last_q=%.2lf q=%.2lf dq=%.2lf\n", + num_pass_left, stats.last_value, stats.value, + stats.last_q, stats.q, stats.dq); +#endif + if (size_p0 > PARTITION0_SIZE_LIMIT) { + ++num_pass_left; + enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... + continue; // ...and start over + } + if (is_last_pass) { + break; // done + } + if (do_search) { + ComputeNextQ(&stats); // Adjust q + } + } + if (ok) { + if (!stats.do_size_search) { + FinalizeTokenProbas(&enc->proba_); + } + ok = VP8EmitTokens(&enc->tokens_, enc->parts_ + 0, + (const uint8_t*)proba->coeffs_, 1); + } + ok = ok && WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); + return PostLoopFinalize(&it, ok); +} + +#else + +int VP8EncTokenLoop(VP8Encoder* const enc) { + (void)enc; + return 0; // we shouldn't be here. +} + +#endif // DISABLE_TOKEN_BUFFER + +//------------------------------------------------------------------------------ + diff --git a/thirdparty/libwebp/enc/histogram.c b/thirdparty/libwebp/enc/histogram.c new file mode 100644 index 0000000000..395372b245 --- /dev/null +++ b/thirdparty/libwebp/enc/histogram.c @@ -0,0 +1,937 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +#ifdef HAVE_CONFIG_H +#include "../webp/config.h" +#endif + +#include <math.h> + +#include "./backward_references.h" +#include "./histogram.h" +#include "../dsp/lossless.h" +#include "../utils/utils.h" + +#define MAX_COST 1.e38 + +// Number of partitions for the three dominant (literal, red and blue) symbol +// costs. +#define NUM_PARTITIONS 4 +// The size of the bin-hash corresponding to the three dominant costs. +#define BIN_SIZE (NUM_PARTITIONS * NUM_PARTITIONS * NUM_PARTITIONS) +// Maximum number of histograms allowed in greedy combining algorithm. +#define MAX_HISTO_GREEDY 100 + +static void HistogramClear(VP8LHistogram* const p) { + uint32_t* const literal = p->literal_; + const int cache_bits = p->palette_code_bits_; + const int histo_size = VP8LGetHistogramSize(cache_bits); + memset(p, 0, histo_size); + p->palette_code_bits_ = cache_bits; + p->literal_ = literal; +} + +// Swap two histogram pointers. +static void HistogramSwap(VP8LHistogram** const A, VP8LHistogram** const B) { + VP8LHistogram* const tmp = *A; + *A = *B; + *B = tmp; +} + +static void HistogramCopy(const VP8LHistogram* const src, + VP8LHistogram* const dst) { + uint32_t* const dst_literal = dst->literal_; + const int dst_cache_bits = dst->palette_code_bits_; + const int histo_size = VP8LGetHistogramSize(dst_cache_bits); + assert(src->palette_code_bits_ == dst_cache_bits); + memcpy(dst, src, histo_size); + dst->literal_ = dst_literal; +} + +int VP8LGetHistogramSize(int cache_bits) { + const int literal_size = VP8LHistogramNumCodes(cache_bits); + const size_t total_size = sizeof(VP8LHistogram) + sizeof(int) * literal_size; + assert(total_size <= (size_t)0x7fffffff); + return (int)total_size; +} + +void VP8LFreeHistogram(VP8LHistogram* const histo) { + WebPSafeFree(histo); +} + +void VP8LFreeHistogramSet(VP8LHistogramSet* const histo) { + WebPSafeFree(histo); +} + +void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs, + VP8LHistogram* const histo) { + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + while (VP8LRefsCursorOk(&c)) { + VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos); + VP8LRefsCursorNext(&c); + } +} + +void VP8LHistogramCreate(VP8LHistogram* const p, + const VP8LBackwardRefs* const refs, + int palette_code_bits) { + if (palette_code_bits >= 0) { + p->palette_code_bits_ = palette_code_bits; + } + HistogramClear(p); + VP8LHistogramStoreRefs(refs, p); +} + +void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits) { + p->palette_code_bits_ = palette_code_bits; + HistogramClear(p); +} + +VP8LHistogram* VP8LAllocateHistogram(int cache_bits) { + VP8LHistogram* histo = NULL; + const int total_size = VP8LGetHistogramSize(cache_bits); + uint8_t* const memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory)); + if (memory == NULL) return NULL; + histo = (VP8LHistogram*)memory; + // literal_ won't necessary be aligned. + histo->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram)); + VP8LHistogramInit(histo, cache_bits); + return histo; +} + +VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) { + int i; + VP8LHistogramSet* set; + const int histo_size = VP8LGetHistogramSize(cache_bits); + const size_t total_size = + sizeof(*set) + size * (sizeof(*set->histograms) + + histo_size + WEBP_ALIGN_CST); + uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory)); + if (memory == NULL) return NULL; + + set = (VP8LHistogramSet*)memory; + memory += sizeof(*set); + set->histograms = (VP8LHistogram**)memory; + memory += size * sizeof(*set->histograms); + set->max_size = size; + set->size = size; + for (i = 0; i < size; ++i) { + memory = (uint8_t*)WEBP_ALIGN(memory); + set->histograms[i] = (VP8LHistogram*)memory; + // literal_ won't necessary be aligned. + set->histograms[i]->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram)); + VP8LHistogramInit(set->histograms[i], cache_bits); + memory += histo_size; + } + return set; +} + +// ----------------------------------------------------------------------------- + +void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, + const PixOrCopy* const v) { + if (PixOrCopyIsLiteral(v)) { + ++histo->alpha_[PixOrCopyLiteral(v, 3)]; + ++histo->red_[PixOrCopyLiteral(v, 2)]; + ++histo->literal_[PixOrCopyLiteral(v, 1)]; + ++histo->blue_[PixOrCopyLiteral(v, 0)]; + } else if (PixOrCopyIsCacheIdx(v)) { + const int literal_ix = + NUM_LITERAL_CODES + NUM_LENGTH_CODES + PixOrCopyCacheIdx(v); + ++histo->literal_[literal_ix]; + } else { + int code, extra_bits; + VP8LPrefixEncodeBits(PixOrCopyLength(v), &code, &extra_bits); + ++histo->literal_[NUM_LITERAL_CODES + code]; + VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits); + ++histo->distance_[code]; + } +} + +// ----------------------------------------------------------------------------- +// Entropy-related functions. + +static WEBP_INLINE double BitsEntropyRefine(const VP8LBitEntropy* entropy) { + double mix; + if (entropy->nonzeros < 5) { + if (entropy->nonzeros <= 1) { + return 0; + } + // Two symbols, they will be 0 and 1 in a Huffman code. + // Let's mix in a bit of entropy to favor good clustering when + // distributions of these are combined. + if (entropy->nonzeros == 2) { + return 0.99 * entropy->sum + 0.01 * entropy->entropy; + } + // No matter what the entropy says, we cannot be better than min_limit + // with Huffman coding. I am mixing a bit of entropy into the + // min_limit since it produces much better (~0.5 %) compression results + // perhaps because of better entropy clustering. + if (entropy->nonzeros == 3) { + mix = 0.95; + } else { + mix = 0.7; // nonzeros == 4. + } + } else { + mix = 0.627; + } + + { + double min_limit = 2 * entropy->sum - entropy->max_val; + min_limit = mix * min_limit + (1.0 - mix) * entropy->entropy; + return (entropy->entropy < min_limit) ? min_limit : entropy->entropy; + } +} + +double VP8LBitsEntropy(const uint32_t* const array, int n, + uint32_t* const trivial_symbol) { + VP8LBitEntropy entropy; + VP8LBitsEntropyUnrefined(array, n, &entropy); + if (trivial_symbol != NULL) { + *trivial_symbol = + (entropy.nonzeros == 1) ? entropy.nonzero_code : VP8L_NON_TRIVIAL_SYM; + } + + return BitsEntropyRefine(&entropy); +} + +static double InitialHuffmanCost(void) { + // Small bias because Huffman code length is typically not stored in + // full length. + static const int kHuffmanCodeOfHuffmanCodeSize = CODE_LENGTH_CODES * 3; + static const double kSmallBias = 9.1; + return kHuffmanCodeOfHuffmanCodeSize - kSmallBias; +} + +// Finalize the Huffman cost based on streak numbers and length type (<3 or >=3) +static double FinalHuffmanCost(const VP8LStreaks* const stats) { + double retval = InitialHuffmanCost(); + retval += stats->counts[0] * 1.5625 + 0.234375 * stats->streaks[0][1]; + retval += stats->counts[1] * 2.578125 + 0.703125 * stats->streaks[1][1]; + retval += 1.796875 * stats->streaks[0][0]; + retval += 3.28125 * stats->streaks[1][0]; + return retval; +} + +// Get the symbol entropy for the distribution 'population'. +// Set 'trivial_sym', if there's only one symbol present in the distribution. +static double PopulationCost(const uint32_t* const population, int length, + uint32_t* const trivial_sym) { + VP8LBitEntropy bit_entropy; + VP8LStreaks stats; + VP8LGetEntropyUnrefined(population, length, &bit_entropy, &stats); + if (trivial_sym != NULL) { + *trivial_sym = (bit_entropy.nonzeros == 1) ? bit_entropy.nonzero_code + : VP8L_NON_TRIVIAL_SYM; + } + + return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats); +} + +static WEBP_INLINE double GetCombinedEntropy(const uint32_t* const X, + const uint32_t* const Y, + int length) { + VP8LBitEntropy bit_entropy; + VP8LStreaks stats; + VP8LGetCombinedEntropyUnrefined(X, Y, length, &bit_entropy, &stats); + + return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats); +} + +// Estimates the Entropy + Huffman + other block overhead size cost. +double VP8LHistogramEstimateBits(const VP8LHistogram* const p) { + return + PopulationCost( + p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_), NULL) + + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL) + + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL) + + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL) + + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL) + + VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES) + + VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES); +} + +// ----------------------------------------------------------------------------- +// Various histogram combine/cost-eval functions + +static int GetCombinedHistogramEntropy(const VP8LHistogram* const a, + const VP8LHistogram* const b, + double cost_threshold, + double* cost) { + const int palette_code_bits = a->palette_code_bits_; + assert(a->palette_code_bits_ == b->palette_code_bits_); + *cost += GetCombinedEntropy(a->literal_, b->literal_, + VP8LHistogramNumCodes(palette_code_bits)); + *cost += VP8LExtraCostCombined(a->literal_ + NUM_LITERAL_CODES, + b->literal_ + NUM_LITERAL_CODES, + NUM_LENGTH_CODES); + if (*cost > cost_threshold) return 0; + + *cost += GetCombinedEntropy(a->red_, b->red_, NUM_LITERAL_CODES); + if (*cost > cost_threshold) return 0; + + *cost += GetCombinedEntropy(a->blue_, b->blue_, NUM_LITERAL_CODES); + if (*cost > cost_threshold) return 0; + + *cost += GetCombinedEntropy(a->alpha_, b->alpha_, NUM_LITERAL_CODES); + if (*cost > cost_threshold) return 0; + + *cost += GetCombinedEntropy(a->distance_, b->distance_, NUM_DISTANCE_CODES); + *cost += + VP8LExtraCostCombined(a->distance_, b->distance_, NUM_DISTANCE_CODES); + if (*cost > cost_threshold) return 0; + + return 1; +} + +// Performs out = a + b, computing the cost C(a+b) - C(a) - C(b) while comparing +// to the threshold value 'cost_threshold'. The score returned is +// Score = C(a+b) - C(a) - C(b), where C(a) + C(b) is known and fixed. +// Since the previous score passed is 'cost_threshold', we only need to compare +// the partial cost against 'cost_threshold + C(a) + C(b)' to possibly bail-out +// early. +static double HistogramAddEval(const VP8LHistogram* const a, + const VP8LHistogram* const b, + VP8LHistogram* const out, + double cost_threshold) { + double cost = 0; + const double sum_cost = a->bit_cost_ + b->bit_cost_; + cost_threshold += sum_cost; + + if (GetCombinedHistogramEntropy(a, b, cost_threshold, &cost)) { + VP8LHistogramAdd(a, b, out); + out->bit_cost_ = cost; + out->palette_code_bits_ = a->palette_code_bits_; + out->trivial_symbol_ = (a->trivial_symbol_ == b->trivial_symbol_) ? + a->trivial_symbol_ : VP8L_NON_TRIVIAL_SYM; + } + + return cost - sum_cost; +} + +// Same as HistogramAddEval(), except that the resulting histogram +// is not stored. Only the cost C(a+b) - C(a) is evaluated. We omit +// the term C(b) which is constant over all the evaluations. +static double HistogramAddThresh(const VP8LHistogram* const a, + const VP8LHistogram* const b, + double cost_threshold) { + double cost = -a->bit_cost_; + GetCombinedHistogramEntropy(a, b, cost_threshold, &cost); + return cost; +} + +// ----------------------------------------------------------------------------- + +// The structure to keep track of cost range for the three dominant entropy +// symbols. +// TODO(skal): Evaluate if float can be used here instead of double for +// representing the entropy costs. +typedef struct { + double literal_max_; + double literal_min_; + double red_max_; + double red_min_; + double blue_max_; + double blue_min_; +} DominantCostRange; + +static void DominantCostRangeInit(DominantCostRange* const c) { + c->literal_max_ = 0.; + c->literal_min_ = MAX_COST; + c->red_max_ = 0.; + c->red_min_ = MAX_COST; + c->blue_max_ = 0.; + c->blue_min_ = MAX_COST; +} + +static void UpdateDominantCostRange( + const VP8LHistogram* const h, DominantCostRange* const c) { + if (c->literal_max_ < h->literal_cost_) c->literal_max_ = h->literal_cost_; + if (c->literal_min_ > h->literal_cost_) c->literal_min_ = h->literal_cost_; + if (c->red_max_ < h->red_cost_) c->red_max_ = h->red_cost_; + if (c->red_min_ > h->red_cost_) c->red_min_ = h->red_cost_; + if (c->blue_max_ < h->blue_cost_) c->blue_max_ = h->blue_cost_; + if (c->blue_min_ > h->blue_cost_) c->blue_min_ = h->blue_cost_; +} + +static void UpdateHistogramCost(VP8LHistogram* const h) { + uint32_t alpha_sym, red_sym, blue_sym; + const double alpha_cost = + PopulationCost(h->alpha_, NUM_LITERAL_CODES, &alpha_sym); + const double distance_cost = + PopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL) + + VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES); + const int num_codes = VP8LHistogramNumCodes(h->palette_code_bits_); + h->literal_cost_ = PopulationCost(h->literal_, num_codes, NULL) + + VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES, + NUM_LENGTH_CODES); + h->red_cost_ = PopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym); + h->blue_cost_ = PopulationCost(h->blue_, NUM_LITERAL_CODES, &blue_sym); + h->bit_cost_ = h->literal_cost_ + h->red_cost_ + h->blue_cost_ + + alpha_cost + distance_cost; + if ((alpha_sym | red_sym | blue_sym) == VP8L_NON_TRIVIAL_SYM) { + h->trivial_symbol_ = VP8L_NON_TRIVIAL_SYM; + } else { + h->trivial_symbol_ = + ((uint32_t)alpha_sym << 24) | (red_sym << 16) | (blue_sym << 0); + } +} + +static int GetBinIdForEntropy(double min, double max, double val) { + const double range = max - min; + if (range > 0.) { + const double delta = val - min; + return (int)((NUM_PARTITIONS - 1e-6) * delta / range); + } else { + return 0; + } +} + +static int GetHistoBinIndex(const VP8LHistogram* const h, + const DominantCostRange* const c, int low_effort) { + int bin_id = GetBinIdForEntropy(c->literal_min_, c->literal_max_, + h->literal_cost_); + assert(bin_id < NUM_PARTITIONS); + if (!low_effort) { + bin_id = bin_id * NUM_PARTITIONS + + GetBinIdForEntropy(c->red_min_, c->red_max_, h->red_cost_); + bin_id = bin_id * NUM_PARTITIONS + + GetBinIdForEntropy(c->blue_min_, c->blue_max_, h->blue_cost_); + assert(bin_id < BIN_SIZE); + } + return bin_id; +} + +// Construct the histograms from backward references. +static void HistogramBuild( + int xsize, int histo_bits, const VP8LBackwardRefs* const backward_refs, + VP8LHistogramSet* const image_histo) { + int x = 0, y = 0; + const int histo_xsize = VP8LSubSampleSize(xsize, histo_bits); + VP8LHistogram** const histograms = image_histo->histograms; + VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs); + assert(histo_bits > 0); + while (VP8LRefsCursorOk(&c)) { + const PixOrCopy* const v = c.cur_pos; + const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits); + VP8LHistogramAddSinglePixOrCopy(histograms[ix], v); + x += PixOrCopyLength(v); + while (x >= xsize) { + x -= xsize; + ++y; + } + VP8LRefsCursorNext(&c); + } +} + +// Copies the histograms and computes its bit_cost. +static void HistogramCopyAndAnalyze( + VP8LHistogramSet* const orig_histo, VP8LHistogramSet* const image_histo) { + int i; + const int histo_size = orig_histo->size; + VP8LHistogram** const orig_histograms = orig_histo->histograms; + VP8LHistogram** const histograms = image_histo->histograms; + for (i = 0; i < histo_size; ++i) { + VP8LHistogram* const histo = orig_histograms[i]; + UpdateHistogramCost(histo); + // Copy histograms from orig_histo[] to image_histo[]. + HistogramCopy(histo, histograms[i]); + } +} + +// Partition histograms to different entropy bins for three dominant (literal, +// red and blue) symbol costs and compute the histogram aggregate bit_cost. +static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo, + int16_t* const bin_map, int low_effort) { + int i; + VP8LHistogram** const histograms = image_histo->histograms; + const int histo_size = image_histo->size; + const int bin_depth = histo_size + 1; + DominantCostRange cost_range; + DominantCostRangeInit(&cost_range); + + // Analyze the dominant (literal, red and blue) entropy costs. + for (i = 0; i < histo_size; ++i) { + VP8LHistogram* const histo = histograms[i]; + UpdateDominantCostRange(histo, &cost_range); + } + + // bin-hash histograms on three of the dominant (literal, red and blue) + // symbol costs. + for (i = 0; i < histo_size; ++i) { + const VP8LHistogram* const histo = histograms[i]; + const int bin_id = GetHistoBinIndex(histo, &cost_range, low_effort); + const int bin_offset = bin_id * bin_depth; + // bin_map[n][0] for every bin 'n' maintains the counter for the number of + // histograms in that bin. + // Get and increment the num_histos in that bin. + const int num_histos = ++bin_map[bin_offset]; + assert(bin_offset + num_histos < bin_depth * BIN_SIZE); + // Add histogram i'th index at num_histos (last) position in the bin_map. + bin_map[bin_offset + num_histos] = i; + } +} + +// Compact the histogram set by removing unused entries. +static void HistogramCompactBins(VP8LHistogramSet* const image_histo) { + VP8LHistogram** const histograms = image_histo->histograms; + int i, j; + + for (i = 0, j = 0; i < image_histo->size; ++i) { + if (histograms[i] != NULL && histograms[i]->bit_cost_ != 0.) { + if (j < i) { + histograms[j] = histograms[i]; + histograms[i] = NULL; + } + ++j; + } + } + image_histo->size = j; +} + +static VP8LHistogram* HistogramCombineEntropyBin( + VP8LHistogramSet* const image_histo, + VP8LHistogram* cur_combo, + int16_t* const bin_map, int bin_depth, int num_bins, + double combine_cost_factor, int low_effort) { + int bin_id; + VP8LHistogram** const histograms = image_histo->histograms; + + for (bin_id = 0; bin_id < num_bins; ++bin_id) { + const int bin_offset = bin_id * bin_depth; + const int num_histos = bin_map[bin_offset]; + const int idx1 = bin_map[bin_offset + 1]; + int num_combine_failures = 0; + int n; + for (n = 2; n <= num_histos; ++n) { + const int idx2 = bin_map[bin_offset + n]; + if (low_effort) { + // Merge all histograms with the same bin index, irrespective of cost of + // the merged histograms. + VP8LHistogramAdd(histograms[idx1], histograms[idx2], histograms[idx1]); + histograms[idx2]->bit_cost_ = 0.; + } else { + const double bit_cost_idx2 = histograms[idx2]->bit_cost_; + if (bit_cost_idx2 > 0.) { + const double bit_cost_thresh = -bit_cost_idx2 * combine_cost_factor; + const double curr_cost_diff = + HistogramAddEval(histograms[idx1], histograms[idx2], + cur_combo, bit_cost_thresh); + if (curr_cost_diff < bit_cost_thresh) { + // Try to merge two histograms only if the combo is a trivial one or + // the two candidate histograms are already non-trivial. + // For some images, 'try_combine' turns out to be false for a lot of + // histogram pairs. In that case, we fallback to combining + // histograms as usual to avoid increasing the header size. + const int try_combine = + (cur_combo->trivial_symbol_ != VP8L_NON_TRIVIAL_SYM) || + ((histograms[idx1]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM) && + (histograms[idx2]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM)); + const int max_combine_failures = 32; + if (try_combine || (num_combine_failures >= max_combine_failures)) { + HistogramSwap(&cur_combo, &histograms[idx1]); + histograms[idx2]->bit_cost_ = 0.; + } else { + ++num_combine_failures; + } + } + } + } + } + if (low_effort) { + // Update the bit_cost for the merged histograms (per bin index). + UpdateHistogramCost(histograms[idx1]); + } + } + HistogramCompactBins(image_histo); + return cur_combo; +} + +static uint32_t MyRand(uint32_t *seed) { + *seed *= 16807U; + if (*seed == 0) { + *seed = 1; + } + return *seed; +} + +// ----------------------------------------------------------------------------- +// Histogram pairs priority queue + +// Pair of histograms. Negative idx1 value means that pair is out-of-date. +typedef struct { + int idx1; + int idx2; + double cost_diff; + double cost_combo; +} HistogramPair; + +typedef struct { + HistogramPair* queue; + int size; + int max_size; +} HistoQueue; + +static int HistoQueueInit(HistoQueue* const histo_queue, const int max_index) { + histo_queue->size = 0; + // max_index^2 for the queue size is safe. If you look at + // HistogramCombineGreedy, and imagine that UpdateQueueFront always pushes + // data to the queue, you insert at most: + // - max_index*(max_index-1)/2 (the first two for loops) + // - max_index - 1 in the last for loop at the first iteration of the while + // loop, max_index - 2 at the second iteration ... therefore + // max_index*(max_index-1)/2 overall too + histo_queue->max_size = max_index * max_index; + // We allocate max_size + 1 because the last element at index "size" is + // used as temporary data (and it could be up to max_size). + histo_queue->queue = WebPSafeMalloc(histo_queue->max_size + 1, + sizeof(*histo_queue->queue)); + return histo_queue->queue != NULL; +} + +static void HistoQueueClear(HistoQueue* const histo_queue) { + assert(histo_queue != NULL); + WebPSafeFree(histo_queue->queue); +} + +static void SwapHistogramPairs(HistogramPair *p1, + HistogramPair *p2) { + const HistogramPair tmp = *p1; + *p1 = *p2; + *p2 = tmp; +} + +// Given a valid priority queue in range [0, queue_size) this function checks +// whether histo_queue[queue_size] should be accepted and swaps it with the +// front if it is smaller. Otherwise, it leaves it as is. +static void UpdateQueueFront(HistoQueue* const histo_queue) { + if (histo_queue->queue[histo_queue->size].cost_diff >= 0) return; + + if (histo_queue->queue[histo_queue->size].cost_diff < + histo_queue->queue[0].cost_diff) { + SwapHistogramPairs(histo_queue->queue, + histo_queue->queue + histo_queue->size); + } + ++histo_queue->size; + + // We cannot add more elements than the capacity. + // The allocation adds an extra element to the official capacity so that + // histo_queue->queue[histo_queue->max_size] is read/written within bound. + assert(histo_queue->size <= histo_queue->max_size); +} + +// ----------------------------------------------------------------------------- + +static void PreparePair(VP8LHistogram** histograms, int idx1, int idx2, + HistogramPair* const pair) { + VP8LHistogram* h1; + VP8LHistogram* h2; + double sum_cost; + + if (idx1 > idx2) { + const int tmp = idx2; + idx2 = idx1; + idx1 = tmp; + } + pair->idx1 = idx1; + pair->idx2 = idx2; + h1 = histograms[idx1]; + h2 = histograms[idx2]; + sum_cost = h1->bit_cost_ + h2->bit_cost_; + pair->cost_combo = 0.; + GetCombinedHistogramEntropy(h1, h2, sum_cost, &pair->cost_combo); + pair->cost_diff = pair->cost_combo - sum_cost; +} + +// Combines histograms by continuously choosing the one with the highest cost +// reduction. +static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo) { + int ok = 0; + int image_histo_size = image_histo->size; + int i, j; + VP8LHistogram** const histograms = image_histo->histograms; + // Indexes of remaining histograms. + int* const clusters = WebPSafeMalloc(image_histo_size, sizeof(*clusters)); + // Priority queue of histogram pairs. + HistoQueue histo_queue; + + if (!HistoQueueInit(&histo_queue, image_histo_size) || clusters == NULL) { + goto End; + } + + for (i = 0; i < image_histo_size; ++i) { + // Initialize clusters indexes. + clusters[i] = i; + for (j = i + 1; j < image_histo_size; ++j) { + // Initialize positions array. + PreparePair(histograms, i, j, &histo_queue.queue[histo_queue.size]); + UpdateQueueFront(&histo_queue); + } + } + + while (image_histo_size > 1 && histo_queue.size > 0) { + HistogramPair* copy_to; + const int idx1 = histo_queue.queue[0].idx1; + const int idx2 = histo_queue.queue[0].idx2; + VP8LHistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]); + histograms[idx1]->bit_cost_ = histo_queue.queue[0].cost_combo; + // Remove merged histogram. + for (i = 0; i + 1 < image_histo_size; ++i) { + if (clusters[i] >= idx2) { + clusters[i] = clusters[i + 1]; + } + } + --image_histo_size; + + // Remove pairs intersecting the just combined best pair. This will + // therefore pop the head of the queue. + copy_to = histo_queue.queue; + for (i = 0; i < histo_queue.size; ++i) { + HistogramPair* const p = histo_queue.queue + i; + if (p->idx1 == idx1 || p->idx2 == idx1 || + p->idx1 == idx2 || p->idx2 == idx2) { + // Do not copy the invalid pair. + continue; + } + if (p->cost_diff < histo_queue.queue[0].cost_diff) { + // Replace the top of the queue if we found better. + SwapHistogramPairs(histo_queue.queue, p); + } + SwapHistogramPairs(copy_to, p); + ++copy_to; + } + histo_queue.size = (int)(copy_to - histo_queue.queue); + + // Push new pairs formed with combined histogram to the queue. + for (i = 0; i < image_histo_size; ++i) { + if (clusters[i] != idx1) { + PreparePair(histograms, idx1, clusters[i], + &histo_queue.queue[histo_queue.size]); + UpdateQueueFront(&histo_queue); + } + } + } + // Move remaining histograms to the beginning of the array. + for (i = 0; i < image_histo_size; ++i) { + if (i != clusters[i]) { // swap the two histograms + HistogramSwap(&histograms[i], &histograms[clusters[i]]); + } + } + + image_histo->size = image_histo_size; + ok = 1; + + End: + WebPSafeFree(clusters); + HistoQueueClear(&histo_queue); + return ok; +} + +static void HistogramCombineStochastic(VP8LHistogramSet* const image_histo, + VP8LHistogram* tmp_histo, + VP8LHistogram* best_combo, + int quality, int min_cluster_size) { + int iter; + uint32_t seed = 0; + int tries_with_no_success = 0; + int image_histo_size = image_histo->size; + const int iter_mult = (quality < 25) ? 2 : 2 + (quality - 25) / 8; + const int outer_iters = image_histo_size * iter_mult; + const int num_pairs = image_histo_size / 2; + const int num_tries_no_success = outer_iters / 2; + VP8LHistogram** const histograms = image_histo->histograms; + + // Collapse similar histograms in 'image_histo'. + ++min_cluster_size; + for (iter = 0; + iter < outer_iters && image_histo_size >= min_cluster_size; + ++iter) { + double best_cost_diff = 0.; + int best_idx1 = -1, best_idx2 = 1; + int j; + const int num_tries = + (num_pairs < image_histo_size) ? num_pairs : image_histo_size; + seed += iter; + for (j = 0; j < num_tries; ++j) { + double curr_cost_diff; + // Choose two histograms at random and try to combine them. + const uint32_t idx1 = MyRand(&seed) % image_histo_size; + const uint32_t tmp = (j & 7) + 1; + const uint32_t diff = + (tmp < 3) ? tmp : MyRand(&seed) % (image_histo_size - 1); + const uint32_t idx2 = (idx1 + diff + 1) % image_histo_size; + if (idx1 == idx2) { + continue; + } + + // Calculate cost reduction on combining. + curr_cost_diff = HistogramAddEval(histograms[idx1], histograms[idx2], + tmp_histo, best_cost_diff); + if (curr_cost_diff < best_cost_diff) { // found a better pair? + HistogramSwap(&best_combo, &tmp_histo); + best_cost_diff = curr_cost_diff; + best_idx1 = idx1; + best_idx2 = idx2; + } + } + + if (best_idx1 >= 0) { + HistogramSwap(&best_combo, &histograms[best_idx1]); + // swap best_idx2 slot with last one (which is now unused) + --image_histo_size; + if (best_idx2 != image_histo_size) { + HistogramSwap(&histograms[image_histo_size], &histograms[best_idx2]); + histograms[image_histo_size] = NULL; + } + tries_with_no_success = 0; + } + if (++tries_with_no_success >= num_tries_no_success) { + break; + } + } + image_histo->size = image_histo_size; +} + +// ----------------------------------------------------------------------------- +// Histogram refinement + +// Find the best 'out' histogram for each of the 'in' histograms. +// Note: we assume that out[]->bit_cost_ is already up-to-date. +static void HistogramRemap(const VP8LHistogramSet* const in, + const VP8LHistogramSet* const out, + uint16_t* const symbols) { + int i; + VP8LHistogram** const in_histo = in->histograms; + VP8LHistogram** const out_histo = out->histograms; + const int in_size = in->size; + const int out_size = out->size; + if (out_size > 1) { + for (i = 0; i < in_size; ++i) { + int best_out = 0; + double best_bits = MAX_COST; + int k; + for (k = 0; k < out_size; ++k) { + const double cur_bits = + HistogramAddThresh(out_histo[k], in_histo[i], best_bits); + if (k == 0 || cur_bits < best_bits) { + best_bits = cur_bits; + best_out = k; + } + } + symbols[i] = best_out; + } + } else { + assert(out_size == 1); + for (i = 0; i < in_size; ++i) { + symbols[i] = 0; + } + } + + // Recompute each out based on raw and symbols. + for (i = 0; i < out_size; ++i) { + HistogramClear(out_histo[i]); + } + + for (i = 0; i < in_size; ++i) { + const int idx = symbols[i]; + VP8LHistogramAdd(in_histo[i], out_histo[idx], out_histo[idx]); + } +} + +static double GetCombineCostFactor(int histo_size, int quality) { + double combine_cost_factor = 0.16; + if (quality < 90) { + if (histo_size > 256) combine_cost_factor /= 2.; + if (histo_size > 512) combine_cost_factor /= 2.; + if (histo_size > 1024) combine_cost_factor /= 2.; + if (quality <= 50) combine_cost_factor /= 2.; + } + return combine_cost_factor; +} + +int VP8LGetHistoImageSymbols(int xsize, int ysize, + const VP8LBackwardRefs* const refs, + int quality, int low_effort, + int histo_bits, int cache_bits, + VP8LHistogramSet* const image_histo, + VP8LHistogramSet* const tmp_histos, + uint16_t* const histogram_symbols) { + int ok = 0; + const int histo_xsize = histo_bits ? VP8LSubSampleSize(xsize, histo_bits) : 1; + const int histo_ysize = histo_bits ? VP8LSubSampleSize(ysize, histo_bits) : 1; + const int image_histo_raw_size = histo_xsize * histo_ysize; + const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE; + + // The bin_map for every bin follows following semantics: + // bin_map[n][0] = num_histo; // The number of histograms in that bin. + // bin_map[n][1] = index of first histogram in that bin; + // bin_map[n][num_histo] = index of last histogram in that bin; + // bin_map[n][num_histo + 1] ... bin_map[n][bin_depth - 1] = unused indices. + const int bin_depth = image_histo_raw_size + 1; + int16_t* bin_map = NULL; + VP8LHistogramSet* const orig_histo = + VP8LAllocateHistogramSet(image_histo_raw_size, cache_bits); + VP8LHistogram* cur_combo; + const int entropy_combine = + (orig_histo->size > entropy_combine_num_bins * 2) && (quality < 100); + + if (orig_histo == NULL) goto Error; + + // Don't attempt linear bin-partition heuristic for: + // histograms of small sizes, as bin_map will be very sparse and; + // Maximum quality (q==100), to preserve the compression gains at that level. + if (entropy_combine) { + const int bin_map_size = bin_depth * entropy_combine_num_bins; + bin_map = (int16_t*)WebPSafeCalloc(bin_map_size, sizeof(*bin_map)); + if (bin_map == NULL) goto Error; + } + + // Construct the histograms from backward references. + HistogramBuild(xsize, histo_bits, refs, orig_histo); + // Copies the histograms and computes its bit_cost. + HistogramCopyAndAnalyze(orig_histo, image_histo); + + cur_combo = tmp_histos->histograms[1]; // pick up working slot + if (entropy_combine) { + const double combine_cost_factor = + GetCombineCostFactor(image_histo_raw_size, quality); + HistogramAnalyzeEntropyBin(orig_histo, bin_map, low_effort); + // Collapse histograms with similar entropy. + cur_combo = HistogramCombineEntropyBin(image_histo, cur_combo, bin_map, + bin_depth, entropy_combine_num_bins, + combine_cost_factor, low_effort); + } + + // Don't combine the histograms using stochastic and greedy heuristics for + // low-effort compression mode. + if (!low_effort || !entropy_combine) { + const float x = quality / 100.f; + // cubic ramp between 1 and MAX_HISTO_GREEDY: + const int threshold_size = (int)(1 + (x * x * x) * (MAX_HISTO_GREEDY - 1)); + HistogramCombineStochastic(image_histo, tmp_histos->histograms[0], + cur_combo, quality, threshold_size); + if ((image_histo->size <= threshold_size) && + !HistogramCombineGreedy(image_histo)) { + goto Error; + } + } + + // TODO(vikasa): Optimize HistogramRemap for low-effort compression mode also. + // Find the optimal map from original histograms to the final ones. + HistogramRemap(orig_histo, image_histo, histogram_symbols); + + ok = 1; + + Error: + WebPSafeFree(bin_map); + VP8LFreeHistogramSet(orig_histo); + return ok; +} diff --git a/thirdparty/libwebp/enc/histogram.h b/thirdparty/libwebp/enc/histogram.h new file mode 100644 index 0000000000..d303d1d58b --- /dev/null +++ b/thirdparty/libwebp/enc/histogram.h @@ -0,0 +1,123 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +// Models the histograms of literal and distance codes. + +#ifndef WEBP_ENC_HISTOGRAM_H_ +#define WEBP_ENC_HISTOGRAM_H_ + +#include <string.h> + +#include "./backward_references.h" +#include "../webp/format_constants.h" +#include "../webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Not a trivial literal symbol. +#define VP8L_NON_TRIVIAL_SYM (0xffffffff) + +// A simple container for histograms of data. +typedef struct { + // literal_ contains green literal, palette-code and + // copy-length-prefix histogram + uint32_t* literal_; // Pointer to the allocated buffer for literal. + uint32_t red_[NUM_LITERAL_CODES]; + uint32_t blue_[NUM_LITERAL_CODES]; + uint32_t alpha_[NUM_LITERAL_CODES]; + // Backward reference prefix-code histogram. + uint32_t distance_[NUM_DISTANCE_CODES]; + int palette_code_bits_; + uint32_t trivial_symbol_; // True, if histograms for Red, Blue & Alpha + // literal symbols are single valued. + double bit_cost_; // cached value of bit cost. + double literal_cost_; // Cached values of dominant entropy costs: + double red_cost_; // literal, red & blue. + double blue_cost_; +} VP8LHistogram; + +// Collection of histograms with fixed capacity, allocated as one +// big memory chunk. Can be destroyed by calling WebPSafeFree(). +typedef struct { + int size; // number of slots currently in use + int max_size; // maximum capacity + VP8LHistogram** histograms; +} VP8LHistogramSet; + +// Create the histogram. +// +// The input data is the PixOrCopy data, which models the literals, stop +// codes and backward references (both distances and lengths). Also: if +// palette_code_bits is >= 0, initialize the histogram with this value. +void VP8LHistogramCreate(VP8LHistogram* const p, + const VP8LBackwardRefs* const refs, + int palette_code_bits); + +// Return the size of the histogram for a given palette_code_bits. +int VP8LGetHistogramSize(int palette_code_bits); + +// Set the palette_code_bits and reset the stats. +void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits); + +// Collect all the references into a histogram (without reset) +void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs, + VP8LHistogram* const histo); + +// Free the memory allocated for the histogram. +void VP8LFreeHistogram(VP8LHistogram* const histo); + +// Free the memory allocated for the histogram set. +void VP8LFreeHistogramSet(VP8LHistogramSet* const histo); + +// Allocate an array of pointer to histograms, allocated and initialized +// using 'cache_bits'. Return NULL in case of memory error. +VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits); + +// Allocate and initialize histogram object with specified 'cache_bits'. +// Returns NULL in case of memory error. +// Special case of VP8LAllocateHistogramSet, with size equals 1. +VP8LHistogram* VP8LAllocateHistogram(int cache_bits); + +// Accumulate a token 'v' into a histogram. +void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, + const PixOrCopy* const v); + +static WEBP_INLINE int VP8LHistogramNumCodes(int palette_code_bits) { + return NUM_LITERAL_CODES + NUM_LENGTH_CODES + + ((palette_code_bits > 0) ? (1 << palette_code_bits) : 0); +} + +// Builds the histogram image. +int VP8LGetHistoImageSymbols(int xsize, int ysize, + const VP8LBackwardRefs* const refs, + int quality, int low_effort, + int histogram_bits, int cache_bits, + VP8LHistogramSet* const image_in, + VP8LHistogramSet* const tmp_histos, + uint16_t* const histogram_symbols); + +// Returns the entropy for the symbols in the input array. +// Also sets trivial_symbol to the code value, if the array has only one code +// value. Otherwise, set it to VP8L_NON_TRIVIAL_SYM. +double VP8LBitsEntropy(const uint32_t* const array, int n, + uint32_t* const trivial_symbol); + +// Estimate how many bits the combined entropy of literals and distance +// approximately maps to. +double VP8LHistogramEstimateBits(const VP8LHistogram* const p); + +#ifdef __cplusplus +} +#endif + +#endif // WEBP_ENC_HISTOGRAM_H_ diff --git a/drivers/webp/enc/iterator.c b/thirdparty/libwebp/enc/iterator.c index 99d960a547..99d960a547 100644 --- a/drivers/webp/enc/iterator.c +++ b/thirdparty/libwebp/enc/iterator.c diff --git a/drivers/webp/enc/near_lossless.c b/thirdparty/libwebp/enc/near_lossless.c index f4ab91f571..f4ab91f571 100644 --- a/drivers/webp/enc/near_lossless.c +++ b/thirdparty/libwebp/enc/near_lossless.c diff --git a/drivers/webp/enc/picture.c b/thirdparty/libwebp/enc/picture.c index d9befbc47d..d9befbc47d 100644 --- a/drivers/webp/enc/picture.c +++ b/thirdparty/libwebp/enc/picture.c diff --git a/drivers/webp/enc/picture_csp.c b/thirdparty/libwebp/enc/picture_csp.c index 607a6240b0..607a6240b0 100644 --- a/drivers/webp/enc/picture_csp.c +++ b/thirdparty/libwebp/enc/picture_csp.c diff --git a/drivers/webp/enc/picture_psnr.c b/thirdparty/libwebp/enc/picture_psnr.c index 81ab1b5ca1..81ab1b5ca1 100644 --- a/drivers/webp/enc/picture_psnr.c +++ b/thirdparty/libwebp/enc/picture_psnr.c diff --git a/drivers/webp/enc/picture_rescale.c b/thirdparty/libwebp/enc/picture_rescale.c index 9f19e8e80f..9f19e8e80f 100644 --- a/drivers/webp/enc/picture_rescale.c +++ b/thirdparty/libwebp/enc/picture_rescale.c diff --git a/drivers/webp/enc/picture_tools.c b/thirdparty/libwebp/enc/picture_tools.c index bf97af8408..bf97af8408 100644 --- a/drivers/webp/enc/picture_tools.c +++ b/thirdparty/libwebp/enc/picture_tools.c diff --git a/drivers/webp/enc/quant.c b/thirdparty/libwebp/enc/quant.c index 549ad26f93..549ad26f93 100644 --- a/drivers/webp/enc/quant.c +++ b/thirdparty/libwebp/enc/quant.c diff --git a/thirdparty/libwebp/enc/syntax.c b/thirdparty/libwebp/enc/syntax.c new file mode 100644 index 0000000000..a0e79ef404 --- /dev/null +++ b/thirdparty/libwebp/enc/syntax.c @@ -0,0 +1,383 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Header syntax writing +// +// Author: Skal (pascal.massimino@gmail.com) + +#include <assert.h> + +#include "../utils/utils.h" +#include "../webp/format_constants.h" // RIFF constants +#include "../webp/mux_types.h" // ALPHA_FLAG +#include "./vp8enci.h" + +//------------------------------------------------------------------------------ +// Helper functions + +static int IsVP8XNeeded(const VP8Encoder* const enc) { + return !!enc->has_alpha_; // Currently the only case when VP8X is needed. + // This could change in the future. +} + +static int PutPaddingByte(const WebPPicture* const pic) { + const uint8_t pad_byte[1] = { 0 }; + return !!pic->writer(pad_byte, 1, pic); +} + +//------------------------------------------------------------------------------ +// Writers for header's various pieces (in order of appearance) + +static WebPEncodingError PutRIFFHeader(const VP8Encoder* const enc, + size_t riff_size) { + const WebPPicture* const pic = enc->pic_; + uint8_t riff[RIFF_HEADER_SIZE] = { + 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P' + }; + assert(riff_size == (uint32_t)riff_size); + PutLE32(riff + TAG_SIZE, (uint32_t)riff_size); + if (!pic->writer(riff, sizeof(riff), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +static WebPEncodingError PutVP8XHeader(const VP8Encoder* const enc) { + const WebPPicture* const pic = enc->pic_; + uint8_t vp8x[CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE] = { + 'V', 'P', '8', 'X' + }; + uint32_t flags = 0; + + assert(IsVP8XNeeded(enc)); + assert(pic->width >= 1 && pic->height >= 1); + assert(pic->width <= MAX_CANVAS_SIZE && pic->height <= MAX_CANVAS_SIZE); + + if (enc->has_alpha_) { + flags |= ALPHA_FLAG; + } + + PutLE32(vp8x + TAG_SIZE, VP8X_CHUNK_SIZE); + PutLE32(vp8x + CHUNK_HEADER_SIZE, flags); + PutLE24(vp8x + CHUNK_HEADER_SIZE + 4, pic->width - 1); + PutLE24(vp8x + CHUNK_HEADER_SIZE + 7, pic->height - 1); + if (!pic->writer(vp8x, sizeof(vp8x), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +static WebPEncodingError PutAlphaChunk(const VP8Encoder* const enc) { + const WebPPicture* const pic = enc->pic_; + uint8_t alpha_chunk_hdr[CHUNK_HEADER_SIZE] = { + 'A', 'L', 'P', 'H' + }; + + assert(enc->has_alpha_); + + // Alpha chunk header. + PutLE32(alpha_chunk_hdr + TAG_SIZE, enc->alpha_data_size_); + if (!pic->writer(alpha_chunk_hdr, sizeof(alpha_chunk_hdr), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + + // Alpha chunk data. + if (!pic->writer(enc->alpha_data_, enc->alpha_data_size_, pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + + // Padding. + if ((enc->alpha_data_size_ & 1) && !PutPaddingByte(pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +static WebPEncodingError PutVP8Header(const WebPPicture* const pic, + size_t vp8_size) { + uint8_t vp8_chunk_hdr[CHUNK_HEADER_SIZE] = { + 'V', 'P', '8', ' ' + }; + assert(vp8_size == (uint32_t)vp8_size); + PutLE32(vp8_chunk_hdr + TAG_SIZE, (uint32_t)vp8_size); + if (!pic->writer(vp8_chunk_hdr, sizeof(vp8_chunk_hdr), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +static WebPEncodingError PutVP8FrameHeader(const WebPPicture* const pic, + int profile, size_t size0) { + uint8_t vp8_frm_hdr[VP8_FRAME_HEADER_SIZE]; + uint32_t bits; + + if (size0 >= VP8_MAX_PARTITION0_SIZE) { // partition #0 is too big to fit + return VP8_ENC_ERROR_PARTITION0_OVERFLOW; + } + + // Paragraph 9.1. + bits = 0 // keyframe (1b) + | (profile << 1) // profile (3b) + | (1 << 4) // visible (1b) + | ((uint32_t)size0 << 5); // partition length (19b) + vp8_frm_hdr[0] = (bits >> 0) & 0xff; + vp8_frm_hdr[1] = (bits >> 8) & 0xff; + vp8_frm_hdr[2] = (bits >> 16) & 0xff; + // signature + vp8_frm_hdr[3] = (VP8_SIGNATURE >> 16) & 0xff; + vp8_frm_hdr[4] = (VP8_SIGNATURE >> 8) & 0xff; + vp8_frm_hdr[5] = (VP8_SIGNATURE >> 0) & 0xff; + // dimensions + vp8_frm_hdr[6] = pic->width & 0xff; + vp8_frm_hdr[7] = pic->width >> 8; + vp8_frm_hdr[8] = pic->height & 0xff; + vp8_frm_hdr[9] = pic->height >> 8; + + if (!pic->writer(vp8_frm_hdr, sizeof(vp8_frm_hdr), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +// WebP Headers. +static int PutWebPHeaders(const VP8Encoder* const enc, size_t size0, + size_t vp8_size, size_t riff_size) { + WebPPicture* const pic = enc->pic_; + WebPEncodingError err = VP8_ENC_OK; + + // RIFF header. + err = PutRIFFHeader(enc, riff_size); + if (err != VP8_ENC_OK) goto Error; + + // VP8X. + if (IsVP8XNeeded(enc)) { + err = PutVP8XHeader(enc); + if (err != VP8_ENC_OK) goto Error; + } + + // Alpha. + if (enc->has_alpha_) { + err = PutAlphaChunk(enc); + if (err != VP8_ENC_OK) goto Error; + } + + // VP8 header. + err = PutVP8Header(pic, vp8_size); + if (err != VP8_ENC_OK) goto Error; + + // VP8 frame header. + err = PutVP8FrameHeader(pic, enc->profile_, size0); + if (err != VP8_ENC_OK) goto Error; + + // All OK. + return 1; + + // Error. + Error: + return WebPEncodingSetError(pic, err); +} + +// Segmentation header +static void PutSegmentHeader(VP8BitWriter* const bw, + const VP8Encoder* const enc) { + const VP8EncSegmentHeader* const hdr = &enc->segment_hdr_; + const VP8EncProba* const proba = &enc->proba_; + if (VP8PutBitUniform(bw, (hdr->num_segments_ > 1))) { + // We always 'update' the quant and filter strength values + const int update_data = 1; + int s; + VP8PutBitUniform(bw, hdr->update_map_); + if (VP8PutBitUniform(bw, update_data)) { + // we always use absolute values, not relative ones + VP8PutBitUniform(bw, 1); // (segment_feature_mode = 1. Paragraph 9.3.) + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + VP8PutSignedBits(bw, enc->dqm_[s].quant_, 7); + } + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + VP8PutSignedBits(bw, enc->dqm_[s].fstrength_, 6); + } + } + if (hdr->update_map_) { + for (s = 0; s < 3; ++s) { + if (VP8PutBitUniform(bw, (proba->segments_[s] != 255u))) { + VP8PutBits(bw, proba->segments_[s], 8); + } + } + } + } +} + +// Filtering parameters header +static void PutFilterHeader(VP8BitWriter* const bw, + const VP8EncFilterHeader* const hdr) { + const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0); + VP8PutBitUniform(bw, hdr->simple_); + VP8PutBits(bw, hdr->level_, 6); + VP8PutBits(bw, hdr->sharpness_, 3); + if (VP8PutBitUniform(bw, use_lf_delta)) { + // '0' is the default value for i4x4_lf_delta_ at frame #0. + const int need_update = (hdr->i4x4_lf_delta_ != 0); + if (VP8PutBitUniform(bw, need_update)) { + // we don't use ref_lf_delta => emit four 0 bits + VP8PutBits(bw, 0, 4); + // we use mode_lf_delta for i4x4 + VP8PutSignedBits(bw, hdr->i4x4_lf_delta_, 6); + VP8PutBits(bw, 0, 3); // all others unused + } + } +} + +// Nominal quantization parameters +static void PutQuant(VP8BitWriter* const bw, + const VP8Encoder* const enc) { + VP8PutBits(bw, enc->base_quant_, 7); + VP8PutSignedBits(bw, enc->dq_y1_dc_, 4); + VP8PutSignedBits(bw, enc->dq_y2_dc_, 4); + VP8PutSignedBits(bw, enc->dq_y2_ac_, 4); + VP8PutSignedBits(bw, enc->dq_uv_dc_, 4); + VP8PutSignedBits(bw, enc->dq_uv_ac_, 4); +} + +// Partition sizes +static int EmitPartitionsSize(const VP8Encoder* const enc, + WebPPicture* const pic) { + uint8_t buf[3 * (MAX_NUM_PARTITIONS - 1)]; + int p; + for (p = 0; p < enc->num_parts_ - 1; ++p) { + const size_t part_size = VP8BitWriterSize(enc->parts_ + p); + if (part_size >= VP8_MAX_PARTITION_SIZE) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_PARTITION_OVERFLOW); + } + buf[3 * p + 0] = (part_size >> 0) & 0xff; + buf[3 * p + 1] = (part_size >> 8) & 0xff; + buf[3 * p + 2] = (part_size >> 16) & 0xff; + } + return p ? pic->writer(buf, 3 * p, pic) : 1; +} + +//------------------------------------------------------------------------------ + +static int GeneratePartition0(VP8Encoder* const enc) { + VP8BitWriter* const bw = &enc->bw_; + const int mb_size = enc->mb_w_ * enc->mb_h_; + uint64_t pos1, pos2, pos3; + + pos1 = VP8BitWriterPos(bw); + if (!VP8BitWriterInit(bw, mb_size * 7 / 8)) { // ~7 bits per macroblock + return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + VP8PutBitUniform(bw, 0); // colorspace + VP8PutBitUniform(bw, 0); // clamp type + + PutSegmentHeader(bw, enc); + PutFilterHeader(bw, &enc->filter_hdr_); + VP8PutBits(bw, enc->num_parts_ == 8 ? 3 : + enc->num_parts_ == 4 ? 2 : + enc->num_parts_ == 2 ? 1 : 0, 2); + PutQuant(bw, enc); + VP8PutBitUniform(bw, 0); // no proba update + VP8WriteProbas(bw, &enc->proba_); + pos2 = VP8BitWriterPos(bw); + VP8CodeIntraModes(enc); + VP8BitWriterFinish(bw); + + pos3 = VP8BitWriterPos(bw); + + if (enc->pic_->stats) { + enc->pic_->stats->header_bytes[0] = (int)((pos2 - pos1 + 7) >> 3); + enc->pic_->stats->header_bytes[1] = (int)((pos3 - pos2 + 7) >> 3); + enc->pic_->stats->alpha_data_size = (int)enc->alpha_data_size_; + } + if (bw->error_) { + return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + return 1; +} + +void VP8EncFreeBitWriters(VP8Encoder* const enc) { + int p; + VP8BitWriterWipeOut(&enc->bw_); + for (p = 0; p < enc->num_parts_; ++p) { + VP8BitWriterWipeOut(enc->parts_ + p); + } +} + +int VP8EncWrite(VP8Encoder* const enc) { + WebPPicture* const pic = enc->pic_; + VP8BitWriter* const bw = &enc->bw_; + const int task_percent = 19; + const int percent_per_part = task_percent / enc->num_parts_; + const int final_percent = enc->percent_ + task_percent; + int ok = 0; + size_t vp8_size, pad, riff_size; + int p; + + // Partition #0 with header and partition sizes + ok = GeneratePartition0(enc); + if (!ok) return 0; + + // Compute VP8 size + vp8_size = VP8_FRAME_HEADER_SIZE + + VP8BitWriterSize(bw) + + 3 * (enc->num_parts_ - 1); + for (p = 0; p < enc->num_parts_; ++p) { + vp8_size += VP8BitWriterSize(enc->parts_ + p); + } + pad = vp8_size & 1; + vp8_size += pad; + + // Compute RIFF size + // At the minimum it is: "WEBPVP8 nnnn" + VP8 data size. + riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8_size; + if (IsVP8XNeeded(enc)) { // Add size for: VP8X header + data. + riff_size += CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; + } + if (enc->has_alpha_) { // Add size for: ALPH header + data. + const uint32_t padded_alpha_size = enc->alpha_data_size_ + + (enc->alpha_data_size_ & 1); + riff_size += CHUNK_HEADER_SIZE + padded_alpha_size; + } + // Sanity check. + if (riff_size > 0xfffffffeU) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_FILE_TOO_BIG); + } + + // Emit headers and partition #0 + { + const uint8_t* const part0 = VP8BitWriterBuf(bw); + const size_t size0 = VP8BitWriterSize(bw); + ok = ok && PutWebPHeaders(enc, size0, vp8_size, riff_size) + && pic->writer(part0, size0, pic) + && EmitPartitionsSize(enc, pic); + VP8BitWriterWipeOut(bw); // will free the internal buffer. + } + + // Token partitions + for (p = 0; p < enc->num_parts_; ++p) { + const uint8_t* const buf = VP8BitWriterBuf(enc->parts_ + p); + const size_t size = VP8BitWriterSize(enc->parts_ + p); + if (size) + ok = ok && pic->writer(buf, size, pic); + VP8BitWriterWipeOut(enc->parts_ + p); // will free the internal buffer. + ok = ok && WebPReportProgress(pic, enc->percent_ + percent_per_part, + &enc->percent_); + } + + // Padding byte + if (ok && pad) { + ok = PutPaddingByte(pic); + } + + enc->coded_size_ = (int)(CHUNK_HEADER_SIZE + riff_size); + ok = ok && WebPReportProgress(pic, final_percent, &enc->percent_); + return ok; +} + +//------------------------------------------------------------------------------ + diff --git a/drivers/webp/enc/token.c b/thirdparty/libwebp/enc/token.c index e73256b37e..e73256b37e 100644 --- a/drivers/webp/enc/token.c +++ b/thirdparty/libwebp/enc/token.c diff --git a/drivers/webp/enc/tree.c b/thirdparty/libwebp/enc/tree.c index f141006d19..f141006d19 100644 --- a/drivers/webp/enc/tree.c +++ b/thirdparty/libwebp/enc/tree.c diff --git a/thirdparty/libwebp/enc/vp8enci.h b/thirdparty/libwebp/enc/vp8enci.h new file mode 100644 index 0000000000..c1fbd7644e --- /dev/null +++ b/thirdparty/libwebp/enc/vp8enci.h @@ -0,0 +1,531 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP encoder: internal header. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_ENC_VP8ENCI_H_ +#define WEBP_ENC_VP8ENCI_H_ + +#include <string.h> // for memcpy() +#include "../dec/common.h" +#include "../dsp/dsp.h" +#include "../utils/bit_writer.h" +#include "../utils/thread.h" +#include "../utils/utils.h" +#include "../webp/encode.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Various defines and enums + +// version numbers +#define ENC_MAJ_VERSION 0 +#define ENC_MIN_VERSION 5 +#define ENC_REV_VERSION 1 + +enum { MAX_LF_LEVELS = 64, // Maximum loop filter level + MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost + MAX_LEVEL = 2047 // max level (note: max codable is 2047 + 67) + }; + +typedef enum { // Rate-distortion optimization levels + RD_OPT_NONE = 0, // no rd-opt + RD_OPT_BASIC = 1, // basic scoring (no trellis) + RD_OPT_TRELLIS = 2, // perform trellis-quant on the final decision only + RD_OPT_TRELLIS_ALL = 3 // trellis-quant for every scoring (much slower) +} VP8RDLevel; + +// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). +// The original or reconstructed samples can be accessed using VP8Scan[]. +// The predicted blocks can be accessed using offsets to yuv_p_ and +// the arrays VP8*ModeOffsets[]. +// * YUV Samples area (yuv_in_/yuv_out_/yuv_out2_) +// (see VP8Scan[] for accessing the blocks, along with +// Y_OFF_ENC/U_OFF_ENC/V_OFF_ENC): +// +----+----+ +// Y_OFF_ENC |YYYY|UUVV| +// U_OFF_ENC |YYYY|UUVV| +// V_OFF_ENC |YYYY|....| <- 25% wasted U/V area +// |YYYY|....| +// +----+----+ +// * Prediction area ('yuv_p_', size = PRED_SIZE_ENC) +// Intra16 predictions (16x16 block each, two per row): +// |I16DC16|I16TM16| +// |I16VE16|I16HE16| +// Chroma U/V predictions (16x8 block each, two per row): +// |C8DC8|C8TM8| +// |C8VE8|C8HE8| +// Intra 4x4 predictions (4x4 block each) +// |I4DC4 I4TM4 I4VE4 I4HE4|I4RD4 I4VR4 I4LD4 I4VL4| +// |I4HD4 I4HU4 I4TMP .....|.......................| <- ~31% wasted +#define YUV_SIZE_ENC (BPS * 16) +#define PRED_SIZE_ENC (32 * BPS + 16 * BPS + 8 * BPS) // I16+Chroma+I4 preds +#define Y_OFF_ENC (0) +#define U_OFF_ENC (16) +#define V_OFF_ENC (16 + 8) + +extern const int VP8Scan[16]; // in quant.c +extern const int VP8UVModeOffsets[4]; // in analyze.c +extern const int VP8I16ModeOffsets[4]; +extern const int VP8I4ModeOffsets[NUM_BMODES]; + +// Layout of prediction blocks +// intra 16x16 +#define I16DC16 (0 * 16 * BPS) +#define I16TM16 (I16DC16 + 16) +#define I16VE16 (1 * 16 * BPS) +#define I16HE16 (I16VE16 + 16) +// chroma 8x8, two U/V blocks side by side (hence: 16x8 each) +#define C8DC8 (2 * 16 * BPS) +#define C8TM8 (C8DC8 + 1 * 16) +#define C8VE8 (2 * 16 * BPS + 8 * BPS) +#define C8HE8 (C8VE8 + 1 * 16) +// intra 4x4 +#define I4DC4 (3 * 16 * BPS + 0) +#define I4TM4 (I4DC4 + 4) +#define I4VE4 (I4DC4 + 8) +#define I4HE4 (I4DC4 + 12) +#define I4RD4 (I4DC4 + 16) +#define I4VR4 (I4DC4 + 20) +#define I4LD4 (I4DC4 + 24) +#define I4VL4 (I4DC4 + 28) +#define I4HD4 (3 * 16 * BPS + 4 * BPS) +#define I4HU4 (I4HD4 + 4) +#define I4TMP (I4HD4 + 8) + +typedef int64_t score_t; // type used for scores, rate, distortion +// Note that MAX_COST is not the maximum allowed by sizeof(score_t), +// in order to allow overflowing computations. +#define MAX_COST ((score_t)0x7fffffffffffffLL) + +#define QFIX 17 +#define BIAS(b) ((b) << (QFIX - 8)) +// Fun fact: this is the _only_ line where we're actually being lossy and +// discarding bits. +static WEBP_INLINE int QUANTDIV(uint32_t n, uint32_t iQ, uint32_t B) { + return (int)((n * iQ + B) >> QFIX); +} + +// Uncomment the following to remove token-buffer code: +// #define DISABLE_TOKEN_BUFFER + +//------------------------------------------------------------------------------ +// Headers + +typedef uint32_t proba_t; // 16b + 16b +typedef uint8_t ProbaArray[NUM_CTX][NUM_PROBAS]; +typedef proba_t StatsArray[NUM_CTX][NUM_PROBAS]; +typedef uint16_t CostArray[NUM_CTX][MAX_VARIABLE_LEVEL + 1]; +typedef const uint16_t* (*CostArrayPtr)[NUM_CTX]; // for easy casting +typedef const uint16_t* CostArrayMap[16][NUM_CTX]; +typedef double LFStats[NUM_MB_SEGMENTS][MAX_LF_LEVELS]; // filter stats + +typedef struct VP8Encoder VP8Encoder; + +// segment features +typedef struct { + int num_segments_; // Actual number of segments. 1 segment only = unused. + int update_map_; // whether to update the segment map or not. + // must be 0 if there's only 1 segment. + int size_; // bit-cost for transmitting the segment map +} VP8EncSegmentHeader; + +// Struct collecting all frame-persistent probabilities. +typedef struct { + uint8_t segments_[3]; // probabilities for segment tree + uint8_t skip_proba_; // final probability of being skipped. + ProbaArray coeffs_[NUM_TYPES][NUM_BANDS]; // 1056 bytes + StatsArray stats_[NUM_TYPES][NUM_BANDS]; // 4224 bytes + CostArray level_cost_[NUM_TYPES][NUM_BANDS]; // 13056 bytes + CostArrayMap remapped_costs_[NUM_TYPES]; // 1536 bytes + int dirty_; // if true, need to call VP8CalculateLevelCosts() + int use_skip_proba_; // Note: we always use skip_proba for now. + int nb_skip_; // number of skipped blocks +} VP8EncProba; + +// Filter parameters. Not actually used in the code (we don't perform +// the in-loop filtering), but filled from user's config +typedef struct { + int simple_; // filtering type: 0=complex, 1=simple + int level_; // base filter level [0..63] + int sharpness_; // [0..7] + int i4x4_lf_delta_; // delta filter level for i4x4 relative to i16x16 +} VP8EncFilterHeader; + +//------------------------------------------------------------------------------ +// Informations about the macroblocks. + +typedef struct { + // block type + unsigned int type_:2; // 0=i4x4, 1=i16x16 + unsigned int uv_mode_:2; + unsigned int skip_:1; + unsigned int segment_:2; + uint8_t alpha_; // quantization-susceptibility +} VP8MBInfo; + +typedef struct VP8Matrix { + uint16_t q_[16]; // quantizer steps + uint16_t iq_[16]; // reciprocals, fixed point. + uint32_t bias_[16]; // rounding bias + uint32_t zthresh_[16]; // value below which a coefficient is zeroed + uint16_t sharpen_[16]; // frequency boosters for slight sharpening +} VP8Matrix; + +typedef struct { + VP8Matrix y1_, y2_, uv_; // quantization matrices + int alpha_; // quant-susceptibility, range [-127,127]. Zero is neutral. + // Lower values indicate a lower risk of blurriness. + int beta_; // filter-susceptibility, range [0,255]. + int quant_; // final segment quantizer. + int fstrength_; // final in-loop filtering strength + int max_edge_; // max edge delta (for filtering strength) + int min_disto_; // minimum distortion required to trigger filtering record + // reactivities + int lambda_i16_, lambda_i4_, lambda_uv_; + int lambda_mode_, lambda_trellis_, tlambda_; + int lambda_trellis_i16_, lambda_trellis_i4_, lambda_trellis_uv_; + + // lambda values for distortion-based evaluation + score_t i4_penalty_; // penalty for using Intra4 +} VP8SegmentInfo; + +// Handy transient struct to accumulate score and info during RD-optimization +// and mode evaluation. +typedef struct { + score_t D, SD; // Distortion, spectral distortion + score_t H, R, score; // header bits, rate, score. + int16_t y_dc_levels[16]; // Quantized levels for luma-DC, luma-AC, chroma. + int16_t y_ac_levels[16][16]; + int16_t uv_levels[4 + 4][16]; + int mode_i16; // mode number for intra16 prediction + uint8_t modes_i4[16]; // mode numbers for intra4 predictions + int mode_uv; // mode number of chroma prediction + uint32_t nz; // non-zero blocks +} VP8ModeScore; + +// Iterator structure to iterate through macroblocks, pointing to the +// right neighbouring data (samples, predictions, contexts, ...) +typedef struct { + int x_, y_; // current macroblock + int y_stride_, uv_stride_; // respective strides + uint8_t* yuv_in_; // input samples + uint8_t* yuv_out_; // output samples + uint8_t* yuv_out2_; // secondary buffer swapped with yuv_out_. + uint8_t* yuv_p_; // scratch buffer for prediction + VP8Encoder* enc_; // back-pointer + VP8MBInfo* mb_; // current macroblock + VP8BitWriter* bw_; // current bit-writer + uint8_t* preds_; // intra mode predictors (4x4 blocks) + uint32_t* nz_; // non-zero pattern + uint8_t i4_boundary_[37]; // 32+5 boundary samples needed by intra4x4 + uint8_t* i4_top_; // pointer to the current top boundary sample + int i4_; // current intra4x4 mode being tested + int top_nz_[9]; // top-non-zero context. + int left_nz_[9]; // left-non-zero. left_nz[8] is independent. + uint64_t bit_count_[4][3]; // bit counters for coded levels. + uint64_t luma_bits_; // macroblock bit-cost for luma + uint64_t uv_bits_; // macroblock bit-cost for chroma + LFStats* lf_stats_; // filter stats (borrowed from enc_) + int do_trellis_; // if true, perform extra level optimisation + int count_down_; // number of mb still to be processed + int count_down0_; // starting counter value (for progress) + int percent0_; // saved initial progress percent + + uint8_t* y_left_; // left luma samples (addressable from index -1 to 15). + uint8_t* u_left_; // left u samples (addressable from index -1 to 7) + uint8_t* v_left_; // left v samples (addressable from index -1 to 7) + + uint8_t* y_top_; // top luma samples at position 'x_' + uint8_t* uv_top_; // top u/v samples at position 'x_', packed as 16 bytes + + // memory for storing y/u/v_left_ + uint8_t yuv_left_mem_[17 + 16 + 16 + 8 + WEBP_ALIGN_CST]; + // memory for yuv_* + uint8_t yuv_mem_[3 * YUV_SIZE_ENC + PRED_SIZE_ENC + WEBP_ALIGN_CST]; +} VP8EncIterator; + + // in iterator.c +// must be called first +void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it); +// restart a scan +void VP8IteratorReset(VP8EncIterator* const it); +// reset iterator position to row 'y' +void VP8IteratorSetRow(VP8EncIterator* const it, int y); +// set count down (=number of iterations to go) +void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down); +// return true if iteration is finished +int VP8IteratorIsDone(const VP8EncIterator* const it); +// Import uncompressed samples from source. +// If tmp_32 is not NULL, import boundary samples too. +// tmp_32 is a 32-bytes scratch buffer that must be aligned in memory. +void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32); +// export decimated samples +void VP8IteratorExport(const VP8EncIterator* const it); +// go to next macroblock. Returns false if not finished. +int VP8IteratorNext(VP8EncIterator* const it); +// save the yuv_out_ boundary values to top_/left_ arrays for next iterations. +void VP8IteratorSaveBoundary(VP8EncIterator* const it); +// Report progression based on macroblock rows. Return 0 for user-abort request. +int VP8IteratorProgress(const VP8EncIterator* const it, + int final_delta_percent); +// Intra4x4 iterations +void VP8IteratorStartI4(VP8EncIterator* const it); +// returns true if not done. +int VP8IteratorRotateI4(VP8EncIterator* const it, + const uint8_t* const yuv_out); + +// Non-zero context setup/teardown +void VP8IteratorNzToBytes(VP8EncIterator* const it); +void VP8IteratorBytesToNz(VP8EncIterator* const it); + +// Helper functions to set mode properties +void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode); +void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes); +void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode); +void VP8SetSkip(const VP8EncIterator* const it, int skip); +void VP8SetSegment(const VP8EncIterator* const it, int segment); + +//------------------------------------------------------------------------------ +// Paginated token buffer + +typedef struct VP8Tokens VP8Tokens; // struct details in token.c + +typedef struct { +#if !defined(DISABLE_TOKEN_BUFFER) + VP8Tokens* pages_; // first page + VP8Tokens** last_page_; // last page + uint16_t* tokens_; // set to (*last_page_)->tokens_ + int left_; // how many free tokens left before the page is full + int page_size_; // number of tokens per page +#endif + int error_; // true in case of malloc error +} VP8TBuffer; + +// initialize an empty buffer +void VP8TBufferInit(VP8TBuffer* const b, int page_size); +void VP8TBufferClear(VP8TBuffer* const b); // de-allocate pages memory + +#if !defined(DISABLE_TOKEN_BUFFER) + +// Finalizes bitstream when probabilities are known. +// Deletes the allocated token memory if final_pass is true. +int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw, + const uint8_t* const probas, int final_pass); + +// record the coding of coefficients without knowing the probabilities yet +int VP8RecordCoeffTokens(const int ctx, const int coeff_type, + int first, int last, + const int16_t* const coeffs, + VP8TBuffer* const tokens); + +// Estimate the final coded size given a set of 'probas'. +size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas); + +// unused for now +void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats); + +#endif // !DISABLE_TOKEN_BUFFER + +//------------------------------------------------------------------------------ +// VP8Encoder + +struct VP8Encoder { + const WebPConfig* config_; // user configuration and parameters + WebPPicture* pic_; // input / output picture + + // headers + VP8EncFilterHeader filter_hdr_; // filtering information + VP8EncSegmentHeader segment_hdr_; // segment information + + int profile_; // VP8's profile, deduced from Config. + + // dimension, in macroblock units. + int mb_w_, mb_h_; + int preds_w_; // stride of the *preds_ prediction plane (=4*mb_w + 1) + + // number of partitions (1, 2, 4 or 8 = MAX_NUM_PARTITIONS) + int num_parts_; + + // per-partition boolean decoders. + VP8BitWriter bw_; // part0 + VP8BitWriter parts_[MAX_NUM_PARTITIONS]; // token partitions + VP8TBuffer tokens_; // token buffer + + int percent_; // for progress + + // transparency blob + int has_alpha_; + uint8_t* alpha_data_; // non-NULL if transparency is present + uint32_t alpha_data_size_; + WebPWorker alpha_worker_; + + // quantization info (one set of DC/AC dequant factor per segment) + VP8SegmentInfo dqm_[NUM_MB_SEGMENTS]; + int base_quant_; // nominal quantizer value. Only used + // for relative coding of segments' quant. + int alpha_; // global susceptibility (<=> complexity) + int uv_alpha_; // U/V quantization susceptibility + // global offset of quantizers, shared by all segments + int dq_y1_dc_; + int dq_y2_dc_, dq_y2_ac_; + int dq_uv_dc_, dq_uv_ac_; + + // probabilities and statistics + VP8EncProba proba_; + uint64_t sse_[4]; // sum of Y/U/V/A squared errors for all macroblocks + uint64_t sse_count_; // pixel count for the sse_[] stats + int coded_size_; + int residual_bytes_[3][4]; + int block_count_[3]; + + // quality/speed settings + int method_; // 0=fastest, 6=best/slowest. + VP8RDLevel rd_opt_level_; // Deduced from method_. + int max_i4_header_bits_; // partition #0 safeness factor + int mb_header_limit_; // rough limit for header bits per MB + int thread_level_; // derived from config->thread_level + int do_search_; // derived from config->target_XXX + int use_tokens_; // if true, use token buffer + + // Memory + VP8MBInfo* mb_info_; // contextual macroblock infos (mb_w_ + 1) + uint8_t* preds_; // predictions modes: (4*mb_w+1) * (4*mb_h+1) + uint32_t* nz_; // non-zero bit context: mb_w+1 + uint8_t* y_top_; // top luma samples. + uint8_t* uv_top_; // top u/v samples. + // U and V are packed into 16 bytes (8 U + 8 V) + LFStats* lf_stats_; // autofilter stats (if NULL, autofilter is off) +}; + +//------------------------------------------------------------------------------ +// internal functions. Not public. + + // in tree.c +extern const uint8_t VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS]; +extern const uint8_t + VP8CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS]; +// Reset the token probabilities to their initial (default) values +void VP8DefaultProbas(VP8Encoder* const enc); +// Write the token probabilities +void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas); +// Writes the partition #0 modes (that is: all intra modes) +void VP8CodeIntraModes(VP8Encoder* const enc); + + // in syntax.c +// Generates the final bitstream by coding the partition0 and headers, +// and appending an assembly of all the pre-coded token partitions. +// Return true if everything is ok. +int VP8EncWrite(VP8Encoder* const enc); +// Release memory allocated for bit-writing in VP8EncLoop & seq. +void VP8EncFreeBitWriters(VP8Encoder* const enc); + + // in frame.c +extern const uint8_t VP8Cat3[]; +extern const uint8_t VP8Cat4[]; +extern const uint8_t VP8Cat5[]; +extern const uint8_t VP8Cat6[]; + +// Form all the four Intra16x16 predictions in the yuv_p_ cache +void VP8MakeLuma16Preds(const VP8EncIterator* const it); +// Form all the four Chroma8x8 predictions in the yuv_p_ cache +void VP8MakeChroma8Preds(const VP8EncIterator* const it); +// Form all the ten Intra4x4 predictions in the yuv_p_ cache +// for the 4x4 block it->i4_ +void VP8MakeIntra4Preds(const VP8EncIterator* const it); +// Rate calculation +int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd); +int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]); +int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd); +// Main coding calls +int VP8EncLoop(VP8Encoder* const enc); +int VP8EncTokenLoop(VP8Encoder* const enc); + + // in webpenc.c +// Assign an error code to a picture. Return false for convenience. +int WebPEncodingSetError(const WebPPicture* const pic, WebPEncodingError error); +int WebPReportProgress(const WebPPicture* const pic, + int percent, int* const percent_store); + + // in analysis.c +// Main analysis loop. Decides the segmentations and complexity. +// Assigns a first guess for Intra16 and uvmode_ prediction modes. +int VP8EncAnalyze(VP8Encoder* const enc); + + // in quant.c +// Sets up segment's quantization values, base_quant_ and filter strengths. +void VP8SetSegmentParams(VP8Encoder* const enc, float quality); +// Pick best modes and fills the levels. Returns true if skipped. +int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, + VP8RDLevel rd_opt); + + // in alpha.c +void VP8EncInitAlpha(VP8Encoder* const enc); // initialize alpha compression +int VP8EncStartAlpha(VP8Encoder* const enc); // start alpha coding process +int VP8EncFinishAlpha(VP8Encoder* const enc); // finalize compressed data +int VP8EncDeleteAlpha(VP8Encoder* const enc); // delete compressed data + + // in filter.c +void VP8SSIMAddStats(const VP8DistoStats* const src, VP8DistoStats* const dst); +void VP8SSIMAccumulatePlane(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2, + int W, int H, VP8DistoStats* const stats); +double VP8SSIMGet(const VP8DistoStats* const stats); +double VP8SSIMGetSquaredError(const VP8DistoStats* const stats); + +// autofilter +void VP8InitFilter(VP8EncIterator* const it); +void VP8StoreFilterStats(VP8EncIterator* const it); +void VP8AdjustFilterStrength(VP8EncIterator* const it); + +// returns the approximate filtering strength needed to smooth a edge +// step of 'delta', given a sharpness parameter 'sharpness'. +int VP8FilterStrengthFromDelta(int sharpness, int delta); + + // misc utils for picture_*.c: + +// Remove reference to the ARGB/YUVA buffer (doesn't free anything). +void WebPPictureResetBuffers(WebPPicture* const picture); + +// Allocates ARGB buffer of given dimension (previous one is always free'd). +// Preserves the YUV(A) buffer. Returns false in case of error (invalid param, +// out-of-memory). +int WebPPictureAllocARGB(WebPPicture* const picture, int width, int height); + +// Allocates YUVA buffer of given dimension (previous one is always free'd). +// Uses picture->csp to determine whether an alpha buffer is needed. +// Preserves the ARGB buffer. +// Returns false in case of error (invalid param, out-of-memory). +int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height); + +// Clean-up the RGB samples under fully transparent area, to help lossless +// compressibility (no guarantee, though). Assumes that pic->use_argb is true. +void WebPCleanupTransparentAreaLossless(WebPPicture* const pic); + + // in near_lossless.c +// Near lossless preprocessing in RGB color-space. +int VP8ApplyNearLossless(int xsize, int ysize, uint32_t* argb, int quality); +// Near lossless adjustment for predictors. +void VP8ApplyNearLosslessPredict(int xsize, int ysize, int pred_bits, + const uint32_t* argb_orig, + uint32_t* argb, uint32_t* argb_scratch, + const uint32_t* const transform_data, + int quality, int subtract_green); +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_ENC_VP8ENCI_H_ */ diff --git a/thirdparty/libwebp/enc/vp8l.c b/thirdparty/libwebp/enc/vp8l.c new file mode 100644 index 0000000000..c16e2560ec --- /dev/null +++ b/thirdparty/libwebp/enc/vp8l.c @@ -0,0 +1,1603 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// main entry for the lossless encoder. +// +// Author: Vikas Arora (vikaas.arora@gmail.com) +// + +#include <assert.h> +#include <stdlib.h> + +#include "./backward_references.h" +#include "./histogram.h" +#include "./vp8enci.h" +#include "./vp8li.h" +#include "../dsp/lossless.h" +#include "../utils/bit_writer.h" +#include "../utils/huffman_encode.h" +#include "../utils/utils.h" +#include "../webp/format_constants.h" + +#include "./delta_palettization.h" + +#define PALETTE_KEY_RIGHT_SHIFT 22 // Key for 1K buffer. +// Maximum number of histogram images (sub-blocks). +#define MAX_HUFF_IMAGE_SIZE 2600 + +// Palette reordering for smaller sum of deltas (and for smaller storage). + +static int PaletteCompareColorsForQsort(const void* p1, const void* p2) { + const uint32_t a = WebPMemToUint32(p1); + const uint32_t b = WebPMemToUint32(p2); + assert(a != b); + return (a < b) ? -1 : 1; +} + +static WEBP_INLINE uint32_t PaletteComponentDistance(uint32_t v) { + return (v <= 128) ? v : (256 - v); +} + +// Computes a value that is related to the entropy created by the +// palette entry diff. +// +// Note that the last & 0xff is a no-operation in the next statement, but +// removed by most compilers and is here only for regularity of the code. +static WEBP_INLINE uint32_t PaletteColorDistance(uint32_t col1, uint32_t col2) { + const uint32_t diff = VP8LSubPixels(col1, col2); + const int kMoreWeightForRGBThanForAlpha = 9; + uint32_t score; + score = PaletteComponentDistance((diff >> 0) & 0xff); + score += PaletteComponentDistance((diff >> 8) & 0xff); + score += PaletteComponentDistance((diff >> 16) & 0xff); + score *= kMoreWeightForRGBThanForAlpha; + score += PaletteComponentDistance((diff >> 24) & 0xff); + return score; +} + +static WEBP_INLINE void SwapColor(uint32_t* const col1, uint32_t* const col2) { + const uint32_t tmp = *col1; + *col1 = *col2; + *col2 = tmp; +} + +static void GreedyMinimizeDeltas(uint32_t palette[], int num_colors) { + // Find greedily always the closest color of the predicted color to minimize + // deltas in the palette. This reduces storage needs since the + // palette is stored with delta encoding. + uint32_t predict = 0x00000000; + int i, k; + for (i = 0; i < num_colors; ++i) { + int best_ix = i; + uint32_t best_score = ~0U; + for (k = i; k < num_colors; ++k) { + const uint32_t cur_score = PaletteColorDistance(palette[k], predict); + if (best_score > cur_score) { + best_score = cur_score; + best_ix = k; + } + } + SwapColor(&palette[best_ix], &palette[i]); + predict = palette[i]; + } +} + +// The palette has been sorted by alpha. This function checks if the other +// components of the palette have a monotonic development with regards to +// position in the palette. If all have monotonic development, there is +// no benefit to re-organize them greedily. A monotonic development +// would be spotted in green-only situations (like lossy alpha) or gray-scale +// images. +static int PaletteHasNonMonotonousDeltas(uint32_t palette[], int num_colors) { + uint32_t predict = 0x000000; + int i; + uint8_t sign_found = 0x00; + for (i = 0; i < num_colors; ++i) { + const uint32_t diff = VP8LSubPixels(palette[i], predict); + const uint8_t rd = (diff >> 16) & 0xff; + const uint8_t gd = (diff >> 8) & 0xff; + const uint8_t bd = (diff >> 0) & 0xff; + if (rd != 0x00) { + sign_found |= (rd < 0x80) ? 1 : 2; + } + if (gd != 0x00) { + sign_found |= (gd < 0x80) ? 8 : 16; + } + if (bd != 0x00) { + sign_found |= (bd < 0x80) ? 64 : 128; + } + predict = palette[i]; + } + return (sign_found & (sign_found << 1)) != 0; // two consequent signs. +} + +// ----------------------------------------------------------------------------- +// Palette + +// If number of colors in the image is less than or equal to MAX_PALETTE_SIZE, +// creates a palette and returns true, else returns false. +static int AnalyzeAndCreatePalette(const WebPPicture* const pic, + int low_effort, + uint32_t palette[MAX_PALETTE_SIZE], + int* const palette_size) { + const int num_colors = WebPGetColorPalette(pic, palette); + if (num_colors > MAX_PALETTE_SIZE) return 0; + *palette_size = num_colors; + qsort(palette, num_colors, sizeof(*palette), PaletteCompareColorsForQsort); + if (!low_effort && PaletteHasNonMonotonousDeltas(palette, num_colors)) { + GreedyMinimizeDeltas(palette, num_colors); + } + return 1; +} + +// These five modes are evaluated and their respective entropy is computed. +typedef enum { + kDirect = 0, + kSpatial = 1, + kSubGreen = 2, + kSpatialSubGreen = 3, + kPalette = 4, + kNumEntropyIx = 5 +} EntropyIx; + +typedef enum { + kHistoAlpha = 0, + kHistoAlphaPred, + kHistoGreen, + kHistoGreenPred, + kHistoRed, + kHistoRedPred, + kHistoBlue, + kHistoBluePred, + kHistoRedSubGreen, + kHistoRedPredSubGreen, + kHistoBlueSubGreen, + kHistoBluePredSubGreen, + kHistoPalette, + kHistoTotal // Must be last. +} HistoIx; + +static void AddSingleSubGreen(uint32_t p, uint32_t* r, uint32_t* b) { + const uint32_t green = p >> 8; // The upper bits are masked away later. + ++r[((p >> 16) - green) & 0xff]; + ++b[(p - green) & 0xff]; +} + +static void AddSingle(uint32_t p, + uint32_t* a, uint32_t* r, uint32_t* g, uint32_t* b) { + ++a[p >> 24]; + ++r[(p >> 16) & 0xff]; + ++g[(p >> 8) & 0xff]; + ++b[(p & 0xff)]; +} + +static int AnalyzeEntropy(const uint32_t* argb, + int width, int height, int argb_stride, + int use_palette, + EntropyIx* const min_entropy_ix, + int* const red_and_blue_always_zero) { + // Allocate histogram set with cache_bits = 0. + uint32_t* const histo = + (uint32_t*)WebPSafeCalloc(kHistoTotal, sizeof(*histo) * 256); + if (histo != NULL) { + int i, x, y; + const uint32_t* prev_row = argb; + const uint32_t* curr_row = argb + argb_stride; + for (y = 1; y < height; ++y) { + uint32_t prev_pix = curr_row[0]; + for (x = 1; x < width; ++x) { + const uint32_t pix = curr_row[x]; + const uint32_t pix_diff = VP8LSubPixels(pix, prev_pix); + if ((pix_diff == 0) || (pix == prev_row[x])) continue; + prev_pix = pix; + AddSingle(pix, + &histo[kHistoAlpha * 256], + &histo[kHistoRed * 256], + &histo[kHistoGreen * 256], + &histo[kHistoBlue * 256]); + AddSingle(pix_diff, + &histo[kHistoAlphaPred * 256], + &histo[kHistoRedPred * 256], + &histo[kHistoGreenPred * 256], + &histo[kHistoBluePred * 256]); + AddSingleSubGreen(pix, + &histo[kHistoRedSubGreen * 256], + &histo[kHistoBlueSubGreen * 256]); + AddSingleSubGreen(pix_diff, + &histo[kHistoRedPredSubGreen * 256], + &histo[kHistoBluePredSubGreen * 256]); + { + // Approximate the palette by the entropy of the multiplicative hash. + const int hash = ((pix + (pix >> 19)) * 0x39c5fba7) >> 24; + ++histo[kHistoPalette * 256 + (hash & 0xff)]; + } + } + prev_row = curr_row; + curr_row += argb_stride; + } + { + double entropy_comp[kHistoTotal]; + double entropy[kNumEntropyIx]; + EntropyIx k; + EntropyIx last_mode_to_analyze = + use_palette ? kPalette : kSpatialSubGreen; + int j; + // Let's add one zero to the predicted histograms. The zeros are removed + // too efficiently by the pix_diff == 0 comparison, at least one of the + // zeros is likely to exist. + ++histo[kHistoRedPredSubGreen * 256]; + ++histo[kHistoBluePredSubGreen * 256]; + ++histo[kHistoRedPred * 256]; + ++histo[kHistoGreenPred * 256]; + ++histo[kHistoBluePred * 256]; + ++histo[kHistoAlphaPred * 256]; + + for (j = 0; j < kHistoTotal; ++j) { + entropy_comp[j] = VP8LBitsEntropy(&histo[j * 256], 256, NULL); + } + entropy[kDirect] = entropy_comp[kHistoAlpha] + + entropy_comp[kHistoRed] + + entropy_comp[kHistoGreen] + + entropy_comp[kHistoBlue]; + entropy[kSpatial] = entropy_comp[kHistoAlphaPred] + + entropy_comp[kHistoRedPred] + + entropy_comp[kHistoGreenPred] + + entropy_comp[kHistoBluePred]; + entropy[kSubGreen] = entropy_comp[kHistoAlpha] + + entropy_comp[kHistoRedSubGreen] + + entropy_comp[kHistoGreen] + + entropy_comp[kHistoBlueSubGreen]; + entropy[kSpatialSubGreen] = entropy_comp[kHistoAlphaPred] + + entropy_comp[kHistoRedPredSubGreen] + + entropy_comp[kHistoGreenPred] + + entropy_comp[kHistoBluePredSubGreen]; + // Palette mode seems more efficient in a breakeven case. Bias with 1.0. + entropy[kPalette] = entropy_comp[kHistoPalette] - 1.0; + + *min_entropy_ix = kDirect; + for (k = kDirect + 1; k <= last_mode_to_analyze; ++k) { + if (entropy[*min_entropy_ix] > entropy[k]) { + *min_entropy_ix = k; + } + } + *red_and_blue_always_zero = 1; + // Let's check if the histogram of the chosen entropy mode has + // non-zero red and blue values. If all are zero, we can later skip + // the cross color optimization. + { + static const uint8_t kHistoPairs[5][2] = { + { kHistoRed, kHistoBlue }, + { kHistoRedPred, kHistoBluePred }, + { kHistoRedSubGreen, kHistoBlueSubGreen }, + { kHistoRedPredSubGreen, kHistoBluePredSubGreen }, + { kHistoRed, kHistoBlue } + }; + const uint32_t* const red_histo = + &histo[256 * kHistoPairs[*min_entropy_ix][0]]; + const uint32_t* const blue_histo = + &histo[256 * kHistoPairs[*min_entropy_ix][1]]; + for (i = 1; i < 256; ++i) { + if ((red_histo[i] | blue_histo[i]) != 0) { + *red_and_blue_always_zero = 0; + break; + } + } + } + } + WebPSafeFree(histo); + return 1; + } else { + return 0; + } +} + +static int GetHistoBits(int method, int use_palette, int width, int height) { + // Make tile size a function of encoding method (Range: 0 to 6). + int histo_bits = (use_palette ? 9 : 7) - method; + while (1) { + const int huff_image_size = VP8LSubSampleSize(width, histo_bits) * + VP8LSubSampleSize(height, histo_bits); + if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break; + ++histo_bits; + } + return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS : + (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits; +} + +static int GetTransformBits(int method, int histo_bits) { + const int max_transform_bits = (method < 4) ? 6 : (method > 4) ? 4 : 5; + return (histo_bits > max_transform_bits) ? max_transform_bits : histo_bits; +} + +static int AnalyzeAndInit(VP8LEncoder* const enc) { + const WebPPicture* const pic = enc->pic_; + const int width = pic->width; + const int height = pic->height; + const int pix_cnt = width * height; + const WebPConfig* const config = enc->config_; + const int method = config->method; + const int low_effort = (config->method == 0); + // we round the block size up, so we're guaranteed to have + // at max MAX_REFS_BLOCK_PER_IMAGE blocks used: + int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1; + assert(pic != NULL && pic->argb != NULL); + + enc->use_cross_color_ = 0; + enc->use_predict_ = 0; + enc->use_subtract_green_ = 0; + enc->use_palette_ = + AnalyzeAndCreatePalette(pic, low_effort, + enc->palette_, &enc->palette_size_); + + // TODO(jyrki): replace the decision to be based on an actual estimate + // of entropy, or even spatial variance of entropy. + enc->histo_bits_ = GetHistoBits(method, enc->use_palette_, + pic->width, pic->height); + enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_); + + if (low_effort) { + // AnalyzeEntropy is somewhat slow. + enc->use_predict_ = !enc->use_palette_; + enc->use_subtract_green_ = !enc->use_palette_; + enc->use_cross_color_ = 0; + } else { + int red_and_blue_always_zero; + EntropyIx min_entropy_ix; + if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, + enc->use_palette_, &min_entropy_ix, + &red_and_blue_always_zero)) { + return 0; + } + enc->use_palette_ = (min_entropy_ix == kPalette); + enc->use_subtract_green_ = + (min_entropy_ix == kSubGreen) || (min_entropy_ix == kSpatialSubGreen); + enc->use_predict_ = + (min_entropy_ix == kSpatial) || (min_entropy_ix == kSpatialSubGreen); + enc->use_cross_color_ = red_and_blue_always_zero ? 0 : enc->use_predict_; + } + + if (!VP8LHashChainInit(&enc->hash_chain_, pix_cnt)) return 0; + + // palette-friendly input typically uses less literals + // -> reduce block size a bit + if (enc->use_palette_) refs_block_size /= 2; + VP8LBackwardRefsInit(&enc->refs_[0], refs_block_size); + VP8LBackwardRefsInit(&enc->refs_[1], refs_block_size); + + return 1; +} + +// Returns false in case of memory error. +static int GetHuffBitLengthsAndCodes( + const VP8LHistogramSet* const histogram_image, + HuffmanTreeCode* const huffman_codes) { + int i, k; + int ok = 0; + uint64_t total_length_size = 0; + uint8_t* mem_buf = NULL; + const int histogram_image_size = histogram_image->size; + int max_num_symbols = 0; + uint8_t* buf_rle = NULL; + HuffmanTree* huff_tree = NULL; + + // Iterate over all histograms and get the aggregate number of codes used. + for (i = 0; i < histogram_image_size; ++i) { + const VP8LHistogram* const histo = histogram_image->histograms[i]; + HuffmanTreeCode* const codes = &huffman_codes[5 * i]; + for (k = 0; k < 5; ++k) { + const int num_symbols = + (k == 0) ? VP8LHistogramNumCodes(histo->palette_code_bits_) : + (k == 4) ? NUM_DISTANCE_CODES : 256; + codes[k].num_symbols = num_symbols; + total_length_size += num_symbols; + } + } + + // Allocate and Set Huffman codes. + { + uint16_t* codes; + uint8_t* lengths; + mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size, + sizeof(*lengths) + sizeof(*codes)); + if (mem_buf == NULL) goto End; + + codes = (uint16_t*)mem_buf; + lengths = (uint8_t*)&codes[total_length_size]; + for (i = 0; i < 5 * histogram_image_size; ++i) { + const int bit_length = huffman_codes[i].num_symbols; + huffman_codes[i].codes = codes; + huffman_codes[i].code_lengths = lengths; + codes += bit_length; + lengths += bit_length; + if (max_num_symbols < bit_length) { + max_num_symbols = bit_length; + } + } + } + + buf_rle = (uint8_t*)WebPSafeMalloc(1ULL, max_num_symbols); + huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * max_num_symbols, + sizeof(*huff_tree)); + if (buf_rle == NULL || huff_tree == NULL) goto End; + + // Create Huffman trees. + for (i = 0; i < histogram_image_size; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[5 * i]; + VP8LHistogram* const histo = histogram_image->histograms[i]; + VP8LCreateHuffmanTree(histo->literal_, 15, buf_rle, huff_tree, codes + 0); + VP8LCreateHuffmanTree(histo->red_, 15, buf_rle, huff_tree, codes + 1); + VP8LCreateHuffmanTree(histo->blue_, 15, buf_rle, huff_tree, codes + 2); + VP8LCreateHuffmanTree(histo->alpha_, 15, buf_rle, huff_tree, codes + 3); + VP8LCreateHuffmanTree(histo->distance_, 15, buf_rle, huff_tree, codes + 4); + } + ok = 1; + End: + WebPSafeFree(huff_tree); + WebPSafeFree(buf_rle); + if (!ok) { + WebPSafeFree(mem_buf); + memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes)); + } + return ok; +} + +static void StoreHuffmanTreeOfHuffmanTreeToBitMask( + VP8LBitWriter* const bw, const uint8_t* code_length_bitdepth) { + // RFC 1951 will calm you down if you are worried about this funny sequence. + // This sequence is tuned from that, but more weighted for lower symbol count, + // and more spiking histograms. + static const uint8_t kStorageOrder[CODE_LENGTH_CODES] = { + 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + }; + int i; + // Throw away trailing zeros: + int codes_to_store = CODE_LENGTH_CODES; + for (; codes_to_store > 4; --codes_to_store) { + if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) { + break; + } + } + VP8LPutBits(bw, codes_to_store - 4, 4); + for (i = 0; i < codes_to_store; ++i) { + VP8LPutBits(bw, code_length_bitdepth[kStorageOrder[i]], 3); + } +} + +static void ClearHuffmanTreeIfOnlyOneSymbol( + HuffmanTreeCode* const huffman_code) { + int k; + int count = 0; + for (k = 0; k < huffman_code->num_symbols; ++k) { + if (huffman_code->code_lengths[k] != 0) { + ++count; + if (count > 1) return; + } + } + for (k = 0; k < huffman_code->num_symbols; ++k) { + huffman_code->code_lengths[k] = 0; + huffman_code->codes[k] = 0; + } +} + +static void StoreHuffmanTreeToBitMask( + VP8LBitWriter* const bw, + const HuffmanTreeToken* const tokens, const int num_tokens, + const HuffmanTreeCode* const huffman_code) { + int i; + for (i = 0; i < num_tokens; ++i) { + const int ix = tokens[i].code; + const int extra_bits = tokens[i].extra_bits; + VP8LPutBits(bw, huffman_code->codes[ix], huffman_code->code_lengths[ix]); + switch (ix) { + case 16: + VP8LPutBits(bw, extra_bits, 2); + break; + case 17: + VP8LPutBits(bw, extra_bits, 3); + break; + case 18: + VP8LPutBits(bw, extra_bits, 7); + break; + } + } +} + +// 'huff_tree' and 'tokens' are pre-alloacted buffers. +static void StoreFullHuffmanCode(VP8LBitWriter* const bw, + HuffmanTree* const huff_tree, + HuffmanTreeToken* const tokens, + const HuffmanTreeCode* const tree) { + uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 }; + uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 }; + const int max_tokens = tree->num_symbols; + int num_tokens; + HuffmanTreeCode huffman_code; + huffman_code.num_symbols = CODE_LENGTH_CODES; + huffman_code.code_lengths = code_length_bitdepth; + huffman_code.codes = code_length_bitdepth_symbols; + + VP8LPutBits(bw, 0, 1); + num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens); + { + uint32_t histogram[CODE_LENGTH_CODES] = { 0 }; + uint8_t buf_rle[CODE_LENGTH_CODES] = { 0 }; + int i; + for (i = 0; i < num_tokens; ++i) { + ++histogram[tokens[i].code]; + } + + VP8LCreateHuffmanTree(histogram, 7, buf_rle, huff_tree, &huffman_code); + } + + StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth); + ClearHuffmanTreeIfOnlyOneSymbol(&huffman_code); + { + int trailing_zero_bits = 0; + int trimmed_length = num_tokens; + int write_trimmed_length; + int length; + int i = num_tokens; + while (i-- > 0) { + const int ix = tokens[i].code; + if (ix == 0 || ix == 17 || ix == 18) { + --trimmed_length; // discount trailing zeros + trailing_zero_bits += code_length_bitdepth[ix]; + if (ix == 17) { + trailing_zero_bits += 3; + } else if (ix == 18) { + trailing_zero_bits += 7; + } + } else { + break; + } + } + write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12); + length = write_trimmed_length ? trimmed_length : num_tokens; + VP8LPutBits(bw, write_trimmed_length, 1); + if (write_trimmed_length) { + const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1); + const int nbitpairs = (nbits == 0) ? 1 : (nbits + 1) / 2; + VP8LPutBits(bw, nbitpairs - 1, 3); + assert(trimmed_length >= 2); + VP8LPutBits(bw, trimmed_length - 2, nbitpairs * 2); + } + StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code); + } +} + +// 'huff_tree' and 'tokens' are pre-alloacted buffers. +static void StoreHuffmanCode(VP8LBitWriter* const bw, + HuffmanTree* const huff_tree, + HuffmanTreeToken* const tokens, + const HuffmanTreeCode* const huffman_code) { + int i; + int count = 0; + int symbols[2] = { 0, 0 }; + const int kMaxBits = 8; + const int kMaxSymbol = 1 << kMaxBits; + + // Check whether it's a small tree. + for (i = 0; i < huffman_code->num_symbols && count < 3; ++i) { + if (huffman_code->code_lengths[i] != 0) { + if (count < 2) symbols[count] = i; + ++count; + } + } + + if (count == 0) { // emit minimal tree for empty cases + // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0 + VP8LPutBits(bw, 0x01, 4); + } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) { + VP8LPutBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols. + VP8LPutBits(bw, count - 1, 1); + if (symbols[0] <= 1) { + VP8LPutBits(bw, 0, 1); // Code bit for small (1 bit) symbol value. + VP8LPutBits(bw, symbols[0], 1); + } else { + VP8LPutBits(bw, 1, 1); + VP8LPutBits(bw, symbols[0], 8); + } + if (count == 2) { + VP8LPutBits(bw, symbols[1], 8); + } + } else { + StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code); + } +} + +static WEBP_INLINE void WriteHuffmanCode(VP8LBitWriter* const bw, + const HuffmanTreeCode* const code, + int code_index) { + const int depth = code->code_lengths[code_index]; + const int symbol = code->codes[code_index]; + VP8LPutBits(bw, symbol, depth); +} + +static WEBP_INLINE void WriteHuffmanCodeWithExtraBits( + VP8LBitWriter* const bw, + const HuffmanTreeCode* const code, + int code_index, + int bits, + int n_bits) { + const int depth = code->code_lengths[code_index]; + const int symbol = code->codes[code_index]; + VP8LPutBits(bw, (bits << depth) | symbol, depth + n_bits); +} + +static WebPEncodingError StoreImageToBitMask( + VP8LBitWriter* const bw, int width, int histo_bits, + VP8LBackwardRefs* const refs, + const uint16_t* histogram_symbols, + const HuffmanTreeCode* const huffman_codes) { + const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1; + const int tile_mask = (histo_bits == 0) ? 0 : -(1 << histo_bits); + // x and y trace the position in the image. + int x = 0; + int y = 0; + int tile_x = x & tile_mask; + int tile_y = y & tile_mask; + int histogram_ix = histogram_symbols[0]; + const HuffmanTreeCode* codes = huffman_codes + 5 * histogram_ix; + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + while (VP8LRefsCursorOk(&c)) { + const PixOrCopy* const v = c.cur_pos; + if ((tile_x != (x & tile_mask)) || (tile_y != (y & tile_mask))) { + tile_x = x & tile_mask; + tile_y = y & tile_mask; + histogram_ix = histogram_symbols[(y >> histo_bits) * histo_xsize + + (x >> histo_bits)]; + codes = huffman_codes + 5 * histogram_ix; + } + if (PixOrCopyIsLiteral(v)) { + static const int order[] = { 1, 2, 0, 3 }; + int k; + for (k = 0; k < 4; ++k) { + const int code = PixOrCopyLiteral(v, order[k]); + WriteHuffmanCode(bw, codes + k, code); + } + } else if (PixOrCopyIsCacheIdx(v)) { + const int code = PixOrCopyCacheIdx(v); + const int literal_ix = 256 + NUM_LENGTH_CODES + code; + WriteHuffmanCode(bw, codes, literal_ix); + } else { + int bits, n_bits; + int code; + + const int distance = PixOrCopyDistance(v); + VP8LPrefixEncode(v->len, &code, &n_bits, &bits); + WriteHuffmanCodeWithExtraBits(bw, codes, 256 + code, bits, n_bits); + + // Don't write the distance with the extra bits code since + // the distance can be up to 18 bits of extra bits, and the prefix + // 15 bits, totaling to 33, and our PutBits only supports up to 32 bits. + // TODO(jyrki): optimize this further. + VP8LPrefixEncode(distance, &code, &n_bits, &bits); + WriteHuffmanCode(bw, codes + 4, code); + VP8LPutBits(bw, bits, n_bits); + } + x += PixOrCopyLength(v); + while (x >= width) { + x -= width; + ++y; + } + VP8LRefsCursorNext(&c); + } + return bw->error_ ? VP8_ENC_ERROR_OUT_OF_MEMORY : VP8_ENC_OK; +} + +// Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31 +static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw, + const uint32_t* const argb, + VP8LHashChain* const hash_chain, + VP8LBackwardRefs refs_array[2], + int width, int height, + int quality) { + int i; + int max_tokens = 0; + WebPEncodingError err = VP8_ENC_OK; + VP8LBackwardRefs* refs; + HuffmanTreeToken* tokens = NULL; + HuffmanTreeCode huffman_codes[5] = { { 0, NULL, NULL } }; + const uint16_t histogram_symbols[1] = { 0 }; // only one tree, one symbol + int cache_bits = 0; + VP8LHistogramSet* histogram_image = NULL; + HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc( + 3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree)); + if (huff_tree == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + // Calculate backward references from ARGB image. + if (VP8LHashChainFill(hash_chain, quality, argb, width, height) == 0) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + refs = VP8LGetBackwardReferences(width, height, argb, quality, 0, &cache_bits, + hash_chain, refs_array); + if (refs == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + histogram_image = VP8LAllocateHistogramSet(1, cache_bits); + if (histogram_image == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + // Build histogram image and symbols from backward references. + VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]); + + // Create Huffman bit lengths and codes for each histogram image. + assert(histogram_image->size == 1); + if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + // No color cache, no Huffman image. + VP8LPutBits(bw, 0, 1); + + // Find maximum number of symbols for the huffman tree-set. + for (i = 0; i < 5; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[i]; + if (max_tokens < codes->num_symbols) { + max_tokens = codes->num_symbols; + } + } + + tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens)); + if (tokens == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + // Store Huffman codes. + for (i = 0; i < 5; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[i]; + StoreHuffmanCode(bw, huff_tree, tokens, codes); + ClearHuffmanTreeIfOnlyOneSymbol(codes); + } + + // Store actual literals. + err = StoreImageToBitMask(bw, width, 0, refs, histogram_symbols, + huffman_codes); + + Error: + WebPSafeFree(tokens); + WebPSafeFree(huff_tree); + VP8LFreeHistogramSet(histogram_image); + WebPSafeFree(huffman_codes[0].codes); + return err; +} + +static WebPEncodingError EncodeImageInternal(VP8LBitWriter* const bw, + const uint32_t* const argb, + VP8LHashChain* const hash_chain, + VP8LBackwardRefs refs_array[2], + int width, int height, int quality, + int low_effort, + int use_cache, int* cache_bits, + int histogram_bits, + size_t init_byte_position, + int* const hdr_size, + int* const data_size) { + WebPEncodingError err = VP8_ENC_OK; + const uint32_t histogram_image_xysize = + VP8LSubSampleSize(width, histogram_bits) * + VP8LSubSampleSize(height, histogram_bits); + VP8LHistogramSet* histogram_image = NULL; + VP8LHistogramSet* tmp_histos = NULL; + int histogram_image_size = 0; + size_t bit_array_size = 0; + HuffmanTree* huff_tree = NULL; + HuffmanTreeToken* tokens = NULL; + HuffmanTreeCode* huffman_codes = NULL; + VP8LBackwardRefs refs; + VP8LBackwardRefs* best_refs; + uint16_t* const histogram_symbols = + (uint16_t*)WebPSafeMalloc(histogram_image_xysize, + sizeof(*histogram_symbols)); + assert(histogram_bits >= MIN_HUFFMAN_BITS); + assert(histogram_bits <= MAX_HUFFMAN_BITS); + assert(hdr_size != NULL); + assert(data_size != NULL); + + VP8LBackwardRefsInit(&refs, refs_array[0].block_size_); + if (histogram_symbols == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + *cache_bits = use_cache ? MAX_COLOR_CACHE_BITS : 0; + // 'best_refs' is the reference to the best backward refs and points to one + // of refs_array[0] or refs_array[1]. + // Calculate backward references from ARGB image. + if (VP8LHashChainFill(hash_chain, quality, argb, width, height) == 0) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + best_refs = VP8LGetBackwardReferences(width, height, argb, quality, + low_effort, cache_bits, hash_chain, + refs_array); + if (best_refs == NULL || !VP8LBackwardRefsCopy(best_refs, &refs)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + histogram_image = + VP8LAllocateHistogramSet(histogram_image_xysize, *cache_bits); + tmp_histos = VP8LAllocateHistogramSet(2, *cache_bits); + if (histogram_image == NULL || tmp_histos == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + // Build histogram image and symbols from backward references. + if (!VP8LGetHistoImageSymbols(width, height, &refs, quality, low_effort, + histogram_bits, *cache_bits, histogram_image, + tmp_histos, histogram_symbols)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + // Create Huffman bit lengths and codes for each histogram image. + histogram_image_size = histogram_image->size; + bit_array_size = 5 * histogram_image_size; + huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size, + sizeof(*huffman_codes)); + // Note: some histogram_image entries may point to tmp_histos[], so the latter + // need to outlive the following call to GetHuffBitLengthsAndCodes(). + if (huffman_codes == NULL || + !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + // Free combined histograms. + VP8LFreeHistogramSet(histogram_image); + histogram_image = NULL; + + // Free scratch histograms. + VP8LFreeHistogramSet(tmp_histos); + tmp_histos = NULL; + + // Color Cache parameters. + if (*cache_bits > 0) { + VP8LPutBits(bw, 1, 1); + VP8LPutBits(bw, *cache_bits, 4); + } else { + VP8LPutBits(bw, 0, 1); + } + + // Huffman image + meta huffman. + { + const int write_histogram_image = (histogram_image_size > 1); + VP8LPutBits(bw, write_histogram_image, 1); + if (write_histogram_image) { + uint32_t* const histogram_argb = + (uint32_t*)WebPSafeMalloc(histogram_image_xysize, + sizeof(*histogram_argb)); + int max_index = 0; + uint32_t i; + if (histogram_argb == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + for (i = 0; i < histogram_image_xysize; ++i) { + const int symbol_index = histogram_symbols[i] & 0xffff; + histogram_argb[i] = (symbol_index << 8); + if (symbol_index >= max_index) { + max_index = symbol_index + 1; + } + } + histogram_image_size = max_index; + + VP8LPutBits(bw, histogram_bits - 2, 3); + err = EncodeImageNoHuffman(bw, histogram_argb, hash_chain, refs_array, + VP8LSubSampleSize(width, histogram_bits), + VP8LSubSampleSize(height, histogram_bits), + quality); + WebPSafeFree(histogram_argb); + if (err != VP8_ENC_OK) goto Error; + } + } + + // Store Huffman codes. + { + int i; + int max_tokens = 0; + huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * CODE_LENGTH_CODES, + sizeof(*huff_tree)); + if (huff_tree == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + // Find maximum number of symbols for the huffman tree-set. + for (i = 0; i < 5 * histogram_image_size; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[i]; + if (max_tokens < codes->num_symbols) { + max_tokens = codes->num_symbols; + } + } + tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, + sizeof(*tokens)); + if (tokens == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + for (i = 0; i < 5 * histogram_image_size; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[i]; + StoreHuffmanCode(bw, huff_tree, tokens, codes); + ClearHuffmanTreeIfOnlyOneSymbol(codes); + } + } + + *hdr_size = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position); + // Store actual literals. + err = StoreImageToBitMask(bw, width, histogram_bits, &refs, + histogram_symbols, huffman_codes); + *data_size = + (int)(VP8LBitWriterNumBytes(bw) - init_byte_position - *hdr_size); + + Error: + WebPSafeFree(tokens); + WebPSafeFree(huff_tree); + VP8LFreeHistogramSet(histogram_image); + VP8LFreeHistogramSet(tmp_histos); + VP8LBackwardRefsClear(&refs); + if (huffman_codes != NULL) { + WebPSafeFree(huffman_codes->codes); + WebPSafeFree(huffman_codes); + } + WebPSafeFree(histogram_symbols); + return err; +} + +// ----------------------------------------------------------------------------- +// Transforms + +static void ApplySubtractGreen(VP8LEncoder* const enc, int width, int height, + VP8LBitWriter* const bw) { + VP8LPutBits(bw, TRANSFORM_PRESENT, 1); + VP8LPutBits(bw, SUBTRACT_GREEN, 2); + VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height); +} + +static WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc, + int width, int height, + int quality, int low_effort, + int used_subtract_green, + VP8LBitWriter* const bw) { + const int pred_bits = enc->transform_bits_; + const int transform_width = VP8LSubSampleSize(width, pred_bits); + const int transform_height = VP8LSubSampleSize(height, pred_bits); + // we disable near-lossless quantization if palette is used. + const int near_lossless_strength = enc->use_palette_ ? 100 + : enc->config_->near_lossless; + + VP8LResidualImage(width, height, pred_bits, low_effort, enc->argb_, + enc->argb_scratch_, enc->transform_data_, + near_lossless_strength, enc->config_->exact, + used_subtract_green); + VP8LPutBits(bw, TRANSFORM_PRESENT, 1); + VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2); + assert(pred_bits >= 2); + VP8LPutBits(bw, pred_bits - 2, 3); + return EncodeImageNoHuffman(bw, enc->transform_data_, + (VP8LHashChain*)&enc->hash_chain_, + (VP8LBackwardRefs*)enc->refs_, // cast const away + transform_width, transform_height, + quality); +} + +static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc, + int width, int height, + int quality, + VP8LBitWriter* const bw) { + const int ccolor_transform_bits = enc->transform_bits_; + const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits); + const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits); + + VP8LColorSpaceTransform(width, height, ccolor_transform_bits, quality, + enc->argb_, enc->transform_data_); + VP8LPutBits(bw, TRANSFORM_PRESENT, 1); + VP8LPutBits(bw, CROSS_COLOR_TRANSFORM, 2); + assert(ccolor_transform_bits >= 2); + VP8LPutBits(bw, ccolor_transform_bits - 2, 3); + return EncodeImageNoHuffman(bw, enc->transform_data_, + (VP8LHashChain*)&enc->hash_chain_, + (VP8LBackwardRefs*)enc->refs_, // cast const away + transform_width, transform_height, + quality); +} + +// ----------------------------------------------------------------------------- + +static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic, + size_t riff_size, size_t vp8l_size) { + uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = { + 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P', + 'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE, + }; + PutLE32(riff + TAG_SIZE, (uint32_t)riff_size); + PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size); + if (!pic->writer(riff, sizeof(riff), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +static int WriteImageSize(const WebPPicture* const pic, + VP8LBitWriter* const bw) { + const int width = pic->width - 1; + const int height = pic->height - 1; + assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION); + + VP8LPutBits(bw, width, VP8L_IMAGE_SIZE_BITS); + VP8LPutBits(bw, height, VP8L_IMAGE_SIZE_BITS); + return !bw->error_; +} + +static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) { + VP8LPutBits(bw, has_alpha, 1); + VP8LPutBits(bw, VP8L_VERSION, VP8L_VERSION_BITS); + return !bw->error_; +} + +static WebPEncodingError WriteImage(const WebPPicture* const pic, + VP8LBitWriter* const bw, + size_t* const coded_size) { + WebPEncodingError err = VP8_ENC_OK; + const uint8_t* const webpll_data = VP8LBitWriterFinish(bw); + const size_t webpll_size = VP8LBitWriterNumBytes(bw); + const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size; + const size_t pad = vp8l_size & 1; + const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad; + + err = WriteRiffHeader(pic, riff_size, vp8l_size); + if (err != VP8_ENC_OK) goto Error; + + if (!pic->writer(webpll_data, webpll_size, pic)) { + err = VP8_ENC_ERROR_BAD_WRITE; + goto Error; + } + + if (pad) { + const uint8_t pad_byte[1] = { 0 }; + if (!pic->writer(pad_byte, 1, pic)) { + err = VP8_ENC_ERROR_BAD_WRITE; + goto Error; + } + } + *coded_size = CHUNK_HEADER_SIZE + riff_size; + return VP8_ENC_OK; + + Error: + return err; +} + +// ----------------------------------------------------------------------------- + +static void ClearTransformBuffer(VP8LEncoder* const enc) { + WebPSafeFree(enc->transform_mem_); + enc->transform_mem_ = NULL; + enc->transform_mem_size_ = 0; +} + +// Allocates the memory for argb (W x H) buffer, 2 rows of context for +// prediction and transform data. +// Flags influencing the memory allocated: +// enc->transform_bits_ +// enc->use_predict_, enc->use_cross_color_ +static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc, + int width, int height) { + WebPEncodingError err = VP8_ENC_OK; + const uint64_t image_size = width * height; + // VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra + // pixel in each, plus 2 regular scanlines of bytes. + // TODO(skal): Clean up by using arithmetic in bytes instead of words. + const uint64_t argb_scratch_size = + enc->use_predict_ + ? (width + 1) * 2 + + (width * 2 + sizeof(uint32_t) - 1) / sizeof(uint32_t) + : 0; + const uint64_t transform_data_size = + (enc->use_predict_ || enc->use_cross_color_) + ? VP8LSubSampleSize(width, enc->transform_bits_) * + VP8LSubSampleSize(height, enc->transform_bits_) + : 0; + const uint64_t max_alignment_in_words = + (WEBP_ALIGN_CST + sizeof(uint32_t) - 1) / sizeof(uint32_t); + const uint64_t mem_size = + image_size + max_alignment_in_words + + argb_scratch_size + max_alignment_in_words + + transform_data_size; + uint32_t* mem = enc->transform_mem_; + if (mem == NULL || mem_size > enc->transform_mem_size_) { + ClearTransformBuffer(enc); + mem = (uint32_t*)WebPSafeMalloc(mem_size, sizeof(*mem)); + if (mem == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + enc->transform_mem_ = mem; + enc->transform_mem_size_ = (size_t)mem_size; + } + enc->argb_ = mem; + mem = (uint32_t*)WEBP_ALIGN(mem + image_size); + enc->argb_scratch_ = mem; + mem = (uint32_t*)WEBP_ALIGN(mem + argb_scratch_size); + enc->transform_data_ = mem; + + enc->current_width_ = width; + Error: + return err; +} + +static WebPEncodingError MakeInputImageCopy(VP8LEncoder* const enc) { + WebPEncodingError err = VP8_ENC_OK; + const WebPPicture* const picture = enc->pic_; + const int width = picture->width; + const int height = picture->height; + int y; + err = AllocateTransformBuffer(enc, width, height); + if (err != VP8_ENC_OK) return err; + for (y = 0; y < height; ++y) { + memcpy(enc->argb_ + y * width, + picture->argb + y * picture->argb_stride, + width * sizeof(*enc->argb_)); + } + assert(enc->current_width_ == width); + return VP8_ENC_OK; +} + +// ----------------------------------------------------------------------------- + +static int SearchColor(const uint32_t sorted[], uint32_t color, int hi) { + int low = 0; + if (sorted[low] == color) return low; // loop invariant: sorted[low] != color + while (1) { + const int mid = (low + hi) >> 1; + if (sorted[mid] == color) { + return mid; + } else if (sorted[mid] < color) { + low = mid; + } else { + hi = mid; + } + } +} + +// Sort palette in increasing order and prepare an inverse mapping array. +static void PrepareMapToPalette(const uint32_t palette[], int num_colors, + uint32_t sorted[], int idx_map[]) { + int i; + memcpy(sorted, palette, num_colors * sizeof(*sorted)); + qsort(sorted, num_colors, sizeof(*sorted), PaletteCompareColorsForQsort); + for (i = 0; i < num_colors; ++i) { + idx_map[SearchColor(sorted, palette[i], num_colors)] = i; + } +} + +static void MapToPalette(const uint32_t sorted_palette[], int num_colors, + uint32_t* const last_pix, int* const last_idx, + const int idx_map[], + const uint32_t* src, uint8_t* dst, int width) { + int x; + int prev_idx = *last_idx; + uint32_t prev_pix = *last_pix; + for (x = 0; x < width; ++x) { + const uint32_t pix = src[x]; + if (pix != prev_pix) { + prev_idx = idx_map[SearchColor(sorted_palette, pix, num_colors)]; + prev_pix = pix; + } + dst[x] = prev_idx; + } + *last_idx = prev_idx; + *last_pix = prev_pix; +} + +// Remap argb values in src[] to packed palettes entries in dst[] +// using 'row' as a temporary buffer of size 'width'. +// We assume that all src[] values have a corresponding entry in the palette. +// Note: src[] can be the same as dst[] +static WebPEncodingError ApplyPalette(const uint32_t* src, uint32_t src_stride, + uint32_t* dst, uint32_t dst_stride, + const uint32_t* palette, int palette_size, + int width, int height, int xbits) { + // TODO(skal): this tmp buffer is not needed if VP8LBundleColorMap() can be + // made to work in-place. + uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row)); + int i, x, y; + int use_LUT = 1; + + if (tmp_row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY; + for (i = 0; i < palette_size; ++i) { + if ((palette[i] & 0xffff00ffu) != 0) { + use_LUT = 0; + break; + } + } + + if (use_LUT) { + uint8_t inv_palette[MAX_PALETTE_SIZE] = { 0 }; + for (i = 0; i < palette_size; ++i) { + const int color = (palette[i] >> 8) & 0xff; + inv_palette[color] = i; + } + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + const int color = (src[x] >> 8) & 0xff; + tmp_row[x] = inv_palette[color]; + } + VP8LBundleColorMap(tmp_row, width, xbits, dst); + src += src_stride; + dst += dst_stride; + } + } else { + // Use 1 pixel cache for ARGB pixels. + uint32_t last_pix; + int last_idx; + uint32_t sorted[MAX_PALETTE_SIZE]; + int idx_map[MAX_PALETTE_SIZE]; + PrepareMapToPalette(palette, palette_size, sorted, idx_map); + last_pix = palette[0]; + last_idx = 0; + for (y = 0; y < height; ++y) { + MapToPalette(sorted, palette_size, &last_pix, &last_idx, + idx_map, src, tmp_row, width); + VP8LBundleColorMap(tmp_row, width, xbits, dst); + src += src_stride; + dst += dst_stride; + } + } + WebPSafeFree(tmp_row); + return VP8_ENC_OK; +} + +// Note: Expects "enc->palette_" to be set properly. +static WebPEncodingError MapImageFromPalette(VP8LEncoder* const enc, + int in_place) { + WebPEncodingError err = VP8_ENC_OK; + const WebPPicture* const pic = enc->pic_; + const int width = pic->width; + const int height = pic->height; + const uint32_t* const palette = enc->palette_; + const uint32_t* src = in_place ? enc->argb_ : pic->argb; + const int src_stride = in_place ? enc->current_width_ : pic->argb_stride; + const int palette_size = enc->palette_size_; + int xbits; + + // Replace each input pixel by corresponding palette index. + // This is done line by line. + if (palette_size <= 4) { + xbits = (palette_size <= 2) ? 3 : 2; + } else { + xbits = (palette_size <= 16) ? 1 : 0; + } + + err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height); + if (err != VP8_ENC_OK) return err; + + err = ApplyPalette(src, src_stride, + enc->argb_, enc->current_width_, + palette, palette_size, width, height, xbits); + return err; +} + +// Save palette_[] to bitstream. +static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, + VP8LEncoder* const enc) { + int i; + uint32_t tmp_palette[MAX_PALETTE_SIZE]; + const int palette_size = enc->palette_size_; + const uint32_t* const palette = enc->palette_; + VP8LPutBits(bw, TRANSFORM_PRESENT, 1); + VP8LPutBits(bw, COLOR_INDEXING_TRANSFORM, 2); + assert(palette_size >= 1 && palette_size <= MAX_PALETTE_SIZE); + VP8LPutBits(bw, palette_size - 1, 8); + for (i = palette_size - 1; i >= 1; --i) { + tmp_palette[i] = VP8LSubPixels(palette[i], palette[i - 1]); + } + tmp_palette[0] = palette[0]; + return EncodeImageNoHuffman(bw, tmp_palette, &enc->hash_chain_, enc->refs_, + palette_size, 1, 20 /* quality */); +} + +#ifdef WEBP_EXPERIMENTAL_FEATURES + +static WebPEncodingError EncodeDeltaPalettePredictorImage( + VP8LBitWriter* const bw, VP8LEncoder* const enc, int quality) { + const WebPPicture* const pic = enc->pic_; + const int width = pic->width; + const int height = pic->height; + + const int pred_bits = 5; + const int transform_width = VP8LSubSampleSize(width, pred_bits); + const int transform_height = VP8LSubSampleSize(height, pred_bits); + const int pred = 7; // default is Predictor7 (Top/Left Average) + const int tiles_per_row = VP8LSubSampleSize(width, pred_bits); + const int tiles_per_col = VP8LSubSampleSize(height, pred_bits); + uint32_t* predictors; + int tile_x, tile_y; + WebPEncodingError err = VP8_ENC_OK; + + predictors = (uint32_t*)WebPSafeMalloc(tiles_per_col * tiles_per_row, + sizeof(*predictors)); + if (predictors == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY; + + for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) { + for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) { + predictors[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8); + } + } + + VP8LPutBits(bw, TRANSFORM_PRESENT, 1); + VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2); + VP8LPutBits(bw, pred_bits - 2, 3); + err = EncodeImageNoHuffman(bw, predictors, &enc->hash_chain_, + (VP8LBackwardRefs*)enc->refs_, // cast const away + transform_width, transform_height, + quality); + WebPSafeFree(predictors); + return err; +} + +#endif // WEBP_EXPERIMENTAL_FEATURES + +// ----------------------------------------------------------------------------- +// VP8LEncoder + +static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config, + const WebPPicture* const picture) { + VP8LEncoder* const enc = (VP8LEncoder*)WebPSafeCalloc(1ULL, sizeof(*enc)); + if (enc == NULL) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + return NULL; + } + enc->config_ = config; + enc->pic_ = picture; + + VP8LEncDspInit(); + + return enc; +} + +static void VP8LEncoderDelete(VP8LEncoder* enc) { + if (enc != NULL) { + VP8LHashChainClear(&enc->hash_chain_); + VP8LBackwardRefsClear(&enc->refs_[0]); + VP8LBackwardRefsClear(&enc->refs_[1]); + ClearTransformBuffer(enc); + WebPSafeFree(enc); + } +} + +// ----------------------------------------------------------------------------- +// Main call + +WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, + const WebPPicture* const picture, + VP8LBitWriter* const bw, int use_cache) { + WebPEncodingError err = VP8_ENC_OK; + const int quality = (int)config->quality; + const int low_effort = (config->method == 0); + const int width = picture->width; + const int height = picture->height; + VP8LEncoder* const enc = VP8LEncoderNew(config, picture); + const size_t byte_position = VP8LBitWriterNumBytes(bw); + int use_near_lossless = 0; + int hdr_size = 0; + int data_size = 0; + int use_delta_palettization = 0; + + if (enc == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + // --------------------------------------------------------------------------- + // Analyze image (entropy, num_palettes etc) + + if (!AnalyzeAndInit(enc)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + // Apply near-lossless preprocessing. + use_near_lossless = + (config->near_lossless < 100) && !enc->use_palette_ && !enc->use_predict_; + if (use_near_lossless) { + if (!VP8ApplyNearLossless(width, height, picture->argb, + config->near_lossless)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + } + +#ifdef WEBP_EXPERIMENTAL_FEATURES + if (config->delta_palettization) { + enc->use_predict_ = 1; + enc->use_cross_color_ = 0; + enc->use_subtract_green_ = 0; + enc->use_palette_ = 1; + err = MakeInputImageCopy(enc); + if (err != VP8_ENC_OK) goto Error; + err = WebPSearchOptimalDeltaPalette(enc); + if (err != VP8_ENC_OK) goto Error; + if (enc->use_palette_) { + err = AllocateTransformBuffer(enc, width, height); + if (err != VP8_ENC_OK) goto Error; + err = EncodeDeltaPalettePredictorImage(bw, enc, quality); + if (err != VP8_ENC_OK) goto Error; + use_delta_palettization = 1; + } + } +#endif // WEBP_EXPERIMENTAL_FEATURES + + // Encode palette + if (enc->use_palette_) { + err = EncodePalette(bw, enc); + if (err != VP8_ENC_OK) goto Error; + err = MapImageFromPalette(enc, use_delta_palettization); + if (err != VP8_ENC_OK) goto Error; + } + if (!use_delta_palettization) { + // In case image is not packed. + if (enc->argb_ == NULL) { + err = MakeInputImageCopy(enc); + if (err != VP8_ENC_OK) goto Error; + } + + // ------------------------------------------------------------------------- + // Apply transforms and write transform data. + + if (enc->use_subtract_green_) { + ApplySubtractGreen(enc, enc->current_width_, height, bw); + } + + if (enc->use_predict_) { + err = ApplyPredictFilter(enc, enc->current_width_, height, quality, + low_effort, enc->use_subtract_green_, bw); + if (err != VP8_ENC_OK) goto Error; + } + + if (enc->use_cross_color_) { + err = ApplyCrossColorFilter(enc, enc->current_width_, + height, quality, bw); + if (err != VP8_ENC_OK) goto Error; + } + } + + VP8LPutBits(bw, !TRANSFORM_PRESENT, 1); // No more transforms. + + // --------------------------------------------------------------------------- + // Encode and write the transformed image. + err = EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_, + enc->current_width_, height, quality, low_effort, + use_cache, &enc->cache_bits_, enc->histo_bits_, + byte_position, &hdr_size, &data_size); + if (err != VP8_ENC_OK) goto Error; + + if (picture->stats != NULL) { + WebPAuxStats* const stats = picture->stats; + stats->lossless_features = 0; + if (enc->use_predict_) stats->lossless_features |= 1; + if (enc->use_cross_color_) stats->lossless_features |= 2; + if (enc->use_subtract_green_) stats->lossless_features |= 4; + if (enc->use_palette_) stats->lossless_features |= 8; + stats->histogram_bits = enc->histo_bits_; + stats->transform_bits = enc->transform_bits_; + stats->cache_bits = enc->cache_bits_; + stats->palette_size = enc->palette_size_; + stats->lossless_size = (int)(VP8LBitWriterNumBytes(bw) - byte_position); + stats->lossless_hdr_size = hdr_size; + stats->lossless_data_size = data_size; + } + + Error: + VP8LEncoderDelete(enc); + return err; +} + +int VP8LEncodeImage(const WebPConfig* const config, + const WebPPicture* const picture) { + int width, height; + int has_alpha; + size_t coded_size; + int percent = 0; + int initial_size; + WebPEncodingError err = VP8_ENC_OK; + VP8LBitWriter bw; + + if (picture == NULL) return 0; + + if (config == NULL || picture->argb == NULL) { + err = VP8_ENC_ERROR_NULL_PARAMETER; + WebPEncodingSetError(picture, err); + return 0; + } + + width = picture->width; + height = picture->height; + // Initialize BitWriter with size corresponding to 16 bpp to photo images and + // 8 bpp for graphical images. + initial_size = (config->image_hint == WEBP_HINT_GRAPH) ? + width * height : width * height * 2; + if (!VP8LBitWriterInit(&bw, initial_size)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + if (!WebPReportProgress(picture, 1, &percent)) { + UserAbort: + err = VP8_ENC_ERROR_USER_ABORT; + goto Error; + } + // Reset stats (for pure lossless coding) + if (picture->stats != NULL) { + WebPAuxStats* const stats = picture->stats; + memset(stats, 0, sizeof(*stats)); + stats->PSNR[0] = 99.f; + stats->PSNR[1] = 99.f; + stats->PSNR[2] = 99.f; + stats->PSNR[3] = 99.f; + stats->PSNR[4] = 99.f; + } + + // Write image size. + if (!WriteImageSize(picture, &bw)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + has_alpha = WebPPictureHasTransparency(picture); + // Write the non-trivial Alpha flag and lossless version. + if (!WriteRealAlphaAndVersion(&bw, has_alpha)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + if (!WebPReportProgress(picture, 5, &percent)) goto UserAbort; + + // Encode main image stream. + err = VP8LEncodeStream(config, picture, &bw, 1 /*use_cache*/); + if (err != VP8_ENC_OK) goto Error; + + // TODO(skal): have a fine-grained progress report in VP8LEncodeStream(). + if (!WebPReportProgress(picture, 90, &percent)) goto UserAbort; + + // Finish the RIFF chunk. + err = WriteImage(picture, &bw, &coded_size); + if (err != VP8_ENC_OK) goto Error; + + if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort; + + // Save size. + if (picture->stats != NULL) { + picture->stats->coded_size += (int)coded_size; + picture->stats->lossless_size = (int)coded_size; + } + + if (picture->extra_info != NULL) { + const int mb_w = (width + 15) >> 4; + const int mb_h = (height + 15) >> 4; + memset(picture->extra_info, 0, mb_w * mb_h * sizeof(*picture->extra_info)); + } + + Error: + if (bw.error_) err = VP8_ENC_ERROR_OUT_OF_MEMORY; + VP8LBitWriterWipeOut(&bw); + if (err != VP8_ENC_OK) { + WebPEncodingSetError(picture, err); + return 0; + } + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/thirdparty/libwebp/enc/vp8li.h b/thirdparty/libwebp/enc/vp8li.h new file mode 100644 index 0000000000..371e276ee0 --- /dev/null +++ b/thirdparty/libwebp/enc/vp8li.h @@ -0,0 +1,81 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Lossless encoder: internal header. +// +// Author: Vikas Arora (vikaas.arora@gmail.com) + +#ifndef WEBP_ENC_VP8LI_H_ +#define WEBP_ENC_VP8LI_H_ + +#include "./backward_references.h" +#include "./histogram.h" +#include "../utils/bit_writer.h" +#include "../webp/encode.h" +#include "../webp/format_constants.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + const WebPConfig* config_; // user configuration and parameters + const WebPPicture* pic_; // input picture. + + uint32_t* argb_; // Transformed argb image data. + uint32_t* argb_scratch_; // Scratch memory for argb rows + // (used for prediction). + uint32_t* transform_data_; // Scratch memory for transform data. + uint32_t* transform_mem_; // Currently allocated memory. + size_t transform_mem_size_; // Currently allocated memory size. + + int current_width_; // Corresponds to packed image width. + + // Encoding parameters derived from quality parameter. + int histo_bits_; + int transform_bits_; + int cache_bits_; // If equal to 0, don't use color cache. + + // Encoding parameters derived from image characteristics. + int use_cross_color_; + int use_subtract_green_; + int use_predict_; + int use_palette_; + int palette_size_; + uint32_t palette_[MAX_PALETTE_SIZE]; + + // Some 'scratch' (potentially large) objects. + struct VP8LBackwardRefs refs_[2]; // Backward Refs array corresponding to + // LZ77 & RLE coding. + VP8LHashChain hash_chain_; // HashChain data for constructing + // backward references. +} VP8LEncoder; + +//------------------------------------------------------------------------------ +// internal functions. Not public. + +// Encodes the picture. +// Returns 0 if config or picture is NULL or picture doesn't have valid argb +// input. +int VP8LEncodeImage(const WebPConfig* const config, + const WebPPicture* const picture); + +// Encodes the main image stream using the supplied bit writer. +// If 'use_cache' is false, disables the use of color cache. +WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, + const WebPPicture* const picture, + VP8LBitWriter* const bw, int use_cache); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_ENC_VP8LI_H_ */ diff --git a/drivers/webp/enc/webpenc.c b/thirdparty/libwebp/enc/webpenc.c index a7d04ea2ce..a7d04ea2ce 100644 --- a/drivers/webp/enc/webpenc.c +++ b/thirdparty/libwebp/enc/webpenc.c diff --git a/thirdparty/libwebp/mux/anim_encode.c b/thirdparty/libwebp/mux/anim_encode.c new file mode 100644 index 0000000000..53e2906a82 --- /dev/null +++ b/thirdparty/libwebp/mux/anim_encode.c @@ -0,0 +1,1534 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// AnimEncoder implementation. +// + +#include <assert.h> +#include <limits.h> +#include <math.h> // for pow() +#include <stdio.h> +#include <stdlib.h> // for abs() + +#include "../utils/utils.h" +#include "../webp/decode.h" +#include "../webp/encode.h" +#include "../webp/format_constants.h" +#include "../webp/mux.h" + +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf +#endif + +#define ERROR_STR_MAX_LENGTH 100 + +//------------------------------------------------------------------------------ +// Internal structs. + +// Stores frame rectangle dimensions. +typedef struct { + int x_offset_, y_offset_, width_, height_; +} FrameRect; + +// Used to store two candidates of encoded data for an animation frame. One of +// the two will be chosen later. +typedef struct { + WebPMuxFrameInfo sub_frame_; // Encoded frame rectangle. + WebPMuxFrameInfo key_frame_; // Encoded frame if it is a key-frame. + int is_key_frame_; // True if 'key_frame' has been chosen. +} EncodedFrame; + +struct WebPAnimEncoder { + const int canvas_width_; // Canvas width. + const int canvas_height_; // Canvas height. + const WebPAnimEncoderOptions options_; // Global encoding options. + + FrameRect prev_rect_; // Previous WebP frame rectangle. + WebPConfig last_config_; // Cached in case a re-encode is needed. + WebPConfig last_config_reversed_; // If 'last_config_' uses lossless, then + // this config uses lossy and vice versa; + // only valid if 'options_.allow_mixed' + // is true. + + WebPPicture* curr_canvas_; // Only pointer; we don't own memory. + + // Canvas buffers. + WebPPicture curr_canvas_copy_; // Possibly modified current canvas. + int curr_canvas_copy_modified_; // True if pixels in 'curr_canvas_copy_' + // differ from those in 'curr_canvas_'. + + WebPPicture prev_canvas_; // Previous canvas. + WebPPicture prev_canvas_disposed_; // Previous canvas disposed to background. + + // Encoded data. + EncodedFrame* encoded_frames_; // Array of encoded frames. + size_t size_; // Number of allocated frames. + size_t start_; // Frame start index. + size_t count_; // Number of valid frames. + size_t flush_count_; // If >0, 'flush_count' frames starting from + // 'start' are ready to be added to mux. + + // key-frame related. + int64_t best_delta_; // min(canvas size - frame size) over the frames. + // Can be negative in certain cases due to + // transparent pixels in a frame. + int keyframe_; // Index of selected key-frame relative to 'start_'. + int count_since_key_frame_; // Frames seen since the last key-frame. + + int first_timestamp_; // Timestamp of the first frame. + int prev_timestamp_; // Timestamp of the last added frame. + int prev_candidate_undecided_; // True if it's not yet decided if previous + // frame would be a sub-frame or a key-frame. + + // Misc. + int is_first_frame_; // True if first frame is yet to be added/being added. + int got_null_frame_; // True if WebPAnimEncoderAdd() has already been called + // with a NULL frame. + + size_t in_frame_count_; // Number of input frames processed so far. + size_t out_frame_count_; // Number of frames added to mux so far. This may be + // different from 'in_frame_count_' due to merging. + + WebPMux* mux_; // Muxer to assemble the WebP bitstream. + char error_str_[ERROR_STR_MAX_LENGTH]; // Error string. Empty if no error. +}; + +// ----------------------------------------------------------------------------- +// Life of WebPAnimEncoder object. + +#define DELTA_INFINITY (1ULL << 32) +#define KEYFRAME_NONE (-1) + +// Reset the counters in the WebPAnimEncoder. +static void ResetCounters(WebPAnimEncoder* const enc) { + enc->start_ = 0; + enc->count_ = 0; + enc->flush_count_ = 0; + enc->best_delta_ = DELTA_INFINITY; + enc->keyframe_ = KEYFRAME_NONE; +} + +static void DisableKeyframes(WebPAnimEncoderOptions* const enc_options) { + enc_options->kmax = INT_MAX; + enc_options->kmin = enc_options->kmax - 1; +} + +#define MAX_CACHED_FRAMES 30 + +static void SanitizeEncoderOptions(WebPAnimEncoderOptions* const enc_options) { + int print_warning = enc_options->verbose; + + if (enc_options->minimize_size) { + DisableKeyframes(enc_options); + } + + if (enc_options->kmin <= 0) { + DisableKeyframes(enc_options); + print_warning = 0; + } + if (enc_options->kmax <= 0) { // All frames will be key-frames. + enc_options->kmin = 0; + enc_options->kmax = 0; + return; + } + + if (enc_options->kmin >= enc_options->kmax) { + enc_options->kmin = enc_options->kmax - 1; + if (print_warning) { + fprintf(stderr, "WARNING: Setting kmin = %d, so that kmin < kmax.\n", + enc_options->kmin); + } + } else { + const int kmin_limit = enc_options->kmax / 2 + 1; + if (enc_options->kmin < kmin_limit && kmin_limit < enc_options->kmax) { + // This ensures that enc.keyframe + kmin >= kmax is always true. So, we + // can flush all the frames in the 'count_since_key_frame == kmax' case. + enc_options->kmin = kmin_limit; + if (print_warning) { + fprintf(stderr, + "WARNING: Setting kmin = %d, so that kmin >= kmax / 2 + 1.\n", + enc_options->kmin); + } + } + } + // Limit the max number of frames that are allocated. + if (enc_options->kmax - enc_options->kmin > MAX_CACHED_FRAMES) { + enc_options->kmin = enc_options->kmax - MAX_CACHED_FRAMES; + if (print_warning) { + fprintf(stderr, + "WARNING: Setting kmin = %d, so that kmax - kmin <= %d.\n", + enc_options->kmin, MAX_CACHED_FRAMES); + } + } + assert(enc_options->kmin < enc_options->kmax); +} + +#undef MAX_CACHED_FRAMES + +static void DefaultEncoderOptions(WebPAnimEncoderOptions* const enc_options) { + enc_options->anim_params.loop_count = 0; + enc_options->anim_params.bgcolor = 0xffffffff; // White. + enc_options->minimize_size = 0; + DisableKeyframes(enc_options); + enc_options->allow_mixed = 0; + enc_options->verbose = 0; +} + +int WebPAnimEncoderOptionsInitInternal(WebPAnimEncoderOptions* enc_options, + int abi_version) { + if (enc_options == NULL || + WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) { + return 0; + } + DefaultEncoderOptions(enc_options); + return 1; +} + +// This starting value is more fit to WebPCleanupTransparentAreaLossless(). +#define TRANSPARENT_COLOR 0x00000000 + +static void ClearRectangle(WebPPicture* const picture, + int left, int top, int width, int height) { + int j; + for (j = top; j < top + height; ++j) { + uint32_t* const dst = picture->argb + j * picture->argb_stride; + int i; + for (i = left; i < left + width; ++i) { + dst[i] = TRANSPARENT_COLOR; + } + } +} + +static void WebPUtilClearPic(WebPPicture* const picture, + const FrameRect* const rect) { + if (rect != NULL) { + ClearRectangle(picture, rect->x_offset_, rect->y_offset_, + rect->width_, rect->height_); + } else { + ClearRectangle(picture, 0, 0, picture->width, picture->height); + } +} + +static void MarkNoError(WebPAnimEncoder* const enc) { + enc->error_str_[0] = '\0'; // Empty string. +} + +static void MarkError(WebPAnimEncoder* const enc, const char* str) { + if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s.", str) < 0) { + assert(0); // FIX ME! + } +} + +static void MarkError2(WebPAnimEncoder* const enc, + const char* str, int error_code) { + if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s: %d.", str, + error_code) < 0) { + assert(0); // FIX ME! + } +} + +WebPAnimEncoder* WebPAnimEncoderNewInternal( + int width, int height, const WebPAnimEncoderOptions* enc_options, + int abi_version) { + WebPAnimEncoder* enc; + + if (WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) { + return NULL; + } + if (width <= 0 || height <= 0 || + (width * (uint64_t)height) >= MAX_IMAGE_AREA) { + return NULL; + } + + enc = (WebPAnimEncoder*)WebPSafeCalloc(1, sizeof(*enc)); + if (enc == NULL) return NULL; + // sanity inits, so we can call WebPAnimEncoderDelete(): + enc->encoded_frames_ = NULL; + enc->mux_ = NULL; + MarkNoError(enc); + + // Dimensions and options. + *(int*)&enc->canvas_width_ = width; + *(int*)&enc->canvas_height_ = height; + if (enc_options != NULL) { + *(WebPAnimEncoderOptions*)&enc->options_ = *enc_options; + SanitizeEncoderOptions((WebPAnimEncoderOptions*)&enc->options_); + } else { + DefaultEncoderOptions((WebPAnimEncoderOptions*)&enc->options_); + } + + // Canvas buffers. + if (!WebPPictureInit(&enc->curr_canvas_copy_) || + !WebPPictureInit(&enc->prev_canvas_) || + !WebPPictureInit(&enc->prev_canvas_disposed_)) { + goto Err; + } + enc->curr_canvas_copy_.width = width; + enc->curr_canvas_copy_.height = height; + enc->curr_canvas_copy_.use_argb = 1; + if (!WebPPictureAlloc(&enc->curr_canvas_copy_) || + !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_) || + !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_disposed_)) { + goto Err; + } + WebPUtilClearPic(&enc->prev_canvas_, NULL); + enc->curr_canvas_copy_modified_ = 1; + + // Encoded frames. + ResetCounters(enc); + // Note: one extra storage is for the previous frame. + enc->size_ = enc->options_.kmax - enc->options_.kmin + 1; + // We need space for at least 2 frames. But when kmin, kmax are both zero, + // enc->size_ will be 1. So we handle that special case below. + if (enc->size_ < 2) enc->size_ = 2; + enc->encoded_frames_ = + (EncodedFrame*)WebPSafeCalloc(enc->size_, sizeof(*enc->encoded_frames_)); + if (enc->encoded_frames_ == NULL) goto Err; + + enc->mux_ = WebPMuxNew(); + if (enc->mux_ == NULL) goto Err; + + enc->count_since_key_frame_ = 0; + enc->first_timestamp_ = 0; + enc->prev_timestamp_ = 0; + enc->prev_candidate_undecided_ = 0; + enc->is_first_frame_ = 1; + enc->got_null_frame_ = 0; + + return enc; // All OK. + + Err: + WebPAnimEncoderDelete(enc); + return NULL; +} + +// Release the data contained by 'encoded_frame'. +static void FrameRelease(EncodedFrame* const encoded_frame) { + if (encoded_frame != NULL) { + WebPDataClear(&encoded_frame->sub_frame_.bitstream); + WebPDataClear(&encoded_frame->key_frame_.bitstream); + memset(encoded_frame, 0, sizeof(*encoded_frame)); + } +} + +void WebPAnimEncoderDelete(WebPAnimEncoder* enc) { + if (enc != NULL) { + WebPPictureFree(&enc->curr_canvas_copy_); + WebPPictureFree(&enc->prev_canvas_); + WebPPictureFree(&enc->prev_canvas_disposed_); + if (enc->encoded_frames_ != NULL) { + size_t i; + for (i = 0; i < enc->size_; ++i) { + FrameRelease(&enc->encoded_frames_[i]); + } + WebPSafeFree(enc->encoded_frames_); + } + WebPMuxDelete(enc->mux_); + WebPSafeFree(enc); + } +} + +// ----------------------------------------------------------------------------- +// Frame addition. + +// Returns cached frame at the given 'position'. +static EncodedFrame* GetFrame(const WebPAnimEncoder* const enc, + size_t position) { + assert(enc->start_ + position < enc->size_); + return &enc->encoded_frames_[enc->start_ + position]; +} + +typedef int (*ComparePixelsFunc)(const uint32_t*, int, const uint32_t*, int, + int, int); + +// Returns true if 'length' number of pixels in 'src' and 'dst' are equal, +// assuming the given step sizes between pixels. +// 'max_allowed_diff' is unused and only there to allow function pointer use. +static WEBP_INLINE int ComparePixelsLossless(const uint32_t* src, int src_step, + const uint32_t* dst, int dst_step, + int length, int max_allowed_diff) { + (void)max_allowed_diff; + assert(length > 0); + while (length-- > 0) { + if (*src != *dst) { + return 0; + } + src += src_step; + dst += dst_step; + } + return 1; +} + +// Helper to check if each channel in 'src' and 'dst' is at most off by +// 'max_allowed_diff'. +static WEBP_INLINE int PixelsAreSimilar(uint32_t src, uint32_t dst, + int max_allowed_diff) { + const int src_a = (src >> 24) & 0xff; + const int src_r = (src >> 16) & 0xff; + const int src_g = (src >> 8) & 0xff; + const int src_b = (src >> 0) & 0xff; + const int dst_a = (dst >> 24) & 0xff; + const int dst_r = (dst >> 16) & 0xff; + const int dst_g = (dst >> 8) & 0xff; + const int dst_b = (dst >> 0) & 0xff; + + return (abs(src_r * src_a - dst_r * dst_a) <= (max_allowed_diff * 255)) && + (abs(src_g * src_a - dst_g * dst_a) <= (max_allowed_diff * 255)) && + (abs(src_b * src_a - dst_b * dst_a) <= (max_allowed_diff * 255)) && + (abs(src_a - dst_a) <= max_allowed_diff); +} + +// Returns true if 'length' number of pixels in 'src' and 'dst' are within an +// error bound, assuming the given step sizes between pixels. +static WEBP_INLINE int ComparePixelsLossy(const uint32_t* src, int src_step, + const uint32_t* dst, int dst_step, + int length, int max_allowed_diff) { + assert(length > 0); + while (length-- > 0) { + if (!PixelsAreSimilar(*src, *dst, max_allowed_diff)) { + return 0; + } + src += src_step; + dst += dst_step; + } + return 1; +} + +static int IsEmptyRect(const FrameRect* const rect) { + return (rect->width_ == 0) || (rect->height_ == 0); +} + +static int QualityToMaxDiff(float quality) { + const double val = pow(quality / 100., 0.5); + const double max_diff = 31 * (1 - val) + 1 * val; + return (int)(max_diff + 0.5); +} + +// Assumes that an initial valid guess of change rectangle 'rect' is passed. +static void MinimizeChangeRectangle(const WebPPicture* const src, + const WebPPicture* const dst, + FrameRect* const rect, + int is_lossless, float quality) { + int i, j; + const ComparePixelsFunc compare_pixels = + is_lossless ? ComparePixelsLossless : ComparePixelsLossy; + const int max_allowed_diff_lossy = QualityToMaxDiff(quality); + const int max_allowed_diff = is_lossless ? 0 : max_allowed_diff_lossy; + + // Sanity checks. + assert(src->width == dst->width && src->height == dst->height); + assert(rect->x_offset_ + rect->width_ <= dst->width); + assert(rect->y_offset_ + rect->height_ <= dst->height); + + // Left boundary. + for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { + const uint32_t* const src_argb = + &src->argb[rect->y_offset_ * src->argb_stride + i]; + const uint32_t* const dst_argb = + &dst->argb[rect->y_offset_ * dst->argb_stride + i]; + if (compare_pixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride, + rect->height_, max_allowed_diff)) { + --rect->width_; // Redundant column. + ++rect->x_offset_; + } else { + break; + } + } + if (rect->width_ == 0) goto NoChange; + + // Right boundary. + for (i = rect->x_offset_ + rect->width_ - 1; i >= rect->x_offset_; --i) { + const uint32_t* const src_argb = + &src->argb[rect->y_offset_ * src->argb_stride + i]; + const uint32_t* const dst_argb = + &dst->argb[rect->y_offset_ * dst->argb_stride + i]; + if (compare_pixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride, + rect->height_, max_allowed_diff)) { + --rect->width_; // Redundant column. + } else { + break; + } + } + if (rect->width_ == 0) goto NoChange; + + // Top boundary. + for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { + const uint32_t* const src_argb = + &src->argb[j * src->argb_stride + rect->x_offset_]; + const uint32_t* const dst_argb = + &dst->argb[j * dst->argb_stride + rect->x_offset_]; + if (compare_pixels(src_argb, 1, dst_argb, 1, rect->width_, + max_allowed_diff)) { + --rect->height_; // Redundant row. + ++rect->y_offset_; + } else { + break; + } + } + if (rect->height_ == 0) goto NoChange; + + // Bottom boundary. + for (j = rect->y_offset_ + rect->height_ - 1; j >= rect->y_offset_; --j) { + const uint32_t* const src_argb = + &src->argb[j * src->argb_stride + rect->x_offset_]; + const uint32_t* const dst_argb = + &dst->argb[j * dst->argb_stride + rect->x_offset_]; + if (compare_pixels(src_argb, 1, dst_argb, 1, rect->width_, + max_allowed_diff)) { + --rect->height_; // Redundant row. + } else { + break; + } + } + if (rect->height_ == 0) goto NoChange; + + if (IsEmptyRect(rect)) { + NoChange: + rect->x_offset_ = 0; + rect->y_offset_ = 0; + rect->width_ = 0; + rect->height_ = 0; + } +} + +// Snap rectangle to even offsets (and adjust dimensions if needed). +static WEBP_INLINE void SnapToEvenOffsets(FrameRect* const rect) { + rect->width_ += (rect->x_offset_ & 1); + rect->height_ += (rect->y_offset_ & 1); + rect->x_offset_ &= ~1; + rect->y_offset_ &= ~1; +} + +typedef struct { + int should_try_; // Should try this set of parameters. + int empty_rect_allowed_; // Frame with empty rectangle can be skipped. + FrameRect rect_ll_; // Frame rectangle for lossless compression. + WebPPicture sub_frame_ll_; // Sub-frame pic for lossless compression. + FrameRect rect_lossy_; // Frame rectangle for lossy compression. + // Could be smaller than rect_ll_ as pixels + // with small diffs can be ignored. + WebPPicture sub_frame_lossy_; // Sub-frame pic for lossless compression. +} SubFrameParams; + +static int SubFrameParamsInit(SubFrameParams* const params, + int should_try, int empty_rect_allowed) { + params->should_try_ = should_try; + params->empty_rect_allowed_ = empty_rect_allowed; + if (!WebPPictureInit(¶ms->sub_frame_ll_) || + !WebPPictureInit(¶ms->sub_frame_lossy_)) { + return 0; + } + return 1; +} + +static void SubFrameParamsFree(SubFrameParams* const params) { + WebPPictureFree(¶ms->sub_frame_ll_); + WebPPictureFree(¶ms->sub_frame_lossy_); +} + +// Given previous and current canvas, picks the optimal rectangle for the +// current frame based on 'is_lossless' and other parameters. Assumes that the +// initial guess 'rect' is valid. +static int GetSubRect(const WebPPicture* const prev_canvas, + const WebPPicture* const curr_canvas, int is_key_frame, + int is_first_frame, int empty_rect_allowed, + int is_lossless, float quality, FrameRect* const rect, + WebPPicture* const sub_frame) { + if (!is_key_frame || is_first_frame) { // Optimize frame rectangle. + // Note: This behaves as expected for first frame, as 'prev_canvas' is + // initialized to a fully transparent canvas in the beginning. + MinimizeChangeRectangle(prev_canvas, curr_canvas, rect, + is_lossless, quality); + } + + if (IsEmptyRect(rect)) { + if (empty_rect_allowed) { // No need to get 'sub_frame'. + return 1; + } else { // Force a 1x1 rectangle. + rect->width_ = 1; + rect->height_ = 1; + assert(rect->x_offset_ == 0); + assert(rect->y_offset_ == 0); + } + } + + SnapToEvenOffsets(rect); + return WebPPictureView(curr_canvas, rect->x_offset_, rect->y_offset_, + rect->width_, rect->height_, sub_frame); +} + +// Picks optimal frame rectangle for both lossless and lossy compression. The +// initial guess for frame rectangles will be the full canvas. +static int GetSubRects(const WebPPicture* const prev_canvas, + const WebPPicture* const curr_canvas, int is_key_frame, + int is_first_frame, float quality, + SubFrameParams* const params) { + // Lossless frame rectangle. + params->rect_ll_.x_offset_ = 0; + params->rect_ll_.y_offset_ = 0; + params->rect_ll_.width_ = curr_canvas->width; + params->rect_ll_.height_ = curr_canvas->height; + if (!GetSubRect(prev_canvas, curr_canvas, is_key_frame, is_first_frame, + params->empty_rect_allowed_, 1, quality, + ¶ms->rect_ll_, ¶ms->sub_frame_ll_)) { + return 0; + } + // Lossy frame rectangle. + params->rect_lossy_ = params->rect_ll_; // seed with lossless rect. + return GetSubRect(prev_canvas, curr_canvas, is_key_frame, is_first_frame, + params->empty_rect_allowed_, 0, quality, + ¶ms->rect_lossy_, ¶ms->sub_frame_lossy_); +} + +static void DisposeFrameRectangle(int dispose_method, + const FrameRect* const rect, + WebPPicture* const curr_canvas) { + assert(rect != NULL); + if (dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { + WebPUtilClearPic(curr_canvas, rect); + } +} + +static uint32_t RectArea(const FrameRect* const rect) { + return (uint32_t)rect->width_ * rect->height_; +} + +static int IsLosslessBlendingPossible(const WebPPicture* const src, + const WebPPicture* const dst, + const FrameRect* const rect) { + int i, j; + assert(src->width == dst->width && src->height == dst->height); + assert(rect->x_offset_ + rect->width_ <= dst->width); + assert(rect->y_offset_ + rect->height_ <= dst->height); + for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { + for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { + const uint32_t src_pixel = src->argb[j * src->argb_stride + i]; + const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i]; + const uint32_t dst_alpha = dst_pixel >> 24; + if (dst_alpha != 0xff && src_pixel != dst_pixel) { + // In this case, if we use blending, we can't attain the desired + // 'dst_pixel' value for this pixel. So, blending is not possible. + return 0; + } + } + } + return 1; +} + +static int IsLossyBlendingPossible(const WebPPicture* const src, + const WebPPicture* const dst, + const FrameRect* const rect, + float quality) { + const int max_allowed_diff_lossy = QualityToMaxDiff(quality); + int i, j; + assert(src->width == dst->width && src->height == dst->height); + assert(rect->x_offset_ + rect->width_ <= dst->width); + assert(rect->y_offset_ + rect->height_ <= dst->height); + for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { + for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { + const uint32_t src_pixel = src->argb[j * src->argb_stride + i]; + const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i]; + const uint32_t dst_alpha = dst_pixel >> 24; + if (dst_alpha != 0xff && + !PixelsAreSimilar(src_pixel, dst_pixel, max_allowed_diff_lossy)) { + // In this case, if we use blending, we can't attain the desired + // 'dst_pixel' value for this pixel. So, blending is not possible. + return 0; + } + } + } + return 1; +} + +// For pixels in 'rect', replace those pixels in 'dst' that are same as 'src' by +// transparent pixels. +// Returns true if at least one pixel gets modified. +static int IncreaseTransparency(const WebPPicture* const src, + const FrameRect* const rect, + WebPPicture* const dst) { + int i, j; + int modified = 0; + assert(src != NULL && dst != NULL && rect != NULL); + assert(src->width == dst->width && src->height == dst->height); + for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { + const uint32_t* const psrc = src->argb + j * src->argb_stride; + uint32_t* const pdst = dst->argb + j * dst->argb_stride; + for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { + if (psrc[i] == pdst[i] && pdst[i] != TRANSPARENT_COLOR) { + pdst[i] = TRANSPARENT_COLOR; + modified = 1; + } + } + } + return modified; +} + +#undef TRANSPARENT_COLOR + +// Replace similar blocks of pixels by a 'see-through' transparent block +// with uniform average color. +// Assumes lossy compression is being used. +// Returns true if at least one pixel gets modified. +static int FlattenSimilarBlocks(const WebPPicture* const src, + const FrameRect* const rect, + WebPPicture* const dst, float quality) { + const int max_allowed_diff_lossy = QualityToMaxDiff(quality); + int i, j; + int modified = 0; + const int block_size = 8; + const int y_start = (rect->y_offset_ + block_size) & ~(block_size - 1); + const int y_end = (rect->y_offset_ + rect->height_) & ~(block_size - 1); + const int x_start = (rect->x_offset_ + block_size) & ~(block_size - 1); + const int x_end = (rect->x_offset_ + rect->width_) & ~(block_size - 1); + assert(src != NULL && dst != NULL && rect != NULL); + assert(src->width == dst->width && src->height == dst->height); + assert((block_size & (block_size - 1)) == 0); // must be a power of 2 + // Iterate over each block and count similar pixels. + for (j = y_start; j < y_end; j += block_size) { + for (i = x_start; i < x_end; i += block_size) { + int cnt = 0; + int avg_r = 0, avg_g = 0, avg_b = 0; + int x, y; + const uint32_t* const psrc = src->argb + j * src->argb_stride + i; + uint32_t* const pdst = dst->argb + j * dst->argb_stride + i; + for (y = 0; y < block_size; ++y) { + for (x = 0; x < block_size; ++x) { + const uint32_t src_pixel = psrc[x + y * src->argb_stride]; + const int alpha = src_pixel >> 24; + if (alpha == 0xff && + PixelsAreSimilar(src_pixel, pdst[x + y * dst->argb_stride], + max_allowed_diff_lossy)) { + ++cnt; + avg_r += (src_pixel >> 16) & 0xff; + avg_g += (src_pixel >> 8) & 0xff; + avg_b += (src_pixel >> 0) & 0xff; + } + } + } + // If we have a fully similar block, we replace it with an + // average transparent block. This compresses better in lossy mode. + if (cnt == block_size * block_size) { + const uint32_t color = (0x00 << 24) | + ((avg_r / cnt) << 16) | + ((avg_g / cnt) << 8) | + ((avg_b / cnt) << 0); + for (y = 0; y < block_size; ++y) { + for (x = 0; x < block_size; ++x) { + pdst[x + y * dst->argb_stride] = color; + } + } + modified = 1; + } + } + } + return modified; +} + +static int EncodeFrame(const WebPConfig* const config, WebPPicture* const pic, + WebPMemoryWriter* const memory) { + pic->use_argb = 1; + pic->writer = WebPMemoryWrite; + pic->custom_ptr = memory; + if (!WebPEncode(config, pic)) { + return 0; + } + return 1; +} + +// Struct representing a candidate encoded frame including its metadata. +typedef struct { + WebPMemoryWriter mem_; + WebPMuxFrameInfo info_; + FrameRect rect_; + int evaluate_; // True if this candidate should be evaluated. +} Candidate; + +// Generates a candidate encoded frame given a picture and metadata. +static WebPEncodingError EncodeCandidate(WebPPicture* const sub_frame, + const FrameRect* const rect, + const WebPConfig* const encoder_config, + int use_blending, + Candidate* const candidate) { + WebPConfig config = *encoder_config; + WebPEncodingError error_code = VP8_ENC_OK; + assert(candidate != NULL); + memset(candidate, 0, sizeof(*candidate)); + + // Set frame rect and info. + candidate->rect_ = *rect; + candidate->info_.id = WEBP_CHUNK_ANMF; + candidate->info_.x_offset = rect->x_offset_; + candidate->info_.y_offset = rect->y_offset_; + candidate->info_.dispose_method = WEBP_MUX_DISPOSE_NONE; // Set later. + candidate->info_.blend_method = + use_blending ? WEBP_MUX_BLEND : WEBP_MUX_NO_BLEND; + candidate->info_.duration = 0; // Set in next call to WebPAnimEncoderAdd(). + + // Encode picture. + WebPMemoryWriterInit(&candidate->mem_); + + if (!config.lossless && use_blending) { + // Disable filtering to avoid blockiness in reconstructed frames at the + // time of decoding. + config.autofilter = 0; + config.filter_strength = 0; + } + if (!EncodeFrame(&config, sub_frame, &candidate->mem_)) { + error_code = sub_frame->error_code; + goto Err; + } + + candidate->evaluate_ = 1; + return error_code; + + Err: + WebPMemoryWriterClear(&candidate->mem_); + return error_code; +} + +static void CopyCurrentCanvas(WebPAnimEncoder* const enc) { + if (enc->curr_canvas_copy_modified_) { + WebPCopyPixels(enc->curr_canvas_, &enc->curr_canvas_copy_); + enc->curr_canvas_copy_.progress_hook = enc->curr_canvas_->progress_hook; + enc->curr_canvas_copy_.user_data = enc->curr_canvas_->user_data; + enc->curr_canvas_copy_modified_ = 0; + } +} + +enum { + LL_DISP_NONE = 0, + LL_DISP_BG, + LOSSY_DISP_NONE, + LOSSY_DISP_BG, + CANDIDATE_COUNT +}; + +#define MIN_COLORS_LOSSY 31 // Don't try lossy below this threshold. +#define MAX_COLORS_LOSSLESS 194 // Don't try lossless above this threshold. + +// Generates candidates for a given dispose method given pre-filled sub-frame +// 'params'. +static WebPEncodingError GenerateCandidates( + WebPAnimEncoder* const enc, Candidate candidates[CANDIDATE_COUNT], + WebPMuxAnimDispose dispose_method, int is_lossless, int is_key_frame, + SubFrameParams* const params, + const WebPConfig* const config_ll, const WebPConfig* const config_lossy) { + WebPEncodingError error_code = VP8_ENC_OK; + const int is_dispose_none = (dispose_method == WEBP_MUX_DISPOSE_NONE); + Candidate* const candidate_ll = + is_dispose_none ? &candidates[LL_DISP_NONE] : &candidates[LL_DISP_BG]; + Candidate* const candidate_lossy = is_dispose_none + ? &candidates[LOSSY_DISP_NONE] + : &candidates[LOSSY_DISP_BG]; + WebPPicture* const curr_canvas = &enc->curr_canvas_copy_; + const WebPPicture* const prev_canvas = + is_dispose_none ? &enc->prev_canvas_ : &enc->prev_canvas_disposed_; + int use_blending_ll; + int use_blending_lossy; + + CopyCurrentCanvas(enc); + use_blending_ll = + !is_key_frame && + IsLosslessBlendingPossible(prev_canvas, curr_canvas, ¶ms->rect_ll_); + use_blending_lossy = + !is_key_frame && + IsLossyBlendingPossible(prev_canvas, curr_canvas, ¶ms->rect_lossy_, + config_lossy->quality); + + // Pick candidates to be tried. + if (!enc->options_.allow_mixed) { + candidate_ll->evaluate_ = is_lossless; + candidate_lossy->evaluate_ = !is_lossless; + } else { // Use a heuristic for trying lossless and/or lossy compression. + const int num_colors = WebPGetColorPalette(¶ms->sub_frame_ll_, NULL); + candidate_ll->evaluate_ = (num_colors < MAX_COLORS_LOSSLESS); + candidate_lossy->evaluate_ = (num_colors >= MIN_COLORS_LOSSY); + } + + // Generate candidates. + if (candidate_ll->evaluate_) { + CopyCurrentCanvas(enc); + if (use_blending_ll) { + enc->curr_canvas_copy_modified_ = + IncreaseTransparency(prev_canvas, ¶ms->rect_ll_, curr_canvas); + } + error_code = EncodeCandidate(¶ms->sub_frame_ll_, ¶ms->rect_ll_, + config_ll, use_blending_ll, candidate_ll); + if (error_code != VP8_ENC_OK) return error_code; + } + if (candidate_lossy->evaluate_) { + CopyCurrentCanvas(enc); + if (use_blending_lossy) { + enc->curr_canvas_copy_modified_ = + FlattenSimilarBlocks(prev_canvas, ¶ms->rect_lossy_, curr_canvas, + config_lossy->quality); + } + error_code = + EncodeCandidate(¶ms->sub_frame_lossy_, ¶ms->rect_lossy_, + config_lossy, use_blending_lossy, candidate_lossy); + if (error_code != VP8_ENC_OK) return error_code; + enc->curr_canvas_copy_modified_ = 1; + } + return error_code; +} + +#undef MIN_COLORS_LOSSY +#undef MAX_COLORS_LOSSLESS + +static void GetEncodedData(const WebPMemoryWriter* const memory, + WebPData* const encoded_data) { + encoded_data->bytes = memory->mem; + encoded_data->size = memory->size; +} + +// Sets dispose method of the previous frame to be 'dispose_method'. +static void SetPreviousDisposeMethod(WebPAnimEncoder* const enc, + WebPMuxAnimDispose dispose_method) { + const size_t position = enc->count_ - 2; + EncodedFrame* const prev_enc_frame = GetFrame(enc, position); + assert(enc->count_ >= 2); // As current and previous frames are in enc. + + if (enc->prev_candidate_undecided_) { + assert(dispose_method == WEBP_MUX_DISPOSE_NONE); + prev_enc_frame->sub_frame_.dispose_method = dispose_method; + prev_enc_frame->key_frame_.dispose_method = dispose_method; + } else { + WebPMuxFrameInfo* const prev_info = prev_enc_frame->is_key_frame_ + ? &prev_enc_frame->key_frame_ + : &prev_enc_frame->sub_frame_; + prev_info->dispose_method = dispose_method; + } +} + +static int IncreasePreviousDuration(WebPAnimEncoder* const enc, int duration) { + const size_t position = enc->count_ - 1; + EncodedFrame* const prev_enc_frame = GetFrame(enc, position); + int new_duration; + + assert(enc->count_ >= 1); + assert(prev_enc_frame->sub_frame_.duration == + prev_enc_frame->key_frame_.duration); + assert(prev_enc_frame->sub_frame_.duration == + (prev_enc_frame->sub_frame_.duration & (MAX_DURATION - 1))); + assert(duration == (duration & (MAX_DURATION - 1))); + + new_duration = prev_enc_frame->sub_frame_.duration + duration; + if (new_duration >= MAX_DURATION) { // Special case. + // Separate out previous frame from earlier merged frames to avoid overflow. + // We add a 1x1 transparent frame for the previous frame, with blending on. + const FrameRect rect = { 0, 0, 1, 1 }; + const uint8_t lossless_1x1_bytes[] = { + 0x52, 0x49, 0x46, 0x46, 0x14, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, + 0x56, 0x50, 0x38, 0x4c, 0x08, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, + 0x10, 0x88, 0x88, 0x08 + }; + const WebPData lossless_1x1 = { + lossless_1x1_bytes, sizeof(lossless_1x1_bytes) + }; + const uint8_t lossy_1x1_bytes[] = { + 0x52, 0x49, 0x46, 0x46, 0x40, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, + 0x56, 0x50, 0x38, 0x58, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x4c, 0x50, 0x48, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x56, 0x50, 0x38, 0x20, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x01, 0x00, 0x9d, 0x01, 0x2a, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x34, 0x25, 0xa4, 0x00, 0x03, 0x70, 0x00, 0xfe, 0xfb, 0xfd, 0x50, 0x00 + }; + const WebPData lossy_1x1 = { lossy_1x1_bytes, sizeof(lossy_1x1_bytes) }; + const int can_use_lossless = + (enc->last_config_.lossless || enc->options_.allow_mixed); + EncodedFrame* const curr_enc_frame = GetFrame(enc, enc->count_); + curr_enc_frame->is_key_frame_ = 0; + curr_enc_frame->sub_frame_.id = WEBP_CHUNK_ANMF; + curr_enc_frame->sub_frame_.x_offset = 0; + curr_enc_frame->sub_frame_.y_offset = 0; + curr_enc_frame->sub_frame_.dispose_method = WEBP_MUX_DISPOSE_NONE; + curr_enc_frame->sub_frame_.blend_method = WEBP_MUX_BLEND; + curr_enc_frame->sub_frame_.duration = duration; + if (!WebPDataCopy(can_use_lossless ? &lossless_1x1 : &lossy_1x1, + &curr_enc_frame->sub_frame_.bitstream)) { + return 0; + } + ++enc->count_; + ++enc->count_since_key_frame_; + enc->flush_count_ = enc->count_ - 1; + enc->prev_candidate_undecided_ = 0; + enc->prev_rect_ = rect; + } else { // Regular case. + // Increase duration of the previous frame by 'duration'. + prev_enc_frame->sub_frame_.duration = new_duration; + prev_enc_frame->key_frame_.duration = new_duration; + } + return 1; +} + +// Pick the candidate encoded frame with smallest size and release other +// candidates. +// TODO(later): Perhaps a rough SSIM/PSNR produced by the encoder should +// also be a criteria, in addition to sizes. +static void PickBestCandidate(WebPAnimEncoder* const enc, + Candidate* const candidates, int is_key_frame, + EncodedFrame* const encoded_frame) { + int i; + int best_idx = -1; + size_t best_size = ~0; + for (i = 0; i < CANDIDATE_COUNT; ++i) { + if (candidates[i].evaluate_) { + const size_t candidate_size = candidates[i].mem_.size; + if (candidate_size < best_size) { + best_idx = i; + best_size = candidate_size; + } + } + } + assert(best_idx != -1); + for (i = 0; i < CANDIDATE_COUNT; ++i) { + if (candidates[i].evaluate_) { + if (i == best_idx) { + WebPMuxFrameInfo* const dst = is_key_frame + ? &encoded_frame->key_frame_ + : &encoded_frame->sub_frame_; + *dst = candidates[i].info_; + GetEncodedData(&candidates[i].mem_, &dst->bitstream); + if (!is_key_frame) { + // Note: Previous dispose method only matters for non-keyframes. + // Also, we don't want to modify previous dispose method that was + // selected when a non key-frame was assumed. + const WebPMuxAnimDispose prev_dispose_method = + (best_idx == LL_DISP_NONE || best_idx == LOSSY_DISP_NONE) + ? WEBP_MUX_DISPOSE_NONE + : WEBP_MUX_DISPOSE_BACKGROUND; + SetPreviousDisposeMethod(enc, prev_dispose_method); + } + enc->prev_rect_ = candidates[i].rect_; // save for next frame. + } else { + WebPMemoryWriterClear(&candidates[i].mem_); + candidates[i].evaluate_ = 0; + } + } + } +} + +// Depending on the configuration, tries different compressions +// (lossy/lossless), dispose methods, blending methods etc to encode the current +// frame and outputs the best one in 'encoded_frame'. +// 'frame_skipped' will be set to true if this frame should actually be skipped. +static WebPEncodingError SetFrame(WebPAnimEncoder* const enc, + const WebPConfig* const config, + int is_key_frame, + EncodedFrame* const encoded_frame, + int* const frame_skipped) { + int i; + WebPEncodingError error_code = VP8_ENC_OK; + const WebPPicture* const curr_canvas = &enc->curr_canvas_copy_; + const WebPPicture* const prev_canvas = &enc->prev_canvas_; + Candidate candidates[CANDIDATE_COUNT]; + const int is_lossless = config->lossless; + const int is_first_frame = enc->is_first_frame_; + + // First frame cannot be skipped as there is no 'previous frame' to merge it + // to. So, empty rectangle is not allowed for the first frame. + const int empty_rect_allowed_none = !is_first_frame; + + // Even if there is exact pixel match between 'disposed previous canvas' and + // 'current canvas', we can't skip current frame, as there may not be exact + // pixel match between 'previous canvas' and 'current canvas'. So, we don't + // allow empty rectangle in this case. + const int empty_rect_allowed_bg = 0; + + // If current frame is a key-frame, dispose method of previous frame doesn't + // matter, so we don't try dispose to background. + // Also, if key-frame insertion is on, and previous frame could be picked as + // either a sub-frame or a key-frame, then we can't be sure about what frame + // rectangle would be disposed. In that case too, we don't try dispose to + // background. + const int dispose_bg_possible = + !is_key_frame && !enc->prev_candidate_undecided_; + + SubFrameParams dispose_none_params; + SubFrameParams dispose_bg_params; + + WebPConfig config_ll = *config; + WebPConfig config_lossy = *config; + config_ll.lossless = 1; + config_lossy.lossless = 0; + enc->last_config_ = *config; + enc->last_config_reversed_ = config->lossless ? config_lossy : config_ll; + *frame_skipped = 0; + + if (!SubFrameParamsInit(&dispose_none_params, 1, empty_rect_allowed_none) || + !SubFrameParamsInit(&dispose_bg_params, 0, empty_rect_allowed_bg)) { + return VP8_ENC_ERROR_INVALID_CONFIGURATION; + } + + for (i = 0; i < CANDIDATE_COUNT; ++i) { + candidates[i].evaluate_ = 0; + } + + // Change-rectangle assuming previous frame was DISPOSE_NONE. + if (!GetSubRects(prev_canvas, curr_canvas, is_key_frame, is_first_frame, + config_lossy.quality, &dispose_none_params)) { + error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; + goto Err; + } + + if ((is_lossless && IsEmptyRect(&dispose_none_params.rect_ll_)) || + (!is_lossless && IsEmptyRect(&dispose_none_params.rect_lossy_))) { + // Don't encode the frame at all. Instead, the duration of the previous + // frame will be increased later. + assert(empty_rect_allowed_none); + *frame_skipped = 1; + goto End; + } + + if (dispose_bg_possible) { + // Change-rectangle assuming previous frame was DISPOSE_BACKGROUND. + WebPPicture* const prev_canvas_disposed = &enc->prev_canvas_disposed_; + WebPCopyPixels(prev_canvas, prev_canvas_disposed); + DisposeFrameRectangle(WEBP_MUX_DISPOSE_BACKGROUND, &enc->prev_rect_, + prev_canvas_disposed); + + if (!GetSubRects(prev_canvas_disposed, curr_canvas, is_key_frame, + is_first_frame, config_lossy.quality, + &dispose_bg_params)) { + error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; + goto Err; + } + assert(!IsEmptyRect(&dispose_bg_params.rect_ll_)); + assert(!IsEmptyRect(&dispose_bg_params.rect_lossy_)); + + if (enc->options_.minimize_size) { // Try both dispose methods. + dispose_bg_params.should_try_ = 1; + dispose_none_params.should_try_ = 1; + } else if ((is_lossless && + RectArea(&dispose_bg_params.rect_ll_) < + RectArea(&dispose_none_params.rect_ll_)) || + (!is_lossless && + RectArea(&dispose_bg_params.rect_lossy_) < + RectArea(&dispose_none_params.rect_lossy_))) { + dispose_bg_params.should_try_ = 1; // Pick DISPOSE_BACKGROUND. + dispose_none_params.should_try_ = 0; + } + } + + if (dispose_none_params.should_try_) { + error_code = GenerateCandidates( + enc, candidates, WEBP_MUX_DISPOSE_NONE, is_lossless, is_key_frame, + &dispose_none_params, &config_ll, &config_lossy); + if (error_code != VP8_ENC_OK) goto Err; + } + + if (dispose_bg_params.should_try_) { + assert(!enc->is_first_frame_); + assert(dispose_bg_possible); + error_code = GenerateCandidates( + enc, candidates, WEBP_MUX_DISPOSE_BACKGROUND, is_lossless, is_key_frame, + &dispose_bg_params, &config_ll, &config_lossy); + if (error_code != VP8_ENC_OK) goto Err; + } + + PickBestCandidate(enc, candidates, is_key_frame, encoded_frame); + + goto End; + + Err: + for (i = 0; i < CANDIDATE_COUNT; ++i) { + if (candidates[i].evaluate_) { + WebPMemoryWriterClear(&candidates[i].mem_); + } + } + + End: + SubFrameParamsFree(&dispose_none_params); + SubFrameParamsFree(&dispose_bg_params); + return error_code; +} + +// Calculate the penalty incurred if we encode given frame as a key frame +// instead of a sub-frame. +static int64_t KeyFramePenalty(const EncodedFrame* const encoded_frame) { + return ((int64_t)encoded_frame->key_frame_.bitstream.size - + encoded_frame->sub_frame_.bitstream.size); +} + +static int CacheFrame(WebPAnimEncoder* const enc, + const WebPConfig* const config) { + int ok = 0; + int frame_skipped = 0; + WebPEncodingError error_code = VP8_ENC_OK; + const size_t position = enc->count_; + EncodedFrame* const encoded_frame = GetFrame(enc, position); + + ++enc->count_; + + if (enc->is_first_frame_) { // Add this as a key-frame. + error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped); + if (error_code != VP8_ENC_OK) goto End; + assert(frame_skipped == 0); // First frame can't be skipped, even if empty. + assert(position == 0 && enc->count_ == 1); + encoded_frame->is_key_frame_ = 1; + enc->flush_count_ = 0; + enc->count_since_key_frame_ = 0; + enc->prev_candidate_undecided_ = 0; + } else { + ++enc->count_since_key_frame_; + if (enc->count_since_key_frame_ <= enc->options_.kmin) { + // Add this as a frame rectangle. + error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped); + if (error_code != VP8_ENC_OK) goto End; + if (frame_skipped) goto Skip; + encoded_frame->is_key_frame_ = 0; + enc->flush_count_ = enc->count_ - 1; + enc->prev_candidate_undecided_ = 0; + } else { + int64_t curr_delta; + + // Add this as a frame rectangle to enc. + error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped); + if (error_code != VP8_ENC_OK) goto End; + if (frame_skipped) goto Skip; + + // Add this as a key-frame to enc, too. + error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped); + if (error_code != VP8_ENC_OK) goto End; + assert(frame_skipped == 0); // Key-frame cannot be an empty rectangle. + + // Analyze size difference of the two variants. + curr_delta = KeyFramePenalty(encoded_frame); + if (curr_delta <= enc->best_delta_) { // Pick this as the key-frame. + if (enc->keyframe_ != KEYFRAME_NONE) { + EncodedFrame* const old_keyframe = GetFrame(enc, enc->keyframe_); + assert(old_keyframe->is_key_frame_); + old_keyframe->is_key_frame_ = 0; + } + encoded_frame->is_key_frame_ = 1; + enc->keyframe_ = (int)position; + enc->best_delta_ = curr_delta; + enc->flush_count_ = enc->count_ - 1; // We can flush previous frames. + } else { + encoded_frame->is_key_frame_ = 0; + } + // Note: We need '>=' below because when kmin and kmax are both zero, + // count_since_key_frame will always be > kmax. + if (enc->count_since_key_frame_ >= enc->options_.kmax) { + enc->flush_count_ = enc->count_ - 1; + enc->count_since_key_frame_ = 0; + enc->keyframe_ = KEYFRAME_NONE; + enc->best_delta_ = DELTA_INFINITY; + } + enc->prev_candidate_undecided_ = 1; + } + } + + // Update previous to previous and previous canvases for next call. + WebPCopyPixels(enc->curr_canvas_, &enc->prev_canvas_); + enc->is_first_frame_ = 0; + + Skip: + ok = 1; + ++enc->in_frame_count_; + + End: + if (!ok || frame_skipped) { + FrameRelease(encoded_frame); + // We reset some counters, as the frame addition failed/was skipped. + --enc->count_; + if (!enc->is_first_frame_) --enc->count_since_key_frame_; + if (!ok) { + MarkError2(enc, "ERROR adding frame. WebPEncodingError", error_code); + } + } + enc->curr_canvas_->error_code = error_code; // report error_code + assert(ok || error_code != VP8_ENC_OK); + return ok; +} + +static int FlushFrames(WebPAnimEncoder* const enc) { + while (enc->flush_count_ > 0) { + WebPMuxError err; + EncodedFrame* const curr = GetFrame(enc, 0); + const WebPMuxFrameInfo* const info = + curr->is_key_frame_ ? &curr->key_frame_ : &curr->sub_frame_; + assert(enc->mux_ != NULL); + err = WebPMuxPushFrame(enc->mux_, info, 1); + if (err != WEBP_MUX_OK) { + MarkError2(enc, "ERROR adding frame. WebPMuxError", err); + return 0; + } + if (enc->options_.verbose) { + fprintf(stderr, "INFO: Added frame. offset:%d,%d dispose:%d blend:%d\n", + info->x_offset, info->y_offset, info->dispose_method, + info->blend_method); + } + ++enc->out_frame_count_; + FrameRelease(curr); + ++enc->start_; + --enc->flush_count_; + --enc->count_; + if (enc->keyframe_ != KEYFRAME_NONE) --enc->keyframe_; + } + + if (enc->count_ == 1 && enc->start_ != 0) { + // Move enc->start to index 0. + const int enc_start_tmp = (int)enc->start_; + EncodedFrame temp = enc->encoded_frames_[0]; + enc->encoded_frames_[0] = enc->encoded_frames_[enc_start_tmp]; + enc->encoded_frames_[enc_start_tmp] = temp; + FrameRelease(&enc->encoded_frames_[enc_start_tmp]); + enc->start_ = 0; + } + return 1; +} + +#undef DELTA_INFINITY +#undef KEYFRAME_NONE + +int WebPAnimEncoderAdd(WebPAnimEncoder* enc, WebPPicture* frame, int timestamp, + const WebPConfig* encoder_config) { + WebPConfig config; + int ok; + + if (enc == NULL) { + return 0; + } + MarkNoError(enc); + + if (!enc->is_first_frame_) { + // Make sure timestamps are non-decreasing (integer wrap-around is OK). + const uint32_t prev_frame_duration = + (uint32_t)timestamp - enc->prev_timestamp_; + if (prev_frame_duration >= MAX_DURATION) { + if (frame != NULL) { + frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; + } + MarkError(enc, "ERROR adding frame: timestamps must be non-decreasing"); + return 0; + } + if (!IncreasePreviousDuration(enc, (int)prev_frame_duration)) { + return 0; + } + } else { + enc->first_timestamp_ = timestamp; + } + + if (frame == NULL) { // Special: last call. + enc->got_null_frame_ = 1; + enc->prev_timestamp_ = timestamp; + return 1; + } + + if (frame->width != enc->canvas_width_ || + frame->height != enc->canvas_height_) { + frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; + MarkError(enc, "ERROR adding frame: Invalid frame dimensions"); + return 0; + } + + if (!frame->use_argb) { // Convert frame from YUV(A) to ARGB. + if (enc->options_.verbose) { + fprintf(stderr, "WARNING: Converting frame from YUV(A) to ARGB format; " + "this incurs a small loss.\n"); + } + if (!WebPPictureYUVAToARGB(frame)) { + MarkError(enc, "ERROR converting frame from YUV(A) to ARGB"); + return 0; + } + } + + if (encoder_config != NULL) { + if (!WebPValidateConfig(encoder_config)) { + MarkError(enc, "ERROR adding frame: Invalid WebPConfig"); + return 0; + } + config = *encoder_config; + } else { + WebPConfigInit(&config); + config.lossless = 1; + } + assert(enc->curr_canvas_ == NULL); + enc->curr_canvas_ = frame; // Store reference. + assert(enc->curr_canvas_copy_modified_ == 1); + CopyCurrentCanvas(enc); + + ok = CacheFrame(enc, &config) && FlushFrames(enc); + + enc->curr_canvas_ = NULL; + enc->curr_canvas_copy_modified_ = 1; + if (ok) { + enc->prev_timestamp_ = timestamp; + } + return ok; +} + +// ----------------------------------------------------------------------------- +// Bitstream assembly. + +static int DecodeFrameOntoCanvas(const WebPMuxFrameInfo* const frame, + WebPPicture* const canvas) { + const WebPData* const image = &frame->bitstream; + WebPPicture sub_image; + WebPDecoderConfig config; + WebPInitDecoderConfig(&config); + WebPUtilClearPic(canvas, NULL); + if (WebPGetFeatures(image->bytes, image->size, &config.input) != + VP8_STATUS_OK) { + return 0; + } + if (!WebPPictureView(canvas, frame->x_offset, frame->y_offset, + config.input.width, config.input.height, &sub_image)) { + return 0; + } + config.output.is_external_memory = 1; + config.output.colorspace = MODE_BGRA; + config.output.u.RGBA.rgba = (uint8_t*)sub_image.argb; + config.output.u.RGBA.stride = sub_image.argb_stride * 4; + config.output.u.RGBA.size = config.output.u.RGBA.stride * sub_image.height; + + if (WebPDecode(image->bytes, image->size, &config) != VP8_STATUS_OK) { + return 0; + } + return 1; +} + +static int FrameToFullCanvas(WebPAnimEncoder* const enc, + const WebPMuxFrameInfo* const frame, + WebPData* const full_image) { + WebPPicture* const canvas_buf = &enc->curr_canvas_copy_; + WebPMemoryWriter mem1, mem2; + WebPMemoryWriterInit(&mem1); + WebPMemoryWriterInit(&mem2); + + if (!DecodeFrameOntoCanvas(frame, canvas_buf)) goto Err; + if (!EncodeFrame(&enc->last_config_, canvas_buf, &mem1)) goto Err; + GetEncodedData(&mem1, full_image); + + if (enc->options_.allow_mixed) { + if (!EncodeFrame(&enc->last_config_reversed_, canvas_buf, &mem2)) goto Err; + if (mem2.size < mem1.size) { + GetEncodedData(&mem2, full_image); + WebPMemoryWriterClear(&mem1); + } else { + WebPMemoryWriterClear(&mem2); + } + } + return 1; + + Err: + WebPMemoryWriterClear(&mem1); + WebPMemoryWriterClear(&mem2); + return 0; +} + +// Convert a single-frame animation to a non-animated image if appropriate. +// TODO(urvang): Can we pick one of the two heuristically (based on frame +// rectangle and/or presence of alpha)? +static WebPMuxError OptimizeSingleFrame(WebPAnimEncoder* const enc, + WebPData* const webp_data) { + WebPMuxError err = WEBP_MUX_OK; + int canvas_width, canvas_height; + WebPMuxFrameInfo frame; + WebPData full_image; + WebPData webp_data2; + WebPMux* const mux = WebPMuxCreate(webp_data, 0); + if (mux == NULL) return WEBP_MUX_BAD_DATA; + assert(enc->out_frame_count_ == 1); + WebPDataInit(&frame.bitstream); + WebPDataInit(&full_image); + WebPDataInit(&webp_data2); + + err = WebPMuxGetFrame(mux, 1, &frame); + if (err != WEBP_MUX_OK) goto End; + if (frame.id != WEBP_CHUNK_ANMF) goto End; // Non-animation: nothing to do. + err = WebPMuxGetCanvasSize(mux, &canvas_width, &canvas_height); + if (err != WEBP_MUX_OK) goto End; + if (!FrameToFullCanvas(enc, &frame, &full_image)) { + err = WEBP_MUX_BAD_DATA; + goto End; + } + err = WebPMuxSetImage(mux, &full_image, 1); + if (err != WEBP_MUX_OK) goto End; + err = WebPMuxAssemble(mux, &webp_data2); + if (err != WEBP_MUX_OK) goto End; + + if (webp_data2.size < webp_data->size) { // Pick 'webp_data2' if smaller. + WebPDataClear(webp_data); + *webp_data = webp_data2; + WebPDataInit(&webp_data2); + } + + End: + WebPDataClear(&frame.bitstream); + WebPDataClear(&full_image); + WebPMuxDelete(mux); + WebPDataClear(&webp_data2); + return err; +} + +int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, WebPData* webp_data) { + WebPMux* mux; + WebPMuxError err; + + if (enc == NULL) { + return 0; + } + MarkNoError(enc); + + if (webp_data == NULL) { + MarkError(enc, "ERROR assembling: NULL input"); + return 0; + } + + if (enc->in_frame_count_ == 0) { + MarkError(enc, "ERROR: No frames to assemble"); + return 0; + } + + if (!enc->got_null_frame_ && enc->in_frame_count_ > 1 && enc->count_ > 0) { + // set duration of the last frame to be avg of durations of previous frames. + const double delta_time = enc->prev_timestamp_ - enc->first_timestamp_; + const int average_duration = (int)(delta_time / (enc->in_frame_count_ - 1)); + if (!IncreasePreviousDuration(enc, average_duration)) { + return 0; + } + } + + // Flush any remaining frames. + enc->flush_count_ = enc->count_; + if (!FlushFrames(enc)) { + return 0; + } + + // Set definitive canvas size. + mux = enc->mux_; + err = WebPMuxSetCanvasSize(mux, enc->canvas_width_, enc->canvas_height_); + if (err != WEBP_MUX_OK) goto Err; + + err = WebPMuxSetAnimationParams(mux, &enc->options_.anim_params); + if (err != WEBP_MUX_OK) goto Err; + + // Assemble into a WebP bitstream. + err = WebPMuxAssemble(mux, webp_data); + if (err != WEBP_MUX_OK) goto Err; + + if (enc->out_frame_count_ == 1) { + err = OptimizeSingleFrame(enc, webp_data); + if (err != WEBP_MUX_OK) goto Err; + } + return 1; + + Err: + MarkError2(enc, "ERROR assembling WebP", err); + return 0; +} + +const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc) { + if (enc == NULL) return NULL; + return enc->error_str_; +} + +// ----------------------------------------------------------------------------- diff --git a/drivers/webp/mux/muxedit.c b/thirdparty/libwebp/mux/muxedit.c index 9bbed42b1a..9bbed42b1a 100644 --- a/drivers/webp/mux/muxedit.c +++ b/thirdparty/libwebp/mux/muxedit.c diff --git a/thirdparty/libwebp/mux/muxi.h b/thirdparty/libwebp/mux/muxi.h new file mode 100644 index 0000000000..d4d5cbad91 --- /dev/null +++ b/thirdparty/libwebp/mux/muxi.h @@ -0,0 +1,232 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for mux library. +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_MUX_MUXI_H_ +#define WEBP_MUX_MUXI_H_ + +#include <stdlib.h> +#include "../dec/vp8i.h" +#include "../dec/vp8li.h" +#include "../webp/mux.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Defines and constants. + +#define MUX_MAJ_VERSION 0 +#define MUX_MIN_VERSION 3 +#define MUX_REV_VERSION 1 + +// Chunk object. +typedef struct WebPChunk WebPChunk; +struct WebPChunk { + uint32_t tag_; + int owner_; // True if *data_ memory is owned internally. + // VP8X, ANIM, and other internally created chunks + // like ANMF/FRGM are always owned. + WebPData data_; + WebPChunk* next_; +}; + +// MuxImage object. Store a full WebP image (including ANMF/FRGM chunk, ALPH +// chunk and VP8/VP8L chunk), +typedef struct WebPMuxImage WebPMuxImage; +struct WebPMuxImage { + WebPChunk* header_; // Corresponds to WEBP_CHUNK_ANMF/WEBP_CHUNK_FRGM. + WebPChunk* alpha_; // Corresponds to WEBP_CHUNK_ALPHA. + WebPChunk* img_; // Corresponds to WEBP_CHUNK_IMAGE. + WebPChunk* unknown_; // Corresponds to WEBP_CHUNK_UNKNOWN. + int width_; + int height_; + int has_alpha_; // Through ALPH chunk or as part of VP8L. + int is_partial_; // True if only some of the chunks are filled. + WebPMuxImage* next_; +}; + +// Main mux object. Stores data chunks. +struct WebPMux { + WebPMuxImage* images_; + WebPChunk* iccp_; + WebPChunk* exif_; + WebPChunk* xmp_; + WebPChunk* anim_; + WebPChunk* vp8x_; + + WebPChunk* unknown_; + int canvas_width_; + int canvas_height_; +}; + +// CHUNK_INDEX enum: used for indexing within 'kChunks' (defined below) only. +// Note: the reason for having two enums ('WebPChunkId' and 'CHUNK_INDEX') is to +// allow two different chunks to have the same id (e.g. WebPChunkId +// 'WEBP_CHUNK_IMAGE' can correspond to CHUNK_INDEX 'IDX_VP8' or 'IDX_VP8L'). +typedef enum { + IDX_VP8X = 0, + IDX_ICCP, + IDX_ANIM, + IDX_ANMF, + IDX_FRGM, + IDX_ALPHA, + IDX_VP8, + IDX_VP8L, + IDX_EXIF, + IDX_XMP, + IDX_UNKNOWN, + + IDX_NIL, + IDX_LAST_CHUNK +} CHUNK_INDEX; + +#define NIL_TAG 0x00000000u // To signal void chunk. + +typedef struct { + uint32_t tag; + WebPChunkId id; + uint32_t size; +} ChunkInfo; + +extern const ChunkInfo kChunks[IDX_LAST_CHUNK]; + +//------------------------------------------------------------------------------ +// Chunk object management. + +// Initialize. +void ChunkInit(WebPChunk* const chunk); + +// Get chunk index from chunk tag. Returns IDX_UNKNOWN if not found. +CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag); + +// Get chunk id from chunk tag. Returns WEBP_CHUNK_UNKNOWN if not found. +WebPChunkId ChunkGetIdFromTag(uint32_t tag); + +// Convert a fourcc string to a tag. +uint32_t ChunkGetTagFromFourCC(const char fourcc[4]); + +// Get chunk index from fourcc. Returns IDX_UNKNOWN if given fourcc is unknown. +CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]); + +// Search for nth chunk with given 'tag' in the chunk list. +// nth = 0 means "last of the list". +WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag); + +// Fill the chunk with the given data. +WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data, + int copy_data, uint32_t tag); + +// Sets 'chunk' at nth position in the 'chunk_list'. +// nth = 0 has the special meaning "last of the list". +// On success ownership is transferred from 'chunk' to the 'chunk_list'. +WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list, + uint32_t nth); + +// Releases chunk and returns chunk->next_. +WebPChunk* ChunkRelease(WebPChunk* const chunk); + +// Deletes given chunk & returns chunk->next_. +WebPChunk* ChunkDelete(WebPChunk* const chunk); + +// Deletes all chunks in the given chunk list. +void ChunkListDelete(WebPChunk** const chunk_list); + +// Returns size of the chunk including chunk header and padding byte (if any). +static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) { + return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U); +} + +// Size of a chunk including header and padding. +static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) { + const size_t data_size = chunk->data_.size; + assert(data_size < MAX_CHUNK_PAYLOAD); + return SizeWithPadding(data_size); +} + +// Total size of a list of chunks. +size_t ChunkListDiskSize(const WebPChunk* chunk_list); + +// Write out the given list of chunks into 'dst'. +uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst); + +//------------------------------------------------------------------------------ +// MuxImage object management. + +// Initialize. +void MuxImageInit(WebPMuxImage* const wpi); + +// Releases image 'wpi' and returns wpi->next. +WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi); + +// Delete image 'wpi' and return the next image in the list or NULL. +// 'wpi' can be NULL. +WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi); + +// Count number of images matching the given tag id in the 'wpi_list'. +// If id == WEBP_CHUNK_NIL, all images will be matched. +int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id); + +// Update width/height/has_alpha info from chunks within wpi. +// Also remove ALPH chunk if not needed. +int MuxImageFinalize(WebPMuxImage* const wpi); + +// Check if given ID corresponds to an image related chunk. +static WEBP_INLINE int IsWPI(WebPChunkId id) { + switch (id) { + case WEBP_CHUNK_ANMF: + case WEBP_CHUNK_FRGM: + case WEBP_CHUNK_ALPHA: + case WEBP_CHUNK_IMAGE: return 1; + default: return 0; + } +} + +// Pushes 'wpi' at the end of 'wpi_list'. +WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list); + +// Delete nth image in the image list. +WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth); + +// Get nth image in the image list. +WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, + WebPMuxImage** wpi); + +// Total size of the given image. +size_t MuxImageDiskSize(const WebPMuxImage* const wpi); + +// Write out the given image into 'dst'. +uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst); + +//------------------------------------------------------------------------------ +// Helper methods for mux. + +// Checks if the given image list contains at least one image with alpha. +int MuxHasAlpha(const WebPMuxImage* images); + +// Write out RIFF header into 'data', given total data size 'size'. +uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size); + +// Returns the list where chunk with given ID is to be inserted in mux. +WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id); + +// Validates the given mux object. +WebPMuxError MuxValidate(const WebPMux* const mux); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_MUX_MUXI_H_ */ diff --git a/drivers/webp/mux/muxinternal.c b/thirdparty/libwebp/mux/muxinternal.c index 4babbe82fc..4babbe82fc 100644 --- a/drivers/webp/mux/muxinternal.c +++ b/thirdparty/libwebp/mux/muxinternal.c diff --git a/drivers/webp/mux/muxread.c b/thirdparty/libwebp/mux/muxread.c index 8957a1e46e..8957a1e46e 100644 --- a/drivers/webp/mux/muxread.c +++ b/thirdparty/libwebp/mux/muxread.c diff --git a/thirdparty/libwebp/utils/bit_reader.c b/thirdparty/libwebp/utils/bit_reader.c new file mode 100644 index 0000000000..2eb46e0b4b --- /dev/null +++ b/thirdparty/libwebp/utils/bit_reader.c @@ -0,0 +1,229 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Boolean decoder non-inlined methods +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifdef HAVE_CONFIG_H +#include "../webp/config.h" +#endif + +#include "./bit_reader_inl.h" +#include "../utils/utils.h" + +//------------------------------------------------------------------------------ +// VP8BitReader + +void VP8BitReaderSetBuffer(VP8BitReader* const br, + const uint8_t* const start, + size_t size) { + br->buf_ = start; + br->buf_end_ = start + size; + br->buf_max_ = + (size >= sizeof(lbit_t)) ? start + size - sizeof(lbit_t) + 1 + : start; +} + +void VP8InitBitReader(VP8BitReader* const br, + const uint8_t* const start, size_t size) { + assert(br != NULL); + assert(start != NULL); + assert(size < (1u << 31)); // limit ensured by format and upstream checks + br->range_ = 255 - 1; + br->value_ = 0; + br->bits_ = -8; // to load the very first 8bits + br->eof_ = 0; + VP8BitReaderSetBuffer(br, start, size); +// -- GODOT -- begin +#ifdef JAVASCRIPT_ENABLED // html5 required aligned reads + while(((uintptr_t)br->buf_ & 1) != 0 && !br->eof_) + VP8LoadFinalBytes(br); +#else + VP8LoadNewBytes(br); +#endif +// -- GODOT -- end +} + +void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) { + if (br->buf_ != NULL) { + br->buf_ += offset; + br->buf_end_ += offset; + br->buf_max_ += offset; + } +} + +const uint8_t kVP8Log2Range[128] = { + 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, + 0 +}; + +// range = ((range - 1) << kVP8Log2Range[range]) + 1 +const uint8_t kVP8NewRange[128] = { + 127, 127, 191, 127, 159, 191, 223, 127, + 143, 159, 175, 191, 207, 223, 239, 127, + 135, 143, 151, 159, 167, 175, 183, 191, + 199, 207, 215, 223, 231, 239, 247, 127, + 131, 135, 139, 143, 147, 151, 155, 159, + 163, 167, 171, 175, 179, 183, 187, 191, + 195, 199, 203, 207, 211, 215, 219, 223, + 227, 231, 235, 239, 243, 247, 251, 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, 127 +}; + +void VP8LoadFinalBytes(VP8BitReader* const br) { + assert(br != NULL && br->buf_ != NULL); + // Only read 8bits at a time + if (br->buf_ < br->buf_end_) { + br->bits_ += 8; + br->value_ = (bit_t)(*br->buf_++) | (br->value_ << 8); + } else if (!br->eof_) { + br->value_ <<= 8; + br->bits_ += 8; + br->eof_ = 1; + } else { + br->bits_ = 0; // This is to avoid undefined behaviour with shifts. + } +} + +//------------------------------------------------------------------------------ +// Higher-level calls + +uint32_t VP8GetValue(VP8BitReader* const br, int bits) { + uint32_t v = 0; + while (bits-- > 0) { + v |= VP8GetBit(br, 0x80) << bits; + } + return v; +} + +int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) { + const int value = VP8GetValue(br, bits); + return VP8Get(br) ? -value : value; +} + +//------------------------------------------------------------------------------ +// VP8LBitReader + +#define VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits. + +#if defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \ + defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64__) || defined(_M_X64) +#define VP8L_USE_FAST_LOAD +#endif + +static const uint32_t kBitMask[VP8L_MAX_NUM_BIT_READ + 1] = { + 0, + 0x000001, 0x000003, 0x000007, 0x00000f, + 0x00001f, 0x00003f, 0x00007f, 0x0000ff, + 0x0001ff, 0x0003ff, 0x0007ff, 0x000fff, + 0x001fff, 0x003fff, 0x007fff, 0x00ffff, + 0x01ffff, 0x03ffff, 0x07ffff, 0x0fffff, + 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff +}; + +void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const start, + size_t length) { + size_t i; + vp8l_val_t value = 0; + assert(br != NULL); + assert(start != NULL); + assert(length < 0xfffffff8u); // can't happen with a RIFF chunk. + + br->len_ = length; + br->val_ = 0; + br->bit_pos_ = 0; + br->eos_ = 0; + + if (length > sizeof(br->val_)) { + length = sizeof(br->val_); + } + for (i = 0; i < length; ++i) { + value |= (vp8l_val_t)start[i] << (8 * i); + } + br->val_ = value; + br->pos_ = length; + br->buf_ = start; +} + +void VP8LBitReaderSetBuffer(VP8LBitReader* const br, + const uint8_t* const buf, size_t len) { + assert(br != NULL); + assert(buf != NULL); + assert(len < 0xfffffff8u); // can't happen with a RIFF chunk. + br->buf_ = buf; + br->len_ = len; + // pos_ > len_ should be considered a param error. + br->eos_ = (br->pos_ > br->len_) || VP8LIsEndOfStream(br); +} + +static void VP8LSetEndOfStream(VP8LBitReader* const br) { + br->eos_ = 1; + br->bit_pos_ = 0; // To avoid undefined behaviour with shifts. +} + +// If not at EOS, reload up to VP8L_LBITS byte-by-byte +static void ShiftBytes(VP8LBitReader* const br) { + while (br->bit_pos_ >= 8 && br->pos_ < br->len_) { + br->val_ >>= 8; + br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8); + ++br->pos_; + br->bit_pos_ -= 8; + } + if (VP8LIsEndOfStream(br)) { + VP8LSetEndOfStream(br); + } +} + +void VP8LDoFillBitWindow(VP8LBitReader* const br) { + assert(br->bit_pos_ >= VP8L_WBITS); +#if defined(VP8L_USE_FAST_LOAD) + if (br->pos_ + sizeof(br->val_) < br->len_) { + br->val_ >>= VP8L_WBITS; + br->bit_pos_ -= VP8L_WBITS; + br->val_ |= (vp8l_val_t)HToLE32(WebPMemToUint32(br->buf_ + br->pos_)) << + (VP8L_LBITS - VP8L_WBITS); + br->pos_ += VP8L_LOG8_WBITS; + return; + } +#endif + ShiftBytes(br); // Slow path. +} + +uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) { + assert(n_bits >= 0); + // Flag an error if end_of_stream or n_bits is more than allowed limit. + if (!br->eos_ && n_bits <= VP8L_MAX_NUM_BIT_READ) { + const uint32_t val = VP8LPrefetchBits(br) & kBitMask[n_bits]; + const int new_bits = br->bit_pos_ + n_bits; + br->bit_pos_ = new_bits; + ShiftBytes(br); + return val; + } else { + VP8LSetEndOfStream(br); + return 0; + } +} + +//------------------------------------------------------------------------------ diff --git a/thirdparty/libwebp/utils/bit_reader.h b/thirdparty/libwebp/utils/bit_reader.h new file mode 100644 index 0000000000..ea5c584eb4 --- /dev/null +++ b/thirdparty/libwebp/utils/bit_reader.h @@ -0,0 +1,184 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Boolean decoder +// +// Author: Skal (pascal.massimino@gmail.com) +// Vikas Arora (vikaas.arora@gmail.com) + +#ifndef WEBP_UTILS_BIT_READER_H_ +#define WEBP_UTILS_BIT_READER_H_ + +#include <assert.h> +#ifdef _MSC_VER +#include <stdlib.h> // _byteswap_ulong +#endif +#include "../webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// The Boolean decoder needs to maintain infinite precision on the value_ field. +// However, since range_ is only 8bit, we only need an active window of 8 bits +// for value_. Left bits (MSB) gets zeroed and shifted away when value_ falls +// below 128, range_ is updated, and fresh bits read from the bitstream are +// brought in as LSB. To avoid reading the fresh bits one by one (slow), we +// cache BITS of them ahead. The total of (BITS + 8) bits must fit into a +// natural register (with type bit_t). To fetch BITS bits from bitstream we +// use a type lbit_t. +// +// BITS can be any multiple of 8 from 8 to 56 (inclusive). +// Pick values that fit natural register size. + +// -- GODOT -- start +#ifdef JAVASCRIPT_ENABLED +#define BITS 16 +#else +// -- GODOT -- end + +#if defined(__i386__) || defined(_M_IX86) // x86 32bit +#define BITS 24 +#elif defined(__x86_64__) || defined(_M_X64) // x86 64bit +#define BITS 56 +#elif defined(__arm__) || defined(_M_ARM) // ARM +#define BITS 24 +#elif defined(__aarch64__) // ARM 64bit +#define BITS 56 +#elif defined(__mips__) // MIPS +#define BITS 24 +#else // reasonable default +#define BITS 24 +#endif + +// -- GODOT -- start +#endif +// -- GODOT -- end + +//------------------------------------------------------------------------------ +// Derived types and constants: +// bit_t = natural register type for storing 'value_' (which is BITS+8 bits) +// range_t = register for 'range_' (which is 8bits only) + +#if (BITS > 24) +typedef uint64_t bit_t; +#else +typedef uint32_t bit_t; +#endif + +typedef uint32_t range_t; + +//------------------------------------------------------------------------------ +// Bitreader + +typedef struct VP8BitReader VP8BitReader; +struct VP8BitReader { + // boolean decoder (keep the field ordering as is!) + bit_t value_; // current value + range_t range_; // current range minus 1. In [127, 254] interval. + int bits_; // number of valid bits left + // read buffer + const uint8_t* buf_; // next byte to be read + const uint8_t* buf_end_; // end of read buffer + const uint8_t* buf_max_; // max packed-read position on buffer + int eof_; // true if input is exhausted +}; + +// Initialize the bit reader and the boolean decoder. +void VP8InitBitReader(VP8BitReader* const br, + const uint8_t* const start, size_t size); +// Sets the working read buffer. +void VP8BitReaderSetBuffer(VP8BitReader* const br, + const uint8_t* const start, size_t size); + +// Update internal pointers to displace the byte buffer by the +// relative offset 'offset'. +void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset); + +// return the next value made of 'num_bits' bits +uint32_t VP8GetValue(VP8BitReader* const br, int num_bits); +static WEBP_INLINE uint32_t VP8Get(VP8BitReader* const br) { + return VP8GetValue(br, 1); +} + +// return the next value with sign-extension. +int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits); + +// bit_reader_inl.h will implement the following methods: +// static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) +// static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) +// and should be included by the .c files that actually need them. +// This is to avoid recompiling the whole library whenever this file is touched, +// and also allowing platform-specific ad-hoc hacks. + +// ----------------------------------------------------------------------------- +// Bitreader for lossless format + +// maximum number of bits (inclusive) the bit-reader can handle: +#define VP8L_MAX_NUM_BIT_READ 24 + +#define VP8L_LBITS 64 // Number of bits prefetched (= bit-size of vp8l_val_t). +#define VP8L_WBITS 32 // Minimum number of bytes ready after VP8LFillBitWindow. + +typedef uint64_t vp8l_val_t; // right now, this bit-reader can only use 64bit. + +typedef struct { + vp8l_val_t val_; // pre-fetched bits + const uint8_t* buf_; // input byte buffer + size_t len_; // buffer length + size_t pos_; // byte position in buf_ + int bit_pos_; // current bit-reading position in val_ + int eos_; // true if a bit was read past the end of buffer +} VP8LBitReader; + +void VP8LInitBitReader(VP8LBitReader* const br, + const uint8_t* const start, + size_t length); + +// Sets a new data buffer. +void VP8LBitReaderSetBuffer(VP8LBitReader* const br, + const uint8_t* const buffer, size_t length); + +// Reads the specified number of bits from read buffer. +// Flags an error in case end_of_stream or n_bits is more than the allowed limit +// of VP8L_MAX_NUM_BIT_READ (inclusive). +// Flags eos_ if this read attempt is going to cross the read buffer. +uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits); + +// Return the prefetched bits, so they can be looked up. +static WEBP_INLINE uint32_t VP8LPrefetchBits(VP8LBitReader* const br) { + return (uint32_t)(br->val_ >> (br->bit_pos_ & (VP8L_LBITS - 1))); +} + +// Returns true if there was an attempt at reading bit past the end of +// the buffer. Doesn't set br->eos_ flag. +static WEBP_INLINE int VP8LIsEndOfStream(const VP8LBitReader* const br) { + assert(br->pos_ <= br->len_); + return br->eos_ || ((br->pos_ == br->len_) && (br->bit_pos_ > VP8L_LBITS)); +} + +// For jumping over a number of bits in the bit stream when accessed with +// VP8LPrefetchBits and VP8LFillBitWindow. +static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) { + br->bit_pos_ = val; + br->eos_ = VP8LIsEndOfStream(br); +} + +// Advances the read buffer by 4 bytes to make room for reading next 32 bits. +// Speed critical, but infrequent part of the code can be non-inlined. +extern void VP8LDoFillBitWindow(VP8LBitReader* const br); +static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) { + if (br->bit_pos_ >= VP8L_WBITS) VP8LDoFillBitWindow(br); +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_UTILS_BIT_READER_H_ */ diff --git a/thirdparty/libwebp/utils/bit_reader_inl.h b/thirdparty/libwebp/utils/bit_reader_inl.h new file mode 100644 index 0000000000..99ed3137d2 --- /dev/null +++ b/thirdparty/libwebp/utils/bit_reader_inl.h @@ -0,0 +1,173 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Specific inlined methods for boolean decoder [VP8GetBit() ...] +// This file should be included by the .c sources that actually need to call +// these methods. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_BIT_READER_INL_H_ +#define WEBP_UTILS_BIT_READER_INL_H_ + +#ifdef HAVE_CONFIG_H +#include "../webp/config.h" +#endif + +#ifdef WEBP_FORCE_ALIGNED +#include <string.h> // memcpy +#endif + +#include "../dsp/dsp.h" +#include "./bit_reader.h" +#include "./endian_inl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Derived type lbit_t = natural type for memory I/O + +#if (BITS > 32) +typedef uint64_t lbit_t; +#elif (BITS > 16) +typedef uint32_t lbit_t; +#elif (BITS > 8) +typedef uint16_t lbit_t; +#else +typedef uint8_t lbit_t; +#endif + +extern const uint8_t kVP8Log2Range[128]; +extern const uint8_t kVP8NewRange[128]; + +// special case for the tail byte-reading +void VP8LoadFinalBytes(VP8BitReader* const br); + +//------------------------------------------------------------------------------ +// Inlined critical functions + +// makes sure br->value_ has at least BITS bits worth of data +static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE +void VP8LoadNewBytes(VP8BitReader* const br) { + assert(br != NULL && br->buf_ != NULL); + // Read 'BITS' bits at a time if possible. + if (br->buf_ < br->buf_max_) { + // convert memory type to register type (with some zero'ing!) + bit_t bits; +#if defined(WEBP_FORCE_ALIGNED) + lbit_t in_bits; + memcpy(&in_bits, br->buf_, sizeof(in_bits)); +#elif defined(WEBP_USE_MIPS32) + // This is needed because of un-aligned read. + lbit_t in_bits; + lbit_t* p_buf_ = (lbit_t*)br->buf_; + __asm__ volatile( + ".set push \n\t" + ".set at \n\t" + ".set macro \n\t" + "ulw %[in_bits], 0(%[p_buf_]) \n\t" + ".set pop \n\t" + : [in_bits]"=r"(in_bits) + : [p_buf_]"r"(p_buf_) + : "memory", "at" + ); +#else + const lbit_t in_bits = *(const lbit_t*)br->buf_; +#endif + br->buf_ += BITS >> 3; +#if !defined(WORDS_BIGENDIAN) +#if (BITS > 32) + bits = BSwap64(in_bits); + bits >>= 64 - BITS; +#elif (BITS >= 24) + bits = BSwap32(in_bits); + bits >>= (32 - BITS); +#elif (BITS == 16) + bits = BSwap16(in_bits); +#else // BITS == 8 + bits = (bit_t)in_bits; +#endif // BITS > 32 +#else // WORDS_BIGENDIAN + bits = (bit_t)in_bits; + if (BITS != 8 * sizeof(bit_t)) bits >>= (8 * sizeof(bit_t) - BITS); +#endif + br->value_ = bits | (br->value_ << BITS); + br->bits_ += BITS; + } else { + VP8LoadFinalBytes(br); // no need to be inlined + } +} + +// Read a bit with proba 'prob'. Speed-critical function! +static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) { + // Don't move this declaration! It makes a big speed difference to store + // 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't + // alter br->range_ value. + range_t range = br->range_; + if (br->bits_ < 0) { + VP8LoadNewBytes(br); + } + { + const int pos = br->bits_; + const range_t split = (range * prob) >> 8; + const range_t value = (range_t)(br->value_ >> pos); +#if defined(__arm__) || defined(_M_ARM) // ARM-specific + const int bit = ((int)(split - value) >> 31) & 1; + if (value > split) { + range -= split + 1; + br->value_ -= (bit_t)(split + 1) << pos; + } else { + range = split; + } +#else // faster version on x86 + int bit; // Don't use 'const int bit = (value > split);", it's slower. + if (value > split) { + range -= split + 1; + br->value_ -= (bit_t)(split + 1) << pos; + bit = 1; + } else { + range = split; + bit = 0; + } +#endif + if (range <= (range_t)0x7e) { + const int shift = kVP8Log2Range[range]; + range = kVP8NewRange[range]; + br->bits_ -= shift; + } + br->range_ = range; + return bit; + } +} + +// simplified version of VP8GetBit() for prob=0x80 (note shift is always 1 here) +static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) { + if (br->bits_ < 0) { + VP8LoadNewBytes(br); + } + { + const int pos = br->bits_; + const range_t split = br->range_ >> 1; + const range_t value = (range_t)(br->value_ >> pos); + const int32_t mask = (int32_t)(split - value) >> 31; // -1 or 0 + br->bits_ -= 1; + br->range_ += mask; + br->range_ |= 1; + br->value_ -= (bit_t)((split + 1) & mask) << pos; + return (v ^ mask) - mask; + } +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_BIT_READER_INL_H_ diff --git a/drivers/webp/utils/bit_writer.c b/thirdparty/libwebp/utils/bit_writer.c index 064428691b..064428691b 100644 --- a/drivers/webp/utils/bit_writer.c +++ b/thirdparty/libwebp/utils/bit_writer.c diff --git a/thirdparty/libwebp/utils/bit_writer.h b/thirdparty/libwebp/utils/bit_writer.h new file mode 100644 index 0000000000..ef360d1dc6 --- /dev/null +++ b/thirdparty/libwebp/utils/bit_writer.h @@ -0,0 +1,145 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Bit writing and boolean coder +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_BIT_WRITER_H_ +#define WEBP_UTILS_BIT_WRITER_H_ + +#include "../webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Bit-writing + +typedef struct VP8BitWriter VP8BitWriter; +struct VP8BitWriter { + int32_t range_; // range-1 + int32_t value_; + int run_; // number of outstanding bits + int nb_bits_; // number of pending bits + uint8_t* buf_; // internal buffer. Re-allocated regularly. Not owned. + size_t pos_; + size_t max_pos_; + int error_; // true in case of error +}; + +// Initialize the object. Allocates some initial memory based on expected_size. +int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size); +// Finalize the bitstream coding. Returns a pointer to the internal buffer. +uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw); +// Release any pending memory and zeroes the object. Not a mandatory call. +// Only useful in case of error, when the internal buffer hasn't been grabbed! +void VP8BitWriterWipeOut(VP8BitWriter* const bw); + +int VP8PutBit(VP8BitWriter* const bw, int bit, int prob); +int VP8PutBitUniform(VP8BitWriter* const bw, int bit); +void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits); +void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits); + +// Appends some bytes to the internal buffer. Data is copied. +int VP8BitWriterAppend(VP8BitWriter* const bw, + const uint8_t* data, size_t size); + +// return approximate write position (in bits) +static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) { + return (uint64_t)(bw->pos_ + bw->run_) * 8 + 8 + bw->nb_bits_; +} + +// Returns a pointer to the internal buffer. +static WEBP_INLINE uint8_t* VP8BitWriterBuf(const VP8BitWriter* const bw) { + return bw->buf_; +} +// Returns the size of the internal buffer. +static WEBP_INLINE size_t VP8BitWriterSize(const VP8BitWriter* const bw) { + return bw->pos_; +} + +//------------------------------------------------------------------------------ +// VP8LBitWriter + +#if defined(__x86_64__) || defined(_M_X64) // 64bit +typedef uint64_t vp8l_atype_t; // accumulator type +typedef uint32_t vp8l_wtype_t; // writing type +#define WSWAP HToLE32 +#define VP8L_WRITER_BYTES 4 // sizeof(vp8l_wtype_t) +#define VP8L_WRITER_BITS 32 // 8 * sizeof(vp8l_wtype_t) +#define VP8L_WRITER_MAX_BITS 64 // 8 * sizeof(vp8l_atype_t) +#else +typedef uint32_t vp8l_atype_t; +typedef uint16_t vp8l_wtype_t; +#define WSWAP HToLE16 +#define VP8L_WRITER_BYTES 2 +#define VP8L_WRITER_BITS 16 +#define VP8L_WRITER_MAX_BITS 32 +#endif + +typedef struct { + vp8l_atype_t bits_; // bit accumulator + int used_; // number of bits used in accumulator + uint8_t* buf_; // start of buffer + uint8_t* cur_; // current write position + uint8_t* end_; // end of buffer + + // After all bits are written (VP8LBitWriterFinish()), the caller must observe + // the state of error_. A value of 1 indicates that a memory allocation + // failure has happened during bit writing. A value of 0 indicates successful + // writing of bits. + int error_; +} VP8LBitWriter; + +static WEBP_INLINE size_t VP8LBitWriterNumBytes(VP8LBitWriter* const bw) { + return (bw->cur_ - bw->buf_) + ((bw->used_ + 7) >> 3); +} + +// Returns false in case of memory allocation error. +int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size); +// Finalize the bitstream coding. Returns a pointer to the internal buffer. +uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw); +// Release any pending memory and zeroes the object. +void VP8LBitWriterWipeOut(VP8LBitWriter* const bw); + +// Internal function for VP8LPutBits flushing 32 bits from the written state. +void VP8LPutBitsFlushBits(VP8LBitWriter* const bw); + +// PutBits internal function used in the 16 bit vp8l_wtype_t case. +void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits); + +// This function writes bits into bytes in increasing addresses (little endian), +// and within a byte least-significant-bit first. +// This function can write up to 32 bits in one go, but VP8LBitReader can only +// read 24 bits max (VP8L_MAX_NUM_BIT_READ). +// VP8LBitWriter's error_ flag is set in case of memory allocation error. +static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw, + uint32_t bits, int n_bits) { + if (sizeof(vp8l_wtype_t) == 4) { + if (n_bits > 0) { + if (bw->used_ >= 32) { + VP8LPutBitsFlushBits(bw); + } + bw->bits_ |= (vp8l_atype_t)bits << bw->used_; + bw->used_ += n_bits; + } + } else { + VP8LPutBitsInternal(bw, bits, n_bits); + } +} + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_UTILS_BIT_WRITER_H_ */ diff --git a/drivers/webp/utils/color_cache.c b/thirdparty/libwebp/utils/color_cache.c index c34b2e7f1a..c34b2e7f1a 100644 --- a/drivers/webp/utils/color_cache.c +++ b/thirdparty/libwebp/utils/color_cache.c diff --git a/thirdparty/libwebp/utils/color_cache.h b/thirdparty/libwebp/utils/color_cache.h new file mode 100644 index 0000000000..a9a9f64270 --- /dev/null +++ b/thirdparty/libwebp/utils/color_cache.h @@ -0,0 +1,80 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Color Cache for WebP Lossless +// +// Authors: Jyrki Alakuijala (jyrki@google.com) +// Urvang Joshi (urvang@google.com) + +#ifndef WEBP_UTILS_COLOR_CACHE_H_ +#define WEBP_UTILS_COLOR_CACHE_H_ + +#include "../webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Main color cache struct. +typedef struct { + uint32_t *colors_; // color entries + int hash_shift_; // Hash shift: 32 - hash_bits_. + int hash_bits_; +} VP8LColorCache; + +static const uint32_t kHashMul = 0x1e35a7bd; + +static WEBP_INLINE uint32_t VP8LColorCacheLookup( + const VP8LColorCache* const cc, uint32_t key) { + assert((key >> cc->hash_bits_) == 0u); + return cc->colors_[key]; +} + +static WEBP_INLINE void VP8LColorCacheSet(const VP8LColorCache* const cc, + uint32_t key, uint32_t argb) { + assert((key >> cc->hash_bits_) == 0u); + cc->colors_[key] = argb; +} + +static WEBP_INLINE void VP8LColorCacheInsert(const VP8LColorCache* const cc, + uint32_t argb) { + const uint32_t key = (kHashMul * argb) >> cc->hash_shift_; + cc->colors_[key] = argb; +} + +static WEBP_INLINE int VP8LColorCacheGetIndex(const VP8LColorCache* const cc, + uint32_t argb) { + return (kHashMul * argb) >> cc->hash_shift_; +} + +static WEBP_INLINE int VP8LColorCacheContains(const VP8LColorCache* const cc, + uint32_t argb) { + const uint32_t key = (kHashMul * argb) >> cc->hash_shift_; + return (cc->colors_[key] == argb); +} + +//------------------------------------------------------------------------------ + +// Initializes the color cache with 'hash_bits' bits for the keys. +// Returns false in case of memory error. +int VP8LColorCacheInit(VP8LColorCache* const color_cache, int hash_bits); + +void VP8LColorCacheCopy(const VP8LColorCache* const src, + VP8LColorCache* const dst); + +// Delete the memory associated to color cache. +void VP8LColorCacheClear(VP8LColorCache* const color_cache); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} +#endif + +#endif // WEBP_UTILS_COLOR_CACHE_H_ diff --git a/drivers/webp/utils/endian_inl.h b/thirdparty/libwebp/utils/endian_inl.h index e11260ff7d..e11260ff7d 100644 --- a/drivers/webp/utils/endian_inl.h +++ b/thirdparty/libwebp/utils/endian_inl.h diff --git a/drivers/webp/utils/filters.c b/thirdparty/libwebp/utils/filters.c index 15543b1271..15543b1271 100644 --- a/drivers/webp/utils/filters.c +++ b/thirdparty/libwebp/utils/filters.c diff --git a/thirdparty/libwebp/utils/filters.h b/thirdparty/libwebp/utils/filters.h new file mode 100644 index 0000000000..088b132fc5 --- /dev/null +++ b/thirdparty/libwebp/utils/filters.h @@ -0,0 +1,32 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Spatial prediction using various filters +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_UTILS_FILTERS_H_ +#define WEBP_UTILS_FILTERS_H_ + +#include "../webp/types.h" +#include "../dsp/dsp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Fast estimate of a potentially good filter. +WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data, + int width, int height, int stride); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_UTILS_FILTERS_H_ */ diff --git a/thirdparty/libwebp/utils/huffman.c b/thirdparty/libwebp/utils/huffman.c new file mode 100644 index 0000000000..36e5502836 --- /dev/null +++ b/thirdparty/libwebp/utils/huffman.c @@ -0,0 +1,205 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for building and looking up Huffman trees. +// +// Author: Urvang Joshi (urvang@google.com) + +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include "./huffman.h" +#include "./utils.h" +#include "../webp/format_constants.h" + +// Huffman data read via DecodeImageStream is represented in two (red and green) +// bytes. +#define MAX_HTREE_GROUPS 0x10000 + +HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups) { + HTreeGroup* const htree_groups = + (HTreeGroup*)WebPSafeMalloc(num_htree_groups, sizeof(*htree_groups)); + if (htree_groups == NULL) { + return NULL; + } + assert(num_htree_groups <= MAX_HTREE_GROUPS); + return htree_groups; +} + +void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups) { + if (htree_groups != NULL) { + WebPSafeFree(htree_groups); + } +} + +// Returns reverse(reverse(key, len) + 1, len), where reverse(key, len) is the +// bit-wise reversal of the len least significant bits of key. +static WEBP_INLINE uint32_t GetNextKey(uint32_t key, int len) { + uint32_t step = 1 << (len - 1); + while (key & step) { + step >>= 1; + } + return (key & (step - 1)) + step; +} + +// Stores code in table[0], table[step], table[2*step], ..., table[end]. +// Assumes that end is an integer multiple of step. +static WEBP_INLINE void ReplicateValue(HuffmanCode* table, + int step, int end, + HuffmanCode code) { + assert(end % step == 0); + do { + end -= step; + table[end] = code; + } while (end > 0); +} + +// Returns the table width of the next 2nd level table. count is the histogram +// of bit lengths for the remaining symbols, len is the code length of the next +// processed symbol +static WEBP_INLINE int NextTableBitSize(const int* const count, + int len, int root_bits) { + int left = 1 << (len - root_bits); + while (len < MAX_ALLOWED_CODE_LENGTH) { + left -= count[len]; + if (left <= 0) break; + ++len; + left <<= 1; + } + return len - root_bits; +} + +int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits, + const int code_lengths[], int code_lengths_size) { + HuffmanCode* table = root_table; // next available space in table + int total_size = 1 << root_bits; // total size root table + 2nd level table + int* sorted = NULL; // symbols sorted by code length + int len; // current code length + int symbol; // symbol index in original or sorted table + // number of codes of each length: + int count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 }; + // offsets in sorted table for each length: + int offset[MAX_ALLOWED_CODE_LENGTH + 1]; + + assert(code_lengths_size != 0); + assert(code_lengths != NULL); + assert(root_table != NULL); + assert(root_bits > 0); + + // Build histogram of code lengths. + for (symbol = 0; symbol < code_lengths_size; ++symbol) { + if (code_lengths[symbol] > MAX_ALLOWED_CODE_LENGTH) { + return 0; + } + ++count[code_lengths[symbol]]; + } + + // Error, all code lengths are zeros. + if (count[0] == code_lengths_size) { + return 0; + } + + // Generate offsets into sorted symbol table by code length. + offset[1] = 0; + for (len = 1; len < MAX_ALLOWED_CODE_LENGTH; ++len) { + if (count[len] > (1 << len)) { + return 0; + } + offset[len + 1] = offset[len] + count[len]; + } + + sorted = (int*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted)); + if (sorted == NULL) { + return 0; + } + + // Sort symbols by length, by symbol order within each length. + for (symbol = 0; symbol < code_lengths_size; ++symbol) { + const int symbol_code_length = code_lengths[symbol]; + if (code_lengths[symbol] > 0) { + sorted[offset[symbol_code_length]++] = symbol; + } + } + + // Special case code with only one value. + if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) { + HuffmanCode code; + code.bits = 0; + code.value = (uint16_t)sorted[0]; + ReplicateValue(table, 1, total_size, code); + WebPSafeFree(sorted); + return total_size; + } + + { + int step; // step size to replicate values in current table + uint32_t low = -1; // low bits for current root entry + uint32_t mask = total_size - 1; // mask for low bits + uint32_t key = 0; // reversed prefix code + int num_nodes = 1; // number of Huffman tree nodes + int num_open = 1; // number of open branches in current tree level + int table_bits = root_bits; // key length of current table + int table_size = 1 << table_bits; // size of current table + symbol = 0; + // Fill in root table. + for (len = 1, step = 2; len <= root_bits; ++len, step <<= 1) { + num_open <<= 1; + num_nodes += num_open; + num_open -= count[len]; + if (num_open < 0) { + WebPSafeFree(sorted); + return 0; + } + for (; count[len] > 0; --count[len]) { + HuffmanCode code; + code.bits = (uint8_t)len; + code.value = (uint16_t)sorted[symbol++]; + ReplicateValue(&table[key], step, table_size, code); + key = GetNextKey(key, len); + } + } + + // Fill in 2nd level tables and add pointers to root table. + for (len = root_bits + 1, step = 2; len <= MAX_ALLOWED_CODE_LENGTH; + ++len, step <<= 1) { + num_open <<= 1; + num_nodes += num_open; + num_open -= count[len]; + if (num_open < 0) { + WebPSafeFree(sorted); + return 0; + } + for (; count[len] > 0; --count[len]) { + HuffmanCode code; + if ((key & mask) != low) { + table += table_size; + table_bits = NextTableBitSize(count, len, root_bits); + table_size = 1 << table_bits; + total_size += table_size; + low = key & mask; + root_table[low].bits = (uint8_t)(table_bits + root_bits); + root_table[low].value = (uint16_t)((table - root_table) - low); + } + code.bits = (uint8_t)(len - root_bits); + code.value = (uint16_t)sorted[symbol++]; + ReplicateValue(&table[key >> root_bits], step, table_size, code); + key = GetNextKey(key, len); + } + } + + // Check if tree is full. + if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) { + WebPSafeFree(sorted); + return 0; + } + } + + WebPSafeFree(sorted); + return total_size; +} diff --git a/thirdparty/libwebp/utils/huffman.h b/thirdparty/libwebp/utils/huffman.h new file mode 100644 index 0000000000..c6dd6aaa45 --- /dev/null +++ b/thirdparty/libwebp/utils/huffman.h @@ -0,0 +1,88 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for building and looking up Huffman trees. +// +// Author: Urvang Joshi (urvang@google.com) + +#ifndef WEBP_UTILS_HUFFMAN_H_ +#define WEBP_UTILS_HUFFMAN_H_ + +#include <assert.h> +#include "../webp/format_constants.h" +#include "../webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define HUFFMAN_TABLE_BITS 8 +#define HUFFMAN_TABLE_MASK ((1 << HUFFMAN_TABLE_BITS) - 1) + +#define LENGTHS_TABLE_BITS 7 +#define LENGTHS_TABLE_MASK ((1 << LENGTHS_TABLE_BITS) - 1) + + +// Huffman lookup table entry +typedef struct { + uint8_t bits; // number of bits used for this symbol + uint16_t value; // symbol value or table offset +} HuffmanCode; + +// long version for holding 32b values +typedef struct { + int bits; // number of bits used for this symbol, + // or an impossible value if not a literal code. + uint32_t value; // 32b packed ARGB value if literal, + // or non-literal symbol otherwise +} HuffmanCode32; + +#define HUFFMAN_PACKED_BITS 6 +#define HUFFMAN_PACKED_TABLE_SIZE (1u << HUFFMAN_PACKED_BITS) + +// Huffman table group. +// Includes special handling for the following cases: +// - is_trivial_literal: one common literal base for RED/BLUE/ALPHA (not GREEN) +// - is_trivial_code: only 1 code (no bit is read from bitstream) +// - use_packed_table: few enough literal symbols, so all the bit codes +// can fit into a small look-up table packed_table[] +// The common literal base, if applicable, is stored in 'literal_arb'. +typedef struct HTreeGroup HTreeGroup; +struct HTreeGroup { + HuffmanCode* htrees[HUFFMAN_CODES_PER_META_CODE]; + int is_trivial_literal; // True, if huffman trees for Red, Blue & Alpha + // Symbols are trivial (have a single code). + uint32_t literal_arb; // If is_trivial_literal is true, this is the + // ARGB value of the pixel, with Green channel + // being set to zero. + int is_trivial_code; // true if is_trivial_literal with only one code + int use_packed_table; // use packed table below for short literal code + // table mapping input bits to a packed values, or escape case to literal code + HuffmanCode32 packed_table[HUFFMAN_PACKED_TABLE_SIZE]; +}; + +// Creates the instance of HTreeGroup with specified number of tree-groups. +HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups); + +// Releases the memory allocated for HTreeGroup. +void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups); + +// Builds Huffman lookup table assuming code lengths are in symbol order. +// The 'code_lengths' is pre-allocated temporary memory buffer used for creating +// the huffman table. +// Returns built table size or 0 in case of error (invalid tree or +// memory error). +int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits, + const int code_lengths[], int code_lengths_size); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_HUFFMAN_H_ diff --git a/thirdparty/libwebp/utils/huffman_encode.c b/thirdparty/libwebp/utils/huffman_encode.c new file mode 100644 index 0000000000..4e5ef6b447 --- /dev/null +++ b/thirdparty/libwebp/utils/huffman_encode.c @@ -0,0 +1,417 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +// Entropy encoding (Huffman) for webp lossless. + +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include "./huffman_encode.h" +#include "./utils.h" +#include "../webp/format_constants.h" + +// ----------------------------------------------------------------------------- +// Util function to optimize the symbol map for RLE coding + +// Heuristics for selecting the stride ranges to collapse. +static int ValuesShouldBeCollapsedToStrideAverage(int a, int b) { + return abs(a - b) < 4; +} + +// Change the population counts in a way that the consequent +// Huffman tree compression, especially its RLE-part, give smaller output. +static void OptimizeHuffmanForRle(int length, uint8_t* const good_for_rle, + uint32_t* const counts) { + // 1) Let's make the Huffman code more compatible with rle encoding. + int i; + for (; length >= 0; --length) { + if (length == 0) { + return; // All zeros. + } + if (counts[length - 1] != 0) { + // Now counts[0..length - 1] does not have trailing zeros. + break; + } + } + // 2) Let's mark all population counts that already can be encoded + // with an rle code. + { + // Let's not spoil any of the existing good rle codes. + // Mark any seq of 0's that is longer as 5 as a good_for_rle. + // Mark any seq of non-0's that is longer as 7 as a good_for_rle. + uint32_t symbol = counts[0]; + int stride = 0; + for (i = 0; i < length + 1; ++i) { + if (i == length || counts[i] != symbol) { + if ((symbol == 0 && stride >= 5) || + (symbol != 0 && stride >= 7)) { + int k; + for (k = 0; k < stride; ++k) { + good_for_rle[i - k - 1] = 1; + } + } + stride = 1; + if (i != length) { + symbol = counts[i]; + } + } else { + ++stride; + } + } + } + // 3) Let's replace those population counts that lead to more rle codes. + { + uint32_t stride = 0; + uint32_t limit = counts[0]; + uint32_t sum = 0; + for (i = 0; i < length + 1; ++i) { + if (i == length || good_for_rle[i] || + (i != 0 && good_for_rle[i - 1]) || + !ValuesShouldBeCollapsedToStrideAverage(counts[i], limit)) { + if (stride >= 4 || (stride >= 3 && sum == 0)) { + uint32_t k; + // The stride must end, collapse what we have, if we have enough (4). + uint32_t count = (sum + stride / 2) / stride; + if (count < 1) { + count = 1; + } + if (sum == 0) { + // Don't make an all zeros stride to be upgraded to ones. + count = 0; + } + for (k = 0; k < stride; ++k) { + // We don't want to change value at counts[i], + // that is already belonging to the next stride. Thus - 1. + counts[i - k - 1] = count; + } + } + stride = 0; + sum = 0; + if (i < length - 3) { + // All interesting strides have a count of at least 4, + // at least when non-zeros. + limit = (counts[i] + counts[i + 1] + + counts[i + 2] + counts[i + 3] + 2) / 4; + } else if (i < length) { + limit = counts[i]; + } else { + limit = 0; + } + } + ++stride; + if (i != length) { + sum += counts[i]; + if (stride >= 4) { + limit = (sum + stride / 2) / stride; + } + } + } + } +} + +// A comparer function for two Huffman trees: sorts first by 'total count' +// (more comes first), and then by 'value' (more comes first). +static int CompareHuffmanTrees(const void* ptr1, const void* ptr2) { + const HuffmanTree* const t1 = (const HuffmanTree*)ptr1; + const HuffmanTree* const t2 = (const HuffmanTree*)ptr2; + if (t1->total_count_ > t2->total_count_) { + return -1; + } else if (t1->total_count_ < t2->total_count_) { + return 1; + } else { + assert(t1->value_ != t2->value_); + return (t1->value_ < t2->value_) ? -1 : 1; + } +} + +static void SetBitDepths(const HuffmanTree* const tree, + const HuffmanTree* const pool, + uint8_t* const bit_depths, int level) { + if (tree->pool_index_left_ >= 0) { + SetBitDepths(&pool[tree->pool_index_left_], pool, bit_depths, level + 1); + SetBitDepths(&pool[tree->pool_index_right_], pool, bit_depths, level + 1); + } else { + bit_depths[tree->value_] = level; + } +} + +// Create an optimal Huffman tree. +// +// (data,length): population counts. +// tree_limit: maximum bit depth (inclusive) of the codes. +// bit_depths[]: how many bits are used for the symbol. +// +// Returns 0 when an error has occurred. +// +// The catch here is that the tree cannot be arbitrarily deep +// +// count_limit is the value that is to be faked as the minimum value +// and this minimum value is raised until the tree matches the +// maximum length requirement. +// +// This algorithm is not of excellent performance for very long data blocks, +// especially when population counts are longer than 2**tree_limit, but +// we are not planning to use this with extremely long blocks. +// +// See http://en.wikipedia.org/wiki/Huffman_coding +static void GenerateOptimalTree(const uint32_t* const histogram, + int histogram_size, + HuffmanTree* tree, int tree_depth_limit, + uint8_t* const bit_depths) { + uint32_t count_min; + HuffmanTree* tree_pool; + int tree_size_orig = 0; + int i; + + for (i = 0; i < histogram_size; ++i) { + if (histogram[i] != 0) { + ++tree_size_orig; + } + } + + if (tree_size_orig == 0) { // pretty optimal already! + return; + } + + tree_pool = tree + tree_size_orig; + + // For block sizes with less than 64k symbols we never need to do a + // second iteration of this loop. + // If we actually start running inside this loop a lot, we would perhaps + // be better off with the Katajainen algorithm. + assert(tree_size_orig <= (1 << (tree_depth_limit - 1))); + for (count_min = 1; ; count_min *= 2) { + int tree_size = tree_size_orig; + // We need to pack the Huffman tree in tree_depth_limit bits. + // So, we try by faking histogram entries to be at least 'count_min'. + int idx = 0; + int j; + for (j = 0; j < histogram_size; ++j) { + if (histogram[j] != 0) { + const uint32_t count = + (histogram[j] < count_min) ? count_min : histogram[j]; + tree[idx].total_count_ = count; + tree[idx].value_ = j; + tree[idx].pool_index_left_ = -1; + tree[idx].pool_index_right_ = -1; + ++idx; + } + } + + // Build the Huffman tree. + qsort(tree, tree_size, sizeof(*tree), CompareHuffmanTrees); + + if (tree_size > 1) { // Normal case. + int tree_pool_size = 0; + while (tree_size > 1) { // Finish when we have only one root. + uint32_t count; + tree_pool[tree_pool_size++] = tree[tree_size - 1]; + tree_pool[tree_pool_size++] = tree[tree_size - 2]; + count = tree_pool[tree_pool_size - 1].total_count_ + + tree_pool[tree_pool_size - 2].total_count_; + tree_size -= 2; + { + // Search for the insertion point. + int k; + for (k = 0; k < tree_size; ++k) { + if (tree[k].total_count_ <= count) { + break; + } + } + memmove(tree + (k + 1), tree + k, (tree_size - k) * sizeof(*tree)); + tree[k].total_count_ = count; + tree[k].value_ = -1; + + tree[k].pool_index_left_ = tree_pool_size - 1; + tree[k].pool_index_right_ = tree_pool_size - 2; + tree_size = tree_size + 1; + } + } + SetBitDepths(&tree[0], tree_pool, bit_depths, 0); + } else if (tree_size == 1) { // Trivial case: only one element. + bit_depths[tree[0].value_] = 1; + } + + { + // Test if this Huffman tree satisfies our 'tree_depth_limit' criteria. + int max_depth = bit_depths[0]; + for (j = 1; j < histogram_size; ++j) { + if (max_depth < bit_depths[j]) { + max_depth = bit_depths[j]; + } + } + if (max_depth <= tree_depth_limit) { + break; + } + } + } +} + +// ----------------------------------------------------------------------------- +// Coding of the Huffman tree values + +static HuffmanTreeToken* CodeRepeatedValues(int repetitions, + HuffmanTreeToken* tokens, + int value, int prev_value) { + assert(value <= MAX_ALLOWED_CODE_LENGTH); + if (value != prev_value) { + tokens->code = value; + tokens->extra_bits = 0; + ++tokens; + --repetitions; + } + while (repetitions >= 1) { + if (repetitions < 3) { + int i; + for (i = 0; i < repetitions; ++i) { + tokens->code = value; + tokens->extra_bits = 0; + ++tokens; + } + break; + } else if (repetitions < 7) { + tokens->code = 16; + tokens->extra_bits = repetitions - 3; + ++tokens; + break; + } else { + tokens->code = 16; + tokens->extra_bits = 3; + ++tokens; + repetitions -= 6; + } + } + return tokens; +} + +static HuffmanTreeToken* CodeRepeatedZeros(int repetitions, + HuffmanTreeToken* tokens) { + while (repetitions >= 1) { + if (repetitions < 3) { + int i; + for (i = 0; i < repetitions; ++i) { + tokens->code = 0; // 0-value + tokens->extra_bits = 0; + ++tokens; + } + break; + } else if (repetitions < 11) { + tokens->code = 17; + tokens->extra_bits = repetitions - 3; + ++tokens; + break; + } else if (repetitions < 139) { + tokens->code = 18; + tokens->extra_bits = repetitions - 11; + ++tokens; + break; + } else { + tokens->code = 18; + tokens->extra_bits = 0x7f; // 138 repeated 0s + ++tokens; + repetitions -= 138; + } + } + return tokens; +} + +int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree, + HuffmanTreeToken* tokens, int max_tokens) { + HuffmanTreeToken* const starting_token = tokens; + HuffmanTreeToken* const ending_token = tokens + max_tokens; + const int depth_size = tree->num_symbols; + int prev_value = 8; // 8 is the initial value for rle. + int i = 0; + assert(tokens != NULL); + while (i < depth_size) { + const int value = tree->code_lengths[i]; + int k = i + 1; + int runs; + while (k < depth_size && tree->code_lengths[k] == value) ++k; + runs = k - i; + if (value == 0) { + tokens = CodeRepeatedZeros(runs, tokens); + } else { + tokens = CodeRepeatedValues(runs, tokens, value, prev_value); + prev_value = value; + } + i += runs; + assert(tokens <= ending_token); + } + (void)ending_token; // suppress 'unused variable' warning + return (int)(tokens - starting_token); +} + +// ----------------------------------------------------------------------------- + +// Pre-reversed 4-bit values. +static const uint8_t kReversedBits[16] = { + 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, + 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf +}; + +static uint32_t ReverseBits(int num_bits, uint32_t bits) { + uint32_t retval = 0; + int i = 0; + while (i < num_bits) { + i += 4; + retval |= kReversedBits[bits & 0xf] << (MAX_ALLOWED_CODE_LENGTH + 1 - i); + bits >>= 4; + } + retval >>= (MAX_ALLOWED_CODE_LENGTH + 1 - num_bits); + return retval; +} + +// Get the actual bit values for a tree of bit depths. +static void ConvertBitDepthsToSymbols(HuffmanTreeCode* const tree) { + // 0 bit-depth means that the symbol does not exist. + int i; + int len; + uint32_t next_code[MAX_ALLOWED_CODE_LENGTH + 1]; + int depth_count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 }; + + assert(tree != NULL); + len = tree->num_symbols; + for (i = 0; i < len; ++i) { + const int code_length = tree->code_lengths[i]; + assert(code_length <= MAX_ALLOWED_CODE_LENGTH); + ++depth_count[code_length]; + } + depth_count[0] = 0; // ignore unused symbol + next_code[0] = 0; + { + uint32_t code = 0; + for (i = 1; i <= MAX_ALLOWED_CODE_LENGTH; ++i) { + code = (code + depth_count[i - 1]) << 1; + next_code[i] = code; + } + } + for (i = 0; i < len; ++i) { + const int code_length = tree->code_lengths[i]; + tree->codes[i] = ReverseBits(code_length, next_code[code_length]++); + } +} + +// ----------------------------------------------------------------------------- +// Main entry point + +void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit, + uint8_t* const buf_rle, + HuffmanTree* const huff_tree, + HuffmanTreeCode* const huff_code) { + const int num_symbols = huff_code->num_symbols; + memset(buf_rle, 0, num_symbols * sizeof(*buf_rle)); + OptimizeHuffmanForRle(num_symbols, buf_rle, histogram); + GenerateOptimalTree(histogram, num_symbols, huff_tree, tree_depth_limit, + huff_code->code_lengths); + // Create the actual bit codes for the bit lengths. + ConvertBitDepthsToSymbols(huff_code); +} diff --git a/thirdparty/libwebp/utils/huffman_encode.h b/thirdparty/libwebp/utils/huffman_encode.h new file mode 100644 index 0000000000..a157165148 --- /dev/null +++ b/thirdparty/libwebp/utils/huffman_encode.h @@ -0,0 +1,60 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +// Entropy encoding (Huffman) for webp lossless + +#ifndef WEBP_UTILS_HUFFMAN_ENCODE_H_ +#define WEBP_UTILS_HUFFMAN_ENCODE_H_ + +#include "../webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Struct for holding the tree header in coded form. +typedef struct { + uint8_t code; // value (0..15) or escape code (16,17,18) + uint8_t extra_bits; // extra bits for escape codes +} HuffmanTreeToken; + +// Struct to represent the tree codes (depth and bits array). +typedef struct { + int num_symbols; // Number of symbols. + uint8_t* code_lengths; // Code lengths of the symbols. + uint16_t* codes; // Symbol Codes. +} HuffmanTreeCode; + +// Struct to represent the Huffman tree. +typedef struct { + uint32_t total_count_; // Symbol frequency. + int value_; // Symbol value. + int pool_index_left_; // Index for the left sub-tree. + int pool_index_right_; // Index for the right sub-tree. +} HuffmanTree; + +// Turn the Huffman tree into a token sequence. +// Returns the number of tokens used. +int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree, + HuffmanTreeToken* tokens, int max_tokens); + +// Create an optimized tree, and tokenize it. +// 'buf_rle' and 'huff_tree' are pre-allocated and the 'tree' is the constructed +// huffman code tree. +void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit, + uint8_t* const buf_rle, HuffmanTree* const huff_tree, + HuffmanTreeCode* const tree); + +#ifdef __cplusplus +} +#endif + +#endif // WEBP_UTILS_HUFFMAN_ENCODE_H_ diff --git a/drivers/webp/utils/quant_levels.c b/thirdparty/libwebp/utils/quant_levels.c index d7c8aab922..d7c8aab922 100644 --- a/drivers/webp/utils/quant_levels.c +++ b/thirdparty/libwebp/utils/quant_levels.c diff --git a/thirdparty/libwebp/utils/quant_levels.h b/thirdparty/libwebp/utils/quant_levels.h new file mode 100644 index 0000000000..1cb5a32cae --- /dev/null +++ b/thirdparty/libwebp/utils/quant_levels.h @@ -0,0 +1,36 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha plane quantization utility +// +// Author: Vikas Arora (vikasa@google.com) + +#ifndef WEBP_UTILS_QUANT_LEVELS_H_ +#define WEBP_UTILS_QUANT_LEVELS_H_ + +#include <stdlib.h> + +#include "../webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Replace the input 'data' of size 'width'x'height' with 'num-levels' +// quantized values. If not NULL, 'sse' will contain the sum of squared error. +// Valid range for 'num_levels' is [2, 256]. +// Returns false in case of error (data is NULL, or parameters are invalid). +int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels, + uint64_t* const sse); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_UTILS_QUANT_LEVELS_H_ */ diff --git a/drivers/webp/utils/quant_levels_dec.c b/thirdparty/libwebp/utils/quant_levels_dec.c index ee0a3fe127..ee0a3fe127 100644 --- a/drivers/webp/utils/quant_levels_dec.c +++ b/thirdparty/libwebp/utils/quant_levels_dec.c diff --git a/thirdparty/libwebp/utils/quant_levels_dec.h b/thirdparty/libwebp/utils/quant_levels_dec.h new file mode 100644 index 0000000000..59a13495d3 --- /dev/null +++ b/thirdparty/libwebp/utils/quant_levels_dec.h @@ -0,0 +1,35 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha plane de-quantization utility +// +// Author: Vikas Arora (vikasa@google.com) + +#ifndef WEBP_UTILS_QUANT_LEVELS_DEC_H_ +#define WEBP_UTILS_QUANT_LEVELS_DEC_H_ + +#include "../webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Apply post-processing to input 'data' of size 'width'x'height' assuming that +// the source was quantized to a reduced number of levels. 'stride' is in bytes. +// Strength is in [0..100] and controls the amount of dithering applied. +// Returns false in case of error (data is NULL, invalid parameters, +// malloc failure, ...). +int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride, + int strength); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_H_ */ diff --git a/drivers/webp/utils/random.c b/thirdparty/libwebp/utils/random.c index 24e96ad648..24e96ad648 100644 --- a/drivers/webp/utils/random.c +++ b/thirdparty/libwebp/utils/random.c diff --git a/thirdparty/libwebp/utils/random.h b/thirdparty/libwebp/utils/random.h new file mode 100644 index 0000000000..c392a615ca --- /dev/null +++ b/thirdparty/libwebp/utils/random.h @@ -0,0 +1,63 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Pseudo-random utilities +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_RANDOM_H_ +#define WEBP_UTILS_RANDOM_H_ + +#include <assert.h> +#include "../webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define VP8_RANDOM_DITHER_FIX 8 // fixed-point precision for dithering +#define VP8_RANDOM_TABLE_SIZE 55 + +typedef struct { + int index1_, index2_; + uint32_t tab_[VP8_RANDOM_TABLE_SIZE]; + int amp_; +} VP8Random; + +// Initializes random generator with an amplitude 'dithering' in range [0..1]. +void VP8InitRandom(VP8Random* const rg, float dithering); + +// Returns a centered pseudo-random number with 'num_bits' amplitude. +// (uses D.Knuth's Difference-based random generator). +// 'amp' is in VP8_RANDOM_DITHER_FIX fixed-point precision. +static WEBP_INLINE int VP8RandomBits2(VP8Random* const rg, int num_bits, + int amp) { + int diff; + assert(num_bits + VP8_RANDOM_DITHER_FIX <= 31); + diff = rg->tab_[rg->index1_] - rg->tab_[rg->index2_]; + if (diff < 0) diff += (1u << 31); + rg->tab_[rg->index1_] = diff; + if (++rg->index1_ == VP8_RANDOM_TABLE_SIZE) rg->index1_ = 0; + if (++rg->index2_ == VP8_RANDOM_TABLE_SIZE) rg->index2_ = 0; + // sign-extend, 0-center + diff = (int)((uint32_t)diff << 1) >> (32 - num_bits); + diff = (diff * amp) >> VP8_RANDOM_DITHER_FIX; // restrict range + diff += 1 << (num_bits - 1); // shift back to 0.5-center + return diff; +} + +static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) { + return VP8RandomBits2(rg, num_bits, rg->amp_); +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_UTILS_RANDOM_H_ */ diff --git a/drivers/webp/utils/rescaler.c b/thirdparty/libwebp/utils/rescaler.c index 00c9300bfb..00c9300bfb 100644 --- a/drivers/webp/utils/rescaler.c +++ b/thirdparty/libwebp/utils/rescaler.c diff --git a/thirdparty/libwebp/utils/rescaler.h b/thirdparty/libwebp/utils/rescaler.h new file mode 100644 index 0000000000..98b01a76d0 --- /dev/null +++ b/thirdparty/libwebp/utils/rescaler.h @@ -0,0 +1,101 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Rescaling functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_RESCALER_H_ +#define WEBP_UTILS_RESCALER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../webp/types.h" + +#define WEBP_RESCALER_RFIX 32 // fixed-point precision for multiplies +#define WEBP_RESCALER_ONE (1ull << WEBP_RESCALER_RFIX) +#define WEBP_RESCALER_FRAC(x, y) \ + ((uint32_t)(((uint64_t)(x) << WEBP_RESCALER_RFIX) / (y))) + +// Structure used for on-the-fly rescaling +typedef uint32_t rescaler_t; // type for side-buffer +typedef struct WebPRescaler WebPRescaler; +struct WebPRescaler { + int x_expand; // true if we're expanding in the x direction + int y_expand; // true if we're expanding in the y direction + int num_channels; // bytes to jump between pixels + uint32_t fx_scale; // fixed-point scaling factors + uint32_t fy_scale; // '' + uint32_t fxy_scale; // '' + int y_accum; // vertical accumulator + int y_add, y_sub; // vertical increments + int x_add, x_sub; // horizontal increments + int src_width, src_height; // source dimensions + int dst_width, dst_height; // destination dimensions + int src_y, dst_y; // row counters for input and output + uint8_t* dst; + int dst_stride; + rescaler_t* irow, *frow; // work buffer +}; + +// Initialize a rescaler given scratch area 'work' and dimensions of src & dst. +void WebPRescalerInit(WebPRescaler* const rescaler, + int src_width, int src_height, + uint8_t* const dst, + int dst_width, int dst_height, int dst_stride, + int num_channels, + rescaler_t* const work); + +// If either 'scaled_width' or 'scaled_height' (but not both) is 0 the value +// will be calculated preserving the aspect ratio, otherwise the values are +// left unmodified. Returns true on success, false if either value is 0 after +// performing the scaling calculation. +int WebPRescalerGetScaledDimensions(int src_width, int src_height, + int* const scaled_width, + int* const scaled_height); + +// Returns the number of input lines needed next to produce one output line, +// considering that the maximum available input lines are 'max_num_lines'. +int WebPRescaleNeededLines(const WebPRescaler* const rescaler, + int max_num_lines); + +// Import multiple rows over all channels, until at least one row is ready to +// be exported. Returns the actual number of lines that were imported. +int WebPRescalerImport(WebPRescaler* const rescaler, int num_rows, + const uint8_t* src, int src_stride); + +// Export as many rows as possible. Return the numbers of rows written. +int WebPRescalerExport(WebPRescaler* const rescaler); + +// Return true if input is finished +static WEBP_INLINE +int WebPRescalerInputDone(const WebPRescaler* const rescaler) { + return (rescaler->src_y >= rescaler->src_height); +} +// Return true if output is finished +static WEBP_INLINE +int WebPRescalerOutputDone(const WebPRescaler* const rescaler) { + return (rescaler->dst_y >= rescaler->dst_height); +} + +// Return true if there are pending output rows ready. +static WEBP_INLINE +int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) { + return !WebPRescalerOutputDone(rescaler) && (rescaler->y_accum <= 0); +} + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_UTILS_RESCALER_H_ */ diff --git a/drivers/webp/utils/thread.c b/thirdparty/libwebp/utils/thread.c index 93f7622797..93f7622797 100644 --- a/drivers/webp/utils/thread.c +++ b/thirdparty/libwebp/utils/thread.c diff --git a/thirdparty/libwebp/utils/thread.h b/thirdparty/libwebp/utils/thread.h new file mode 100644 index 0000000000..8408311855 --- /dev/null +++ b/thirdparty/libwebp/utils/thread.h @@ -0,0 +1,93 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Multi-threaded worker +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_THREAD_H_ +#define WEBP_UTILS_THREAD_H_ + +#ifdef HAVE_CONFIG_H +#include "../webp/config.h" +#endif + +#include "../webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// State of the worker thread object +typedef enum { + NOT_OK = 0, // object is unusable + OK, // ready to work + WORK // busy finishing the current task +} WebPWorkerStatus; + +// Function to be called by the worker thread. Takes two opaque pointers as +// arguments (data1 and data2), and should return false in case of error. +typedef int (*WebPWorkerHook)(void*, void*); + +// Platform-dependent implementation details for the worker. +typedef struct WebPWorkerImpl WebPWorkerImpl; + +// Synchronization object used to launch job in the worker thread +typedef struct { + WebPWorkerImpl* impl_; + WebPWorkerStatus status_; + WebPWorkerHook hook; // hook to call + void* data1; // first argument passed to 'hook' + void* data2; // second argument passed to 'hook' + int had_error; // return value of the last call to 'hook' +} WebPWorker; + +// The interface for all thread-worker related functions. All these functions +// must be implemented. +typedef struct { + // Must be called first, before any other method. + void (*Init)(WebPWorker* const worker); + // Must be called to initialize the object and spawn the thread. Re-entrant. + // Will potentially launch the thread. Returns false in case of error. + int (*Reset)(WebPWorker* const worker); + // Makes sure the previous work is finished. Returns true if worker->had_error + // was not set and no error condition was triggered by the working thread. + int (*Sync)(WebPWorker* const worker); + // Triggers the thread to call hook() with data1 and data2 arguments. These + // hook/data1/data2 values can be changed at any time before calling this + // function, but not be changed afterward until the next call to Sync(). + void (*Launch)(WebPWorker* const worker); + // This function is similar to Launch() except that it calls the + // hook directly instead of using a thread. Convenient to bypass the thread + // mechanism while still using the WebPWorker structs. Sync() must + // still be called afterward (for error reporting). + void (*Execute)(WebPWorker* const worker); + // Kill the thread and terminate the object. To use the object again, one + // must call Reset() again. + void (*End)(WebPWorker* const worker); +} WebPWorkerInterface; + +// Install a new set of threading functions, overriding the defaults. This +// should be done before any workers are started, i.e., before any encoding or +// decoding takes place. The contents of the interface struct are copied, it +// is safe to free the corresponding memory after this call. This function is +// not thread-safe. Return false in case of invalid pointer or methods. +WEBP_EXTERN(int) WebPSetWorkerInterface( + const WebPWorkerInterface* const winterface); + +// Retrieve the currently set thread worker interface. +WEBP_EXTERN(const WebPWorkerInterface*) WebPGetWorkerInterface(void); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_UTILS_THREAD_H_ */ diff --git a/thirdparty/libwebp/utils/utils.c b/thirdparty/libwebp/utils/utils.c new file mode 100644 index 0000000000..2602ca3c9f --- /dev/null +++ b/thirdparty/libwebp/utils/utils.c @@ -0,0 +1,305 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include <stdlib.h> +#include <string.h> // for memcpy() +#include "../webp/decode.h" +#include "../webp/encode.h" +#include "../webp/format_constants.h" // for MAX_PALETTE_SIZE +#include "./utils.h" + +// If PRINT_MEM_INFO is defined, extra info (like total memory used, number of +// alloc/free etc) is printed. For debugging/tuning purpose only (it's slow, +// and not multi-thread safe!). +// An interesting alternative is valgrind's 'massif' tool: +// http://valgrind.org/docs/manual/ms-manual.html +// Here is an example command line: +/* valgrind --tool=massif --massif-out-file=massif.out \ + --stacks=yes --alloc-fn=WebPSafeAlloc --alloc-fn=WebPSafeCalloc + ms_print massif.out +*/ +// In addition: +// * if PRINT_MEM_TRAFFIC is defined, all the details of the malloc/free cycles +// are printed. +// * if MALLOC_FAIL_AT is defined, the global environment variable +// $MALLOC_FAIL_AT is used to simulate a memory error when calloc or malloc +// is called for the nth time. Example usage: +// export MALLOC_FAIL_AT=50 && ./examples/cwebp input.png +// * if MALLOC_LIMIT is defined, the global environment variable $MALLOC_LIMIT +// sets the maximum amount of memory (in bytes) made available to libwebp. +// This can be used to emulate environment with very limited memory. +// Example: export MALLOC_LIMIT=64000000 && ./examples/dwebp picture.webp + +// #define PRINT_MEM_INFO +// #define PRINT_MEM_TRAFFIC +// #define MALLOC_FAIL_AT +// #define MALLOC_LIMIT + +//------------------------------------------------------------------------------ +// Checked memory allocation + +#if defined(PRINT_MEM_INFO) + +#include <stdio.h> + +static int num_malloc_calls = 0; +static int num_calloc_calls = 0; +static int num_free_calls = 0; +static int countdown_to_fail = 0; // 0 = off + +typedef struct MemBlock MemBlock; +struct MemBlock { + void* ptr_; + size_t size_; + MemBlock* next_; +}; + +static MemBlock* all_blocks = NULL; +static size_t total_mem = 0; +static size_t total_mem_allocated = 0; +static size_t high_water_mark = 0; +static size_t mem_limit = 0; + +static int exit_registered = 0; + +static void PrintMemInfo(void) { + fprintf(stderr, "\nMEMORY INFO:\n"); + fprintf(stderr, "num calls to: malloc = %4d\n", num_malloc_calls); + fprintf(stderr, " calloc = %4d\n", num_calloc_calls); + fprintf(stderr, " free = %4d\n", num_free_calls); + fprintf(stderr, "total_mem: %u\n", (uint32_t)total_mem); + fprintf(stderr, "total_mem allocated: %u\n", (uint32_t)total_mem_allocated); + fprintf(stderr, "high-water mark: %u\n", (uint32_t)high_water_mark); + while (all_blocks != NULL) { + MemBlock* b = all_blocks; + all_blocks = b->next_; + free(b); + } +} + +static void Increment(int* const v) { + if (!exit_registered) { +#if defined(MALLOC_FAIL_AT) + { + const char* const malloc_fail_at_str = getenv("MALLOC_FAIL_AT"); + if (malloc_fail_at_str != NULL) { + countdown_to_fail = atoi(malloc_fail_at_str); + } + } +#endif +#if defined(MALLOC_LIMIT) + { + const char* const malloc_limit_str = getenv("MALLOC_LIMIT"); + if (malloc_limit_str != NULL) { + mem_limit = atoi(malloc_limit_str); + } + } +#endif + (void)countdown_to_fail; + (void)mem_limit; + atexit(PrintMemInfo); + exit_registered = 1; + } + ++*v; +} + +static void AddMem(void* ptr, size_t size) { + if (ptr != NULL) { + MemBlock* const b = (MemBlock*)malloc(sizeof(*b)); + if (b == NULL) abort(); + b->next_ = all_blocks; + all_blocks = b; + b->ptr_ = ptr; + b->size_ = size; + total_mem += size; + total_mem_allocated += size; +#if defined(PRINT_MEM_TRAFFIC) +#if defined(MALLOC_FAIL_AT) + fprintf(stderr, "fail-count: %5d [mem=%u]\n", + num_malloc_calls + num_calloc_calls, (uint32_t)total_mem); +#else + fprintf(stderr, "Mem: %u (+%u)\n", (uint32_t)total_mem, (uint32_t)size); +#endif +#endif + if (total_mem > high_water_mark) high_water_mark = total_mem; + } +} + +static void SubMem(void* ptr) { + if (ptr != NULL) { + MemBlock** b = &all_blocks; + // Inefficient search, but that's just for debugging. + while (*b != NULL && (*b)->ptr_ != ptr) b = &(*b)->next_; + if (*b == NULL) { + fprintf(stderr, "Invalid pointer free! (%p)\n", ptr); + abort(); + } + { + MemBlock* const block = *b; + *b = block->next_; + total_mem -= block->size_; +#if defined(PRINT_MEM_TRAFFIC) + fprintf(stderr, "Mem: %u (-%u)\n", + (uint32_t)total_mem, (uint32_t)block->size_); +#endif + free(block); + } + } +} + +#else +#define Increment(v) do {} while (0) +#define AddMem(p, s) do {} while (0) +#define SubMem(p) do {} while (0) +#endif + +// Returns 0 in case of overflow of nmemb * size. +static int CheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) { + const uint64_t total_size = nmemb * size; + if (nmemb == 0) return 1; + if ((uint64_t)size > WEBP_MAX_ALLOCABLE_MEMORY / nmemb) return 0; + if (total_size != (size_t)total_size) return 0; +#if defined(PRINT_MEM_INFO) && defined(MALLOC_FAIL_AT) + if (countdown_to_fail > 0 && --countdown_to_fail == 0) { + return 0; // fake fail! + } +#endif +#if defined(MALLOC_LIMIT) + if (mem_limit > 0 && total_mem + total_size >= mem_limit) { + return 0; // fake fail! + } +#endif + + return 1; +} + +void* WebPSafeMalloc(uint64_t nmemb, size_t size) { + void* ptr; + Increment(&num_malloc_calls); + if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; + assert(nmemb * size > 0); + ptr = malloc((size_t)(nmemb * size)); + AddMem(ptr, (size_t)(nmemb * size)); + return ptr; +} + +void* WebPSafeCalloc(uint64_t nmemb, size_t size) { + void* ptr; + Increment(&num_calloc_calls); + if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; + assert(nmemb * size > 0); + ptr = calloc((size_t)nmemb, size); + AddMem(ptr, (size_t)(nmemb * size)); + return ptr; +} + +void WebPSafeFree(void* const ptr) { + if (ptr != NULL) { + Increment(&num_free_calls); + SubMem(ptr); + } + free(ptr); +} + +// Public API function. +void WebPFree(void* ptr) { + free(ptr); +} + +//------------------------------------------------------------------------------ + +void WebPCopyPlane(const uint8_t* src, int src_stride, + uint8_t* dst, int dst_stride, int width, int height) { + assert(src != NULL && dst != NULL); + assert(src_stride >= width && dst_stride >= width); + while (height-- > 0) { + memcpy(dst, src, width); + src += src_stride; + dst += dst_stride; + } +} + +void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) { + assert(src != NULL && dst != NULL); + assert(src->width == dst->width && src->height == dst->height); + assert(src->use_argb && dst->use_argb); + WebPCopyPlane((uint8_t*)src->argb, 4 * src->argb_stride, (uint8_t*)dst->argb, + 4 * dst->argb_stride, 4 * src->width, src->height); +} + +//------------------------------------------------------------------------------ + +#define MAX_COLOR_COUNT MAX_PALETTE_SIZE +#define COLOR_HASH_SIZE (MAX_COLOR_COUNT * 4) +#define COLOR_HASH_RIGHT_SHIFT 22 // 32 - log2(COLOR_HASH_SIZE). + +int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) { + int i; + int x, y; + int num_colors = 0; + uint8_t in_use[COLOR_HASH_SIZE] = { 0 }; + uint32_t colors[COLOR_HASH_SIZE]; + static const uint32_t kHashMul = 0x1e35a7bdU; + const uint32_t* argb = pic->argb; + const int width = pic->width; + const int height = pic->height; + uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0] + assert(pic != NULL); + assert(pic->use_argb); + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + int key; + if (argb[x] == last_pix) { + continue; + } + last_pix = argb[x]; + key = (kHashMul * last_pix) >> COLOR_HASH_RIGHT_SHIFT; + while (1) { + if (!in_use[key]) { + colors[key] = last_pix; + in_use[key] = 1; + ++num_colors; + if (num_colors > MAX_COLOR_COUNT) { + return MAX_COLOR_COUNT + 1; // Exact count not needed. + } + break; + } else if (colors[key] == last_pix) { + break; // The color is already there. + } else { + // Some other color sits here, so do linear conflict resolution. + ++key; + key &= (COLOR_HASH_SIZE - 1); // Key mask. + } + } + } + argb += pic->argb_stride; + } + + if (palette != NULL) { // Fill the colors into palette. + num_colors = 0; + for (i = 0; i < COLOR_HASH_SIZE; ++i) { + if (in_use[i]) { + palette[num_colors] = colors[i]; + ++num_colors; + } + } + } + return num_colors; +} + +#undef MAX_COLOR_COUNT +#undef COLOR_HASH_SIZE +#undef COLOR_HASH_RIGHT_SHIFT + +//------------------------------------------------------------------------------ diff --git a/thirdparty/libwebp/utils/utils.h b/thirdparty/libwebp/utils/utils.h new file mode 100644 index 0000000000..e0a81126df --- /dev/null +++ b/thirdparty/libwebp/utils/utils.h @@ -0,0 +1,182 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +#ifndef WEBP_UTILS_UTILS_H_ +#define WEBP_UTILS_UTILS_H_ + +#ifdef HAVE_CONFIG_H +#include "../webp/config.h" +#endif + +#include <assert.h> + +#include "../dsp/dsp.h" +#include "../webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Memory allocation + +// This is the maximum memory amount that libwebp will ever try to allocate. +#define WEBP_MAX_ALLOCABLE_MEMORY (1ULL << 40) + +// size-checking safe malloc/calloc: verify that the requested size is not too +// large, or return NULL. You don't need to call these for constructs like +// malloc(sizeof(foo)), but only if there's picture-dependent size involved +// somewhere (like: malloc(num_pixels * sizeof(*something))). That's why this +// safe malloc() borrows the signature from calloc(), pointing at the dangerous +// underlying multiply involved. +WEBP_EXTERN(void*) WebPSafeMalloc(uint64_t nmemb, size_t size); +// Note that WebPSafeCalloc() expects the second argument type to be 'size_t' +// in order to favor the "calloc(num_foo, sizeof(foo))" pattern. +WEBP_EXTERN(void*) WebPSafeCalloc(uint64_t nmemb, size_t size); + +// Companion deallocation function to the above allocations. +WEBP_EXTERN(void) WebPSafeFree(void* const ptr); + +//------------------------------------------------------------------------------ +// Alignment + +#define WEBP_ALIGN_CST 31 +#define WEBP_ALIGN(PTR) (((uintptr_t)(PTR) + WEBP_ALIGN_CST) & ~WEBP_ALIGN_CST) + +#if defined(WEBP_FORCE_ALIGNED) +#include <string.h> +// memcpy() is the safe way of moving potentially unaligned 32b memory. +static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) { + uint32_t A; + memcpy(&A, (const int*)ptr, sizeof(A)); + return A; +} +static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { + memcpy(ptr, &val, sizeof(val)); +} +#else +static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE +uint32_t WebPMemToUint32(const uint8_t* const ptr) { + return *(const uint32_t*)ptr; +} +static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE +void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { + *(uint32_t*)ptr = val; +} +#endif + +//------------------------------------------------------------------------------ +// Reading/writing data. + +// Read 16, 24 or 32 bits stored in little-endian order. +static WEBP_INLINE int GetLE16(const uint8_t* const data) { + return (int)(data[0] << 0) | (data[1] << 8); +} + +static WEBP_INLINE int GetLE24(const uint8_t* const data) { + return GetLE16(data) | (data[2] << 16); +} + +static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) { + return GetLE16(data) | ((uint32_t)GetLE16(data + 2) << 16); +} + +// Store 16, 24 or 32 bits in little-endian order. +static WEBP_INLINE void PutLE16(uint8_t* const data, int val) { + assert(val < (1 << 16)); + data[0] = (val >> 0); + data[1] = (val >> 8); +} + +static WEBP_INLINE void PutLE24(uint8_t* const data, int val) { + assert(val < (1 << 24)); + PutLE16(data, val & 0xffff); + data[2] = (val >> 16); +} + +static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) { + PutLE16(data, (int)(val & 0xffff)); + PutLE16(data + 2, (int)(val >> 16)); +} + +// Returns (int)floor(log2(n)). n must be > 0. +// use GNU builtins where available. +#if defined(__GNUC__) && \ + ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) +static WEBP_INLINE int BitsLog2Floor(uint32_t n) { + return 31 ^ __builtin_clz(n); +} +#elif defined(_MSC_VER) && _MSC_VER > 1310 && \ + (defined(_M_X64) || defined(_M_IX86)) +#include <intrin.h> +#pragma intrinsic(_BitScanReverse) + +static WEBP_INLINE int BitsLog2Floor(uint32_t n) { + unsigned long first_set_bit; + _BitScanReverse(&first_set_bit, n); + return first_set_bit; +} +#else +static WEBP_INLINE int BitsLog2Floor(uint32_t n) { + int log = 0; + uint32_t value = n; + int i; + + for (i = 4; i >= 0; --i) { + const int shift = (1 << i); + const uint32_t x = value >> shift; + if (x != 0) { + value = x; + log += shift; + } + } + return log; +} +#endif + +//------------------------------------------------------------------------------ +// Pixel copying. + +struct WebPPicture; + +// Copy width x height pixels from 'src' to 'dst' honoring the strides. +WEBP_EXTERN(void) WebPCopyPlane(const uint8_t* src, int src_stride, + uint8_t* dst, int dst_stride, + int width, int height); + +// Copy ARGB pixels from 'src' to 'dst' honoring strides. 'src' and 'dst' are +// assumed to be already allocated and using ARGB data. +WEBP_EXTERN(void) WebPCopyPixels(const struct WebPPicture* const src, + struct WebPPicture* const dst); + +//------------------------------------------------------------------------------ +// Unique colors. + +// Returns count of unique colors in 'pic', assuming pic->use_argb is true. +// If the unique color count is more than MAX_COLOR_COUNT, returns +// MAX_COLOR_COUNT+1. +// If 'palette' is not NULL and number of unique colors is less than or equal to +// MAX_COLOR_COUNT, also outputs the actual unique colors into 'palette'. +// Note: 'palette' is assumed to be an array already allocated with at least +// MAX_COLOR_COUNT elements. +WEBP_EXTERN(int) WebPGetColorPalette(const struct WebPPicture* const pic, + uint32_t* const palette); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_UTILS_UTILS_H_ */ diff --git a/drivers/webp/config.h b/thirdparty/libwebp/webp/config.h index 0ce1c7064d..0ce1c7064d 100644 --- a/drivers/webp/config.h +++ b/thirdparty/libwebp/webp/config.h diff --git a/drivers/webp/decode.h b/thirdparty/libwebp/webp/decode.h index 7a3bed93a4..7a3bed93a4 100644 --- a/drivers/webp/decode.h +++ b/thirdparty/libwebp/webp/decode.h diff --git a/drivers/webp/demux.h b/thirdparty/libwebp/webp/demux.h index 454f6914b2..454f6914b2 100644 --- a/drivers/webp/demux.h +++ b/thirdparty/libwebp/webp/demux.h diff --git a/drivers/webp/encode.h b/thirdparty/libwebp/webp/encode.h index 9291b7195c..9291b7195c 100644 --- a/drivers/webp/encode.h +++ b/thirdparty/libwebp/webp/encode.h diff --git a/drivers/webp/format_constants.h b/thirdparty/libwebp/webp/format_constants.h index b6e78a643e..b6e78a643e 100644 --- a/drivers/webp/format_constants.h +++ b/thirdparty/libwebp/webp/format_constants.h diff --git a/drivers/webp/mux.h b/thirdparty/libwebp/webp/mux.h index b72658c741..b72658c741 100644 --- a/drivers/webp/mux.h +++ b/thirdparty/libwebp/webp/mux.h diff --git a/drivers/webp/mux_types.h b/thirdparty/libwebp/webp/mux_types.h index c94043a3c0..c94043a3c0 100644 --- a/drivers/webp/mux_types.h +++ b/thirdparty/libwebp/webp/mux_types.h diff --git a/drivers/webp/types.h b/thirdparty/libwebp/webp/types.h index 98fff35a11..98fff35a11 100644 --- a/drivers/webp/types.h +++ b/thirdparty/libwebp/webp/types.h diff --git a/thirdparty/openssl/LICENSE b/thirdparty/openssl/LICENSE new file mode 100644 index 0000000000..fb03713dd1 --- /dev/null +++ b/thirdparty/openssl/LICENSE @@ -0,0 +1,127 @@ + + LICENSE ISSUES + ============== + + The OpenSSL toolkit stays under a dual license, i.e. both the conditions of + the OpenSSL License and the original SSLeay license apply to the toolkit. + See below for the actual license texts. Actually both licenses are BSD-style + Open Source licenses. In case of any license issues related to OpenSSL + please contact openssl-core@openssl.org. + + OpenSSL License + --------------- + +/* ==================================================================== + * Copyright (c) 1998-2016 The OpenSSL Project. All rights reserved. + * + * 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. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF 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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + Original SSLeay License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + diff --git a/drivers/builtin_openssl2/buildinf.h b/thirdparty/openssl/buildinf.h index 2e287c42d8..2e287c42d8 100644 --- a/drivers/builtin_openssl2/buildinf.h +++ b/thirdparty/openssl/buildinf.h diff --git a/drivers/builtin_openssl2/crypto/LPdir_nyi.c b/thirdparty/openssl/crypto/LPdir_nyi.c index 283d5b0636..283d5b0636 100644 --- a/drivers/builtin_openssl2/crypto/LPdir_nyi.c +++ b/thirdparty/openssl/crypto/LPdir_nyi.c diff --git a/drivers/builtin_openssl2/crypto/LPdir_unix.c b/thirdparty/openssl/crypto/LPdir_unix.c index bead6abd71..bead6abd71 100644 --- a/drivers/builtin_openssl2/crypto/LPdir_unix.c +++ b/thirdparty/openssl/crypto/LPdir_unix.c diff --git a/drivers/builtin_openssl2/crypto/LPdir_vms.c b/thirdparty/openssl/crypto/LPdir_vms.c index 88c7ddd85c..88c7ddd85c 100644 --- a/drivers/builtin_openssl2/crypto/LPdir_vms.c +++ b/thirdparty/openssl/crypto/LPdir_vms.c diff --git a/drivers/builtin_openssl2/crypto/LPdir_win.c b/thirdparty/openssl/crypto/LPdir_win.c index 07e63fb424..07e63fb424 100644 --- a/drivers/builtin_openssl2/crypto/LPdir_win.c +++ b/thirdparty/openssl/crypto/LPdir_win.c diff --git a/drivers/builtin_openssl2/crypto/LPdir_win32.c b/thirdparty/openssl/crypto/LPdir_win32.c index b1c983d87f..b1c983d87f 100644 --- a/drivers/builtin_openssl2/crypto/LPdir_win32.c +++ b/thirdparty/openssl/crypto/LPdir_win32.c diff --git a/drivers/builtin_openssl2/crypto/LPdir_wince.c b/thirdparty/openssl/crypto/LPdir_wince.c index ae8a56f4be..ae8a56f4be 100644 --- a/drivers/builtin_openssl2/crypto/LPdir_wince.c +++ b/thirdparty/openssl/crypto/LPdir_wince.c diff --git a/drivers/builtin_openssl2/crypto/aes/README b/thirdparty/openssl/crypto/aes/README index 0f9620a80e..0f9620a80e 100644 --- a/drivers/builtin_openssl2/crypto/aes/README +++ b/thirdparty/openssl/crypto/aes/README diff --git a/drivers/builtin_openssl2/crypto/aes/aes_cbc.c b/thirdparty/openssl/crypto/aes/aes_cbc.c index 805d0e260a..805d0e260a 100644 --- a/drivers/builtin_openssl2/crypto/aes/aes_cbc.c +++ b/thirdparty/openssl/crypto/aes/aes_cbc.c diff --git a/drivers/builtin_openssl2/crypto/aes/aes_cfb.c b/thirdparty/openssl/crypto/aes/aes_cfb.c index 1225000963..1225000963 100644 --- a/drivers/builtin_openssl2/crypto/aes/aes_cfb.c +++ b/thirdparty/openssl/crypto/aes/aes_cfb.c diff --git a/drivers/builtin_openssl2/crypto/aes/aes_core.c b/thirdparty/openssl/crypto/aes/aes_core.c index 7019b5d7aa..7019b5d7aa 100644 --- a/drivers/builtin_openssl2/crypto/aes/aes_core.c +++ b/thirdparty/openssl/crypto/aes/aes_core.c diff --git a/drivers/builtin_openssl2/crypto/aes/aes_ctr.c b/thirdparty/openssl/crypto/aes/aes_ctr.c index 9e760c4b12..9e760c4b12 100644 --- a/drivers/builtin_openssl2/crypto/aes/aes_ctr.c +++ b/thirdparty/openssl/crypto/aes/aes_ctr.c diff --git a/drivers/builtin_openssl2/crypto/aes/aes_ecb.c b/thirdparty/openssl/crypto/aes/aes_ecb.c index 52151a5c70..52151a5c70 100644 --- a/drivers/builtin_openssl2/crypto/aes/aes_ecb.c +++ b/thirdparty/openssl/crypto/aes/aes_ecb.c diff --git a/drivers/builtin_openssl2/crypto/aes/aes_ige.c b/thirdparty/openssl/crypto/aes/aes_ige.c index 8f2b770647..8f2b770647 100644 --- a/drivers/builtin_openssl2/crypto/aes/aes_ige.c +++ b/thirdparty/openssl/crypto/aes/aes_ige.c diff --git a/drivers/builtin_openssl2/crypto/aes/aes_locl.h b/thirdparty/openssl/crypto/aes/aes_locl.h index 7acd74ec16..7acd74ec16 100644 --- a/drivers/builtin_openssl2/crypto/aes/aes_locl.h +++ b/thirdparty/openssl/crypto/aes/aes_locl.h diff --git a/drivers/builtin_openssl2/crypto/aes/aes_misc.c b/thirdparty/openssl/crypto/aes/aes_misc.c index fafad4d6f5..fafad4d6f5 100644 --- a/drivers/builtin_openssl2/crypto/aes/aes_misc.c +++ b/thirdparty/openssl/crypto/aes/aes_misc.c diff --git a/drivers/builtin_openssl2/crypto/aes/aes_ofb.c b/thirdparty/openssl/crypto/aes/aes_ofb.c index 64a08caaec..64a08caaec 100644 --- a/drivers/builtin_openssl2/crypto/aes/aes_ofb.c +++ b/thirdparty/openssl/crypto/aes/aes_ofb.c diff --git a/drivers/builtin_openssl2/crypto/aes/aes_wrap.c b/thirdparty/openssl/crypto/aes/aes_wrap.c index b7b64d57a4..b7b64d57a4 100644 --- a/drivers/builtin_openssl2/crypto/aes/aes_wrap.c +++ b/thirdparty/openssl/crypto/aes/aes_wrap.c diff --git a/drivers/builtin_openssl2/crypto/aes/aes_x86core.c b/thirdparty/openssl/crypto/aes/aes_x86core.c index b5dd697677..b5dd697677 100644 --- a/drivers/builtin_openssl2/crypto/aes/aes_x86core.c +++ b/thirdparty/openssl/crypto/aes/aes_x86core.c diff --git a/drivers/builtin_openssl2/crypto/arm_arch.h b/thirdparty/openssl/crypto/arm_arch.h index 9d6e58880d..9d6e58880d 100644 --- a/drivers/builtin_openssl2/crypto/arm_arch.h +++ b/thirdparty/openssl/crypto/arm_arch.h diff --git a/drivers/builtin_openssl2/crypto/armcap.c b/thirdparty/openssl/crypto/armcap.c index 356fa15287..356fa15287 100644 --- a/drivers/builtin_openssl2/crypto/armcap.c +++ b/thirdparty/openssl/crypto/armcap.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_bitstr.c b/thirdparty/openssl/crypto/asn1/a_bitstr.c index f906188b11..f906188b11 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_bitstr.c +++ b/thirdparty/openssl/crypto/asn1/a_bitstr.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_bool.c b/thirdparty/openssl/crypto/asn1/a_bool.c index 1b85bc9e61..1b85bc9e61 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_bool.c +++ b/thirdparty/openssl/crypto/asn1/a_bool.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_bytes.c b/thirdparty/openssl/crypto/asn1/a_bytes.c index 385b53986a..385b53986a 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_bytes.c +++ b/thirdparty/openssl/crypto/asn1/a_bytes.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_d2i_fp.c b/thirdparty/openssl/crypto/asn1/a_d2i_fp.c index 51b6f245ab..51b6f245ab 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_d2i_fp.c +++ b/thirdparty/openssl/crypto/asn1/a_d2i_fp.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_digest.c b/thirdparty/openssl/crypto/asn1/a_digest.c index 7cbc4751cd..7cbc4751cd 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_digest.c +++ b/thirdparty/openssl/crypto/asn1/a_digest.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_dup.c b/thirdparty/openssl/crypto/asn1/a_dup.c index 349ab56213..349ab56213 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_dup.c +++ b/thirdparty/openssl/crypto/asn1/a_dup.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_enum.c b/thirdparty/openssl/crypto/asn1/a_enum.c index c3498ac99c..c3498ac99c 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_enum.c +++ b/thirdparty/openssl/crypto/asn1/a_enum.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_gentm.c b/thirdparty/openssl/crypto/asn1/a_gentm.c index fa76dcac91..fa76dcac91 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_gentm.c +++ b/thirdparty/openssl/crypto/asn1/a_gentm.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_i2d_fp.c b/thirdparty/openssl/crypto/asn1/a_i2d_fp.c index 0f56cd4e07..0f56cd4e07 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_i2d_fp.c +++ b/thirdparty/openssl/crypto/asn1/a_i2d_fp.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_int.c b/thirdparty/openssl/crypto/asn1/a_int.c index 7e26704a54..7e26704a54 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_int.c +++ b/thirdparty/openssl/crypto/asn1/a_int.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_mbstr.c b/thirdparty/openssl/crypto/asn1/a_mbstr.c index 6935efe09f..6935efe09f 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_mbstr.c +++ b/thirdparty/openssl/crypto/asn1/a_mbstr.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_object.c b/thirdparty/openssl/crypto/asn1/a_object.c index 27f9c16914..27f9c16914 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_object.c +++ b/thirdparty/openssl/crypto/asn1/a_object.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_octet.c b/thirdparty/openssl/crypto/asn1/a_octet.c index 1a6e9ca9cc..1a6e9ca9cc 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_octet.c +++ b/thirdparty/openssl/crypto/asn1/a_octet.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_print.c b/thirdparty/openssl/crypto/asn1/a_print.c index d83e4ad82c..d83e4ad82c 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_print.c +++ b/thirdparty/openssl/crypto/asn1/a_print.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_set.c b/thirdparty/openssl/crypto/asn1/a_set.c index bf3f971889..bf3f971889 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_set.c +++ b/thirdparty/openssl/crypto/asn1/a_set.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_sign.c b/thirdparty/openssl/crypto/asn1/a_sign.c index 51c6a0c34d..51c6a0c34d 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_sign.c +++ b/thirdparty/openssl/crypto/asn1/a_sign.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_strex.c b/thirdparty/openssl/crypto/asn1/a_strex.c index 35fd44cd22..35fd44cd22 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_strex.c +++ b/thirdparty/openssl/crypto/asn1/a_strex.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_strnid.c b/thirdparty/openssl/crypto/asn1/a_strnid.c index 5224345368..5224345368 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_strnid.c +++ b/thirdparty/openssl/crypto/asn1/a_strnid.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_time.c b/thirdparty/openssl/crypto/asn1/a_time.c index fcb2d565cd..fcb2d565cd 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_time.c +++ b/thirdparty/openssl/crypto/asn1/a_time.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_type.c b/thirdparty/openssl/crypto/asn1/a_type.c index bb166e8568..bb166e8568 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_type.c +++ b/thirdparty/openssl/crypto/asn1/a_type.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_utctm.c b/thirdparty/openssl/crypto/asn1/a_utctm.c index 724a10be4e..724a10be4e 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_utctm.c +++ b/thirdparty/openssl/crypto/asn1/a_utctm.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_utf8.c b/thirdparty/openssl/crypto/asn1/a_utf8.c index 23dc2e828a..23dc2e828a 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_utf8.c +++ b/thirdparty/openssl/crypto/asn1/a_utf8.c diff --git a/drivers/builtin_openssl2/crypto/asn1/a_verify.c b/thirdparty/openssl/crypto/asn1/a_verify.c index 3ffd934cba..3ffd934cba 100644 --- a/drivers/builtin_openssl2/crypto/asn1/a_verify.c +++ b/thirdparty/openssl/crypto/asn1/a_verify.c diff --git a/drivers/builtin_openssl2/crypto/asn1/ameth_lib.c b/thirdparty/openssl/crypto/asn1/ameth_lib.c index 5389c04347..5389c04347 100644 --- a/drivers/builtin_openssl2/crypto/asn1/ameth_lib.c +++ b/thirdparty/openssl/crypto/asn1/ameth_lib.c diff --git a/drivers/builtin_openssl2/crypto/asn1/asn1_err.c b/thirdparty/openssl/crypto/asn1/asn1_err.c index fd4ac8d9db..fd4ac8d9db 100644 --- a/drivers/builtin_openssl2/crypto/asn1/asn1_err.c +++ b/thirdparty/openssl/crypto/asn1/asn1_err.c diff --git a/drivers/builtin_openssl2/crypto/asn1/asn1_gen.c b/thirdparty/openssl/crypto/asn1/asn1_gen.c index 65749239b1..65749239b1 100644 --- a/drivers/builtin_openssl2/crypto/asn1/asn1_gen.c +++ b/thirdparty/openssl/crypto/asn1/asn1_gen.c diff --git a/drivers/builtin_openssl2/crypto/asn1/asn1_lib.c b/thirdparty/openssl/crypto/asn1/asn1_lib.c index 874b1af8b0..874b1af8b0 100644 --- a/drivers/builtin_openssl2/crypto/asn1/asn1_lib.c +++ b/thirdparty/openssl/crypto/asn1/asn1_lib.c diff --git a/drivers/builtin_openssl2/crypto/asn1/asn1_locl.h b/thirdparty/openssl/crypto/asn1/asn1_locl.h index 4c004fab9a..4c004fab9a 100644 --- a/drivers/builtin_openssl2/crypto/asn1/asn1_locl.h +++ b/thirdparty/openssl/crypto/asn1/asn1_locl.h diff --git a/drivers/builtin_openssl2/crypto/asn1/asn1_par.c b/thirdparty/openssl/crypto/asn1/asn1_par.c index e85e3398b6..e85e3398b6 100644 --- a/drivers/builtin_openssl2/crypto/asn1/asn1_par.c +++ b/thirdparty/openssl/crypto/asn1/asn1_par.c diff --git a/drivers/builtin_openssl2/crypto/asn1/asn_mime.c b/thirdparty/openssl/crypto/asn1/asn_mime.c index 96110c540f..96110c540f 100644 --- a/drivers/builtin_openssl2/crypto/asn1/asn_mime.c +++ b/thirdparty/openssl/crypto/asn1/asn_mime.c diff --git a/drivers/builtin_openssl2/crypto/asn1/asn_moid.c b/thirdparty/openssl/crypto/asn1/asn_moid.c index fab2dd92e2..fab2dd92e2 100644 --- a/drivers/builtin_openssl2/crypto/asn1/asn_moid.c +++ b/thirdparty/openssl/crypto/asn1/asn_moid.c diff --git a/drivers/builtin_openssl2/crypto/asn1/asn_pack.c b/thirdparty/openssl/crypto/asn1/asn_pack.c index 366caf01f0..366caf01f0 100644 --- a/drivers/builtin_openssl2/crypto/asn1/asn_pack.c +++ b/thirdparty/openssl/crypto/asn1/asn_pack.c diff --git a/drivers/builtin_openssl2/crypto/asn1/bio_asn1.c b/thirdparty/openssl/crypto/asn1/bio_asn1.c index 60189b3b2c..60189b3b2c 100644 --- a/drivers/builtin_openssl2/crypto/asn1/bio_asn1.c +++ b/thirdparty/openssl/crypto/asn1/bio_asn1.c diff --git a/drivers/builtin_openssl2/crypto/asn1/bio_ndef.c b/thirdparty/openssl/crypto/asn1/bio_ndef.c index 31949b8794..31949b8794 100644 --- a/drivers/builtin_openssl2/crypto/asn1/bio_ndef.c +++ b/thirdparty/openssl/crypto/asn1/bio_ndef.c diff --git a/drivers/builtin_openssl2/crypto/asn1/charmap.h b/thirdparty/openssl/crypto/asn1/charmap.h index 3305ad146b..3305ad146b 100644 --- a/drivers/builtin_openssl2/crypto/asn1/charmap.h +++ b/thirdparty/openssl/crypto/asn1/charmap.h diff --git a/drivers/builtin_openssl2/crypto/asn1/d2i_pr.c b/thirdparty/openssl/crypto/asn1/d2i_pr.c index d21829af19..d21829af19 100644 --- a/drivers/builtin_openssl2/crypto/asn1/d2i_pr.c +++ b/thirdparty/openssl/crypto/asn1/d2i_pr.c diff --git a/drivers/builtin_openssl2/crypto/asn1/d2i_pu.c b/thirdparty/openssl/crypto/asn1/d2i_pu.c index 33542dd122..33542dd122 100644 --- a/drivers/builtin_openssl2/crypto/asn1/d2i_pu.c +++ b/thirdparty/openssl/crypto/asn1/d2i_pu.c diff --git a/drivers/builtin_openssl2/crypto/asn1/evp_asn1.c b/thirdparty/openssl/crypto/asn1/evp_asn1.c index 5876afa5e4..5876afa5e4 100644 --- a/drivers/builtin_openssl2/crypto/asn1/evp_asn1.c +++ b/thirdparty/openssl/crypto/asn1/evp_asn1.c diff --git a/drivers/builtin_openssl2/crypto/asn1/f_enum.c b/thirdparty/openssl/crypto/asn1/f_enum.c index 591c3b5781..591c3b5781 100644 --- a/drivers/builtin_openssl2/crypto/asn1/f_enum.c +++ b/thirdparty/openssl/crypto/asn1/f_enum.c diff --git a/drivers/builtin_openssl2/crypto/asn1/f_int.c b/thirdparty/openssl/crypto/asn1/f_int.c index 4a81f81c88..4a81f81c88 100644 --- a/drivers/builtin_openssl2/crypto/asn1/f_int.c +++ b/thirdparty/openssl/crypto/asn1/f_int.c diff --git a/drivers/builtin_openssl2/crypto/asn1/f_string.c b/thirdparty/openssl/crypto/asn1/f_string.c index 6a6cf34714..6a6cf34714 100644 --- a/drivers/builtin_openssl2/crypto/asn1/f_string.c +++ b/thirdparty/openssl/crypto/asn1/f_string.c diff --git a/drivers/builtin_openssl2/crypto/asn1/i2d_pr.c b/thirdparty/openssl/crypto/asn1/i2d_pr.c index 4d338ac55a..4d338ac55a 100644 --- a/drivers/builtin_openssl2/crypto/asn1/i2d_pr.c +++ b/thirdparty/openssl/crypto/asn1/i2d_pr.c diff --git a/drivers/builtin_openssl2/crypto/asn1/i2d_pu.c b/thirdparty/openssl/crypto/asn1/i2d_pu.c index b8ed355411..b8ed355411 100644 --- a/drivers/builtin_openssl2/crypto/asn1/i2d_pu.c +++ b/thirdparty/openssl/crypto/asn1/i2d_pu.c diff --git a/drivers/builtin_openssl2/crypto/asn1/n_pkey.c b/thirdparty/openssl/crypto/asn1/n_pkey.c index d5a55146a4..d5a55146a4 100644 --- a/drivers/builtin_openssl2/crypto/asn1/n_pkey.c +++ b/thirdparty/openssl/crypto/asn1/n_pkey.c diff --git a/drivers/builtin_openssl2/crypto/asn1/nsseq.c b/thirdparty/openssl/crypto/asn1/nsseq.c index f2f7cba49e..f2f7cba49e 100644 --- a/drivers/builtin_openssl2/crypto/asn1/nsseq.c +++ b/thirdparty/openssl/crypto/asn1/nsseq.c diff --git a/drivers/builtin_openssl2/crypto/asn1/p5_pbe.c b/thirdparty/openssl/crypto/asn1/p5_pbe.c index bdbfdcd67c..bdbfdcd67c 100644 --- a/drivers/builtin_openssl2/crypto/asn1/p5_pbe.c +++ b/thirdparty/openssl/crypto/asn1/p5_pbe.c diff --git a/drivers/builtin_openssl2/crypto/asn1/p5_pbev2.c b/thirdparty/openssl/crypto/asn1/p5_pbev2.c index 73ba4a3d67..73ba4a3d67 100644 --- a/drivers/builtin_openssl2/crypto/asn1/p5_pbev2.c +++ b/thirdparty/openssl/crypto/asn1/p5_pbev2.c diff --git a/drivers/builtin_openssl2/crypto/asn1/p8_pkey.c b/thirdparty/openssl/crypto/asn1/p8_pkey.c index 0a425cd29d..0a425cd29d 100644 --- a/drivers/builtin_openssl2/crypto/asn1/p8_pkey.c +++ b/thirdparty/openssl/crypto/asn1/p8_pkey.c diff --git a/drivers/builtin_openssl2/crypto/asn1/t_bitst.c b/thirdparty/openssl/crypto/asn1/t_bitst.c index d5cf3c7732..d5cf3c7732 100644 --- a/drivers/builtin_openssl2/crypto/asn1/t_bitst.c +++ b/thirdparty/openssl/crypto/asn1/t_bitst.c diff --git a/drivers/builtin_openssl2/crypto/asn1/t_crl.c b/thirdparty/openssl/crypto/asn1/t_crl.c index 0dfaf0ba26..0dfaf0ba26 100644 --- a/drivers/builtin_openssl2/crypto/asn1/t_crl.c +++ b/thirdparty/openssl/crypto/asn1/t_crl.c diff --git a/drivers/builtin_openssl2/crypto/asn1/t_pkey.c b/thirdparty/openssl/crypto/asn1/t_pkey.c index 735c34264b..735c34264b 100644 --- a/drivers/builtin_openssl2/crypto/asn1/t_pkey.c +++ b/thirdparty/openssl/crypto/asn1/t_pkey.c diff --git a/drivers/builtin_openssl2/crypto/asn1/t_req.c b/thirdparty/openssl/crypto/asn1/t_req.c index 024553ab19..024553ab19 100644 --- a/drivers/builtin_openssl2/crypto/asn1/t_req.c +++ b/thirdparty/openssl/crypto/asn1/t_req.c diff --git a/drivers/builtin_openssl2/crypto/asn1/t_spki.c b/thirdparty/openssl/crypto/asn1/t_spki.c index 3bf48db509..3bf48db509 100644 --- a/drivers/builtin_openssl2/crypto/asn1/t_spki.c +++ b/thirdparty/openssl/crypto/asn1/t_spki.c diff --git a/drivers/builtin_openssl2/crypto/asn1/t_x509.c b/thirdparty/openssl/crypto/asn1/t_x509.c index 8888396f84..8888396f84 100644 --- a/drivers/builtin_openssl2/crypto/asn1/t_x509.c +++ b/thirdparty/openssl/crypto/asn1/t_x509.c diff --git a/drivers/builtin_openssl2/crypto/asn1/t_x509a.c b/thirdparty/openssl/crypto/asn1/t_x509a.c index f4b8f94cb3..f4b8f94cb3 100644 --- a/drivers/builtin_openssl2/crypto/asn1/t_x509a.c +++ b/thirdparty/openssl/crypto/asn1/t_x509a.c diff --git a/drivers/builtin_openssl2/crypto/asn1/tasn_dec.c b/thirdparty/openssl/crypto/asn1/tasn_dec.c index 6bdcd5c542..6bdcd5c542 100644 --- a/drivers/builtin_openssl2/crypto/asn1/tasn_dec.c +++ b/thirdparty/openssl/crypto/asn1/tasn_dec.c diff --git a/drivers/builtin_openssl2/crypto/asn1/tasn_enc.c b/thirdparty/openssl/crypto/asn1/tasn_enc.c index f7f83e56a9..f7f83e56a9 100644 --- a/drivers/builtin_openssl2/crypto/asn1/tasn_enc.c +++ b/thirdparty/openssl/crypto/asn1/tasn_enc.c diff --git a/drivers/builtin_openssl2/crypto/asn1/tasn_fre.c b/thirdparty/openssl/crypto/asn1/tasn_fre.c index aeea4eff7a..aeea4eff7a 100644 --- a/drivers/builtin_openssl2/crypto/asn1/tasn_fre.c +++ b/thirdparty/openssl/crypto/asn1/tasn_fre.c diff --git a/drivers/builtin_openssl2/crypto/asn1/tasn_new.c b/thirdparty/openssl/crypto/asn1/tasn_new.c index b0c73beeb5..b0c73beeb5 100644 --- a/drivers/builtin_openssl2/crypto/asn1/tasn_new.c +++ b/thirdparty/openssl/crypto/asn1/tasn_new.c diff --git a/drivers/builtin_openssl2/crypto/asn1/tasn_prn.c b/thirdparty/openssl/crypto/asn1/tasn_prn.c index 5e7d53e985..5e7d53e985 100644 --- a/drivers/builtin_openssl2/crypto/asn1/tasn_prn.c +++ b/thirdparty/openssl/crypto/asn1/tasn_prn.c diff --git a/drivers/builtin_openssl2/crypto/asn1/tasn_typ.c b/thirdparty/openssl/crypto/asn1/tasn_typ.c index 740e86d5fc..740e86d5fc 100644 --- a/drivers/builtin_openssl2/crypto/asn1/tasn_typ.c +++ b/thirdparty/openssl/crypto/asn1/tasn_typ.c diff --git a/drivers/builtin_openssl2/crypto/asn1/tasn_utl.c b/thirdparty/openssl/crypto/asn1/tasn_utl.c index 41726d8feb..41726d8feb 100644 --- a/drivers/builtin_openssl2/crypto/asn1/tasn_utl.c +++ b/thirdparty/openssl/crypto/asn1/tasn_utl.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_algor.c b/thirdparty/openssl/crypto/asn1/x_algor.c index fd7d16d404..fd7d16d404 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_algor.c +++ b/thirdparty/openssl/crypto/asn1/x_algor.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_attrib.c b/thirdparty/openssl/crypto/asn1/x_attrib.c index 93ef53bd5e..93ef53bd5e 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_attrib.c +++ b/thirdparty/openssl/crypto/asn1/x_attrib.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_bignum.c b/thirdparty/openssl/crypto/asn1/x_bignum.c index eaf046639d..eaf046639d 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_bignum.c +++ b/thirdparty/openssl/crypto/asn1/x_bignum.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_crl.c b/thirdparty/openssl/crypto/asn1/x_crl.c index 027950330d..027950330d 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_crl.c +++ b/thirdparty/openssl/crypto/asn1/x_crl.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_exten.c b/thirdparty/openssl/crypto/asn1/x_exten.c index 00a9580aa7..00a9580aa7 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_exten.c +++ b/thirdparty/openssl/crypto/asn1/x_exten.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_info.c b/thirdparty/openssl/crypto/asn1/x_info.c index 067fd72a6e..067fd72a6e 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_info.c +++ b/thirdparty/openssl/crypto/asn1/x_info.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_long.c b/thirdparty/openssl/crypto/asn1/x_long.c index 3aed44a3dd..3aed44a3dd 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_long.c +++ b/thirdparty/openssl/crypto/asn1/x_long.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_name.c b/thirdparty/openssl/crypto/asn1/x_name.c index a858c2993b..a858c2993b 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_name.c +++ b/thirdparty/openssl/crypto/asn1/x_name.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_nx509.c b/thirdparty/openssl/crypto/asn1/x_nx509.c index 5aa0ed58b4..5aa0ed58b4 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_nx509.c +++ b/thirdparty/openssl/crypto/asn1/x_nx509.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_pkey.c b/thirdparty/openssl/crypto/asn1/x_pkey.c index 2da23e4756..2da23e4756 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_pkey.c +++ b/thirdparty/openssl/crypto/asn1/x_pkey.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_pubkey.c b/thirdparty/openssl/crypto/asn1/x_pubkey.c index 6c57a7971c..6c57a7971c 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_pubkey.c +++ b/thirdparty/openssl/crypto/asn1/x_pubkey.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_req.c b/thirdparty/openssl/crypto/asn1/x_req.c index ae293aa0ca..ae293aa0ca 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_req.c +++ b/thirdparty/openssl/crypto/asn1/x_req.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_sig.c b/thirdparty/openssl/crypto/asn1/x_sig.c index dd33720c10..dd33720c10 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_sig.c +++ b/thirdparty/openssl/crypto/asn1/x_sig.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_spki.c b/thirdparty/openssl/crypto/asn1/x_spki.c index 1df6b87d2b..1df6b87d2b 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_spki.c +++ b/thirdparty/openssl/crypto/asn1/x_spki.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_val.c b/thirdparty/openssl/crypto/asn1/x_val.c index ee75a1e254..ee75a1e254 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_val.c +++ b/thirdparty/openssl/crypto/asn1/x_val.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_x509.c b/thirdparty/openssl/crypto/asn1/x_x509.c index e31e1e750d..e31e1e750d 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_x509.c +++ b/thirdparty/openssl/crypto/asn1/x_x509.c diff --git a/drivers/builtin_openssl2/crypto/asn1/x_x509a.c b/thirdparty/openssl/crypto/asn1/x_x509a.c index ad93592a71..ad93592a71 100644 --- a/drivers/builtin_openssl2/crypto/asn1/x_x509a.c +++ b/thirdparty/openssl/crypto/asn1/x_x509a.c diff --git a/drivers/builtin_openssl2/crypto/bf/COPYRIGHT b/thirdparty/openssl/crypto/bf/COPYRIGHT index 6857223506..6857223506 100644 --- a/drivers/builtin_openssl2/crypto/bf/COPYRIGHT +++ b/thirdparty/openssl/crypto/bf/COPYRIGHT diff --git a/drivers/builtin_openssl2/crypto/bf/INSTALL b/thirdparty/openssl/crypto/bf/INSTALL index 3b25923532..3b25923532 100644 --- a/drivers/builtin_openssl2/crypto/bf/INSTALL +++ b/thirdparty/openssl/crypto/bf/INSTALL diff --git a/drivers/builtin_openssl2/crypto/bf/README b/thirdparty/openssl/crypto/bf/README index f2712fd0e7..f2712fd0e7 100644 --- a/drivers/builtin_openssl2/crypto/bf/README +++ b/thirdparty/openssl/crypto/bf/README diff --git a/drivers/builtin_openssl2/crypto/bf/VERSION b/thirdparty/openssl/crypto/bf/VERSION index be995855e4..be995855e4 100644 --- a/drivers/builtin_openssl2/crypto/bf/VERSION +++ b/thirdparty/openssl/crypto/bf/VERSION diff --git a/drivers/builtin_openssl2/crypto/bf/asm/readme b/thirdparty/openssl/crypto/bf/asm/readme index 2385fa3812..2385fa3812 100644 --- a/drivers/builtin_openssl2/crypto/bf/asm/readme +++ b/thirdparty/openssl/crypto/bf/asm/readme diff --git a/drivers/builtin_openssl2/crypto/bf/bf_cbc.c b/thirdparty/openssl/crypto/bf/bf_cbc.c index de827a1a3c..de827a1a3c 100644 --- a/drivers/builtin_openssl2/crypto/bf/bf_cbc.c +++ b/thirdparty/openssl/crypto/bf/bf_cbc.c diff --git a/drivers/builtin_openssl2/crypto/bf/bf_cfb64.c b/thirdparty/openssl/crypto/bf/bf_cfb64.c index ddeab6eb77..ddeab6eb77 100644 --- a/drivers/builtin_openssl2/crypto/bf/bf_cfb64.c +++ b/thirdparty/openssl/crypto/bf/bf_cfb64.c diff --git a/drivers/builtin_openssl2/crypto/bf/bf_ecb.c b/thirdparty/openssl/crypto/bf/bf_ecb.c index 967a7f5507..967a7f5507 100644 --- a/drivers/builtin_openssl2/crypto/bf/bf_ecb.c +++ b/thirdparty/openssl/crypto/bf/bf_ecb.c diff --git a/drivers/builtin_openssl2/crypto/bf/bf_enc.c b/thirdparty/openssl/crypto/bf/bf_enc.c index b268795f5b..b268795f5b 100644 --- a/drivers/builtin_openssl2/crypto/bf/bf_enc.c +++ b/thirdparty/openssl/crypto/bf/bf_enc.c diff --git a/drivers/builtin_openssl2/crypto/bf/bf_locl.h b/thirdparty/openssl/crypto/bf/bf_locl.h index 9448aed424..9448aed424 100644 --- a/drivers/builtin_openssl2/crypto/bf/bf_locl.h +++ b/thirdparty/openssl/crypto/bf/bf_locl.h diff --git a/drivers/builtin_openssl2/crypto/bf/bf_ofb64.c b/thirdparty/openssl/crypto/bf/bf_ofb64.c index a8d190b5dd..a8d190b5dd 100644 --- a/drivers/builtin_openssl2/crypto/bf/bf_ofb64.c +++ b/thirdparty/openssl/crypto/bf/bf_ofb64.c diff --git a/drivers/builtin_openssl2/crypto/bf/bf_opts.c b/thirdparty/openssl/crypto/bf/bf_opts.c index f85495cf9d..f85495cf9d 100644 --- a/drivers/builtin_openssl2/crypto/bf/bf_opts.c +++ b/thirdparty/openssl/crypto/bf/bf_opts.c diff --git a/drivers/builtin_openssl2/crypto/bf/bf_pi.h b/thirdparty/openssl/crypto/bf/bf_pi.h index 46a26739be..46a26739be 100644 --- a/drivers/builtin_openssl2/crypto/bf/bf_pi.h +++ b/thirdparty/openssl/crypto/bf/bf_pi.h diff --git a/drivers/builtin_openssl2/crypto/bf/bf_skey.c b/thirdparty/openssl/crypto/bf/bf_skey.c index 2cb3c66c8f..2cb3c66c8f 100644 --- a/drivers/builtin_openssl2/crypto/bf/bf_skey.c +++ b/thirdparty/openssl/crypto/bf/bf_skey.c diff --git a/drivers/builtin_openssl2/crypto/bf/bfs.cpp b/thirdparty/openssl/crypto/bf/bfs.cpp index d74c457760..d74c457760 100644 --- a/drivers/builtin_openssl2/crypto/bf/bfs.cpp +++ b/thirdparty/openssl/crypto/bf/bfs.cpp diff --git a/drivers/builtin_openssl2/crypto/bf/bfspeed.c b/thirdparty/openssl/crypto/bf/bfspeed.c index 305ad8bcbe..305ad8bcbe 100644 --- a/drivers/builtin_openssl2/crypto/bf/bfspeed.c +++ b/thirdparty/openssl/crypto/bf/bfspeed.c diff --git a/drivers/builtin_openssl2/crypto/bio/b_dump.c b/thirdparty/openssl/crypto/bio/b_dump.c index ccf0e287c4..ccf0e287c4 100644 --- a/drivers/builtin_openssl2/crypto/bio/b_dump.c +++ b/thirdparty/openssl/crypto/bio/b_dump.c diff --git a/drivers/builtin_openssl2/crypto/bio/b_print.c b/thirdparty/openssl/crypto/bio/b_print.c index 90248fa2aa..90248fa2aa 100644 --- a/drivers/builtin_openssl2/crypto/bio/b_print.c +++ b/thirdparty/openssl/crypto/bio/b_print.c diff --git a/drivers/builtin_openssl2/crypto/bio/b_sock.c b/thirdparty/openssl/crypto/bio/b_sock.c index 5bad0a2bad..5bad0a2bad 100644 --- a/drivers/builtin_openssl2/crypto/bio/b_sock.c +++ b/thirdparty/openssl/crypto/bio/b_sock.c diff --git a/drivers/builtin_openssl2/crypto/bio/bf_buff.c b/thirdparty/openssl/crypto/bio/bf_buff.c index 478fa16a07..478fa16a07 100644 --- a/drivers/builtin_openssl2/crypto/bio/bf_buff.c +++ b/thirdparty/openssl/crypto/bio/bf_buff.c diff --git a/drivers/builtin_openssl2/crypto/bio/bf_lbuf.c b/thirdparty/openssl/crypto/bio/bf_lbuf.c index 46d0d5a1e6..46d0d5a1e6 100644 --- a/drivers/builtin_openssl2/crypto/bio/bf_lbuf.c +++ b/thirdparty/openssl/crypto/bio/bf_lbuf.c diff --git a/drivers/builtin_openssl2/crypto/bio/bf_nbio.c b/thirdparty/openssl/crypto/bio/bf_nbio.c index a04f32a008..a04f32a008 100644 --- a/drivers/builtin_openssl2/crypto/bio/bf_nbio.c +++ b/thirdparty/openssl/crypto/bio/bf_nbio.c diff --git a/drivers/builtin_openssl2/crypto/bio/bf_null.c b/thirdparty/openssl/crypto/bio/bf_null.c index e0c79e8291..e0c79e8291 100644 --- a/drivers/builtin_openssl2/crypto/bio/bf_null.c +++ b/thirdparty/openssl/crypto/bio/bf_null.c diff --git a/drivers/builtin_openssl2/crypto/bio/bio_cb.c b/thirdparty/openssl/crypto/bio/bio_cb.c index d3e860686c..d3e860686c 100644 --- a/drivers/builtin_openssl2/crypto/bio/bio_cb.c +++ b/thirdparty/openssl/crypto/bio/bio_cb.c diff --git a/drivers/builtin_openssl2/crypto/bio/bio_err.c b/thirdparty/openssl/crypto/bio/bio_err.c index d9007aa3d3..d9007aa3d3 100644 --- a/drivers/builtin_openssl2/crypto/bio/bio_err.c +++ b/thirdparty/openssl/crypto/bio/bio_err.c diff --git a/drivers/builtin_openssl2/crypto/bio/bio_lcl.h b/thirdparty/openssl/crypto/bio/bio_lcl.h index 741884da84..741884da84 100644 --- a/drivers/builtin_openssl2/crypto/bio/bio_lcl.h +++ b/thirdparty/openssl/crypto/bio/bio_lcl.h diff --git a/drivers/builtin_openssl2/crypto/bio/bio_lib.c b/thirdparty/openssl/crypto/bio/bio_lib.c index 07934f8a66..07934f8a66 100644 --- a/drivers/builtin_openssl2/crypto/bio/bio_lib.c +++ b/thirdparty/openssl/crypto/bio/bio_lib.c diff --git a/drivers/builtin_openssl2/crypto/bio/bss_acpt.c b/thirdparty/openssl/crypto/bio/bss_acpt.c index 4a5e39bd38..4a5e39bd38 100644 --- a/drivers/builtin_openssl2/crypto/bio/bss_acpt.c +++ b/thirdparty/openssl/crypto/bio/bss_acpt.c diff --git a/drivers/builtin_openssl2/crypto/bio/bss_bio.c b/thirdparty/openssl/crypto/bio/bss_bio.c index 4d8727f8f8..4d8727f8f8 100644 --- a/drivers/builtin_openssl2/crypto/bio/bss_bio.c +++ b/thirdparty/openssl/crypto/bio/bss_bio.c diff --git a/drivers/builtin_openssl2/crypto/bio/bss_conn.c b/thirdparty/openssl/crypto/bio/bss_conn.c index 7d15ad29dc..7d15ad29dc 100644 --- a/drivers/builtin_openssl2/crypto/bio/bss_conn.c +++ b/thirdparty/openssl/crypto/bio/bss_conn.c diff --git a/drivers/builtin_openssl2/crypto/bio/bss_dgram.c b/thirdparty/openssl/crypto/bio/bss_dgram.c index bdd7bf88ea..bdd7bf88ea 100644 --- a/drivers/builtin_openssl2/crypto/bio/bss_dgram.c +++ b/thirdparty/openssl/crypto/bio/bss_dgram.c diff --git a/drivers/builtin_openssl2/crypto/bio/bss_fd.c b/thirdparty/openssl/crypto/bio/bss_fd.c index 5f4e34481b..5f4e34481b 100644 --- a/drivers/builtin_openssl2/crypto/bio/bss_fd.c +++ b/thirdparty/openssl/crypto/bio/bss_fd.c diff --git a/drivers/builtin_openssl2/crypto/bio/bss_file.c b/thirdparty/openssl/crypto/bio/bss_file.c index bfba93e62b..bfba93e62b 100644 --- a/drivers/builtin_openssl2/crypto/bio/bss_file.c +++ b/thirdparty/openssl/crypto/bio/bss_file.c diff --git a/drivers/builtin_openssl2/crypto/bio/bss_log.c b/thirdparty/openssl/crypto/bio/bss_log.c index 1283a525b4..1283a525b4 100644 --- a/drivers/builtin_openssl2/crypto/bio/bss_log.c +++ b/thirdparty/openssl/crypto/bio/bss_log.c diff --git a/drivers/builtin_openssl2/crypto/bio/bss_mem.c b/thirdparty/openssl/crypto/bio/bss_mem.c index b0394a960d..b0394a960d 100644 --- a/drivers/builtin_openssl2/crypto/bio/bss_mem.c +++ b/thirdparty/openssl/crypto/bio/bss_mem.c diff --git a/drivers/builtin_openssl2/crypto/bio/bss_null.c b/thirdparty/openssl/crypto/bio/bss_null.c index 6a03fa2465..6a03fa2465 100644 --- a/drivers/builtin_openssl2/crypto/bio/bss_null.c +++ b/thirdparty/openssl/crypto/bio/bss_null.c diff --git a/drivers/builtin_openssl2/crypto/bio/bss_rtcp.c b/thirdparty/openssl/crypto/bio/bss_rtcp.c index 09f14f48dc..09f14f48dc 100644 --- a/drivers/builtin_openssl2/crypto/bio/bss_rtcp.c +++ b/thirdparty/openssl/crypto/bio/bss_rtcp.c diff --git a/drivers/builtin_openssl2/crypto/bio/bss_sock.c b/thirdparty/openssl/crypto/bio/bss_sock.c index 6194d2c031..6194d2c031 100644 --- a/drivers/builtin_openssl2/crypto/bio/bss_sock.c +++ b/thirdparty/openssl/crypto/bio/bss_sock.c diff --git a/drivers/builtin_openssl2/crypto/bn/asm/README b/thirdparty/openssl/crypto/bn/asm/README index b0f3a68a06..b0f3a68a06 100644 --- a/drivers/builtin_openssl2/crypto/bn/asm/README +++ b/thirdparty/openssl/crypto/bn/asm/README diff --git a/drivers/builtin_openssl2/crypto/bn/asm/vms.mar b/thirdparty/openssl/crypto/bn/asm/vms.mar index aefab15cdb..aefab15cdb 100644 --- a/drivers/builtin_openssl2/crypto/bn/asm/vms.mar +++ b/thirdparty/openssl/crypto/bn/asm/vms.mar diff --git a/drivers/builtin_openssl2/crypto/bn/asm/x86/f b/thirdparty/openssl/crypto/bn/asm/x86/f index 22e4112224..22e4112224 100644 --- a/drivers/builtin_openssl2/crypto/bn/asm/x86/f +++ b/thirdparty/openssl/crypto/bn/asm/x86/f diff --git a/drivers/builtin_openssl2/crypto/bn/asm/x86_64-gcc.c b/thirdparty/openssl/crypto/bn/asm/x86_64-gcc.c index d77dc433d4..d77dc433d4 100644 --- a/drivers/builtin_openssl2/crypto/bn/asm/x86_64-gcc.c +++ b/thirdparty/openssl/crypto/bn/asm/x86_64-gcc.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn.mul b/thirdparty/openssl/crypto/bn/bn.mul index 9728870d38..9728870d38 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn.mul +++ b/thirdparty/openssl/crypto/bn/bn.mul diff --git a/drivers/builtin_openssl2/crypto/bn/bn_add.c b/thirdparty/openssl/crypto/bn/bn_add.c index 2f3d110449..2f3d110449 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_add.c +++ b/thirdparty/openssl/crypto/bn/bn_add.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_asm.c b/thirdparty/openssl/crypto/bn/bn_asm.c index 03a33cffe5..03a33cffe5 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_asm.c +++ b/thirdparty/openssl/crypto/bn/bn_asm.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_blind.c b/thirdparty/openssl/crypto/bn/bn_blind.c index d448daa3c7..d448daa3c7 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_blind.c +++ b/thirdparty/openssl/crypto/bn/bn_blind.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_const.c b/thirdparty/openssl/crypto/bn/bn_const.c index 12c3208c24..12c3208c24 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_const.c +++ b/thirdparty/openssl/crypto/bn/bn_const.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_ctx.c b/thirdparty/openssl/crypto/bn/bn_ctx.c index 526c6a046d..526c6a046d 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_ctx.c +++ b/thirdparty/openssl/crypto/bn/bn_ctx.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_depr.c b/thirdparty/openssl/crypto/bn/bn_depr.c index 34895f5982..34895f5982 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_depr.c +++ b/thirdparty/openssl/crypto/bn/bn_depr.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_div.c b/thirdparty/openssl/crypto/bn/bn_div.c index 72e6ce3f74..72e6ce3f74 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_div.c +++ b/thirdparty/openssl/crypto/bn/bn_div.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_err.c b/thirdparty/openssl/crypto/bn/bn_err.c index e7a703826e..e7a703826e 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_err.c +++ b/thirdparty/openssl/crypto/bn/bn_err.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_exp.c b/thirdparty/openssl/crypto/bn/bn_exp.c index 1670f01d1d..1670f01d1d 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_exp.c +++ b/thirdparty/openssl/crypto/bn/bn_exp.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_exp2.c b/thirdparty/openssl/crypto/bn/bn_exp2.c index 43fd2044c0..43fd2044c0 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_exp2.c +++ b/thirdparty/openssl/crypto/bn/bn_exp2.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_gcd.c b/thirdparty/openssl/crypto/bn/bn_gcd.c index ce59fe701f..ce59fe701f 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_gcd.c +++ b/thirdparty/openssl/crypto/bn/bn_gcd.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_gf2m.c b/thirdparty/openssl/crypto/bn/bn_gf2m.c index 2c61da1109..2c61da1109 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_gf2m.c +++ b/thirdparty/openssl/crypto/bn/bn_gf2m.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_kron.c b/thirdparty/openssl/crypto/bn/bn_kron.c index 88d731ac75..88d731ac75 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_kron.c +++ b/thirdparty/openssl/crypto/bn/bn_kron.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_lcl.h b/thirdparty/openssl/crypto/bn/bn_lcl.h index 00f4f09945..00f4f09945 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_lcl.h +++ b/thirdparty/openssl/crypto/bn/bn_lcl.h diff --git a/drivers/builtin_openssl2/crypto/bn/bn_lib.c b/thirdparty/openssl/crypto/bn/bn_lib.c index 80105fff41..80105fff41 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_lib.c +++ b/thirdparty/openssl/crypto/bn/bn_lib.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_mod.c b/thirdparty/openssl/crypto/bn/bn_mod.c index ffbce890cf..ffbce890cf 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_mod.c +++ b/thirdparty/openssl/crypto/bn/bn_mod.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_mont.c b/thirdparty/openssl/crypto/bn/bn_mont.c index be95bd55d0..be95bd55d0 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_mont.c +++ b/thirdparty/openssl/crypto/bn/bn_mont.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_mpi.c b/thirdparty/openssl/crypto/bn/bn_mpi.c index 3bd40bbd2b..3bd40bbd2b 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_mpi.c +++ b/thirdparty/openssl/crypto/bn/bn_mpi.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_mul.c b/thirdparty/openssl/crypto/bn/bn_mul.c index b174850b6b..b174850b6b 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_mul.c +++ b/thirdparty/openssl/crypto/bn/bn_mul.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_nist.c b/thirdparty/openssl/crypto/bn/bn_nist.c index 4a45404c6f..4a45404c6f 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_nist.c +++ b/thirdparty/openssl/crypto/bn/bn_nist.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_prime.c b/thirdparty/openssl/crypto/bn/bn_prime.c index 1d256874c9..1d256874c9 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_prime.c +++ b/thirdparty/openssl/crypto/bn/bn_prime.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_prime.h b/thirdparty/openssl/crypto/bn/bn_prime.h index 5cf0de169e..5cf0de169e 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_prime.h +++ b/thirdparty/openssl/crypto/bn/bn_prime.h diff --git a/drivers/builtin_openssl2/crypto/bn/bn_print.c b/thirdparty/openssl/crypto/bn/bn_print.c index bfa31efc56..bfa31efc56 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_print.c +++ b/thirdparty/openssl/crypto/bn/bn_print.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_rand.c b/thirdparty/openssl/crypto/bn/bn_rand.c index f9fb2e9e45..f9fb2e9e45 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_rand.c +++ b/thirdparty/openssl/crypto/bn/bn_rand.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_recp.c b/thirdparty/openssl/crypto/bn/bn_recp.c index f047040efe..f047040efe 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_recp.c +++ b/thirdparty/openssl/crypto/bn/bn_recp.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_shift.c b/thirdparty/openssl/crypto/bn/bn_shift.c index 9673d9a306..9673d9a306 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_shift.c +++ b/thirdparty/openssl/crypto/bn/bn_shift.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_sqr.c b/thirdparty/openssl/crypto/bn/bn_sqr.c index 3ca69879ee..3ca69879ee 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_sqr.c +++ b/thirdparty/openssl/crypto/bn/bn_sqr.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_sqrt.c b/thirdparty/openssl/crypto/bn/bn_sqrt.c index 232af99a21..232af99a21 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_sqrt.c +++ b/thirdparty/openssl/crypto/bn/bn_sqrt.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_word.c b/thirdparty/openssl/crypto/bn/bn_word.c index b031a60b5b..b031a60b5b 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_word.c +++ b/thirdparty/openssl/crypto/bn/bn_word.c diff --git a/drivers/builtin_openssl2/crypto/bn/bn_x931p.c b/thirdparty/openssl/crypto/bn/bn_x931p.c index efa48bdf87..efa48bdf87 100644 --- a/drivers/builtin_openssl2/crypto/bn/bn_x931p.c +++ b/thirdparty/openssl/crypto/bn/bn_x931p.c diff --git a/drivers/builtin_openssl2/crypto/bn/bnspeed.c b/thirdparty/openssl/crypto/bn/bnspeed.c index e387fdfbc2..e387fdfbc2 100644 --- a/drivers/builtin_openssl2/crypto/bn/bnspeed.c +++ b/thirdparty/openssl/crypto/bn/bnspeed.c diff --git a/drivers/builtin_openssl2/crypto/bn/exp.c b/thirdparty/openssl/crypto/bn/exp.c index fbce28c5be..fbce28c5be 100644 --- a/drivers/builtin_openssl2/crypto/bn/exp.c +++ b/thirdparty/openssl/crypto/bn/exp.c diff --git a/drivers/builtin_openssl2/crypto/bn/expspeed.c b/thirdparty/openssl/crypto/bn/expspeed.c index 513a568a48..513a568a48 100644 --- a/drivers/builtin_openssl2/crypto/bn/expspeed.c +++ b/thirdparty/openssl/crypto/bn/expspeed.c diff --git a/drivers/builtin_openssl2/crypto/bn/rsaz_exp.c b/thirdparty/openssl/crypto/bn/rsaz_exp.c index c54c6feb51..c54c6feb51 100644 --- a/drivers/builtin_openssl2/crypto/bn/rsaz_exp.c +++ b/thirdparty/openssl/crypto/bn/rsaz_exp.c diff --git a/drivers/builtin_openssl2/crypto/bn/rsaz_exp.h b/thirdparty/openssl/crypto/bn/rsaz_exp.h index 229e181f67..229e181f67 100644 --- a/drivers/builtin_openssl2/crypto/bn/rsaz_exp.h +++ b/thirdparty/openssl/crypto/bn/rsaz_exp.h diff --git a/drivers/builtin_openssl2/crypto/bn/todo b/thirdparty/openssl/crypto/bn/todo index e47e381aea..e47e381aea 100644 --- a/drivers/builtin_openssl2/crypto/bn/todo +++ b/thirdparty/openssl/crypto/bn/todo diff --git a/drivers/builtin_openssl2/crypto/bn/vms-helper.c b/thirdparty/openssl/crypto/bn/vms-helper.c index f342e90cbf..f342e90cbf 100644 --- a/drivers/builtin_openssl2/crypto/bn/vms-helper.c +++ b/thirdparty/openssl/crypto/bn/vms-helper.c diff --git a/drivers/builtin_openssl2/crypto/buffer/buf_err.c b/thirdparty/openssl/crypto/buffer/buf_err.c index 631eec38d7..631eec38d7 100644 --- a/drivers/builtin_openssl2/crypto/buffer/buf_err.c +++ b/thirdparty/openssl/crypto/buffer/buf_err.c diff --git a/drivers/builtin_openssl2/crypto/buffer/buf_str.c b/thirdparty/openssl/crypto/buffer/buf_str.c index fa0d608e76..fa0d608e76 100644 --- a/drivers/builtin_openssl2/crypto/buffer/buf_str.c +++ b/thirdparty/openssl/crypto/buffer/buf_str.c diff --git a/drivers/builtin_openssl2/crypto/buffer/buffer.c b/thirdparty/openssl/crypto/buffer/buffer.c index eff3e08157..eff3e08157 100644 --- a/drivers/builtin_openssl2/crypto/buffer/buffer.c +++ b/thirdparty/openssl/crypto/buffer/buffer.c diff --git a/drivers/builtin_openssl2/crypto/camellia/camellia.c b/thirdparty/openssl/crypto/camellia/camellia.c index 719fa61cf6..719fa61cf6 100644 --- a/drivers/builtin_openssl2/crypto/camellia/camellia.c +++ b/thirdparty/openssl/crypto/camellia/camellia.c diff --git a/drivers/builtin_openssl2/crypto/camellia/cmll_cbc.c b/thirdparty/openssl/crypto/camellia/cmll_cbc.c index 4017e00d92..4017e00d92 100644 --- a/drivers/builtin_openssl2/crypto/camellia/cmll_cbc.c +++ b/thirdparty/openssl/crypto/camellia/cmll_cbc.c diff --git a/drivers/builtin_openssl2/crypto/camellia/cmll_cfb.c b/thirdparty/openssl/crypto/camellia/cmll_cfb.c index 78f2ae4566..78f2ae4566 100644 --- a/drivers/builtin_openssl2/crypto/camellia/cmll_cfb.c +++ b/thirdparty/openssl/crypto/camellia/cmll_cfb.c diff --git a/drivers/builtin_openssl2/crypto/camellia/cmll_ctr.c b/thirdparty/openssl/crypto/camellia/cmll_ctr.c index 95e26621b7..95e26621b7 100644 --- a/drivers/builtin_openssl2/crypto/camellia/cmll_ctr.c +++ b/thirdparty/openssl/crypto/camellia/cmll_ctr.c diff --git a/drivers/builtin_openssl2/crypto/camellia/cmll_ecb.c b/thirdparty/openssl/crypto/camellia/cmll_ecb.c index b030791b27..b030791b27 100644 --- a/drivers/builtin_openssl2/crypto/camellia/cmll_ecb.c +++ b/thirdparty/openssl/crypto/camellia/cmll_ecb.c diff --git a/drivers/builtin_openssl2/crypto/camellia/cmll_locl.h b/thirdparty/openssl/crypto/camellia/cmll_locl.h index 2bd79b8c4e..2bd79b8c4e 100644 --- a/drivers/builtin_openssl2/crypto/camellia/cmll_locl.h +++ b/thirdparty/openssl/crypto/camellia/cmll_locl.h diff --git a/drivers/builtin_openssl2/crypto/camellia/cmll_misc.c b/thirdparty/openssl/crypto/camellia/cmll_misc.c index 694d2fac8f..694d2fac8f 100644 --- a/drivers/builtin_openssl2/crypto/camellia/cmll_misc.c +++ b/thirdparty/openssl/crypto/camellia/cmll_misc.c diff --git a/drivers/builtin_openssl2/crypto/camellia/cmll_ofb.c b/thirdparty/openssl/crypto/camellia/cmll_ofb.c index 85eb892156..85eb892156 100644 --- a/drivers/builtin_openssl2/crypto/camellia/cmll_ofb.c +++ b/thirdparty/openssl/crypto/camellia/cmll_ofb.c diff --git a/drivers/builtin_openssl2/crypto/camellia/cmll_utl.c b/thirdparty/openssl/crypto/camellia/cmll_utl.c index d5eb6b4d68..d5eb6b4d68 100644 --- a/drivers/builtin_openssl2/crypto/camellia/cmll_utl.c +++ b/thirdparty/openssl/crypto/camellia/cmll_utl.c diff --git a/drivers/builtin_openssl2/crypto/cast/asm/readme b/thirdparty/openssl/crypto/cast/asm/readme index fbcd76289e..fbcd76289e 100644 --- a/drivers/builtin_openssl2/crypto/cast/asm/readme +++ b/thirdparty/openssl/crypto/cast/asm/readme diff --git a/drivers/builtin_openssl2/crypto/cast/c_cfb64.c b/thirdparty/openssl/crypto/cast/c_cfb64.c index f2f16e5d77..f2f16e5d77 100644 --- a/drivers/builtin_openssl2/crypto/cast/c_cfb64.c +++ b/thirdparty/openssl/crypto/cast/c_cfb64.c diff --git a/drivers/builtin_openssl2/crypto/cast/c_ecb.c b/thirdparty/openssl/crypto/cast/c_ecb.c index 4793f28edf..4793f28edf 100644 --- a/drivers/builtin_openssl2/crypto/cast/c_ecb.c +++ b/thirdparty/openssl/crypto/cast/c_ecb.c diff --git a/drivers/builtin_openssl2/crypto/cast/c_enc.c b/thirdparty/openssl/crypto/cast/c_enc.c index 6e1d50f10d..6e1d50f10d 100644 --- a/drivers/builtin_openssl2/crypto/cast/c_enc.c +++ b/thirdparty/openssl/crypto/cast/c_enc.c diff --git a/drivers/builtin_openssl2/crypto/cast/c_ofb64.c b/thirdparty/openssl/crypto/cast/c_ofb64.c index 4e0a7c2e6e..4e0a7c2e6e 100644 --- a/drivers/builtin_openssl2/crypto/cast/c_ofb64.c +++ b/thirdparty/openssl/crypto/cast/c_ofb64.c diff --git a/drivers/builtin_openssl2/crypto/cast/c_skey.c b/thirdparty/openssl/crypto/cast/c_skey.c index bbb6d56099..bbb6d56099 100644 --- a/drivers/builtin_openssl2/crypto/cast/c_skey.c +++ b/thirdparty/openssl/crypto/cast/c_skey.c diff --git a/drivers/builtin_openssl2/crypto/cast/cast_lcl.h b/thirdparty/openssl/crypto/cast/cast_lcl.h index b0f08294e3..b0f08294e3 100644 --- a/drivers/builtin_openssl2/crypto/cast/cast_lcl.h +++ b/thirdparty/openssl/crypto/cast/cast_lcl.h diff --git a/drivers/builtin_openssl2/crypto/cast/cast_s.h b/thirdparty/openssl/crypto/cast/cast_s.h index 380dc81aef..380dc81aef 100644 --- a/drivers/builtin_openssl2/crypto/cast/cast_s.h +++ b/thirdparty/openssl/crypto/cast/cast_s.h diff --git a/drivers/builtin_openssl2/crypto/cast/cast_spd.c b/thirdparty/openssl/crypto/cast/cast_spd.c index 91d2ce23f7..91d2ce23f7 100644 --- a/drivers/builtin_openssl2/crypto/cast/cast_spd.c +++ b/thirdparty/openssl/crypto/cast/cast_spd.c diff --git a/drivers/builtin_openssl2/crypto/cast/castopts.c b/thirdparty/openssl/crypto/cast/castopts.c index 42687f2884..42687f2884 100644 --- a/drivers/builtin_openssl2/crypto/cast/castopts.c +++ b/thirdparty/openssl/crypto/cast/castopts.c diff --git a/drivers/builtin_openssl2/crypto/cast/casts.cpp b/thirdparty/openssl/crypto/cast/casts.cpp index 8d7bd468d2..8d7bd468d2 100644 --- a/drivers/builtin_openssl2/crypto/cast/casts.cpp +++ b/thirdparty/openssl/crypto/cast/casts.cpp diff --git a/drivers/builtin_openssl2/crypto/cmac/cm_ameth.c b/thirdparty/openssl/crypto/cmac/cm_ameth.c index bf933e0866..bf933e0866 100644 --- a/drivers/builtin_openssl2/crypto/cmac/cm_ameth.c +++ b/thirdparty/openssl/crypto/cmac/cm_ameth.c diff --git a/drivers/builtin_openssl2/crypto/cmac/cm_pmeth.c b/thirdparty/openssl/crypto/cmac/cm_pmeth.c index a2300df187..a2300df187 100644 --- a/drivers/builtin_openssl2/crypto/cmac/cm_pmeth.c +++ b/thirdparty/openssl/crypto/cmac/cm_pmeth.c diff --git a/drivers/builtin_openssl2/crypto/cmac/cmac.c b/thirdparty/openssl/crypto/cmac/cmac.c index 2954b6eb7d..2954b6eb7d 100644 --- a/drivers/builtin_openssl2/crypto/cmac/cmac.c +++ b/thirdparty/openssl/crypto/cmac/cmac.c diff --git a/drivers/builtin_openssl2/crypto/cms/cms_asn1.c b/thirdparty/openssl/crypto/cms/cms_asn1.c index 81a3407f12..81a3407f12 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_asn1.c +++ b/thirdparty/openssl/crypto/cms/cms_asn1.c diff --git a/drivers/builtin_openssl2/crypto/cms/cms_att.c b/thirdparty/openssl/crypto/cms/cms_att.c index f79a49d518..f79a49d518 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_att.c +++ b/thirdparty/openssl/crypto/cms/cms_att.c diff --git a/drivers/builtin_openssl2/crypto/cms/cms_cd.c b/thirdparty/openssl/crypto/cms/cms_cd.c index aa3238f584..aa3238f584 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_cd.c +++ b/thirdparty/openssl/crypto/cms/cms_cd.c diff --git a/drivers/builtin_openssl2/crypto/cms/cms_dd.c b/thirdparty/openssl/crypto/cms/cms_dd.c index 23e9f2d3a4..23e9f2d3a4 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_dd.c +++ b/thirdparty/openssl/crypto/cms/cms_dd.c diff --git a/drivers/builtin_openssl2/crypto/cms/cms_enc.c b/thirdparty/openssl/crypto/cms/cms_enc.c index b14b4b68b5..b14b4b68b5 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_enc.c +++ b/thirdparty/openssl/crypto/cms/cms_enc.c diff --git a/drivers/builtin_openssl2/crypto/cms/cms_env.c b/thirdparty/openssl/crypto/cms/cms_env.c index 93c06cb00a..93c06cb00a 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_env.c +++ b/thirdparty/openssl/crypto/cms/cms_env.c diff --git a/drivers/builtin_openssl2/crypto/cms/cms_err.c b/thirdparty/openssl/crypto/cms/cms_err.c index 15572ea348..15572ea348 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_err.c +++ b/thirdparty/openssl/crypto/cms/cms_err.c diff --git a/drivers/builtin_openssl2/crypto/cms/cms_ess.c b/thirdparty/openssl/crypto/cms/cms_ess.c index 8631a2eb2b..8631a2eb2b 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_ess.c +++ b/thirdparty/openssl/crypto/cms/cms_ess.c diff --git a/drivers/builtin_openssl2/crypto/cms/cms_io.c b/thirdparty/openssl/crypto/cms/cms_io.c index ec51f8e680..ec51f8e680 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_io.c +++ b/thirdparty/openssl/crypto/cms/cms_io.c diff --git a/drivers/builtin_openssl2/crypto/cms/cms_kari.c b/thirdparty/openssl/crypto/cms/cms_kari.c index 2cfcdb29cd..2cfcdb29cd 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_kari.c +++ b/thirdparty/openssl/crypto/cms/cms_kari.c diff --git a/drivers/builtin_openssl2/crypto/cms/cms_lcl.h b/thirdparty/openssl/crypto/cms/cms_lcl.h index 20f2c25f5a..20f2c25f5a 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_lcl.h +++ b/thirdparty/openssl/crypto/cms/cms_lcl.h diff --git a/drivers/builtin_openssl2/crypto/cms/cms_lib.c b/thirdparty/openssl/crypto/cms/cms_lib.c index d6cb60d02d..d6cb60d02d 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_lib.c +++ b/thirdparty/openssl/crypto/cms/cms_lib.c diff --git a/drivers/builtin_openssl2/crypto/cms/cms_pwri.c b/thirdparty/openssl/crypto/cms/cms_pwri.c index b91c01691f..b91c01691f 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_pwri.c +++ b/thirdparty/openssl/crypto/cms/cms_pwri.c diff --git a/drivers/builtin_openssl2/crypto/cms/cms_sd.c b/thirdparty/openssl/crypto/cms/cms_sd.c index a41aca8e12..a41aca8e12 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_sd.c +++ b/thirdparty/openssl/crypto/cms/cms_sd.c diff --git a/drivers/builtin_openssl2/crypto/cms/cms_smime.c b/thirdparty/openssl/crypto/cms/cms_smime.c index 07e3472e10..07e3472e10 100644 --- a/drivers/builtin_openssl2/crypto/cms/cms_smime.c +++ b/thirdparty/openssl/crypto/cms/cms_smime.c diff --git a/drivers/builtin_openssl2/crypto/comp/c_rle.c b/thirdparty/openssl/crypto/comp/c_rle.c index e9aabbd166..e9aabbd166 100644 --- a/drivers/builtin_openssl2/crypto/comp/c_rle.c +++ b/thirdparty/openssl/crypto/comp/c_rle.c diff --git a/drivers/builtin_openssl2/crypto/comp/c_zlib.c b/thirdparty/openssl/crypto/comp/c_zlib.c index 9c32614d3c..9c32614d3c 100644 --- a/drivers/builtin_openssl2/crypto/comp/c_zlib.c +++ b/thirdparty/openssl/crypto/comp/c_zlib.c diff --git a/drivers/builtin_openssl2/crypto/comp/comp_err.c b/thirdparty/openssl/crypto/comp/comp_err.c index 8ca159b60e..8ca159b60e 100644 --- a/drivers/builtin_openssl2/crypto/comp/comp_err.c +++ b/thirdparty/openssl/crypto/comp/comp_err.c diff --git a/drivers/builtin_openssl2/crypto/comp/comp_lib.c b/thirdparty/openssl/crypto/comp/comp_lib.c index bd4eb7a1ab..bd4eb7a1ab 100644 --- a/drivers/builtin_openssl2/crypto/comp/comp_lib.c +++ b/thirdparty/openssl/crypto/comp/comp_lib.c diff --git a/drivers/builtin_openssl2/crypto/conf/README b/thirdparty/openssl/crypto/conf/README index 96e53b34ed..96e53b34ed 100644 --- a/drivers/builtin_openssl2/crypto/conf/README +++ b/thirdparty/openssl/crypto/conf/README diff --git a/drivers/builtin_openssl2/crypto/conf/cnf_save.c b/thirdparty/openssl/crypto/conf/cnf_save.c index 71c4317428..71c4317428 100644 --- a/drivers/builtin_openssl2/crypto/conf/cnf_save.c +++ b/thirdparty/openssl/crypto/conf/cnf_save.c diff --git a/drivers/builtin_openssl2/crypto/conf/conf_api.c b/thirdparty/openssl/crypto/conf/conf_api.c index 4cf7553376..4cf7553376 100644 --- a/drivers/builtin_openssl2/crypto/conf/conf_api.c +++ b/thirdparty/openssl/crypto/conf/conf_api.c diff --git a/drivers/builtin_openssl2/crypto/conf/conf_def.c b/thirdparty/openssl/crypto/conf/conf_def.c index 68c77cec7d..68c77cec7d 100644 --- a/drivers/builtin_openssl2/crypto/conf/conf_def.c +++ b/thirdparty/openssl/crypto/conf/conf_def.c diff --git a/drivers/builtin_openssl2/crypto/conf/conf_def.h b/thirdparty/openssl/crypto/conf/conf_def.h index 7d897b89f1..7d897b89f1 100644 --- a/drivers/builtin_openssl2/crypto/conf/conf_def.h +++ b/thirdparty/openssl/crypto/conf/conf_def.h diff --git a/drivers/builtin_openssl2/crypto/conf/conf_err.c b/thirdparty/openssl/crypto/conf/conf_err.c index bb5e2fe252..bb5e2fe252 100644 --- a/drivers/builtin_openssl2/crypto/conf/conf_err.c +++ b/thirdparty/openssl/crypto/conf/conf_err.c diff --git a/drivers/builtin_openssl2/crypto/conf/conf_lib.c b/thirdparty/openssl/crypto/conf/conf_lib.c index 5281384807..5281384807 100644 --- a/drivers/builtin_openssl2/crypto/conf/conf_lib.c +++ b/thirdparty/openssl/crypto/conf/conf_lib.c diff --git a/drivers/builtin_openssl2/crypto/conf/conf_mall.c b/thirdparty/openssl/crypto/conf/conf_mall.c index b4dbd662d0..b4dbd662d0 100644 --- a/drivers/builtin_openssl2/crypto/conf/conf_mall.c +++ b/thirdparty/openssl/crypto/conf/conf_mall.c diff --git a/drivers/builtin_openssl2/crypto/conf/conf_mod.c b/thirdparty/openssl/crypto/conf/conf_mod.c index 9acfca4f71..9acfca4f71 100644 --- a/drivers/builtin_openssl2/crypto/conf/conf_mod.c +++ b/thirdparty/openssl/crypto/conf/conf_mod.c diff --git a/drivers/builtin_openssl2/crypto/conf/conf_sap.c b/thirdparty/openssl/crypto/conf/conf_sap.c index c042cf222d..c042cf222d 100644 --- a/drivers/builtin_openssl2/crypto/conf/conf_sap.c +++ b/thirdparty/openssl/crypto/conf/conf_sap.c diff --git a/drivers/builtin_openssl2/crypto/conf/ssleay.cnf b/thirdparty/openssl/crypto/conf/ssleay.cnf index ed33af601e..ed33af601e 100644 --- a/drivers/builtin_openssl2/crypto/conf/ssleay.cnf +++ b/thirdparty/openssl/crypto/conf/ssleay.cnf diff --git a/drivers/builtin_openssl2/crypto/constant_time_locl.h b/thirdparty/openssl/crypto/constant_time_locl.h index c786aea949..c786aea949 100644 --- a/drivers/builtin_openssl2/crypto/constant_time_locl.h +++ b/thirdparty/openssl/crypto/constant_time_locl.h diff --git a/drivers/builtin_openssl2/crypto/cpt_err.c b/thirdparty/openssl/crypto/cpt_err.c index a5138381a0..a5138381a0 100644 --- a/drivers/builtin_openssl2/crypto/cpt_err.c +++ b/thirdparty/openssl/crypto/cpt_err.c diff --git a/drivers/builtin_openssl2/crypto/cryptlib.c b/thirdparty/openssl/crypto/cryptlib.c index 1925428f5e..1925428f5e 100644 --- a/drivers/builtin_openssl2/crypto/cryptlib.c +++ b/thirdparty/openssl/crypto/cryptlib.c diff --git a/drivers/builtin_openssl2/crypto/cryptlib.h b/thirdparty/openssl/crypto/cryptlib.h index fba180a6b2..fba180a6b2 100644 --- a/drivers/builtin_openssl2/crypto/cryptlib.h +++ b/thirdparty/openssl/crypto/cryptlib.h diff --git a/drivers/builtin_openssl2/crypto/crypto-lib.com b/thirdparty/openssl/crypto/crypto-lib.com index 1423cac288..1423cac288 100644 --- a/drivers/builtin_openssl2/crypto/crypto-lib.com +++ b/thirdparty/openssl/crypto/crypto-lib.com diff --git a/drivers/builtin_openssl2/crypto/cversion.c b/thirdparty/openssl/crypto/cversion.c index bfff6995c1..bfff6995c1 100644 --- a/drivers/builtin_openssl2/crypto/cversion.c +++ b/thirdparty/openssl/crypto/cversion.c diff --git a/drivers/builtin_openssl2/crypto/des/COPYRIGHT b/thirdparty/openssl/crypto/des/COPYRIGHT index 5469e1e469..5469e1e469 100644 --- a/drivers/builtin_openssl2/crypto/des/COPYRIGHT +++ b/thirdparty/openssl/crypto/des/COPYRIGHT diff --git a/drivers/builtin_openssl2/crypto/des/DES.pm b/thirdparty/openssl/crypto/des/DES.pm index 6a175b6ca4..6a175b6ca4 100644 --- a/drivers/builtin_openssl2/crypto/des/DES.pm +++ b/thirdparty/openssl/crypto/des/DES.pm diff --git a/drivers/builtin_openssl2/crypto/des/DES.xs b/thirdparty/openssl/crypto/des/DES.xs index b8050b9edf..b8050b9edf 100644 --- a/drivers/builtin_openssl2/crypto/des/DES.xs +++ b/thirdparty/openssl/crypto/des/DES.xs diff --git a/drivers/builtin_openssl2/crypto/des/FILES0 b/thirdparty/openssl/crypto/des/FILES0 index 4c7ea2de7a..4c7ea2de7a 100644 --- a/drivers/builtin_openssl2/crypto/des/FILES0 +++ b/thirdparty/openssl/crypto/des/FILES0 diff --git a/drivers/builtin_openssl2/crypto/des/INSTALL b/thirdparty/openssl/crypto/des/INSTALL index 8aebdfe110..8aebdfe110 100644 --- a/drivers/builtin_openssl2/crypto/des/INSTALL +++ b/thirdparty/openssl/crypto/des/INSTALL diff --git a/drivers/builtin_openssl2/crypto/des/Imakefile b/thirdparty/openssl/crypto/des/Imakefile index 1b9b5629e1..1b9b5629e1 100644 --- a/drivers/builtin_openssl2/crypto/des/Imakefile +++ b/thirdparty/openssl/crypto/des/Imakefile diff --git a/drivers/builtin_openssl2/crypto/des/KERBEROS b/thirdparty/openssl/crypto/des/KERBEROS index f401b10014..f401b10014 100644 --- a/drivers/builtin_openssl2/crypto/des/KERBEROS +++ b/thirdparty/openssl/crypto/des/KERBEROS diff --git a/drivers/builtin_openssl2/crypto/des/README b/thirdparty/openssl/crypto/des/README index 621a5ab467..621a5ab467 100644 --- a/drivers/builtin_openssl2/crypto/des/README +++ b/thirdparty/openssl/crypto/des/README diff --git a/drivers/builtin_openssl2/crypto/des/VERSION b/thirdparty/openssl/crypto/des/VERSION index c7d01542bc..c7d01542bc 100644 --- a/drivers/builtin_openssl2/crypto/des/VERSION +++ b/thirdparty/openssl/crypto/des/VERSION diff --git a/drivers/builtin_openssl2/crypto/des/asm/des_enc.m4 b/thirdparty/openssl/crypto/des/asm/des_enc.m4 index dda08e126d..dda08e126d 100644 --- a/drivers/builtin_openssl2/crypto/des/asm/des_enc.m4 +++ b/thirdparty/openssl/crypto/des/asm/des_enc.m4 diff --git a/drivers/builtin_openssl2/crypto/des/asm/readme b/thirdparty/openssl/crypto/des/asm/readme index 1beafe253b..1beafe253b 100644 --- a/drivers/builtin_openssl2/crypto/des/asm/readme +++ b/thirdparty/openssl/crypto/des/asm/readme diff --git a/drivers/builtin_openssl2/crypto/des/cbc3_enc.c b/thirdparty/openssl/crypto/des/cbc3_enc.c index 249518a6a6..249518a6a6 100644 --- a/drivers/builtin_openssl2/crypto/des/cbc3_enc.c +++ b/thirdparty/openssl/crypto/des/cbc3_enc.c diff --git a/drivers/builtin_openssl2/crypto/des/cbc_cksm.c b/thirdparty/openssl/crypto/des/cbc_cksm.c index f89b5b98e4..f89b5b98e4 100644 --- a/drivers/builtin_openssl2/crypto/des/cbc_cksm.c +++ b/thirdparty/openssl/crypto/des/cbc_cksm.c diff --git a/drivers/builtin_openssl2/crypto/des/cbc_enc.c b/thirdparty/openssl/crypto/des/cbc_enc.c index 7ee359928c..7ee359928c 100644 --- a/drivers/builtin_openssl2/crypto/des/cbc_enc.c +++ b/thirdparty/openssl/crypto/des/cbc_enc.c diff --git a/drivers/builtin_openssl2/crypto/des/cfb64ede.c b/thirdparty/openssl/crypto/des/cfb64ede.c index 5d709c12d3..5d709c12d3 100644 --- a/drivers/builtin_openssl2/crypto/des/cfb64ede.c +++ b/thirdparty/openssl/crypto/des/cfb64ede.c diff --git a/drivers/builtin_openssl2/crypto/des/cfb64enc.c b/thirdparty/openssl/crypto/des/cfb64enc.c index 7346774eb2..7346774eb2 100644 --- a/drivers/builtin_openssl2/crypto/des/cfb64enc.c +++ b/thirdparty/openssl/crypto/des/cfb64enc.c diff --git a/drivers/builtin_openssl2/crypto/des/cfb_enc.c b/thirdparty/openssl/crypto/des/cfb_enc.c index bd0e299716..bd0e299716 100644 --- a/drivers/builtin_openssl2/crypto/des/cfb_enc.c +++ b/thirdparty/openssl/crypto/des/cfb_enc.c diff --git a/drivers/builtin_openssl2/crypto/des/des-lib.com b/thirdparty/openssl/crypto/des/des-lib.com index 348f1c0470..348f1c0470 100644 --- a/drivers/builtin_openssl2/crypto/des/des-lib.com +++ b/thirdparty/openssl/crypto/des/des-lib.com diff --git a/drivers/builtin_openssl2/crypto/des/des.c b/thirdparty/openssl/crypto/des/des.c index 586aed7237..586aed7237 100644 --- a/drivers/builtin_openssl2/crypto/des/des.c +++ b/thirdparty/openssl/crypto/des/des.c diff --git a/drivers/builtin_openssl2/crypto/des/des3s.cpp b/thirdparty/openssl/crypto/des/des3s.cpp index 02d527c057..02d527c057 100644 --- a/drivers/builtin_openssl2/crypto/des/des3s.cpp +++ b/thirdparty/openssl/crypto/des/des3s.cpp diff --git a/drivers/builtin_openssl2/crypto/des/des_enc.c b/thirdparty/openssl/crypto/des/des_enc.c index c0b062da3d..c0b062da3d 100644 --- a/drivers/builtin_openssl2/crypto/des/des_enc.c +++ b/thirdparty/openssl/crypto/des/des_enc.c diff --git a/drivers/builtin_openssl2/crypto/des/des_locl.h b/thirdparty/openssl/crypto/des/des_locl.h index 23ea9d32a7..23ea9d32a7 100644 --- a/drivers/builtin_openssl2/crypto/des/des_locl.h +++ b/thirdparty/openssl/crypto/des/des_locl.h diff --git a/drivers/builtin_openssl2/crypto/des/des_old.c b/thirdparty/openssl/crypto/des/des_old.c index c5c5a00f00..c5c5a00f00 100644 --- a/drivers/builtin_openssl2/crypto/des/des_old.c +++ b/thirdparty/openssl/crypto/des/des_old.c diff --git a/drivers/builtin_openssl2/crypto/des/des_old2.c b/thirdparty/openssl/crypto/des/des_old2.c index 247ff8dcf8..247ff8dcf8 100644 --- a/drivers/builtin_openssl2/crypto/des/des_old2.c +++ b/thirdparty/openssl/crypto/des/des_old2.c diff --git a/drivers/builtin_openssl2/crypto/des/des_opts.c b/thirdparty/openssl/crypto/des/des_opts.c index ec50e94f55..ec50e94f55 100644 --- a/drivers/builtin_openssl2/crypto/des/des_opts.c +++ b/thirdparty/openssl/crypto/des/des_opts.c diff --git a/drivers/builtin_openssl2/crypto/des/des_ver.h b/thirdparty/openssl/crypto/des/des_ver.h index 276de2b616..276de2b616 100644 --- a/drivers/builtin_openssl2/crypto/des/des_ver.h +++ b/thirdparty/openssl/crypto/des/des_ver.h diff --git a/drivers/builtin_openssl2/crypto/des/dess.cpp b/thirdparty/openssl/crypto/des/dess.cpp index 5549bab90a..5549bab90a 100644 --- a/drivers/builtin_openssl2/crypto/des/dess.cpp +++ b/thirdparty/openssl/crypto/des/dess.cpp diff --git a/drivers/builtin_openssl2/crypto/des/ecb3_enc.c b/thirdparty/openssl/crypto/des/ecb3_enc.c index c49fbd41e6..c49fbd41e6 100644 --- a/drivers/builtin_openssl2/crypto/des/ecb3_enc.c +++ b/thirdparty/openssl/crypto/des/ecb3_enc.c diff --git a/drivers/builtin_openssl2/crypto/des/ecb_enc.c b/thirdparty/openssl/crypto/des/ecb_enc.c index f97fd971dc..f97fd971dc 100644 --- a/drivers/builtin_openssl2/crypto/des/ecb_enc.c +++ b/thirdparty/openssl/crypto/des/ecb_enc.c diff --git a/drivers/builtin_openssl2/crypto/des/ede_cbcm_enc.c b/thirdparty/openssl/crypto/des/ede_cbcm_enc.c index 86f27d077a..86f27d077a 100644 --- a/drivers/builtin_openssl2/crypto/des/ede_cbcm_enc.c +++ b/thirdparty/openssl/crypto/des/ede_cbcm_enc.c diff --git a/drivers/builtin_openssl2/crypto/des/enc_read.c b/thirdparty/openssl/crypto/des/enc_read.c index fcb66541bd..fcb66541bd 100644 --- a/drivers/builtin_openssl2/crypto/des/enc_read.c +++ b/thirdparty/openssl/crypto/des/enc_read.c diff --git a/drivers/builtin_openssl2/crypto/des/enc_writ.c b/thirdparty/openssl/crypto/des/enc_writ.c index bfaabde516..bfaabde516 100644 --- a/drivers/builtin_openssl2/crypto/des/enc_writ.c +++ b/thirdparty/openssl/crypto/des/enc_writ.c diff --git a/drivers/builtin_openssl2/crypto/des/fcrypt.c b/thirdparty/openssl/crypto/des/fcrypt.c index 111f1e4617..111f1e4617 100644 --- a/drivers/builtin_openssl2/crypto/des/fcrypt.c +++ b/thirdparty/openssl/crypto/des/fcrypt.c diff --git a/drivers/builtin_openssl2/crypto/des/fcrypt_b.c b/thirdparty/openssl/crypto/des/fcrypt_b.c index b9e87383d2..b9e87383d2 100644 --- a/drivers/builtin_openssl2/crypto/des/fcrypt_b.c +++ b/thirdparty/openssl/crypto/des/fcrypt_b.c diff --git a/drivers/builtin_openssl2/crypto/des/makefile.bc b/thirdparty/openssl/crypto/des/makefile.bc index 1fe6d4915a..1fe6d4915a 100644 --- a/drivers/builtin_openssl2/crypto/des/makefile.bc +++ b/thirdparty/openssl/crypto/des/makefile.bc diff --git a/drivers/builtin_openssl2/crypto/des/ncbc_enc.c b/thirdparty/openssl/crypto/des/ncbc_enc.c index ab267cbf38..ab267cbf38 100644 --- a/drivers/builtin_openssl2/crypto/des/ncbc_enc.c +++ b/thirdparty/openssl/crypto/des/ncbc_enc.c diff --git a/drivers/builtin_openssl2/crypto/des/ofb64ede.c b/thirdparty/openssl/crypto/des/ofb64ede.c index 45c67505a6..45c67505a6 100644 --- a/drivers/builtin_openssl2/crypto/des/ofb64ede.c +++ b/thirdparty/openssl/crypto/des/ofb64ede.c diff --git a/drivers/builtin_openssl2/crypto/des/ofb64enc.c b/thirdparty/openssl/crypto/des/ofb64enc.c index 8e72dece51..8e72dece51 100644 --- a/drivers/builtin_openssl2/crypto/des/ofb64enc.c +++ b/thirdparty/openssl/crypto/des/ofb64enc.c diff --git a/drivers/builtin_openssl2/crypto/des/ofb_enc.c b/thirdparty/openssl/crypto/des/ofb_enc.c index 02a787752e..02a787752e 100644 --- a/drivers/builtin_openssl2/crypto/des/ofb_enc.c +++ b/thirdparty/openssl/crypto/des/ofb_enc.c diff --git a/drivers/builtin_openssl2/crypto/des/options.txt b/thirdparty/openssl/crypto/des/options.txt index 6e2b50f765..6e2b50f765 100644 --- a/drivers/builtin_openssl2/crypto/des/options.txt +++ b/thirdparty/openssl/crypto/des/options.txt diff --git a/drivers/builtin_openssl2/crypto/des/pcbc_enc.c b/thirdparty/openssl/crypto/des/pcbc_enc.c index 144d5ed88f..144d5ed88f 100644 --- a/drivers/builtin_openssl2/crypto/des/pcbc_enc.c +++ b/thirdparty/openssl/crypto/des/pcbc_enc.c diff --git a/drivers/builtin_openssl2/crypto/des/qud_cksm.c b/thirdparty/openssl/crypto/des/qud_cksm.c index 2a168a5769..2a168a5769 100644 --- a/drivers/builtin_openssl2/crypto/des/qud_cksm.c +++ b/thirdparty/openssl/crypto/des/qud_cksm.c diff --git a/drivers/builtin_openssl2/crypto/des/rand_key.c b/thirdparty/openssl/crypto/des/rand_key.c index b75cc5f9b0..b75cc5f9b0 100644 --- a/drivers/builtin_openssl2/crypto/des/rand_key.c +++ b/thirdparty/openssl/crypto/des/rand_key.c diff --git a/drivers/builtin_openssl2/crypto/des/read2pwd.c b/thirdparty/openssl/crypto/des/read2pwd.c index 01e275f331..01e275f331 100644 --- a/drivers/builtin_openssl2/crypto/des/read2pwd.c +++ b/thirdparty/openssl/crypto/des/read2pwd.c diff --git a/drivers/builtin_openssl2/crypto/des/read_pwd.c b/thirdparty/openssl/crypto/des/read_pwd.c index 514a7063b4..514a7063b4 100644 --- a/drivers/builtin_openssl2/crypto/des/read_pwd.c +++ b/thirdparty/openssl/crypto/des/read_pwd.c diff --git a/drivers/builtin_openssl2/crypto/des/rpc_des.h b/thirdparty/openssl/crypto/des/rpc_des.h index 4db9062d97..4db9062d97 100644 --- a/drivers/builtin_openssl2/crypto/des/rpc_des.h +++ b/thirdparty/openssl/crypto/des/rpc_des.h diff --git a/drivers/builtin_openssl2/crypto/des/rpc_enc.c b/thirdparty/openssl/crypto/des/rpc_enc.c index f5a84c5b05..f5a84c5b05 100644 --- a/drivers/builtin_openssl2/crypto/des/rpc_enc.c +++ b/thirdparty/openssl/crypto/des/rpc_enc.c diff --git a/drivers/builtin_openssl2/crypto/des/rpw.c b/thirdparty/openssl/crypto/des/rpw.c index ab65eacae3..ab65eacae3 100644 --- a/drivers/builtin_openssl2/crypto/des/rpw.c +++ b/thirdparty/openssl/crypto/des/rpw.c diff --git a/drivers/builtin_openssl2/crypto/des/set_key.c b/thirdparty/openssl/crypto/des/set_key.c index 8fd8fe14bb..8fd8fe14bb 100644 --- a/drivers/builtin_openssl2/crypto/des/set_key.c +++ b/thirdparty/openssl/crypto/des/set_key.c diff --git a/drivers/builtin_openssl2/crypto/des/speed.c b/thirdparty/openssl/crypto/des/speed.c index 9a3d929d29..9a3d929d29 100644 --- a/drivers/builtin_openssl2/crypto/des/speed.c +++ b/thirdparty/openssl/crypto/des/speed.c diff --git a/drivers/builtin_openssl2/crypto/des/spr.h b/thirdparty/openssl/crypto/des/spr.h index e85d310052..e85d310052 100644 --- a/drivers/builtin_openssl2/crypto/des/spr.h +++ b/thirdparty/openssl/crypto/des/spr.h diff --git a/drivers/builtin_openssl2/crypto/des/str2key.c b/thirdparty/openssl/crypto/des/str2key.c index 38a478cf43..38a478cf43 100644 --- a/drivers/builtin_openssl2/crypto/des/str2key.c +++ b/thirdparty/openssl/crypto/des/str2key.c diff --git a/drivers/builtin_openssl2/crypto/des/t/test b/thirdparty/openssl/crypto/des/t/test index 97acd0552e..97acd0552e 100644 --- a/drivers/builtin_openssl2/crypto/des/t/test +++ b/thirdparty/openssl/crypto/des/t/test diff --git a/drivers/builtin_openssl2/crypto/des/times/486-50.sol b/thirdparty/openssl/crypto/des/times/486-50.sol index 0de62d6db3..0de62d6db3 100644 --- a/drivers/builtin_openssl2/crypto/des/times/486-50.sol +++ b/thirdparty/openssl/crypto/des/times/486-50.sol diff --git a/drivers/builtin_openssl2/crypto/des/times/586-100.lnx b/thirdparty/openssl/crypto/des/times/586-100.lnx index 4323914a11..4323914a11 100644 --- a/drivers/builtin_openssl2/crypto/des/times/586-100.lnx +++ b/thirdparty/openssl/crypto/des/times/586-100.lnx diff --git a/drivers/builtin_openssl2/crypto/des/times/686-200.fre b/thirdparty/openssl/crypto/des/times/686-200.fre index 7d83f6adee..7d83f6adee 100644 --- a/drivers/builtin_openssl2/crypto/des/times/686-200.fre +++ b/thirdparty/openssl/crypto/des/times/686-200.fre diff --git a/drivers/builtin_openssl2/crypto/des/times/aix.cc b/thirdparty/openssl/crypto/des/times/aix.cc index d96b74e2ce..d96b74e2ce 100644 --- a/drivers/builtin_openssl2/crypto/des/times/aix.cc +++ b/thirdparty/openssl/crypto/des/times/aix.cc diff --git a/drivers/builtin_openssl2/crypto/des/times/alpha.cc b/thirdparty/openssl/crypto/des/times/alpha.cc index 95c17efae7..95c17efae7 100644 --- a/drivers/builtin_openssl2/crypto/des/times/alpha.cc +++ b/thirdparty/openssl/crypto/des/times/alpha.cc diff --git a/drivers/builtin_openssl2/crypto/des/times/hpux.cc b/thirdparty/openssl/crypto/des/times/hpux.cc index 3de856ddac..3de856ddac 100644 --- a/drivers/builtin_openssl2/crypto/des/times/hpux.cc +++ b/thirdparty/openssl/crypto/des/times/hpux.cc diff --git a/drivers/builtin_openssl2/crypto/des/times/sparc.gcc b/thirdparty/openssl/crypto/des/times/sparc.gcc index 8eaa042104..8eaa042104 100644 --- a/drivers/builtin_openssl2/crypto/des/times/sparc.gcc +++ b/thirdparty/openssl/crypto/des/times/sparc.gcc diff --git a/drivers/builtin_openssl2/crypto/des/times/usparc.cc b/thirdparty/openssl/crypto/des/times/usparc.cc index 0864285ef6..0864285ef6 100644 --- a/drivers/builtin_openssl2/crypto/des/times/usparc.cc +++ b/thirdparty/openssl/crypto/des/times/usparc.cc diff --git a/drivers/builtin_openssl2/crypto/des/typemap b/thirdparty/openssl/crypto/des/typemap index a524f53634..a524f53634 100644 --- a/drivers/builtin_openssl2/crypto/des/typemap +++ b/thirdparty/openssl/crypto/des/typemap diff --git a/drivers/builtin_openssl2/crypto/des/xcbc_enc.c b/thirdparty/openssl/crypto/des/xcbc_enc.c index 6fe021be75..6fe021be75 100644 --- a/drivers/builtin_openssl2/crypto/des/xcbc_enc.c +++ b/thirdparty/openssl/crypto/des/xcbc_enc.c diff --git a/drivers/builtin_openssl2/crypto/dh/dh1024.pem b/thirdparty/openssl/crypto/dh/dh1024.pem index 81d43f6a3e..81d43f6a3e 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh1024.pem +++ b/thirdparty/openssl/crypto/dh/dh1024.pem diff --git a/drivers/builtin_openssl2/crypto/dh/dh192.pem b/thirdparty/openssl/crypto/dh/dh192.pem index 521c07271d..521c07271d 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh192.pem +++ b/thirdparty/openssl/crypto/dh/dh192.pem diff --git a/drivers/builtin_openssl2/crypto/dh/dh2048.pem b/thirdparty/openssl/crypto/dh/dh2048.pem index 295460f508..295460f508 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh2048.pem +++ b/thirdparty/openssl/crypto/dh/dh2048.pem diff --git a/drivers/builtin_openssl2/crypto/dh/dh4096.pem b/thirdparty/openssl/crypto/dh/dh4096.pem index 390943a21d..390943a21d 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh4096.pem +++ b/thirdparty/openssl/crypto/dh/dh4096.pem diff --git a/drivers/builtin_openssl2/crypto/dh/dh512.pem b/thirdparty/openssl/crypto/dh/dh512.pem index 0a4d863ebe..0a4d863ebe 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh512.pem +++ b/thirdparty/openssl/crypto/dh/dh512.pem diff --git a/drivers/builtin_openssl2/crypto/dh/dh_ameth.c b/thirdparty/openssl/crypto/dh/dh_ameth.c index ac72468bd1..ac72468bd1 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh_ameth.c +++ b/thirdparty/openssl/crypto/dh/dh_ameth.c diff --git a/drivers/builtin_openssl2/crypto/dh/dh_asn1.c b/thirdparty/openssl/crypto/dh/dh_asn1.c index f470214399..f470214399 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh_asn1.c +++ b/thirdparty/openssl/crypto/dh/dh_asn1.c diff --git a/drivers/builtin_openssl2/crypto/dh/dh_check.c b/thirdparty/openssl/crypto/dh/dh_check.c index 0277041114..0277041114 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh_check.c +++ b/thirdparty/openssl/crypto/dh/dh_check.c diff --git a/drivers/builtin_openssl2/crypto/dh/dh_depr.c b/thirdparty/openssl/crypto/dh/dh_depr.c index b622119930..b622119930 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh_depr.c +++ b/thirdparty/openssl/crypto/dh/dh_depr.c diff --git a/drivers/builtin_openssl2/crypto/dh/dh_err.c b/thirdparty/openssl/crypto/dh/dh_err.c index b890cca817..b890cca817 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh_err.c +++ b/thirdparty/openssl/crypto/dh/dh_err.c diff --git a/drivers/builtin_openssl2/crypto/dh/dh_gen.c b/thirdparty/openssl/crypto/dh/dh_gen.c index 5bedb665f2..5bedb665f2 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh_gen.c +++ b/thirdparty/openssl/crypto/dh/dh_gen.c diff --git a/drivers/builtin_openssl2/crypto/dh/dh_kdf.c b/thirdparty/openssl/crypto/dh/dh_kdf.c index a882cb286e..a882cb286e 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh_kdf.c +++ b/thirdparty/openssl/crypto/dh/dh_kdf.c diff --git a/drivers/builtin_openssl2/crypto/dh/dh_key.c b/thirdparty/openssl/crypto/dh/dh_key.c index 1d80fb2c5f..1d80fb2c5f 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh_key.c +++ b/thirdparty/openssl/crypto/dh/dh_key.c diff --git a/drivers/builtin_openssl2/crypto/dh/dh_lib.c b/thirdparty/openssl/crypto/dh/dh_lib.c index bebc160ed6..bebc160ed6 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh_lib.c +++ b/thirdparty/openssl/crypto/dh/dh_lib.c diff --git a/drivers/builtin_openssl2/crypto/dh/dh_pmeth.c b/thirdparty/openssl/crypto/dh/dh_pmeth.c index b58e3fa86f..b58e3fa86f 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh_pmeth.c +++ b/thirdparty/openssl/crypto/dh/dh_pmeth.c diff --git a/drivers/builtin_openssl2/crypto/dh/dh_prn.c b/thirdparty/openssl/crypto/dh/dh_prn.c index 5d6c3a37e7..5d6c3a37e7 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh_prn.c +++ b/thirdparty/openssl/crypto/dh/dh_prn.c diff --git a/drivers/builtin_openssl2/crypto/dh/dh_rfc5114.c b/thirdparty/openssl/crypto/dh/dh_rfc5114.c index e96e2aa3fc..e96e2aa3fc 100644 --- a/drivers/builtin_openssl2/crypto/dh/dh_rfc5114.c +++ b/thirdparty/openssl/crypto/dh/dh_rfc5114.c diff --git a/drivers/builtin_openssl2/crypto/dh/example b/thirdparty/openssl/crypto/dh/example index 16a33d2910..16a33d2910 100644 --- a/drivers/builtin_openssl2/crypto/dh/example +++ b/thirdparty/openssl/crypto/dh/example diff --git a/drivers/builtin_openssl2/crypto/dh/generate b/thirdparty/openssl/crypto/dh/generate index 5d407231df..5d407231df 100644 --- a/drivers/builtin_openssl2/crypto/dh/generate +++ b/thirdparty/openssl/crypto/dh/generate diff --git a/drivers/builtin_openssl2/crypto/dh/p1024.c b/thirdparty/openssl/crypto/dh/p1024.c index a4b014b6a3..a4b014b6a3 100644 --- a/drivers/builtin_openssl2/crypto/dh/p1024.c +++ b/thirdparty/openssl/crypto/dh/p1024.c diff --git a/drivers/builtin_openssl2/crypto/dh/p192.c b/thirdparty/openssl/crypto/dh/p192.c index 9f49f76835..9f49f76835 100644 --- a/drivers/builtin_openssl2/crypto/dh/p192.c +++ b/thirdparty/openssl/crypto/dh/p192.c diff --git a/drivers/builtin_openssl2/crypto/dh/p512.c b/thirdparty/openssl/crypto/dh/p512.c index 606fa4d6c3..606fa4d6c3 100644 --- a/drivers/builtin_openssl2/crypto/dh/p512.c +++ b/thirdparty/openssl/crypto/dh/p512.c diff --git a/drivers/builtin_openssl2/crypto/dsa/README b/thirdparty/openssl/crypto/dsa/README index 6a7e9c170a..6a7e9c170a 100644 --- a/drivers/builtin_openssl2/crypto/dsa/README +++ b/thirdparty/openssl/crypto/dsa/README diff --git a/drivers/builtin_openssl2/crypto/dsa/dsa_ameth.c b/thirdparty/openssl/crypto/dsa/dsa_ameth.c index cc83d6e6ad..cc83d6e6ad 100644 --- a/drivers/builtin_openssl2/crypto/dsa/dsa_ameth.c +++ b/thirdparty/openssl/crypto/dsa/dsa_ameth.c diff --git a/drivers/builtin_openssl2/crypto/dsa/dsa_asn1.c b/thirdparty/openssl/crypto/dsa/dsa_asn1.c index 3283a2295b..3283a2295b 100644 --- a/drivers/builtin_openssl2/crypto/dsa/dsa_asn1.c +++ b/thirdparty/openssl/crypto/dsa/dsa_asn1.c diff --git a/drivers/builtin_openssl2/crypto/dsa/dsa_depr.c b/thirdparty/openssl/crypto/dsa/dsa_depr.c index 54f88bc440..54f88bc440 100644 --- a/drivers/builtin_openssl2/crypto/dsa/dsa_depr.c +++ b/thirdparty/openssl/crypto/dsa/dsa_depr.c diff --git a/drivers/builtin_openssl2/crypto/dsa/dsa_err.c b/thirdparty/openssl/crypto/dsa/dsa_err.c index f5ddc66b8a..f5ddc66b8a 100644 --- a/drivers/builtin_openssl2/crypto/dsa/dsa_err.c +++ b/thirdparty/openssl/crypto/dsa/dsa_err.c diff --git a/drivers/builtin_openssl2/crypto/dsa/dsa_gen.c b/thirdparty/openssl/crypto/dsa/dsa_gen.c index 15f3bb4f3f..15f3bb4f3f 100644 --- a/drivers/builtin_openssl2/crypto/dsa/dsa_gen.c +++ b/thirdparty/openssl/crypto/dsa/dsa_gen.c diff --git a/drivers/builtin_openssl2/crypto/dsa/dsa_key.c b/thirdparty/openssl/crypto/dsa/dsa_key.c index e8c8d2e6aa..e8c8d2e6aa 100644 --- a/drivers/builtin_openssl2/crypto/dsa/dsa_key.c +++ b/thirdparty/openssl/crypto/dsa/dsa_key.c diff --git a/drivers/builtin_openssl2/crypto/dsa/dsa_lib.c b/thirdparty/openssl/crypto/dsa/dsa_lib.c index eb9d21d9ae..eb9d21d9ae 100644 --- a/drivers/builtin_openssl2/crypto/dsa/dsa_lib.c +++ b/thirdparty/openssl/crypto/dsa/dsa_lib.c diff --git a/drivers/builtin_openssl2/crypto/dsa/dsa_locl.h b/thirdparty/openssl/crypto/dsa/dsa_locl.h index 9c23c3ef90..9c23c3ef90 100644 --- a/drivers/builtin_openssl2/crypto/dsa/dsa_locl.h +++ b/thirdparty/openssl/crypto/dsa/dsa_locl.h diff --git a/drivers/builtin_openssl2/crypto/dsa/dsa_ossl.c b/thirdparty/openssl/crypto/dsa/dsa_ossl.c index efc4f1b6ae..efc4f1b6ae 100644 --- a/drivers/builtin_openssl2/crypto/dsa/dsa_ossl.c +++ b/thirdparty/openssl/crypto/dsa/dsa_ossl.c diff --git a/drivers/builtin_openssl2/crypto/dsa/dsa_pmeth.c b/thirdparty/openssl/crypto/dsa/dsa_pmeth.c index 42b8bb0862..42b8bb0862 100644 --- a/drivers/builtin_openssl2/crypto/dsa/dsa_pmeth.c +++ b/thirdparty/openssl/crypto/dsa/dsa_pmeth.c diff --git a/drivers/builtin_openssl2/crypto/dsa/dsa_prn.c b/thirdparty/openssl/crypto/dsa/dsa_prn.c index ce690dfcf5..ce690dfcf5 100644 --- a/drivers/builtin_openssl2/crypto/dsa/dsa_prn.c +++ b/thirdparty/openssl/crypto/dsa/dsa_prn.c diff --git a/drivers/builtin_openssl2/crypto/dsa/dsa_sign.c b/thirdparty/openssl/crypto/dsa/dsa_sign.c index c2b71d856f..c2b71d856f 100644 --- a/drivers/builtin_openssl2/crypto/dsa/dsa_sign.c +++ b/thirdparty/openssl/crypto/dsa/dsa_sign.c diff --git a/drivers/builtin_openssl2/crypto/dsa/dsa_vrf.c b/thirdparty/openssl/crypto/dsa/dsa_vrf.c index 7dbd0ca279..7dbd0ca279 100644 --- a/drivers/builtin_openssl2/crypto/dsa/dsa_vrf.c +++ b/thirdparty/openssl/crypto/dsa/dsa_vrf.c diff --git a/drivers/builtin_openssl2/crypto/dsa/dsagen.c b/thirdparty/openssl/crypto/dsa/dsagen.c index e7d346b1ec..e7d346b1ec 100644 --- a/drivers/builtin_openssl2/crypto/dsa/dsagen.c +++ b/thirdparty/openssl/crypto/dsa/dsagen.c diff --git a/drivers/builtin_openssl2/crypto/dsa/fips186a.txt b/thirdparty/openssl/crypto/dsa/fips186a.txt index 3a2e0a0d51..3a2e0a0d51 100644 --- a/drivers/builtin_openssl2/crypto/dsa/fips186a.txt +++ b/thirdparty/openssl/crypto/dsa/fips186a.txt diff --git a/drivers/builtin_openssl2/crypto/dso/README b/thirdparty/openssl/crypto/dso/README index d0bc9a89fb..d0bc9a89fb 100644 --- a/drivers/builtin_openssl2/crypto/dso/README +++ b/thirdparty/openssl/crypto/dso/README diff --git a/drivers/builtin_openssl2/crypto/dso/dso_beos.c b/thirdparty/openssl/crypto/dso/dso_beos.c index 68ebcd8a24..68ebcd8a24 100644 --- a/drivers/builtin_openssl2/crypto/dso/dso_beos.c +++ b/thirdparty/openssl/crypto/dso/dso_beos.c diff --git a/drivers/builtin_openssl2/crypto/dso/dso_dl.c b/thirdparty/openssl/crypto/dso/dso_dl.c index ceedf66e88..ceedf66e88 100644 --- a/drivers/builtin_openssl2/crypto/dso/dso_dl.c +++ b/thirdparty/openssl/crypto/dso/dso_dl.c diff --git a/drivers/builtin_openssl2/crypto/dso/dso_dlfcn.c b/thirdparty/openssl/crypto/dso/dso_dlfcn.c index 78df723ffb..78df723ffb 100644 --- a/drivers/builtin_openssl2/crypto/dso/dso_dlfcn.c +++ b/thirdparty/openssl/crypto/dso/dso_dlfcn.c diff --git a/drivers/builtin_openssl2/crypto/dso/dso_err.c b/thirdparty/openssl/crypto/dso/dso_err.c index e143cc01f0..e143cc01f0 100644 --- a/drivers/builtin_openssl2/crypto/dso/dso_err.c +++ b/thirdparty/openssl/crypto/dso/dso_err.c diff --git a/drivers/builtin_openssl2/crypto/dso/dso_lib.c b/thirdparty/openssl/crypto/dso/dso_lib.c index 2beb7c1ba5..2beb7c1ba5 100644 --- a/drivers/builtin_openssl2/crypto/dso/dso_lib.c +++ b/thirdparty/openssl/crypto/dso/dso_lib.c diff --git a/drivers/builtin_openssl2/crypto/dso/dso_null.c b/thirdparty/openssl/crypto/dso/dso_null.c index 20122d1cab..20122d1cab 100644 --- a/drivers/builtin_openssl2/crypto/dso/dso_null.c +++ b/thirdparty/openssl/crypto/dso/dso_null.c diff --git a/drivers/builtin_openssl2/crypto/dso/dso_openssl.c b/thirdparty/openssl/crypto/dso/dso_openssl.c index 087e989e1c..087e989e1c 100644 --- a/drivers/builtin_openssl2/crypto/dso/dso_openssl.c +++ b/thirdparty/openssl/crypto/dso/dso_openssl.c diff --git a/drivers/builtin_openssl2/crypto/dso/dso_vms.c b/thirdparty/openssl/crypto/dso/dso_vms.c index 1efd84b945..1efd84b945 100644 --- a/drivers/builtin_openssl2/crypto/dso/dso_vms.c +++ b/thirdparty/openssl/crypto/dso/dso_vms.c diff --git a/drivers/builtin_openssl2/crypto/dso/dso_win32.c b/thirdparty/openssl/crypto/dso/dso_win32.c index 706e754a3f..706e754a3f 100644 --- a/drivers/builtin_openssl2/crypto/dso/dso_win32.c +++ b/thirdparty/openssl/crypto/dso/dso_win32.c diff --git a/drivers/builtin_openssl2/crypto/ebcdic.c b/thirdparty/openssl/crypto/ebcdic.c index fd6df92b46..fd6df92b46 100644 --- a/drivers/builtin_openssl2/crypto/ebcdic.c +++ b/thirdparty/openssl/crypto/ebcdic.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec2_mult.c b/thirdparty/openssl/crypto/ec/ec2_mult.c index 68cc8771d5..68cc8771d5 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec2_mult.c +++ b/thirdparty/openssl/crypto/ec/ec2_mult.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec2_oct.c b/thirdparty/openssl/crypto/ec/ec2_oct.c index 0d04cc6923..0d04cc6923 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec2_oct.c +++ b/thirdparty/openssl/crypto/ec/ec2_oct.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec2_smpl.c b/thirdparty/openssl/crypto/ec/ec2_smpl.c index 5b27b91fcc..5b27b91fcc 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec2_smpl.c +++ b/thirdparty/openssl/crypto/ec/ec2_smpl.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec_ameth.c b/thirdparty/openssl/crypto/ec/ec_ameth.c index 83e208cfe4..83e208cfe4 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec_ameth.c +++ b/thirdparty/openssl/crypto/ec/ec_ameth.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec_asn1.c b/thirdparty/openssl/crypto/ec/ec_asn1.c index 33abf61f44..33abf61f44 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec_asn1.c +++ b/thirdparty/openssl/crypto/ec/ec_asn1.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec_check.c b/thirdparty/openssl/crypto/ec/ec_check.c index dd6f0ac409..dd6f0ac409 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec_check.c +++ b/thirdparty/openssl/crypto/ec/ec_check.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec_curve.c b/thirdparty/openssl/crypto/ec/ec_curve.c index 6dbe9d8258..6dbe9d8258 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec_curve.c +++ b/thirdparty/openssl/crypto/ec/ec_curve.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec_cvt.c b/thirdparty/openssl/crypto/ec/ec_cvt.c index 5a832ba1cf..5a832ba1cf 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec_cvt.c +++ b/thirdparty/openssl/crypto/ec/ec_cvt.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec_err.c b/thirdparty/openssl/crypto/ec/ec_err.c index 6fe5baafd4..6fe5baafd4 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec_err.c +++ b/thirdparty/openssl/crypto/ec/ec_err.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec_key.c b/thirdparty/openssl/crypto/ec/ec_key.c index bc94ab5661..bc94ab5661 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec_key.c +++ b/thirdparty/openssl/crypto/ec/ec_key.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec_lcl.h b/thirdparty/openssl/crypto/ec/ec_lcl.h index 969fd147ef..969fd147ef 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec_lcl.h +++ b/thirdparty/openssl/crypto/ec/ec_lcl.h diff --git a/drivers/builtin_openssl2/crypto/ec/ec_lib.c b/thirdparty/openssl/crypto/ec/ec_lib.c index 3ffa112cc3..3ffa112cc3 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec_lib.c +++ b/thirdparty/openssl/crypto/ec/ec_lib.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec_mult.c b/thirdparty/openssl/crypto/ec/ec_mult.c index 23b8c3089b..23b8c3089b 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec_mult.c +++ b/thirdparty/openssl/crypto/ec/ec_mult.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec_oct.c b/thirdparty/openssl/crypto/ec/ec_oct.c index 040c414a33..040c414a33 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec_oct.c +++ b/thirdparty/openssl/crypto/ec/ec_oct.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec_pmeth.c b/thirdparty/openssl/crypto/ec/ec_pmeth.c index b76749010c..b76749010c 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec_pmeth.c +++ b/thirdparty/openssl/crypto/ec/ec_pmeth.c diff --git a/drivers/builtin_openssl2/crypto/ec/ec_print.c b/thirdparty/openssl/crypto/ec/ec_print.c index 96b294d877..96b294d877 100644 --- a/drivers/builtin_openssl2/crypto/ec/ec_print.c +++ b/thirdparty/openssl/crypto/ec/ec_print.c diff --git a/drivers/builtin_openssl2/crypto/ec/eck_prn.c b/thirdparty/openssl/crypto/ec/eck_prn.c index df9b37a750..df9b37a750 100644 --- a/drivers/builtin_openssl2/crypto/ec/eck_prn.c +++ b/thirdparty/openssl/crypto/ec/eck_prn.c diff --git a/drivers/builtin_openssl2/crypto/ec/ecp_mont.c b/thirdparty/openssl/crypto/ec/ecp_mont.c index b2de7faea7..b2de7faea7 100644 --- a/drivers/builtin_openssl2/crypto/ec/ecp_mont.c +++ b/thirdparty/openssl/crypto/ec/ecp_mont.c diff --git a/drivers/builtin_openssl2/crypto/ec/ecp_nist.c b/thirdparty/openssl/crypto/ec/ecp_nist.c index 3944e24935..3944e24935 100644 --- a/drivers/builtin_openssl2/crypto/ec/ecp_nist.c +++ b/thirdparty/openssl/crypto/ec/ecp_nist.c diff --git a/drivers/builtin_openssl2/crypto/ec/ecp_nistp224.c b/thirdparty/openssl/crypto/ec/ecp_nistp224.c index d81cc9ce6b..d81cc9ce6b 100644 --- a/drivers/builtin_openssl2/crypto/ec/ecp_nistp224.c +++ b/thirdparty/openssl/crypto/ec/ecp_nistp224.c diff --git a/drivers/builtin_openssl2/crypto/ec/ecp_nistp256.c b/thirdparty/openssl/crypto/ec/ecp_nistp256.c index 78d191aac7..78d191aac7 100644 --- a/drivers/builtin_openssl2/crypto/ec/ecp_nistp256.c +++ b/thirdparty/openssl/crypto/ec/ecp_nistp256.c diff --git a/drivers/builtin_openssl2/crypto/ec/ecp_nistp521.c b/thirdparty/openssl/crypto/ec/ecp_nistp521.c index c53a61bbfb..c53a61bbfb 100644 --- a/drivers/builtin_openssl2/crypto/ec/ecp_nistp521.c +++ b/thirdparty/openssl/crypto/ec/ecp_nistp521.c diff --git a/drivers/builtin_openssl2/crypto/ec/ecp_nistputil.c b/thirdparty/openssl/crypto/ec/ecp_nistputil.c index 8ba2a25e93..8ba2a25e93 100644 --- a/drivers/builtin_openssl2/crypto/ec/ecp_nistputil.c +++ b/thirdparty/openssl/crypto/ec/ecp_nistputil.c diff --git a/drivers/builtin_openssl2/crypto/ec/ecp_nistz256.c b/thirdparty/openssl/crypto/ec/ecp_nistz256.c index ca44d0aaee..ca44d0aaee 100644 --- a/drivers/builtin_openssl2/crypto/ec/ecp_nistz256.c +++ b/thirdparty/openssl/crypto/ec/ecp_nistz256.c diff --git a/drivers/builtin_openssl2/crypto/ec/ecp_nistz256_table.c b/thirdparty/openssl/crypto/ec/ecp_nistz256_table.c index 2f0797db6b..2f0797db6b 100644 --- a/drivers/builtin_openssl2/crypto/ec/ecp_nistz256_table.c +++ b/thirdparty/openssl/crypto/ec/ecp_nistz256_table.c diff --git a/drivers/builtin_openssl2/crypto/ec/ecp_oct.c b/thirdparty/openssl/crypto/ec/ecp_oct.c index 1bc3f39ad1..1bc3f39ad1 100644 --- a/drivers/builtin_openssl2/crypto/ec/ecp_oct.c +++ b/thirdparty/openssl/crypto/ec/ecp_oct.c diff --git a/drivers/builtin_openssl2/crypto/ec/ecp_smpl.c b/thirdparty/openssl/crypto/ec/ecp_smpl.c index 2b848216d7..2b848216d7 100644 --- a/drivers/builtin_openssl2/crypto/ec/ecp_smpl.c +++ b/thirdparty/openssl/crypto/ec/ecp_smpl.c diff --git a/drivers/builtin_openssl2/crypto/ecdh/ech_err.c b/thirdparty/openssl/crypto/ecdh/ech_err.c index af9f625b41..af9f625b41 100644 --- a/drivers/builtin_openssl2/crypto/ecdh/ech_err.c +++ b/thirdparty/openssl/crypto/ecdh/ech_err.c diff --git a/drivers/builtin_openssl2/crypto/ecdh/ech_kdf.c b/thirdparty/openssl/crypto/ecdh/ech_kdf.c index ac722ac9ee..ac722ac9ee 100644 --- a/drivers/builtin_openssl2/crypto/ecdh/ech_kdf.c +++ b/thirdparty/openssl/crypto/ecdh/ech_kdf.c diff --git a/drivers/builtin_openssl2/crypto/ecdh/ech_key.c b/thirdparty/openssl/crypto/ecdh/ech_key.c index 4f14498962..4f14498962 100644 --- a/drivers/builtin_openssl2/crypto/ecdh/ech_key.c +++ b/thirdparty/openssl/crypto/ecdh/ech_key.c diff --git a/drivers/builtin_openssl2/crypto/ecdh/ech_lib.c b/thirdparty/openssl/crypto/ecdh/ech_lib.c index cbc21d1a27..cbc21d1a27 100644 --- a/drivers/builtin_openssl2/crypto/ecdh/ech_lib.c +++ b/thirdparty/openssl/crypto/ecdh/ech_lib.c diff --git a/drivers/builtin_openssl2/crypto/ecdh/ech_locl.h b/thirdparty/openssl/crypto/ecdh/ech_locl.h index 4e66024c75..4e66024c75 100644 --- a/drivers/builtin_openssl2/crypto/ecdh/ech_locl.h +++ b/thirdparty/openssl/crypto/ecdh/ech_locl.h diff --git a/drivers/builtin_openssl2/crypto/ecdh/ech_ossl.c b/thirdparty/openssl/crypto/ecdh/ech_ossl.c index df115cc262..df115cc262 100644 --- a/drivers/builtin_openssl2/crypto/ecdh/ech_ossl.c +++ b/thirdparty/openssl/crypto/ecdh/ech_ossl.c diff --git a/drivers/builtin_openssl2/crypto/ecdsa/ecs_asn1.c b/thirdparty/openssl/crypto/ecdsa/ecs_asn1.c index 508b079f25..508b079f25 100644 --- a/drivers/builtin_openssl2/crypto/ecdsa/ecs_asn1.c +++ b/thirdparty/openssl/crypto/ecdsa/ecs_asn1.c diff --git a/drivers/builtin_openssl2/crypto/ecdsa/ecs_err.c b/thirdparty/openssl/crypto/ecdsa/ecs_err.c index f1fa7b55f9..f1fa7b55f9 100644 --- a/drivers/builtin_openssl2/crypto/ecdsa/ecs_err.c +++ b/thirdparty/openssl/crypto/ecdsa/ecs_err.c diff --git a/drivers/builtin_openssl2/crypto/ecdsa/ecs_lib.c b/thirdparty/openssl/crypto/ecdsa/ecs_lib.c index 8dc1dda462..8dc1dda462 100644 --- a/drivers/builtin_openssl2/crypto/ecdsa/ecs_lib.c +++ b/thirdparty/openssl/crypto/ecdsa/ecs_lib.c diff --git a/drivers/builtin_openssl2/crypto/ecdsa/ecs_locl.h b/thirdparty/openssl/crypto/ecdsa/ecs_locl.h index d3a5efc547..d3a5efc547 100644 --- a/drivers/builtin_openssl2/crypto/ecdsa/ecs_locl.h +++ b/thirdparty/openssl/crypto/ecdsa/ecs_locl.h diff --git a/drivers/builtin_openssl2/crypto/ecdsa/ecs_ossl.c b/thirdparty/openssl/crypto/ecdsa/ecs_ossl.c index dd769609be..dd769609be 100644 --- a/drivers/builtin_openssl2/crypto/ecdsa/ecs_ossl.c +++ b/thirdparty/openssl/crypto/ecdsa/ecs_ossl.c diff --git a/drivers/builtin_openssl2/crypto/ecdsa/ecs_sign.c b/thirdparty/openssl/crypto/ecdsa/ecs_sign.c index 28652d455d..28652d455d 100644 --- a/drivers/builtin_openssl2/crypto/ecdsa/ecs_sign.c +++ b/thirdparty/openssl/crypto/ecdsa/ecs_sign.c diff --git a/drivers/builtin_openssl2/crypto/ecdsa/ecs_vrf.c b/thirdparty/openssl/crypto/ecdsa/ecs_vrf.c index e909aeb400..e909aeb400 100644 --- a/drivers/builtin_openssl2/crypto/ecdsa/ecs_vrf.c +++ b/thirdparty/openssl/crypto/ecdsa/ecs_vrf.c diff --git a/drivers/builtin_openssl2/crypto/engine/README b/thirdparty/openssl/crypto/engine/README index 6b69b70f57..6b69b70f57 100644 --- a/drivers/builtin_openssl2/crypto/engine/README +++ b/thirdparty/openssl/crypto/engine/README diff --git a/drivers/builtin_openssl2/crypto/engine/eng_all.c b/thirdparty/openssl/crypto/engine/eng_all.c index 48ad0d26b4..48ad0d26b4 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_all.c +++ b/thirdparty/openssl/crypto/engine/eng_all.c diff --git a/drivers/builtin_openssl2/crypto/engine/eng_cnf.c b/thirdparty/openssl/crypto/engine/eng_cnf.c index f09bec4e9a..f09bec4e9a 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_cnf.c +++ b/thirdparty/openssl/crypto/engine/eng_cnf.c diff --git a/drivers/builtin_openssl2/crypto/engine/eng_cryptodev.c b/thirdparty/openssl/crypto/engine/eng_cryptodev.c index 8fb9c3373d..8fb9c3373d 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_cryptodev.c +++ b/thirdparty/openssl/crypto/engine/eng_cryptodev.c diff --git a/drivers/builtin_openssl2/crypto/engine/eng_ctrl.c b/thirdparty/openssl/crypto/engine/eng_ctrl.c index e6c0dfb011..e6c0dfb011 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_ctrl.c +++ b/thirdparty/openssl/crypto/engine/eng_ctrl.c diff --git a/drivers/builtin_openssl2/crypto/engine/eng_dyn.c b/thirdparty/openssl/crypto/engine/eng_dyn.c index 40f30e9d58..40f30e9d58 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_dyn.c +++ b/thirdparty/openssl/crypto/engine/eng_dyn.c diff --git a/drivers/builtin_openssl2/crypto/engine/eng_err.c b/thirdparty/openssl/crypto/engine/eng_err.c index bcc234852d..bcc234852d 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_err.c +++ b/thirdparty/openssl/crypto/engine/eng_err.c diff --git a/drivers/builtin_openssl2/crypto/engine/eng_fat.c b/thirdparty/openssl/crypto/engine/eng_fat.c index 4279dd94b1..4279dd94b1 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_fat.c +++ b/thirdparty/openssl/crypto/engine/eng_fat.c diff --git a/drivers/builtin_openssl2/crypto/engine/eng_init.c b/thirdparty/openssl/crypto/engine/eng_init.c index 4ea7fe633c..4ea7fe633c 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_init.c +++ b/thirdparty/openssl/crypto/engine/eng_init.c diff --git a/drivers/builtin_openssl2/crypto/engine/eng_int.h b/thirdparty/openssl/crypto/engine/eng_int.h index 46f163b1f5..46f163b1f5 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_int.h +++ b/thirdparty/openssl/crypto/engine/eng_int.h diff --git a/drivers/builtin_openssl2/crypto/engine/eng_lib.c b/thirdparty/openssl/crypto/engine/eng_lib.c index dc2abd28ec..dc2abd28ec 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_lib.c +++ b/thirdparty/openssl/crypto/engine/eng_lib.c diff --git a/drivers/builtin_openssl2/crypto/engine/eng_list.c b/thirdparty/openssl/crypto/engine/eng_list.c index 83c95d56f4..83c95d56f4 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_list.c +++ b/thirdparty/openssl/crypto/engine/eng_list.c diff --git a/drivers/builtin_openssl2/crypto/engine/eng_openssl.c b/thirdparty/openssl/crypto/engine/eng_openssl.c index 34b002950e..34b002950e 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_openssl.c +++ b/thirdparty/openssl/crypto/engine/eng_openssl.c diff --git a/drivers/builtin_openssl2/crypto/engine/eng_pkey.c b/thirdparty/openssl/crypto/engine/eng_pkey.c index 23580d9ec8..23580d9ec8 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_pkey.c +++ b/thirdparty/openssl/crypto/engine/eng_pkey.c diff --git a/drivers/builtin_openssl2/crypto/engine/eng_rdrand.c b/thirdparty/openssl/crypto/engine/eng_rdrand.c index 9316d6fe21..9316d6fe21 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_rdrand.c +++ b/thirdparty/openssl/crypto/engine/eng_rdrand.c diff --git a/drivers/builtin_openssl2/crypto/engine/eng_table.c b/thirdparty/openssl/crypto/engine/eng_table.c index 27d31f70c8..27d31f70c8 100644 --- a/drivers/builtin_openssl2/crypto/engine/eng_table.c +++ b/thirdparty/openssl/crypto/engine/eng_table.c diff --git a/drivers/builtin_openssl2/crypto/engine/tb_asnmth.c b/thirdparty/openssl/crypto/engine/tb_asnmth.c index a1a9b88c43..a1a9b88c43 100644 --- a/drivers/builtin_openssl2/crypto/engine/tb_asnmth.c +++ b/thirdparty/openssl/crypto/engine/tb_asnmth.c diff --git a/drivers/builtin_openssl2/crypto/engine/tb_cipher.c b/thirdparty/openssl/crypto/engine/tb_cipher.c index fcfb2efd8f..fcfb2efd8f 100644 --- a/drivers/builtin_openssl2/crypto/engine/tb_cipher.c +++ b/thirdparty/openssl/crypto/engine/tb_cipher.c diff --git a/drivers/builtin_openssl2/crypto/engine/tb_dh.c b/thirdparty/openssl/crypto/engine/tb_dh.c index 8114afa63a..8114afa63a 100644 --- a/drivers/builtin_openssl2/crypto/engine/tb_dh.c +++ b/thirdparty/openssl/crypto/engine/tb_dh.c diff --git a/drivers/builtin_openssl2/crypto/engine/tb_digest.c b/thirdparty/openssl/crypto/engine/tb_digest.c index de1ad9c01b..de1ad9c01b 100644 --- a/drivers/builtin_openssl2/crypto/engine/tb_digest.c +++ b/thirdparty/openssl/crypto/engine/tb_digest.c diff --git a/drivers/builtin_openssl2/crypto/engine/tb_dsa.c b/thirdparty/openssl/crypto/engine/tb_dsa.c index c1f57f146c..c1f57f146c 100644 --- a/drivers/builtin_openssl2/crypto/engine/tb_dsa.c +++ b/thirdparty/openssl/crypto/engine/tb_dsa.c diff --git a/drivers/builtin_openssl2/crypto/engine/tb_ecdh.c b/thirdparty/openssl/crypto/engine/tb_ecdh.c index c51441be8a..c51441be8a 100644 --- a/drivers/builtin_openssl2/crypto/engine/tb_ecdh.c +++ b/thirdparty/openssl/crypto/engine/tb_ecdh.c diff --git a/drivers/builtin_openssl2/crypto/engine/tb_ecdsa.c b/thirdparty/openssl/crypto/engine/tb_ecdsa.c index a8b9be60d7..a8b9be60d7 100644 --- a/drivers/builtin_openssl2/crypto/engine/tb_ecdsa.c +++ b/thirdparty/openssl/crypto/engine/tb_ecdsa.c diff --git a/drivers/builtin_openssl2/crypto/engine/tb_pkmeth.c b/thirdparty/openssl/crypto/engine/tb_pkmeth.c index 29e65be1ad..29e65be1ad 100644 --- a/drivers/builtin_openssl2/crypto/engine/tb_pkmeth.c +++ b/thirdparty/openssl/crypto/engine/tb_pkmeth.c diff --git a/drivers/builtin_openssl2/crypto/engine/tb_rand.c b/thirdparty/openssl/crypto/engine/tb_rand.c index a522264d04..a522264d04 100644 --- a/drivers/builtin_openssl2/crypto/engine/tb_rand.c +++ b/thirdparty/openssl/crypto/engine/tb_rand.c diff --git a/drivers/builtin_openssl2/crypto/engine/tb_rsa.c b/thirdparty/openssl/crypto/engine/tb_rsa.c index 2790a82192..2790a82192 100644 --- a/drivers/builtin_openssl2/crypto/engine/tb_rsa.c +++ b/thirdparty/openssl/crypto/engine/tb_rsa.c diff --git a/drivers/builtin_openssl2/crypto/engine/tb_store.c b/thirdparty/openssl/crypto/engine/tb_store.c index 1eab49d745..1eab49d745 100644 --- a/drivers/builtin_openssl2/crypto/engine/tb_store.c +++ b/thirdparty/openssl/crypto/engine/tb_store.c diff --git a/drivers/builtin_openssl2/crypto/err/err.c b/thirdparty/openssl/crypto/err/err.c index e77d963b6b..e77d963b6b 100644 --- a/drivers/builtin_openssl2/crypto/err/err.c +++ b/thirdparty/openssl/crypto/err/err.c diff --git a/drivers/builtin_openssl2/crypto/err/err_all.c b/thirdparty/openssl/crypto/err/err_all.c index d7575a7ef8..d7575a7ef8 100644 --- a/drivers/builtin_openssl2/crypto/err/err_all.c +++ b/thirdparty/openssl/crypto/err/err_all.c diff --git a/drivers/builtin_openssl2/crypto/err/err_prn.c b/thirdparty/openssl/crypto/err/err_prn.c index 6e352effe3..6e352effe3 100644 --- a/drivers/builtin_openssl2/crypto/err/err_prn.c +++ b/thirdparty/openssl/crypto/err/err_prn.c diff --git a/drivers/builtin_openssl2/crypto/err/openssl.ec b/thirdparty/openssl/crypto/err/openssl.ec index 139afe3234..139afe3234 100644 --- a/drivers/builtin_openssl2/crypto/err/openssl.ec +++ b/thirdparty/openssl/crypto/err/openssl.ec diff --git a/drivers/builtin_openssl2/crypto/evp/bio_b64.c b/thirdparty/openssl/crypto/evp/bio_b64.c index 538b520264..538b520264 100644 --- a/drivers/builtin_openssl2/crypto/evp/bio_b64.c +++ b/thirdparty/openssl/crypto/evp/bio_b64.c diff --git a/drivers/builtin_openssl2/crypto/evp/bio_enc.c b/thirdparty/openssl/crypto/evp/bio_enc.c index 363e0246ae..363e0246ae 100644 --- a/drivers/builtin_openssl2/crypto/evp/bio_enc.c +++ b/thirdparty/openssl/crypto/evp/bio_enc.c diff --git a/drivers/builtin_openssl2/crypto/evp/bio_md.c b/thirdparty/openssl/crypto/evp/bio_md.c index f0b0c0c0a7..f0b0c0c0a7 100644 --- a/drivers/builtin_openssl2/crypto/evp/bio_md.c +++ b/thirdparty/openssl/crypto/evp/bio_md.c diff --git a/drivers/builtin_openssl2/crypto/evp/bio_ok.c b/thirdparty/openssl/crypto/evp/bio_ok.c index 5c32e35e17..5c32e35e17 100644 --- a/drivers/builtin_openssl2/crypto/evp/bio_ok.c +++ b/thirdparty/openssl/crypto/evp/bio_ok.c diff --git a/drivers/builtin_openssl2/crypto/evp/c_all.c b/thirdparty/openssl/crypto/evp/c_all.c index a3ed00d4c1..a3ed00d4c1 100644 --- a/drivers/builtin_openssl2/crypto/evp/c_all.c +++ b/thirdparty/openssl/crypto/evp/c_all.c diff --git a/drivers/builtin_openssl2/crypto/evp/c_allc.c b/thirdparty/openssl/crypto/evp/c_allc.c index 280e58408f..280e58408f 100644 --- a/drivers/builtin_openssl2/crypto/evp/c_allc.c +++ b/thirdparty/openssl/crypto/evp/c_allc.c diff --git a/drivers/builtin_openssl2/crypto/evp/c_alld.c b/thirdparty/openssl/crypto/evp/c_alld.c index fdbe3ee048..fdbe3ee048 100644 --- a/drivers/builtin_openssl2/crypto/evp/c_alld.c +++ b/thirdparty/openssl/crypto/evp/c_alld.c diff --git a/drivers/builtin_openssl2/crypto/evp/digest.c b/thirdparty/openssl/crypto/evp/digest.c index 5b642b23fc..5b642b23fc 100644 --- a/drivers/builtin_openssl2/crypto/evp/digest.c +++ b/thirdparty/openssl/crypto/evp/digest.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_aes.c b/thirdparty/openssl/crypto/evp/e_aes.c index 1734a823c1..1734a823c1 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_aes.c +++ b/thirdparty/openssl/crypto/evp/e_aes.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_aes_cbc_hmac_sha1.c b/thirdparty/openssl/crypto/evp/e_aes_cbc_hmac_sha1.c index 6dfd590a4a..6dfd590a4a 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_aes_cbc_hmac_sha1.c +++ b/thirdparty/openssl/crypto/evp/e_aes_cbc_hmac_sha1.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_aes_cbc_hmac_sha256.c b/thirdparty/openssl/crypto/evp/e_aes_cbc_hmac_sha256.c index 46c9d03389..46c9d03389 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_aes_cbc_hmac_sha256.c +++ b/thirdparty/openssl/crypto/evp/e_aes_cbc_hmac_sha256.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_bf.c b/thirdparty/openssl/crypto/evp/e_bf.c index d6a017826e..d6a017826e 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_bf.c +++ b/thirdparty/openssl/crypto/evp/e_bf.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_camellia.c b/thirdparty/openssl/crypto/evp/e_camellia.c index f273f9c947..f273f9c947 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_camellia.c +++ b/thirdparty/openssl/crypto/evp/e_camellia.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_cast.c b/thirdparty/openssl/crypto/evp/e_cast.c index 3f74548569..3f74548569 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_cast.c +++ b/thirdparty/openssl/crypto/evp/e_cast.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_des.c b/thirdparty/openssl/crypto/evp/e_des.c index 8ca65cd03a..8ca65cd03a 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_des.c +++ b/thirdparty/openssl/crypto/evp/e_des.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_des3.c b/thirdparty/openssl/crypto/evp/e_des3.c index 0e910d6d80..0e910d6d80 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_des3.c +++ b/thirdparty/openssl/crypto/evp/e_des3.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_dsa.c b/thirdparty/openssl/crypto/evp/e_dsa.c index 523993f4d9..523993f4d9 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_dsa.c +++ b/thirdparty/openssl/crypto/evp/e_dsa.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_idea.c b/thirdparty/openssl/crypto/evp/e_idea.c index cac72b33ba..cac72b33ba 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_idea.c +++ b/thirdparty/openssl/crypto/evp/e_idea.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_null.c b/thirdparty/openssl/crypto/evp/e_null.c index 599fcb808d..599fcb808d 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_null.c +++ b/thirdparty/openssl/crypto/evp/e_null.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_old.c b/thirdparty/openssl/crypto/evp/e_old.c index a23d143b7f..a23d143b7f 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_old.c +++ b/thirdparty/openssl/crypto/evp/e_old.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_rc2.c b/thirdparty/openssl/crypto/evp/e_rc2.c index 718cc8694f..718cc8694f 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_rc2.c +++ b/thirdparty/openssl/crypto/evp/e_rc2.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_rc4.c b/thirdparty/openssl/crypto/evp/e_rc4.c index 08e48f391d..08e48f391d 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_rc4.c +++ b/thirdparty/openssl/crypto/evp/e_rc4.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_rc4_hmac_md5.c b/thirdparty/openssl/crypto/evp/e_rc4_hmac_md5.c index 2da1117829..2da1117829 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_rc4_hmac_md5.c +++ b/thirdparty/openssl/crypto/evp/e_rc4_hmac_md5.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_rc5.c b/thirdparty/openssl/crypto/evp/e_rc5.c index f17e99d0c5..f17e99d0c5 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_rc5.c +++ b/thirdparty/openssl/crypto/evp/e_rc5.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_seed.c b/thirdparty/openssl/crypto/evp/e_seed.c index 7249d1b1ee..7249d1b1ee 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_seed.c +++ b/thirdparty/openssl/crypto/evp/e_seed.c diff --git a/drivers/builtin_openssl2/crypto/evp/e_xcbc_d.c b/thirdparty/openssl/crypto/evp/e_xcbc_d.c index 3430df9e8e..3430df9e8e 100644 --- a/drivers/builtin_openssl2/crypto/evp/e_xcbc_d.c +++ b/thirdparty/openssl/crypto/evp/e_xcbc_d.c diff --git a/drivers/builtin_openssl2/crypto/evp/encode.c b/thirdparty/openssl/crypto/evp/encode.c index c6c775e0a0..c6c775e0a0 100644 --- a/drivers/builtin_openssl2/crypto/evp/encode.c +++ b/thirdparty/openssl/crypto/evp/encode.c diff --git a/drivers/builtin_openssl2/crypto/evp/evp_acnf.c b/thirdparty/openssl/crypto/evp/evp_acnf.c index 9703116e02..9703116e02 100644 --- a/drivers/builtin_openssl2/crypto/evp/evp_acnf.c +++ b/thirdparty/openssl/crypto/evp/evp_acnf.c diff --git a/drivers/builtin_openssl2/crypto/evp/evp_cnf.c b/thirdparty/openssl/crypto/evp/evp_cnf.c index 6fd3a6da0b..6fd3a6da0b 100644 --- a/drivers/builtin_openssl2/crypto/evp/evp_cnf.c +++ b/thirdparty/openssl/crypto/evp/evp_cnf.c diff --git a/drivers/builtin_openssl2/crypto/evp/evp_enc.c b/thirdparty/openssl/crypto/evp/evp_enc.c index 7d7be245b0..7d7be245b0 100644 --- a/drivers/builtin_openssl2/crypto/evp/evp_enc.c +++ b/thirdparty/openssl/crypto/evp/evp_enc.c diff --git a/drivers/builtin_openssl2/crypto/evp/evp_err.c b/thirdparty/openssl/crypto/evp/evp_err.c index 15cf5532b3..15cf5532b3 100644 --- a/drivers/builtin_openssl2/crypto/evp/evp_err.c +++ b/thirdparty/openssl/crypto/evp/evp_err.c diff --git a/drivers/builtin_openssl2/crypto/evp/evp_key.c b/thirdparty/openssl/crypto/evp/evp_key.c index 5be9e336f9..5be9e336f9 100644 --- a/drivers/builtin_openssl2/crypto/evp/evp_key.c +++ b/thirdparty/openssl/crypto/evp/evp_key.c diff --git a/drivers/builtin_openssl2/crypto/evp/evp_lib.c b/thirdparty/openssl/crypto/evp/evp_lib.c index 7e0bab90d4..7e0bab90d4 100644 --- a/drivers/builtin_openssl2/crypto/evp/evp_lib.c +++ b/thirdparty/openssl/crypto/evp/evp_lib.c diff --git a/drivers/builtin_openssl2/crypto/evp/evp_locl.h b/thirdparty/openssl/crypto/evp/evp_locl.h index 2bb709a065..2bb709a065 100644 --- a/drivers/builtin_openssl2/crypto/evp/evp_locl.h +++ b/thirdparty/openssl/crypto/evp/evp_locl.h diff --git a/drivers/builtin_openssl2/crypto/evp/evp_pbe.c b/thirdparty/openssl/crypto/evp/evp_pbe.c index 7934c95fad..7934c95fad 100644 --- a/drivers/builtin_openssl2/crypto/evp/evp_pbe.c +++ b/thirdparty/openssl/crypto/evp/evp_pbe.c diff --git a/drivers/builtin_openssl2/crypto/evp/evp_pkey.c b/thirdparty/openssl/crypto/evp/evp_pkey.c index 6a456297bc..6a456297bc 100644 --- a/drivers/builtin_openssl2/crypto/evp/evp_pkey.c +++ b/thirdparty/openssl/crypto/evp/evp_pkey.c diff --git a/drivers/builtin_openssl2/crypto/evp/evptests.txt b/thirdparty/openssl/crypto/evp/evptests.txt index 4e9958b3b5..4e9958b3b5 100644 --- a/drivers/builtin_openssl2/crypto/evp/evptests.txt +++ b/thirdparty/openssl/crypto/evp/evptests.txt diff --git a/drivers/builtin_openssl2/crypto/evp/m_dss.c b/thirdparty/openssl/crypto/evp/m_dss.c index 147844862d..147844862d 100644 --- a/drivers/builtin_openssl2/crypto/evp/m_dss.c +++ b/thirdparty/openssl/crypto/evp/m_dss.c diff --git a/drivers/builtin_openssl2/crypto/evp/m_dss1.c b/thirdparty/openssl/crypto/evp/m_dss1.c index e36fabff70..e36fabff70 100644 --- a/drivers/builtin_openssl2/crypto/evp/m_dss1.c +++ b/thirdparty/openssl/crypto/evp/m_dss1.c diff --git a/drivers/builtin_openssl2/crypto/evp/m_ecdsa.c b/thirdparty/openssl/crypto/evp/m_ecdsa.c index 803d314955..803d314955 100644 --- a/drivers/builtin_openssl2/crypto/evp/m_ecdsa.c +++ b/thirdparty/openssl/crypto/evp/m_ecdsa.c diff --git a/drivers/builtin_openssl2/crypto/evp/m_md2.c b/thirdparty/openssl/crypto/evp/m_md2.c index 3c4cd7bf88..3c4cd7bf88 100644 --- a/drivers/builtin_openssl2/crypto/evp/m_md2.c +++ b/thirdparty/openssl/crypto/evp/m_md2.c diff --git a/drivers/builtin_openssl2/crypto/evp/m_md4.c b/thirdparty/openssl/crypto/evp/m_md4.c index 851de69f88..851de69f88 100644 --- a/drivers/builtin_openssl2/crypto/evp/m_md4.c +++ b/thirdparty/openssl/crypto/evp/m_md4.c diff --git a/drivers/builtin_openssl2/crypto/evp/m_md5.c b/thirdparty/openssl/crypto/evp/m_md5.c index e5d5f71b87..e5d5f71b87 100644 --- a/drivers/builtin_openssl2/crypto/evp/m_md5.c +++ b/thirdparty/openssl/crypto/evp/m_md5.c diff --git a/drivers/builtin_openssl2/crypto/evp/m_mdc2.c b/thirdparty/openssl/crypto/evp/m_mdc2.c index 94e12a6bd5..94e12a6bd5 100644 --- a/drivers/builtin_openssl2/crypto/evp/m_mdc2.c +++ b/thirdparty/openssl/crypto/evp/m_mdc2.c diff --git a/drivers/builtin_openssl2/crypto/evp/m_null.c b/thirdparty/openssl/crypto/evp/m_null.c index 017e1feb0b..017e1feb0b 100644 --- a/drivers/builtin_openssl2/crypto/evp/m_null.c +++ b/thirdparty/openssl/crypto/evp/m_null.c diff --git a/drivers/builtin_openssl2/crypto/evp/m_ripemd.c b/thirdparty/openssl/crypto/evp/m_ripemd.c index 81de0ef4e1..81de0ef4e1 100644 --- a/drivers/builtin_openssl2/crypto/evp/m_ripemd.c +++ b/thirdparty/openssl/crypto/evp/m_ripemd.c diff --git a/drivers/builtin_openssl2/crypto/evp/m_sha.c b/thirdparty/openssl/crypto/evp/m_sha.c index e1e22e0c19..e1e22e0c19 100644 --- a/drivers/builtin_openssl2/crypto/evp/m_sha.c +++ b/thirdparty/openssl/crypto/evp/m_sha.c diff --git a/drivers/builtin_openssl2/crypto/evp/m_sha1.c b/thirdparty/openssl/crypto/evp/m_sha1.c index a74e6b7794..a74e6b7794 100644 --- a/drivers/builtin_openssl2/crypto/evp/m_sha1.c +++ b/thirdparty/openssl/crypto/evp/m_sha1.c diff --git a/drivers/builtin_openssl2/crypto/evp/m_sigver.c b/thirdparty/openssl/crypto/evp/m_sigver.c index 4492d207f2..4492d207f2 100644 --- a/drivers/builtin_openssl2/crypto/evp/m_sigver.c +++ b/thirdparty/openssl/crypto/evp/m_sigver.c diff --git a/drivers/builtin_openssl2/crypto/evp/m_wp.c b/thirdparty/openssl/crypto/evp/m_wp.c index a890939ec4..a890939ec4 100644 --- a/drivers/builtin_openssl2/crypto/evp/m_wp.c +++ b/thirdparty/openssl/crypto/evp/m_wp.c diff --git a/drivers/builtin_openssl2/crypto/evp/names.c b/thirdparty/openssl/crypto/evp/names.c index ff115a31c8..ff115a31c8 100644 --- a/drivers/builtin_openssl2/crypto/evp/names.c +++ b/thirdparty/openssl/crypto/evp/names.c diff --git a/drivers/builtin_openssl2/crypto/evp/openbsd_hw.c b/thirdparty/openssl/crypto/evp/openbsd_hw.c index 75d12e2330..75d12e2330 100644 --- a/drivers/builtin_openssl2/crypto/evp/openbsd_hw.c +++ b/thirdparty/openssl/crypto/evp/openbsd_hw.c diff --git a/drivers/builtin_openssl2/crypto/evp/p5_crpt.c b/thirdparty/openssl/crypto/evp/p5_crpt.c index d06ab90a3e..d06ab90a3e 100644 --- a/drivers/builtin_openssl2/crypto/evp/p5_crpt.c +++ b/thirdparty/openssl/crypto/evp/p5_crpt.c diff --git a/drivers/builtin_openssl2/crypto/evp/p5_crpt2.c b/thirdparty/openssl/crypto/evp/p5_crpt2.c index f2ae1e5790..f2ae1e5790 100644 --- a/drivers/builtin_openssl2/crypto/evp/p5_crpt2.c +++ b/thirdparty/openssl/crypto/evp/p5_crpt2.c diff --git a/drivers/builtin_openssl2/crypto/evp/p_dec.c b/thirdparty/openssl/crypto/evp/p_dec.c index 225b8b45ed..225b8b45ed 100644 --- a/drivers/builtin_openssl2/crypto/evp/p_dec.c +++ b/thirdparty/openssl/crypto/evp/p_dec.c diff --git a/drivers/builtin_openssl2/crypto/evp/p_enc.c b/thirdparty/openssl/crypto/evp/p_enc.c index f565f33fbf..f565f33fbf 100644 --- a/drivers/builtin_openssl2/crypto/evp/p_enc.c +++ b/thirdparty/openssl/crypto/evp/p_enc.c diff --git a/drivers/builtin_openssl2/crypto/evp/p_lib.c b/thirdparty/openssl/crypto/evp/p_lib.c index c0171244d5..c0171244d5 100644 --- a/drivers/builtin_openssl2/crypto/evp/p_lib.c +++ b/thirdparty/openssl/crypto/evp/p_lib.c diff --git a/drivers/builtin_openssl2/crypto/evp/p_open.c b/thirdparty/openssl/crypto/evp/p_open.c index 229eb6417a..229eb6417a 100644 --- a/drivers/builtin_openssl2/crypto/evp/p_open.c +++ b/thirdparty/openssl/crypto/evp/p_open.c diff --git a/drivers/builtin_openssl2/crypto/evp/p_seal.c b/thirdparty/openssl/crypto/evp/p_seal.c index ba9dfff215..ba9dfff215 100644 --- a/drivers/builtin_openssl2/crypto/evp/p_seal.c +++ b/thirdparty/openssl/crypto/evp/p_seal.c diff --git a/drivers/builtin_openssl2/crypto/evp/p_sign.c b/thirdparty/openssl/crypto/evp/p_sign.c index 1b9ba060d4..1b9ba060d4 100644 --- a/drivers/builtin_openssl2/crypto/evp/p_sign.c +++ b/thirdparty/openssl/crypto/evp/p_sign.c diff --git a/drivers/builtin_openssl2/crypto/evp/p_verify.c b/thirdparty/openssl/crypto/evp/p_verify.c index 65e1e21692..65e1e21692 100644 --- a/drivers/builtin_openssl2/crypto/evp/p_verify.c +++ b/thirdparty/openssl/crypto/evp/p_verify.c diff --git a/drivers/builtin_openssl2/crypto/evp/pmeth_fn.c b/thirdparty/openssl/crypto/evp/pmeth_fn.c index a8b7f2f6d5..a8b7f2f6d5 100644 --- a/drivers/builtin_openssl2/crypto/evp/pmeth_fn.c +++ b/thirdparty/openssl/crypto/evp/pmeth_fn.c diff --git a/drivers/builtin_openssl2/crypto/evp/pmeth_gn.c b/thirdparty/openssl/crypto/evp/pmeth_gn.c index 6435f1b632..6435f1b632 100644 --- a/drivers/builtin_openssl2/crypto/evp/pmeth_gn.c +++ b/thirdparty/openssl/crypto/evp/pmeth_gn.c diff --git a/drivers/builtin_openssl2/crypto/evp/pmeth_lib.c b/thirdparty/openssl/crypto/evp/pmeth_lib.c index 9f81d10021..9f81d10021 100644 --- a/drivers/builtin_openssl2/crypto/evp/pmeth_lib.c +++ b/thirdparty/openssl/crypto/evp/pmeth_lib.c diff --git a/drivers/builtin_openssl2/crypto/ex_data.c b/thirdparty/openssl/crypto/ex_data.c index f96a51781a..f96a51781a 100644 --- a/drivers/builtin_openssl2/crypto/ex_data.c +++ b/thirdparty/openssl/crypto/ex_data.c diff --git a/drivers/builtin_openssl2/crypto/fips_err.h b/thirdparty/openssl/crypto/fips_err.h index 0308b63bbc..0308b63bbc 100644 --- a/drivers/builtin_openssl2/crypto/fips_err.h +++ b/thirdparty/openssl/crypto/fips_err.h diff --git a/drivers/builtin_openssl2/crypto/fips_ers.c b/thirdparty/openssl/crypto/fips_ers.c index 1788ed2884..1788ed2884 100644 --- a/drivers/builtin_openssl2/crypto/fips_ers.c +++ b/thirdparty/openssl/crypto/fips_ers.c diff --git a/drivers/builtin_openssl2/crypto/hmac/hm_ameth.c b/thirdparty/openssl/crypto/hmac/hm_ameth.c index 944c6c857b..944c6c857b 100644 --- a/drivers/builtin_openssl2/crypto/hmac/hm_ameth.c +++ b/thirdparty/openssl/crypto/hmac/hm_ameth.c diff --git a/drivers/builtin_openssl2/crypto/hmac/hm_pmeth.c b/thirdparty/openssl/crypto/hmac/hm_pmeth.c index 0ffff79cc4..0ffff79cc4 100644 --- a/drivers/builtin_openssl2/crypto/hmac/hm_pmeth.c +++ b/thirdparty/openssl/crypto/hmac/hm_pmeth.c diff --git a/drivers/builtin_openssl2/crypto/hmac/hmac.c b/thirdparty/openssl/crypto/hmac/hmac.c index 51a0a3efcd..51a0a3efcd 100644 --- a/drivers/builtin_openssl2/crypto/hmac/hmac.c +++ b/thirdparty/openssl/crypto/hmac/hmac.c diff --git a/drivers/builtin_openssl2/crypto/idea/i_cbc.c b/thirdparty/openssl/crypto/idea/i_cbc.c index 950df98c95..950df98c95 100644 --- a/drivers/builtin_openssl2/crypto/idea/i_cbc.c +++ b/thirdparty/openssl/crypto/idea/i_cbc.c diff --git a/drivers/builtin_openssl2/crypto/idea/i_cfb64.c b/thirdparty/openssl/crypto/idea/i_cfb64.c index a1547ed5d7..a1547ed5d7 100644 --- a/drivers/builtin_openssl2/crypto/idea/i_cfb64.c +++ b/thirdparty/openssl/crypto/idea/i_cfb64.c diff --git a/drivers/builtin_openssl2/crypto/idea/i_ecb.c b/thirdparty/openssl/crypto/idea/i_ecb.c index a6b879a927..a6b879a927 100644 --- a/drivers/builtin_openssl2/crypto/idea/i_ecb.c +++ b/thirdparty/openssl/crypto/idea/i_ecb.c diff --git a/drivers/builtin_openssl2/crypto/idea/i_ofb64.c b/thirdparty/openssl/crypto/idea/i_ofb64.c index aa5948801b..aa5948801b 100644 --- a/drivers/builtin_openssl2/crypto/idea/i_ofb64.c +++ b/thirdparty/openssl/crypto/idea/i_ofb64.c diff --git a/drivers/builtin_openssl2/crypto/idea/i_skey.c b/thirdparty/openssl/crypto/idea/i_skey.c index 5365151335..5365151335 100644 --- a/drivers/builtin_openssl2/crypto/idea/i_skey.c +++ b/thirdparty/openssl/crypto/idea/i_skey.c diff --git a/drivers/builtin_openssl2/crypto/idea/idea_lcl.h b/thirdparty/openssl/crypto/idea/idea_lcl.h index e40695384d..e40695384d 100644 --- a/drivers/builtin_openssl2/crypto/idea/idea_lcl.h +++ b/thirdparty/openssl/crypto/idea/idea_lcl.h diff --git a/drivers/builtin_openssl2/crypto/idea/idea_spd.c b/thirdparty/openssl/crypto/idea/idea_spd.c index 59acc407d7..59acc407d7 100644 --- a/drivers/builtin_openssl2/crypto/idea/idea_spd.c +++ b/thirdparty/openssl/crypto/idea/idea_spd.c diff --git a/drivers/builtin_openssl2/crypto/idea/version b/thirdparty/openssl/crypto/idea/version index 3f22293795..3f22293795 100644 --- a/drivers/builtin_openssl2/crypto/idea/version +++ b/thirdparty/openssl/crypto/idea/version diff --git a/drivers/builtin_openssl2/crypto/install-crypto.com b/thirdparty/openssl/crypto/install-crypto.com index af1d75b526..af1d75b526 100755 --- a/drivers/builtin_openssl2/crypto/install-crypto.com +++ b/thirdparty/openssl/crypto/install-crypto.com diff --git a/drivers/builtin_openssl2/crypto/jpake/jpake.c b/thirdparty/openssl/crypto/jpake/jpake.c index ebc0975575..ebc0975575 100644 --- a/drivers/builtin_openssl2/crypto/jpake/jpake.c +++ b/thirdparty/openssl/crypto/jpake/jpake.c diff --git a/drivers/builtin_openssl2/crypto/jpake/jpake.h b/thirdparty/openssl/crypto/jpake/jpake.h index 371eed679c..371eed679c 100644 --- a/drivers/builtin_openssl2/crypto/jpake/jpake.h +++ b/thirdparty/openssl/crypto/jpake/jpake.h diff --git a/drivers/builtin_openssl2/crypto/jpake/jpake_err.c b/thirdparty/openssl/crypto/jpake/jpake_err.c index be236d9ea8..be236d9ea8 100644 --- a/drivers/builtin_openssl2/crypto/jpake/jpake_err.c +++ b/thirdparty/openssl/crypto/jpake/jpake_err.c diff --git a/drivers/builtin_openssl2/crypto/krb5/krb5_asn.c b/thirdparty/openssl/crypto/krb5/krb5_asn.c index d9851e9737..d9851e9737 100644 --- a/drivers/builtin_openssl2/crypto/krb5/krb5_asn.c +++ b/thirdparty/openssl/crypto/krb5/krb5_asn.c diff --git a/drivers/builtin_openssl2/crypto/lhash/lh_stats.c b/thirdparty/openssl/crypto/lhash/lh_stats.c index 0bfec2322e..0bfec2322e 100644 --- a/drivers/builtin_openssl2/crypto/lhash/lh_stats.c +++ b/thirdparty/openssl/crypto/lhash/lh_stats.c diff --git a/drivers/builtin_openssl2/crypto/lhash/lhash.c b/thirdparty/openssl/crypto/lhash/lhash.c index 53c5c138bb..53c5c138bb 100644 --- a/drivers/builtin_openssl2/crypto/lhash/lhash.c +++ b/thirdparty/openssl/crypto/lhash/lhash.c diff --git a/drivers/builtin_openssl2/crypto/md2/md2.c b/thirdparty/openssl/crypto/md2/md2.c index 584e34a648..584e34a648 100644 --- a/drivers/builtin_openssl2/crypto/md2/md2.c +++ b/thirdparty/openssl/crypto/md2/md2.c diff --git a/drivers/builtin_openssl2/crypto/md2/md2.h b/thirdparty/openssl/crypto/md2/md2.h index b568d3f987..b568d3f987 100644 --- a/drivers/builtin_openssl2/crypto/md2/md2.h +++ b/thirdparty/openssl/crypto/md2/md2.h diff --git a/drivers/builtin_openssl2/crypto/md2/md2_dgst.c b/thirdparty/openssl/crypto/md2/md2_dgst.c index 9cd79f8d70..9cd79f8d70 100644 --- a/drivers/builtin_openssl2/crypto/md2/md2_dgst.c +++ b/thirdparty/openssl/crypto/md2/md2_dgst.c diff --git a/drivers/builtin_openssl2/crypto/md2/md2_one.c b/thirdparty/openssl/crypto/md2/md2_one.c index cd2631b261..cd2631b261 100644 --- a/drivers/builtin_openssl2/crypto/md2/md2_one.c +++ b/thirdparty/openssl/crypto/md2/md2_one.c diff --git a/drivers/builtin_openssl2/crypto/md32_common.h b/thirdparty/openssl/crypto/md32_common.h index 96828d2693..96828d2693 100644 --- a/drivers/builtin_openssl2/crypto/md32_common.h +++ b/thirdparty/openssl/crypto/md32_common.h diff --git a/drivers/builtin_openssl2/crypto/md4/md4.c b/thirdparty/openssl/crypto/md4/md4.c index c9fab6669a..c9fab6669a 100644 --- a/drivers/builtin_openssl2/crypto/md4/md4.c +++ b/thirdparty/openssl/crypto/md4/md4.c diff --git a/drivers/builtin_openssl2/crypto/md4/md4_dgst.c b/thirdparty/openssl/crypto/md4/md4_dgst.c index 614fca0056..614fca0056 100644 --- a/drivers/builtin_openssl2/crypto/md4/md4_dgst.c +++ b/thirdparty/openssl/crypto/md4/md4_dgst.c diff --git a/drivers/builtin_openssl2/crypto/md4/md4_locl.h b/thirdparty/openssl/crypto/md4/md4_locl.h index dc86a86c56..dc86a86c56 100644 --- a/drivers/builtin_openssl2/crypto/md4/md4_locl.h +++ b/thirdparty/openssl/crypto/md4/md4_locl.h diff --git a/drivers/builtin_openssl2/crypto/md4/md4_one.c b/thirdparty/openssl/crypto/md4/md4_one.c index 32ebd5facf..32ebd5facf 100644 --- a/drivers/builtin_openssl2/crypto/md4/md4_one.c +++ b/thirdparty/openssl/crypto/md4/md4_one.c diff --git a/drivers/builtin_openssl2/crypto/md4/md4s.cpp b/thirdparty/openssl/crypto/md4/md4s.cpp index c0ec97fc9f..c0ec97fc9f 100644 --- a/drivers/builtin_openssl2/crypto/md4/md4s.cpp +++ b/thirdparty/openssl/crypto/md4/md4s.cpp diff --git a/drivers/builtin_openssl2/crypto/md5/md5.c b/thirdparty/openssl/crypto/md5/md5.c index f0282c507e..f0282c507e 100644 --- a/drivers/builtin_openssl2/crypto/md5/md5.c +++ b/thirdparty/openssl/crypto/md5/md5.c diff --git a/drivers/builtin_openssl2/crypto/md5/md5_dgst.c b/thirdparty/openssl/crypto/md5/md5_dgst.c index 2b51946708..2b51946708 100644 --- a/drivers/builtin_openssl2/crypto/md5/md5_dgst.c +++ b/thirdparty/openssl/crypto/md5/md5_dgst.c diff --git a/drivers/builtin_openssl2/crypto/md5/md5_locl.h b/thirdparty/openssl/crypto/md5/md5_locl.h index 82e69218da..82e69218da 100644 --- a/drivers/builtin_openssl2/crypto/md5/md5_locl.h +++ b/thirdparty/openssl/crypto/md5/md5_locl.h diff --git a/drivers/builtin_openssl2/crypto/md5/md5_one.c b/thirdparty/openssl/crypto/md5/md5_one.c index 4ac882e739..4ac882e739 100644 --- a/drivers/builtin_openssl2/crypto/md5/md5_one.c +++ b/thirdparty/openssl/crypto/md5/md5_one.c diff --git a/drivers/builtin_openssl2/crypto/md5/md5s.cpp b/thirdparty/openssl/crypto/md5/md5s.cpp index dd343fd4e6..dd343fd4e6 100644 --- a/drivers/builtin_openssl2/crypto/md5/md5s.cpp +++ b/thirdparty/openssl/crypto/md5/md5s.cpp diff --git a/drivers/builtin_openssl2/crypto/mdc2/mdc2_one.c b/thirdparty/openssl/crypto/mdc2/mdc2_one.c index 790775c6fe..790775c6fe 100644 --- a/drivers/builtin_openssl2/crypto/mdc2/mdc2_one.c +++ b/thirdparty/openssl/crypto/mdc2/mdc2_one.c diff --git a/drivers/builtin_openssl2/crypto/mdc2/mdc2dgst.c b/thirdparty/openssl/crypto/mdc2/mdc2dgst.c index 6615cf84d7..6615cf84d7 100644 --- a/drivers/builtin_openssl2/crypto/mdc2/mdc2dgst.c +++ b/thirdparty/openssl/crypto/mdc2/mdc2dgst.c diff --git a/drivers/builtin_openssl2/crypto/mem.c b/thirdparty/openssl/crypto/mem.c index fdad49b76e..fdad49b76e 100644 --- a/drivers/builtin_openssl2/crypto/mem.c +++ b/thirdparty/openssl/crypto/mem.c diff --git a/drivers/builtin_openssl2/crypto/mem_clr.c b/thirdparty/openssl/crypto/mem_clr.c index ab85344eef..ab85344eef 100644 --- a/drivers/builtin_openssl2/crypto/mem_clr.c +++ b/thirdparty/openssl/crypto/mem_clr.c diff --git a/drivers/builtin_openssl2/crypto/mem_dbg.c b/thirdparty/openssl/crypto/mem_dbg.c index 8525ded78c..8525ded78c 100644 --- a/drivers/builtin_openssl2/crypto/mem_dbg.c +++ b/thirdparty/openssl/crypto/mem_dbg.c diff --git a/drivers/builtin_openssl2/crypto/modes/cbc128.c b/thirdparty/openssl/crypto/modes/cbc128.c index c13caea535..c13caea535 100644 --- a/drivers/builtin_openssl2/crypto/modes/cbc128.c +++ b/thirdparty/openssl/crypto/modes/cbc128.c diff --git a/drivers/builtin_openssl2/crypto/modes/ccm128.c b/thirdparty/openssl/crypto/modes/ccm128.c index c1ded0f914..c1ded0f914 100644 --- a/drivers/builtin_openssl2/crypto/modes/ccm128.c +++ b/thirdparty/openssl/crypto/modes/ccm128.c diff --git a/drivers/builtin_openssl2/crypto/modes/cfb128.c b/thirdparty/openssl/crypto/modes/cfb128.c index d4ecbd08ee..d4ecbd08ee 100644 --- a/drivers/builtin_openssl2/crypto/modes/cfb128.c +++ b/thirdparty/openssl/crypto/modes/cfb128.c diff --git a/drivers/builtin_openssl2/crypto/modes/ctr128.c b/thirdparty/openssl/crypto/modes/ctr128.c index bcafd6b6bf..bcafd6b6bf 100644 --- a/drivers/builtin_openssl2/crypto/modes/ctr128.c +++ b/thirdparty/openssl/crypto/modes/ctr128.c diff --git a/drivers/builtin_openssl2/crypto/modes/cts128.c b/thirdparty/openssl/crypto/modes/cts128.c index 137be595a1..137be595a1 100644 --- a/drivers/builtin_openssl2/crypto/modes/cts128.c +++ b/thirdparty/openssl/crypto/modes/cts128.c diff --git a/drivers/builtin_openssl2/crypto/modes/gcm128.c b/thirdparty/openssl/crypto/modes/gcm128.c index e299131c13..e299131c13 100644 --- a/drivers/builtin_openssl2/crypto/modes/gcm128.c +++ b/thirdparty/openssl/crypto/modes/gcm128.c diff --git a/drivers/builtin_openssl2/crypto/modes/modes_lcl.h b/thirdparty/openssl/crypto/modes/modes_lcl.h index fe14ec7002..fe14ec7002 100644 --- a/drivers/builtin_openssl2/crypto/modes/modes_lcl.h +++ b/thirdparty/openssl/crypto/modes/modes_lcl.h diff --git a/drivers/builtin_openssl2/crypto/modes/ofb128.c b/thirdparty/openssl/crypto/modes/ofb128.c index 4dbaccd7a6..4dbaccd7a6 100644 --- a/drivers/builtin_openssl2/crypto/modes/ofb128.c +++ b/thirdparty/openssl/crypto/modes/ofb128.c diff --git a/drivers/builtin_openssl2/crypto/modes/wrap128.c b/thirdparty/openssl/crypto/modes/wrap128.c index 384978371a..384978371a 100644 --- a/drivers/builtin_openssl2/crypto/modes/wrap128.c +++ b/thirdparty/openssl/crypto/modes/wrap128.c diff --git a/drivers/builtin_openssl2/crypto/modes/xts128.c b/thirdparty/openssl/crypto/modes/xts128.c index 8f2af588b2..8f2af588b2 100644 --- a/drivers/builtin_openssl2/crypto/modes/xts128.c +++ b/thirdparty/openssl/crypto/modes/xts128.c diff --git a/drivers/builtin_openssl2/crypto/o_dir.c b/thirdparty/openssl/crypto/o_dir.c index f9dbed8711..f9dbed8711 100644 --- a/drivers/builtin_openssl2/crypto/o_dir.c +++ b/thirdparty/openssl/crypto/o_dir.c diff --git a/drivers/builtin_openssl2/crypto/o_dir.h b/thirdparty/openssl/crypto/o_dir.h index bf45a14d02..bf45a14d02 100644 --- a/drivers/builtin_openssl2/crypto/o_dir.h +++ b/thirdparty/openssl/crypto/o_dir.h diff --git a/drivers/builtin_openssl2/crypto/o_fips.c b/thirdparty/openssl/crypto/o_fips.c index f56d5bb79d..f56d5bb79d 100644 --- a/drivers/builtin_openssl2/crypto/o_fips.c +++ b/thirdparty/openssl/crypto/o_fips.c diff --git a/drivers/builtin_openssl2/crypto/o_init.c b/thirdparty/openssl/crypto/o_init.c index 2088388128..2088388128 100644 --- a/drivers/builtin_openssl2/crypto/o_init.c +++ b/thirdparty/openssl/crypto/o_init.c diff --git a/drivers/builtin_openssl2/crypto/o_str.c b/thirdparty/openssl/crypto/o_str.c index c10842300d..c10842300d 100644 --- a/drivers/builtin_openssl2/crypto/o_str.c +++ b/thirdparty/openssl/crypto/o_str.c diff --git a/drivers/builtin_openssl2/crypto/o_str.h b/thirdparty/openssl/crypto/o_str.h index fa512eb397..fa512eb397 100644 --- a/drivers/builtin_openssl2/crypto/o_str.h +++ b/thirdparty/openssl/crypto/o_str.h diff --git a/drivers/builtin_openssl2/crypto/o_time.c b/thirdparty/openssl/crypto/o_time.c index 635dae184d..635dae184d 100644 --- a/drivers/builtin_openssl2/crypto/o_time.c +++ b/thirdparty/openssl/crypto/o_time.c diff --git a/drivers/builtin_openssl2/crypto/o_time.h b/thirdparty/openssl/crypto/o_time.h index f192c6dccf..f192c6dccf 100644 --- a/drivers/builtin_openssl2/crypto/o_time.h +++ b/thirdparty/openssl/crypto/o_time.h diff --git a/drivers/builtin_openssl2/crypto/objects/o_names.c b/thirdparty/openssl/crypto/objects/o_names.c index 24859926ac..24859926ac 100644 --- a/drivers/builtin_openssl2/crypto/objects/o_names.c +++ b/thirdparty/openssl/crypto/objects/o_names.c diff --git a/drivers/builtin_openssl2/crypto/objects/obj_dat.c b/thirdparty/openssl/crypto/objects/obj_dat.c index aca382a6e9..aca382a6e9 100644 --- a/drivers/builtin_openssl2/crypto/objects/obj_dat.c +++ b/thirdparty/openssl/crypto/objects/obj_dat.c diff --git a/drivers/builtin_openssl2/crypto/objects/obj_dat.h b/thirdparty/openssl/crypto/objects/obj_dat.h index b7e3cf280e..b7e3cf280e 100644 --- a/drivers/builtin_openssl2/crypto/objects/obj_dat.h +++ b/thirdparty/openssl/crypto/objects/obj_dat.h diff --git a/drivers/builtin_openssl2/crypto/objects/obj_err.c b/thirdparty/openssl/crypto/objects/obj_err.c index 238aaa59f9..238aaa59f9 100644 --- a/drivers/builtin_openssl2/crypto/objects/obj_err.c +++ b/thirdparty/openssl/crypto/objects/obj_err.c diff --git a/drivers/builtin_openssl2/crypto/objects/obj_lib.c b/thirdparty/openssl/crypto/objects/obj_lib.c index 8851baffb2..8851baffb2 100644 --- a/drivers/builtin_openssl2/crypto/objects/obj_lib.c +++ b/thirdparty/openssl/crypto/objects/obj_lib.c diff --git a/drivers/builtin_openssl2/crypto/objects/obj_mac.num b/thirdparty/openssl/crypto/objects/obj_mac.num index 8e5ea83363..8e5ea83363 100644 --- a/drivers/builtin_openssl2/crypto/objects/obj_mac.num +++ b/thirdparty/openssl/crypto/objects/obj_mac.num diff --git a/drivers/builtin_openssl2/crypto/objects/obj_xref.c b/thirdparty/openssl/crypto/objects/obj_xref.c index 97b305d213..97b305d213 100644 --- a/drivers/builtin_openssl2/crypto/objects/obj_xref.c +++ b/thirdparty/openssl/crypto/objects/obj_xref.c diff --git a/drivers/builtin_openssl2/crypto/objects/obj_xref.h b/thirdparty/openssl/crypto/objects/obj_xref.h index e453e99f83..e453e99f83 100644 --- a/drivers/builtin_openssl2/crypto/objects/obj_xref.h +++ b/thirdparty/openssl/crypto/objects/obj_xref.h diff --git a/drivers/builtin_openssl2/crypto/objects/obj_xref.txt b/thirdparty/openssl/crypto/objects/obj_xref.txt index 19c94226b2..19c94226b2 100644 --- a/drivers/builtin_openssl2/crypto/objects/obj_xref.txt +++ b/thirdparty/openssl/crypto/objects/obj_xref.txt diff --git a/drivers/builtin_openssl2/crypto/objects/objects.README b/thirdparty/openssl/crypto/objects/objects.README index cb1d216ce8..cb1d216ce8 100644 --- a/drivers/builtin_openssl2/crypto/objects/objects.README +++ b/thirdparty/openssl/crypto/objects/objects.README diff --git a/drivers/builtin_openssl2/crypto/objects/objects.txt b/thirdparty/openssl/crypto/objects/objects.txt index b57aabb226..b57aabb226 100644 --- a/drivers/builtin_openssl2/crypto/objects/objects.txt +++ b/thirdparty/openssl/crypto/objects/objects.txt diff --git a/drivers/builtin_openssl2/crypto/ocsp/ocsp_asn.c b/thirdparty/openssl/crypto/ocsp/ocsp_asn.c index e2e52e77af..e2e52e77af 100644 --- a/drivers/builtin_openssl2/crypto/ocsp/ocsp_asn.c +++ b/thirdparty/openssl/crypto/ocsp/ocsp_asn.c diff --git a/drivers/builtin_openssl2/crypto/ocsp/ocsp_cl.c b/thirdparty/openssl/crypto/ocsp/ocsp_cl.c index b3612c8dfc..b3612c8dfc 100644 --- a/drivers/builtin_openssl2/crypto/ocsp/ocsp_cl.c +++ b/thirdparty/openssl/crypto/ocsp/ocsp_cl.c diff --git a/drivers/builtin_openssl2/crypto/ocsp/ocsp_err.c b/thirdparty/openssl/crypto/ocsp/ocsp_err.c index 722043c0f2..722043c0f2 100644 --- a/drivers/builtin_openssl2/crypto/ocsp/ocsp_err.c +++ b/thirdparty/openssl/crypto/ocsp/ocsp_err.c diff --git a/drivers/builtin_openssl2/crypto/ocsp/ocsp_ext.c b/thirdparty/openssl/crypto/ocsp/ocsp_ext.c index c19648c732..c19648c732 100644 --- a/drivers/builtin_openssl2/crypto/ocsp/ocsp_ext.c +++ b/thirdparty/openssl/crypto/ocsp/ocsp_ext.c diff --git a/drivers/builtin_openssl2/crypto/ocsp/ocsp_ht.c b/thirdparty/openssl/crypto/ocsp/ocsp_ht.c index 88b26b38e8..88b26b38e8 100644 --- a/drivers/builtin_openssl2/crypto/ocsp/ocsp_ht.c +++ b/thirdparty/openssl/crypto/ocsp/ocsp_ht.c diff --git a/drivers/builtin_openssl2/crypto/ocsp/ocsp_lib.c b/thirdparty/openssl/crypto/ocsp/ocsp_lib.c index cabf53933a..cabf53933a 100644 --- a/drivers/builtin_openssl2/crypto/ocsp/ocsp_lib.c +++ b/thirdparty/openssl/crypto/ocsp/ocsp_lib.c diff --git a/drivers/builtin_openssl2/crypto/ocsp/ocsp_prn.c b/thirdparty/openssl/crypto/ocsp/ocsp_prn.c index 47d5f83ef9..47d5f83ef9 100644 --- a/drivers/builtin_openssl2/crypto/ocsp/ocsp_prn.c +++ b/thirdparty/openssl/crypto/ocsp/ocsp_prn.c diff --git a/drivers/builtin_openssl2/crypto/ocsp/ocsp_srv.c b/thirdparty/openssl/crypto/ocsp/ocsp_srv.c index 2ec2c63618..2ec2c63618 100644 --- a/drivers/builtin_openssl2/crypto/ocsp/ocsp_srv.c +++ b/thirdparty/openssl/crypto/ocsp/ocsp_srv.c diff --git a/drivers/builtin_openssl2/crypto/ocsp/ocsp_vfy.c b/thirdparty/openssl/crypto/ocsp/ocsp_vfy.c index d4a257c33b..d4a257c33b 100644 --- a/drivers/builtin_openssl2/crypto/ocsp/ocsp_vfy.c +++ b/thirdparty/openssl/crypto/ocsp/ocsp_vfy.c diff --git a/drivers/builtin_openssl2/crypto/opensslconf.h.in b/thirdparty/openssl/crypto/opensslconf.h.in index 7a1c85d6ec..7a1c85d6ec 100644 --- a/drivers/builtin_openssl2/crypto/opensslconf.h.in +++ b/thirdparty/openssl/crypto/opensslconf.h.in diff --git a/drivers/builtin_openssl2/crypto/pem/message b/thirdparty/openssl/crypto/pem/message index e8bf9d7592..e8bf9d7592 100644 --- a/drivers/builtin_openssl2/crypto/pem/message +++ b/thirdparty/openssl/crypto/pem/message diff --git a/drivers/builtin_openssl2/crypto/pem/pem_all.c b/thirdparty/openssl/crypto/pem/pem_all.c index 0e5be63ef0..0e5be63ef0 100644 --- a/drivers/builtin_openssl2/crypto/pem/pem_all.c +++ b/thirdparty/openssl/crypto/pem/pem_all.c diff --git a/drivers/builtin_openssl2/crypto/pem/pem_err.c b/thirdparty/openssl/crypto/pem/pem_err.c index e1f4fdb432..e1f4fdb432 100644 --- a/drivers/builtin_openssl2/crypto/pem/pem_err.c +++ b/thirdparty/openssl/crypto/pem/pem_err.c diff --git a/drivers/builtin_openssl2/crypto/pem/pem_info.c b/thirdparty/openssl/crypto/pem/pem_info.c index 4d736a1d07..4d736a1d07 100644 --- a/drivers/builtin_openssl2/crypto/pem/pem_info.c +++ b/thirdparty/openssl/crypto/pem/pem_info.c diff --git a/drivers/builtin_openssl2/crypto/pem/pem_lib.c b/thirdparty/openssl/crypto/pem/pem_lib.c index fe881d6641..fe881d6641 100644 --- a/drivers/builtin_openssl2/crypto/pem/pem_lib.c +++ b/thirdparty/openssl/crypto/pem/pem_lib.c diff --git a/drivers/builtin_openssl2/crypto/pem/pem_oth.c b/thirdparty/openssl/crypto/pem/pem_oth.c index 1dd3bd7a1b..1dd3bd7a1b 100644 --- a/drivers/builtin_openssl2/crypto/pem/pem_oth.c +++ b/thirdparty/openssl/crypto/pem/pem_oth.c diff --git a/drivers/builtin_openssl2/crypto/pem/pem_pk8.c b/thirdparty/openssl/crypto/pem/pem_pk8.c index 5747c7366e..5747c7366e 100644 --- a/drivers/builtin_openssl2/crypto/pem/pem_pk8.c +++ b/thirdparty/openssl/crypto/pem/pem_pk8.c diff --git a/drivers/builtin_openssl2/crypto/pem/pem_pkey.c b/thirdparty/openssl/crypto/pem/pem_pkey.c index 04d6319a22..04d6319a22 100644 --- a/drivers/builtin_openssl2/crypto/pem/pem_pkey.c +++ b/thirdparty/openssl/crypto/pem/pem_pkey.c diff --git a/drivers/builtin_openssl2/crypto/pem/pem_seal.c b/thirdparty/openssl/crypto/pem/pem_seal.c index a5c1812575..a5c1812575 100644 --- a/drivers/builtin_openssl2/crypto/pem/pem_seal.c +++ b/thirdparty/openssl/crypto/pem/pem_seal.c diff --git a/drivers/builtin_openssl2/crypto/pem/pem_sign.c b/thirdparty/openssl/crypto/pem/pem_sign.c index b5e5c29b0e..b5e5c29b0e 100644 --- a/drivers/builtin_openssl2/crypto/pem/pem_sign.c +++ b/thirdparty/openssl/crypto/pem/pem_sign.c diff --git a/drivers/builtin_openssl2/crypto/pem/pem_x509.c b/thirdparty/openssl/crypto/pem/pem_x509.c index 3c20ff28ad..3c20ff28ad 100644 --- a/drivers/builtin_openssl2/crypto/pem/pem_x509.c +++ b/thirdparty/openssl/crypto/pem/pem_x509.c diff --git a/drivers/builtin_openssl2/crypto/pem/pem_xaux.c b/thirdparty/openssl/crypto/pem/pem_xaux.c index c523430189..c523430189 100644 --- a/drivers/builtin_openssl2/crypto/pem/pem_xaux.c +++ b/thirdparty/openssl/crypto/pem/pem_xaux.c diff --git a/drivers/builtin_openssl2/crypto/pem/pkcs7.lis b/thirdparty/openssl/crypto/pem/pkcs7.lis index be90c5d87f..be90c5d87f 100644 --- a/drivers/builtin_openssl2/crypto/pem/pkcs7.lis +++ b/thirdparty/openssl/crypto/pem/pkcs7.lis diff --git a/drivers/builtin_openssl2/crypto/pem/pvkfmt.c b/thirdparty/openssl/crypto/pem/pvkfmt.c index 61864468f6..61864468f6 100644 --- a/drivers/builtin_openssl2/crypto/pem/pvkfmt.c +++ b/thirdparty/openssl/crypto/pem/pvkfmt.c diff --git a/drivers/builtin_openssl2/crypto/perlasm/readme b/thirdparty/openssl/crypto/perlasm/readme index f02bbee75a..f02bbee75a 100644 --- a/drivers/builtin_openssl2/crypto/perlasm/readme +++ b/thirdparty/openssl/crypto/perlasm/readme diff --git a/drivers/builtin_openssl2/crypto/pkcs12/p12_add.c b/thirdparty/openssl/crypto/pkcs12/p12_add.c index d9f03a39fd..d9f03a39fd 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/p12_add.c +++ b/thirdparty/openssl/crypto/pkcs12/p12_add.c diff --git a/drivers/builtin_openssl2/crypto/pkcs12/p12_asn.c b/thirdparty/openssl/crypto/pkcs12/p12_asn.c index 370ddbd6e7..370ddbd6e7 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/p12_asn.c +++ b/thirdparty/openssl/crypto/pkcs12/p12_asn.c diff --git a/drivers/builtin_openssl2/crypto/pkcs12/p12_attr.c b/thirdparty/openssl/crypto/pkcs12/p12_attr.c index fff3ba1ece..fff3ba1ece 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/p12_attr.c +++ b/thirdparty/openssl/crypto/pkcs12/p12_attr.c diff --git a/drivers/builtin_openssl2/crypto/pkcs12/p12_crpt.c b/thirdparty/openssl/crypto/pkcs12/p12_crpt.c index 9c2dcab024..9c2dcab024 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/p12_crpt.c +++ b/thirdparty/openssl/crypto/pkcs12/p12_crpt.c diff --git a/drivers/builtin_openssl2/crypto/pkcs12/p12_crt.c b/thirdparty/openssl/crypto/pkcs12/p12_crt.c index 7d2aeefac3..7d2aeefac3 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/p12_crt.c +++ b/thirdparty/openssl/crypto/pkcs12/p12_crt.c diff --git a/drivers/builtin_openssl2/crypto/pkcs12/p12_decr.c b/thirdparty/openssl/crypto/pkcs12/p12_decr.c index b40ea10ccb..b40ea10ccb 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/p12_decr.c +++ b/thirdparty/openssl/crypto/pkcs12/p12_decr.c diff --git a/drivers/builtin_openssl2/crypto/pkcs12/p12_init.c b/thirdparty/openssl/crypto/pkcs12/p12_init.c index 0322df944a..0322df944a 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/p12_init.c +++ b/thirdparty/openssl/crypto/pkcs12/p12_init.c diff --git a/drivers/builtin_openssl2/crypto/pkcs12/p12_key.c b/thirdparty/openssl/crypto/pkcs12/p12_key.c index 99b8260c96..99b8260c96 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/p12_key.c +++ b/thirdparty/openssl/crypto/pkcs12/p12_key.c diff --git a/drivers/builtin_openssl2/crypto/pkcs12/p12_kiss.c b/thirdparty/openssl/crypto/pkcs12/p12_kiss.c index 9aa3c90c4e..9aa3c90c4e 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/p12_kiss.c +++ b/thirdparty/openssl/crypto/pkcs12/p12_kiss.c diff --git a/drivers/builtin_openssl2/crypto/pkcs12/p12_mutl.c b/thirdparty/openssl/crypto/pkcs12/p12_mutl.c index a9277827ff..a9277827ff 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/p12_mutl.c +++ b/thirdparty/openssl/crypto/pkcs12/p12_mutl.c diff --git a/drivers/builtin_openssl2/crypto/pkcs12/p12_npas.c b/thirdparty/openssl/crypto/pkcs12/p12_npas.c index a89b61abab..a89b61abab 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/p12_npas.c +++ b/thirdparty/openssl/crypto/pkcs12/p12_npas.c diff --git a/drivers/builtin_openssl2/crypto/pkcs12/p12_p8d.c b/thirdparty/openssl/crypto/pkcs12/p12_p8d.c index 3cc7a9f40e..3cc7a9f40e 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/p12_p8d.c +++ b/thirdparty/openssl/crypto/pkcs12/p12_p8d.c diff --git a/drivers/builtin_openssl2/crypto/pkcs12/p12_p8e.c b/thirdparty/openssl/crypto/pkcs12/p12_p8e.c index 861a087f80..861a087f80 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/p12_p8e.c +++ b/thirdparty/openssl/crypto/pkcs12/p12_p8e.c diff --git a/drivers/builtin_openssl2/crypto/pkcs12/p12_utl.c b/thirdparty/openssl/crypto/pkcs12/p12_utl.c index a0b992eab6..a0b992eab6 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/p12_utl.c +++ b/thirdparty/openssl/crypto/pkcs12/p12_utl.c diff --git a/drivers/builtin_openssl2/crypto/pkcs12/pk12err.c b/thirdparty/openssl/crypto/pkcs12/pk12err.c index e58710b253..e58710b253 100644 --- a/drivers/builtin_openssl2/crypto/pkcs12/pk12err.c +++ b/thirdparty/openssl/crypto/pkcs12/pk12err.c diff --git a/drivers/builtin_openssl2/crypto/pkcs7/bio_pk7.c b/thirdparty/openssl/crypto/pkcs7/bio_pk7.c index fae1c564c4..fae1c564c4 100644 --- a/drivers/builtin_openssl2/crypto/pkcs7/bio_pk7.c +++ b/thirdparty/openssl/crypto/pkcs7/bio_pk7.c diff --git a/drivers/builtin_openssl2/crypto/pkcs7/pk7_asn1.c b/thirdparty/openssl/crypto/pkcs7/pk7_asn1.c index 9c0a43981e..9c0a43981e 100644 --- a/drivers/builtin_openssl2/crypto/pkcs7/pk7_asn1.c +++ b/thirdparty/openssl/crypto/pkcs7/pk7_asn1.c diff --git a/drivers/builtin_openssl2/crypto/pkcs7/pk7_attr.c b/thirdparty/openssl/crypto/pkcs7/pk7_attr.c index 88922efe27..88922efe27 100644 --- a/drivers/builtin_openssl2/crypto/pkcs7/pk7_attr.c +++ b/thirdparty/openssl/crypto/pkcs7/pk7_attr.c diff --git a/drivers/builtin_openssl2/crypto/pkcs7/pk7_dgst.c b/thirdparty/openssl/crypto/pkcs7/pk7_dgst.c index 6b57f97aba..6b57f97aba 100644 --- a/drivers/builtin_openssl2/crypto/pkcs7/pk7_dgst.c +++ b/thirdparty/openssl/crypto/pkcs7/pk7_dgst.c diff --git a/drivers/builtin_openssl2/crypto/pkcs7/pk7_doit.c b/thirdparty/openssl/crypto/pkcs7/pk7_doit.c index 946aaa6543..946aaa6543 100644 --- a/drivers/builtin_openssl2/crypto/pkcs7/pk7_doit.c +++ b/thirdparty/openssl/crypto/pkcs7/pk7_doit.c diff --git a/drivers/builtin_openssl2/crypto/pkcs7/pk7_enc.c b/thirdparty/openssl/crypto/pkcs7/pk7_enc.c index 6983e014cd..6983e014cd 100644 --- a/drivers/builtin_openssl2/crypto/pkcs7/pk7_enc.c +++ b/thirdparty/openssl/crypto/pkcs7/pk7_enc.c diff --git a/drivers/builtin_openssl2/crypto/pkcs7/pk7_lib.c b/thirdparty/openssl/crypto/pkcs7/pk7_lib.c index 0c5fcaa6aa..0c5fcaa6aa 100644 --- a/drivers/builtin_openssl2/crypto/pkcs7/pk7_lib.c +++ b/thirdparty/openssl/crypto/pkcs7/pk7_lib.c diff --git a/drivers/builtin_openssl2/crypto/pkcs7/pk7_mime.c b/thirdparty/openssl/crypto/pkcs7/pk7_mime.c index 62fb2997ee..62fb2997ee 100644 --- a/drivers/builtin_openssl2/crypto/pkcs7/pk7_mime.c +++ b/thirdparty/openssl/crypto/pkcs7/pk7_mime.c diff --git a/drivers/builtin_openssl2/crypto/pkcs7/pk7_smime.c b/thirdparty/openssl/crypto/pkcs7/pk7_smime.c index dc9b484078..dc9b484078 100644 --- a/drivers/builtin_openssl2/crypto/pkcs7/pk7_smime.c +++ b/thirdparty/openssl/crypto/pkcs7/pk7_smime.c diff --git a/drivers/builtin_openssl2/crypto/pkcs7/pkcs7err.c b/thirdparty/openssl/crypto/pkcs7/pkcs7err.c index 323513fe8e..323513fe8e 100644 --- a/drivers/builtin_openssl2/crypto/pkcs7/pkcs7err.c +++ b/thirdparty/openssl/crypto/pkcs7/pkcs7err.c diff --git a/drivers/builtin_openssl2/crypto/ppc_arch.h b/thirdparty/openssl/crypto/ppc_arch.h index b50ec996a5..b50ec996a5 100644 --- a/drivers/builtin_openssl2/crypto/ppc_arch.h +++ b/thirdparty/openssl/crypto/ppc_arch.h diff --git a/drivers/builtin_openssl2/crypto/ppccap.c b/thirdparty/openssl/crypto/ppccap.c index 74af4732b5..74af4732b5 100644 --- a/drivers/builtin_openssl2/crypto/ppccap.c +++ b/thirdparty/openssl/crypto/ppccap.c diff --git a/drivers/builtin_openssl2/crypto/pqueue/pqueue.c b/thirdparty/openssl/crypto/pqueue/pqueue.c index 75f9734931..75f9734931 100644 --- a/drivers/builtin_openssl2/crypto/pqueue/pqueue.c +++ b/thirdparty/openssl/crypto/pqueue/pqueue.c diff --git a/drivers/builtin_openssl2/crypto/rand/md_rand.c b/thirdparty/openssl/crypto/rand/md_rand.c index 5c13d57765..5c13d57765 100644 --- a/drivers/builtin_openssl2/crypto/rand/md_rand.c +++ b/thirdparty/openssl/crypto/rand/md_rand.c diff --git a/drivers/builtin_openssl2/crypto/rand/rand_egd.c b/thirdparty/openssl/crypto/rand/rand_egd.c index 737aebfa22..737aebfa22 100644 --- a/drivers/builtin_openssl2/crypto/rand/rand_egd.c +++ b/thirdparty/openssl/crypto/rand/rand_egd.c diff --git a/drivers/builtin_openssl2/crypto/rand/rand_err.c b/thirdparty/openssl/crypto/rand/rand_err.c index 55d86ea8a3..55d86ea8a3 100644 --- a/drivers/builtin_openssl2/crypto/rand/rand_err.c +++ b/thirdparty/openssl/crypto/rand/rand_err.c diff --git a/drivers/builtin_openssl2/crypto/rand/rand_lcl.h b/thirdparty/openssl/crypto/rand/rand_lcl.h index f9fda3eb89..f9fda3eb89 100644 --- a/drivers/builtin_openssl2/crypto/rand/rand_lcl.h +++ b/thirdparty/openssl/crypto/rand/rand_lcl.h diff --git a/drivers/builtin_openssl2/crypto/rand/rand_lib.c b/thirdparty/openssl/crypto/rand/rand_lib.c index 88a78d3506..88a78d3506 100644 --- a/drivers/builtin_openssl2/crypto/rand/rand_lib.c +++ b/thirdparty/openssl/crypto/rand/rand_lib.c diff --git a/drivers/builtin_openssl2/crypto/rand/rand_nw.c b/thirdparty/openssl/crypto/rand/rand_nw.c index 55ffe9ad51..55ffe9ad51 100644 --- a/drivers/builtin_openssl2/crypto/rand/rand_nw.c +++ b/thirdparty/openssl/crypto/rand/rand_nw.c diff --git a/drivers/builtin_openssl2/crypto/rand/rand_os2.c b/thirdparty/openssl/crypto/rand/rand_os2.c index 706ab1e817..706ab1e817 100644 --- a/drivers/builtin_openssl2/crypto/rand/rand_os2.c +++ b/thirdparty/openssl/crypto/rand/rand_os2.c diff --git a/drivers/builtin_openssl2/crypto/rand/rand_unix.c b/thirdparty/openssl/crypto/rand/rand_unix.c index 266111edda..266111edda 100644 --- a/drivers/builtin_openssl2/crypto/rand/rand_unix.c +++ b/thirdparty/openssl/crypto/rand/rand_unix.c diff --git a/drivers/builtin_openssl2/crypto/rand/rand_vms.c b/thirdparty/openssl/crypto/rand/rand_vms.c index 0e10c363e2..0e10c363e2 100644 --- a/drivers/builtin_openssl2/crypto/rand/rand_vms.c +++ b/thirdparty/openssl/crypto/rand/rand_vms.c diff --git a/thirdparty/openssl/crypto/rand/rand_win.c b/thirdparty/openssl/crypto/rand/rand_win.c new file mode 100644 index 0000000000..70fd52a7aa --- /dev/null +++ b/thirdparty/openssl/crypto/rand/rand_win.c @@ -0,0 +1,757 @@ +/* crypto/rand/rand_win.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * 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. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF 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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include "cryptlib.h" +#include <openssl/rand.h> +#include "rand_lcl.h" + +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) +# include <windows.h> +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0400 +# endif +#ifndef WINRT_ENABLED +# include <wincrypt.h> +# include <tlhelp32.h> +#endif + +/* + * Limit the time spent walking through the heap, processes, threads and + * modules to a maximum of 1000 miliseconds each, unless CryptoGenRandom + * failed + */ +# define MAXDELAY 1000 + +/* + * Intel hardware RNG CSP -- available from + * http://developer.intel.com/design/security/rng/redist_license.htm + */ +# define PROV_INTEL_SEC 22 +# define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider" + +static void readtimer(void); +static void readscreen(void); + +/* + * It appears like CURSORINFO, PCURSORINFO and LPCURSORINFO are only defined + * when WINVER is 0x0500 and up, which currently only happens on Win2000. + * Unfortunately, those are typedefs, so they're a little bit difficult to + * detect properly. On the other hand, the macro CURSOR_SHOWING is defined + * within the same conditional, so it can be use to detect the absence of + * said typedefs. + */ + +# ifndef CURSOR_SHOWING +/* + * Information about the global cursor. + */ +typedef struct tagCURSORINFO { + DWORD cbSize; + DWORD flags; + HCURSOR hCursor; + POINT ptScreenPos; +} CURSORINFO, *PCURSORINFO, *LPCURSORINFO; + +# define CURSOR_SHOWING 0x00000001 +# endif /* CURSOR_SHOWING */ + +# if !defined(OPENSSL_SYS_WINCE) && !defined(WINRT_ENABLED) +typedef BOOL(WINAPI *CRYPTACQUIRECONTEXTW) (HCRYPTPROV *, LPCWSTR, LPCWSTR, + DWORD, DWORD); +typedef BOOL(WINAPI *CRYPTGENRANDOM) (HCRYPTPROV, DWORD, BYTE *); +typedef BOOL(WINAPI *CRYPTRELEASECONTEXT) (HCRYPTPROV, DWORD); + +typedef HWND(WINAPI *GETFOREGROUNDWINDOW) (VOID); +typedef BOOL(WINAPI *GETCURSORINFO) (PCURSORINFO); +typedef DWORD(WINAPI *GETQUEUESTATUS) (UINT); + +typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD); +typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE); +typedef BOOL(WINAPI *HEAP32FIRST) (LPHEAPENTRY32, DWORD, size_t); +typedef BOOL(WINAPI *HEAP32NEXT) (LPHEAPENTRY32); +typedef BOOL(WINAPI *HEAP32LIST) (HANDLE, LPHEAPLIST32); +typedef BOOL(WINAPI *PROCESS32) (HANDLE, LPPROCESSENTRY32); +typedef BOOL(WINAPI *THREAD32) (HANDLE, LPTHREADENTRY32); +typedef BOOL(WINAPI *MODULE32) (HANDLE, LPMODULEENTRY32); + +# include <lmcons.h> +# include <lmstats.h> +# if 1 +/* + * The NET API is Unicode only. It requires the use of the UNICODE macro. + * When UNICODE is defined LPTSTR becomes LPWSTR. LMSTR was was added to the + * Platform SDK to allow the NET API to be used in non-Unicode applications + * provided that Unicode strings were still used for input. LMSTR is defined + * as LPWSTR. + */ +typedef NET_API_STATUS(NET_API_FUNCTION *NETSTATGET) + (LPWSTR, LPWSTR, DWORD, DWORD, LPBYTE *); +typedef NET_API_STATUS(NET_API_FUNCTION *NETFREE) (LPBYTE); +# endif /* 1 */ +# endif /* !OPENSSL_SYS_WINCE */ + +#if !defined(WINRT_ENABLED) +int RAND_poll(void) +{ + MEMORYSTATUS m; + HCRYPTPROV hProvider = 0; + DWORD w; + int good = 0; + +# if defined(OPENSSL_SYS_WINCE) +# if defined(_WIN32_WCE) && _WIN32_WCE>=300 + /* + * Even though MSDN says _WIN32_WCE>=210, it doesn't seem to be available + * in commonly available implementations prior 300... + */ + { + BYTE buf[64]; + /* poll the CryptoAPI PRNG */ + /* The CryptoAPI returns sizeof(buf) bytes of randomness */ + if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) { + if (CryptGenRandom(hProvider, sizeof(buf), buf)) + RAND_add(buf, sizeof(buf), sizeof(buf)); + CryptReleaseContext(hProvider, 0); + } + } +# endif +# else /* OPENSSL_SYS_WINCE */ + /* + * None of below libraries are present on Windows CE, which is + * why we #ifndef the whole section. This also excuses us from + * handling the GetProcAddress issue. The trouble is that in + * real Win32 API GetProcAddress is available in ANSI flavor + * only. In WinCE on the other hand GetProcAddress is a macro + * most commonly defined as GetProcAddressW, which accepts + * Unicode argument. If we were to call GetProcAddress under + * WinCE, I'd recommend to either redefine GetProcAddress as + * GetProcAddressA (there seem to be one in common CE spec) or + * implement own shim routine, which would accept ANSI argument + * and expand it to Unicode. + */ + { + /* load functions dynamically - not available on all systems */ + HMODULE advapi = LoadLibrary(TEXT("ADVAPI32.DLL")); + HMODULE kernel = LoadLibrary(TEXT("KERNEL32.DLL")); + HMODULE user = NULL; + HMODULE netapi = LoadLibrary(TEXT("NETAPI32.DLL")); + CRYPTACQUIRECONTEXTW acquire = NULL; + CRYPTGENRANDOM gen = NULL; + CRYPTRELEASECONTEXT release = NULL; + NETSTATGET netstatget = NULL; + NETFREE netfree = NULL; + BYTE buf[64]; + + if (netapi) { + netstatget = + (NETSTATGET) GetProcAddress(netapi, "NetStatisticsGet"); + netfree = (NETFREE) GetProcAddress(netapi, "NetApiBufferFree"); + } + + if (netstatget && netfree) { + LPBYTE outbuf; + /* + * NetStatisticsGet() is a Unicode only function + * STAT_WORKSTATION_0 contains 45 fields and STAT_SERVER_0 + * contains 17 fields. We treat each field as a source of one + * byte of entropy. + */ + + if (netstatget(NULL, L"LanmanWorkstation", 0, 0, &outbuf) == 0) { + RAND_add(outbuf, sizeof(STAT_WORKSTATION_0), 45); + netfree(outbuf); + } + if (netstatget(NULL, L"LanmanServer", 0, 0, &outbuf) == 0) { + RAND_add(outbuf, sizeof(STAT_SERVER_0), 17); + netfree(outbuf); + } + } + + if (netapi) + FreeLibrary(netapi); + + /* + * It appears like this can cause an exception deep within + * ADVAPI32.DLL at random times on Windows 2000. Reported by Jeffrey + * Altman. Only use it on NT. + */ + + if (advapi) { + /* + * If it's available, then it's available in both ANSI + * and UNICODE flavors even in Win9x, documentation says. + * We favor Unicode... + */ + acquire = (CRYPTACQUIRECONTEXTW) GetProcAddress(advapi, + "CryptAcquireContextW"); + gen = (CRYPTGENRANDOM) GetProcAddress(advapi, "CryptGenRandom"); + release = (CRYPTRELEASECONTEXT) GetProcAddress(advapi, + "CryptReleaseContext"); + } + + if (acquire && gen && release) { + /* poll the CryptoAPI PRNG */ + /* The CryptoAPI returns sizeof(buf) bytes of randomness */ + if (acquire(&hProvider, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) { + if (gen(hProvider, sizeof(buf), buf) != 0) { + RAND_add(buf, sizeof(buf), 0); + good = 1; +# if 0 + printf("randomness from PROV_RSA_FULL\n"); +# endif + } + release(hProvider, 0); + } + + /* poll the Pentium PRG with CryptoAPI */ + if (acquire(&hProvider, 0, INTEL_DEF_PROV, PROV_INTEL_SEC, 0)) { + if (gen(hProvider, sizeof(buf), buf) != 0) { + RAND_add(buf, sizeof(buf), sizeof(buf)); + good = 1; +# if 0 + printf("randomness from PROV_INTEL_SEC\n"); +# endif + } + release(hProvider, 0); + } + } + + if (advapi) + FreeLibrary(advapi); + + if ((!check_winnt() || + !OPENSSL_isservice()) && + (user = LoadLibrary(TEXT("USER32.DLL")))) { + GETCURSORINFO cursor; + GETFOREGROUNDWINDOW win; + GETQUEUESTATUS queue; + + win = + (GETFOREGROUNDWINDOW) GetProcAddress(user, + "GetForegroundWindow"); + cursor = (GETCURSORINFO) GetProcAddress(user, "GetCursorInfo"); + queue = (GETQUEUESTATUS) GetProcAddress(user, "GetQueueStatus"); + + if (win) { + /* window handle */ + HWND h = win(); + RAND_add(&h, sizeof(h), 0); + } + if (cursor) { + /* + * unfortunately, its not safe to call GetCursorInfo() on NT4 + * even though it exists in SP3 (or SP6) and higher. + */ + if (check_winnt() && !check_win_minplat(5)) + cursor = 0; + } + if (cursor) { + /* cursor position */ + /* assume 2 bytes of entropy */ + CURSORINFO ci; + ci.cbSize = sizeof(CURSORINFO); + if (cursor(&ci)) + RAND_add(&ci, ci.cbSize, 2); + } + + if (queue) { + /* message queue status */ + /* assume 1 byte of entropy */ + w = queue(QS_ALLEVENTS); + RAND_add(&w, sizeof(w), 1); + } + + FreeLibrary(user); + } + + /*- + * Toolhelp32 snapshot: enumerate processes, threads, modules and heap + * http://msdn.microsoft.com/library/psdk/winbase/toolhelp_5pfd.htm + * (Win 9x and 2000 only, not available on NT) + * + * This seeding method was proposed in Peter Gutmann, Software + * Generation of Practically Strong Random Numbers, + * http://www.usenix.org/publications/library/proceedings/sec98/gutmann.html + * revised version at http://www.cryptoengines.com/~peter/06_random.pdf + * (The assignment of entropy estimates below is arbitrary, but based + * on Peter's analysis the full poll appears to be safe. Additional + * interactive seeding is encouraged.) + */ + + if (kernel) { + CREATETOOLHELP32SNAPSHOT snap; + CLOSETOOLHELP32SNAPSHOT close_snap; + HANDLE handle; + + HEAP32FIRST heap_first; + HEAP32NEXT heap_next; + HEAP32LIST heaplist_first, heaplist_next; + PROCESS32 process_first, process_next; + THREAD32 thread_first, thread_next; + MODULE32 module_first, module_next; + + HEAPLIST32 hlist; + HEAPENTRY32 hentry; + PROCESSENTRY32 p; + THREADENTRY32 t; + MODULEENTRY32 m; + DWORD starttime = 0; + + snap = (CREATETOOLHELP32SNAPSHOT) + GetProcAddress(kernel, "CreateToolhelp32Snapshot"); + close_snap = (CLOSETOOLHELP32SNAPSHOT) + GetProcAddress(kernel, "CloseToolhelp32Snapshot"); + heap_first = (HEAP32FIRST) GetProcAddress(kernel, "Heap32First"); + heap_next = (HEAP32NEXT) GetProcAddress(kernel, "Heap32Next"); + heaplist_first = + (HEAP32LIST) GetProcAddress(kernel, "Heap32ListFirst"); + heaplist_next = + (HEAP32LIST) GetProcAddress(kernel, "Heap32ListNext"); + process_first = + (PROCESS32) GetProcAddress(kernel, "Process32First"); + process_next = + (PROCESS32) GetProcAddress(kernel, "Process32Next"); + thread_first = (THREAD32) GetProcAddress(kernel, "Thread32First"); + thread_next = (THREAD32) GetProcAddress(kernel, "Thread32Next"); + module_first = (MODULE32) GetProcAddress(kernel, "Module32First"); + module_next = (MODULE32) GetProcAddress(kernel, "Module32Next"); + + if (snap && heap_first && heap_next && heaplist_first && + heaplist_next && process_first && process_next && + thread_first && thread_next && module_first && + module_next && (handle = snap(TH32CS_SNAPALL, 0)) + != INVALID_HANDLE_VALUE) { + /* heap list and heap walking */ + /* + * HEAPLIST32 contains 3 fields that will change with each + * entry. Consider each field a source of 1 byte of entropy. + * HEAPENTRY32 contains 5 fields that will change with each + * entry. Consider each field a source of 1 byte of entropy. + */ + ZeroMemory(&hlist, sizeof(HEAPLIST32)); + hlist.dwSize = sizeof(HEAPLIST32); + if (good) + starttime = GetTickCount(); +# ifdef _MSC_VER + if (heaplist_first(handle, &hlist)) { + /* + * following discussion on dev ML, exception on WinCE (or + * other Win platform) is theoretically of unknown + * origin; prevent infinite loop here when this + * theoretical case occurs; otherwise cope with the + * expected (MSDN documented) exception-throwing + * behaviour of Heap32Next() on WinCE. + * + * based on patch in original message by Tanguy Fautré + * (2009/03/02) Subject: RAND_poll() and + * CreateToolhelp32Snapshot() stability + */ + int ex_cnt_limit = 42; + do { + RAND_add(&hlist, hlist.dwSize, 3); + __try { + ZeroMemory(&hentry, sizeof(HEAPENTRY32)); + hentry.dwSize = sizeof(HEAPENTRY32); + if (heap_first(&hentry, + hlist.th32ProcessID, + hlist.th32HeapID)) { + int entrycnt = 80; + do + RAND_add(&hentry, hentry.dwSize, 5); + while (heap_next(&hentry) + && (!good + || (GetTickCount() - starttime) < + MAXDELAY) + && --entrycnt > 0); + } + } + __except(EXCEPTION_EXECUTE_HANDLER) { + /* + * ignore access violations when walking the heap + * list + */ + ex_cnt_limit--; + } + } while (heaplist_next(handle, &hlist) + && (!good + || (GetTickCount() - starttime) < MAXDELAY) + && ex_cnt_limit > 0); + } +# else + if (heaplist_first(handle, &hlist)) { + do { + RAND_add(&hlist, hlist.dwSize, 3); + hentry.dwSize = sizeof(HEAPENTRY32); + if (heap_first(&hentry, + hlist.th32ProcessID, + hlist.th32HeapID)) { + int entrycnt = 80; + do + RAND_add(&hentry, hentry.dwSize, 5); + while (heap_next(&hentry) + && --entrycnt > 0); + } + } while (heaplist_next(handle, &hlist) + && (!good + || (GetTickCount() - starttime) < MAXDELAY)); + } +# endif + + /* process walking */ + /* + * PROCESSENTRY32 contains 9 fields that will change with + * each entry. Consider each field a source of 1 byte of + * entropy. + */ + p.dwSize = sizeof(PROCESSENTRY32); + + if (good) + starttime = GetTickCount(); + if (process_first(handle, &p)) + do + RAND_add(&p, p.dwSize, 9); + while (process_next(handle, &p) + && (!good + || (GetTickCount() - starttime) < MAXDELAY)); + + /* thread walking */ + /* + * THREADENTRY32 contains 6 fields that will change with each + * entry. Consider each field a source of 1 byte of entropy. + */ + t.dwSize = sizeof(THREADENTRY32); + if (good) + starttime = GetTickCount(); + if (thread_first(handle, &t)) + do + RAND_add(&t, t.dwSize, 6); + while (thread_next(handle, &t) + && (!good + || (GetTickCount() - starttime) < MAXDELAY)); + + /* module walking */ + /* + * MODULEENTRY32 contains 9 fields that will change with each + * entry. Consider each field a source of 1 byte of entropy. + */ + m.dwSize = sizeof(MODULEENTRY32); + if (good) + starttime = GetTickCount(); + if (module_first(handle, &m)) + do + RAND_add(&m, m.dwSize, 9); + while (module_next(handle, &m) + && (!good + || (GetTickCount() - starttime) < MAXDELAY)); + if (close_snap) + close_snap(handle); + else + CloseHandle(handle); + + } + + FreeLibrary(kernel); + } + } +# endif /* !OPENSSL_SYS_WINCE */ + + /* timer data */ + readtimer(); + + /* memory usage statistics */ + GlobalMemoryStatus(&m); + RAND_add(&m, sizeof(m), 1); + + /* process ID */ + w = GetCurrentProcessId(); + RAND_add(&w, sizeof(w), 1); + +# if 0 + printf("Exiting RAND_poll\n"); +# endif + + return (1); +} + +#endif // WINRT_ENABLED + +int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + double add_entropy = 0; + + switch (iMsg) { + case WM_KEYDOWN: + { + static WPARAM key; + if (key != wParam) + add_entropy = 0.05; + key = wParam; + } + break; + case WM_MOUSEMOVE: + { + static int lastx, lasty, lastdx, lastdy; + int x, y, dx, dy; + + x = LOWORD(lParam); + y = HIWORD(lParam); + dx = lastx - x; + dy = lasty - y; + if (dx != 0 && dy != 0 && dx - lastdx != 0 && dy - lastdy != 0) + add_entropy = .2; + lastx = x, lasty = y; + lastdx = dx, lastdy = dy; + } + break; + } + + readtimer(); + RAND_add(&iMsg, sizeof(iMsg), add_entropy); + RAND_add(&wParam, sizeof(wParam), 0); + RAND_add(&lParam, sizeof(lParam), 0); + + return (RAND_status()); +} + +void RAND_screen(void) +{ /* function available for backward + * compatibility */ + RAND_poll(); + readscreen(); +} + +/* feed timing information to the PRNG */ +static void readtimer(void) +{ + DWORD w; + LARGE_INTEGER l; + static int have_perfc = 1; +# if defined(_MSC_VER) && defined(_M_X86) + static int have_tsc = 1; + DWORD cyclecount; + + if (have_tsc) { + __try { + __asm { + _emit 0x0f _emit 0x31 mov cyclecount, eax} + RAND_add(&cyclecount, sizeof(cyclecount), 1); + } + __except(EXCEPTION_EXECUTE_HANDLER) { + have_tsc = 0; + } + } +# else +# define have_tsc 0 +# endif + + if (have_perfc) { + if (QueryPerformanceCounter(&l) == 0) + have_perfc = 0; + else + RAND_add(&l, sizeof(l), 0); + } + + if (!have_tsc && !have_perfc) { + w = GetTickCount(); + RAND_add(&w, sizeof(w), 0); + } +} + +/* feed screen contents to PRNG */ +/***************************************************************************** + * + * Created 960901 by Gertjan van Oosten, gertjan@West.NL, West Consulting B.V. + * + * Code adapted from + * <URL:http://support.microsoft.com/default.aspx?scid=kb;[LN];97193>; + * the original copyright message is: + * + * (C) Copyright Microsoft Corp. 1993. All rights reserved. + * + * You have a royalty-free right to use, modify, reproduce and + * distribute the Sample Files (and/or any modified version) in + * any way you find useful, provided that you agree that + * Microsoft has no warranty obligations or liability for any + * Sample Application Files which are modified. + */ + +static void readscreen(void) +{ +# if !defined(OPENSSL_SYS_WINCE) && !defined(OPENSSL_SYS_WIN32_CYGWIN) && !defined(WINRT_ENABLED) + HDC hScrDC; /* screen DC */ + HBITMAP hBitmap; /* handle for our bitmap */ + BITMAP bm; /* bitmap properties */ + unsigned int size; /* size of bitmap */ + char *bmbits; /* contents of bitmap */ + int w; /* screen width */ + int h; /* screen height */ + int y; /* y-coordinate of screen lines to grab */ + int n = 16; /* number of screen lines to grab at a time */ + BITMAPINFOHEADER bi; /* info about the bitmap */ + + if (check_winnt() && OPENSSL_isservice() > 0) + return; + + /* Get a reference to the screen DC */ + hScrDC = GetDC(NULL); + + /* Get screen resolution */ + w = GetDeviceCaps(hScrDC, HORZRES); + h = GetDeviceCaps(hScrDC, VERTRES); + + /* Create a bitmap compatible with the screen DC */ + hBitmap = CreateCompatibleBitmap(hScrDC, w, n); + + /* Get bitmap properties */ + GetObject(hBitmap, sizeof(BITMAP), (LPSTR) & bm); + size = (unsigned int)bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes; + + bi.biSize = sizeof(BITMAPINFOHEADER); + bi.biWidth = bm.bmWidth; + bi.biHeight = bm.bmHeight; + bi.biPlanes = bm.bmPlanes; + bi.biBitCount = bm.bmBitsPixel; + bi.biCompression = BI_RGB; + bi.biSizeImage = 0; + bi.biXPelsPerMeter = 0; + bi.biYPelsPerMeter = 0; + bi.biClrUsed = 0; + bi.biClrImportant = 0; + + bmbits = OPENSSL_malloc(size); + if (bmbits) { + /* Now go through the whole screen, repeatedly grabbing n lines */ + for (y = 0; y < h - n; y += n) { + unsigned char md[MD_DIGEST_LENGTH]; + + /* Copy the bits of the current line range into the buffer */ + GetDIBits(hScrDC, hBitmap, y, n, + bmbits, (BITMAPINFO *) & bi, DIB_RGB_COLORS); + + /* Get the hash of the bitmap */ + MD(bmbits, size, md); + + /* Seed the random generator with the hash value */ + RAND_add(md, MD_DIGEST_LENGTH, 0); + } + + OPENSSL_free(bmbits); + } + + /* Clean up */ + DeleteObject(hBitmap); + ReleaseDC(NULL, hScrDC); +# endif /* !OPENSSL_SYS_WINCE */ +} + +#endif diff --git a/drivers/builtin_openssl2/crypto/rand/randfile.c b/thirdparty/openssl/crypto/rand/randfile.c index 9537c56a78..9537c56a78 100644 --- a/drivers/builtin_openssl2/crypto/rand/randfile.c +++ b/thirdparty/openssl/crypto/rand/randfile.c diff --git a/drivers/builtin_openssl2/crypto/rc2/rc2_cbc.c b/thirdparty/openssl/crypto/rc2/rc2_cbc.c index 5eaf01d2e0..5eaf01d2e0 100644 --- a/drivers/builtin_openssl2/crypto/rc2/rc2_cbc.c +++ b/thirdparty/openssl/crypto/rc2/rc2_cbc.c diff --git a/drivers/builtin_openssl2/crypto/rc2/rc2_ecb.c b/thirdparty/openssl/crypto/rc2/rc2_ecb.c index 48442a3f39..48442a3f39 100644 --- a/drivers/builtin_openssl2/crypto/rc2/rc2_ecb.c +++ b/thirdparty/openssl/crypto/rc2/rc2_ecb.c diff --git a/drivers/builtin_openssl2/crypto/rc2/rc2_locl.h b/thirdparty/openssl/crypto/rc2/rc2_locl.h index e72a20c0ca..e72a20c0ca 100644 --- a/drivers/builtin_openssl2/crypto/rc2/rc2_locl.h +++ b/thirdparty/openssl/crypto/rc2/rc2_locl.h diff --git a/drivers/builtin_openssl2/crypto/rc2/rc2_skey.c b/thirdparty/openssl/crypto/rc2/rc2_skey.c index bcec0a85d2..bcec0a85d2 100644 --- a/drivers/builtin_openssl2/crypto/rc2/rc2_skey.c +++ b/thirdparty/openssl/crypto/rc2/rc2_skey.c diff --git a/drivers/builtin_openssl2/crypto/rc2/rc2cfb64.c b/thirdparty/openssl/crypto/rc2/rc2cfb64.c index 8b5929fde3..8b5929fde3 100644 --- a/drivers/builtin_openssl2/crypto/rc2/rc2cfb64.c +++ b/thirdparty/openssl/crypto/rc2/rc2cfb64.c diff --git a/drivers/builtin_openssl2/crypto/rc2/rc2ofb64.c b/thirdparty/openssl/crypto/rc2/rc2ofb64.c index b9f4d8c35b..b9f4d8c35b 100644 --- a/drivers/builtin_openssl2/crypto/rc2/rc2ofb64.c +++ b/thirdparty/openssl/crypto/rc2/rc2ofb64.c diff --git a/drivers/builtin_openssl2/crypto/rc2/rc2speed.c b/thirdparty/openssl/crypto/rc2/rc2speed.c index 3e45eb0841..3e45eb0841 100644 --- a/drivers/builtin_openssl2/crypto/rc2/rc2speed.c +++ b/thirdparty/openssl/crypto/rc2/rc2speed.c diff --git a/drivers/builtin_openssl2/crypto/rc2/rrc2.doc b/thirdparty/openssl/crypto/rc2/rrc2.doc index f93ee003d2..f93ee003d2 100644 --- a/drivers/builtin_openssl2/crypto/rc2/rrc2.doc +++ b/thirdparty/openssl/crypto/rc2/rrc2.doc diff --git a/drivers/builtin_openssl2/crypto/rc2/tab.c b/thirdparty/openssl/crypto/rc2/tab.c index 0534e37506..0534e37506 100644 --- a/drivers/builtin_openssl2/crypto/rc2/tab.c +++ b/thirdparty/openssl/crypto/rc2/tab.c diff --git a/drivers/builtin_openssl2/crypto/rc2/version b/thirdparty/openssl/crypto/rc2/version index 6f89d595f1..6f89d595f1 100644 --- a/drivers/builtin_openssl2/crypto/rc2/version +++ b/thirdparty/openssl/crypto/rc2/version diff --git a/drivers/builtin_openssl2/crypto/rc4/rc4.c b/thirdparty/openssl/crypto/rc4/rc4.c index 99082e8919..99082e8919 100644 --- a/drivers/builtin_openssl2/crypto/rc4/rc4.c +++ b/thirdparty/openssl/crypto/rc4/rc4.c diff --git a/drivers/builtin_openssl2/crypto/rc4/rc4_enc.c b/thirdparty/openssl/crypto/rc4/rc4_enc.c index 0f0a2487a7..0f0a2487a7 100644 --- a/drivers/builtin_openssl2/crypto/rc4/rc4_enc.c +++ b/thirdparty/openssl/crypto/rc4/rc4_enc.c diff --git a/drivers/builtin_openssl2/crypto/rc4/rc4_locl.h b/thirdparty/openssl/crypto/rc4/rc4_locl.h index faf8742f01..faf8742f01 100644 --- a/drivers/builtin_openssl2/crypto/rc4/rc4_locl.h +++ b/thirdparty/openssl/crypto/rc4/rc4_locl.h diff --git a/drivers/builtin_openssl2/crypto/rc4/rc4_skey.c b/thirdparty/openssl/crypto/rc4/rc4_skey.c index 06890d16ae..06890d16ae 100644 --- a/drivers/builtin_openssl2/crypto/rc4/rc4_skey.c +++ b/thirdparty/openssl/crypto/rc4/rc4_skey.c diff --git a/drivers/builtin_openssl2/crypto/rc4/rc4_utl.c b/thirdparty/openssl/crypto/rc4/rc4_utl.c index cbd4a24e4b..cbd4a24e4b 100644 --- a/drivers/builtin_openssl2/crypto/rc4/rc4_utl.c +++ b/thirdparty/openssl/crypto/rc4/rc4_utl.c diff --git a/drivers/builtin_openssl2/crypto/rc4/rc4s.cpp b/thirdparty/openssl/crypto/rc4/rc4s.cpp index 3814fde997..3814fde997 100644 --- a/drivers/builtin_openssl2/crypto/rc4/rc4s.cpp +++ b/thirdparty/openssl/crypto/rc4/rc4s.cpp diff --git a/drivers/builtin_openssl2/crypto/rc4/rc4speed.c b/thirdparty/openssl/crypto/rc4/rc4speed.c index 3f13a2b2bc..3f13a2b2bc 100644 --- a/drivers/builtin_openssl2/crypto/rc4/rc4speed.c +++ b/thirdparty/openssl/crypto/rc4/rc4speed.c diff --git a/drivers/builtin_openssl2/crypto/rc4/rrc4.doc b/thirdparty/openssl/crypto/rc4/rrc4.doc index 2f9a953c12..2f9a953c12 100644 --- a/drivers/builtin_openssl2/crypto/rc4/rrc4.doc +++ b/thirdparty/openssl/crypto/rc4/rrc4.doc diff --git a/drivers/builtin_openssl2/crypto/rc5/rc5.h b/thirdparty/openssl/crypto/rc5/rc5.h index fba613713d..fba613713d 100644 --- a/drivers/builtin_openssl2/crypto/rc5/rc5.h +++ b/thirdparty/openssl/crypto/rc5/rc5.h diff --git a/drivers/builtin_openssl2/crypto/rc5/rc5_ecb.c b/thirdparty/openssl/crypto/rc5/rc5_ecb.c index e657a93b9a..e657a93b9a 100644 --- a/drivers/builtin_openssl2/crypto/rc5/rc5_ecb.c +++ b/thirdparty/openssl/crypto/rc5/rc5_ecb.c diff --git a/drivers/builtin_openssl2/crypto/rc5/rc5_enc.c b/thirdparty/openssl/crypto/rc5/rc5_enc.c index 06b89d83a1..06b89d83a1 100644 --- a/drivers/builtin_openssl2/crypto/rc5/rc5_enc.c +++ b/thirdparty/openssl/crypto/rc5/rc5_enc.c diff --git a/drivers/builtin_openssl2/crypto/rc5/rc5_locl.h b/thirdparty/openssl/crypto/rc5/rc5_locl.h index ee757e6477..ee757e6477 100644 --- a/drivers/builtin_openssl2/crypto/rc5/rc5_locl.h +++ b/thirdparty/openssl/crypto/rc5/rc5_locl.h diff --git a/drivers/builtin_openssl2/crypto/rc5/rc5_skey.c b/thirdparty/openssl/crypto/rc5/rc5_skey.c index 5dd4a52743..5dd4a52743 100644 --- a/drivers/builtin_openssl2/crypto/rc5/rc5_skey.c +++ b/thirdparty/openssl/crypto/rc5/rc5_skey.c diff --git a/drivers/builtin_openssl2/crypto/rc5/rc5cfb64.c b/thirdparty/openssl/crypto/rc5/rc5cfb64.c index a3813e030b..a3813e030b 100644 --- a/drivers/builtin_openssl2/crypto/rc5/rc5cfb64.c +++ b/thirdparty/openssl/crypto/rc5/rc5cfb64.c diff --git a/drivers/builtin_openssl2/crypto/rc5/rc5ofb64.c b/thirdparty/openssl/crypto/rc5/rc5ofb64.c index d3c63067b7..d3c63067b7 100644 --- a/drivers/builtin_openssl2/crypto/rc5/rc5ofb64.c +++ b/thirdparty/openssl/crypto/rc5/rc5ofb64.c diff --git a/drivers/builtin_openssl2/crypto/rc5/rc5s.cpp b/thirdparty/openssl/crypto/rc5/rc5s.cpp index 1c5518bc80..1c5518bc80 100644 --- a/drivers/builtin_openssl2/crypto/rc5/rc5s.cpp +++ b/thirdparty/openssl/crypto/rc5/rc5s.cpp diff --git a/drivers/builtin_openssl2/crypto/rc5/rc5speed.c b/thirdparty/openssl/crypto/rc5/rc5speed.c index 3f595704a9..3f595704a9 100644 --- a/drivers/builtin_openssl2/crypto/rc5/rc5speed.c +++ b/thirdparty/openssl/crypto/rc5/rc5speed.c diff --git a/drivers/builtin_openssl2/crypto/ripemd/README b/thirdparty/openssl/crypto/ripemd/README index f1ffc8b134..f1ffc8b134 100644 --- a/drivers/builtin_openssl2/crypto/ripemd/README +++ b/thirdparty/openssl/crypto/ripemd/README diff --git a/drivers/builtin_openssl2/crypto/ripemd/asm/rips.cpp b/thirdparty/openssl/crypto/ripemd/asm/rips.cpp index f7a13677a9..f7a13677a9 100644 --- a/drivers/builtin_openssl2/crypto/ripemd/asm/rips.cpp +++ b/thirdparty/openssl/crypto/ripemd/asm/rips.cpp diff --git a/drivers/builtin_openssl2/crypto/ripemd/rmd160.c b/thirdparty/openssl/crypto/ripemd/rmd160.c index a4f8007040..a4f8007040 100644 --- a/drivers/builtin_openssl2/crypto/ripemd/rmd160.c +++ b/thirdparty/openssl/crypto/ripemd/rmd160.c diff --git a/drivers/builtin_openssl2/crypto/ripemd/rmd_dgst.c b/thirdparty/openssl/crypto/ripemd/rmd_dgst.c index 4ddd939fcf..4ddd939fcf 100644 --- a/drivers/builtin_openssl2/crypto/ripemd/rmd_dgst.c +++ b/thirdparty/openssl/crypto/ripemd/rmd_dgst.c diff --git a/drivers/builtin_openssl2/crypto/ripemd/rmd_locl.h b/thirdparty/openssl/crypto/ripemd/rmd_locl.h index 26e0256333..26e0256333 100644 --- a/drivers/builtin_openssl2/crypto/ripemd/rmd_locl.h +++ b/thirdparty/openssl/crypto/ripemd/rmd_locl.h diff --git a/drivers/builtin_openssl2/crypto/ripemd/rmd_one.c b/thirdparty/openssl/crypto/ripemd/rmd_one.c index 666e01a41b..666e01a41b 100644 --- a/drivers/builtin_openssl2/crypto/ripemd/rmd_one.c +++ b/thirdparty/openssl/crypto/ripemd/rmd_one.c diff --git a/drivers/builtin_openssl2/crypto/ripemd/rmdconst.h b/thirdparty/openssl/crypto/ripemd/rmdconst.h index 8fe33de14e..8fe33de14e 100644 --- a/drivers/builtin_openssl2/crypto/ripemd/rmdconst.h +++ b/thirdparty/openssl/crypto/ripemd/rmdconst.h diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_ameth.c b/thirdparty/openssl/crypto/rsa/rsa_ameth.c index 4e0621827c..4e0621827c 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_ameth.c +++ b/thirdparty/openssl/crypto/rsa/rsa_ameth.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_asn1.c b/thirdparty/openssl/crypto/rsa/rsa_asn1.c index aff8b583fa..aff8b583fa 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_asn1.c +++ b/thirdparty/openssl/crypto/rsa/rsa_asn1.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_chk.c b/thirdparty/openssl/crypto/rsa/rsa_chk.c index 607faa0017..607faa0017 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_chk.c +++ b/thirdparty/openssl/crypto/rsa/rsa_chk.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_crpt.c b/thirdparty/openssl/crypto/rsa/rsa_crpt.c index 5c416b53fa..5c416b53fa 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_crpt.c +++ b/thirdparty/openssl/crypto/rsa/rsa_crpt.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_depr.c b/thirdparty/openssl/crypto/rsa/rsa_depr.c index 32f0c8887f..32f0c8887f 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_depr.c +++ b/thirdparty/openssl/crypto/rsa/rsa_depr.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_eay.c b/thirdparty/openssl/crypto/rsa/rsa_eay.c index b147fff8bd..b147fff8bd 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_eay.c +++ b/thirdparty/openssl/crypto/rsa/rsa_eay.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_err.c b/thirdparty/openssl/crypto/rsa/rsa_err.c index 0bab05efcf..0bab05efcf 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_err.c +++ b/thirdparty/openssl/crypto/rsa/rsa_err.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_gen.c b/thirdparty/openssl/crypto/rsa/rsa_gen.c index 7f7dca39fd..7f7dca39fd 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_gen.c +++ b/thirdparty/openssl/crypto/rsa/rsa_gen.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_lib.c b/thirdparty/openssl/crypto/rsa/rsa_lib.c index a6805debc8..a6805debc8 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_lib.c +++ b/thirdparty/openssl/crypto/rsa/rsa_lib.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_locl.h b/thirdparty/openssl/crypto/rsa/rsa_locl.h index 3e88187d9b..3e88187d9b 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_locl.h +++ b/thirdparty/openssl/crypto/rsa/rsa_locl.h diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_none.c b/thirdparty/openssl/crypto/rsa/rsa_none.c index 982b31f28c..982b31f28c 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_none.c +++ b/thirdparty/openssl/crypto/rsa/rsa_none.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_null.c b/thirdparty/openssl/crypto/rsa/rsa_null.c index 241b431ad5..241b431ad5 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_null.c +++ b/thirdparty/openssl/crypto/rsa/rsa_null.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_oaep.c b/thirdparty/openssl/crypto/rsa/rsa_oaep.c index 9c2a943cf7..9c2a943cf7 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_oaep.c +++ b/thirdparty/openssl/crypto/rsa/rsa_oaep.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_pk1.c b/thirdparty/openssl/crypto/rsa/rsa_pk1.c index efa1fd3e99..efa1fd3e99 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_pk1.c +++ b/thirdparty/openssl/crypto/rsa/rsa_pk1.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_pmeth.c b/thirdparty/openssl/crypto/rsa/rsa_pmeth.c index 203635595f..203635595f 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_pmeth.c +++ b/thirdparty/openssl/crypto/rsa/rsa_pmeth.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_prn.c b/thirdparty/openssl/crypto/rsa/rsa_prn.c index 076f871b31..076f871b31 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_prn.c +++ b/thirdparty/openssl/crypto/rsa/rsa_prn.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_pss.c b/thirdparty/openssl/crypto/rsa/rsa_pss.c index 41bc0844e4..41bc0844e4 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_pss.c +++ b/thirdparty/openssl/crypto/rsa/rsa_pss.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_saos.c b/thirdparty/openssl/crypto/rsa/rsa_saos.c index e400236057..e400236057 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_saos.c +++ b/thirdparty/openssl/crypto/rsa/rsa_saos.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_sign.c b/thirdparty/openssl/crypto/rsa/rsa_sign.c index 82ca8324df..82ca8324df 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_sign.c +++ b/thirdparty/openssl/crypto/rsa/rsa_sign.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_ssl.c b/thirdparty/openssl/crypto/rsa/rsa_ssl.c index 746e01f64a..746e01f64a 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_ssl.c +++ b/thirdparty/openssl/crypto/rsa/rsa_ssl.c diff --git a/drivers/builtin_openssl2/crypto/rsa/rsa_x931.c b/thirdparty/openssl/crypto/rsa/rsa_x931.c index 725ead049c..725ead049c 100644 --- a/drivers/builtin_openssl2/crypto/rsa/rsa_x931.c +++ b/thirdparty/openssl/crypto/rsa/rsa_x931.c diff --git a/drivers/builtin_openssl2/crypto/s390xcap.c b/thirdparty/openssl/crypto/s390xcap.c index 47d6b6ff51..47d6b6ff51 100644 --- a/drivers/builtin_openssl2/crypto/s390xcap.c +++ b/thirdparty/openssl/crypto/s390xcap.c diff --git a/drivers/builtin_openssl2/crypto/seed/seed.c b/thirdparty/openssl/crypto/seed/seed.c index a90587227e..a90587227e 100644 --- a/drivers/builtin_openssl2/crypto/seed/seed.c +++ b/thirdparty/openssl/crypto/seed/seed.c diff --git a/drivers/builtin_openssl2/crypto/seed/seed_cbc.c b/thirdparty/openssl/crypto/seed/seed_cbc.c index ee1115b4c1..ee1115b4c1 100644 --- a/drivers/builtin_openssl2/crypto/seed/seed_cbc.c +++ b/thirdparty/openssl/crypto/seed/seed_cbc.c diff --git a/drivers/builtin_openssl2/crypto/seed/seed_cfb.c b/thirdparty/openssl/crypto/seed/seed_cfb.c index b6a5648b35..b6a5648b35 100644 --- a/drivers/builtin_openssl2/crypto/seed/seed_cfb.c +++ b/thirdparty/openssl/crypto/seed/seed_cfb.c diff --git a/drivers/builtin_openssl2/crypto/seed/seed_ecb.c b/thirdparty/openssl/crypto/seed/seed_ecb.c index 9363d55080..9363d55080 100644 --- a/drivers/builtin_openssl2/crypto/seed/seed_ecb.c +++ b/thirdparty/openssl/crypto/seed/seed_ecb.c diff --git a/drivers/builtin_openssl2/crypto/seed/seed_locl.h b/thirdparty/openssl/crypto/seed/seed_locl.h index 96ec43022d..96ec43022d 100644 --- a/drivers/builtin_openssl2/crypto/seed/seed_locl.h +++ b/thirdparty/openssl/crypto/seed/seed_locl.h diff --git a/drivers/builtin_openssl2/crypto/seed/seed_ofb.c b/thirdparty/openssl/crypto/seed/seed_ofb.c index 48b71224c5..48b71224c5 100644 --- a/drivers/builtin_openssl2/crypto/seed/seed_ofb.c +++ b/thirdparty/openssl/crypto/seed/seed_ofb.c diff --git a/drivers/builtin_openssl2/crypto/sha/asm/README b/thirdparty/openssl/crypto/sha/asm/README index b7e755765f..b7e755765f 100644 --- a/drivers/builtin_openssl2/crypto/sha/asm/README +++ b/thirdparty/openssl/crypto/sha/asm/README diff --git a/drivers/builtin_openssl2/crypto/sha/sha.c b/thirdparty/openssl/crypto/sha/sha.c index cfc12f3edc..cfc12f3edc 100644 --- a/drivers/builtin_openssl2/crypto/sha/sha.c +++ b/thirdparty/openssl/crypto/sha/sha.c diff --git a/drivers/builtin_openssl2/crypto/sha/sha1.c b/thirdparty/openssl/crypto/sha/sha1.c index 8dd19431b4..8dd19431b4 100644 --- a/drivers/builtin_openssl2/crypto/sha/sha1.c +++ b/thirdparty/openssl/crypto/sha/sha1.c diff --git a/drivers/builtin_openssl2/crypto/sha/sha1_one.c b/thirdparty/openssl/crypto/sha/sha1_one.c index a6dd760a1e..a6dd760a1e 100644 --- a/drivers/builtin_openssl2/crypto/sha/sha1_one.c +++ b/thirdparty/openssl/crypto/sha/sha1_one.c diff --git a/drivers/builtin_openssl2/crypto/sha/sha1dgst.c b/thirdparty/openssl/crypto/sha/sha1dgst.c index a67f1fe364..a67f1fe364 100644 --- a/drivers/builtin_openssl2/crypto/sha/sha1dgst.c +++ b/thirdparty/openssl/crypto/sha/sha1dgst.c diff --git a/drivers/builtin_openssl2/crypto/sha/sha256.c b/thirdparty/openssl/crypto/sha/sha256.c index 72a1159369..72a1159369 100644 --- a/drivers/builtin_openssl2/crypto/sha/sha256.c +++ b/thirdparty/openssl/crypto/sha/sha256.c diff --git a/drivers/builtin_openssl2/crypto/sha/sha256t.c b/thirdparty/openssl/crypto/sha/sha256t.c index 35dbbc2a96..35dbbc2a96 100644 --- a/drivers/builtin_openssl2/crypto/sha/sha256t.c +++ b/thirdparty/openssl/crypto/sha/sha256t.c diff --git a/drivers/builtin_openssl2/crypto/sha/sha512.c b/thirdparty/openssl/crypto/sha/sha512.c index 3bf66ae198..3bf66ae198 100644 --- a/drivers/builtin_openssl2/crypto/sha/sha512.c +++ b/thirdparty/openssl/crypto/sha/sha512.c diff --git a/drivers/builtin_openssl2/crypto/sha/sha512t.c b/thirdparty/openssl/crypto/sha/sha512t.c index 178882fc76..178882fc76 100644 --- a/drivers/builtin_openssl2/crypto/sha/sha512t.c +++ b/thirdparty/openssl/crypto/sha/sha512t.c diff --git a/drivers/builtin_openssl2/crypto/sha/sha_dgst.c b/thirdparty/openssl/crypto/sha/sha_dgst.c index f77cf5e38d..f77cf5e38d 100644 --- a/drivers/builtin_openssl2/crypto/sha/sha_dgst.c +++ b/thirdparty/openssl/crypto/sha/sha_dgst.c diff --git a/drivers/builtin_openssl2/crypto/sha/sha_locl.h b/thirdparty/openssl/crypto/sha/sha_locl.h index 03bd411ede..03bd411ede 100644 --- a/drivers/builtin_openssl2/crypto/sha/sha_locl.h +++ b/thirdparty/openssl/crypto/sha/sha_locl.h diff --git a/drivers/builtin_openssl2/crypto/sha/sha_one.c b/thirdparty/openssl/crypto/sha/sha_one.c index 0930b98a66..0930b98a66 100644 --- a/drivers/builtin_openssl2/crypto/sha/sha_one.c +++ b/thirdparty/openssl/crypto/sha/sha_one.c diff --git a/drivers/builtin_openssl2/crypto/sparc_arch.h b/thirdparty/openssl/crypto/sparc_arch.h index e30d322a4a..e30d322a4a 100644 --- a/drivers/builtin_openssl2/crypto/sparc_arch.h +++ b/thirdparty/openssl/crypto/sparc_arch.h diff --git a/drivers/builtin_openssl2/crypto/sparcv9cap.c b/thirdparty/openssl/crypto/sparcv9cap.c index a36e461792..a36e461792 100644 --- a/drivers/builtin_openssl2/crypto/sparcv9cap.c +++ b/thirdparty/openssl/crypto/sparcv9cap.c diff --git a/drivers/builtin_openssl2/crypto/srp/srp_grps.h b/thirdparty/openssl/crypto/srp/srp_grps.h index 31312de15c..31312de15c 100644 --- a/drivers/builtin_openssl2/crypto/srp/srp_grps.h +++ b/thirdparty/openssl/crypto/srp/srp_grps.h diff --git a/drivers/builtin_openssl2/crypto/srp/srp_lcl.h b/thirdparty/openssl/crypto/srp/srp_lcl.h index 9a7fce1b4c..9a7fce1b4c 100644 --- a/drivers/builtin_openssl2/crypto/srp/srp_lcl.h +++ b/thirdparty/openssl/crypto/srp/srp_lcl.h diff --git a/drivers/builtin_openssl2/crypto/srp/srp_lib.c b/thirdparty/openssl/crypto/srp/srp_lib.c index e9a2e058f6..e9a2e058f6 100644 --- a/drivers/builtin_openssl2/crypto/srp/srp_lib.c +++ b/thirdparty/openssl/crypto/srp/srp_lib.c diff --git a/drivers/builtin_openssl2/crypto/srp/srp_vfy.c b/thirdparty/openssl/crypto/srp/srp_vfy.c index 26ad3e07b4..26ad3e07b4 100644 --- a/drivers/builtin_openssl2/crypto/srp/srp_vfy.c +++ b/thirdparty/openssl/crypto/srp/srp_vfy.c diff --git a/drivers/builtin_openssl2/crypto/stack/stack.c b/thirdparty/openssl/crypto/stack/stack.c index fa50083e22..fa50083e22 100644 --- a/drivers/builtin_openssl2/crypto/stack/stack.c +++ b/thirdparty/openssl/crypto/stack/stack.c diff --git a/drivers/builtin_openssl2/crypto/store/README b/thirdparty/openssl/crypto/store/README index 966168f6a5..966168f6a5 100644 --- a/drivers/builtin_openssl2/crypto/store/README +++ b/thirdparty/openssl/crypto/store/README diff --git a/drivers/builtin_openssl2/crypto/store/store.h b/thirdparty/openssl/crypto/store/store.h index ce3709d9f0..ce3709d9f0 100644 --- a/drivers/builtin_openssl2/crypto/store/store.h +++ b/thirdparty/openssl/crypto/store/store.h diff --git a/drivers/builtin_openssl2/crypto/store/str_err.c b/thirdparty/openssl/crypto/store/str_err.c index 9858e606ea..9858e606ea 100644 --- a/drivers/builtin_openssl2/crypto/store/str_err.c +++ b/thirdparty/openssl/crypto/store/str_err.c diff --git a/drivers/builtin_openssl2/crypto/store/str_lib.c b/thirdparty/openssl/crypto/store/str_lib.c index e3d5da9388..e3d5da9388 100644 --- a/drivers/builtin_openssl2/crypto/store/str_lib.c +++ b/thirdparty/openssl/crypto/store/str_lib.c diff --git a/drivers/builtin_openssl2/crypto/store/str_locl.h b/thirdparty/openssl/crypto/store/str_locl.h index c0b40f0db6..c0b40f0db6 100644 --- a/drivers/builtin_openssl2/crypto/store/str_locl.h +++ b/thirdparty/openssl/crypto/store/str_locl.h diff --git a/drivers/builtin_openssl2/crypto/store/str_mem.c b/thirdparty/openssl/crypto/store/str_mem.c index 6eee5bba29..6eee5bba29 100644 --- a/drivers/builtin_openssl2/crypto/store/str_mem.c +++ b/thirdparty/openssl/crypto/store/str_mem.c diff --git a/drivers/builtin_openssl2/crypto/store/str_meth.c b/thirdparty/openssl/crypto/store/str_meth.c index c83fbc565a..c83fbc565a 100644 --- a/drivers/builtin_openssl2/crypto/store/str_meth.c +++ b/thirdparty/openssl/crypto/store/str_meth.c diff --git a/drivers/builtin_openssl2/crypto/threads/README b/thirdparty/openssl/crypto/threads/README index df6b26e146..df6b26e146 100644 --- a/drivers/builtin_openssl2/crypto/threads/README +++ b/thirdparty/openssl/crypto/threads/README diff --git a/drivers/builtin_openssl2/crypto/threads/netware.bat b/thirdparty/openssl/crypto/threads/netware.bat index 0b3eca3caf..0b3eca3caf 100644 --- a/drivers/builtin_openssl2/crypto/threads/netware.bat +++ b/thirdparty/openssl/crypto/threads/netware.bat diff --git a/drivers/builtin_openssl2/crypto/threads/profile.sh b/thirdparty/openssl/crypto/threads/profile.sh index 6e3e342fc0..6e3e342fc0 100644 --- a/drivers/builtin_openssl2/crypto/threads/profile.sh +++ b/thirdparty/openssl/crypto/threads/profile.sh diff --git a/drivers/builtin_openssl2/crypto/threads/ptest.bat b/thirdparty/openssl/crypto/threads/ptest.bat index 4071b5ffea..4071b5ffea 100755 --- a/drivers/builtin_openssl2/crypto/threads/ptest.bat +++ b/thirdparty/openssl/crypto/threads/ptest.bat diff --git a/drivers/builtin_openssl2/crypto/threads/pthread.sh b/thirdparty/openssl/crypto/threads/pthread.sh index f1c49821d2..f1c49821d2 100644 --- a/drivers/builtin_openssl2/crypto/threads/pthread.sh +++ b/thirdparty/openssl/crypto/threads/pthread.sh diff --git a/drivers/builtin_openssl2/crypto/threads/pthread2.sh b/thirdparty/openssl/crypto/threads/pthread2.sh index ec945c451b..ec945c451b 100755 --- a/drivers/builtin_openssl2/crypto/threads/pthread2.sh +++ b/thirdparty/openssl/crypto/threads/pthread2.sh diff --git a/drivers/builtin_openssl2/crypto/threads/pthreads-vms.com b/thirdparty/openssl/crypto/threads/pthreads-vms.com index 1cf92bdf57..1cf92bdf57 100644 --- a/drivers/builtin_openssl2/crypto/threads/pthreads-vms.com +++ b/thirdparty/openssl/crypto/threads/pthreads-vms.com diff --git a/drivers/builtin_openssl2/crypto/threads/purify.sh b/thirdparty/openssl/crypto/threads/purify.sh index 6d44fe26b7..6d44fe26b7 100644 --- a/drivers/builtin_openssl2/crypto/threads/purify.sh +++ b/thirdparty/openssl/crypto/threads/purify.sh diff --git a/drivers/builtin_openssl2/crypto/threads/solaris.sh b/thirdparty/openssl/crypto/threads/solaris.sh index bc93094a27..bc93094a27 100644 --- a/drivers/builtin_openssl2/crypto/threads/solaris.sh +++ b/thirdparty/openssl/crypto/threads/solaris.sh diff --git a/drivers/builtin_openssl2/crypto/threads/th-lock.c b/thirdparty/openssl/crypto/threads/th-lock.c index cc8cf2581d..cc8cf2581d 100644 --- a/drivers/builtin_openssl2/crypto/threads/th-lock.c +++ b/thirdparty/openssl/crypto/threads/th-lock.c diff --git a/drivers/builtin_openssl2/crypto/threads/win32.bat b/thirdparty/openssl/crypto/threads/win32.bat index ee6da80a07..ee6da80a07 100755 --- a/drivers/builtin_openssl2/crypto/threads/win32.bat +++ b/thirdparty/openssl/crypto/threads/win32.bat diff --git a/drivers/builtin_openssl2/crypto/ts/ts_asn1.c b/thirdparty/openssl/crypto/ts/ts_asn1.c index 657dc4ca4d..657dc4ca4d 100644 --- a/drivers/builtin_openssl2/crypto/ts/ts_asn1.c +++ b/thirdparty/openssl/crypto/ts/ts_asn1.c diff --git a/drivers/builtin_openssl2/crypto/ts/ts_conf.c b/thirdparty/openssl/crypto/ts/ts_conf.c index 4716b2336d..4716b2336d 100644 --- a/drivers/builtin_openssl2/crypto/ts/ts_conf.c +++ b/thirdparty/openssl/crypto/ts/ts_conf.c diff --git a/drivers/builtin_openssl2/crypto/ts/ts_err.c b/thirdparty/openssl/crypto/ts/ts_err.c index ff1abf4533..ff1abf4533 100644 --- a/drivers/builtin_openssl2/crypto/ts/ts_err.c +++ b/thirdparty/openssl/crypto/ts/ts_err.c diff --git a/drivers/builtin_openssl2/crypto/ts/ts_lib.c b/thirdparty/openssl/crypto/ts/ts_lib.c index c51538a17f..c51538a17f 100644 --- a/drivers/builtin_openssl2/crypto/ts/ts_lib.c +++ b/thirdparty/openssl/crypto/ts/ts_lib.c diff --git a/drivers/builtin_openssl2/crypto/ts/ts_req_print.c b/thirdparty/openssl/crypto/ts/ts_req_print.c index 31940eef50..31940eef50 100644 --- a/drivers/builtin_openssl2/crypto/ts/ts_req_print.c +++ b/thirdparty/openssl/crypto/ts/ts_req_print.c diff --git a/drivers/builtin_openssl2/crypto/ts/ts_req_utils.c b/thirdparty/openssl/crypto/ts/ts_req_utils.c index 362e5e589a..362e5e589a 100644 --- a/drivers/builtin_openssl2/crypto/ts/ts_req_utils.c +++ b/thirdparty/openssl/crypto/ts/ts_req_utils.c diff --git a/drivers/builtin_openssl2/crypto/ts/ts_rsp_print.c b/thirdparty/openssl/crypto/ts/ts_rsp_print.c index e706a5687a..e706a5687a 100644 --- a/drivers/builtin_openssl2/crypto/ts/ts_rsp_print.c +++ b/thirdparty/openssl/crypto/ts/ts_rsp_print.c diff --git a/drivers/builtin_openssl2/crypto/ts/ts_rsp_sign.c b/thirdparty/openssl/crypto/ts/ts_rsp_sign.c index db6ce3241f..db6ce3241f 100644 --- a/drivers/builtin_openssl2/crypto/ts/ts_rsp_sign.c +++ b/thirdparty/openssl/crypto/ts/ts_rsp_sign.c diff --git a/drivers/builtin_openssl2/crypto/ts/ts_rsp_utils.c b/thirdparty/openssl/crypto/ts/ts_rsp_utils.c index f6f63329a0..f6f63329a0 100644 --- a/drivers/builtin_openssl2/crypto/ts/ts_rsp_utils.c +++ b/thirdparty/openssl/crypto/ts/ts_rsp_utils.c diff --git a/drivers/builtin_openssl2/crypto/ts/ts_rsp_verify.c b/thirdparty/openssl/crypto/ts/ts_rsp_verify.c index 29aa5a497e..29aa5a497e 100644 --- a/drivers/builtin_openssl2/crypto/ts/ts_rsp_verify.c +++ b/thirdparty/openssl/crypto/ts/ts_rsp_verify.c diff --git a/drivers/builtin_openssl2/crypto/ts/ts_verify_ctx.c b/thirdparty/openssl/crypto/ts/ts_verify_ctx.c index 3e6fcb57be..3e6fcb57be 100644 --- a/drivers/builtin_openssl2/crypto/ts/ts_verify_ctx.c +++ b/thirdparty/openssl/crypto/ts/ts_verify_ctx.c diff --git a/drivers/builtin_openssl2/crypto/txt_db/txt_db.c b/thirdparty/openssl/crypto/txt_db/txt_db.c index f9b42ac6e5..f9b42ac6e5 100644 --- a/drivers/builtin_openssl2/crypto/txt_db/txt_db.c +++ b/thirdparty/openssl/crypto/txt_db/txt_db.c diff --git a/drivers/builtin_openssl2/crypto/ui/ui_compat.c b/thirdparty/openssl/crypto/ui/ui_compat.c index e79d54eea6..e79d54eea6 100644 --- a/drivers/builtin_openssl2/crypto/ui/ui_compat.c +++ b/thirdparty/openssl/crypto/ui/ui_compat.c diff --git a/drivers/builtin_openssl2/crypto/ui/ui_err.c b/thirdparty/openssl/crypto/ui/ui_err.c index 8097da836a..8097da836a 100644 --- a/drivers/builtin_openssl2/crypto/ui/ui_err.c +++ b/thirdparty/openssl/crypto/ui/ui_err.c diff --git a/drivers/builtin_openssl2/crypto/ui/ui_lib.c b/thirdparty/openssl/crypto/ui/ui_lib.c index 2f580352ce..2f580352ce 100644 --- a/drivers/builtin_openssl2/crypto/ui/ui_lib.c +++ b/thirdparty/openssl/crypto/ui/ui_lib.c diff --git a/drivers/builtin_openssl2/crypto/ui/ui_locl.h b/thirdparty/openssl/crypto/ui/ui_locl.h index bebc13abfc..bebc13abfc 100644 --- a/drivers/builtin_openssl2/crypto/ui/ui_locl.h +++ b/thirdparty/openssl/crypto/ui/ui_locl.h diff --git a/drivers/builtin_openssl2/crypto/ui/ui_openssl.c b/thirdparty/openssl/crypto/ui/ui_openssl.c index 9ab259b8f6..9ab259b8f6 100644 --- a/drivers/builtin_openssl2/crypto/ui/ui_openssl.c +++ b/thirdparty/openssl/crypto/ui/ui_openssl.c diff --git a/drivers/builtin_openssl2/crypto/ui/ui_util.c b/thirdparty/openssl/crypto/ui/ui_util.c index 0f290115d0..0f290115d0 100644 --- a/drivers/builtin_openssl2/crypto/ui/ui_util.c +++ b/thirdparty/openssl/crypto/ui/ui_util.c diff --git a/drivers/builtin_openssl2/crypto/uid.c b/thirdparty/openssl/crypto/uid.c index 90694c6725..90694c6725 100644 --- a/drivers/builtin_openssl2/crypto/uid.c +++ b/thirdparty/openssl/crypto/uid.c diff --git a/drivers/builtin_openssl2/crypto/vms_rms.h b/thirdparty/openssl/crypto/vms_rms.h index 09c280e87b..09c280e87b 100644 --- a/drivers/builtin_openssl2/crypto/vms_rms.h +++ b/thirdparty/openssl/crypto/vms_rms.h diff --git a/drivers/builtin_openssl2/crypto/whrlpool/wp_block.c b/thirdparty/openssl/crypto/whrlpool/wp_block.c index 920430bd6c..920430bd6c 100644 --- a/drivers/builtin_openssl2/crypto/whrlpool/wp_block.c +++ b/thirdparty/openssl/crypto/whrlpool/wp_block.c diff --git a/drivers/builtin_openssl2/crypto/whrlpool/wp_dgst.c b/thirdparty/openssl/crypto/whrlpool/wp_dgst.c index e33bb4f833..e33bb4f833 100644 --- a/drivers/builtin_openssl2/crypto/whrlpool/wp_dgst.c +++ b/thirdparty/openssl/crypto/whrlpool/wp_dgst.c diff --git a/drivers/builtin_openssl2/crypto/whrlpool/wp_locl.h b/thirdparty/openssl/crypto/whrlpool/wp_locl.h index 6e7b549e1e..6e7b549e1e 100644 --- a/drivers/builtin_openssl2/crypto/whrlpool/wp_locl.h +++ b/thirdparty/openssl/crypto/whrlpool/wp_locl.h diff --git a/drivers/builtin_openssl2/crypto/x509/by_dir.c b/thirdparty/openssl/crypto/x509/by_dir.c index 9ee8f8d859..9ee8f8d859 100644 --- a/drivers/builtin_openssl2/crypto/x509/by_dir.c +++ b/thirdparty/openssl/crypto/x509/by_dir.c diff --git a/drivers/builtin_openssl2/crypto/x509/by_file.c b/thirdparty/openssl/crypto/x509/by_file.c index 43a073003d..43a073003d 100644 --- a/drivers/builtin_openssl2/crypto/x509/by_file.c +++ b/thirdparty/openssl/crypto/x509/by_file.c diff --git a/drivers/builtin_openssl2/crypto/x509/vpm_int.h b/thirdparty/openssl/crypto/x509/vpm_int.h index 9c55defc51..9c55defc51 100644 --- a/drivers/builtin_openssl2/crypto/x509/vpm_int.h +++ b/thirdparty/openssl/crypto/x509/vpm_int.h diff --git a/drivers/builtin_openssl2/crypto/x509/x509_att.c b/thirdparty/openssl/crypto/x509/x509_att.c index bd59281f9d..bd59281f9d 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_att.c +++ b/thirdparty/openssl/crypto/x509/x509_att.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_cmp.c b/thirdparty/openssl/crypto/x509/x509_cmp.c index 49c71b9128..49c71b9128 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_cmp.c +++ b/thirdparty/openssl/crypto/x509/x509_cmp.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_d2.c b/thirdparty/openssl/crypto/x509/x509_d2.c index 50ca2a6d18..50ca2a6d18 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_d2.c +++ b/thirdparty/openssl/crypto/x509/x509_d2.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_def.c b/thirdparty/openssl/crypto/x509/x509_def.c index 25c5537556..25c5537556 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_def.c +++ b/thirdparty/openssl/crypto/x509/x509_def.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_err.c b/thirdparty/openssl/crypto/x509/x509_err.c index 1e779fefd9..1e779fefd9 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_err.c +++ b/thirdparty/openssl/crypto/x509/x509_err.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_ext.c b/thirdparty/openssl/crypto/x509/x509_ext.c index fb4e311d71..fb4e311d71 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_ext.c +++ b/thirdparty/openssl/crypto/x509/x509_ext.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_lu.c b/thirdparty/openssl/crypto/x509/x509_lu.c index 50120a4d70..50120a4d70 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_lu.c +++ b/thirdparty/openssl/crypto/x509/x509_lu.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_obj.c b/thirdparty/openssl/crypto/x509/x509_obj.c index 3de3ac7204..3de3ac7204 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_obj.c +++ b/thirdparty/openssl/crypto/x509/x509_obj.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_r2x.c b/thirdparty/openssl/crypto/x509/x509_r2x.c index 0ff439c99f..0ff439c99f 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_r2x.c +++ b/thirdparty/openssl/crypto/x509/x509_r2x.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_req.c b/thirdparty/openssl/crypto/x509/x509_req.c index 01795f4b3f..01795f4b3f 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_req.c +++ b/thirdparty/openssl/crypto/x509/x509_req.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_set.c b/thirdparty/openssl/crypto/x509/x509_set.c index 5b802bd6c7..5b802bd6c7 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_set.c +++ b/thirdparty/openssl/crypto/x509/x509_set.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_trs.c b/thirdparty/openssl/crypto/x509/x509_trs.c index 11e0763403..11e0763403 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_trs.c +++ b/thirdparty/openssl/crypto/x509/x509_trs.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_txt.c b/thirdparty/openssl/crypto/x509/x509_txt.c index 3d46d3ff83..3d46d3ff83 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_txt.c +++ b/thirdparty/openssl/crypto/x509/x509_txt.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_v3.c b/thirdparty/openssl/crypto/x509/x509_v3.c index 4a03445a64..4a03445a64 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_v3.c +++ b/thirdparty/openssl/crypto/x509/x509_v3.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_vfy.c b/thirdparty/openssl/crypto/x509/x509_vfy.c index 4d34dbac93..4d34dbac93 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_vfy.c +++ b/thirdparty/openssl/crypto/x509/x509_vfy.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509_vpm.c b/thirdparty/openssl/crypto/x509/x509_vpm.c index 1ac15a881a..1ac15a881a 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509_vpm.c +++ b/thirdparty/openssl/crypto/x509/x509_vpm.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509cset.c b/thirdparty/openssl/crypto/x509/x509cset.c index 24ca35b58b..24ca35b58b 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509cset.c +++ b/thirdparty/openssl/crypto/x509/x509cset.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509name.c b/thirdparty/openssl/crypto/x509/x509name.c index 6ea601f962..6ea601f962 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509name.c +++ b/thirdparty/openssl/crypto/x509/x509name.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509rset.c b/thirdparty/openssl/crypto/x509/x509rset.c index 80e273e642..80e273e642 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509rset.c +++ b/thirdparty/openssl/crypto/x509/x509rset.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509spki.c b/thirdparty/openssl/crypto/x509/x509spki.c index 2df84ead9e..2df84ead9e 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509spki.c +++ b/thirdparty/openssl/crypto/x509/x509spki.c diff --git a/drivers/builtin_openssl2/crypto/x509/x509type.c b/thirdparty/openssl/crypto/x509/x509type.c index 9219f753bf..9219f753bf 100644 --- a/drivers/builtin_openssl2/crypto/x509/x509type.c +++ b/thirdparty/openssl/crypto/x509/x509type.c diff --git a/drivers/builtin_openssl2/crypto/x509/x_all.c b/thirdparty/openssl/crypto/x509/x_all.c index 0f26c546d8..0f26c546d8 100644 --- a/drivers/builtin_openssl2/crypto/x509/x_all.c +++ b/thirdparty/openssl/crypto/x509/x_all.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/ext_dat.h b/thirdparty/openssl/crypto/x509v3/ext_dat.h index c3a6fce752..c3a6fce752 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/ext_dat.h +++ b/thirdparty/openssl/crypto/x509v3/ext_dat.h diff --git a/drivers/builtin_openssl2/crypto/x509v3/pcy_cache.c b/thirdparty/openssl/crypto/x509v3/pcy_cache.c index c8f41f24bc..c8f41f24bc 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/pcy_cache.c +++ b/thirdparty/openssl/crypto/x509v3/pcy_cache.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/pcy_data.c b/thirdparty/openssl/crypto/x509v3/pcy_data.c index 90e9970e46..90e9970e46 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/pcy_data.c +++ b/thirdparty/openssl/crypto/x509v3/pcy_data.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/pcy_int.h b/thirdparty/openssl/crypto/x509v3/pcy_int.h index b5075f9edb..b5075f9edb 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/pcy_int.h +++ b/thirdparty/openssl/crypto/x509v3/pcy_int.h diff --git a/drivers/builtin_openssl2/crypto/x509v3/pcy_lib.c b/thirdparty/openssl/crypto/x509v3/pcy_lib.c index dbb29835fa..dbb29835fa 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/pcy_lib.c +++ b/thirdparty/openssl/crypto/x509v3/pcy_lib.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/pcy_map.c b/thirdparty/openssl/crypto/x509v3/pcy_map.c index b99eb91cf7..b99eb91cf7 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/pcy_map.c +++ b/thirdparty/openssl/crypto/x509v3/pcy_map.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/pcy_node.c b/thirdparty/openssl/crypto/x509v3/pcy_node.c index d6c917650a..d6c917650a 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/pcy_node.c +++ b/thirdparty/openssl/crypto/x509v3/pcy_node.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/pcy_tree.c b/thirdparty/openssl/crypto/x509v3/pcy_tree.c index 09b8691c86..09b8691c86 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/pcy_tree.c +++ b/thirdparty/openssl/crypto/x509v3/pcy_tree.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_addr.c b/thirdparty/openssl/crypto/x509v3/v3_addr.c index 94cfed0509..94cfed0509 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_addr.c +++ b/thirdparty/openssl/crypto/x509v3/v3_addr.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_akey.c b/thirdparty/openssl/crypto/x509v3/v3_akey.c index e920270e16..e920270e16 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_akey.c +++ b/thirdparty/openssl/crypto/x509v3/v3_akey.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_akeya.c b/thirdparty/openssl/crypto/x509v3/v3_akeya.c index 2cc85b7623..2cc85b7623 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_akeya.c +++ b/thirdparty/openssl/crypto/x509v3/v3_akeya.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_alt.c b/thirdparty/openssl/crypto/x509v3/v3_alt.c index 22ec202846..22ec202846 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_alt.c +++ b/thirdparty/openssl/crypto/x509v3/v3_alt.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_asid.c b/thirdparty/openssl/crypto/x509v3/v3_asid.c index 2a32c9d0c9..2a32c9d0c9 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_asid.c +++ b/thirdparty/openssl/crypto/x509v3/v3_asid.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_bcons.c b/thirdparty/openssl/crypto/x509v3/v3_bcons.c index dc00b9cb05..dc00b9cb05 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_bcons.c +++ b/thirdparty/openssl/crypto/x509v3/v3_bcons.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_bitst.c b/thirdparty/openssl/crypto/x509v3/v3_bitst.c index b7bb3b556f..b7bb3b556f 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_bitst.c +++ b/thirdparty/openssl/crypto/x509v3/v3_bitst.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_conf.c b/thirdparty/openssl/crypto/x509v3/v3_conf.c index eeff8bd185..eeff8bd185 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_conf.c +++ b/thirdparty/openssl/crypto/x509v3/v3_conf.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_cpols.c b/thirdparty/openssl/crypto/x509v3/v3_cpols.c index d97f6226b9..d97f6226b9 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_cpols.c +++ b/thirdparty/openssl/crypto/x509v3/v3_cpols.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_crld.c b/thirdparty/openssl/crypto/x509v3/v3_crld.c index d3e1d1b057..d3e1d1b057 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_crld.c +++ b/thirdparty/openssl/crypto/x509v3/v3_crld.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_enum.c b/thirdparty/openssl/crypto/x509v3/v3_enum.c index 7678664fc3..7678664fc3 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_enum.c +++ b/thirdparty/openssl/crypto/x509v3/v3_enum.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_extku.c b/thirdparty/openssl/crypto/x509v3/v3_extku.c index 6092c2e4bd..6092c2e4bd 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_extku.c +++ b/thirdparty/openssl/crypto/x509v3/v3_extku.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_genn.c b/thirdparty/openssl/crypto/x509v3/v3_genn.c index 7f40bfabe0..7f40bfabe0 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_genn.c +++ b/thirdparty/openssl/crypto/x509v3/v3_genn.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_ia5.c b/thirdparty/openssl/crypto/x509v3/v3_ia5.c index c170a55ff4..c170a55ff4 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_ia5.c +++ b/thirdparty/openssl/crypto/x509v3/v3_ia5.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_info.c b/thirdparty/openssl/crypto/x509v3/v3_info.c index e052a34b94..e052a34b94 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_info.c +++ b/thirdparty/openssl/crypto/x509v3/v3_info.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_int.c b/thirdparty/openssl/crypto/x509v3/v3_int.c index 8bfdb37e7a..8bfdb37e7a 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_int.c +++ b/thirdparty/openssl/crypto/x509v3/v3_int.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_lib.c b/thirdparty/openssl/crypto/x509v3/v3_lib.c index 8350429aaf..8350429aaf 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_lib.c +++ b/thirdparty/openssl/crypto/x509v3/v3_lib.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_ncons.c b/thirdparty/openssl/crypto/x509v3/v3_ncons.c index 2855269668..2855269668 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_ncons.c +++ b/thirdparty/openssl/crypto/x509v3/v3_ncons.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_ocsp.c b/thirdparty/openssl/crypto/x509v3/v3_ocsp.c index b151eaccba..b151eaccba 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_ocsp.c +++ b/thirdparty/openssl/crypto/x509v3/v3_ocsp.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_pci.c b/thirdparty/openssl/crypto/x509v3/v3_pci.c index 34cad53cb5..34cad53cb5 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_pci.c +++ b/thirdparty/openssl/crypto/x509v3/v3_pci.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_pcia.c b/thirdparty/openssl/crypto/x509v3/v3_pcia.c index e53c82e8dc..e53c82e8dc 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_pcia.c +++ b/thirdparty/openssl/crypto/x509v3/v3_pcia.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_pcons.c b/thirdparty/openssl/crypto/x509v3/v3_pcons.c index cfccb97de6..cfccb97de6 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_pcons.c +++ b/thirdparty/openssl/crypto/x509v3/v3_pcons.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_pku.c b/thirdparty/openssl/crypto/x509v3/v3_pku.c index dd01c44169..dd01c44169 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_pku.c +++ b/thirdparty/openssl/crypto/x509v3/v3_pku.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_pmaps.c b/thirdparty/openssl/crypto/x509v3/v3_pmaps.c index a168343b82..a168343b82 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_pmaps.c +++ b/thirdparty/openssl/crypto/x509v3/v3_pmaps.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_prn.c b/thirdparty/openssl/crypto/x509v3/v3_prn.c index acc9c6d991..acc9c6d991 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_prn.c +++ b/thirdparty/openssl/crypto/x509v3/v3_prn.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_purp.c b/thirdparty/openssl/crypto/x509v3/v3_purp.c index 845be673b7..845be673b7 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_purp.c +++ b/thirdparty/openssl/crypto/x509v3/v3_purp.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_scts.c b/thirdparty/openssl/crypto/x509v3/v3_scts.c index 0b7c68180e..0b7c68180e 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_scts.c +++ b/thirdparty/openssl/crypto/x509v3/v3_scts.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_skey.c b/thirdparty/openssl/crypto/x509v3/v3_skey.c index 1cede04727..1cede04727 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_skey.c +++ b/thirdparty/openssl/crypto/x509v3/v3_skey.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_sxnet.c b/thirdparty/openssl/crypto/x509v3/v3_sxnet.c index a4e6a93e0b..a4e6a93e0b 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_sxnet.c +++ b/thirdparty/openssl/crypto/x509v3/v3_sxnet.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3_utl.c b/thirdparty/openssl/crypto/x509v3/v3_utl.c index 43b9cb9c58..43b9cb9c58 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3_utl.c +++ b/thirdparty/openssl/crypto/x509v3/v3_utl.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3conf.c b/thirdparty/openssl/crypto/x509v3/v3conf.c index 41aa266948..41aa266948 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3conf.c +++ b/thirdparty/openssl/crypto/x509v3/v3conf.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3err.c b/thirdparty/openssl/crypto/x509v3/v3err.c index bcc1be722e..bcc1be722e 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3err.c +++ b/thirdparty/openssl/crypto/x509v3/v3err.c diff --git a/drivers/builtin_openssl2/crypto/x509v3/v3prin.c b/thirdparty/openssl/crypto/x509v3/v3prin.c index cbc357079d..cbc357079d 100644 --- a/drivers/builtin_openssl2/crypto/x509v3/v3prin.c +++ b/thirdparty/openssl/crypto/x509v3/v3prin.c diff --git a/drivers/builtin_openssl2/e_os.h b/thirdparty/openssl/e_os.h index 1fa36c1719..1fa36c1719 100644 --- a/drivers/builtin_openssl2/e_os.h +++ b/thirdparty/openssl/e_os.h diff --git a/drivers/builtin_openssl2/openssl/aes.h b/thirdparty/openssl/openssl/aes.h index faa66c4914..faa66c4914 100644 --- a/drivers/builtin_openssl2/openssl/aes.h +++ b/thirdparty/openssl/openssl/aes.h diff --git a/drivers/builtin_openssl2/openssl/asn1.h b/thirdparty/openssl/openssl/asn1.h index 68e791fcdb..68e791fcdb 100644 --- a/drivers/builtin_openssl2/openssl/asn1.h +++ b/thirdparty/openssl/openssl/asn1.h diff --git a/drivers/builtin_openssl2/openssl/asn1_mac.h b/thirdparty/openssl/openssl/asn1_mac.h index abc6dc35ca..abc6dc35ca 100644 --- a/drivers/builtin_openssl2/openssl/asn1_mac.h +++ b/thirdparty/openssl/openssl/asn1_mac.h diff --git a/drivers/builtin_openssl2/openssl/asn1t.h b/thirdparty/openssl/openssl/asn1t.h index 99bc0eecf3..99bc0eecf3 100644 --- a/drivers/builtin_openssl2/openssl/asn1t.h +++ b/thirdparty/openssl/openssl/asn1t.h diff --git a/drivers/builtin_openssl2/openssl/bio.h b/thirdparty/openssl/openssl/bio.h index 6790aed28e..6790aed28e 100644 --- a/drivers/builtin_openssl2/openssl/bio.h +++ b/thirdparty/openssl/openssl/bio.h diff --git a/drivers/builtin_openssl2/openssl/blowfish.h b/thirdparty/openssl/openssl/blowfish.h index 832930272c..832930272c 100644 --- a/drivers/builtin_openssl2/openssl/blowfish.h +++ b/thirdparty/openssl/openssl/blowfish.h diff --git a/drivers/builtin_openssl2/openssl/bn.h b/thirdparty/openssl/openssl/bn.h index 86264ae631..86264ae631 100644 --- a/drivers/builtin_openssl2/openssl/bn.h +++ b/thirdparty/openssl/openssl/bn.h diff --git a/drivers/builtin_openssl2/openssl/buffer.h b/thirdparty/openssl/openssl/buffer.h index efd240a5f9..efd240a5f9 100644 --- a/drivers/builtin_openssl2/openssl/buffer.h +++ b/thirdparty/openssl/openssl/buffer.h diff --git a/drivers/builtin_openssl2/openssl/camellia.h b/thirdparty/openssl/openssl/camellia.h index 45e8d25b1d..45e8d25b1d 100644 --- a/drivers/builtin_openssl2/openssl/camellia.h +++ b/thirdparty/openssl/openssl/camellia.h diff --git a/drivers/builtin_openssl2/openssl/cast.h b/thirdparty/openssl/openssl/cast.h index 0003ec9c7c..0003ec9c7c 100644 --- a/drivers/builtin_openssl2/openssl/cast.h +++ b/thirdparty/openssl/openssl/cast.h diff --git a/drivers/builtin_openssl2/openssl/cmac.h b/thirdparty/openssl/openssl/cmac.h index 175be8348a..175be8348a 100644 --- a/drivers/builtin_openssl2/openssl/cmac.h +++ b/thirdparty/openssl/openssl/cmac.h diff --git a/drivers/builtin_openssl2/openssl/cms.h b/thirdparty/openssl/openssl/cms.h index e6c7f964bf..e6c7f964bf 100644 --- a/drivers/builtin_openssl2/openssl/cms.h +++ b/thirdparty/openssl/openssl/cms.h diff --git a/drivers/builtin_openssl2/openssl/comp.h b/thirdparty/openssl/openssl/comp.h index 60a073404e..60a073404e 100644 --- a/drivers/builtin_openssl2/openssl/comp.h +++ b/thirdparty/openssl/openssl/comp.h diff --git a/drivers/builtin_openssl2/openssl/conf.h b/thirdparty/openssl/openssl/conf.h index 8d926d5d82..8d926d5d82 100644 --- a/drivers/builtin_openssl2/openssl/conf.h +++ b/thirdparty/openssl/openssl/conf.h diff --git a/drivers/builtin_openssl2/openssl/conf_api.h b/thirdparty/openssl/openssl/conf_api.h index e478f7df4b..e478f7df4b 100644 --- a/drivers/builtin_openssl2/openssl/conf_api.h +++ b/thirdparty/openssl/openssl/conf_api.h diff --git a/drivers/builtin_openssl2/openssl/crypto.h b/thirdparty/openssl/openssl/crypto.h index 6c644ce12a..6c644ce12a 100644 --- a/drivers/builtin_openssl2/openssl/crypto.h +++ b/thirdparty/openssl/openssl/crypto.h diff --git a/drivers/builtin_openssl2/openssl/des.h b/thirdparty/openssl/openssl/des.h index 1b40144e1b..1b40144e1b 100644 --- a/drivers/builtin_openssl2/openssl/des.h +++ b/thirdparty/openssl/openssl/des.h diff --git a/drivers/builtin_openssl2/openssl/des_old.h b/thirdparty/openssl/openssl/des_old.h index ee7607a241..ee7607a241 100644 --- a/drivers/builtin_openssl2/openssl/des_old.h +++ b/thirdparty/openssl/openssl/des_old.h diff --git a/drivers/builtin_openssl2/openssl/dh.h b/thirdparty/openssl/openssl/dh.h index a5bd9016aa..a5bd9016aa 100644 --- a/drivers/builtin_openssl2/openssl/dh.h +++ b/thirdparty/openssl/openssl/dh.h diff --git a/drivers/builtin_openssl2/openssl/dsa.h b/thirdparty/openssl/openssl/dsa.h index 545358fd02..545358fd02 100644 --- a/drivers/builtin_openssl2/openssl/dsa.h +++ b/thirdparty/openssl/openssl/dsa.h diff --git a/drivers/builtin_openssl2/openssl/dso.h b/thirdparty/openssl/openssl/dso.h index c9013f5cea..c9013f5cea 100644 --- a/drivers/builtin_openssl2/openssl/dso.h +++ b/thirdparty/openssl/openssl/dso.h diff --git a/thirdparty/openssl/openssl/dtls1.h b/thirdparty/openssl/openssl/dtls1.h new file mode 100644 index 0000000000..a58aca248d --- /dev/null +++ b/thirdparty/openssl/openssl/dtls1.h @@ -0,0 +1,278 @@ +/* ssl/dtls1.h */ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * 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. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF 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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_DTLS1_H +# define HEADER_DTLS1_H + +# include <openssl/buffer.h> +# include <openssl/pqueue.h> +# ifdef OPENSSL_SYS_VMS +# include <resource.h> +# include <sys/timeb.h> +# endif +# ifdef OPENSSL_SYS_WIN32 +/* Needed for struct timeval */ +# include <winsock.h> +#ifdef X509_NAME +#undef X509_NAME +#endif +# elif defined(OPENSSL_SYS_NETWARE) && !defined(_WINSOCK2API_) +# include <sys/timeval.h> +# else +# if defined(OPENSSL_SYS_VXWORKS) +# include <sys/times.h> +# else +# include <sys/time.h> +# endif +# endif +#ifdef WINRT_ENABLED +#include <winsock2.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +# define DTLS1_VERSION 0xFEFF +# define DTLS1_2_VERSION 0xFEFD +# define DTLS_MAX_VERSION DTLS1_2_VERSION +# define DTLS1_VERSION_MAJOR 0xFE + +# define DTLS1_BAD_VER 0x0100 + +/* Special value for method supporting multiple versions */ +# define DTLS_ANY_VERSION 0x1FFFF + +# if 0 +/* this alert description is not specified anywhere... */ +# define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE 110 +# endif + +/* lengths of messages */ +# define DTLS1_COOKIE_LENGTH 256 + +# define DTLS1_RT_HEADER_LENGTH 13 + +# define DTLS1_HM_HEADER_LENGTH 12 + +# define DTLS1_HM_BAD_FRAGMENT -2 +# define DTLS1_HM_FRAGMENT_RETRY -3 + +# define DTLS1_CCS_HEADER_LENGTH 1 + +# ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE +# define DTLS1_AL_HEADER_LENGTH 7 +# else +# define DTLS1_AL_HEADER_LENGTH 2 +# endif + +# ifndef OPENSSL_NO_SSL_INTERN + +# ifndef OPENSSL_NO_SCTP +# define DTLS1_SCTP_AUTH_LABEL "EXPORTER_DTLS_OVER_SCTP" +# endif + +/* Max MTU overhead we know about so far is 40 for IPv6 + 8 for UDP */ +# define DTLS1_MAX_MTU_OVERHEAD 48 + +typedef struct dtls1_bitmap_st { + unsigned long map; /* track 32 packets on 32-bit systems and 64 + * - on 64-bit systems */ + unsigned char max_seq_num[8]; /* max record number seen so far, 64-bit + * value in big-endian encoding */ +} DTLS1_BITMAP; + +struct dtls1_retransmit_state { + EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */ + EVP_MD_CTX *write_hash; /* used for mac generation */ +# ifndef OPENSSL_NO_COMP + COMP_CTX *compress; /* compression */ +# else + char *compress; +# endif + SSL_SESSION *session; + unsigned short epoch; +}; + +struct hm_header_st { + unsigned char type; + unsigned long msg_len; + unsigned short seq; + unsigned long frag_off; + unsigned long frag_len; + unsigned int is_ccs; + struct dtls1_retransmit_state saved_retransmit_state; +}; + +struct ccs_header_st { + unsigned char type; + unsigned short seq; +}; + +struct dtls1_timeout_st { + /* Number of read timeouts so far */ + unsigned int read_timeouts; + /* Number of write timeouts so far */ + unsigned int write_timeouts; + /* Number of alerts received so far */ + unsigned int num_alerts; +}; + +typedef struct record_pqueue_st { + unsigned short epoch; + pqueue q; +} record_pqueue; + +typedef struct hm_fragment_st { + struct hm_header_st msg_header; + unsigned char *fragment; + unsigned char *reassembly; +} hm_fragment; + +typedef struct dtls1_state_st { + unsigned int send_cookie; + unsigned char cookie[DTLS1_COOKIE_LENGTH]; + unsigned char rcvd_cookie[DTLS1_COOKIE_LENGTH]; + unsigned int cookie_len; + /* + * The current data and handshake epoch. This is initially + * undefined, and starts at zero once the initial handshake is + * completed + */ + unsigned short r_epoch; + unsigned short w_epoch; + /* records being received in the current epoch */ + DTLS1_BITMAP bitmap; + /* renegotiation starts a new set of sequence numbers */ + DTLS1_BITMAP next_bitmap; + /* handshake message numbers */ + unsigned short handshake_write_seq; + unsigned short next_handshake_write_seq; + unsigned short handshake_read_seq; + /* save last sequence number for retransmissions */ + unsigned char last_write_sequence[8]; + /* Received handshake records (processed and unprocessed) */ + record_pqueue unprocessed_rcds; + record_pqueue processed_rcds; + /* Buffered handshake messages */ + pqueue buffered_messages; + /* Buffered (sent) handshake records */ + pqueue sent_messages; + /* + * Buffered application records. Only for records between CCS and + * Finished to prevent either protocol violation or unnecessary message + * loss. + */ + record_pqueue buffered_app_data; + /* Is set when listening for new connections with dtls1_listen() */ + unsigned int listen; + unsigned int link_mtu; /* max on-the-wire DTLS packet size */ + unsigned int mtu; /* max DTLS packet size */ + struct hm_header_st w_msg_hdr; + struct hm_header_st r_msg_hdr; + struct dtls1_timeout_st timeout; + /* + * Indicates when the last handshake msg or heartbeat sent will timeout + */ + struct timeval next_timeout; + /* Timeout duration */ + unsigned short timeout_duration; + /* + * storage for Alert/Handshake protocol data received but not yet + * processed by ssl3_read_bytes: + */ + unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH]; + unsigned int alert_fragment_len; + unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH]; + unsigned int handshake_fragment_len; + unsigned int retransmitting; + /* + * Set when the handshake is ready to process peer's ChangeCipherSpec message. + * Cleared after the message has been processed. + */ + unsigned int change_cipher_spec_ok; +# ifndef OPENSSL_NO_SCTP + /* used when SSL_ST_XX_FLUSH is entered */ + int next_state; + int shutdown_received; +# endif +} DTLS1_STATE; + +typedef struct dtls1_record_data_st { + unsigned char *packet; + unsigned int packet_length; + SSL3_BUFFER rbuf; + SSL3_RECORD rrec; +# ifndef OPENSSL_NO_SCTP + struct bio_dgram_sctp_rcvinfo recordinfo; +# endif +} DTLS1_RECORD_DATA; + +# endif + +/* Timeout multipliers (timeout slice is defined in apps/timeouts.h */ +# define DTLS1_TMO_READ_COUNT 2 +# define DTLS1_TMO_WRITE_COUNT 2 + +# define DTLS1_TMO_ALERT_COUNT 12 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/drivers/builtin_openssl2/openssl/e_os2.h b/thirdparty/openssl/openssl/e_os2.h index 7be9989ac3..7be9989ac3 100644 --- a/drivers/builtin_openssl2/openssl/e_os2.h +++ b/thirdparty/openssl/openssl/e_os2.h diff --git a/drivers/builtin_openssl2/openssl/ebcdic.h b/thirdparty/openssl/openssl/ebcdic.h index 4cbdfeb7ae..4cbdfeb7ae 100644 --- a/drivers/builtin_openssl2/openssl/ebcdic.h +++ b/thirdparty/openssl/openssl/ebcdic.h diff --git a/drivers/builtin_openssl2/openssl/ec.h b/thirdparty/openssl/openssl/ec.h index 81e6faf6c5..81e6faf6c5 100644 --- a/drivers/builtin_openssl2/openssl/ec.h +++ b/thirdparty/openssl/openssl/ec.h diff --git a/drivers/builtin_openssl2/openssl/ecdh.h b/thirdparty/openssl/openssl/ecdh.h index 25348b30fe..25348b30fe 100644 --- a/drivers/builtin_openssl2/openssl/ecdh.h +++ b/thirdparty/openssl/openssl/ecdh.h diff --git a/drivers/builtin_openssl2/openssl/ecdsa.h b/thirdparty/openssl/openssl/ecdsa.h index a6f0930f82..a6f0930f82 100644 --- a/drivers/builtin_openssl2/openssl/ecdsa.h +++ b/thirdparty/openssl/openssl/ecdsa.h diff --git a/drivers/builtin_openssl2/openssl/engine.h b/thirdparty/openssl/openssl/engine.h index bd7b591447..bd7b591447 100644 --- a/drivers/builtin_openssl2/openssl/engine.h +++ b/thirdparty/openssl/openssl/engine.h diff --git a/drivers/builtin_openssl2/openssl/err.h b/thirdparty/openssl/openssl/err.h index 585aa8ba3d..585aa8ba3d 100644 --- a/drivers/builtin_openssl2/openssl/err.h +++ b/thirdparty/openssl/openssl/err.h diff --git a/drivers/builtin_openssl2/openssl/evp.h b/thirdparty/openssl/openssl/evp.h index 39ab7937d2..39ab7937d2 100644 --- a/drivers/builtin_openssl2/openssl/evp.h +++ b/thirdparty/openssl/openssl/evp.h diff --git a/drivers/builtin_openssl2/openssl/hmac.h b/thirdparty/openssl/openssl/hmac.h index b8b55cda7d..b8b55cda7d 100644 --- a/drivers/builtin_openssl2/openssl/hmac.h +++ b/thirdparty/openssl/openssl/hmac.h diff --git a/drivers/builtin_openssl2/openssl/idea.h b/thirdparty/openssl/openssl/idea.h index 6075984039..6075984039 100644 --- a/drivers/builtin_openssl2/openssl/idea.h +++ b/thirdparty/openssl/openssl/idea.h diff --git a/drivers/builtin_openssl2/openssl/krb5_asn.h b/thirdparty/openssl/openssl/krb5_asn.h index 9cf5a26dd8..9cf5a26dd8 100644 --- a/drivers/builtin_openssl2/openssl/krb5_asn.h +++ b/thirdparty/openssl/openssl/krb5_asn.h diff --git a/drivers/builtin_openssl2/openssl/kssl.h b/thirdparty/openssl/openssl/kssl.h index ae8a51f472..ae8a51f472 100644 --- a/drivers/builtin_openssl2/openssl/kssl.h +++ b/thirdparty/openssl/openssl/kssl.h diff --git a/drivers/builtin_openssl2/openssl/lhash.h b/thirdparty/openssl/openssl/lhash.h index b6c328bffb..b6c328bffb 100644 --- a/drivers/builtin_openssl2/openssl/lhash.h +++ b/thirdparty/openssl/openssl/lhash.h diff --git a/drivers/builtin_openssl2/openssl/md4.h b/thirdparty/openssl/openssl/md4.h index 11fd71295b..11fd71295b 100644 --- a/drivers/builtin_openssl2/openssl/md4.h +++ b/thirdparty/openssl/openssl/md4.h diff --git a/drivers/builtin_openssl2/openssl/md5.h b/thirdparty/openssl/openssl/md5.h index 300d3f3463..300d3f3463 100644 --- a/drivers/builtin_openssl2/openssl/md5.h +++ b/thirdparty/openssl/openssl/md5.h diff --git a/drivers/builtin_openssl2/openssl/mdc2.h b/thirdparty/openssl/openssl/mdc2.h index 7efe53bc29..7efe53bc29 100644 --- a/drivers/builtin_openssl2/openssl/mdc2.h +++ b/thirdparty/openssl/openssl/mdc2.h diff --git a/drivers/builtin_openssl2/openssl/modes.h b/thirdparty/openssl/openssl/modes.h index fd488499a0..fd488499a0 100644 --- a/drivers/builtin_openssl2/openssl/modes.h +++ b/thirdparty/openssl/openssl/modes.h diff --git a/drivers/builtin_openssl2/openssl/obj_mac.h b/thirdparty/openssl/openssl/obj_mac.h index 779c309b86..779c309b86 100644 --- a/drivers/builtin_openssl2/openssl/obj_mac.h +++ b/thirdparty/openssl/openssl/obj_mac.h diff --git a/drivers/builtin_openssl2/openssl/objects.h b/thirdparty/openssl/openssl/objects.h index b8dafa89ce..b8dafa89ce 100644 --- a/drivers/builtin_openssl2/openssl/objects.h +++ b/thirdparty/openssl/openssl/objects.h diff --git a/drivers/builtin_openssl2/openssl/ocsp.h b/thirdparty/openssl/openssl/ocsp.h index ca2ee76dce..ca2ee76dce 100644 --- a/drivers/builtin_openssl2/openssl/ocsp.h +++ b/thirdparty/openssl/openssl/ocsp.h diff --git a/drivers/builtin_openssl2/openssl/opensslconf.h b/thirdparty/openssl/openssl/opensslconf.h index c86bb60b94..c86bb60b94 100644 --- a/drivers/builtin_openssl2/openssl/opensslconf.h +++ b/thirdparty/openssl/openssl/opensslconf.h diff --git a/drivers/builtin_openssl2/openssl/opensslv.h b/thirdparty/openssl/openssl/opensslv.h index 13fe440231..13fe440231 100644 --- a/drivers/builtin_openssl2/openssl/opensslv.h +++ b/thirdparty/openssl/openssl/opensslv.h diff --git a/drivers/builtin_openssl2/openssl/ossl_typ.h b/thirdparty/openssl/openssl/ossl_typ.h index 9144ea2cf6..9144ea2cf6 100644 --- a/drivers/builtin_openssl2/openssl/ossl_typ.h +++ b/thirdparty/openssl/openssl/ossl_typ.h diff --git a/drivers/builtin_openssl2/openssl/pem.h b/thirdparty/openssl/openssl/pem.h index d3b23fc997..d3b23fc997 100644 --- a/drivers/builtin_openssl2/openssl/pem.h +++ b/thirdparty/openssl/openssl/pem.h diff --git a/drivers/builtin_openssl2/openssl/pem2.h b/thirdparty/openssl/openssl/pem2.h index 84897d5ec3..84897d5ec3 100644 --- a/drivers/builtin_openssl2/openssl/pem2.h +++ b/thirdparty/openssl/openssl/pem2.h diff --git a/drivers/builtin_openssl2/openssl/pkcs12.h b/thirdparty/openssl/openssl/pkcs12.h index a39adf5eb5..a39adf5eb5 100644 --- a/drivers/builtin_openssl2/openssl/pkcs12.h +++ b/thirdparty/openssl/openssl/pkcs12.h diff --git a/drivers/builtin_openssl2/openssl/pkcs7.h b/thirdparty/openssl/openssl/pkcs7.h index b51b3863eb..b51b3863eb 100644 --- a/drivers/builtin_openssl2/openssl/pkcs7.h +++ b/thirdparty/openssl/openssl/pkcs7.h diff --git a/drivers/builtin_openssl2/openssl/pqueue.h b/thirdparty/openssl/openssl/pqueue.h index d40d9c7d85..d40d9c7d85 100644 --- a/drivers/builtin_openssl2/openssl/pqueue.h +++ b/thirdparty/openssl/openssl/pqueue.h diff --git a/drivers/builtin_openssl2/openssl/rand.h b/thirdparty/openssl/openssl/rand.h index 66068834eb..66068834eb 100644 --- a/drivers/builtin_openssl2/openssl/rand.h +++ b/thirdparty/openssl/openssl/rand.h diff --git a/drivers/builtin_openssl2/openssl/rc2.h b/thirdparty/openssl/openssl/rc2.h index 29d02d7322..29d02d7322 100644 --- a/drivers/builtin_openssl2/openssl/rc2.h +++ b/thirdparty/openssl/openssl/rc2.h diff --git a/drivers/builtin_openssl2/openssl/rc4.h b/thirdparty/openssl/openssl/rc4.h index 39162b1648..39162b1648 100644 --- a/drivers/builtin_openssl2/openssl/rc4.h +++ b/thirdparty/openssl/openssl/rc4.h diff --git a/drivers/builtin_openssl2/openssl/ripemd.h b/thirdparty/openssl/openssl/ripemd.h index b88ef25e72..b88ef25e72 100644 --- a/drivers/builtin_openssl2/openssl/ripemd.h +++ b/thirdparty/openssl/openssl/ripemd.h diff --git a/drivers/builtin_openssl2/openssl/rsa.h b/thirdparty/openssl/openssl/rsa.h index d2ee37406e..d2ee37406e 100644 --- a/drivers/builtin_openssl2/openssl/rsa.h +++ b/thirdparty/openssl/openssl/rsa.h diff --git a/drivers/builtin_openssl2/openssl/safestack.h b/thirdparty/openssl/openssl/safestack.h index 1d4f87eab3..1d4f87eab3 100644 --- a/drivers/builtin_openssl2/openssl/safestack.h +++ b/thirdparty/openssl/openssl/safestack.h diff --git a/drivers/builtin_openssl2/openssl/seed.h b/thirdparty/openssl/openssl/seed.h index 8cbf0d9281..8cbf0d9281 100644 --- a/drivers/builtin_openssl2/openssl/seed.h +++ b/thirdparty/openssl/openssl/seed.h diff --git a/drivers/builtin_openssl2/openssl/sha.h b/thirdparty/openssl/openssl/sha.h index e5169e4fee..e5169e4fee 100644 --- a/drivers/builtin_openssl2/openssl/sha.h +++ b/thirdparty/openssl/openssl/sha.h diff --git a/drivers/builtin_openssl2/openssl/srp.h b/thirdparty/openssl/openssl/srp.h index 028892a1ff..028892a1ff 100644 --- a/drivers/builtin_openssl2/openssl/srp.h +++ b/thirdparty/openssl/openssl/srp.h diff --git a/drivers/builtin_openssl2/openssl/srtp.h b/thirdparty/openssl/openssl/srtp.h index 2279c32b89..2279c32b89 100644 --- a/drivers/builtin_openssl2/openssl/srtp.h +++ b/thirdparty/openssl/openssl/srtp.h diff --git a/drivers/builtin_openssl2/openssl/ssl.h b/thirdparty/openssl/openssl/ssl.h index 5ef56faa50..5ef56faa50 100644 --- a/drivers/builtin_openssl2/openssl/ssl.h +++ b/thirdparty/openssl/openssl/ssl.h diff --git a/drivers/builtin_openssl2/openssl/ssl2.h b/thirdparty/openssl/openssl/ssl2.h index 03c7dd8cac..03c7dd8cac 100644 --- a/drivers/builtin_openssl2/openssl/ssl2.h +++ b/thirdparty/openssl/openssl/ssl2.h diff --git a/drivers/builtin_openssl2/openssl/ssl23.h b/thirdparty/openssl/openssl/ssl23.h index 9de4685af9..9de4685af9 100644 --- a/drivers/builtin_openssl2/openssl/ssl23.h +++ b/thirdparty/openssl/openssl/ssl23.h diff --git a/drivers/builtin_openssl2/openssl/ssl3.h b/thirdparty/openssl/openssl/ssl3.h index e681d50a9e..e681d50a9e 100644 --- a/drivers/builtin_openssl2/openssl/ssl3.h +++ b/thirdparty/openssl/openssl/ssl3.h diff --git a/drivers/builtin_openssl2/openssl/stack.h b/thirdparty/openssl/openssl/stack.h index eb07216659..eb07216659 100644 --- a/drivers/builtin_openssl2/openssl/stack.h +++ b/thirdparty/openssl/openssl/stack.h diff --git a/drivers/builtin_openssl2/openssl/symhacks.h b/thirdparty/openssl/openssl/symhacks.h index 239fa4fb1b..239fa4fb1b 100644 --- a/drivers/builtin_openssl2/openssl/symhacks.h +++ b/thirdparty/openssl/openssl/symhacks.h diff --git a/drivers/builtin_openssl2/openssl/tls1.h b/thirdparty/openssl/openssl/tls1.h index 7e237d0631..7e237d0631 100644 --- a/drivers/builtin_openssl2/openssl/tls1.h +++ b/thirdparty/openssl/openssl/tls1.h diff --git a/drivers/builtin_openssl2/openssl/ts.h b/thirdparty/openssl/openssl/ts.h index 16eccbb38d..16eccbb38d 100644 --- a/drivers/builtin_openssl2/openssl/ts.h +++ b/thirdparty/openssl/openssl/ts.h diff --git a/drivers/builtin_openssl2/openssl/txt_db.h b/thirdparty/openssl/openssl/txt_db.h index 98e23a2003..98e23a2003 100644 --- a/drivers/builtin_openssl2/openssl/txt_db.h +++ b/thirdparty/openssl/openssl/txt_db.h diff --git a/drivers/builtin_openssl2/openssl/ui.h b/thirdparty/openssl/openssl/ui.h index 0dc16330b8..0dc16330b8 100644 --- a/drivers/builtin_openssl2/openssl/ui.h +++ b/thirdparty/openssl/openssl/ui.h diff --git a/drivers/builtin_openssl2/openssl/ui_compat.h b/thirdparty/openssl/openssl/ui_compat.h index bf541542c0..bf541542c0 100644 --- a/drivers/builtin_openssl2/openssl/ui_compat.h +++ b/thirdparty/openssl/openssl/ui_compat.h diff --git a/drivers/builtin_openssl2/openssl/whrlpool.h b/thirdparty/openssl/openssl/whrlpool.h index 73c749da81..73c749da81 100644 --- a/drivers/builtin_openssl2/openssl/whrlpool.h +++ b/thirdparty/openssl/openssl/whrlpool.h diff --git a/drivers/builtin_openssl2/openssl/x509.h b/thirdparty/openssl/openssl/x509.h index fc613ce635..fc613ce635 100644 --- a/drivers/builtin_openssl2/openssl/x509.h +++ b/thirdparty/openssl/openssl/x509.h diff --git a/drivers/builtin_openssl2/openssl/x509_vfy.h b/thirdparty/openssl/openssl/x509_vfy.h index 2663e1c0a3..2663e1c0a3 100644 --- a/drivers/builtin_openssl2/openssl/x509_vfy.h +++ b/thirdparty/openssl/openssl/x509_vfy.h diff --git a/drivers/builtin_openssl2/openssl/x509v3.h b/thirdparty/openssl/openssl/x509v3.h index f5c61560aa..f5c61560aa 100644 --- a/drivers/builtin_openssl2/openssl/x509v3.h +++ b/thirdparty/openssl/openssl/x509v3.h diff --git a/drivers/builtin_openssl2/ssl/bio_ssl.c b/thirdparty/openssl/ssl/bio_ssl.c index d2d4d2ea2d..d2d4d2ea2d 100644 --- a/drivers/builtin_openssl2/ssl/bio_ssl.c +++ b/thirdparty/openssl/ssl/bio_ssl.c diff --git a/drivers/builtin_openssl2/ssl/d1_both.c b/thirdparty/openssl/ssl/d1_both.c index 5d26c94926..5d26c94926 100644 --- a/drivers/builtin_openssl2/ssl/d1_both.c +++ b/thirdparty/openssl/ssl/d1_both.c diff --git a/drivers/builtin_openssl2/ssl/d1_clnt.c b/thirdparty/openssl/ssl/d1_clnt.c index 3ddfa7bca4..3ddfa7bca4 100644 --- a/drivers/builtin_openssl2/ssl/d1_clnt.c +++ b/thirdparty/openssl/ssl/d1_clnt.c diff --git a/drivers/builtin_openssl2/ssl/d1_lib.c b/thirdparty/openssl/ssl/d1_lib.c index ee78921ba8..ee78921ba8 100644 --- a/drivers/builtin_openssl2/ssl/d1_lib.c +++ b/thirdparty/openssl/ssl/d1_lib.c diff --git a/drivers/builtin_openssl2/ssl/d1_meth.c b/thirdparty/openssl/ssl/d1_meth.c index 899010e985..899010e985 100644 --- a/drivers/builtin_openssl2/ssl/d1_meth.c +++ b/thirdparty/openssl/ssl/d1_meth.c diff --git a/drivers/builtin_openssl2/ssl/d1_pkt.c b/thirdparty/openssl/ssl/d1_pkt.c index fe30ec7d00..fe30ec7d00 100644 --- a/drivers/builtin_openssl2/ssl/d1_pkt.c +++ b/thirdparty/openssl/ssl/d1_pkt.c diff --git a/drivers/builtin_openssl2/ssl/d1_srtp.c b/thirdparty/openssl/ssl/d1_srtp.c index 64d0634a38..64d0634a38 100644 --- a/drivers/builtin_openssl2/ssl/d1_srtp.c +++ b/thirdparty/openssl/ssl/d1_srtp.c diff --git a/drivers/builtin_openssl2/ssl/d1_srvr.c b/thirdparty/openssl/ssl/d1_srvr.c index e677d880f0..e677d880f0 100644 --- a/drivers/builtin_openssl2/ssl/d1_srvr.c +++ b/thirdparty/openssl/ssl/d1_srvr.c diff --git a/drivers/builtin_openssl2/ssl/install-ssl.com b/thirdparty/openssl/ssl/install-ssl.com index afe6967f85..afe6967f85 100755 --- a/drivers/builtin_openssl2/ssl/install-ssl.com +++ b/thirdparty/openssl/ssl/install-ssl.com diff --git a/drivers/builtin_openssl2/ssl/kssl.c b/thirdparty/openssl/ssl/kssl.c index f2839bdcd7..f2839bdcd7 100644 --- a/drivers/builtin_openssl2/ssl/kssl.c +++ b/thirdparty/openssl/ssl/kssl.c diff --git a/drivers/builtin_openssl2/ssl/kssl_lcl.h b/thirdparty/openssl/ssl/kssl_lcl.h index 8e6a6d69e9..8e6a6d69e9 100644 --- a/drivers/builtin_openssl2/ssl/kssl_lcl.h +++ b/thirdparty/openssl/ssl/kssl_lcl.h diff --git a/drivers/builtin_openssl2/ssl/s23_clnt.c b/thirdparty/openssl/ssl/s23_clnt.c index f782010c47..f782010c47 100644 --- a/drivers/builtin_openssl2/ssl/s23_clnt.c +++ b/thirdparty/openssl/ssl/s23_clnt.c diff --git a/drivers/builtin_openssl2/ssl/s23_lib.c b/thirdparty/openssl/ssl/s23_lib.c index 9056d39e83..9056d39e83 100644 --- a/drivers/builtin_openssl2/ssl/s23_lib.c +++ b/thirdparty/openssl/ssl/s23_lib.c diff --git a/drivers/builtin_openssl2/ssl/s23_meth.c b/thirdparty/openssl/ssl/s23_meth.c index eb76098792..eb76098792 100644 --- a/drivers/builtin_openssl2/ssl/s23_meth.c +++ b/thirdparty/openssl/ssl/s23_meth.c diff --git a/drivers/builtin_openssl2/ssl/s23_pkt.c b/thirdparty/openssl/ssl/s23_pkt.c index efc8647841..efc8647841 100644 --- a/drivers/builtin_openssl2/ssl/s23_pkt.c +++ b/thirdparty/openssl/ssl/s23_pkt.c diff --git a/drivers/builtin_openssl2/ssl/s23_srvr.c b/thirdparty/openssl/ssl/s23_srvr.c index 470bd3d94f..470bd3d94f 100644 --- a/drivers/builtin_openssl2/ssl/s23_srvr.c +++ b/thirdparty/openssl/ssl/s23_srvr.c diff --git a/drivers/builtin_openssl2/ssl/s2_clnt.c b/thirdparty/openssl/ssl/s2_clnt.c index 69da6b1421..69da6b1421 100644 --- a/drivers/builtin_openssl2/ssl/s2_clnt.c +++ b/thirdparty/openssl/ssl/s2_clnt.c diff --git a/drivers/builtin_openssl2/ssl/s2_enc.c b/thirdparty/openssl/ssl/s2_enc.c index 23eef72aa4..23eef72aa4 100644 --- a/drivers/builtin_openssl2/ssl/s2_enc.c +++ b/thirdparty/openssl/ssl/s2_enc.c diff --git a/drivers/builtin_openssl2/ssl/s2_lib.c b/thirdparty/openssl/ssl/s2_lib.c index 88e67f083a..88e67f083a 100644 --- a/drivers/builtin_openssl2/ssl/s2_lib.c +++ b/thirdparty/openssl/ssl/s2_lib.c diff --git a/drivers/builtin_openssl2/ssl/s2_meth.c b/thirdparty/openssl/ssl/s2_meth.c index 73885b7ecf..73885b7ecf 100644 --- a/drivers/builtin_openssl2/ssl/s2_meth.c +++ b/thirdparty/openssl/ssl/s2_meth.c diff --git a/drivers/builtin_openssl2/ssl/s2_pkt.c b/thirdparty/openssl/ssl/s2_pkt.c index 7a61888134..7a61888134 100644 --- a/drivers/builtin_openssl2/ssl/s2_pkt.c +++ b/thirdparty/openssl/ssl/s2_pkt.c diff --git a/drivers/builtin_openssl2/ssl/s2_srvr.c b/thirdparty/openssl/ssl/s2_srvr.c index 07e9df8282..07e9df8282 100644 --- a/drivers/builtin_openssl2/ssl/s2_srvr.c +++ b/thirdparty/openssl/ssl/s2_srvr.c diff --git a/drivers/builtin_openssl2/ssl/s3_both.c b/thirdparty/openssl/ssl/s3_both.c index 09d0661e81..09d0661e81 100644 --- a/drivers/builtin_openssl2/ssl/s3_both.c +++ b/thirdparty/openssl/ssl/s3_both.c diff --git a/drivers/builtin_openssl2/ssl/s3_cbc.c b/thirdparty/openssl/ssl/s3_cbc.c index 557622f513..557622f513 100644 --- a/drivers/builtin_openssl2/ssl/s3_cbc.c +++ b/thirdparty/openssl/ssl/s3_cbc.c diff --git a/drivers/builtin_openssl2/ssl/s3_clnt.c b/thirdparty/openssl/ssl/s3_clnt.c index 19dc8648b9..19dc8648b9 100644 --- a/drivers/builtin_openssl2/ssl/s3_clnt.c +++ b/thirdparty/openssl/ssl/s3_clnt.c diff --git a/drivers/builtin_openssl2/ssl/s3_enc.c b/thirdparty/openssl/ssl/s3_enc.c index 47a0ec9fe0..47a0ec9fe0 100644 --- a/drivers/builtin_openssl2/ssl/s3_enc.c +++ b/thirdparty/openssl/ssl/s3_enc.c diff --git a/drivers/builtin_openssl2/ssl/s3_lib.c b/thirdparty/openssl/ssl/s3_lib.c index 872e636af9..872e636af9 100644 --- a/drivers/builtin_openssl2/ssl/s3_lib.c +++ b/thirdparty/openssl/ssl/s3_lib.c diff --git a/drivers/builtin_openssl2/ssl/s3_meth.c b/thirdparty/openssl/ssl/s3_meth.c index e5a52993fc..e5a52993fc 100644 --- a/drivers/builtin_openssl2/ssl/s3_meth.c +++ b/thirdparty/openssl/ssl/s3_meth.c diff --git a/drivers/builtin_openssl2/ssl/s3_pkt.c b/thirdparty/openssl/ssl/s3_pkt.c index 379890237e..379890237e 100644 --- a/drivers/builtin_openssl2/ssl/s3_pkt.c +++ b/thirdparty/openssl/ssl/s3_pkt.c diff --git a/drivers/builtin_openssl2/ssl/s3_srvr.c b/thirdparty/openssl/ssl/s3_srvr.c index ab28702ee9..ab28702ee9 100644 --- a/drivers/builtin_openssl2/ssl/s3_srvr.c +++ b/thirdparty/openssl/ssl/s3_srvr.c diff --git a/drivers/builtin_openssl2/ssl/ssl-lib.com b/thirdparty/openssl/ssl/ssl-lib.com index 43fea17541..43fea17541 100644 --- a/drivers/builtin_openssl2/ssl/ssl-lib.com +++ b/thirdparty/openssl/ssl/ssl-lib.com diff --git a/drivers/builtin_openssl2/ssl/ssl_algs.c b/thirdparty/openssl/ssl/ssl_algs.c index e6f515ff62..e6f515ff62 100644 --- a/drivers/builtin_openssl2/ssl/ssl_algs.c +++ b/thirdparty/openssl/ssl/ssl_algs.c diff --git a/drivers/builtin_openssl2/ssl/ssl_asn1.c b/thirdparty/openssl/ssl/ssl_asn1.c index 35cc27c5e9..35cc27c5e9 100644 --- a/drivers/builtin_openssl2/ssl/ssl_asn1.c +++ b/thirdparty/openssl/ssl/ssl_asn1.c diff --git a/drivers/builtin_openssl2/ssl/ssl_cert.c b/thirdparty/openssl/ssl/ssl_cert.c index f48ebaecc0..f48ebaecc0 100644 --- a/drivers/builtin_openssl2/ssl/ssl_cert.c +++ b/thirdparty/openssl/ssl/ssl_cert.c diff --git a/drivers/builtin_openssl2/ssl/ssl_ciph.c b/thirdparty/openssl/ssl/ssl_ciph.c index 302464e643..302464e643 100644 --- a/drivers/builtin_openssl2/ssl/ssl_ciph.c +++ b/thirdparty/openssl/ssl/ssl_ciph.c diff --git a/drivers/builtin_openssl2/ssl/ssl_conf.c b/thirdparty/openssl/ssl/ssl_conf.c index 8d3709d2b6..8d3709d2b6 100644 --- a/drivers/builtin_openssl2/ssl/ssl_conf.c +++ b/thirdparty/openssl/ssl/ssl_conf.c diff --git a/drivers/builtin_openssl2/ssl/ssl_err.c b/thirdparty/openssl/ssl/ssl_err.c index 704088dc46..704088dc46 100644 --- a/drivers/builtin_openssl2/ssl/ssl_err.c +++ b/thirdparty/openssl/ssl/ssl_err.c diff --git a/drivers/builtin_openssl2/ssl/ssl_err2.c b/thirdparty/openssl/ssl/ssl_err2.c index 14e48221f4..14e48221f4 100644 --- a/drivers/builtin_openssl2/ssl/ssl_err2.c +++ b/thirdparty/openssl/ssl/ssl_err2.c diff --git a/drivers/builtin_openssl2/ssl/ssl_lib.c b/thirdparty/openssl/ssl/ssl_lib.c index fd94325bb3..fd94325bb3 100644 --- a/drivers/builtin_openssl2/ssl/ssl_lib.c +++ b/thirdparty/openssl/ssl/ssl_lib.c diff --git a/drivers/builtin_openssl2/ssl/ssl_locl.h b/thirdparty/openssl/ssl/ssl_locl.h index 747e718a52..747e718a52 100644 --- a/drivers/builtin_openssl2/ssl/ssl_locl.h +++ b/thirdparty/openssl/ssl/ssl_locl.h diff --git a/drivers/builtin_openssl2/ssl/ssl_rsa.c b/thirdparty/openssl/ssl/ssl_rsa.c index 82022470bf..82022470bf 100644 --- a/drivers/builtin_openssl2/ssl/ssl_rsa.c +++ b/thirdparty/openssl/ssl/ssl_rsa.c diff --git a/drivers/builtin_openssl2/ssl/ssl_sess.c b/thirdparty/openssl/ssl/ssl_sess.c index b182998343..b182998343 100644 --- a/drivers/builtin_openssl2/ssl/ssl_sess.c +++ b/thirdparty/openssl/ssl/ssl_sess.c diff --git a/drivers/builtin_openssl2/ssl/ssl_stat.c b/thirdparty/openssl/ssl/ssl_stat.c index 1b9069f978..1b9069f978 100644 --- a/drivers/builtin_openssl2/ssl/ssl_stat.c +++ b/thirdparty/openssl/ssl/ssl_stat.c diff --git a/drivers/builtin_openssl2/ssl/ssl_task.c b/thirdparty/openssl/ssl/ssl_task.c index fb770753e2..fb770753e2 100644 --- a/drivers/builtin_openssl2/ssl/ssl_task.c +++ b/thirdparty/openssl/ssl/ssl_task.c diff --git a/drivers/builtin_openssl2/ssl/ssl_txt.c b/thirdparty/openssl/ssl/ssl_txt.c index 45308d8b65..45308d8b65 100644 --- a/drivers/builtin_openssl2/ssl/ssl_txt.c +++ b/thirdparty/openssl/ssl/ssl_txt.c diff --git a/drivers/builtin_openssl2/ssl/ssl_utst.c b/thirdparty/openssl/ssl/ssl_utst.c index 53bdde330d..53bdde330d 100644 --- a/drivers/builtin_openssl2/ssl/ssl_utst.c +++ b/thirdparty/openssl/ssl/ssl_utst.c diff --git a/drivers/builtin_openssl2/ssl/t1_clnt.c b/thirdparty/openssl/ssl/t1_clnt.c index 746b4e6b7a..746b4e6b7a 100644 --- a/drivers/builtin_openssl2/ssl/t1_clnt.c +++ b/thirdparty/openssl/ssl/t1_clnt.c diff --git a/drivers/builtin_openssl2/ssl/t1_enc.c b/thirdparty/openssl/ssl/t1_enc.c index 514fcb3e4e..514fcb3e4e 100644 --- a/drivers/builtin_openssl2/ssl/t1_enc.c +++ b/thirdparty/openssl/ssl/t1_enc.c diff --git a/drivers/builtin_openssl2/ssl/t1_ext.c b/thirdparty/openssl/ssl/t1_ext.c index 724ddf76ac..724ddf76ac 100644 --- a/drivers/builtin_openssl2/ssl/t1_ext.c +++ b/thirdparty/openssl/ssl/t1_ext.c diff --git a/drivers/builtin_openssl2/ssl/t1_lib.c b/thirdparty/openssl/ssl/t1_lib.c index dd5bd0050d..dd5bd0050d 100644 --- a/drivers/builtin_openssl2/ssl/t1_lib.c +++ b/thirdparty/openssl/ssl/t1_lib.c diff --git a/drivers/builtin_openssl2/ssl/t1_meth.c b/thirdparty/openssl/ssl/t1_meth.c index 335d57b530..335d57b530 100644 --- a/drivers/builtin_openssl2/ssl/t1_meth.c +++ b/thirdparty/openssl/ssl/t1_meth.c diff --git a/drivers/builtin_openssl2/ssl/t1_reneg.c b/thirdparty/openssl/ssl/t1_reneg.c index b9a35c7fc2..b9a35c7fc2 100644 --- a/drivers/builtin_openssl2/ssl/t1_reneg.c +++ b/thirdparty/openssl/ssl/t1_reneg.c diff --git a/drivers/builtin_openssl2/ssl/t1_srvr.c b/thirdparty/openssl/ssl/t1_srvr.c index 8c6b3dff2f..8c6b3dff2f 100644 --- a/drivers/builtin_openssl2/ssl/t1_srvr.c +++ b/thirdparty/openssl/ssl/t1_srvr.c diff --git a/drivers/builtin_openssl2/ssl/t1_trce.c b/thirdparty/openssl/ssl/t1_trce.c index c5e21df77a..c5e21df77a 100644 --- a/drivers/builtin_openssl2/ssl/t1_trce.c +++ b/thirdparty/openssl/ssl/t1_trce.c diff --git a/drivers/builtin_openssl2/ssl/tls_srp.c b/thirdparty/openssl/ssl/tls_srp.c index bb719ba4cf..bb719ba4cf 100644 --- a/drivers/builtin_openssl2/ssl/tls_srp.c +++ b/thirdparty/openssl/ssl/tls_srp.c diff --git a/thirdparty/openssl/winrt.cpp b/thirdparty/openssl/winrt.cpp new file mode 100644 index 0000000000..c3a6f8bfcc --- /dev/null +++ b/thirdparty/openssl/winrt.cpp @@ -0,0 +1,155 @@ +/* Snippets extracted from https://github.com/Microsoft/openssl/blob/ec7e430e06e4e3ac87c183dee33cb216814cf980/ms/winrt.cpp + * Adapted for Godot definitions + */ +/* winrt.cpp + * Copyright 2014 Microsoft Corporation + * C++/CX Entropy/shims for Windows Phone/Windows Store platform + * written by Alejandro Jimenez Martinez + * (aljim@microsoft.com) for the OpenSSL project 2014. + */ + +#include <windows.h> +#if defined(WINAPI_FAMILY) +extern "C" +{ + unsigned entropyRT(BYTE *buffer, unsigned len); + void RAND_add(const void *buf,int num,double entropy); + int RAND_poll(void); +} +#endif + +unsigned entropyRT(BYTE *buffer, unsigned len) + { + using namespace Platform; + using namespace Windows::Foundation; + using namespace Windows::Foundation::Collections; + using namespace Windows::Security::Cryptography; + using namespace Windows::Storage::Streams; + IBuffer ^buf = CryptographicBuffer::GenerateRandom(len); + Array<unsigned char> ^arr; + CryptographicBuffer::CopyToByteArray(buf, &arr); + unsigned arrayLen = arr->Length; + + // Make sure not to overflow the copy + arrayLen = (arrayLen > len) ? len : arrayLen; + memcpy(buffer, arr->Data, arrayLen); + return arrayLen; + } + +int RAND_poll(void) + { + BYTE buf[60]; + unsigned collected = entropyRT(buf , sizeof(buf)); + RAND_add(buf, collected, collected); + return 1; + } + +#if defined(WINRT_ENABLED) +extern "C" +{ +#include<stdio.h> +#include<string.h> +#include<stdlib.h> + + void* GetModuleHandle( + _In_opt_ LPCTSTR lpModuleName + ) + { + return NULL; + } + //no log for phone + int RegisterEventSource( + _In_ LPCTSTR lpUNCServerName, + _In_ LPCTSTR lpSourceName + ) + { + return NULL; + } + + int ReportEvent( + _In_ HANDLE hEventLog, + _In_ WORD wType, + _In_ WORD wCategory, + _In_ DWORD dwEventID, + _In_ PSID lpUserSid, + _In_ WORD wNumStrings, + _In_ DWORD dwDataSize, + _In_ LPCTSTR *lpStrings, + _In_ LPVOID lpRawData + ) + { + return 0; + } + int MessageBox( + _In_opt_ HWND hWnd, + _In_opt_ LPCTSTR lpText, + _In_opt_ LPCTSTR lpCaption, + _In_ UINT uType + ) + { + return 0; + } + int __cdecl GetProcessWindowStation(void) + { + return NULL; + } + BOOL __cdecl GetUserObjectInformationW( + _In_ HANDLE hObj, + _In_ int nIndex, + _Out_opt_ PVOID pvInfo, + _In_ DWORD nLength, + _Out_opt_ LPDWORD lpnLengthNeeded + ) + { + return 0; + } + int __cdecl GetStdHandle( + _In_ DWORD nStdHandle + ) + { + return 0; + } + BOOL DeregisterEventSource( + _Inout_ HANDLE hEventLog + ) + { + return 0; + } + char *getenv( + const char *varname + ) + { + //hardcoded environmental variables used for the appx testing application for store/phone + if (!strcmp(varname, "OPENSSL_CONF")) + { + return "./openssl.cnf"; + } + return 0; + } + int setenv(const char *envname, const char *envval, int overwrite) + { + return -1; + } + int _getch(void) + { + return 0; + } + int _kbhit() + { + return 0; + } + BOOL __cdecl FlushConsoleInputBuffer( + _In_ HANDLE hConsoleInput + ) + { + return 0; + } + int winrt_GetTickCount(void) + { + LARGE_INTEGER t; + return(int) (QueryPerformanceCounter(&t) ? t.QuadPart : 0); + } + void *OPENSSL_UplinkTable [26]= {0}; +} //extern C + +#endif /*defined(WINRT_ENABLED)*/ diff --git a/thirdparty/openssl/winrt_fix.patch b/thirdparty/openssl/winrt_fix.patch new file mode 100644 index 0000000000..caf180a75b --- /dev/null +++ b/thirdparty/openssl/winrt_fix.patch @@ -0,0 +1,64 @@ +diff --git a/drivers/builtin_openssl2/crypto/rand/rand_win.c b/drivers/builtin_openssl2/crypto/rand/rand_win.c +index 06670ae..70fd52a 100644 +--- a/drivers/builtin_openssl2/crypto/rand/rand_win.c ++++ b/drivers/builtin_openssl2/crypto/rand/rand_win.c +@@ -118,8 +118,10 @@ + # ifndef _WIN32_WINNT + # define _WIN32_WINNT 0x0400 + # endif ++#ifndef WINRT_ENABLED + # include <wincrypt.h> + # include <tlhelp32.h> ++#endif + + /* + * Limit the time spent walking through the heap, processes, threads and +@@ -161,7 +163,7 @@ typedef struct tagCURSORINFO { + # define CURSOR_SHOWING 0x00000001 + # endif /* CURSOR_SHOWING */ + +-# if !defined(OPENSSL_SYS_WINCE) ++# if !defined(OPENSSL_SYS_WINCE) && !defined(WINRT_ENABLED) + typedef BOOL(WINAPI *CRYPTACQUIRECONTEXTW) (HCRYPTPROV *, LPCWSTR, LPCWSTR, + DWORD, DWORD); + typedef BOOL(WINAPI *CRYPTGENRANDOM) (HCRYPTPROV, DWORD, BYTE *); +@@ -196,6 +198,7 @@ typedef NET_API_STATUS(NET_API_FUNCTION *NETFREE) (LPBYTE); + # endif /* 1 */ + # endif /* !OPENSSL_SYS_WINCE */ + ++#if !defined(WINRT_ENABLED) + int RAND_poll(void) + { + MEMORYSTATUS m; +@@ -580,6 +583,8 @@ int RAND_poll(void) + return (1); + } + ++#endif // WINRT_ENABLED ++ + int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam) + { + double add_entropy = 0; +@@ -682,7 +687,7 @@ static void readtimer(void) + + static void readscreen(void) + { +-# if !defined(OPENSSL_SYS_WINCE) && !defined(OPENSSL_SYS_WIN32_CYGWIN) ++# if !defined(OPENSSL_SYS_WINCE) && !defined(OPENSSL_SYS_WIN32_CYGWIN) && !defined(WINRT_ENABLED) + HDC hScrDC; /* screen DC */ + HBITMAP hBitmap; /* handle for our bitmap */ + BITMAP bm; /* bitmap properties */ +diff --git a/drivers/builtin_openssl2/openssl/dtls1.h b/drivers/builtin_openssl2/openssl/dtls1.h +index 64ad3c8..a58aca2 100644 +--- a/drivers/builtin_openssl2/openssl/dtls1.h ++++ b/drivers/builtin_openssl2/openssl/dtls1.h +@@ -81,6 +81,9 @@ + # include <sys/time.h> + # endif + # endif ++#ifdef WINRT_ENABLED ++#include <winsock2.h> ++#endif + + #ifdef __cplusplus + extern "C" { diff --git a/drivers/opus/COPYING b/thirdparty/opus/COPYING index 7b53d665df..7b53d665df 100644 --- a/drivers/opus/COPYING +++ b/thirdparty/opus/COPYING diff --git a/thirdparty/opus/analysis.c b/thirdparty/opus/analysis.c new file mode 100644 index 0000000000..360ebcc8dd --- /dev/null +++ b/thirdparty/opus/analysis.c @@ -0,0 +1,675 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "kiss_fft.h" +#include "celt.h" +#include "modes.h" +#include "arch.h" +#include "quant_bands.h" +#include <stdio.h> +#include "analysis.h" +#include "mlp.h" +#include "stack_alloc.h" + +#ifndef M_PI +#define M_PI 3.141592653 +#endif + +static const float dct_table[128] = { + 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, + 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, + 0.351851f, 0.338330f, 0.311806f, 0.273300f, 0.224292f, 0.166664f, 0.102631f, 0.034654f, + -0.034654f,-0.102631f,-0.166664f,-0.224292f,-0.273300f,-0.311806f,-0.338330f,-0.351851f, + 0.346760f, 0.293969f, 0.196424f, 0.068975f,-0.068975f,-0.196424f,-0.293969f,-0.346760f, + -0.346760f,-0.293969f,-0.196424f,-0.068975f, 0.068975f, 0.196424f, 0.293969f, 0.346760f, + 0.338330f, 0.224292f, 0.034654f,-0.166664f,-0.311806f,-0.351851f,-0.273300f,-0.102631f, + 0.102631f, 0.273300f, 0.351851f, 0.311806f, 0.166664f,-0.034654f,-0.224292f,-0.338330f, + 0.326641f, 0.135299f,-0.135299f,-0.326641f,-0.326641f,-0.135299f, 0.135299f, 0.326641f, + 0.326641f, 0.135299f,-0.135299f,-0.326641f,-0.326641f,-0.135299f, 0.135299f, 0.326641f, + 0.311806f, 0.034654f,-0.273300f,-0.338330f,-0.102631f, 0.224292f, 0.351851f, 0.166664f, + -0.166664f,-0.351851f,-0.224292f, 0.102631f, 0.338330f, 0.273300f,-0.034654f,-0.311806f, + 0.293969f,-0.068975f,-0.346760f,-0.196424f, 0.196424f, 0.346760f, 0.068975f,-0.293969f, + -0.293969f, 0.068975f, 0.346760f, 0.196424f,-0.196424f,-0.346760f,-0.068975f, 0.293969f, + 0.273300f,-0.166664f,-0.338330f, 0.034654f, 0.351851f, 0.102631f,-0.311806f,-0.224292f, + 0.224292f, 0.311806f,-0.102631f,-0.351851f,-0.034654f, 0.338330f, 0.166664f,-0.273300f, +}; + +static const float analysis_window[240] = { + 0.000043f, 0.000171f, 0.000385f, 0.000685f, 0.001071f, 0.001541f, 0.002098f, 0.002739f, + 0.003466f, 0.004278f, 0.005174f, 0.006156f, 0.007222f, 0.008373f, 0.009607f, 0.010926f, + 0.012329f, 0.013815f, 0.015385f, 0.017037f, 0.018772f, 0.020590f, 0.022490f, 0.024472f, + 0.026535f, 0.028679f, 0.030904f, 0.033210f, 0.035595f, 0.038060f, 0.040604f, 0.043227f, + 0.045928f, 0.048707f, 0.051564f, 0.054497f, 0.057506f, 0.060591f, 0.063752f, 0.066987f, + 0.070297f, 0.073680f, 0.077136f, 0.080665f, 0.084265f, 0.087937f, 0.091679f, 0.095492f, + 0.099373f, 0.103323f, 0.107342f, 0.111427f, 0.115579f, 0.119797f, 0.124080f, 0.128428f, + 0.132839f, 0.137313f, 0.141849f, 0.146447f, 0.151105f, 0.155823f, 0.160600f, 0.165435f, + 0.170327f, 0.175276f, 0.180280f, 0.185340f, 0.190453f, 0.195619f, 0.200838f, 0.206107f, + 0.211427f, 0.216797f, 0.222215f, 0.227680f, 0.233193f, 0.238751f, 0.244353f, 0.250000f, + 0.255689f, 0.261421f, 0.267193f, 0.273005f, 0.278856f, 0.284744f, 0.290670f, 0.296632f, + 0.302628f, 0.308658f, 0.314721f, 0.320816f, 0.326941f, 0.333097f, 0.339280f, 0.345492f, + 0.351729f, 0.357992f, 0.364280f, 0.370590f, 0.376923f, 0.383277f, 0.389651f, 0.396044f, + 0.402455f, 0.408882f, 0.415325f, 0.421783f, 0.428254f, 0.434737f, 0.441231f, 0.447736f, + 0.454249f, 0.460770f, 0.467298f, 0.473832f, 0.480370f, 0.486912f, 0.493455f, 0.500000f, + 0.506545f, 0.513088f, 0.519630f, 0.526168f, 0.532702f, 0.539230f, 0.545751f, 0.552264f, + 0.558769f, 0.565263f, 0.571746f, 0.578217f, 0.584675f, 0.591118f, 0.597545f, 0.603956f, + 0.610349f, 0.616723f, 0.623077f, 0.629410f, 0.635720f, 0.642008f, 0.648271f, 0.654508f, + 0.660720f, 0.666903f, 0.673059f, 0.679184f, 0.685279f, 0.691342f, 0.697372f, 0.703368f, + 0.709330f, 0.715256f, 0.721144f, 0.726995f, 0.732807f, 0.738579f, 0.744311f, 0.750000f, + 0.755647f, 0.761249f, 0.766807f, 0.772320f, 0.777785f, 0.783203f, 0.788573f, 0.793893f, + 0.799162f, 0.804381f, 0.809547f, 0.814660f, 0.819720f, 0.824724f, 0.829673f, 0.834565f, + 0.839400f, 0.844177f, 0.848895f, 0.853553f, 0.858151f, 0.862687f, 0.867161f, 0.871572f, + 0.875920f, 0.880203f, 0.884421f, 0.888573f, 0.892658f, 0.896677f, 0.900627f, 0.904508f, + 0.908321f, 0.912063f, 0.915735f, 0.919335f, 0.922864f, 0.926320f, 0.929703f, 0.933013f, + 0.936248f, 0.939409f, 0.942494f, 0.945503f, 0.948436f, 0.951293f, 0.954072f, 0.956773f, + 0.959396f, 0.961940f, 0.964405f, 0.966790f, 0.969096f, 0.971321f, 0.973465f, 0.975528f, + 0.977510f, 0.979410f, 0.981228f, 0.982963f, 0.984615f, 0.986185f, 0.987671f, 0.989074f, + 0.990393f, 0.991627f, 0.992778f, 0.993844f, 0.994826f, 0.995722f, 0.996534f, 0.997261f, + 0.997902f, 0.998459f, 0.998929f, 0.999315f, 0.999615f, 0.999829f, 0.999957f, 1.000000f, +}; + +static const int tbands[NB_TBANDS+1] = { + 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120 +}; + +static const int extra_bands[NB_TOT_BANDS+1] = { + 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120, 160, 200 +}; + +/*static const float tweight[NB_TBANDS+1] = { + .3, .4, .5, .6, .7, .8, .9, 1., 1., 1., 1., 1., 1., 1., .8, .7, .6, .5 +};*/ + +#define NB_TONAL_SKIP_BANDS 9 + +#define cA 0.43157974f +#define cB 0.67848403f +#define cC 0.08595542f +#define cE ((float)M_PI/2) +static OPUS_INLINE float fast_atan2f(float y, float x) { + float x2, y2; + /* Should avoid underflow on the values we'll get */ + if (ABS16(x)+ABS16(y)<1e-9f) + { + x*=1e12f; + y*=1e12f; + } + x2 = x*x; + y2 = y*y; + if(x2<y2){ + float den = (y2 + cB*x2) * (y2 + cC*x2); + if (den!=0) + return -x*y*(y2 + cA*x2) / den + (y<0 ? -cE : cE); + else + return (y<0 ? -cE : cE); + }else{ + float den = (x2 + cB*y2) * (x2 + cC*y2); + if (den!=0) + return x*y*(x2 + cA*y2) / den + (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE); + else + return (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE); + } +} + +void tonality_analysis_init(TonalityAnalysisState *tonal) +{ + /* Initialize reusable fields. */ + tonal->arch = opus_select_arch(); + /* Clear remaining fields. */ + tonality_analysis_reset(tonal); +} + +void tonality_analysis_reset(TonalityAnalysisState *tonal) +{ + /* Clear non-reusable fields. */ + char *start = (char*)&tonal->TONALITY_ANALYSIS_RESET_START; + OPUS_CLEAR(start, sizeof(TonalityAnalysisState) - (start - (char*)tonal)); +} + +void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len) +{ + int pos; + int curr_lookahead; + float psum; + int i; + + pos = tonal->read_pos; + curr_lookahead = tonal->write_pos-tonal->read_pos; + if (curr_lookahead<0) + curr_lookahead += DETECT_SIZE; + + if (len > 480 && pos != tonal->write_pos) + { + pos++; + if (pos==DETECT_SIZE) + pos=0; + } + if (pos == tonal->write_pos) + pos--; + if (pos<0) + pos = DETECT_SIZE-1; + OPUS_COPY(info_out, &tonal->info[pos], 1); + tonal->read_subframe += len/120; + while (tonal->read_subframe>=4) + { + tonal->read_subframe -= 4; + tonal->read_pos++; + } + if (tonal->read_pos>=DETECT_SIZE) + tonal->read_pos-=DETECT_SIZE; + + /* Compensate for the delay in the features themselves. + FIXME: Need a better estimate the 10 I just made up */ + curr_lookahead = IMAX(curr_lookahead-10, 0); + + psum=0; + /* Summing the probability of transition patterns that involve music at + time (DETECT_SIZE-curr_lookahead-1) */ + for (i=0;i<DETECT_SIZE-curr_lookahead;i++) + psum += tonal->pmusic[i]; + for (;i<DETECT_SIZE;i++) + psum += tonal->pspeech[i]; + psum = psum*tonal->music_confidence + (1-psum)*tonal->speech_confidence; + /*printf("%f %f %f\n", psum, info_out->music_prob, info_out->tonality);*/ + + info_out->music_prob = psum; +} + +static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt_mode, const void *x, int len, int offset, int c1, int c2, int C, int lsb_depth, downmix_func downmix) +{ + int i, b; + const kiss_fft_state *kfft; + VARDECL(kiss_fft_cpx, in); + VARDECL(kiss_fft_cpx, out); + int N = 480, N2=240; + float * OPUS_RESTRICT A = tonal->angle; + float * OPUS_RESTRICT dA = tonal->d_angle; + float * OPUS_RESTRICT d2A = tonal->d2_angle; + VARDECL(float, tonality); + VARDECL(float, noisiness); + float band_tonality[NB_TBANDS]; + float logE[NB_TBANDS]; + float BFCC[8]; + float features[25]; + float frame_tonality; + float max_frame_tonality; + /*float tw_sum=0;*/ + float frame_noisiness; + const float pi4 = (float)(M_PI*M_PI*M_PI*M_PI); + float slope=0; + float frame_stationarity; + float relativeE; + float frame_probs[2]; + float alpha, alphaE, alphaE2; + float frame_loudness; + float bandwidth_mask; + int bandwidth=0; + float maxE = 0; + float noise_floor; + int remaining; + AnalysisInfo *info; + SAVE_STACK; + + tonal->last_transition++; + alpha = 1.f/IMIN(20, 1+tonal->count); + alphaE = 1.f/IMIN(50, 1+tonal->count); + alphaE2 = 1.f/IMIN(1000, 1+tonal->count); + + if (tonal->count<4) + tonal->music_prob = .5; + kfft = celt_mode->mdct.kfft[0]; + if (tonal->count==0) + tonal->mem_fill = 240; + downmix(x, &tonal->inmem[tonal->mem_fill], IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, c1, c2, C); + if (tonal->mem_fill+len < ANALYSIS_BUF_SIZE) + { + tonal->mem_fill += len; + /* Don't have enough to update the analysis */ + RESTORE_STACK; + return; + } + info = &tonal->info[tonal->write_pos++]; + if (tonal->write_pos>=DETECT_SIZE) + tonal->write_pos-=DETECT_SIZE; + + ALLOC(in, 480, kiss_fft_cpx); + ALLOC(out, 480, kiss_fft_cpx); + ALLOC(tonality, 240, float); + ALLOC(noisiness, 240, float); + for (i=0;i<N2;i++) + { + float w = analysis_window[i]; + in[i].r = (kiss_fft_scalar)(w*tonal->inmem[i]); + in[i].i = (kiss_fft_scalar)(w*tonal->inmem[N2+i]); + in[N-i-1].r = (kiss_fft_scalar)(w*tonal->inmem[N-i-1]); + in[N-i-1].i = (kiss_fft_scalar)(w*tonal->inmem[N+N2-i-1]); + } + OPUS_MOVE(tonal->inmem, tonal->inmem+ANALYSIS_BUF_SIZE-240, 240); + remaining = len - (ANALYSIS_BUF_SIZE-tonal->mem_fill); + downmix(x, &tonal->inmem[240], remaining, offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C); + tonal->mem_fill = 240 + remaining; + opus_fft(kfft, in, out, tonal->arch); +#ifndef FIXED_POINT + /* If there's any NaN on the input, the entire output will be NaN, so we only need to check one value. */ + if (celt_isnan(out[0].r)) + { + info->valid = 0; + RESTORE_STACK; + return; + } +#endif + + for (i=1;i<N2;i++) + { + float X1r, X2r, X1i, X2i; + float angle, d_angle, d2_angle; + float angle2, d_angle2, d2_angle2; + float mod1, mod2, avg_mod; + X1r = (float)out[i].r+out[N-i].r; + X1i = (float)out[i].i-out[N-i].i; + X2r = (float)out[i].i+out[N-i].i; + X2i = (float)out[N-i].r-out[i].r; + + angle = (float)(.5f/M_PI)*fast_atan2f(X1i, X1r); + d_angle = angle - A[i]; + d2_angle = d_angle - dA[i]; + + angle2 = (float)(.5f/M_PI)*fast_atan2f(X2i, X2r); + d_angle2 = angle2 - angle; + d2_angle2 = d_angle2 - d_angle; + + mod1 = d2_angle - (float)floor(.5+d2_angle); + noisiness[i] = ABS16(mod1); + mod1 *= mod1; + mod1 *= mod1; + + mod2 = d2_angle2 - (float)floor(.5+d2_angle2); + noisiness[i] += ABS16(mod2); + mod2 *= mod2; + mod2 *= mod2; + + avg_mod = .25f*(d2A[i]+2.f*mod1+mod2); + tonality[i] = 1.f/(1.f+40.f*16.f*pi4*avg_mod)-.015f; + + A[i] = angle2; + dA[i] = d_angle2; + d2A[i] = mod2; + } + + frame_tonality = 0; + max_frame_tonality = 0; + /*tw_sum = 0;*/ + info->activity = 0; + frame_noisiness = 0; + frame_stationarity = 0; + if (!tonal->count) + { + for (b=0;b<NB_TBANDS;b++) + { + tonal->lowE[b] = 1e10; + tonal->highE[b] = -1e10; + } + } + relativeE = 0; + frame_loudness = 0; + for (b=0;b<NB_TBANDS;b++) + { + float E=0, tE=0, nE=0; + float L1, L2; + float stationarity; + for (i=tbands[b];i<tbands[b+1];i++) + { + float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r + + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i; +#ifdef FIXED_POINT + /* FIXME: It's probably best to change the BFCC filter initial state instead */ + binE *= 5.55e-17f; +#endif + E += binE; + tE += binE*tonality[i]; + nE += binE*2.f*(.5f-noisiness[i]); + } +#ifndef FIXED_POINT + /* Check for extreme band energies that could cause NaNs later. */ + if (!(E<1e9f) || celt_isnan(E)) + { + info->valid = 0; + RESTORE_STACK; + return; + } +#endif + + tonal->E[tonal->E_count][b] = E; + frame_noisiness += nE/(1e-15f+E); + + frame_loudness += (float)sqrt(E+1e-10f); + logE[b] = (float)log(E+1e-10f); + tonal->lowE[b] = MIN32(logE[b], tonal->lowE[b]+.01f); + tonal->highE[b] = MAX32(logE[b], tonal->highE[b]-.1f); + if (tonal->highE[b] < tonal->lowE[b]+1.f) + { + tonal->highE[b]+=.5f; + tonal->lowE[b]-=.5f; + } + relativeE += (logE[b]-tonal->lowE[b])/(1e-15f+tonal->highE[b]-tonal->lowE[b]); + + L1=L2=0; + for (i=0;i<NB_FRAMES;i++) + { + L1 += (float)sqrt(tonal->E[i][b]); + L2 += tonal->E[i][b]; + } + + stationarity = MIN16(0.99f,L1/(float)sqrt(1e-15+NB_FRAMES*L2)); + stationarity *= stationarity; + stationarity *= stationarity; + frame_stationarity += stationarity; + /*band_tonality[b] = tE/(1e-15+E)*/; + band_tonality[b] = MAX16(tE/(1e-15f+E), stationarity*tonal->prev_band_tonality[b]); +#if 0 + if (b>=NB_TONAL_SKIP_BANDS) + { + frame_tonality += tweight[b]*band_tonality[b]; + tw_sum += tweight[b]; + } +#else + frame_tonality += band_tonality[b]; + if (b>=NB_TBANDS-NB_TONAL_SKIP_BANDS) + frame_tonality -= band_tonality[b-NB_TBANDS+NB_TONAL_SKIP_BANDS]; +#endif + max_frame_tonality = MAX16(max_frame_tonality, (1.f+.03f*(b-NB_TBANDS))*frame_tonality); + slope += band_tonality[b]*(b-8); + /*printf("%f %f ", band_tonality[b], stationarity);*/ + tonal->prev_band_tonality[b] = band_tonality[b]; + } + + bandwidth_mask = 0; + bandwidth = 0; + maxE = 0; + noise_floor = 5.7e-4f/(1<<(IMAX(0,lsb_depth-8))); +#ifdef FIXED_POINT + noise_floor *= 1<<(15+SIG_SHIFT); +#endif + noise_floor *= noise_floor; + for (b=0;b<NB_TOT_BANDS;b++) + { + float E=0; + int band_start, band_end; + /* Keep a margin of 300 Hz for aliasing */ + band_start = extra_bands[b]; + band_end = extra_bands[b+1]; + for (i=band_start;i<band_end;i++) + { + float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r + + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i; + E += binE; + } + maxE = MAX32(maxE, E); + tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E); + E = MAX32(E, tonal->meanE[b]); + /* Use a simple follower with 13 dB/Bark slope for spreading function */ + bandwidth_mask = MAX32(.05f*bandwidth_mask, E); + /* Consider the band "active" only if all these conditions are met: + 1) less than 10 dB below the simple follower + 2) less than 90 dB below the peak band (maximal masking possible considering + both the ATH and the loudness-dependent slope of the spreading function) + 3) above the PCM quantization noise floor + */ + if (E>.1*bandwidth_mask && E*1e9f > maxE && E > noise_floor*(band_end-band_start)) + bandwidth = b; + } + if (tonal->count<=2) + bandwidth = 20; + frame_loudness = 20*(float)log10(frame_loudness); + tonal->Etracker = MAX32(tonal->Etracker-.03f, frame_loudness); + tonal->lowECount *= (1-alphaE); + if (frame_loudness < tonal->Etracker-30) + tonal->lowECount += alphaE; + + for (i=0;i<8;i++) + { + float sum=0; + for (b=0;b<16;b++) + sum += dct_table[i*16+b]*logE[b]; + BFCC[i] = sum; + } + + frame_stationarity /= NB_TBANDS; + relativeE /= NB_TBANDS; + if (tonal->count<10) + relativeE = .5; + frame_noisiness /= NB_TBANDS; +#if 1 + info->activity = frame_noisiness + (1-frame_noisiness)*relativeE; +#else + info->activity = .5*(1+frame_noisiness-frame_stationarity); +#endif + frame_tonality = (max_frame_tonality/(NB_TBANDS-NB_TONAL_SKIP_BANDS)); + frame_tonality = MAX16(frame_tonality, tonal->prev_tonality*.8f); + tonal->prev_tonality = frame_tonality; + + slope /= 8*8; + info->tonality_slope = slope; + + tonal->E_count = (tonal->E_count+1)%NB_FRAMES; + tonal->count++; + info->tonality = frame_tonality; + + for (i=0;i<4;i++) + features[i] = -0.12299f*(BFCC[i]+tonal->mem[i+24]) + 0.49195f*(tonal->mem[i]+tonal->mem[i+16]) + 0.69693f*tonal->mem[i+8] - 1.4349f*tonal->cmean[i]; + + for (i=0;i<4;i++) + tonal->cmean[i] = (1-alpha)*tonal->cmean[i] + alpha*BFCC[i]; + + for (i=0;i<4;i++) + features[4+i] = 0.63246f*(BFCC[i]-tonal->mem[i+24]) + 0.31623f*(tonal->mem[i]-tonal->mem[i+16]); + for (i=0;i<3;i++) + features[8+i] = 0.53452f*(BFCC[i]+tonal->mem[i+24]) - 0.26726f*(tonal->mem[i]+tonal->mem[i+16]) -0.53452f*tonal->mem[i+8]; + + if (tonal->count > 5) + { + for (i=0;i<9;i++) + tonal->std[i] = (1-alpha)*tonal->std[i] + alpha*features[i]*features[i]; + } + + for (i=0;i<8;i++) + { + tonal->mem[i+24] = tonal->mem[i+16]; + tonal->mem[i+16] = tonal->mem[i+8]; + tonal->mem[i+8] = tonal->mem[i]; + tonal->mem[i] = BFCC[i]; + } + for (i=0;i<9;i++) + features[11+i] = (float)sqrt(tonal->std[i]); + features[20] = info->tonality; + features[21] = info->activity; + features[22] = frame_stationarity; + features[23] = info->tonality_slope; + features[24] = tonal->lowECount; + +#ifndef DISABLE_FLOAT_API + mlp_process(&net, features, frame_probs); + frame_probs[0] = .5f*(frame_probs[0]+1); + /* Curve fitting between the MLP probability and the actual probability */ + frame_probs[0] = .01f + 1.21f*frame_probs[0]*frame_probs[0] - .23f*(float)pow(frame_probs[0], 10); + /* Probability of active audio (as opposed to silence) */ + frame_probs[1] = .5f*frame_probs[1]+.5f; + /* Consider that silence has a 50-50 probability. */ + frame_probs[0] = frame_probs[1]*frame_probs[0] + (1-frame_probs[1])*.5f; + + /*printf("%f %f ", frame_probs[0], frame_probs[1]);*/ + { + /* Probability of state transition */ + float tau; + /* Represents independence of the MLP probabilities, where + beta=1 means fully independent. */ + float beta; + /* Denormalized probability of speech (p0) and music (p1) after update */ + float p0, p1; + /* Probabilities for "all speech" and "all music" */ + float s0, m0; + /* Probability sum for renormalisation */ + float psum; + /* Instantaneous probability of speech and music, with beta pre-applied. */ + float speech0; + float music0; + + /* One transition every 3 minutes of active audio */ + tau = .00005f*frame_probs[1]; + beta = .05f; + if (1) { + /* Adapt beta based on how "unexpected" the new prob is */ + float p, q; + p = MAX16(.05f,MIN16(.95f,frame_probs[0])); + q = MAX16(.05f,MIN16(.95f,tonal->music_prob)); + beta = .01f+.05f*ABS16(p-q)/(p*(1-q)+q*(1-p)); + } + /* p0 and p1 are the probabilities of speech and music at this frame + using only information from previous frame and applying the + state transition model */ + p0 = (1-tonal->music_prob)*(1-tau) + tonal->music_prob *tau; + p1 = tonal->music_prob *(1-tau) + (1-tonal->music_prob)*tau; + /* We apply the current probability with exponent beta to work around + the fact that the probability estimates aren't independent. */ + p0 *= (float)pow(1-frame_probs[0], beta); + p1 *= (float)pow(frame_probs[0], beta); + /* Normalise the probabilities to get the Marokv probability of music. */ + tonal->music_prob = p1/(p0+p1); + info->music_prob = tonal->music_prob; + + /* This chunk of code deals with delayed decision. */ + psum=1e-20f; + /* Instantaneous probability of speech and music, with beta pre-applied. */ + speech0 = (float)pow(1-frame_probs[0], beta); + music0 = (float)pow(frame_probs[0], beta); + if (tonal->count==1) + { + tonal->pspeech[0]=.5; + tonal->pmusic [0]=.5; + } + /* Updated probability of having only speech (s0) or only music (m0), + before considering the new observation. */ + s0 = tonal->pspeech[0] + tonal->pspeech[1]; + m0 = tonal->pmusic [0] + tonal->pmusic [1]; + /* Updates s0 and m0 with instantaneous probability. */ + tonal->pspeech[0] = s0*(1-tau)*speech0; + tonal->pmusic [0] = m0*(1-tau)*music0; + /* Propagate the transition probabilities */ + for (i=1;i<DETECT_SIZE-1;i++) + { + tonal->pspeech[i] = tonal->pspeech[i+1]*speech0; + tonal->pmusic [i] = tonal->pmusic [i+1]*music0; + } + /* Probability that the latest frame is speech, when all the previous ones were music. */ + tonal->pspeech[DETECT_SIZE-1] = m0*tau*speech0; + /* Probability that the latest frame is music, when all the previous ones were speech. */ + tonal->pmusic [DETECT_SIZE-1] = s0*tau*music0; + + /* Renormalise probabilities to 1 */ + for (i=0;i<DETECT_SIZE;i++) + psum += tonal->pspeech[i] + tonal->pmusic[i]; + psum = 1.f/psum; + for (i=0;i<DETECT_SIZE;i++) + { + tonal->pspeech[i] *= psum; + tonal->pmusic [i] *= psum; + } + psum = tonal->pmusic[0]; + for (i=1;i<DETECT_SIZE;i++) + psum += tonal->pspeech[i]; + + /* Estimate our confidence in the speech/music decisions */ + if (frame_probs[1]>.75) + { + if (tonal->music_prob>.9) + { + float adapt; + adapt = 1.f/(++tonal->music_confidence_count); + tonal->music_confidence_count = IMIN(tonal->music_confidence_count, 500); + tonal->music_confidence += adapt*MAX16(-.2f,frame_probs[0]-tonal->music_confidence); + } + if (tonal->music_prob<.1) + { + float adapt; + adapt = 1.f/(++tonal->speech_confidence_count); + tonal->speech_confidence_count = IMIN(tonal->speech_confidence_count, 500); + tonal->speech_confidence += adapt*MIN16(.2f,frame_probs[0]-tonal->speech_confidence); + } + } else { + if (tonal->music_confidence_count==0) + tonal->music_confidence = .9f; + if (tonal->speech_confidence_count==0) + tonal->speech_confidence = .1f; + } + } + if (tonal->last_music != (tonal->music_prob>.5f)) + tonal->last_transition=0; + tonal->last_music = tonal->music_prob>.5f; +#else + info->music_prob = 0; +#endif + /*for (i=0;i<25;i++) + printf("%f ", features[i]); + printf("\n");*/ + + info->bandwidth = bandwidth; + /*printf("%d %d\n", info->bandwidth, info->opus_bandwidth);*/ + info->noisiness = frame_noisiness; + info->valid = 1; + RESTORE_STACK; +} + +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) +{ + int offset; + int pcm_len; + + if (analysis_pcm != NULL) + { + /* Avoid overflow/wrap-around of the analysis buffer */ + analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/100, analysis_frame_size); + + pcm_len = analysis_frame_size - analysis->analysis_offset; + offset = analysis->analysis_offset; + do { + tonality_analysis(analysis, celt_mode, analysis_pcm, IMIN(480, pcm_len), offset, c1, c2, C, lsb_depth, downmix); + offset += 480; + pcm_len -= 480; + } while (pcm_len>0); + analysis->analysis_offset = analysis_frame_size; + + analysis->analysis_offset -= frame_size; + } + + analysis_info->valid = 0; + tonality_get_info(analysis, analysis_info, frame_size); +} diff --git a/thirdparty/opus/analysis.h b/thirdparty/opus/analysis.h new file mode 100644 index 0000000000..9eae56a525 --- /dev/null +++ b/thirdparty/opus/analysis.h @@ -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" + +#define NB_FRAMES 8 +#define NB_TBANDS 18 +#define NB_TOT_BANDS 21 +#define ANALYSIS_BUF_SIZE 720 /* 15 ms at 48 kHz */ + +#define DETECT_SIZE 200 + +typedef struct { + int arch; +#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; + float E[NB_FRAMES][NB_TBANDS]; + float lowE[NB_TBANDS]; + float highE[NB_TBANDS]; + float meanE[NB_TOT_BANDS]; + float mem[32]; + float cmean[8]; + float std[9]; + float music_prob; + float Etracker; + float lowECount; + int E_count; + int last_music; + int last_transition; + int count; + float subframe_mem[3]; + int analysis_offset; + /** Probability of having speech for time i to DETECT_SIZE-1 (and music before). + pspeech[0] is the probability that all frames in the window are speech. */ + float pspeech[DETECT_SIZE]; + /** Probability of having music for time i to DETECT_SIZE-1 (and speech before). + pmusic[0] is the probability that all frames in the window are music. */ + float pmusic[DETECT_SIZE]; + float speech_confidence; + float music_confidence; + int speech_confidence_count; + int music_confidence_count; + int write_pos; + int read_pos; + int read_subframe; + 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); + +/** Reset a TonalityAnalysisState stuct. + * + * 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/thirdparty/opus/celt/_kiss_fft_guts.h b/thirdparty/opus/celt/_kiss_fft_guts.h new file mode 100644 index 0000000000..5e3d58fd66 --- /dev/null +++ b/thirdparty/opus/celt/_kiss_fft_guts.h @@ -0,0 +1,182 @@ +/*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 + + +# define S_MUL(a,b) MULT16_32_Q15(b, a) + +# define C_MUL(m,a,b) \ + do{ (m).r = SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ + (m).i = ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0) + +# define C_MULC(m,a,b) \ + do{ (m).r = ADD32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ + (m).i = SUB32(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((a).r,(b).r); (res).i=ADD32((a).i,(b).i); \ + }while(0) +#define C_SUB( res, a,b)\ + do {(res).r=SUB32((a).r,(b).r); (res).i=SUB32((a).i,(b).i); \ + }while(0) +#define C_ADDTO( res , a)\ + do {(res).r = ADD32((res).r, (a).r); (res).i = ADD32((res).i,(a).i);\ + }while(0) + +#define C_SUBFROM( res , a)\ + do {(res).r = ADD32((res).r,(a).r); (res).i = SUB32((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(MIPSr1_ASM) +#include "mips/kiss_fft_mipsr1.h" +#endif + +#else /* not FIXED_POINT*/ + +# define S_MUL(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/thirdparty/opus/celt/arch.h b/thirdparty/opus/celt/arch.h new file mode 100644 index 0000000000..9f74ddd267 --- /dev/null +++ b/thirdparty/opus/celt/arch.h @@ -0,0 +1,241 @@ +/* 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 + +#define CELT_SIG_SCALE 32768.f + +#define celt_fatal(str) _celt_fatal(str, __FILE__, __LINE__); +#ifdef ENABLE_ASSERTIONS +#include <stdio.h> +#include <stdlib.h> +#ifdef __GNUC__ +__attribute__((noreturn)) +#endif +static OPUS_INLINE 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); + abort(); +} +#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);}} +#else +#define celt_assert(cond) +#define celt_assert2(cond, message) +#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 UADD32(a,b) ((a)+(b)) +#define USUB32(a,b) ((a)-(b)) + +#define PRINT_MIPS(file) + +#ifdef FIXED_POINT + +typedef opus_int16 opus_val16; +typedef opus_int32 opus_val32; + +typedef opus_val32 celt_sig; +typedef opus_val16 celt_norm; +typedef opus_val32 celt_ener; + +#define Q15ONE 32767 + +#define SIG_SHIFT 12 + +#define NORM_SCALING 16384 + +#define DB_SHIFT 10 + +#define EPSILON 1 +#define VERY_SMALL 0 +#define VERY_LARGE16 ((opus_val16)32767) +#define Q15_ONE ((opus_val16)32767) + +#define SCALEIN(a) (a) +#define SCALEOUT(a) (a) + +#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_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 celt_sig; +typedef float celt_norm; +typedef float celt_ener; + +#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 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 NEG16(x) (-(x)) +#define NEG32(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 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 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 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_Q31(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 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 DIV32_16(a,b) (((opus_val32)(a))/(opus_val16)(b)) +#define DIV32(a,b) (((opus_val32)(a))/(opus_val32)(b)) + +#define SCALEIN(a) ((a)*CELT_SIG_SCALE) +#define SCALEOUT(a) ((a)*(1/CELT_SIG_SCALE)) + +#define SIG2WORD16(x) (x) + +#endif /* !FIXED_POINT */ + +#ifndef GLOBAL_STACK_SIZE +#ifdef FIXED_POINT +#define GLOBAL_STACK_SIZE 100000 +#else +#define GLOBAL_STACK_SIZE 100000 +#endif +#endif + +#endif /* ARCH_H */ diff --git a/drivers/opus/celt/arm/arm2gnu.pl b/thirdparty/opus/celt/arm/arm2gnu.pl index 6c922ac819..6c922ac819 100755 --- a/drivers/opus/celt/arm/arm2gnu.pl +++ b/thirdparty/opus/celt/arm/arm2gnu.pl diff --git a/thirdparty/opus/celt/arm/arm_celt_map.c b/thirdparty/opus/celt/arm/arm_celt_map.c new file mode 100644 index 0000000000..ee6c244786 --- /dev/null +++ b/thirdparty/opus/celt/arm/arm_celt_map.c @@ -0,0 +1,121 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pitch.h" +#include "kiss_fft.h" +#include "mdct.h" + +#if defined(OPUS_HAVE_RTCD) + +# if defined(FIXED_POINT) +opus_val32 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *, + const opus_val16 *, opus_val32 *, int , int) = { + celt_pitch_xcorr_c, /* ARMv4 */ + MAY_HAVE_EDSP(celt_pitch_xcorr), /* EDSP */ + MAY_HAVE_MEDIA(celt_pitch_xcorr), /* Media */ + MAY_HAVE_NEON(celt_pitch_xcorr) /* NEON */ +}; +# else /* !FIXED_POINT */ +# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +void (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *, + const opus_val16 *, opus_val32 *, int, int) = { + celt_pitch_xcorr_c, /* ARMv4 */ + celt_pitch_xcorr_c, /* EDSP */ + celt_pitch_xcorr_c, /* Media */ + celt_pitch_xcorr_float_neon /* Neon */ +}; +# endif +# endif /* FIXED_POINT */ + +# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# if defined(HAVE_ARM_NE10) +# if defined(CUSTOM_MODES) +int (*const OPUS_FFT_ALLOC_ARCH_IMPL[OPUS_ARCHMASK+1])(kiss_fft_state *st) = { + opus_fft_alloc_arch_c, /* ARMv4 */ + opus_fft_alloc_arch_c, /* EDSP */ + opus_fft_alloc_arch_c, /* Media */ + opus_fft_alloc_arm_neon /* Neon with NE10 library support */ +}; + +void (*const OPUS_FFT_FREE_ARCH_IMPL[OPUS_ARCHMASK+1])(kiss_fft_state *st) = { + opus_fft_free_arch_c, /* ARMv4 */ + opus_fft_free_arch_c, /* EDSP */ + opus_fft_free_arch_c, /* Media */ + opus_fft_free_arm_neon /* Neon with NE10 */ +}; +# endif /* CUSTOM_MODES */ + +void (*const OPUS_FFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg, + const kiss_fft_cpx *fin, + kiss_fft_cpx *fout) = { + opus_fft_c, /* ARMv4 */ + opus_fft_c, /* EDSP */ + opus_fft_c, /* Media */ + opus_fft_neon /* Neon with NE10 */ +}; + +void (*const OPUS_IFFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg, + const kiss_fft_cpx *fin, + kiss_fft_cpx *fout) = { + opus_ifft_c, /* ARMv4 */ + opus_ifft_c, /* EDSP */ + opus_ifft_c, /* Media */ + opus_ifft_neon /* Neon with NE10 */ +}; + +void (*const CLT_MDCT_FORWARD_IMPL[OPUS_ARCHMASK+1])(const mdct_lookup *l, + kiss_fft_scalar *in, + kiss_fft_scalar * OPUS_RESTRICT out, + const opus_val16 *window, + int overlap, int shift, + int stride, int arch) = { + clt_mdct_forward_c, /* ARMv4 */ + clt_mdct_forward_c, /* EDSP */ + clt_mdct_forward_c, /* Media */ + clt_mdct_forward_neon /* Neon with NE10 */ +}; + +void (*const CLT_MDCT_BACKWARD_IMPL[OPUS_ARCHMASK+1])(const mdct_lookup *l, + kiss_fft_scalar *in, + kiss_fft_scalar * OPUS_RESTRICT out, + const opus_val16 *window, + int overlap, int shift, + int stride, int arch) = { + clt_mdct_backward_c, /* ARMv4 */ + clt_mdct_backward_c, /* EDSP */ + clt_mdct_backward_c, /* Media */ + clt_mdct_backward_neon /* Neon with NE10 */ +}; + +# endif /* HAVE_ARM_NE10 */ +# endif /* OPUS_ARM_MAY_HAVE_NEON_INTR */ + +#endif /* OPUS_HAVE_RTCD */ diff --git a/thirdparty/opus/celt/arm/armcpu.c b/thirdparty/opus/celt/arm/armcpu.c new file mode 100644 index 0000000000..5e5d10c344 --- /dev/null +++ b/thirdparty/opus/celt/arm/armcpu.c @@ -0,0 +1,174 @@ +/* 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. +*/ + +/* Original code from libtheora modified to suit to Opus */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef OPUS_HAVE_RTCD + +#include "armcpu.h" +#include "cpu_support.h" +#include "os_support.h" +#include "opus_types.h" + +#define OPUS_CPU_ARM_V4 (1) +#define OPUS_CPU_ARM_EDSP (1<<1) +#define OPUS_CPU_ARM_MEDIA (1<<2) +#define OPUS_CPU_ARM_NEON (1<<3) + +#if defined(_MSC_VER) +/*For GetExceptionCode() and EXCEPTION_ILLEGAL_INSTRUCTION.*/ +# define WIN32_LEAN_AND_MEAN +# define WIN32_EXTRA_LEAN +# include <windows.h> + +static OPUS_INLINE opus_uint32 opus_cpu_capabilities(void){ + opus_uint32 flags; + flags=0; + /* MSVC has no OPUS_INLINE __asm support for ARM, but it does let you __emit + * instructions via their assembled hex code. + * All of these instructions should be essentially nops. */ +# if defined(OPUS_ARM_MAY_HAVE_EDSP) + __try{ + /*PLD [r13]*/ + __emit(0xF5DDF000); + flags|=OPUS_CPU_ARM_EDSP; + } + __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){ + /*Ignore exception.*/ + } +# if defined(OPUS_ARM_MAY_HAVE_MEDIA) + __try{ + /*SHADD8 r3,r3,r3*/ + __emit(0xE6333F93); + flags|=OPUS_CPU_ARM_MEDIA; + } + __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){ + /*Ignore exception.*/ + } +# if defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR) + __try{ + /*VORR q0,q0,q0*/ + __emit(0xF2200150); + flags|=OPUS_CPU_ARM_NEON; + } + __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){ + /*Ignore exception.*/ + } +# endif +# endif +# endif + return flags; +} + +#elif defined(__linux__) +/* Linux based */ +opus_uint32 opus_cpu_capabilities(void) +{ + opus_uint32 flags = 0; + FILE *cpuinfo; + + /* Reading /proc/self/auxv would be easier, but that doesn't work reliably on + * Android */ + cpuinfo = fopen("/proc/cpuinfo", "r"); + + if(cpuinfo != NULL) + { + /* 512 should be enough for anybody (it's even enough for all the flags that + * x86 has accumulated... so far). */ + char buf[512]; + + while(fgets(buf, 512, cpuinfo) != NULL) + { +# if defined(OPUS_ARM_MAY_HAVE_EDSP) || defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR) + /* Search for edsp and neon flag */ + if(memcmp(buf, "Features", 8) == 0) + { + char *p; +# if defined(OPUS_ARM_MAY_HAVE_EDSP) + p = strstr(buf, " edsp"); + if(p != NULL && (p[5] == ' ' || p[5] == '\n')) + flags |= OPUS_CPU_ARM_EDSP; +# endif + +# if defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR) + p = strstr(buf, " neon"); + if(p != NULL && (p[5] == ' ' || p[5] == '\n')) + flags |= OPUS_CPU_ARM_NEON; +# endif + } +# endif + +# if defined(OPUS_ARM_MAY_HAVE_MEDIA) + /* Search for media capabilities (>= ARMv6) */ + if(memcmp(buf, "CPU architecture:", 17) == 0) + { + int version; + version = atoi(buf+17); + + if(version >= 6) + flags |= OPUS_CPU_ARM_MEDIA; + } +# endif + } + + fclose(cpuinfo); + } + return flags; +} +#else +/* The feature registers which can tell us what the processor supports are + * accessible in priveleged modes only, so we can't have a general user-space + * detection method like on x86.*/ +# error "Configured to use ARM asm but no CPU detection method available for " \ + "your platform. Reconfigure with --disable-rtcd (or send patches)." +#endif + +int opus_select_arch(void) +{ + opus_uint32 flags = opus_cpu_capabilities(); + int arch = 0; + + if(!(flags & OPUS_CPU_ARM_EDSP)) + return arch; + arch++; + + if(!(flags & OPUS_CPU_ARM_MEDIA)) + return arch; + arch++; + + if(!(flags & OPUS_CPU_ARM_NEON)) + return arch; + arch++; + + return arch; +} + +#endif diff --git a/drivers/opus/celt/arm/armcpu.h b/thirdparty/opus/celt/arm/armcpu.h index ac5744606e..ac5744606e 100644 --- a/drivers/opus/celt/arm/armcpu.h +++ b/thirdparty/opus/celt/arm/armcpu.h diff --git a/drivers/opus/celt/arm/armopts.s.in b/thirdparty/opus/celt/arm/armopts.s.in index 3d8aaf2754..3d8aaf2754 100644 --- a/drivers/opus/celt/arm/armopts.s.in +++ b/thirdparty/opus/celt/arm/armopts.s.in diff --git a/thirdparty/opus/celt/arm/celt_ne10_fft.c b/thirdparty/opus/celt/arm/celt_ne10_fft.c new file mode 100644 index 0000000000..42d96a7117 --- /dev/null +++ b/thirdparty/opus/celt/arm/celt_ne10_fft.c @@ -0,0 +1,174 @@ +/* Copyright (c) 2015 Xiph.Org Foundation + Written by Viswanath Puttagunta */ +/** + @file celt_ne10_fft.c + @brief ARM Neon optimizations for fft using NE10 library + */ + +/* + 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 SKIP_CONFIG_H +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#endif + +#include <NE10_init.h> +#include <NE10_dsp.h> +#include "os_support.h" +#include "kiss_fft.h" +#include "stack_alloc.h" + +#if !defined(FIXED_POINT) +# define NE10_FFT_ALLOC_C2C_TYPE_NEON ne10_fft_alloc_c2c_float32_neon +# define NE10_FFT_CFG_TYPE_T ne10_fft_cfg_float32_t +# define NE10_FFT_STATE_TYPE_T ne10_fft_state_float32_t +# define NE10_FFT_DESTROY_C2C_TYPE ne10_fft_destroy_c2c_float32 +# define NE10_FFT_CPX_TYPE_T ne10_fft_cpx_float32_t +# define NE10_FFT_C2C_1D_TYPE_NEON ne10_fft_c2c_1d_float32_neon +#else +# define NE10_FFT_ALLOC_C2C_TYPE_NEON(nfft) ne10_fft_alloc_c2c_int32_neon(nfft) +# define NE10_FFT_CFG_TYPE_T ne10_fft_cfg_int32_t +# define NE10_FFT_STATE_TYPE_T ne10_fft_state_int32_t +# define NE10_FFT_DESTROY_C2C_TYPE ne10_fft_destroy_c2c_int32 +# define NE10_FFT_DESTROY_C2C_TYPE ne10_fft_destroy_c2c_int32 +# define NE10_FFT_CPX_TYPE_T ne10_fft_cpx_int32_t +# define NE10_FFT_C2C_1D_TYPE_NEON ne10_fft_c2c_1d_int32_neon +#endif + +#if defined(CUSTOM_MODES) + +/* nfft lengths in NE10 that support scaled fft */ +# define NE10_FFTSCALED_SUPPORT_MAX 4 +static const int ne10_fft_scaled_support[NE10_FFTSCALED_SUPPORT_MAX] = { + 480, 240, 120, 60 +}; + +int opus_fft_alloc_arm_neon(kiss_fft_state *st) +{ + int i; + size_t memneeded = sizeof(struct arch_fft_state); + + st->arch_fft = (arch_fft_state *)opus_alloc(memneeded); + if (!st->arch_fft) + return -1; + + for (i = 0; i < NE10_FFTSCALED_SUPPORT_MAX; i++) { + if(st->nfft == ne10_fft_scaled_support[i]) + break; + } + if (i == NE10_FFTSCALED_SUPPORT_MAX) { + /* This nfft length (scaled fft) is not supported in NE10 */ + st->arch_fft->is_supported = 0; + st->arch_fft->priv = NULL; + } + else { + st->arch_fft->is_supported = 1; + st->arch_fft->priv = (void *)NE10_FFT_ALLOC_C2C_TYPE_NEON(st->nfft); + if (st->arch_fft->priv == NULL) { + return -1; + } + } + return 0; +} + +void opus_fft_free_arm_neon(kiss_fft_state *st) +{ + NE10_FFT_CFG_TYPE_T cfg; + + if (!st->arch_fft) + return; + + cfg = (NE10_FFT_CFG_TYPE_T)st->arch_fft->priv; + if (cfg) + NE10_FFT_DESTROY_C2C_TYPE(cfg); + opus_free(st->arch_fft); +} +#endif + +void opus_fft_neon(const kiss_fft_state *st, + const kiss_fft_cpx *fin, + kiss_fft_cpx *fout) +{ + NE10_FFT_STATE_TYPE_T state; + NE10_FFT_CFG_TYPE_T cfg = &state; + VARDECL(NE10_FFT_CPX_TYPE_T, buffer); + SAVE_STACK; + ALLOC(buffer, st->nfft, NE10_FFT_CPX_TYPE_T); + + if (!st->arch_fft->is_supported) { + /* This nfft length (scaled fft) not supported in NE10 */ + opus_fft_c(st, fin, fout); + } + else { + memcpy((void *)cfg, st->arch_fft->priv, sizeof(NE10_FFT_STATE_TYPE_T)); + state.buffer = (NE10_FFT_CPX_TYPE_T *)&buffer[0]; +#if !defined(FIXED_POINT) + state.is_forward_scaled = 1; + + NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout, + (NE10_FFT_CPX_TYPE_T *)fin, + cfg, 0); +#else + NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout, + (NE10_FFT_CPX_TYPE_T *)fin, + cfg, 0, 1); +#endif + } + RESTORE_STACK; +} + +void opus_ifft_neon(const kiss_fft_state *st, + const kiss_fft_cpx *fin, + kiss_fft_cpx *fout) +{ + NE10_FFT_STATE_TYPE_T state; + NE10_FFT_CFG_TYPE_T cfg = &state; + VARDECL(NE10_FFT_CPX_TYPE_T, buffer); + SAVE_STACK; + ALLOC(buffer, st->nfft, NE10_FFT_CPX_TYPE_T); + + if (!st->arch_fft->is_supported) { + /* This nfft length (scaled fft) not supported in NE10 */ + opus_ifft_c(st, fin, fout); + } + else { + memcpy((void *)cfg, st->arch_fft->priv, sizeof(NE10_FFT_STATE_TYPE_T)); + state.buffer = (NE10_FFT_CPX_TYPE_T *)&buffer[0]; +#if !defined(FIXED_POINT) + state.is_backward_scaled = 0; + + NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout, + (NE10_FFT_CPX_TYPE_T *)fin, + cfg, 1); +#else + NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout, + (NE10_FFT_CPX_TYPE_T *)fin, + cfg, 1, 0); +#endif + } + RESTORE_STACK; +} diff --git a/thirdparty/opus/celt/arm/celt_ne10_mdct.c b/thirdparty/opus/celt/arm/celt_ne10_mdct.c new file mode 100644 index 0000000000..293c3efd7a --- /dev/null +++ b/thirdparty/opus/celt/arm/celt_ne10_mdct.c @@ -0,0 +1,258 @@ +/* Copyright (c) 2015 Xiph.Org Foundation + Written by Viswanath Puttagunta */ +/** + @file celt_ne10_mdct.c + @brief ARM Neon optimizations for mdct using NE10 library + */ + +/* + 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 SKIP_CONFIG_H +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#endif + +#include "kiss_fft.h" +#include "_kiss_fft_guts.h" +#include "mdct.h" +#include "stack_alloc.h" + +void clt_mdct_forward_neon(const mdct_lookup *l, + kiss_fft_scalar *in, + kiss_fft_scalar * OPUS_RESTRICT out, + const opus_val16 *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; + + SAVE_STACK; + + 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 opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1); + const opus_val16 * 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++ = MULT16_32_Q15(*wp2, xp1[N2]) + MULT16_32_Q15(*wp1,*xp2); + *yp++ = MULT16_32_Q15(*wp1, *xp1) - MULT16_32_Q15(*wp2, xp2[-N2]); + 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++ = -MULT16_32_Q15(*wp1, xp1[-N2]) + MULT16_32_Q15(*wp2, *xp2); + *yp++ = MULT16_32_Q15(*wp2, *xp1) + MULT16_32_Q15(*wp1, xp2[N2]); + xp1+=2; + xp2-=2; + wp1+=2; + wp2-=2; + } + } + /* Pre-rotation */ + { + kiss_fft_scalar * OPUS_RESTRICT yp = f; + const kiss_twiddle_scalar *t = &trig[0]; + 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); + yc.r = yr; + yc.i = yi; + f2[i] = yc; + } + } + + opus_fft(st, f2, (kiss_fft_cpx *)f, arch); + + /* Post-rotate */ + { + /* Temp pointers to make it really clear to the compiler what we're doing */ + const kiss_fft_cpx * OPUS_RESTRICT fp = (kiss_fft_cpx *)f; + 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; + yr = S_MUL(fp->i,t[N4+i]) - S_MUL(fp->r,t[i]); + yi = S_MUL(fp->r,t[N4+i]) + S_MUL(fp->i,t[i]); + *yp1 = yr; + *yp2 = yi; + fp++; + yp1 += 2*stride; + yp2 -= 2*stride; + } + } + RESTORE_STACK; +} + +void clt_mdct_backward_neon(const mdct_lookup *l, + kiss_fft_scalar *in, + kiss_fft_scalar * OPUS_RESTRICT out, + const opus_val16 * OPUS_RESTRICT window, + int overlap, int shift, int stride, int arch) +{ + int i; + int N, N2, N4; + VARDECL(kiss_fft_scalar, f); + const kiss_twiddle_scalar *trig; + const kiss_fft_state *st = l->kfft[shift]; + + 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); + + /* 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 = f; + const kiss_twiddle_scalar * OPUS_RESTRICT t = &trig[0]; + for(i=0;i<N4;i++) + { + kiss_fft_scalar yr, yi; + yr = S_MUL(*xp2, t[i]) + S_MUL(*xp1, t[N4+i]); + yi = S_MUL(*xp1, t[i]) - S_MUL(*xp2, t[N4+i]); + yp[2*i] = yr; + yp[2*i+1] = yi; + xp1+=2*stride; + xp2-=2*stride; + } + } + + opus_ifft(st, (kiss_fft_cpx *)f, (kiss_fft_cpx*)(out+(overlap>>1)), arch); + + /* 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; + re = yp0[0]; + im = yp0[1]; + t0 = t[i]; + t1 = t[N4+i]; + /* We'd scale up by 2 here, but instead it's done when mixing the windows */ + yr = S_MUL(re,t0) + S_MUL(im,t1); + yi = S_MUL(re,t1) - S_MUL(im,t0); + re = yp1[0]; + im = yp1[1]; + 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 = S_MUL(re,t0) + S_MUL(im,t1); + yi = S_MUL(re,t1) - S_MUL(im,t0); + 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 opus_val16 * OPUS_RESTRICT wp1 = window; + const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1; + + for(i = 0; i < overlap/2; i++) + { + kiss_fft_scalar x1, x2; + x1 = *xp1; + x2 = *yp1; + *yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1); + *xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1); + wp1++; + wp2--; + } + } + RESTORE_STACK; +} diff --git a/thirdparty/opus/celt/arm/celt_neon_intr.c b/thirdparty/opus/celt/arm/celt_neon_intr.c new file mode 100644 index 0000000000..47dce15ba5 --- /dev/null +++ b/thirdparty/opus/celt/arm/celt_neon_intr.c @@ -0,0 +1,252 @@ +/* Copyright (c) 2014-2015 Xiph.Org Foundation + Written by Viswanath Puttagunta */ +/** + @file celt_neon_intr.c + @brief ARM Neon Intrinsic optimizations 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <arm_neon.h> +#include "../pitch.h" + +#if !defined(FIXED_POINT) +/* + * Function: xcorr_kernel_neon_float + * --------------------------------- + * Computes 4 correlation values and stores them in sum[4] + */ +static void xcorr_kernel_neon_float(const float32_t *x, const float32_t *y, + float32_t sum[4], int len) { + float32x4_t YY[3]; + float32x4_t YEXT[3]; + float32x4_t XX[2]; + float32x2_t XX_2; + float32x4_t SUMM; + const float32_t *xi = x; + const float32_t *yi = y; + + celt_assert(len>0); + + YY[0] = vld1q_f32(yi); + SUMM = vdupq_n_f32(0); + + /* Consume 8 elements in x vector and 12 elements in y + * vector. However, the 12'th element never really gets + * touched in this loop. So, if len == 8, then we only + * must access y[0] to y[10]. y[11] must not be accessed + * hence make sure len > 8 and not len >= 8 + */ + while (len > 8) { + yi += 4; + YY[1] = vld1q_f32(yi); + yi += 4; + YY[2] = vld1q_f32(yi); + + XX[0] = vld1q_f32(xi); + xi += 4; + XX[1] = vld1q_f32(xi); + xi += 4; + + SUMM = vmlaq_lane_f32(SUMM, YY[0], vget_low_f32(XX[0]), 0); + YEXT[0] = vextq_f32(YY[0], YY[1], 1); + SUMM = vmlaq_lane_f32(SUMM, YEXT[0], vget_low_f32(XX[0]), 1); + YEXT[1] = vextq_f32(YY[0], YY[1], 2); + SUMM = vmlaq_lane_f32(SUMM, YEXT[1], vget_high_f32(XX[0]), 0); + YEXT[2] = vextq_f32(YY[0], YY[1], 3); + SUMM = vmlaq_lane_f32(SUMM, YEXT[2], vget_high_f32(XX[0]), 1); + + SUMM = vmlaq_lane_f32(SUMM, YY[1], vget_low_f32(XX[1]), 0); + YEXT[0] = vextq_f32(YY[1], YY[2], 1); + SUMM = vmlaq_lane_f32(SUMM, YEXT[0], vget_low_f32(XX[1]), 1); + YEXT[1] = vextq_f32(YY[1], YY[2], 2); + SUMM = vmlaq_lane_f32(SUMM, YEXT[1], vget_high_f32(XX[1]), 0); + YEXT[2] = vextq_f32(YY[1], YY[2], 3); + SUMM = vmlaq_lane_f32(SUMM, YEXT[2], vget_high_f32(XX[1]), 1); + + YY[0] = YY[2]; + len -= 8; + } + + /* Consume 4 elements in x vector and 8 elements in y + * vector. However, the 8'th element in y never really gets + * touched in this loop. So, if len == 4, then we only + * must access y[0] to y[6]. y[7] must not be accessed + * hence make sure len>4 and not len>=4 + */ + if (len > 4) { + yi += 4; + YY[1] = vld1q_f32(yi); + + XX[0] = vld1q_f32(xi); + xi += 4; + + SUMM = vmlaq_lane_f32(SUMM, YY[0], vget_low_f32(XX[0]), 0); + YEXT[0] = vextq_f32(YY[0], YY[1], 1); + SUMM = vmlaq_lane_f32(SUMM, YEXT[0], vget_low_f32(XX[0]), 1); + YEXT[1] = vextq_f32(YY[0], YY[1], 2); + SUMM = vmlaq_lane_f32(SUMM, YEXT[1], vget_high_f32(XX[0]), 0); + YEXT[2] = vextq_f32(YY[0], YY[1], 3); + SUMM = vmlaq_lane_f32(SUMM, YEXT[2], vget_high_f32(XX[0]), 1); + + YY[0] = YY[1]; + len -= 4; + } + + while (--len > 0) { + XX_2 = vld1_dup_f32(xi++); + SUMM = vmlaq_lane_f32(SUMM, YY[0], XX_2, 0); + YY[0]= vld1q_f32(++yi); + } + + XX_2 = vld1_dup_f32(xi); + SUMM = vmlaq_lane_f32(SUMM, YY[0], XX_2, 0); + + vst1q_f32(sum, SUMM); +} + +/* + * Function: xcorr_kernel_neon_float_process1 + * --------------------------------- + * Computes single correlation values and stores in *sum + */ +static void xcorr_kernel_neon_float_process1(const float32_t *x, + const float32_t *y, float32_t *sum, int len) { + float32x4_t XX[4]; + float32x4_t YY[4]; + float32x2_t XX_2; + float32x2_t YY_2; + float32x4_t SUMM; + float32x2_t SUMM_2[2]; + const float32_t *xi = x; + const float32_t *yi = y; + + SUMM = vdupq_n_f32(0); + + /* Work on 16 values per iteration */ + while (len >= 16) { + XX[0] = vld1q_f32(xi); + xi += 4; + XX[1] = vld1q_f32(xi); + xi += 4; + XX[2] = vld1q_f32(xi); + xi += 4; + XX[3] = vld1q_f32(xi); + xi += 4; + + YY[0] = vld1q_f32(yi); + yi += 4; + YY[1] = vld1q_f32(yi); + yi += 4; + YY[2] = vld1q_f32(yi); + yi += 4; + YY[3] = vld1q_f32(yi); + yi += 4; + + SUMM = vmlaq_f32(SUMM, YY[0], XX[0]); + SUMM = vmlaq_f32(SUMM, YY[1], XX[1]); + SUMM = vmlaq_f32(SUMM, YY[2], XX[2]); + SUMM = vmlaq_f32(SUMM, YY[3], XX[3]); + len -= 16; + } + + /* Work on 8 values */ + if (len >= 8) { + XX[0] = vld1q_f32(xi); + xi += 4; + XX[1] = vld1q_f32(xi); + xi += 4; + + YY[0] = vld1q_f32(yi); + yi += 4; + YY[1] = vld1q_f32(yi); + yi += 4; + + SUMM = vmlaq_f32(SUMM, YY[0], XX[0]); + SUMM = vmlaq_f32(SUMM, YY[1], XX[1]); + len -= 8; + } + + /* Work on 4 values */ + if (len >= 4) { + XX[0] = vld1q_f32(xi); + xi += 4; + YY[0] = vld1q_f32(yi); + yi += 4; + SUMM = vmlaq_f32(SUMM, YY[0], XX[0]); + len -= 4; + } + + /* Start accumulating results */ + SUMM_2[0] = vget_low_f32(SUMM); + if (len >= 2) { + /* While at it, consume 2 more values if available */ + XX_2 = vld1_f32(xi); + xi += 2; + YY_2 = vld1_f32(yi); + yi += 2; + SUMM_2[0] = vmla_f32(SUMM_2[0], YY_2, XX_2); + len -= 2; + } + SUMM_2[1] = vget_high_f32(SUMM); + SUMM_2[0] = vadd_f32(SUMM_2[0], SUMM_2[1]); + SUMM_2[0] = vpadd_f32(SUMM_2[0], SUMM_2[0]); + /* Ok, now we have result accumulated in SUMM_2[0].0 */ + + if (len > 0) { + /* Case when you have one value left */ + XX_2 = vld1_dup_f32(xi); + YY_2 = vld1_dup_f32(yi); + SUMM_2[0] = vmla_f32(SUMM_2[0], XX_2, YY_2); + } + + vst1_lane_f32(sum, SUMM_2[0], 0); +} + +void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y, + opus_val32 *xcorr, int len, int max_pitch) { + int i; + celt_assert(max_pitch > 0); + celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0); + + for (i = 0; i < (max_pitch-3); i += 4) { + xcorr_kernel_neon_float((const float32_t *)_x, (const float32_t *)_y+i, + (float32_t *)xcorr+i, len); + } + + /* In case max_pitch isn't multiple of 4 + * compute single correlation value per iteration + */ + for (; i < max_pitch; i++) { + xcorr_kernel_neon_float_process1((const float32_t *)_x, + (const float32_t *)_y+i, (float32_t *)xcorr+i, len); + } +} +#endif diff --git a/drivers/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S b/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S index 5b2ee55a10..5b2ee55a10 100644 --- a/drivers/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S +++ b/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S diff --git a/drivers/opus/celt/arm/celt_pitch_xcorr_arm.s b/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm.s index f96e0a88bb..f96e0a88bb 100644 --- a/drivers/opus/celt/arm/celt_pitch_xcorr_arm.s +++ b/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm.s diff --git a/thirdparty/opus/celt/arm/fft_arm.h b/thirdparty/opus/celt/arm/fft_arm.h new file mode 100644 index 0000000000..0cb55d8e22 --- /dev/null +++ b/thirdparty/opus/celt/arm/fft_arm.h @@ -0,0 +1,72 @@ +/* Copyright (c) 2015 Xiph.Org Foundation + Written by Viswanath Puttagunta */ +/** + @file fft_arm.h + @brief ARM Neon Intrinsic optimizations for fft using NE10 library + */ + +/* + 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(FFT_ARM_H) +#define FFT_ARM_H + +#include "config.h" +#include "kiss_fft.h" + +#if defined(HAVE_ARM_NE10) + +int opus_fft_alloc_arm_neon(kiss_fft_state *st); +void opus_fft_free_arm_neon(kiss_fft_state *st); + +void opus_fft_neon(const kiss_fft_state *st, + const kiss_fft_cpx *fin, + kiss_fft_cpx *fout); + +void opus_ifft_neon(const kiss_fft_state *st, + const kiss_fft_cpx *fin, + kiss_fft_cpx *fout); + +#if !defined(OPUS_HAVE_RTCD) +#define OVERRIDE_OPUS_FFT (1) + +#define opus_fft_alloc_arch(_st, arch) \ + ((void)(arch), opus_fft_alloc_arm_neon(_st)) + +#define opus_fft_free_arch(_st, arch) \ + ((void)(arch), opus_fft_free_arm_neon(_st)) + +#define opus_fft(_st, _fin, _fout, arch) \ + ((void)(arch), opus_fft_neon(_st, _fin, _fout)) + +#define opus_ifft(_st, _fin, _fout, arch) \ + ((void)(arch), opus_ifft_neon(_st, _fin, _fout)) + +#endif /* OPUS_HAVE_RTCD */ + +#endif /* HAVE_ARM_NE10 */ + +#endif diff --git a/thirdparty/opus/celt/arm/fixed_arm64.h b/thirdparty/opus/celt/arm/fixed_arm64.h new file mode 100644 index 0000000000..c6fbd3db2c --- /dev/null +++ b/thirdparty/opus/celt/arm/fixed_arm64.h @@ -0,0 +1,35 @@ +/* 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. + + 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_ARM64_H +#define FIXED_ARM64_H + +#include <arm_neon.h> + +#undef SIG2WORD16 +#define SIG2WORD16(x) (vqmovns_s32(PSHR32((x), SIG_SHIFT))) + +#endif diff --git a/drivers/opus/celt/arm/fixed_armv4.h b/thirdparty/opus/celt/arm/fixed_armv4.h index efb3b1896a..efb3b1896a 100644 --- a/drivers/opus/celt/arm/fixed_armv4.h +++ b/thirdparty/opus/celt/arm/fixed_armv4.h diff --git a/thirdparty/opus/celt/arm/fixed_armv5e.h b/thirdparty/opus/celt/arm/fixed_armv5e.h new file mode 100644 index 0000000000..36a6321101 --- /dev/null +++ b/thirdparty/opus/celt/arm/fixed_armv5e.h @@ -0,0 +1,151 @@ +/* Copyright (C) 2007-2009 Xiph.Org Foundation + Copyright (C) 2003-2008 Jean-Marc Valin + Copyright (C) 2007-2008 CSIRO + 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 FIXED_ARMv5E_H +#define FIXED_ARMv5E_H + +#include "fixed_armv4.h" + +/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */ +#undef MULT16_32_Q16 +static OPUS_INLINE opus_val32 MULT16_32_Q16_armv5e(opus_val16 a, opus_val32 b) +{ + int res; + __asm__( + "#MULT16_32_Q16\n\t" + "smulwb %0, %1, %2\n\t" + : "=r"(res) + : "r"(b),"r"(a) + ); + return res; +} +#define MULT16_32_Q16(a, b) (MULT16_32_Q16_armv5e(a, b)) + + +/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */ +#undef MULT16_32_Q15 +static OPUS_INLINE opus_val32 MULT16_32_Q15_armv5e(opus_val16 a, opus_val32 b) +{ + int res; + __asm__( + "#MULT16_32_Q15\n\t" + "smulwb %0, %1, %2\n\t" + : "=r"(res) + : "r"(b), "r"(a) + ); + return res<<1; +} +#define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv5e(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. */ +#undef MAC16_32_Q15 +static OPUS_INLINE opus_val32 MAC16_32_Q15_armv5e(opus_val32 c, opus_val16 a, + opus_val32 b) +{ + int res; + __asm__( + "#MAC16_32_Q15\n\t" + "smlawb %0, %1, %2, %3;\n" + : "=r"(res) + : "r"(b<<1), "r"(a), "r"(c) + ); + return res; +} +#define MAC16_32_Q15(c, a, b) (MAC16_32_Q15_armv5e(c, a, b)) + +/** 16x32 multiply, followed by a 16-bit shift right and 32-bit add. + Result fits in 32 bits. */ +#undef MAC16_32_Q16 +static OPUS_INLINE opus_val32 MAC16_32_Q16_armv5e(opus_val32 c, opus_val16 a, + opus_val32 b) +{ + int res; + __asm__( + "#MAC16_32_Q16\n\t" + "smlawb %0, %1, %2, %3;\n" + : "=r"(res) + : "r"(b), "r"(a), "r"(c) + ); + return res; +} +#define MAC16_32_Q16(c, a, b) (MAC16_32_Q16_armv5e(c, a, b)) + +/** 16x16 multiply-add where the result fits in 32 bits */ +#undef MAC16_16 +static OPUS_INLINE opus_val32 MAC16_16_armv5e(opus_val32 c, opus_val16 a, + opus_val16 b) +{ + int res; + __asm__( + "#MAC16_16\n\t" + "smlabb %0, %1, %2, %3;\n" + : "=r"(res) + : "r"(a), "r"(b), "r"(c) + ); + return res; +} +#define MAC16_16(c, a, b) (MAC16_16_armv5e(c, a, b)) + +/** 16x16 multiplication where the result fits in 32 bits */ +#undef MULT16_16 +static OPUS_INLINE opus_val32 MULT16_16_armv5e(opus_val16 a, opus_val16 b) +{ + int res; + __asm__( + "#MULT16_16\n\t" + "smulbb %0, %1, %2;\n" + : "=r"(res) + : "r"(a), "r"(b) + ); + return res; +} +#define MULT16_16(a, b) (MULT16_16_armv5e(a, b)) + +#ifdef OPUS_ARM_INLINE_MEDIA + +#undef SIG2WORD16 +static OPUS_INLINE opus_val16 SIG2WORD16_armv6(opus_val32 x) +{ + celt_sig res; + __asm__( + "#SIG2WORD16\n\t" + "ssat %0, #16, %1, ASR #12\n\t" + : "=r"(res) + : "r"(x+2048) + ); + return EXTRACT16(res); +} +#define SIG2WORD16(x) (SIG2WORD16_armv6(x)) + +#endif /* OPUS_ARM_INLINE_MEDIA */ + +#endif diff --git a/thirdparty/opus/celt/arm/kiss_fft_armv4.h b/thirdparty/opus/celt/arm/kiss_fft_armv4.h new file mode 100644 index 0000000000..e4faad6f2b --- /dev/null +++ b/thirdparty/opus/celt/arm/kiss_fft_armv4.h @@ -0,0 +1,121 @@ +/*Copyright (c) 2013, Xiph.Org Foundation and contributors. + + 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_ARMv4_H +#define KISS_FFT_ARMv4_H + +#if !defined(KISS_FFT_GUTS_H) +#error "This file should only be included from _kiss_fft_guts.h" +#endif + +#ifdef FIXED_POINT + +#undef C_MUL +#define C_MUL(m,a,b) \ + do{ \ + int br__; \ + int bi__; \ + int tt__; \ + __asm__ __volatile__( \ + "#C_MUL\n\t" \ + "ldrsh %[br], [%[bp], #0]\n\t" \ + "ldm %[ap], {r0,r1}\n\t" \ + "ldrsh %[bi], [%[bp], #2]\n\t" \ + "smull %[tt], %[mi], r1, %[br]\n\t" \ + "smlal %[tt], %[mi], r0, %[bi]\n\t" \ + "rsb %[bi], %[bi], #0\n\t" \ + "smull %[br], %[mr], r0, %[br]\n\t" \ + "mov %[tt], %[tt], lsr #15\n\t" \ + "smlal %[br], %[mr], r1, %[bi]\n\t" \ + "orr %[mi], %[tt], %[mi], lsl #17\n\t" \ + "mov %[br], %[br], lsr #15\n\t" \ + "orr %[mr], %[br], %[mr], lsl #17\n\t" \ + : [mr]"=r"((m).r), [mi]"=r"((m).i), \ + [br]"=&r"(br__), [bi]"=r"(bi__), [tt]"=r"(tt__) \ + : [ap]"r"(&(a)), [bp]"r"(&(b)) \ + : "r0", "r1" \ + ); \ + } \ + while(0) + +#undef C_MUL4 +#define C_MUL4(m,a,b) \ + do{ \ + int br__; \ + int bi__; \ + int tt__; \ + __asm__ __volatile__( \ + "#C_MUL4\n\t" \ + "ldrsh %[br], [%[bp], #0]\n\t" \ + "ldm %[ap], {r0,r1}\n\t" \ + "ldrsh %[bi], [%[bp], #2]\n\t" \ + "smull %[tt], %[mi], r1, %[br]\n\t" \ + "smlal %[tt], %[mi], r0, %[bi]\n\t" \ + "rsb %[bi], %[bi], #0\n\t" \ + "smull %[br], %[mr], r0, %[br]\n\t" \ + "mov %[tt], %[tt], lsr #17\n\t" \ + "smlal %[br], %[mr], r1, %[bi]\n\t" \ + "orr %[mi], %[tt], %[mi], lsl #15\n\t" \ + "mov %[br], %[br], lsr #17\n\t" \ + "orr %[mr], %[br], %[mr], lsl #15\n\t" \ + : [mr]"=r"((m).r), [mi]"=r"((m).i), \ + [br]"=&r"(br__), [bi]"=r"(bi__), [tt]"=r"(tt__) \ + : [ap]"r"(&(a)), [bp]"r"(&(b)) \ + : "r0", "r1" \ + ); \ + } \ + while(0) + +#undef C_MULC +#define C_MULC(m,a,b) \ + do{ \ + int br__; \ + int bi__; \ + int tt__; \ + __asm__ __volatile__( \ + "#C_MULC\n\t" \ + "ldrsh %[br], [%[bp], #0]\n\t" \ + "ldm %[ap], {r0,r1}\n\t" \ + "ldrsh %[bi], [%[bp], #2]\n\t" \ + "smull %[tt], %[mr], r0, %[br]\n\t" \ + "smlal %[tt], %[mr], r1, %[bi]\n\t" \ + "rsb %[bi], %[bi], #0\n\t" \ + "smull %[br], %[mi], r1, %[br]\n\t" \ + "mov %[tt], %[tt], lsr #15\n\t" \ + "smlal %[br], %[mi], r0, %[bi]\n\t" \ + "orr %[mr], %[tt], %[mr], lsl #17\n\t" \ + "mov %[br], %[br], lsr #15\n\t" \ + "orr %[mi], %[br], %[mi], lsl #17\n\t" \ + : [mr]"=r"((m).r), [mi]"=r"((m).i), \ + [br]"=&r"(br__), [bi]"=r"(bi__), [tt]"=r"(tt__) \ + : [ap]"r"(&(a)), [bp]"r"(&(b)) \ + : "r0", "r1" \ + ); \ + } \ + while(0) + +#endif /* FIXED_POINT */ + +#endif /* KISS_FFT_ARMv4_H */ diff --git a/thirdparty/opus/celt/arm/kiss_fft_armv5e.h b/thirdparty/opus/celt/arm/kiss_fft_armv5e.h new file mode 100644 index 0000000000..9eca183d77 --- /dev/null +++ b/thirdparty/opus/celt/arm/kiss_fft_armv5e.h @@ -0,0 +1,118 @@ +/*Copyright (c) 2013, Xiph.Org Foundation and contributors. + + 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_ARMv5E_H +#define KISS_FFT_ARMv5E_H + +#if !defined(KISS_FFT_GUTS_H) +#error "This file should only be included from _kiss_fft_guts.h" +#endif + +#ifdef FIXED_POINT + +#if defined(__thumb__)||defined(__thumb2__) +#define LDRD_CONS "Q" +#else +#define LDRD_CONS "Uq" +#endif + +#undef C_MUL +#define C_MUL(m,a,b) \ + do{ \ + int mr1__; \ + int mr2__; \ + int mi__; \ + long long aval__; \ + int bval__; \ + __asm__( \ + "#C_MUL\n\t" \ + "ldrd %[aval], %H[aval], %[ap]\n\t" \ + "ldr %[bval], %[bp]\n\t" \ + "smulwb %[mi], %H[aval], %[bval]\n\t" \ + "smulwb %[mr1], %[aval], %[bval]\n\t" \ + "smulwt %[mr2], %H[aval], %[bval]\n\t" \ + "smlawt %[mi], %[aval], %[bval], %[mi]\n\t" \ + : [mr1]"=r"(mr1__), [mr2]"=r"(mr2__), [mi]"=r"(mi__), \ + [aval]"=&r"(aval__), [bval]"=r"(bval__) \ + : [ap]LDRD_CONS(a), [bp]"m"(b) \ + ); \ + (m).r = SHL32(SUB32(mr1__, mr2__), 1); \ + (m).i = SHL32(mi__, 1); \ + } \ + while(0) + +#undef C_MUL4 +#define C_MUL4(m,a,b) \ + do{ \ + int mr1__; \ + int mr2__; \ + int mi__; \ + long long aval__; \ + int bval__; \ + __asm__( \ + "#C_MUL4\n\t" \ + "ldrd %[aval], %H[aval], %[ap]\n\t" \ + "ldr %[bval], %[bp]\n\t" \ + "smulwb %[mi], %H[aval], %[bval]\n\t" \ + "smulwb %[mr1], %[aval], %[bval]\n\t" \ + "smulwt %[mr2], %H[aval], %[bval]\n\t" \ + "smlawt %[mi], %[aval], %[bval], %[mi]\n\t" \ + : [mr1]"=r"(mr1__), [mr2]"=r"(mr2__), [mi]"=r"(mi__), \ + [aval]"=&r"(aval__), [bval]"=r"(bval__) \ + : [ap]LDRD_CONS(a), [bp]"m"(b) \ + ); \ + (m).r = SHR32(SUB32(mr1__, mr2__), 1); \ + (m).i = SHR32(mi__, 1); \ + } \ + while(0) + +#undef C_MULC +#define C_MULC(m,a,b) \ + do{ \ + int mr__; \ + int mi1__; \ + int mi2__; \ + long long aval__; \ + int bval__; \ + __asm__( \ + "#C_MULC\n\t" \ + "ldrd %[aval], %H[aval], %[ap]\n\t" \ + "ldr %[bval], %[bp]\n\t" \ + "smulwb %[mr], %[aval], %[bval]\n\t" \ + "smulwb %[mi1], %H[aval], %[bval]\n\t" \ + "smulwt %[mi2], %[aval], %[bval]\n\t" \ + "smlawt %[mr], %H[aval], %[bval], %[mr]\n\t" \ + : [mr]"=r"(mr__), [mi1]"=r"(mi1__), [mi2]"=r"(mi2__), \ + [aval]"=&r"(aval__), [bval]"=r"(bval__) \ + : [ap]LDRD_CONS(a), [bp]"m"(b) \ + ); \ + (m).r = SHL32(mr__, 1); \ + (m).i = SHL32(SUB32(mi1__, mi2__), 1); \ + } \ + while(0) + +#endif /* FIXED_POINT */ + +#endif /* KISS_FFT_GUTS_H */ diff --git a/thirdparty/opus/celt/arm/mdct_arm.h b/thirdparty/opus/celt/arm/mdct_arm.h new file mode 100644 index 0000000000..49cbb44576 --- /dev/null +++ b/thirdparty/opus/celt/arm/mdct_arm.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2015 Xiph.Org Foundation + Written by Viswanath Puttagunta */ +/** + @file arm_mdct.h + @brief ARM Neon Intrinsic optimizations for mdct using NE10 library + */ + +/* + 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(MDCT_ARM_H) +#define MDCT_ARM_H + +#include "config.h" +#include "mdct.h" + +#if defined(HAVE_ARM_NE10) +/** Compute a forward MDCT and scale by 4/N, trashes the input array */ +void clt_mdct_forward_neon(const mdct_lookup *l, kiss_fft_scalar *in, + kiss_fft_scalar * OPUS_RESTRICT out, + const opus_val16 *window, int overlap, + int shift, int stride, int arch); + +void clt_mdct_backward_neon(const mdct_lookup *l, kiss_fft_scalar *in, + kiss_fft_scalar * OPUS_RESTRICT out, + const opus_val16 *window, int overlap, + int shift, int stride, int arch); + +#if !defined(OPUS_HAVE_RTCD) +#define OVERRIDE_OPUS_MDCT (1) +#define clt_mdct_forward(_l, _in, _out, _window, _int, _shift, _stride, _arch) \ + clt_mdct_forward_neon(_l, _in, _out, _window, _int, _shift, _stride, _arch) +#define clt_mdct_backward(_l, _in, _out, _window, _int, _shift, _stride, _arch) \ + clt_mdct_backward_neon(_l, _in, _out, _window, _int, _shift, _stride, _arch) +#endif /* OPUS_HAVE_RTCD */ +#endif /* HAVE_ARM_NE10 */ + +#endif diff --git a/thirdparty/opus/celt/arm/pitch_arm.h b/thirdparty/opus/celt/arm/pitch_arm.h new file mode 100644 index 0000000000..8626ed75b9 --- /dev/null +++ b/thirdparty/opus/celt/arm/pitch_arm.h @@ -0,0 +1,68 @@ +/* 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. +*/ + +#if !defined(PITCH_ARM_H) +# define PITCH_ARM_H + +# include "armcpu.h" + +# if defined(FIXED_POINT) + +# if defined(OPUS_ARM_MAY_HAVE_NEON) +opus_val32 celt_pitch_xcorr_neon(const opus_val16 *_x, const opus_val16 *_y, + opus_val32 *xcorr, int len, int max_pitch); +# endif + +# if defined(OPUS_ARM_MAY_HAVE_MEDIA) +# define celt_pitch_xcorr_media MAY_HAVE_EDSP(celt_pitch_xcorr) +# endif + +# if defined(OPUS_ARM_MAY_HAVE_EDSP) +opus_val32 celt_pitch_xcorr_edsp(const opus_val16 *_x, const opus_val16 *_y, + opus_val32 *xcorr, int len, int max_pitch); +# endif + +# if !defined(OPUS_HAVE_RTCD) +# define OVERRIDE_PITCH_XCORR (1) +# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \ + ((void)(arch),PRESUME_NEON(celt_pitch_xcorr)(_x, _y, xcorr, len, max_pitch)) +# endif + +#else /* Start !FIXED_POINT */ +/* Float case */ +#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y, + opus_val32 *xcorr, int len, int max_pitch); +#if !defined(OPUS_HAVE_RTCD) || defined(OPUS_ARM_PRESUME_NEON_INTR) +#define OVERRIDE_PITCH_XCORR (1) +# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \ + ((void)(arch),celt_pitch_xcorr_float_neon(_x, _y, xcorr, len, max_pitch)) +#endif +#endif + +#endif /* end !FIXED_POINT */ +#endif diff --git a/thirdparty/opus/celt/bands.c b/thirdparty/opus/celt/bands.c new file mode 100644 index 0000000000..25f229e267 --- /dev/null +++ b/thirdparty/opus/celt/bands.c @@ -0,0 +1,1529 @@ +/* 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 */ +static opus_int16 bitexact_cos(opus_int16 x) +{ + opus_int32 tmp; + opus_int16 x2; + tmp = (4096+((opus_int32)(x)*(x)))>>13; + celt_assert(tmp<=32767); + x2 = tmp; + x2 = (32767-x2) + FRAC_MUL16(x2, (-7651 + FRAC_MUL16(x2, (8277 + FRAC_MUL16(-626, x2))))); + celt_assert(x2<=32766); + return 1+x2; +} + +static 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 i, c, N; + const opus_int16 *eBands = m->eBands; + 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 = celt_ilog2(maxval) - 14 + (((m->logN[i]>>BITRES)+LM+1)>>1); + j=eBands[i]<<LM; + if (shift>0) + { + do { + sum = MAC16_16(sum, EXTRACT16(SHR32(X[j+c*N],shift)), + EXTRACT16(SHR32(X[j+c*N],shift))); + } while (++j<eBands[i+1]<<LM); + } else { + do { + sum = MAC16_16(sum, EXTRACT16(SHL32(X[j+c*N],-shift)), + EXTRACT16(SHL32(X[j+c*N],-shift))); + } while (++j<eBands[i+1]<<LM); + } + /* We're adding one here to ensure the normalized band isn't larger than unity norm */ + bandE[i+c*m->nbEBands] = EPSILON+VSHR32(EXTEND32(celt_sqrt(sum)),-shift); + } else { + bandE[i+c*m->nbEBands] = EPSILON; + } + /*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 { + i=0; do { + opus_val16 g; + int j,shift; + opus_val16 E; + shift = celt_zlog2(bandE[i+c*m->nbEBands])-13; + E = VSHR32(bandE[i+c*m->nbEBands], shift); + g = EXTRACT16(celt_rcp(SHL32(E,3))); + j=M*eBands[i]; do { + X[j+c*N] = MULT16_16_Q15(VSHR32(freq[j+c*N],shift-1),g); + } 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 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_c(&X[c*N+(eBands[i]<<LM)], &X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM); + 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 opus_val16 *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]; + for (i=0;i<M*eBands[start];i++) + *f++ = 0; + for (i=start;i<end;i++) + { + int j, band_end; + opus_val16 g; + opus_val16 lg; +#ifdef FIXED_POINT + int shift; +#endif + j=M*eBands[i]; + band_end = M*eBands[i+1]; + lg = ADD16(bandLogE[i], SHL16((opus_val16)eMeans[i],6)); +#ifndef FIXED_POINT + g = celt_exp2(lg); +#else + /* Handle the integer part of the log energy */ + shift = 16-(lg>>DB_SHIFT); + if (shift>31) + { + shift=0; + g=0; + } else { + /* Handle the fractional part. */ + g = celt_exp2_frac(lg&((1<<DB_SHIFT)-1)); + } + /* Handle extreme gains with negative shift. */ + if (shift<0) + { + /* For shift < -2 we'd be likely to overflow, so we're capping + the gain here. This shouldn't happen unless the bitstream is + already corrupted. */ + if (shift < -2) + { + g = 32767; + shift = -2; + } + do { + *f++ = SHL32(MULT16_16(*x++, g), -shift); + } while (++j<band_end); + } else +#endif + /* Be careful of the fixed-point "else" just above when changing this code */ + do { + *f++ = SHR32(MULT16_16(*x++, g), shift); + } 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 opus_val16 *logE, const opus_val16 *prev1logE, + const opus_val16 *prev2logE, const int *pulses, opus_uint32 seed, 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_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; + opus_val16 prev1; + opus_val16 prev2; + opus_val32 Ediff; + opus_val16 r; + int renormalize=0; + prev1 = prev1logE[c*m->nbEBands+i]; + prev2 = prev2logE[c*m->nbEBands+i]; + if (C==1) + { + prev1 = MAX16(prev1,prev1logE[m->nbEBands+i]); + prev2 = MAX16(prev2,prev2logE[m->nbEBands+i]); + } + Ediff = EXTEND32(logE[c*m->nbEBands+i])-EXTEND32(MIN16(prev1,prev2)); + Ediff = MAX32(0, Ediff); + +#ifdef FIXED_POINT + if (Ediff < 16384) + { + opus_val32 r32 = SHR32(celt_exp2(-EXTRACT16(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 = SHR32(MULT16_16_Q15(sqrt_1, r),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(-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, Q15ONE, arch); + } while (++c<C); + } +} + +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)); + a1 = DIV32_16(SHL32(EXTEND32(left),14),norm); + a2 = DIV32_16(SHL32(EXTEND32(right),14),norm); + for (j=0;j<N;j++) + { + celt_norm r, l; + l = X[j]; + r = Y[j]; + X[j] = EXTRACT16(SHR32(MAC16_16(MULT16_16(a1, l), a2, r), 14)); + /* 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 = MULT16_16(QCONST16(.70710678f, 15), X[j]); + r = MULT16_16(QCONST16(.70710678f, 15), Y[j]); + X[j] = EXTRACT16(SHR32(ADD32(l, r), 15)); + Y[j] = EXTRACT16(SHR32(SUB32(r, l), 15)); + } +} + +static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT Y, opus_val16 mid, int N, int arch) +{ + int j; + opus_val32 xp=0, side=0; + opus_val32 El, Er; + opus_val16 mid2; +#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) */ + dual_inner_prod(Y, X, Y, N, &xp, &side, arch); + /* Compensating for the mid normalization */ + xp = MULT16_32_Q15(mid, xp); + /* mid and side are in Q15, not Q14 like X and Y */ + mid2 = SHR32(mid, 1); + El = MULT16_16(mid2, mid2) + side - 2*xp; + Er = MULT16_16(mid2, mid2) + 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-7)<<1); + lgain = celt_rsqrt_norm(t); + t = VSHR32(Er, (kr-7)<<1); + rgain = celt_rsqrt_norm(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 = MULT16_16_P15(mid, X[j]); + r = Y[j]; + X[j] = EXTRACT16(PSHR32(MULT16_16(lgain, SUB16(l,r)), kl+1)); + Y[j] = EXTRACT16(PSHR32(MULT16_16(rgain, ADD16(l,r)), kr+1)); + } +} + +/* 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) +{ + 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(x[j], x[j]), 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*256; + nbBands++; + } + } 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(sum, 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 = MULT16_16(QCONST16(.70710678f,15), X[stride*2*j+i]); + tmp2 = MULT16_16(QCONST16(.70710678f,15), X[stride*(2*j+1)+i]); + X[stride*2*j+i] = EXTRACT16(PSHR32(ADD32(tmp1, tmp2), 15)); + X[stride*(2*j+1)+i] = EXTRACT16(PSHR32(SUB32(tmp1, tmp2), 15)); + } +} + +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; + 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; +}; + +struct split_ctx { + int inv; + int imid; + int iside; + int delta; + int itheta; + 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) +{ + int qn; + int itheta=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 = stereo_itheta(X, Y, stereo, N, ctx->arch); + } + tell = ec_tell_frac(ec); + if (qn!=1) + { + if (encode) + itheta = (itheta*qn+8192)>>14; + + /* 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); + 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; + 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; + itheta = 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; + sctx->qalloc = qalloc; +} +static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y, int b, + celt_norm *lowband_out) +{ +#ifdef RESYNTH + int resynth = 1; +#else + int resynth = !ctx->encode; +#endif + 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; + b-=1<<BITRES; + } + if (resynth) + x[0] = sign ? -NORM_SCALING : NORM_SCALING; + x = Y; + } while (++c<1+stereo); + if (lowband_out) + lowband_out[0] = SHR16(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_val16 gain, int fill) +{ + const unsigned char *cache; + int q; + int curr_bits; + int imid=0, iside=0; + int B0=B; + opus_val16 mid=0, side=0; + unsigned cm=0; +#ifdef RESYNTH + int resynth = 1; +#else + int resynth = !ctx->encode; +#endif + 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); + imid = sctx.imid; + iside = sctx.iside; + delta = sctx.delta; + itheta = sctx.itheta; + qalloc = sctx.qalloc; +#ifdef FIXED_POINT + mid = imid; + side = iside; +#else + mid = (1.f/32768)*imid; + side = (1.f/32768)*iside; +#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, + MULT16_16_P15(gain,mid), fill); + 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, + MULT16_16_P15(gain,side), fill>>B)<<(B0>>1); + } else { + cm = quant_partition(ctx, Y, N, sbits, B, + next_lowband2, LM, + MULT16_16_P15(gain,side), fill>>B)<<(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, + MULT16_16_P15(gain,mid), fill); + } + } else { + /* 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 +#ifdef RESYNTH + , gain +#endif + ); + } else { + cm = alg_unquant(X, N, K, spread, B, ec, gain); + } + } else { + /* If there's no pulse, fill the band anyway */ + int j; + if (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] = (celt_norm)((opus_int32)ctx->seed>>20); + } + 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, 10); + tmp = (ctx->seed)&0x8000 ? tmp : -tmp; + X[j] = lowband[j]+tmp; + } + cm = fill; + } + renormalise_vector(X, N, gain, ctx->arch); + } + } + } + } + + return cm; +} + + +/* 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_val16 gain, celt_norm *lowband_scratch, int fill) +{ + 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; +#ifdef RESYNTH + int resynth = 1; +#else + int resynth = !ctx->encode; +#endif + 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, b, 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); + } + + cm = quant_partition(ctx, X, N, b, B, lowband, + LM, gain, fill); + + /* This code is used by the decoder and by the resynthesis-enabled encoder */ + if (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_16_Q15(n,X[j]); + } + cm &= (1<<B)-1; + } + return cm; +} + + +/* 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) +{ + int imid=0, iside=0; + int inv = 0; + opus_val16 mid=0, side=0; + unsigned cm=0; +#ifdef RESYNTH + int resynth = 1; +#else + int resynth = !ctx->encode; +#endif + 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, b, lowband_out); + } + + orig_fill = fill; + + compute_theta(ctx, &sctx, X, Y, N, &b, B, B, + LM, 1, &fill); + inv = sctx.inv; + imid = sctx.imid; + iside = sctx.iside; + delta = sctx.delta; + itheta = sctx.itheta; + qalloc = sctx.qalloc; +#ifdef FIXED_POINT + mid = imid; + side = iside; +#else + mid = (1.f/32768)*imid; + side = (1.f/32768)*iside; +#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. */ + sign = x2[0]*y2[1] - 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, Q15ONE, lowband_scratch, orig_fill); + /* 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 (resynth) + { + celt_norm tmp; + X[0] = MULT16_16_Q15(mid, X[0]); + X[1] = MULT16_16_Q15(mid, X[1]); + Y[0] = MULT16_16_Q15(side, Y[0]); + Y[1] = MULT16_16_Q15(side, Y[1]); + tmp = X[0]; + X[0] = SUB16(tmp,Y[0]); + Y[0] = ADD16(tmp,Y[0]); + tmp = X[1]; + X[1] = SUB16(tmp,Y[1]); + Y[1] = ADD16(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) + { + /* 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, + Q15ONE, lowband_scratch, fill); + rebalance = mbits - (rebalance-ctx->remaining_bits); + if (rebalance > 3<<BITRES && itheta!=0) + sbits += rebalance - (3<<BITRES); + + /* 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); + } else { + /* 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); + rebalance = sbits - (rebalance-ctx->remaining_bits); + if (rebalance > 3<<BITRES && itheta!=16384) + mbits += rebalance - (3<<BITRES); + /* 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, + Q15ONE, lowband_scratch, fill); + } + } + + + /* This code is used by the decoder and by the resynthesis-enabled encoder */ + if (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; +} + + +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 arch) +{ + 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); + celt_norm *lowband_scratch; + int B; + int M; + int lowband_offset; + int update_lowband = 1; + int C = Y_ != NULL ? 2 : 1; + int norm_offset; +#ifdef RESYNTH + int resynth = 1; +#else + int resynth = !encode; +#endif + struct band_ctx ctx; + 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; + /* We can use the last band as scratch space because we don't need that + scratch space for the last band. */ + lowband_scratch = X_+M*eBands[m->nbEBands-1]; + + 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; + 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]; + 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; + 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; + } + + if (resynth && M*eBands[i]-N >= M*eBands[start] && (update_lowband || lowband_offset==0)) + lowband_offset = i; + + 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 (i==end-1) + 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; + while(M*eBands[++fold_end] < effective_lowband+norm_offset+N); + 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, Q15ONE, lowband_scratch, x_cm); + 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, Q15ONE, lowband_scratch, y_cm); + } else { + if (Y!=NULL) + { + 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); + } 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, Q15ONE, lowband_scratch, x_cm|y_cm); + } + 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); + } + *seed = ctx.seed; + + RESTORE_STACK; +} + diff --git a/thirdparty/opus/celt/bands.h b/thirdparty/opus/celt/bands.h new file mode 100644 index 0000000000..e8bef4bad0 --- /dev/null +++ b/thirdparty/opus/celt/bands.h @@ -0,0 +1,120 @@ +/* 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" + +/** 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); + +/*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 opus_val16 *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); + +#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 arch); + +void anti_collapse(const CELTMode *m, celt_norm *X_, + unsigned char *collapse_masks, int LM, int C, int size, int start, + int end, const opus_val16 *logE, const opus_val16 *prev1logE, + const opus_val16 *prev2logE, const int *pulses, opus_uint32 seed, + 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/thirdparty/opus/celt/celt.c b/thirdparty/opus/celt/celt.c new file mode 100644 index 0000000000..b121c51a1f --- /dev/null +++ b/thirdparty/opus/celt/celt.c @@ -0,0 +1,299 @@ +/* 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(MIPSr1_ASM) +#include "mips/celt_mipsr1.h" +#endif + + +int resampling_factor(opus_int32 rate) +{ + int ret; + switch (rate) + { + 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, + opus_val16 g10, opus_val16 g11, opus_val16 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 = MAC16_32_Q16(x[i], g10, x2); + t = MAC16_32_Q16(t, g11, ADD32(x1,x3)); + t = MAC16_32_Q16(t, g12, ADD32(x0,x4)); + y[i] = t; + x4=SHL32(x[i-T+3],1); + t = MAC16_32_Q16(x[i+1], g10, x1); + t = MAC16_32_Q16(t, g11, ADD32(x0,x2)); + t = MAC16_32_Q16(t, g12, ADD32(x4,x3)); + y[i+1] = t; + x3=SHL32(x[i-T+4],1); + t = MAC16_32_Q16(x[i+2], g10, x0); + t = MAC16_32_Q16(t, g11, ADD32(x4,x1)); + t = MAC16_32_Q16(t, g12, ADD32(x3,x2)); + y[i+2] = t; + x2=SHL32(x[i-T+5],1); + t = MAC16_32_Q16(x[i+3], g10, x4); + t = MAC16_32_Q16(t, g11, ADD32(x3,x0)); + t = MAC16_32_Q16(t, g12, ADD32(x2,x1)); + y[i+3] = t; + x1=SHL32(x[i-T+6],1); + t = MAC16_32_Q16(x[i+4], g10, x3); + t = MAC16_32_Q16(t, g11, ADD32(x2,x4)); + t = MAC16_32_Q16(t, g12, ADD32(x1,x0)); + y[i+4] = t; + } +#ifdef CUSTOM_MODES + for (;i<N;i++) + { + opus_val32 t; + x0=SHL32(x[i-T+2],1); + t = MAC16_32_Q16(x[i], g10, x2); + t = MAC16_32_Q16(t, g11, ADD32(x1,x3)); + t = MAC16_32_Q16(t, g12, ADD32(x0,x4)); + 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, + opus_val16 g10, opus_val16 g11, opus_val16 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] + + MULT16_32_Q15(g10,x2) + + MULT16_32_Q15(g11,ADD32(x1,x3)) + + MULT16_32_Q15(g12,ADD32(x0,x4)); + x4=x3; + x3=x2; + x2=x1; + x1=x0; + } + +} +#endif +#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 opus_val16 *window, int overlap, int arch) +{ + int i; + /* printf ("%d %d %f %f\n", T0, T1, g0, g1); */ + opus_val16 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)}}; + + 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; + } + g00 = MULT16_16_P15(g0, gains[tapset0][0]); + g01 = MULT16_16_P15(g0, gains[tapset0][1]); + g02 = MULT16_16_P15(g0, gains[tapset0][2]); + g10 = MULT16_16_P15(g1, gains[tapset1][0]); + g11 = MULT16_16_P15(g1, gains[tapset1][1]); + g12 = MULT16_16_P15(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++) + { + opus_val16 f; + x0=x[i-T1+2]; + f = MULT16_16_Q15(window[i],window[i]); + y[i] = x[i] + + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g00),x[i-T0]) + + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g01),ADD32(x[i-T0+1],x[i-T0-1])) + + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g02),ADD32(x[i-T0+2],x[i-T0-2])) + + MULT16_32_Q15(MULT16_16_Q15(f,g10),x2) + + MULT16_32_Q15(MULT16_16_Q15(f,g11),ADD32(x1,x3)) + + MULT16_32_Q15(MULT16_16_Q15(f,g12),ADD32(x0,x4)); + 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 */ + +const signed char tf_select_table[4][8] = { + {0, -1, 0, -1, 0,-1, 0,-1}, + {0, -1, 0, -2, 1, 0, 1,-1}, + {0, -2, 0, -3, 2, 0, 1,-1}, + {0, -2, 0, -3, 3, 0, 1,-1}, +}; + + +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/thirdparty/opus/celt/celt.h b/thirdparty/opus/celt/celt.h new file mode 100644 index 0000000000..a423b95046 --- /dev/null +++ b/thirdparty/opus/celt/celt.h @@ -0,0 +1,229 @@ +/* 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" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CELTEncoder OpusCustomEncoder +#define CELTDecoder OpusCustomDecoder +#define CELTMode OpusCustomMode + +typedef struct { + int valid; + float tonality; + float tonality_slope; + float noisiness; + float activity; + float music_prob; + int bandwidth; +}AnalysisInfo; + +#define __celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr))) + +#define __celt_check_analysis_ptr(ptr) ((ptr) + ((ptr) - (const AnalysisInfo*)(ptr))) + +/* Encoder/decoder Requests */ + +/* Expose this option again when variable framesize actually works */ +#define OPUS_FRAMESIZE_VARIABLE 5010 /**< Optimize the frame size dynamically */ + + +#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, __opus_check_val16_ptr(x) + +/* Encoder stuff */ + +int celt_encoder_get_size(int channels); + +int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_val16 * 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(OpusCustomDecoder * OPUS_RESTRICT st, const unsigned char *data, + int len, opus_val16 * 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 + + +#ifdef CUSTOM_MODES +#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}; + +#ifdef CUSTOM_MODES +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]; + +int resampling_factor(opus_int32 rate); + +void celt_preemphasis(const opus_val16 * 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 opus_val16 *window, int overlap, int arch); + +#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 + +void init_caps(const CELTMode *m,int *cap,int LM,int C); + +#ifdef RESYNTH +void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef, celt_sig *mem); +void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[], + opus_val16 *oldBandE, int start, int effEnd, int C, int CC, int isTransient, + int LM, int downsample, int silence); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* CELT_H */ diff --git a/thirdparty/opus/celt/celt_decoder.c b/thirdparty/opus/celt/celt_decoder.c new file mode 100644 index 0000000000..b688f2a4e3 --- /dev/null +++ b/thirdparty/opus/celt/celt_decoder.c @@ -0,0 +1,1244 @@ +/* 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" + +#if defined(SMALL_FOOTPRINT) && defined(FIXED_POINT) +#define NORM_ALIASING_HACK +#endif +/**********************************************************************/ +/* */ +/* DECODER */ +/* */ +/**********************************************************************/ +#define DECODE_BUFFER_SIZE 2048 + +/** 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 arch; + + /* 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_count; + int postfilter_period; + int postfilter_period_old; + opus_val16 postfilter_gain; + opus_val16 postfilter_gain_old; + int postfilter_tapset; + int postfilter_tapset_old; + + celt_sig preemph_memD[2]; + + celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */ + /* opus_val16 lpc[], Size = channels*LPC_ORDER */ + /* opus_val16 oldEBands[], Size = 2*mode->nbEBands */ + /* opus_val16 oldLogE[], Size = 2*mode->nbEBands */ + /* opus_val16 oldLogE2[], Size = 2*mode->nbEBands */ + /* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */ +}; + +int celt_decoder_get_size(int channels) +{ + const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL); + return opus_custom_decoder_get_size(mode, channels); +} + +OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_get_size(const CELTMode *mode, int channels) +{ + int size = sizeof(struct CELTDecoder) + + (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig) + + channels*LPC_ORDER*sizeof(opus_val16) + + 4*2*mode->nbEBands*sizeof(opus_val16); + return size; +} + +#ifdef CUSTOM_MODES +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; + 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; + st->arch = opus_select_arch(); + + st->loss_count = 0; + + opus_custom_decoder_ctl(st, OPUS_RESET_STATE); + + return OPUS_OK; +} + +#ifdef CUSTOM_MODES +void opus_custom_decoder_destroy(CELTDecoder *st) +{ + opus_free(st); +} +#endif /* CUSTOM_MODES */ + + +#ifndef RESYNTH +static +#endif +void deemphasis(celt_sig *in[], opus_val16 *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; +#ifndef FIXED_POINT + (void)accum; + celt_assert(accum==0); +#endif + ALLOC(scratch, N, celt_sig); + coef0 = coef[0]; + Nd = N/downsample; + c=0; do { + int j; + celt_sig * OPUS_RESTRICT x; + opus_val16 * OPUS_RESTRICT y; + celt_sig m = mem[c]; + x =in[c]; + y = pcm+c; +#ifdef CUSTOM_MODES + if (coef[1] != 0) + { + opus_val16 coef1 = coef[1]; + opus_val16 coef3 = coef[3]; + for (j=0;j<N;j++) + { + celt_sig tmp = x[j] + m + VERY_SMALL; + 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 = x[j] + m + VERY_SMALL; + m = MULT16_32_Q15(coef0, tmp); + scratch[j] = tmp; + } + apply_downsampling=1; + } else { + /* Shortcut for the standard (non-custom modes) case */ +#ifdef FIXED_POINT + if (accum) + { + for (j=0;j<N;j++) + { + celt_sig tmp = x[j] + m + VERY_SMALL; + m = MULT16_32_Q15(coef0, tmp); + y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(tmp)))); + } + } else +#endif + { + for (j=0;j<N;j++) + { + celt_sig tmp = x[j] + m + VERY_SMALL; + m = MULT16_32_Q15(coef0, tmp); + y[j*C] = SCALEOUT(SIG2WORD16(tmp)); + } + } + } + mem[c] = m; + + if (apply_downsampling) + { + /* Perform down-sampling */ +#ifdef FIXED_POINT + if (accum) + { + for (j=0;j<Nd;j++) + y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(scratch[j*downsample])))); + } else +#endif + { + for (j=0;j<Nd;j++) + y[j*C] = SCALEOUT(SIG2WORD16(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[], + opus_val16 *oldBandE, int start, int effEnd, int C, int CC, + int isTransient, int LM, int downsample, + int silence, int arch) +{ + 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; + + 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); + /* 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); + for (i=0;i<N;i++) + freq[i] = HALF32(ADD32(freq[i],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); + 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); + } + 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]]; + } +} + +/* 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) + +static int celt_plc_pitch_search(celt_sig *decode_mem[2], int C, int arch) +{ + int pitch_index; + VARDECL( opus_val16, lp_pitch_buf ); + SAVE_STACK; + ALLOC( lp_pitch_buf, DECODE_BUFFER_SIZE>>1, opus_val16 ); + pitch_downsample(decode_mem, lp_pitch_buf, + DECODE_BUFFER_SIZE, C, 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 pitch_index; +} + +static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM) +{ + int c; + int i; + const int C = st->channels; + celt_sig *decode_mem[2]; + celt_sig *out_syn[2]; + opus_val16 *lpc; + opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE; + const OpusCustomMode *mode; + int nbEBands; + int overlap; + int start; + int loss_count; + int noise_based; + const opus_int16 *eBands; + SAVE_STACK; + + 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); + lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*C); + oldBandE = lpc+C*LPC_ORDER; + oldLogE = oldBandE + 2*nbEBands; + oldLogE2 = oldLogE + 2*nbEBands; + backgroundLogE = oldLogE2 + 2*nbEBands; + + loss_count = st->loss_count; + start = st->start; + noise_based = loss_count >= 5 || start != 0; + if (noise_based) + { + /* Noise-based PLC/CNG */ +#ifdef NORM_ALIASING_HACK + celt_norm *X; +#else + VARDECL(celt_norm, X); +#endif + opus_uint32 seed; + int end; + int effEnd; + opus_val16 decay; + end = st->end; + effEnd = IMAX(start, IMIN(end, mode->effEBands)); + +#ifdef NORM_ALIASING_HACK + /* This is an ugly hack that breaks aliasing rules and would be easily broken, + but it saves almost 4kB of stack. */ + X = (celt_norm*)(out_syn[C-1]+overlap/2); +#else + ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ +#endif + + /* Energy decay */ + decay = loss_count==0 ? QCONST16(1.5f, DB_SHIFT) : QCONST16(.5f, DB_SHIFT); + c=0; do + { + for (i=start;i<end;i++) + oldBandE[c*nbEBands+i] = MAX16(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] = (celt_norm)((opus_int32)seed>>20); + } + renormalise_vector(X+boffs, blen, Q15ONE, st->arch); + } + } + st->rng = seed; + + c=0; do { + OPUS_MOVE(decode_mem[c], decode_mem[c]+N, + DECODE_BUFFER_SIZE-N+(overlap>>1)); + } while (++c<C); + + celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, C, C, 0, LM, st->downsample, 0, st->arch); + } else { + /* Pitch-based PLC */ + const opus_val16 *window; + opus_val16 fade = Q15ONE; + int pitch_index; + VARDECL(opus_val32, etmp); + VARDECL(opus_val16, exc); + + if (loss_count == 0) + { + st->last_pitch_index = pitch_index = celt_plc_pitch_search(decode_mem, C, st->arch); + } else { + pitch_index = st->last_pitch_index; + fade = QCONST16(.8f,15); + } + + ALLOC(etmp, overlap, opus_val32); + ALLOC(exc, MAX_PERIOD, opus_val16); + 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 exc_length; + int j; + + buf = decode_mem[c]; + for (i=0;i<MAX_PERIOD;i++) { + exc[i] = ROUND16(buf[DECODE_BUFFER_SIZE-MAX_PERIOD+i], SIG_SHIFT); + } + + if (loss_count == 0) + { + opus_val32 ac[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, + 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<=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*LPC_ORDER, ac, LPC_ORDER); + } + /* 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); + /* Initialize the LPC history with the samples just before the start + of the region for which we're computing the excitation. */ + { + opus_val16 lpc_mem[LPC_ORDER]; + for (i=0;i<LPC_ORDER;i++) + { + lpc_mem[i] = + ROUND16(buf[DECODE_BUFFER_SIZE-exc_length-1-i], SIG_SHIFT); + } + /* Compute the excitation for exc_length samples before the loss. */ + celt_fir(exc+MAX_PERIOD-exc_length, lpc+c*LPC_ORDER, + exc+MAX_PERIOD-exc_length, exc_length, LPC_ORDER, lpc_mem, st->arch); + } + + /* 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); +#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 = ROUND16( + buf[DECODE_BUFFER_SIZE-MAX_PERIOD-N+extrapolation_offset+j], + SIG_SHIFT); + S1 += SHR32(MULT16_16(tmp, tmp), 8); + } + + { + opus_val16 lpc_mem[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<LPC_ORDER;i++) + lpc_mem[i] = ROUND16(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*LPC_ORDER, + buf+DECODE_BUFFER_SIZE-N, extrapolation_len, LPC_ORDER, + lpc_mem, st->arch); + } + + /* 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 = ROUND16(buf[DECODE_BUFFER_SIZE-N+i], SIG_SHIFT); + S2 += SHR32(MULT16_16(tmp, tmp), 8); + } + /* 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(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]); + } + } + } + + /* 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, buf+DECODE_BUFFER_SIZE, + st->postfilter_period, st->postfilter_period, overlap, + -st->postfilter_gain, -st->postfilter_gain, + st->postfilter_tapset, 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++) + { + buf[DECODE_BUFFER_SIZE+i] = + MULT16_32_Q15(window[i], etmp[overlap-1-i]) + + MULT16_32_Q15(window[overlap-i-1], etmp[i]); + } + } while (++c<C); + } + + st->loss_count = loss_count+1; + + RESTORE_STACK; +} + +int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, + int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum) +{ + int c, i, N; + int spread_decision; + opus_int32 bits; + ec_dec _dec; +#ifdef NORM_ALIASING_HACK + celt_norm *X; +#else + VARDECL(celt_norm, X); +#endif + 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]; + opus_val16 *lpc; + opus_val16 *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; + ALLOC_STACK; + + mode = st->mode; + nbEBands = mode->nbEBands; + overlap = mode->overlap; + eBands = mode->eBands; + start = st->start; + end = st->end; + frame_size *= st->downsample; + + lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*CC); + oldBandE = lpc+CC*LPC_ORDER; + oldLogE = oldBandE + 2*nbEBands; + oldLogE2 = oldLogE + 2*nbEBands; + backgroundLogE = oldLogE2 + 2*nbEBands; + +#ifdef CUSTOM_MODES + if (st->signalling && data!=NULL) + { + int data0=data[0]; + /* Convert "standard mode" to Opus header */ + if (mode->Fs==48000 && mode->shortMdctSize==120) + { + 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); + 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); + deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum); + RESTORE_STACK; + return frame_size/st->downsample; + } + + if (dec == NULL) + { + ec_dec_init(&_dec,(unsigned char*)data,len); + dec = &_dec; + } + + if (C==1) + { + for (i=0;i<nbEBands;i++) + oldBandE[i]=MAX16(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; + /* 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) - 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 = 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, fine_quant, dec, C); + + c=0; do { + OPUS_MOVE(decode_mem[c], decode_mem[c]+N, DECODE_BUFFER_SIZE-N+overlap/2); + } while (++c<CC); + + /* Decode fixed codebook */ + ALLOC(collapse_masks, C*nbEBands, unsigned char); + +#ifdef NORM_ALIASING_HACK + /* This is an ugly hack that breaks aliasing rules and would be easily broken, + but it saves almost 4kB of stack. */ + X = (celt_norm*)(out_syn[CC-1]+overlap/2); +#else + ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ +#endif + + 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, st->arch); + + if (anti_collapse_rsv > 0) + { + anti_collapse_on = ec_dec_bits(dec, 1); + } + + unquant_energy_finalise(mode, start, end, 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, st->arch); + + if (silence) + { + for (i=0;i<C*nbEBands;i++) + oldBandE[i] = -QCONST16(28.f,DB_SHIFT); + } + + celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, + C, CC, isTransient, LM, st->downsample, silence, st->arch); + + 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); + + /* In case start or end were to change */ + if (!isTransient) + { + opus_val16 max_background_increase; + OPUS_COPY(oldLogE2, oldLogE, 2*nbEBands); + OPUS_COPY(oldLogE, oldBandE, 2*nbEBands); + /* 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 allow up to 6 dB + increase for each update.*/ + if (st->loss_count < 10) + max_background_increase = M*QCONST16(0.001f,DB_SHIFT); + else + max_background_increase = QCONST16(1.f,DB_SHIFT); + for (i=0;i<2*nbEBands;i++) + backgroundLogE[i] = MIN16(backgroundLogE[i] + max_background_increase, oldBandE[i]); + } else { + for (i=0;i<2*nbEBands;i++) + oldLogE[i] = MIN16(oldLogE[i], oldBandE[i]); + } + c=0; do + { + for (i=0;i<start;i++) + { + oldBandE[c*nbEBands+i]=0; + oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT); + } + for (i=end;i<nbEBands;i++) + { + oldBandE[c*nbEBands+i]=0; + oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT); + } + } while (++c<2); + st->rng = dec->rng; + + deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum); + st->loss_count = 0; + RESTORE_STACK; + if (ec_tell(dec) > 8*len) + return OPUS_INTERNAL_ERROR; + if(ec_get_error(dec)) + st->error = 1; + return frame_size/st->downsample; +} + + +#ifdef CUSTOM_MODES + +#ifdef FIXED_POINT +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); +} + +#ifndef DISABLE_FLOAT_API +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_int16, out); + ALLOC_STACK; + + if (pcm==NULL) + return OPUS_BAD_ARG; + + C = st->channels; + N = frame_size; + + ALLOC(out, C*N, opus_int16); + 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]=out[j]*(1.f/32768.f); + + RESTORE_STACK; + return ret; +} +#endif /* DISABLE_FLOAT_API */ + +#else + +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); +} + +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(celt_sig, out); + ALLOC_STACK; + + if (pcm==NULL) + return OPUS_BAD_ARG; + + C = st->channels; + N = frame_size; + ALLOC(out, C*N, celt_sig); + + 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] = FLOAT2INT16 (out[j]); + + RESTORE_STACK; + return ret; +} + +#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 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; + opus_val16 *lpc, *oldBandE, *oldLogE, *oldLogE2; + lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*st->channels); + oldBandE = lpc+st->channels*LPC_ORDER; + 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]=-QCONST16(28.f,DB_SHIFT); + } + 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; + 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/thirdparty/opus/celt/celt_encoder.c b/thirdparty/opus/celt/celt_encoder.c new file mode 100644 index 0000000000..41fbfd49c8 --- /dev/null +++ b/thirdparty/opus/celt/celt_encoder.c @@ -0,0 +1,2407 @@ +/* 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_ENCODER_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" + + +/** Encoder state + @brief Encoder state + */ +struct OpusCustomEncoder { + const OpusCustomMode *mode; /**< Mode used by the encoder */ + int channels; + int stream_channels; + + int force_intra; + int clip; + int disable_pf; + int complexity; + int upsample; + int start, end; + + opus_int32 bitrate; + int vbr; + int signalling; + int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */ + int loss_rate; + int lsb_depth; + int variable_duration; + int lfe; + int arch; + + /* Everything beyond this point gets cleared on a reset */ +#define ENCODER_RESET_START rng + + opus_uint32 rng; + int spread_decision; + opus_val32 delayedIntra; + int tonal_average; + int lastCodedBands; + int hf_average; + int tapset_decision; + + int prefilter_period; + opus_val16 prefilter_gain; + int prefilter_tapset; +#ifdef RESYNTH + int prefilter_period_old; + opus_val16 prefilter_gain_old; + int prefilter_tapset_old; +#endif + int consec_transient; + AnalysisInfo analysis; + + opus_val32 preemph_memE[2]; + opus_val32 preemph_memD[2]; + + /* VBR-related parameters */ + opus_int32 vbr_reservoir; + opus_int32 vbr_drift; + opus_int32 vbr_offset; + opus_int32 vbr_count; + opus_val32 overlap_max; + opus_val16 stereo_saving; + int intensity; + opus_val16 *energy_mask; + opus_val16 spec_avg; + +#ifdef RESYNTH + /* +MAX_PERIOD/2 to make space for overlap */ + celt_sig syn_mem[2][2*MAX_PERIOD+MAX_PERIOD/2]; +#endif + + celt_sig in_mem[1]; /* Size = channels*mode->overlap */ + /* celt_sig prefilter_mem[], Size = channels*COMBFILTER_MAXPERIOD */ + /* opus_val16 oldBandE[], Size = channels*mode->nbEBands */ + /* opus_val16 oldLogE[], Size = channels*mode->nbEBands */ + /* opus_val16 oldLogE2[], Size = channels*mode->nbEBands */ +}; + +int celt_encoder_get_size(int channels) +{ + CELTMode *mode = opus_custom_mode_create(48000, 960, NULL); + return opus_custom_encoder_get_size(mode, channels); +} + +OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_get_size(const CELTMode *mode, int channels) +{ + int size = sizeof(struct CELTEncoder) + + (channels*mode->overlap-1)*sizeof(celt_sig) /* celt_sig in_mem[channels*mode->overlap]; */ + + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig) /* celt_sig prefilter_mem[channels*COMBFILTER_MAXPERIOD]; */ + + 3*channels*mode->nbEBands*sizeof(opus_val16); /* opus_val16 oldBandE[channels*mode->nbEBands]; */ + /* opus_val16 oldLogE[channels*mode->nbEBands]; */ + /* opus_val16 oldLogE2[channels*mode->nbEBands]; */ + return size; +} + +#ifdef CUSTOM_MODES +CELTEncoder *opus_custom_encoder_create(const CELTMode *mode, int channels, int *error) +{ + int ret; + CELTEncoder *st = (CELTEncoder *)opus_alloc(opus_custom_encoder_get_size(mode, channels)); + /* init will handle the NULL case */ + ret = opus_custom_encoder_init(st, mode, channels); + if (ret != OPUS_OK) + { + opus_custom_encoder_destroy(st); + st = NULL; + } + if (error) + *error = ret; + return st; +} +#endif /* CUSTOM_MODES */ + +static int opus_custom_encoder_init_arch(CELTEncoder *st, const CELTMode *mode, + int channels, int arch) +{ + if (channels < 0 || channels > 2) + return OPUS_BAD_ARG; + + if (st==NULL || mode==NULL) + return OPUS_ALLOC_FAIL; + + OPUS_CLEAR((char*)st, opus_custom_encoder_get_size(mode, channels)); + + st->mode = mode; + st->stream_channels = st->channels = channels; + + st->upsample = 1; + st->start = 0; + st->end = st->mode->effEBands; + st->signalling = 1; + + st->arch = arch; + + st->constrained_vbr = 1; + st->clip = 1; + + st->bitrate = OPUS_BITRATE_MAX; + st->vbr = 0; + st->force_intra = 0; + st->complexity = 5; + st->lsb_depth=24; + + opus_custom_encoder_ctl(st, OPUS_RESET_STATE); + + return OPUS_OK; +} + +#ifdef CUSTOM_MODES +int opus_custom_encoder_init(CELTEncoder *st, const CELTMode *mode, int channels) +{ + return opus_custom_encoder_init_arch(st, mode, channels, opus_select_arch()); +} +#endif + +int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels, + int arch) +{ + int ret; + ret = opus_custom_encoder_init_arch(st, + opus_custom_mode_create(48000, 960, NULL), channels, arch); + if (ret != OPUS_OK) + return ret; + st->upsample = resampling_factor(sampling_rate); + return OPUS_OK; +} + +#ifdef CUSTOM_MODES +void opus_custom_encoder_destroy(CELTEncoder *st) +{ + opus_free(st); +} +#endif /* CUSTOM_MODES */ + + +static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int C, + opus_val16 *tf_estimate, int *tf_chan) +{ + int i; + VARDECL(opus_val16, tmp); + opus_val32 mem0,mem1; + int is_transient = 0; + opus_int32 mask_metric = 0; + int c; + opus_val16 tf_max; + int len2; + /* Table of 6*64/x, trained on real data to minimize the average error */ + static const unsigned char inv_table[128] = { + 255,255,156,110, 86, 70, 59, 51, 45, 40, 37, 33, 31, 28, 26, 25, + 23, 22, 21, 20, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12, + 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, + 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + }; + SAVE_STACK; + ALLOC(tmp, len, opus_val16); + + len2=len/2; + for (c=0;c<C;c++) + { + opus_val32 mean; + opus_int32 unmask=0; + opus_val32 norm; + opus_val16 maxE; + mem0=0; + mem1=0; + /* High-pass filter: (1 - 2*z^-1 + z^-2) / (1 - z^-1 + .5*z^-2) */ + for (i=0;i<len;i++) + { + opus_val32 x,y; + x = SHR32(in[i+c*len],SIG_SHIFT); + y = ADD32(mem0, x); +#ifdef FIXED_POINT + mem0 = mem1 + y - SHL32(x,1); + mem1 = x - SHR32(y,1); +#else + mem0 = mem1 + y - 2*x; + mem1 = x - .5f*y; +#endif + tmp[i] = EXTRACT16(SHR32(y,2)); + /*printf("%f ", tmp[i]);*/ + } + /*printf("\n");*/ + /* First few samples are bad because we don't propagate the memory */ + OPUS_CLEAR(tmp, 12); + +#ifdef FIXED_POINT + /* Normalize tmp to max range */ + { + int shift=0; + shift = 14-celt_ilog2(1+celt_maxabs16(tmp, len)); + if (shift!=0) + { + for (i=0;i<len;i++) + tmp[i] = SHL16(tmp[i], shift); + } + } +#endif + + mean=0; + mem0=0; + /* Grouping by two to reduce complexity */ + /* Forward pass to compute the post-echo threshold*/ + for (i=0;i<len2;i++) + { + opus_val16 x2 = PSHR32(MULT16_16(tmp[2*i],tmp[2*i]) + MULT16_16(tmp[2*i+1],tmp[2*i+1]),16); + mean += x2; +#ifdef FIXED_POINT + /* FIXME: Use PSHR16() instead */ + tmp[i] = mem0 + PSHR32(x2-mem0,4); +#else + tmp[i] = mem0 + MULT16_16_P15(QCONST16(.0625f,15),x2-mem0); +#endif + mem0 = tmp[i]; + } + + mem0=0; + maxE=0; + /* Backward pass to compute the pre-echo threshold */ + for (i=len2-1;i>=0;i--) + { +#ifdef FIXED_POINT + /* FIXME: Use PSHR16() instead */ + tmp[i] = mem0 + PSHR32(tmp[i]-mem0,3); +#else + tmp[i] = mem0 + MULT16_16_P15(QCONST16(0.125f,15),tmp[i]-mem0); +#endif + mem0 = tmp[i]; + maxE = MAX16(maxE, mem0); + } + /*for (i=0;i<len2;i++)printf("%f ", tmp[i]/mean);printf("\n");*/ + + /* Compute the ratio of the "frame energy" over the harmonic mean of the energy. + This essentially corresponds to a bitrate-normalized temporal noise-to-mask + ratio */ + + /* As a compromise with the old transient detector, frame energy is the + geometric mean of the energy and half the max */ +#ifdef FIXED_POINT + /* Costs two sqrt() to avoid overflows */ + mean = MULT16_16(celt_sqrt(mean), celt_sqrt(MULT16_16(maxE,len2>>1))); +#else + mean = celt_sqrt(mean * maxE*.5*len2); +#endif + /* Inverse of the mean energy in Q15+6 */ + norm = SHL32(EXTEND32(len2),6+14)/ADD32(EPSILON,SHR32(mean,1)); + /* Compute harmonic mean discarding the unreliable boundaries + The data is smooth, so we only take 1/4th of the samples */ + unmask=0; + for (i=12;i<len2-5;i+=4) + { + int id; +#ifdef FIXED_POINT + id = MAX32(0,MIN32(127,MULT16_32_Q15(tmp[i]+EPSILON,norm))); /* Do not round to nearest */ +#else + id = (int)MAX32(0,MIN32(127,floor(64*norm*(tmp[i]+EPSILON)))); /* Do not round to nearest */ +#endif + unmask += inv_table[id]; + } + /*printf("%d\n", unmask);*/ + /* Normalize, compensate for the 1/4th of the sample and the factor of 6 in the inverse table */ + unmask = 64*unmask*4/(6*(len2-17)); + if (unmask>mask_metric) + { + *tf_chan = c; + mask_metric = unmask; + } + } + is_transient = mask_metric>200; + + /* Arbitrary metric for VBR boost */ + tf_max = MAX16(0,celt_sqrt(27*mask_metric)-42); + /* *tf_estimate = 1 + MIN16(1, sqrt(MAX16(0, tf_max-30))/20); */ + *tf_estimate = celt_sqrt(MAX32(0, SHL32(MULT16_16(QCONST16(0.0069,14),MIN16(163,tf_max)),14)-QCONST32(0.139,28))); + /*printf("%d %f\n", tf_max, mask_metric);*/ + RESTORE_STACK; +#ifdef FUZZING + is_transient = rand()&0x1; +#endif + /*printf("%d %f %d\n", is_transient, (float)*tf_estimate, tf_max);*/ + return is_transient; +} + +/* Looks for sudden increases of energy to decide whether we need to patch + the transient decision */ +static int patch_transient_decision(opus_val16 *newE, opus_val16 *oldE, int nbEBands, + int start, int end, int C) +{ + int i, c; + opus_val32 mean_diff=0; + opus_val16 spread_old[26]; + /* Apply an aggressive (-6 dB/Bark) spreading function to the old frame to + avoid false detection caused by irrelevant bands */ + if (C==1) + { + spread_old[start] = oldE[start]; + for (i=start+1;i<end;i++) + spread_old[i] = MAX16(spread_old[i-1]-QCONST16(1.0f, DB_SHIFT), oldE[i]); + } else { + spread_old[start] = MAX16(oldE[start],oldE[start+nbEBands]); + for (i=start+1;i<end;i++) + spread_old[i] = MAX16(spread_old[i-1]-QCONST16(1.0f, DB_SHIFT), + MAX16(oldE[i],oldE[i+nbEBands])); + } + for (i=end-2;i>=start;i--) + spread_old[i] = MAX16(spread_old[i], spread_old[i+1]-QCONST16(1.0f, DB_SHIFT)); + /* Compute mean increase */ + c=0; do { + for (i=IMAX(2,start);i<end-1;i++) + { + opus_val16 x1, x2; + x1 = MAX16(0, newE[i + c*nbEBands]); + x2 = MAX16(0, spread_old[i]); + mean_diff = ADD32(mean_diff, EXTEND32(MAX16(0, SUB16(x1, x2)))); + } + } while (++c<C); + mean_diff = DIV32(mean_diff, C*(end-1-IMAX(2,start))); + /*printf("%f %f %d\n", mean_diff, max_diff, count);*/ + return mean_diff > QCONST16(1.f, DB_SHIFT); +} + +/** Apply window and compute the MDCT for all sub-frames and + all channels in a frame */ +static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig * OPUS_RESTRICT in, + celt_sig * OPUS_RESTRICT out, int C, int CC, int LM, int upsample, + int arch) +{ + const int overlap = mode->overlap; + int N; + int B; + int shift; + int i, b, c; + if (shortBlocks) + { + B = shortBlocks; + N = mode->shortMdctSize; + shift = mode->maxLM; + } else { + B = 1; + N = mode->shortMdctSize<<LM; + shift = mode->maxLM-LM; + } + c=0; do { + for (b=0;b<B;b++) + { + /* Interleaving the sub-frames while doing the MDCTs */ + clt_mdct_forward(&mode->mdct, in+c*(B*N+overlap)+b*N, + &out[b+c*N*B], mode->window, overlap, shift, B, + arch); + } + } while (++c<CC); + if (CC==2&&C==1) + { + for (i=0;i<B*N;i++) + out[i] = ADD32(HALF32(out[i]), HALF32(out[B*N+i])); + } + if (upsample != 1) + { + c=0; do + { + int bound = B*N/upsample; + for (i=0;i<bound;i++) + out[c*B*N+i] *= upsample; + OPUS_CLEAR(&out[c*B*N+bound], B*N-bound); + } while (++c<C); + } +} + + +void celt_preemphasis(const opus_val16 * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp, + int N, int CC, int upsample, const opus_val16 *coef, celt_sig *mem, int clip) +{ + int i; + opus_val16 coef0; + celt_sig m; + int Nu; + + coef0 = coef[0]; + m = *mem; + + /* Fast path for the normal 48kHz case and no clipping */ + if (coef[1] == 0 && upsample == 1 && !clip) + { + for (i=0;i<N;i++) + { + opus_val16 x; + x = SCALEIN(pcmp[CC*i]); + /* Apply pre-emphasis */ + inp[i] = SHL32(x, SIG_SHIFT) - m; + m = SHR32(MULT16_16(coef0, x), 15-SIG_SHIFT); + } + *mem = m; + return; + } + + Nu = N/upsample; + if (upsample!=1) + { + OPUS_CLEAR(inp, N); + } + for (i=0;i<Nu;i++) + inp[i*upsample] = SCALEIN(pcmp[CC*i]); + +#ifndef FIXED_POINT + if (clip) + { + /* Clip input to avoid encoding non-portable files */ + for (i=0;i<Nu;i++) + inp[i*upsample] = MAX32(-65536.f, MIN32(65536.f,inp[i*upsample])); + } +#else + (void)clip; /* Avoids a warning about clip being unused. */ +#endif +#ifdef CUSTOM_MODES + if (coef[1] != 0) + { + opus_val16 coef1 = coef[1]; + opus_val16 coef2 = coef[2]; + for (i=0;i<N;i++) + { + celt_sig x, tmp; + x = inp[i]; + /* Apply pre-emphasis */ + tmp = MULT16_16(coef2, x); + inp[i] = tmp + m; + m = MULT16_32_Q15(coef1, inp[i]) - MULT16_32_Q15(coef0, tmp); + } + } else +#endif + { + for (i=0;i<N;i++) + { + opus_val16 x; + x = inp[i]; + /* Apply pre-emphasis */ + inp[i] = SHL32(x, SIG_SHIFT) - m; + m = SHR32(MULT16_16(coef0, x), 15-SIG_SHIFT); + } + } + *mem = m; +} + + + +static opus_val32 l1_metric(const celt_norm *tmp, int N, int LM, opus_val16 bias) +{ + int i; + opus_val32 L1; + L1 = 0; + for (i=0;i<N;i++) + L1 += EXTEND32(ABS16(tmp[i])); + /* When in doubt, prefer good freq resolution */ + L1 = MAC16_32_Q15(L1, LM*bias, L1); + return L1; + +} + +static int tf_analysis(const CELTMode *m, int len, int isTransient, + int *tf_res, int lambda, celt_norm *X, int N0, int LM, + int *tf_sum, opus_val16 tf_estimate, int tf_chan) +{ + int i; + VARDECL(int, metric); + int cost0; + int cost1; + VARDECL(int, path0); + VARDECL(int, path1); + VARDECL(celt_norm, tmp); + VARDECL(celt_norm, tmp_1); + int sel; + int selcost[2]; + int tf_select=0; + opus_val16 bias; + + SAVE_STACK; + bias = MULT16_16_Q14(QCONST16(.04f,15), MAX16(-QCONST16(.25f,14), QCONST16(.5f,14)-tf_estimate)); + /*printf("%f ", bias);*/ + + ALLOC(metric, len, int); + ALLOC(tmp, (m->eBands[len]-m->eBands[len-1])<<LM, celt_norm); + ALLOC(tmp_1, (m->eBands[len]-m->eBands[len-1])<<LM, celt_norm); + ALLOC(path0, len, int); + ALLOC(path1, len, int); + + *tf_sum = 0; + for (i=0;i<len;i++) + { + int k, N; + int narrow; + opus_val32 L1, best_L1; + int best_level=0; + N = (m->eBands[i+1]-m->eBands[i])<<LM; + /* band is too narrow to be split down to LM=-1 */ + narrow = (m->eBands[i+1]-m->eBands[i])==1; + OPUS_COPY(tmp, &X[tf_chan*N0 + (m->eBands[i]<<LM)], N); + /* Just add the right channel if we're in stereo */ + /*if (C==2) + for (j=0;j<N;j++) + tmp[j] = ADD16(SHR16(tmp[j], 1),SHR16(X[N0+j+(m->eBands[i]<<LM)], 1));*/ + L1 = l1_metric(tmp, N, isTransient ? LM : 0, bias); + best_L1 = L1; + /* Check the -1 case for transients */ + if (isTransient && !narrow) + { + OPUS_COPY(tmp_1, tmp, N); + haar1(tmp_1, N>>LM, 1<<LM); + L1 = l1_metric(tmp_1, N, LM+1, bias); + if (L1<best_L1) + { + best_L1 = L1; + best_level = -1; + } + } + /*printf ("%f ", L1);*/ + for (k=0;k<LM+!(isTransient||narrow);k++) + { + int B; + + if (isTransient) + B = (LM-k-1); + else + B = k+1; + + haar1(tmp, N>>k, 1<<k); + + L1 = l1_metric(tmp, N, B, bias); + + if (L1 < best_L1) + { + best_L1 = L1; + best_level = k+1; + } + } + /*printf ("%d ", isTransient ? LM-best_level : best_level);*/ + /* metric is in Q1 to be able to select the mid-point (-0.5) for narrower bands */ + if (isTransient) + metric[i] = 2*best_level; + else + metric[i] = -2*best_level; + *tf_sum += (isTransient ? LM : 0) - metric[i]/2; + /* For bands that can't be split to -1, set the metric to the half-way point to avoid + biasing the decision */ + if (narrow && (metric[i]==0 || metric[i]==-2*LM)) + metric[i]-=1; + /*printf("%d ", metric[i]);*/ + } + /*printf("\n");*/ + /* Search for the optimal tf resolution, including tf_select */ + tf_select = 0; + for (sel=0;sel<2;sel++) + { + cost0 = 0; + cost1 = isTransient ? 0 : lambda; + for (i=1;i<len;i++) + { + int curr0, curr1; + curr0 = IMIN(cost0, cost1 + lambda); + curr1 = IMIN(cost0 + lambda, cost1); + cost0 = curr0 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*sel+0]); + cost1 = curr1 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*sel+1]); + } + cost0 = IMIN(cost0, cost1); + selcost[sel]=cost0; + } + /* For now, we're conservative and only allow tf_select=1 for transients. + * If tests confirm it's useful for non-transients, we could allow it. */ + if (selcost[1]<selcost[0] && isTransient) + tf_select=1; + cost0 = 0; + cost1 = isTransient ? 0 : lambda; + /* Viterbi forward pass */ + for (i=1;i<len;i++) + { + int curr0, curr1; + int from0, from1; + + from0 = cost0; + from1 = cost1 + lambda; + if (from0 < from1) + { + curr0 = from0; + path0[i]= 0; + } else { + curr0 = from1; + path0[i]= 1; + } + + from0 = cost0 + lambda; + from1 = cost1; + if (from0 < from1) + { + curr1 = from0; + path1[i]= 0; + } else { + curr1 = from1; + path1[i]= 1; + } + cost0 = curr0 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*tf_select+0]); + cost1 = curr1 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*tf_select+1]); + } + tf_res[len-1] = cost0 < cost1 ? 0 : 1; + /* Viterbi backward pass to check the decisions */ + for (i=len-2;i>=0;i--) + { + if (tf_res[i+1] == 1) + tf_res[i] = path1[i+1]; + else + tf_res[i] = path0[i+1]; + } + /*printf("%d %f\n", *tf_sum, tf_estimate);*/ + RESTORE_STACK; +#ifdef FUZZING + tf_select = rand()&0x1; + tf_res[0] = rand()&0x1; + for (i=1;i<len;i++) + tf_res[i] = tf_res[i-1] ^ ((rand()&0xF) == 0); +#endif + return tf_select; +} + +static void tf_encode(int start, int end, int isTransient, int *tf_res, int LM, int tf_select, ec_enc *enc) +{ + int curr, i; + int tf_select_rsv; + int tf_changed; + int logp; + opus_uint32 budget; + opus_uint32 tell; + budget = enc->storage*8; + tell = ec_tell(enc); + logp = isTransient ? 2 : 4; + /* Reserve space to code the tf_select decision. */ + tf_select_rsv = LM>0 && tell+logp+1 <= budget; + budget -= tf_select_rsv; + curr = tf_changed = 0; + for (i=start;i<end;i++) + { + if (tell+logp<=budget) + { + ec_enc_bit_logp(enc, tf_res[i] ^ curr, logp); + tell = ec_tell(enc); + curr = tf_res[i]; + tf_changed |= curr; + } + else + tf_res[i] = curr; + logp = isTransient ? 4 : 5; + } + /* Only code tf_select if it would actually make a difference. */ + if (tf_select_rsv && + tf_select_table[LM][4*isTransient+0+tf_changed]!= + tf_select_table[LM][4*isTransient+2+tf_changed]) + ec_enc_bit_logp(enc, tf_select, 1); + else + tf_select = 0; + for (i=start;i<end;i++) + tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]]; + /*for(i=0;i<end;i++)printf("%d ", isTransient ? tf_res[i] : LM+tf_res[i]);printf("\n");*/ +} + + +static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X, + const opus_val16 *bandLogE, int end, int LM, int C, int N0, + AnalysisInfo *analysis, opus_val16 *stereo_saving, opus_val16 tf_estimate, + int intensity, opus_val16 surround_trim, int arch) +{ + int i; + opus_val32 diff=0; + int c; + int trim_index; + opus_val16 trim = QCONST16(5.f, 8); + opus_val16 logXC, logXC2; + if (C==2) + { + opus_val16 sum = 0; /* Q10 */ + opus_val16 minXC; /* Q10 */ + /* Compute inter-channel correlation for low frequencies */ + for (i=0;i<8;i++) + { + opus_val32 partial; + partial = celt_inner_prod(&X[m->eBands[i]<<LM], &X[N0+(m->eBands[i]<<LM)], + (m->eBands[i+1]-m->eBands[i])<<LM, arch); + sum = ADD16(sum, EXTRACT16(SHR32(partial, 18))); + } + sum = MULT16_16_Q15(QCONST16(1.f/8, 15), sum); + sum = MIN16(QCONST16(1.f, 10), ABS16(sum)); + minXC = sum; + for (i=8;i<intensity;i++) + { + opus_val32 partial; + partial = celt_inner_prod(&X[m->eBands[i]<<LM], &X[N0+(m->eBands[i]<<LM)], + (m->eBands[i+1]-m->eBands[i])<<LM, arch); + minXC = MIN16(minXC, ABS16(EXTRACT16(SHR32(partial, 18)))); + } + minXC = MIN16(QCONST16(1.f, 10), ABS16(minXC)); + /*printf ("%f\n", sum);*/ + /* mid-side savings estimations based on the LF average*/ + logXC = celt_log2(QCONST32(1.001f, 20)-MULT16_16(sum, sum)); + /* mid-side savings estimations based on min correlation */ + logXC2 = MAX16(HALF16(logXC), celt_log2(QCONST32(1.001f, 20)-MULT16_16(minXC, minXC))); +#ifdef FIXED_POINT + /* Compensate for Q20 vs Q14 input and convert output to Q8 */ + logXC = PSHR32(logXC-QCONST16(6.f, DB_SHIFT),DB_SHIFT-8); + logXC2 = PSHR32(logXC2-QCONST16(6.f, DB_SHIFT),DB_SHIFT-8); +#endif + + trim += MAX16(-QCONST16(4.f, 8), MULT16_16_Q15(QCONST16(.75f,15),logXC)); + *stereo_saving = MIN16(*stereo_saving + QCONST16(0.25f, 8), -HALF16(logXC2)); + } + + /* Estimate spectral tilt */ + c=0; do { + for (i=0;i<end-1;i++) + { + diff += bandLogE[i+c*m->nbEBands]*(opus_int32)(2+2*i-end); + } + } while (++c<C); + diff /= C*(end-1); + /*printf("%f\n", diff);*/ + trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), SHR16(diff+QCONST16(1.f, DB_SHIFT),DB_SHIFT-8)/6 )); + trim -= SHR16(surround_trim, DB_SHIFT-8); + trim -= 2*SHR16(tf_estimate, 14-8); +#ifndef DISABLE_FLOAT_API + if (analysis->valid) + { + trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), + (opus_val16)(QCONST16(2.f, 8)*(analysis->tonality_slope+.05f)))); + } +#else + (void)analysis; +#endif + +#ifdef FIXED_POINT + trim_index = PSHR32(trim, 8); +#else + trim_index = (int)floor(.5f+trim); +#endif + trim_index = IMAX(0, IMIN(10, trim_index)); + /*printf("%d\n", trim_index);*/ +#ifdef FUZZING + trim_index = rand()%11; +#endif + return trim_index; +} + +static int stereo_analysis(const CELTMode *m, const celt_norm *X, + int LM, int N0) +{ + int i; + int thetas; + opus_val32 sumLR = EPSILON, sumMS = EPSILON; + + /* Use the L1 norm to model the entropy of the L/R signal vs the M/S signal */ + for (i=0;i<13;i++) + { + int j; + for (j=m->eBands[i]<<LM;j<m->eBands[i+1]<<LM;j++) + { + opus_val32 L, R, M, S; + /* We cast to 32-bit first because of the -32768 case */ + L = EXTEND32(X[j]); + R = EXTEND32(X[N0+j]); + M = ADD32(L, R); + S = SUB32(L, R); + sumLR = ADD32(sumLR, ADD32(ABS32(L), ABS32(R))); + sumMS = ADD32(sumMS, ADD32(ABS32(M), ABS32(S))); + } + } + sumMS = MULT16_32_Q15(QCONST16(0.707107f, 15), sumMS); + thetas = 13; + /* We don't need thetas for lower bands with LM<=1 */ + if (LM<=1) + thetas -= 8; + return MULT16_32_Q15((m->eBands[13]<<(LM+1))+thetas, sumMS) + > MULT16_32_Q15(m->eBands[13]<<(LM+1), sumLR); +} + +#define MSWAP(a,b) do {opus_val16 tmp = a;a=b;b=tmp;} while(0) +static opus_val16 median_of_5(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) + { + MSWAP(t0, t3); + MSWAP(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); + } +} + +static opus_val16 median_of_3(const opus_val16 *x) +{ + opus_val16 t0, t1, t2; + if (x[0] > x[1]) + { + t0 = x[1]; + t1 = x[0]; + } else { + t0 = x[0]; + t1 = x[1]; + } + t2 = x[2]; + if (t1 < t2) + return t1; + else if (t0 < t2) + return t2; + else + return t0; +} + +static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16 *bandLogE2, + int nbEBands, int start, int end, int C, int *offsets, int lsb_depth, const opus_int16 *logN, + int isTransient, int vbr, int constrained_vbr, const opus_int16 *eBands, int LM, + int effectiveBytes, opus_int32 *tot_boost_, int lfe, opus_val16 *surround_dynalloc) +{ + int i, c; + opus_int32 tot_boost=0; + opus_val16 maxDepth; + VARDECL(opus_val16, follower); + VARDECL(opus_val16, noise_floor); + SAVE_STACK; + ALLOC(follower, C*nbEBands, opus_val16); + ALLOC(noise_floor, C*nbEBands, opus_val16); + OPUS_CLEAR(offsets, nbEBands); + /* Dynamic allocation code */ + maxDepth=-QCONST16(31.9f, DB_SHIFT); + for (i=0;i<end;i++) + { + /* Noise floor must take into account eMeans, the depth, the width of the bands + and the preemphasis filter (approx. square of bark band ID) */ + noise_floor[i] = MULT16_16(QCONST16(0.0625f, DB_SHIFT),logN[i]) + +QCONST16(.5f,DB_SHIFT)+SHL16(9-lsb_depth,DB_SHIFT)-SHL16(eMeans[i],6) + +MULT16_16(QCONST16(.0062,DB_SHIFT),(i+5)*(i+5)); + } + c=0;do + { + for (i=0;i<end;i++) + maxDepth = MAX16(maxDepth, bandLogE[c*nbEBands+i]-noise_floor[i]); + } while (++c<C); + /* Make sure that dynamic allocation can't make us bust the budget */ + if (effectiveBytes > 50 && LM>=1 && !lfe) + { + int last=0; + c=0;do + { + opus_val16 offset; + opus_val16 tmp; + opus_val16 *f; + f = &follower[c*nbEBands]; + f[0] = bandLogE2[c*nbEBands]; + for (i=1;i<end;i++) + { + /* The last band to be at least 3 dB higher than the previous one + is the last we'll consider. Otherwise, we run into problems on + bandlimited signals. */ + if (bandLogE2[c*nbEBands+i] > bandLogE2[c*nbEBands+i-1]+QCONST16(.5f,DB_SHIFT)) + last=i; + f[i] = MIN16(f[i-1]+QCONST16(1.5f,DB_SHIFT), bandLogE2[c*nbEBands+i]); + } + for (i=last-1;i>=0;i--) + f[i] = MIN16(f[i], MIN16(f[i+1]+QCONST16(2.f,DB_SHIFT), bandLogE2[c*nbEBands+i])); + + /* Combine with a median filter to avoid dynalloc triggering unnecessarily. + The "offset" value controls how conservative we are -- a higher offset + reduces the impact of the median filter and makes dynalloc use more bits. */ + offset = QCONST16(1.f, DB_SHIFT); + for (i=2;i<end-2;i++) + f[i] = MAX16(f[i], median_of_5(&bandLogE2[c*nbEBands+i-2])-offset); + tmp = median_of_3(&bandLogE2[c*nbEBands])-offset; + f[0] = MAX16(f[0], tmp); + f[1] = MAX16(f[1], tmp); + tmp = median_of_3(&bandLogE2[c*nbEBands+end-3])-offset; + f[end-2] = MAX16(f[end-2], tmp); + f[end-1] = MAX16(f[end-1], tmp); + + for (i=0;i<end;i++) + f[i] = MAX16(f[i], noise_floor[i]); + } while (++c<C); + if (C==2) + { + for (i=start;i<end;i++) + { + /* Consider 24 dB "cross-talk" */ + follower[nbEBands+i] = MAX16(follower[nbEBands+i], follower[ i]-QCONST16(4.f,DB_SHIFT)); + follower[ i] = MAX16(follower[ i], follower[nbEBands+i]-QCONST16(4.f,DB_SHIFT)); + follower[i] = HALF16(MAX16(0, bandLogE[i]-follower[i]) + MAX16(0, bandLogE[nbEBands+i]-follower[nbEBands+i])); + } + } else { + for (i=start;i<end;i++) + { + follower[i] = MAX16(0, bandLogE[i]-follower[i]); + } + } + for (i=start;i<end;i++) + follower[i] = MAX16(follower[i], surround_dynalloc[i]); + /* For non-transient CBR/CVBR frames, halve the dynalloc contribution */ + if ((!vbr || constrained_vbr)&&!isTransient) + { + for (i=start;i<end;i++) + follower[i] = HALF16(follower[i]); + } + for (i=start;i<end;i++) + { + int width; + int boost; + int boost_bits; + + if (i<8) + follower[i] *= 2; + if (i>=12) + follower[i] = HALF16(follower[i]); + follower[i] = MIN16(follower[i], QCONST16(4, DB_SHIFT)); + + width = C*(eBands[i+1]-eBands[i])<<LM; + if (width<6) + { + boost = (int)SHR32(EXTEND32(follower[i]),DB_SHIFT); + boost_bits = boost*width<<BITRES; + } else if (width > 48) { + boost = (int)SHR32(EXTEND32(follower[i])*8,DB_SHIFT); + boost_bits = (boost*width<<BITRES)/8; + } else { + boost = (int)SHR32(EXTEND32(follower[i])*width/6,DB_SHIFT); + boost_bits = boost*6<<BITRES; + } + /* For CBR and non-transient CVBR frames, limit dynalloc to 1/4 of the bits */ + if ((!vbr || (constrained_vbr&&!isTransient)) + && (tot_boost+boost_bits)>>BITRES>>3 > effectiveBytes/4) + { + opus_int32 cap = ((effectiveBytes/4)<<BITRES<<3); + offsets[i] = cap-tot_boost; + tot_boost = cap; + break; + } else { + offsets[i] = boost; + tot_boost += boost_bits; + } + } + } + *tot_boost_ = tot_boost; + RESTORE_STACK; + return maxDepth; +} + + +static int run_prefilter(CELTEncoder *st, celt_sig *in, celt_sig *prefilter_mem, int CC, int N, + int prefilter_tapset, int *pitch, opus_val16 *gain, int *qgain, int enabled, int nbAvailableBytes) +{ + int c; + VARDECL(celt_sig, _pre); + celt_sig *pre[2]; + const CELTMode *mode; + int pitch_index; + opus_val16 gain1; + opus_val16 pf_threshold; + int pf_on; + int qg; + int overlap; + SAVE_STACK; + + mode = st->mode; + overlap = mode->overlap; + ALLOC(_pre, CC*(N+COMBFILTER_MAXPERIOD), celt_sig); + + pre[0] = _pre; + pre[1] = _pre + (N+COMBFILTER_MAXPERIOD); + + + c=0; do { + OPUS_COPY(pre[c], prefilter_mem+c*COMBFILTER_MAXPERIOD, COMBFILTER_MAXPERIOD); + OPUS_COPY(pre[c]+COMBFILTER_MAXPERIOD, in+c*(N+overlap)+overlap, N); + } while (++c<CC); + + if (enabled) + { + VARDECL(opus_val16, pitch_buf); + ALLOC(pitch_buf, (COMBFILTER_MAXPERIOD+N)>>1, opus_val16); + + pitch_downsample(pre, pitch_buf, COMBFILTER_MAXPERIOD+N, CC, st->arch); + /* Don't search for the fir last 1.5 octave of the range because + there's too many false-positives due to short-term correlation */ + pitch_search(pitch_buf+(COMBFILTER_MAXPERIOD>>1), pitch_buf, N, + COMBFILTER_MAXPERIOD-3*COMBFILTER_MINPERIOD, &pitch_index, + st->arch); + pitch_index = COMBFILTER_MAXPERIOD-pitch_index; + + gain1 = remove_doubling(pitch_buf, COMBFILTER_MAXPERIOD, COMBFILTER_MINPERIOD, + N, &pitch_index, st->prefilter_period, st->prefilter_gain, st->arch); + if (pitch_index > COMBFILTER_MAXPERIOD-2) + pitch_index = COMBFILTER_MAXPERIOD-2; + gain1 = MULT16_16_Q15(QCONST16(.7f,15),gain1); + /*printf("%d %d %f %f\n", pitch_change, pitch_index, gain1, st->analysis.tonality);*/ + if (st->loss_rate>2) + gain1 = HALF32(gain1); + if (st->loss_rate>4) + gain1 = HALF32(gain1); + if (st->loss_rate>8) + gain1 = 0; + } else { + gain1 = 0; + pitch_index = COMBFILTER_MINPERIOD; + } + + /* Gain threshold for enabling the prefilter/postfilter */ + pf_threshold = QCONST16(.2f,15); + + /* Adjusting the threshold based on rate and continuity */ + if (abs(pitch_index-st->prefilter_period)*10>pitch_index) + pf_threshold += QCONST16(.2f,15); + if (nbAvailableBytes<25) + pf_threshold += QCONST16(.1f,15); + if (nbAvailableBytes<35) + pf_threshold += QCONST16(.1f,15); + if (st->prefilter_gain > QCONST16(.4f,15)) + pf_threshold -= QCONST16(.1f,15); + if (st->prefilter_gain > QCONST16(.55f,15)) + pf_threshold -= QCONST16(.1f,15); + + /* Hard threshold at 0.2 */ + pf_threshold = MAX16(pf_threshold, QCONST16(.2f,15)); + if (gain1<pf_threshold) + { + gain1 = 0; + pf_on = 0; + qg = 0; + } else { + /*This block is not gated by a total bits check only because + of the nbAvailableBytes check above.*/ + if (ABS16(gain1-st->prefilter_gain)<QCONST16(.1f,15)) + gain1=st->prefilter_gain; + +#ifdef FIXED_POINT + qg = ((gain1+1536)>>10)/3-1; +#else + qg = (int)floor(.5f+gain1*32/3)-1; +#endif + qg = IMAX(0, IMIN(7, qg)); + gain1 = QCONST16(0.09375f,15)*(qg+1); + pf_on = 1; + } + /*printf("%d %f\n", pitch_index, gain1);*/ + + c=0; do { + int offset = mode->shortMdctSize-overlap; + st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD); + OPUS_COPY(in+c*(N+overlap), st->in_mem+c*(overlap), overlap); + if (offset) + comb_filter(in+c*(N+overlap)+overlap, pre[c]+COMBFILTER_MAXPERIOD, + st->prefilter_period, st->prefilter_period, offset, -st->prefilter_gain, -st->prefilter_gain, + st->prefilter_tapset, st->prefilter_tapset, NULL, 0, st->arch); + + comb_filter(in+c*(N+overlap)+overlap+offset, pre[c]+COMBFILTER_MAXPERIOD+offset, + st->prefilter_period, pitch_index, N-offset, -st->prefilter_gain, -gain1, + st->prefilter_tapset, prefilter_tapset, mode->window, overlap, st->arch); + OPUS_COPY(st->in_mem+c*(overlap), in+c*(N+overlap)+N, overlap); + + if (N>COMBFILTER_MAXPERIOD) + { + OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, pre[c]+N, COMBFILTER_MAXPERIOD); + } else { + OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, prefilter_mem+c*COMBFILTER_MAXPERIOD+N, COMBFILTER_MAXPERIOD-N); + OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD+COMBFILTER_MAXPERIOD-N, pre[c]+COMBFILTER_MAXPERIOD, N); + } + } while (++c<CC); + + RESTORE_STACK; + *gain = gain1; + *pitch = pitch_index; + *qgain = qg; + return pf_on; +} + +static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32 base_target, + int LM, opus_int32 bitrate, int lastCodedBands, int C, int intensity, + int constrained_vbr, opus_val16 stereo_saving, int tot_boost, + opus_val16 tf_estimate, int pitch_change, opus_val16 maxDepth, + int variable_duration, int lfe, int has_surround_mask, opus_val16 surround_masking, + opus_val16 temporal_vbr) +{ + /* The target rate in 8th bits per frame */ + opus_int32 target; + int coded_bins; + int coded_bands; + opus_val16 tf_calibration; + int nbEBands; + const opus_int16 *eBands; + + nbEBands = mode->nbEBands; + eBands = mode->eBands; + + coded_bands = lastCodedBands ? lastCodedBands : nbEBands; + coded_bins = eBands[coded_bands]<<LM; + if (C==2) + coded_bins += eBands[IMIN(intensity, coded_bands)]<<LM; + + target = base_target; + + /*printf("%f %f %f %f %d %d ", st->analysis.activity, st->analysis.tonality, tf_estimate, st->stereo_saving, tot_boost, coded_bands);*/ +#ifndef DISABLE_FLOAT_API + if (analysis->valid && analysis->activity<.4) + target -= (opus_int32)((coded_bins<<BITRES)*(.4f-analysis->activity)); +#endif + /* Stereo savings */ + if (C==2) + { + int coded_stereo_bands; + int coded_stereo_dof; + opus_val16 max_frac; + coded_stereo_bands = IMIN(intensity, coded_bands); + coded_stereo_dof = (eBands[coded_stereo_bands]<<LM)-coded_stereo_bands; + /* Maximum fraction of the bits we can save if the signal is mono. */ + max_frac = DIV32_16(MULT16_16(QCONST16(0.8f, 15), coded_stereo_dof), coded_bins); + stereo_saving = MIN16(stereo_saving, QCONST16(1.f, 8)); + /*printf("%d %d %d ", coded_stereo_dof, coded_bins, tot_boost);*/ + target -= (opus_int32)MIN32(MULT16_32_Q15(max_frac,target), + SHR32(MULT16_16(stereo_saving-QCONST16(0.1f,8),(coded_stereo_dof<<BITRES)),8)); + } + /* Boost the rate according to dynalloc (minus the dynalloc average for calibration). */ + target += tot_boost-(16<<LM); + /* Apply transient boost, compensating for average boost. */ + tf_calibration = variable_duration==OPUS_FRAMESIZE_VARIABLE ? + QCONST16(0.02f,14) : QCONST16(0.04f,14); + target += (opus_int32)SHL32(MULT16_32_Q15(tf_estimate-tf_calibration, target),1); + +#ifndef DISABLE_FLOAT_API + /* Apply tonality boost */ + if (analysis->valid && !lfe) + { + opus_int32 tonal_target; + float tonal; + + /* Tonality boost (compensating for the average). */ + tonal = MAX16(0.f,analysis->tonality-.15f)-0.09f; + tonal_target = target + (opus_int32)((coded_bins<<BITRES)*1.2f*tonal); + if (pitch_change) + tonal_target += (opus_int32)((coded_bins<<BITRES)*.8f); + /*printf("%f %f ", analysis->tonality, tonal);*/ + target = tonal_target; + } +#else + (void)analysis; + (void)pitch_change; +#endif + + if (has_surround_mask&&!lfe) + { + opus_int32 surround_target = target + (opus_int32)SHR32(MULT16_16(surround_masking,coded_bins<<BITRES), DB_SHIFT); + /*printf("%f %d %d %d %d %d %d ", surround_masking, coded_bins, st->end, st->intensity, surround_target, target, st->bitrate);*/ + target = IMAX(target/4, surround_target); + } + + { + opus_int32 floor_depth; + int bins; + bins = eBands[nbEBands-2]<<LM; + /*floor_depth = SHR32(MULT16_16((C*bins<<BITRES),celt_log2(SHL32(MAX16(1,sample_max),13))), DB_SHIFT);*/ + floor_depth = (opus_int32)SHR32(MULT16_16((C*bins<<BITRES),maxDepth), DB_SHIFT); + floor_depth = IMAX(floor_depth, target>>2); + target = IMIN(target, floor_depth); + /*printf("%f %d\n", maxDepth, floor_depth);*/ + } + + if ((!has_surround_mask||lfe) && (constrained_vbr || bitrate<64000)) + { + opus_val16 rate_factor; +#ifdef FIXED_POINT + rate_factor = MAX16(0,(bitrate-32000)); +#else + rate_factor = MAX16(0,(1.f/32768)*(bitrate-32000)); +#endif + if (constrained_vbr) + rate_factor = MIN16(rate_factor, QCONST16(0.67f, 15)); + target = base_target + (opus_int32)MULT16_32_Q15(rate_factor, target-base_target); + + } + + if (!has_surround_mask && tf_estimate < QCONST16(.2f, 14)) + { + opus_val16 amount; + opus_val16 tvbr_factor; + amount = MULT16_16_Q15(QCONST16(.0000031f, 30), IMAX(0, IMIN(32000, 96000-bitrate))); + tvbr_factor = SHR32(MULT16_16(temporal_vbr, amount), DB_SHIFT); + target += (opus_int32)MULT16_32_Q15(tvbr_factor, target); + } + + /* Don't allow more than doubling the rate */ + target = IMIN(2*base_target, target); + + return target; +} + +int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc) +{ + int i, c, N; + opus_int32 bits; + ec_enc _enc; + VARDECL(celt_sig, in); + VARDECL(celt_sig, freq); + VARDECL(celt_norm, X); + VARDECL(celt_ener, bandE); + VARDECL(opus_val16, bandLogE); + VARDECL(opus_val16, bandLogE2); + VARDECL(int, fine_quant); + VARDECL(opus_val16, error); + VARDECL(int, pulses); + VARDECL(int, cap); + VARDECL(int, offsets); + VARDECL(int, fine_priority); + VARDECL(int, tf_res); + VARDECL(unsigned char, collapse_masks); + celt_sig *prefilter_mem; + opus_val16 *oldBandE, *oldLogE, *oldLogE2; + int shortBlocks=0; + int isTransient=0; + const int CC = st->channels; + const int C = st->stream_channels; + int LM, M; + int tf_select; + int nbFilledBytes, nbAvailableBytes; + int start; + int end; + int effEnd; + int codedBands; + int tf_sum; + int alloc_trim; + int pitch_index=COMBFILTER_MINPERIOD; + opus_val16 gain1 = 0; + int dual_stereo=0; + int effectiveBytes; + int dynalloc_logp; + opus_int32 vbr_rate; + opus_int32 total_bits; + opus_int32 total_boost; + opus_int32 balance; + opus_int32 tell; + int prefilter_tapset=0; + int pf_on; + int anti_collapse_rsv; + int anti_collapse_on=0; + int silence=0; + int tf_chan = 0; + opus_val16 tf_estimate; + int pitch_change=0; + opus_int32 tot_boost; + opus_val32 sample_max; + opus_val16 maxDepth; + const OpusCustomMode *mode; + int nbEBands; + int overlap; + const opus_int16 *eBands; + int secondMdct; + int signalBandwidth; + int transient_got_disabled=0; + opus_val16 surround_masking=0; + opus_val16 temporal_vbr=0; + opus_val16 surround_trim = 0; + opus_int32 equiv_rate = 510000; + VARDECL(opus_val16, surround_dynalloc); + ALLOC_STACK; + + mode = st->mode; + nbEBands = mode->nbEBands; + overlap = mode->overlap; + eBands = mode->eBands; + start = st->start; + end = st->end; + tf_estimate = 0; + if (nbCompressedBytes<2 || pcm==NULL) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + + frame_size *= st->upsample; + for (LM=0;LM<=mode->maxLM;LM++) + if (mode->shortMdctSize<<LM==frame_size) + break; + if (LM>mode->maxLM) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + M=1<<LM; + N = M*mode->shortMdctSize; + + prefilter_mem = st->in_mem+CC*(overlap); + oldBandE = (opus_val16*)(st->in_mem+CC*(overlap+COMBFILTER_MAXPERIOD)); + oldLogE = oldBandE + CC*nbEBands; + oldLogE2 = oldLogE + CC*nbEBands; + + if (enc==NULL) + { + tell=1; + nbFilledBytes=0; + } else { + tell=ec_tell(enc); + nbFilledBytes=(tell+4)>>3; + } + +#ifdef CUSTOM_MODES + if (st->signalling && enc==NULL) + { + int tmp = (mode->effEBands-end)>>1; + end = st->end = IMAX(1, mode->effEBands-tmp); + compressed[0] = tmp<<5; + compressed[0] |= LM<<3; + compressed[0] |= (C==2)<<2; + /* Convert "standard mode" to Opus header */ + if (mode->Fs==48000 && mode->shortMdctSize==120) + { + int c0 = toOpus(compressed[0]); + if (c0<0) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + compressed[0] = c0; + } + compressed++; + nbCompressedBytes--; + } +#else + celt_assert(st->signalling==0); +#endif + + /* Can't produce more than 1275 output bytes */ + nbCompressedBytes = IMIN(nbCompressedBytes,1275); + nbAvailableBytes = nbCompressedBytes - nbFilledBytes; + + if (st->vbr && st->bitrate!=OPUS_BITRATE_MAX) + { + opus_int32 den=mode->Fs>>BITRES; + vbr_rate=(st->bitrate*frame_size+(den>>1))/den; +#ifdef CUSTOM_MODES + if (st->signalling) + vbr_rate -= 8<<BITRES; +#endif + effectiveBytes = vbr_rate>>(3+BITRES); + } else { + opus_int32 tmp; + vbr_rate = 0; + tmp = st->bitrate*frame_size; + if (tell>1) + tmp += tell; + if (st->bitrate!=OPUS_BITRATE_MAX) + nbCompressedBytes = IMAX(2, IMIN(nbCompressedBytes, + (tmp+4*mode->Fs)/(8*mode->Fs)-!!st->signalling)); + effectiveBytes = nbCompressedBytes; + } + if (st->bitrate != OPUS_BITRATE_MAX) + equiv_rate = st->bitrate - (40*C+20)*((400>>LM) - 50); + + if (enc==NULL) + { + ec_enc_init(&_enc, compressed, nbCompressedBytes); + enc = &_enc; + } + + if (vbr_rate>0) + { + /* Computes the max bit-rate allowed in VBR mode to avoid violating the + target rate and buffering. + We must do this up front so that bust-prevention logic triggers + correctly if we don't have enough bits. */ + if (st->constrained_vbr) + { + opus_int32 vbr_bound; + opus_int32 max_allowed; + /* We could use any multiple of vbr_rate as bound (depending on the + delay). + This is clamped to ensure we use at least two bytes if the encoder + was entirely empty, but to allow 0 in hybrid mode. */ + vbr_bound = vbr_rate; + max_allowed = IMIN(IMAX(tell==1?2:0, + (vbr_rate+vbr_bound-st->vbr_reservoir)>>(BITRES+3)), + nbAvailableBytes); + if(max_allowed < nbAvailableBytes) + { + nbCompressedBytes = nbFilledBytes+max_allowed; + nbAvailableBytes = max_allowed; + ec_enc_shrink(enc, nbCompressedBytes); + } + } + } + total_bits = nbCompressedBytes*8; + + effEnd = end; + if (effEnd > mode->effEBands) + effEnd = mode->effEBands; + + ALLOC(in, CC*(N+overlap), celt_sig); + + sample_max=MAX32(st->overlap_max, celt_maxabs16(pcm, C*(N-overlap)/st->upsample)); + st->overlap_max=celt_maxabs16(pcm+C*(N-overlap)/st->upsample, C*overlap/st->upsample); + sample_max=MAX32(sample_max, st->overlap_max); +#ifdef FIXED_POINT + silence = (sample_max==0); +#else + silence = (sample_max <= (opus_val16)1/(1<<st->lsb_depth)); +#endif +#ifdef FUZZING + if ((rand()&0x3F)==0) + silence = 1; +#endif + if (tell==1) + ec_enc_bit_logp(enc, silence, 15); + else + silence=0; + if (silence) + { + /*In VBR mode there is no need to send more than the minimum. */ + if (vbr_rate>0) + { + effectiveBytes=nbCompressedBytes=IMIN(nbCompressedBytes, nbFilledBytes+2); + total_bits=nbCompressedBytes*8; + nbAvailableBytes=2; + ec_enc_shrink(enc, nbCompressedBytes); + } + /* Pretend we've filled all the remaining bits with zeros + (that's what the initialiser did anyway) */ + tell = nbCompressedBytes*8; + enc->nbits_total+=tell-ec_tell(enc); + } + c=0; do { + int need_clip=0; +#ifndef FIXED_POINT + need_clip = st->clip && sample_max>65536.f; +#endif + celt_preemphasis(pcm+c, in+c*(N+overlap)+overlap, N, CC, st->upsample, + mode->preemph, st->preemph_memE+c, need_clip); + } while (++c<CC); + + + + /* Find pitch period and gain */ + { + int enabled; + int qg; + enabled = ((st->lfe&&nbAvailableBytes>3) || nbAvailableBytes>12*C) && start==0 && !silence && !st->disable_pf + && st->complexity >= 5 && !(st->consec_transient && LM!=3 && st->variable_duration==OPUS_FRAMESIZE_VARIABLE); + + prefilter_tapset = st->tapset_decision; + pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, nbAvailableBytes); + if ((gain1 > QCONST16(.4f,15) || st->prefilter_gain > QCONST16(.4f,15)) && (!st->analysis.valid || st->analysis.tonality > .3) + && (pitch_index > 1.26*st->prefilter_period || pitch_index < .79*st->prefilter_period)) + pitch_change = 1; + if (pf_on==0) + { + if(start==0 && tell+16<=total_bits) + ec_enc_bit_logp(enc, 0, 1); + } else { + /*This block is not gated by a total bits check only because + of the nbAvailableBytes check above.*/ + int octave; + ec_enc_bit_logp(enc, 1, 1); + pitch_index += 1; + octave = EC_ILOG(pitch_index)-5; + ec_enc_uint(enc, octave, 6); + ec_enc_bits(enc, pitch_index-(16<<octave), 4+octave); + pitch_index -= 1; + ec_enc_bits(enc, qg, 3); + ec_enc_icdf(enc, prefilter_tapset, tapset_icdf, 2); + } + } + + isTransient = 0; + shortBlocks = 0; + if (st->complexity >= 1 && !st->lfe) + { + isTransient = transient_analysis(in, N+overlap, CC, + &tf_estimate, &tf_chan); + } + if (LM>0 && ec_tell(enc)+3<=total_bits) + { + if (isTransient) + shortBlocks = M; + } else { + isTransient = 0; + transient_got_disabled=1; + } + + ALLOC(freq, CC*N, celt_sig); /**< Interleaved signal MDCTs */ + ALLOC(bandE,nbEBands*CC, celt_ener); + ALLOC(bandLogE,nbEBands*CC, opus_val16); + + secondMdct = shortBlocks && st->complexity>=8; + ALLOC(bandLogE2, C*nbEBands, opus_val16); + if (secondMdct) + { + compute_mdcts(mode, 0, in, freq, C, CC, LM, st->upsample, st->arch); + compute_band_energies(mode, freq, bandE, effEnd, C, LM); + amp2Log2(mode, effEnd, end, bandE, bandLogE2, C); + for (i=0;i<C*nbEBands;i++) + bandLogE2[i] += HALF16(SHL16(LM, DB_SHIFT)); + } + + compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample, st->arch); + if (CC==2&&C==1) + tf_chan = 0; + compute_band_energies(mode, freq, bandE, effEnd, C, LM); + + if (st->lfe) + { + for (i=2;i<end;i++) + { + bandE[i] = IMIN(bandE[i], MULT16_32_Q15(QCONST16(1e-4f,15),bandE[0])); + bandE[i] = MAX32(bandE[i], EPSILON); + } + } + amp2Log2(mode, effEnd, end, bandE, bandLogE, C); + + ALLOC(surround_dynalloc, C*nbEBands, opus_val16); + OPUS_CLEAR(surround_dynalloc, end); + /* This computes how much masking takes place between surround channels */ + if (start==0&&st->energy_mask&&!st->lfe) + { + int mask_end; + int midband; + int count_dynalloc; + opus_val32 mask_avg=0; + opus_val32 diff=0; + int count=0; + mask_end = IMAX(2,st->lastCodedBands); + for (c=0;c<C;c++) + { + for(i=0;i<mask_end;i++) + { + opus_val16 mask; + mask = MAX16(MIN16(st->energy_mask[nbEBands*c+i], + QCONST16(.25f, DB_SHIFT)), -QCONST16(2.0f, DB_SHIFT)); + if (mask > 0) + mask = HALF16(mask); + mask_avg += MULT16_16(mask, eBands[i+1]-eBands[i]); + count += eBands[i+1]-eBands[i]; + diff += MULT16_16(mask, 1+2*i-mask_end); + } + } + celt_assert(count>0); + mask_avg = DIV32_16(mask_avg,count); + mask_avg += QCONST16(.2f, DB_SHIFT); + diff = diff*6/(C*(mask_end-1)*(mask_end+1)*mask_end); + /* Again, being conservative */ + diff = HALF32(diff); + diff = MAX32(MIN32(diff, QCONST32(.031f, DB_SHIFT)), -QCONST32(.031f, DB_SHIFT)); + /* Find the band that's in the middle of the coded spectrum */ + for (midband=0;eBands[midband+1] < eBands[mask_end]/2;midband++); + count_dynalloc=0; + for(i=0;i<mask_end;i++) + { + opus_val32 lin; + opus_val16 unmask; + lin = mask_avg + diff*(i-midband); + if (C==2) + unmask = MAX16(st->energy_mask[i], st->energy_mask[nbEBands+i]); + else + unmask = st->energy_mask[i]; + unmask = MIN16(unmask, QCONST16(.0f, DB_SHIFT)); + unmask -= lin; + if (unmask > QCONST16(.25f, DB_SHIFT)) + { + surround_dynalloc[i] = unmask - QCONST16(.25f, DB_SHIFT); + count_dynalloc++; + } + } + if (count_dynalloc>=3) + { + /* If we need dynalloc in many bands, it's probably because our + initial masking rate was too low. */ + mask_avg += QCONST16(.25f, DB_SHIFT); + if (mask_avg>0) + { + /* Something went really wrong in the original calculations, + disabling masking. */ + mask_avg = 0; + diff = 0; + OPUS_CLEAR(surround_dynalloc, mask_end); + } else { + for(i=0;i<mask_end;i++) + surround_dynalloc[i] = MAX16(0, surround_dynalloc[i]-QCONST16(.25f, DB_SHIFT)); + } + } + mask_avg += QCONST16(.2f, DB_SHIFT); + /* Convert to 1/64th units used for the trim */ + surround_trim = 64*diff; + /*printf("%d %d ", mask_avg, surround_trim);*/ + surround_masking = mask_avg; + } + /* Temporal VBR (but not for LFE) */ + if (!st->lfe) + { + opus_val16 follow=-QCONST16(10.0f,DB_SHIFT); + opus_val32 frame_avg=0; + opus_val16 offset = shortBlocks?HALF16(SHL16(LM, DB_SHIFT)):0; + for(i=start;i<end;i++) + { + follow = MAX16(follow-QCONST16(1.f, DB_SHIFT), bandLogE[i]-offset); + if (C==2) + follow = MAX16(follow, bandLogE[i+nbEBands]-offset); + frame_avg += follow; + } + frame_avg /= (end-start); + temporal_vbr = SUB16(frame_avg,st->spec_avg); + temporal_vbr = MIN16(QCONST16(3.f, DB_SHIFT), MAX16(-QCONST16(1.5f, DB_SHIFT), temporal_vbr)); + st->spec_avg += MULT16_16_Q15(QCONST16(.02f, 15), temporal_vbr); + } + /*for (i=0;i<21;i++) + printf("%f ", bandLogE[i]); + printf("\n");*/ + + if (!secondMdct) + { + OPUS_COPY(bandLogE2, bandLogE, C*nbEBands); + } + + /* Last chance to catch any transient we might have missed in the + time-domain analysis */ + if (LM>0 && ec_tell(enc)+3<=total_bits && !isTransient && st->complexity>=5 && !st->lfe) + { + if (patch_transient_decision(bandLogE, oldBandE, nbEBands, start, end, C)) + { + isTransient = 1; + shortBlocks = M; + compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample, st->arch); + compute_band_energies(mode, freq, bandE, effEnd, C, LM); + amp2Log2(mode, effEnd, end, bandE, bandLogE, C); + /* Compensate for the scaling of short vs long mdcts */ + for (i=0;i<C*nbEBands;i++) + bandLogE2[i] += HALF16(SHL16(LM, DB_SHIFT)); + tf_estimate = QCONST16(.2f,14); + } + } + + if (LM>0 && ec_tell(enc)+3<=total_bits) + ec_enc_bit_logp(enc, isTransient, 3); + + ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ + + /* Band normalisation */ + normalise_bands(mode, freq, X, bandE, effEnd, C, M); + + ALLOC(tf_res, nbEBands, int); + /* Disable variable tf resolution for hybrid and at very low bitrate */ + if (effectiveBytes>=15*C && start==0 && st->complexity>=2 && !st->lfe) + { + int lambda; + if (effectiveBytes<40) + lambda = 12; + else if (effectiveBytes<60) + lambda = 6; + else if (effectiveBytes<100) + lambda = 4; + else + lambda = 3; + lambda*=2; + tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, &tf_sum, tf_estimate, tf_chan); + for (i=effEnd;i<end;i++) + tf_res[i] = tf_res[effEnd-1]; + } else { + tf_sum = 0; + for (i=0;i<end;i++) + tf_res[i] = isTransient; + tf_select=0; + } + + ALLOC(error, C*nbEBands, opus_val16); + quant_coarse_energy(mode, start, end, effEnd, bandLogE, + oldBandE, total_bits, error, enc, + C, LM, nbAvailableBytes, st->force_intra, + &st->delayedIntra, st->complexity >= 4, st->loss_rate, st->lfe); + + tf_encode(start, end, isTransient, tf_res, LM, tf_select, enc); + + if (ec_tell(enc)+4<=total_bits) + { + if (st->lfe) + { + st->tapset_decision = 0; + st->spread_decision = SPREAD_NORMAL; + } else if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C || start != 0) + { + if (st->complexity == 0) + st->spread_decision = SPREAD_NONE; + else + st->spread_decision = SPREAD_NORMAL; + } else { + /* Disable new spreading+tapset estimator until we can show it works + better than the old one. So far it seems like spreading_decision() + works best. */ +#if 0 + if (st->analysis.valid) + { + static const opus_val16 spread_thresholds[3] = {-QCONST16(.6f, 15), -QCONST16(.2f, 15), -QCONST16(.07f, 15)}; + static const opus_val16 spread_histeresis[3] = {QCONST16(.15f, 15), QCONST16(.07f, 15), QCONST16(.02f, 15)}; + static const opus_val16 tapset_thresholds[2] = {QCONST16(.0f, 15), QCONST16(.15f, 15)}; + static const opus_val16 tapset_histeresis[2] = {QCONST16(.1f, 15), QCONST16(.05f, 15)}; + st->spread_decision = hysteresis_decision(-st->analysis.tonality, spread_thresholds, spread_histeresis, 3, st->spread_decision); + st->tapset_decision = hysteresis_decision(st->analysis.tonality_slope, tapset_thresholds, tapset_histeresis, 2, st->tapset_decision); + } else +#endif + { + st->spread_decision = spreading_decision(mode, X, + &st->tonal_average, st->spread_decision, &st->hf_average, + &st->tapset_decision, pf_on&&!shortBlocks, effEnd, C, M); + } + /*printf("%d %d\n", st->tapset_decision, st->spread_decision);*/ + /*printf("%f %d %f %d\n\n", st->analysis.tonality, st->spread_decision, st->analysis.tonality_slope, st->tapset_decision);*/ + } + ec_enc_icdf(enc, st->spread_decision, spread_icdf, 5); + } + + ALLOC(offsets, nbEBands, int); + + maxDepth = dynalloc_analysis(bandLogE, bandLogE2, nbEBands, start, end, C, offsets, + st->lsb_depth, mode->logN, isTransient, st->vbr, st->constrained_vbr, + eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc); + /* For LFE, everything interesting is in the first band */ + if (st->lfe) + offsets[0] = IMIN(8, effectiveBytes/3); + ALLOC(cap, nbEBands, int); + init_caps(mode,cap,LM,C); + + dynalloc_logp = 6; + total_bits<<=BITRES; + total_boost = 0; + tell = ec_tell_frac(enc); + for (i=start;i<end;i++) + { + int width, quanta; + int dynalloc_loop_logp; + int boost; + int j; + 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; + for (j = 0; tell+(dynalloc_loop_logp<<BITRES) < total_bits-total_boost + && boost < cap[i]; j++) + { + int flag; + flag = j<offsets[i]; + ec_enc_bit_logp(enc, flag, dynalloc_loop_logp); + tell = ec_tell_frac(enc); + if (!flag) + break; + boost += quanta; + total_boost += quanta; + dynalloc_loop_logp = 1; + } + /* Making dynalloc more likely */ + if (j) + dynalloc_logp = IMAX(2, dynalloc_logp-1); + offsets[i] = boost; + } + + if (C==2) + { + static const opus_val16 intensity_thresholds[21]= + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 off*/ + { 1, 2, 3, 4, 5, 6, 7, 8,16,24,36,44,50,56,62,67,72,79,88,106,134}; + static const opus_val16 intensity_histeresis[21]= + { 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 5, 6, 8, 8}; + + /* Always use MS for 2.5 ms frames until we can do a better analysis */ + if (LM!=0) + dual_stereo = stereo_analysis(mode, X, LM, N); + + st->intensity = hysteresis_decision((opus_val16)(equiv_rate/1000), + intensity_thresholds, intensity_histeresis, 21, st->intensity); + st->intensity = IMIN(end,IMAX(start, st->intensity)); + } + + alloc_trim = 5; + if (tell+(6<<BITRES) <= total_bits - total_boost) + { + if (st->lfe) + alloc_trim = 5; + else + alloc_trim = alloc_trim_analysis(mode, X, bandLogE, + end, LM, C, N, &st->analysis, &st->stereo_saving, tf_estimate, + st->intensity, surround_trim, st->arch); + ec_enc_icdf(enc, alloc_trim, trim_icdf, 7); + tell = ec_tell_frac(enc); + } + + /* Variable bitrate */ + if (vbr_rate>0) + { + opus_val16 alpha; + opus_int32 delta; + /* The target rate in 8th bits per frame */ + opus_int32 target, base_target; + opus_int32 min_allowed; + int lm_diff = mode->maxLM - LM; + + /* Don't attempt to use more than 510 kb/s, even for frames smaller than 20 ms. + The CELT allocator will just not be able to use more than that anyway. */ + nbCompressedBytes = IMIN(nbCompressedBytes,1275>>(3-LM)); + base_target = vbr_rate - ((40*C+20)<<BITRES); + + if (st->constrained_vbr) + base_target += (st->vbr_offset>>lm_diff); + + target = compute_vbr(mode, &st->analysis, base_target, LM, equiv_rate, + st->lastCodedBands, C, st->intensity, st->constrained_vbr, + st->stereo_saving, tot_boost, tf_estimate, pitch_change, maxDepth, + st->variable_duration, st->lfe, st->energy_mask!=NULL, surround_masking, + temporal_vbr); + + /* The current offset is removed from the target and the space used + so far is added*/ + target=target+tell; + /* In VBR mode the frame size must not be reduced so much that it would + result in the encoder running out of bits. + The margin of 2 bytes ensures that none of the bust-prevention logic + in the decoder will have triggered so far. */ + min_allowed = ((tell+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3)) + 2 - nbFilledBytes; + + nbAvailableBytes = (target+(1<<(BITRES+2)))>>(BITRES+3); + nbAvailableBytes = IMAX(min_allowed,nbAvailableBytes); + nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes) - nbFilledBytes; + + /* By how much did we "miss" the target on that frame */ + delta = target - vbr_rate; + + target=nbAvailableBytes<<(BITRES+3); + + /*If the frame is silent we don't adjust our drift, otherwise + the encoder will shoot to very high rates after hitting a + span of silence, but we do allow the bitres to refill. + This means that we'll undershoot our target in CVBR/VBR modes + on files with lots of silence. */ + if(silence) + { + nbAvailableBytes = 2; + target = 2*8<<BITRES; + delta = 0; + } + + if (st->vbr_count < 970) + { + st->vbr_count++; + alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+20),16)); + } else + alpha = QCONST16(.001f,15); + /* How many bits have we used in excess of what we're allowed */ + if (st->constrained_vbr) + st->vbr_reservoir += target - vbr_rate; + /*printf ("%d\n", st->vbr_reservoir);*/ + + /* Compute the offset we need to apply in order to reach the target */ + if (st->constrained_vbr) + { + st->vbr_drift += (opus_int32)MULT16_32_Q15(alpha,(delta*(1<<lm_diff))-st->vbr_offset-st->vbr_drift); + st->vbr_offset = -st->vbr_drift; + } + /*printf ("%d\n", st->vbr_drift);*/ + + if (st->constrained_vbr && st->vbr_reservoir < 0) + { + /* We're under the min value -- increase rate */ + int adjust = (-st->vbr_reservoir)/(8<<BITRES); + /* Unless we're just coding silence */ + nbAvailableBytes += silence?0:adjust; + st->vbr_reservoir = 0; + /*printf ("+%d\n", adjust);*/ + } + nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes); + /*printf("%d\n", nbCompressedBytes*50*8);*/ + /* This moves the raw bits to take into account the new compressed size */ + ec_enc_shrink(enc, nbCompressedBytes); + } + + /* Bit allocation */ + ALLOC(fine_quant, nbEBands, int); + ALLOC(pulses, nbEBands, int); + ALLOC(fine_priority, nbEBands, int); + + /* bits = packet size - where we are - safety*/ + bits = (((opus_int32)nbCompressedBytes*8)<<BITRES) - ec_tell_frac(enc) - 1; + anti_collapse_rsv = isTransient&&LM>=2&&bits>=((LM+2)<<BITRES) ? (1<<BITRES) : 0; + bits -= anti_collapse_rsv; + signalBandwidth = end-1; +#ifndef DISABLE_FLOAT_API + if (st->analysis.valid) + { + int min_bandwidth; + if (equiv_rate < (opus_int32)32000*C) + min_bandwidth = 13; + else if (equiv_rate < (opus_int32)48000*C) + min_bandwidth = 16; + else if (equiv_rate < (opus_int32)60000*C) + min_bandwidth = 18; + else if (equiv_rate < (opus_int32)80000*C) + min_bandwidth = 19; + else + min_bandwidth = 20; + signalBandwidth = IMAX(st->analysis.bandwidth, min_bandwidth); + } +#endif + if (st->lfe) + signalBandwidth = 1; + codedBands = compute_allocation(mode, start, end, offsets, cap, + alloc_trim, &st->intensity, &dual_stereo, bits, &balance, pulses, + fine_quant, fine_priority, C, LM, enc, 1, st->lastCodedBands, signalBandwidth); + if (st->lastCodedBands) + st->lastCodedBands = IMIN(st->lastCodedBands+1,IMAX(st->lastCodedBands-1,codedBands)); + else + st->lastCodedBands = codedBands; + + quant_fine_energy(mode, start, end, oldBandE, error, fine_quant, enc, C); + + /* Residual quantisation */ + ALLOC(collapse_masks, C*nbEBands, unsigned char); + quant_all_bands(1, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks, + bandE, pulses, shortBlocks, st->spread_decision, + dual_stereo, st->intensity, tf_res, nbCompressedBytes*(8<<BITRES)-anti_collapse_rsv, + balance, enc, LM, codedBands, &st->rng, st->arch); + + if (anti_collapse_rsv > 0) + { + anti_collapse_on = st->consec_transient<2; +#ifdef FUZZING + anti_collapse_on = rand()&0x1; +#endif + ec_enc_bits(enc, anti_collapse_on, 1); + } + quant_energy_finalise(mode, start, end, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_tell(enc), enc, C); + + if (silence) + { + for (i=0;i<C*nbEBands;i++) + oldBandE[i] = -QCONST16(28.f,DB_SHIFT); + } + +#ifdef RESYNTH + /* Re-synthesis of the coded audio if required */ + { + celt_sig *out_mem[2]; + + if (anti_collapse_on) + { + anti_collapse(mode, X, collapse_masks, LM, C, N, + start, end, oldBandE, oldLogE, oldLogE2, pulses, st->rng); + } + + c=0; do { + OPUS_MOVE(st->syn_mem[c], st->syn_mem[c]+N, 2*MAX_PERIOD-N+overlap/2); + } while (++c<CC); + + c=0; do { + out_mem[c] = st->syn_mem[c]+2*MAX_PERIOD-N; + } while (++c<CC); + + celt_synthesis(mode, X, out_mem, oldBandE, start, effEnd, + C, CC, isTransient, LM, st->upsample, silence, st->arch); + + c=0; do { + st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD); + st->prefilter_period_old=IMAX(st->prefilter_period_old, COMBFILTER_MINPERIOD); + comb_filter(out_mem[c], out_mem[c], st->prefilter_period_old, st->prefilter_period, mode->shortMdctSize, + st->prefilter_gain_old, st->prefilter_gain, st->prefilter_tapset_old, st->prefilter_tapset, + mode->window, overlap); + if (LM!=0) + comb_filter(out_mem[c]+mode->shortMdctSize, out_mem[c]+mode->shortMdctSize, st->prefilter_period, pitch_index, N-mode->shortMdctSize, + st->prefilter_gain, gain1, st->prefilter_tapset, prefilter_tapset, + mode->window, overlap); + } while (++c<CC); + + /* We reuse freq[] as scratch space for the de-emphasis */ + deemphasis(out_mem, (opus_val16*)pcm, N, CC, st->upsample, mode->preemph, st->preemph_memD); + st->prefilter_period_old = st->prefilter_period; + st->prefilter_gain_old = st->prefilter_gain; + st->prefilter_tapset_old = st->prefilter_tapset; + } +#endif + + st->prefilter_period = pitch_index; + st->prefilter_gain = gain1; + st->prefilter_tapset = prefilter_tapset; +#ifdef RESYNTH + if (LM!=0) + { + st->prefilter_period_old = st->prefilter_period; + st->prefilter_gain_old = st->prefilter_gain; + st->prefilter_tapset_old = st->prefilter_tapset; + } +#endif + + if (CC==2&&C==1) { + OPUS_COPY(&oldBandE[nbEBands], oldBandE, nbEBands); + } + + if (!isTransient) + { + OPUS_COPY(oldLogE2, oldLogE, CC*nbEBands); + OPUS_COPY(oldLogE, oldBandE, CC*nbEBands); + } else { + for (i=0;i<CC*nbEBands;i++) + oldLogE[i] = MIN16(oldLogE[i], 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]=-QCONST16(28.f,DB_SHIFT); + } + for (i=end;i<nbEBands;i++) + { + oldBandE[c*nbEBands+i]=0; + oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT); + } + } while (++c<CC); + + if (isTransient || transient_got_disabled) + st->consec_transient++; + else + st->consec_transient=0; + st->rng = enc->rng; + + /* If there's any room left (can only happen for very high rates), + it's already filled with zeros */ + ec_enc_done(enc); + +#ifdef CUSTOM_MODES + if (st->signalling) + nbCompressedBytes++; +#endif + + RESTORE_STACK; + if (ec_get_error(enc)) + return OPUS_INTERNAL_ERROR; + else + return nbCompressedBytes; +} + + +#ifdef CUSTOM_MODES + +#ifdef FIXED_POINT +int opus_custom_encode(CELTEncoder * OPUS_RESTRICT st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) +{ + return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL); +} + +#ifndef DISABLE_FLOAT_API +int opus_custom_encode_float(CELTEncoder * OPUS_RESTRICT st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) +{ + int j, ret, C, N; + VARDECL(opus_int16, in); + ALLOC_STACK; + + if (pcm==NULL) + return OPUS_BAD_ARG; + + C = st->channels; + N = frame_size; + ALLOC(in, C*N, opus_int16); + + for (j=0;j<C*N;j++) + in[j] = FLOAT2INT16(pcm[j]); + + ret=celt_encode_with_ec(st,in,frame_size,compressed,nbCompressedBytes, NULL); +#ifdef RESYNTH + for (j=0;j<C*N;j++) + ((float*)pcm)[j]=in[j]*(1.f/32768.f); +#endif + RESTORE_STACK; + return ret; +} +#endif /* DISABLE_FLOAT_API */ +#else + +int opus_custom_encode(CELTEncoder * OPUS_RESTRICT st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) +{ + int j, ret, C, N; + VARDECL(celt_sig, in); + ALLOC_STACK; + + if (pcm==NULL) + return OPUS_BAD_ARG; + + C=st->channels; + N=frame_size; + ALLOC(in, C*N, celt_sig); + for (j=0;j<C*N;j++) { + in[j] = SCALEOUT(pcm[j]); + } + + ret = celt_encode_with_ec(st,in,frame_size,compressed,nbCompressedBytes, NULL); +#ifdef RESYNTH + for (j=0;j<C*N;j++) + ((opus_int16*)pcm)[j] = FLOAT2INT16(in[j]); +#endif + RESTORE_STACK; + return ret; +} + +int opus_custom_encode_float(CELTEncoder * OPUS_RESTRICT st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) +{ + return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL); +} + +#endif + +#endif /* CUSTOM_MODES */ + +int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...) +{ + va_list ap; + + va_start(ap, request); + switch (request) + { + case OPUS_SET_COMPLEXITY_REQUEST: + { + int value = va_arg(ap, opus_int32); + if (value<0 || value>10) + goto bad_arg; + st->complexity = value; + } + 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_PREDICTION_REQUEST: + { + int value = va_arg(ap, opus_int32); + if (value<0 || value>2) + goto bad_arg; + st->disable_pf = value<=1; + st->force_intra = value==0; + } + break; + case OPUS_SET_PACKET_LOSS_PERC_REQUEST: + { + int value = va_arg(ap, opus_int32); + if (value<0 || value>100) + goto bad_arg; + st->loss_rate = value; + } + break; + case OPUS_SET_VBR_CONSTRAINT_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->constrained_vbr = value; + } + break; + case OPUS_SET_VBR_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->vbr = value; + } + break; + case OPUS_SET_BITRATE_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<=500 && value!=OPUS_BITRATE_MAX) + goto bad_arg; + value = IMIN(value, 260000*st->channels); + st->bitrate = 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 OPUS_SET_LSB_DEPTH_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<8 || value>24) + goto bad_arg; + st->lsb_depth=value; + } + break; + case OPUS_GET_LSB_DEPTH_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + *value=st->lsb_depth; + } + break; + case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->variable_duration = value; + } + break; + case OPUS_RESET_STATE: + { + int i; + opus_val16 *oldBandE, *oldLogE, *oldLogE2; + oldBandE = (opus_val16*)(st->in_mem+st->channels*(st->mode->overlap+COMBFILTER_MAXPERIOD)); + oldLogE = oldBandE + st->channels*st->mode->nbEBands; + oldLogE2 = oldLogE + st->channels*st->mode->nbEBands; + OPUS_CLEAR((char*)&st->ENCODER_RESET_START, + opus_custom_encoder_get_size(st->mode, st->channels)- + ((char*)&st->ENCODER_RESET_START - (char*)st)); + for (i=0;i<st->channels*st->mode->nbEBands;i++) + oldLogE[i]=oldLogE2[i]=-QCONST16(28.f,DB_SHIFT); + st->vbr_offset = 0; + st->delayedIntra = 1; + st->spread_decision = SPREAD_NORMAL; + st->tonal_average = 256; + st->hf_average = 0; + st->tapset_decision = 0; + } + break; +#ifdef CUSTOM_MODES + case CELT_SET_INPUT_CLIPPING_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->clip = value; + } + break; +#endif + case CELT_SET_SIGNALLING_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->signalling = value; + } + break; + case CELT_SET_ANALYSIS_REQUEST: + { + AnalysisInfo *info = va_arg(ap, AnalysisInfo *); + if (info) + OPUS_COPY(&st->analysis, info, 1); + } + 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 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_LFE_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->lfe = value; + } + break; + case OPUS_SET_ENERGY_MASK_REQUEST: + { + opus_val16 *value = va_arg(ap, opus_val16*); + st->energy_mask = value; + } + 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/thirdparty/opus/celt/celt_lpc.c b/thirdparty/opus/celt/celt_lpc.c new file mode 100644 index 0000000000..f02145af0d --- /dev/null +++ b/thirdparty/opus/celt/celt_lpc.c @@ -0,0 +1,315 @@ +/* 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[LPC_ORDER]; +#else + float *lpc = _lpc; +#endif + + for (i = 0; i < p; i++) + lpc[i] = 0; + if (ac[0] != 0) + { + for (i = 0; i < p; i++) { + /* Sum up this iteration's reflection coefficient */ + opus_val32 rr = 0; + for (j = 0; j < i; j++) + rr += MULT32_32_Q31(lpc[j],ac[i - j]); + rr += SHR32(ac[i + 1],3); + r = -frac_div32(SHL32(rr,3), error); + /* Update LPC coefficients and total error */ + lpc[i] = SHR32(r,3); + 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 + for (i=0;i<p;i++) + _lpc[i] = ROUND16(lpc[i],16); +#endif +} + + +void celt_fir_c( + const opus_val16 *_x, + const opus_val16 *num, + opus_val16 *_y, + int N, + int ord, + opus_val16 *mem, + int arch) +{ + int i,j; + VARDECL(opus_val16, rnum); + VARDECL(opus_val16, x); + SAVE_STACK; + + ALLOC(rnum, ord, opus_val16); + ALLOC(x, N+ord, opus_val16); + for(i=0;i<ord;i++) + rnum[i] = num[ord-i-1]; + for(i=0;i<ord;i++) + x[i] = mem[ord-i-1]; + for (i=0;i<N;i++) + x[i+ord]=_x[i]; + for(i=0;i<ord;i++) + mem[i] = _x[N-i-1]; +#ifdef SMALL_FOOTPRINT + (void)arch; + for (i=0;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]); + } + _y[i] = SATURATE16(PSHR32(sum, SIG_SHIFT)); + } +#else + for (i=0;i<N-3;i+=4) + { + opus_val32 sum[4]={0,0,0,0}; + xcorr_kernel(rnum, x+i, sum, ord, arch); + _y[i ] = SATURATE16(ADD32(EXTEND32(_x[i ]), PSHR32(sum[0], SIG_SHIFT))); + _y[i+1] = SATURATE16(ADD32(EXTEND32(_x[i+1]), PSHR32(sum[1], SIG_SHIFT))); + _y[i+2] = SATURATE16(ADD32(EXTEND32(_x[i+2]), PSHR32(sum[2], SIG_SHIFT))); + _y[i+3] = SATURATE16(ADD32(EXTEND32(_x[i+3]), PSHR32(sum[3], SIG_SHIFT))); + } + for (;i<N;i++) + { + opus_val32 sum = 0; + for (j=0;j<ord;j++) + sum = MAC16_16(sum,rnum[j],x[i+j]); + _y[i] = SATURATE16(ADD32(EXTEND32(_x[i]), PSHR32(sum, SIG_SHIFT))); + } +#endif + 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] = ROUND16(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]; + xcorr_kernel(rden, y+i, sum, ord, arch); + + /* Patch up the result to compensate for the fact that this is an IIR */ + y[i+ord ] = -ROUND16(sum[0],SIG_SHIFT); + _y[i ] = sum[0]; + sum[1] = MAC16_16(sum[1], y[i+ord ], den[0]); + y[i+ord+1] = -ROUND16(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] = -ROUND16(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] = -ROUND16(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] = ROUND16(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 opus_val16 *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++) + { + xx[i] = MULT16_16_Q15(x[i],window[i]); + xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]); + } + xptr = xx; + } + shift=0; +#ifdef FIXED_POINT + { + opus_val32 ac0; + ac0 = 1+(n<<7); + if (n&1) ac0 += SHR32(MULT16_16(xptr[0],xptr[0]),9); + for(i=(n&1);i<n;i+=2) + { + ac0 += SHR32(MULT16_16(xptr[i],xptr[i]),9); + ac0 += SHR32(MULT16_16(xptr[i+1],xptr[i+1]),9); + } + + shift = celt_ilog2(ac0)-30+10; + 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/thirdparty/opus/celt/celt_lpc.h b/thirdparty/opus/celt/celt_lpc.h new file mode 100644 index 0000000000..323459eb1a --- /dev/null +++ b/thirdparty/opus/celt/celt_lpc.h @@ -0,0 +1,67 @@ +/* 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 PLC_H +#define PLC_H + +#include "arch.h" +#include "cpu_support.h" + +#if defined(OPUS_X86_MAY_HAVE_SSE4_1) +#include "x86/celt_lpc_sse.h" +#endif + +#define 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, + opus_val16 *mem, + int arch); + +#if !defined(OVERRIDE_CELT_FIR) +#define celt_fir(x, num, y, N, ord, mem, arch) \ + (celt_fir_c(x, num, y, N, ord, mem, 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 opus_val16 *window, int overlap, int lag, int n, int arch); + +#endif /* PLC_H */ diff --git a/thirdparty/opus/celt/cpu_support.h b/thirdparty/opus/celt/cpu_support.h new file mode 100644 index 0000000000..68fc60678f --- /dev/null +++ b/thirdparty/opus/celt/cpu_support.h @@ -0,0 +1,70 @@ +/* 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 4 ARM variants: + * arch[0] -> ARMv4 + * arch[1] -> ARMv5E + * arch[2] -> ARMv6 + * arch[3] -> NEON + */ +#define OPUS_ARCHMASK 3 + +#elif (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_AVX) && !defined(OPUS_X86_PRESUME_AVX)) + +#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/thirdparty/opus/celt/cwrs.c b/thirdparty/opus/celt/cwrs.c new file mode 100644 index 0000000000..2fa9f89cd6 --- /dev/null +++ b/thirdparty/opus/celt/cwrs.c @@ -0,0 +1,715 @@ +/* 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" + +#ifdef 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 + http://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(CUSTOM_MODES) +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(CUSTOM_MODES) + /*...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(CUSTOM_MODES) + /*...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(CUSTOM_MODES) + /*...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(CUSTOM_MODES) + /*...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(CUSTOM_MODES) + /*...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(CUSTOM_MODES) + /*...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(CUSTOM_MODES) + /*...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(CUSTOM_MODES) + /*...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(CUSTOM_MODES) + /*...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(CUSTOM_MODES) + /*...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(CUSTOM_MODES) + /*...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(CUSTOM_MODES) +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_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; +} + +#ifdef 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/thirdparty/opus/celt/cwrs.h b/thirdparty/opus/celt/cwrs.h new file mode 100644 index 0000000000..7cd4717459 --- /dev/null +++ b/thirdparty/opus/celt/cwrs.h @@ -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/thirdparty/opus/celt/ecintrin.h b/thirdparty/opus/celt/ecintrin.h new file mode 100644 index 0000000000..2263cff6bd --- /dev/null +++ b/thirdparty/opus/celt/ecintrin.h @@ -0,0 +1,87 @@ +/* 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) +# include <intrin.h> +/*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/thirdparty/opus/celt/entcode.c b/thirdparty/opus/celt/entcode.c new file mode 100644 index 0000000000..70f32016ec --- /dev/null +++ b/thirdparty/opus/celt/entcode.c @@ -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/thirdparty/opus/celt/entcode.h b/thirdparty/opus/celt/entcode.h new file mode 100644 index 0000000000..13d6c84ef0 --- /dev/null +++ b/thirdparty/opus/celt/entcode.h @@ -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 oustanding 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_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_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/thirdparty/opus/celt/entdec.c b/thirdparty/opus/celt/entdec.c new file mode 100644 index 0000000000..0b3433ed8b --- /dev/null +++ b/thirdparty/opus/celt/entdec.c @@ -0,0 +1,245 @@ +/* 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; +} + +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/thirdparty/opus/celt/entdec.h b/thirdparty/opus/celt/entdec.h new file mode 100644 index 0000000000..d8ab318730 --- /dev/null +++ b/thirdparty/opus/celt/entdec.h @@ -0,0 +1,100 @@ +/* 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); + +/*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 one, 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/thirdparty/opus/celt/entenc.c b/thirdparty/opus/celt/entenc.c new file mode 100644 index 0000000000..f1750d25b8 --- /dev/null +++ b/thirdparty/opus/celt/entenc.c @@ -0,0 +1,294 @@ +/* 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_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){ + 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/thirdparty/opus/celt/entenc.h b/thirdparty/opus/celt/entenc.h new file mode 100644 index 0000000000..796bc4d572 --- /dev/null +++ b/thirdparty/opus/celt/entenc.h @@ -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(_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 discernable 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 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 one, 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 reamining 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/thirdparty/opus/celt/fixed_debug.h b/thirdparty/opus/celt/fixed_debug.h new file mode 100644 index 0000000000..d28227f5dc --- /dev/null +++ b/thirdparty/opus/celt/fixed_debug.h @@ -0,0 +1,784 @@ +/* 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_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)) + +/** 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_val32)1)<<(bits)))) + +#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) + +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) +{ + int 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 = 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", a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = a<<shift; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "SHL32: output is not int: %lld<<%d = %lld in %s: line %d\n", a, shift, 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 ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a)))) +#define HALF16(x) (SHR16(x,1)) +#define HALF32(x) (SHR32(x,1)) + +//#define SHR(a,shift) ((a) >> (shift)) +//#define SHL(a,shift) ((a) << (shift)) + +#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", a, 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", 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", a, 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", a, 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", a, b, 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; +} + +#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_val32)(1)<<(15+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)<<(15+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", celt_mips);} while (0); + +#endif diff --git a/thirdparty/opus/celt/fixed_generic.h b/thirdparty/opus/celt/fixed_generic.h new file mode 100644 index 0000000000..ac67d37ce8 --- /dev/null +++ b/thirdparty/opus/celt/fixed_generic.h @@ -0,0 +1,151 @@ +/* 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 */ +#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR((b),16)), SHR(MULT16_16SU((a),((b)&0x0000ffff)),16)) + +/** 16x32 multiplication, followed by a 16-bit shift right (round-to-nearest). Results fits in 32 bits */ +#define MULT16_32_P16(a,b) ADD32(MULT16_16((a),SHR((b),16)), PSHR(MULT16_16SU((a),((b)&0x0000ffff)),16)) + +/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */ +#define MULT16_32_Q15(a,b) ADD32(SHL(MULT16_16((a),SHR((b),16)),1), SHR(MULT16_16SU((a),((b)&0x0000ffff)),15)) + +/** 32x32 multiplication, followed by a 31-bit shift right. Results fits in 32 bits */ +#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)) + +/** 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_val32)1)<<(bits)))) + +/** 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))) + +/** "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-neareast 32-bit value. Result is a 16-bit value */ +#define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a)))) +/** 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)) + +/** 16x16 multiplication where the result fits in 16 bits */ +#define MULT16_16_16(a,b) ((((opus_val16)(a))*((opus_val16)(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(MIPSr1_ASM) +#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/thirdparty/opus/celt/float_cast.h b/thirdparty/opus/celt/float_cast.h new file mode 100644 index 0000000000..ed5a39b543 --- /dev/null +++ b/thirdparty/opus/celt/float_cast.h @@ -0,0 +1,140 @@ +/* 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. +*/ + +#if (HAVE_LRINTF) + +/* 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)) + +#define _ISOC9X_SOURCE 1 +#define _ISOC99_SOURCE 1 + +#define __USE_ISOC9X 1 +#define __USE_ISOC99 1 + +#include <math.h> +#define float2int(x) lrint(x) + +#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && defined (_M_X64) + #include <xmmintrin.h> + + __inline long int float2int(float value) + { + 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. + */ + + __inline long int + float2int (float flt) + { int intgr; + + _asm + { fld flt + fistp intgr + } ; + + return intgr ; + } + +#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); +} +#endif /* DISABLE_FLOAT_API */ + +#endif /* FLOAT_CAST_H */ diff --git a/thirdparty/opus/celt/kiss_fft.c b/thirdparty/opus/celt/kiss_fft.c new file mode 100644 index 0000000000..4ed37d2bb7 --- /dev/null +++ b/thirdparty/opus/celt/kiss_fft.c @@ -0,0 +1,604 @@ +/*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" + +/* The guts header contains all the multiplication and addition macros that are defined for + complex numbers. It also delares 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 + { + opus_val16 tw; + tw = QCONST16(0.7071067812f, 15); + /* 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(Fout2[1].r+Fout2[1].i, tw); + t.i = S_MUL(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 = -Fout2[2].r; + C_SUB( Fout2[2] , Fout[2] , t ); + C_ADDTO( Fout[2] , t ); + + t.r = S_MUL(Fout2[3].i-Fout2[3].r, tw); + t.i = S_MUL(-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 = scratch0.r + scratch1.i; + Fout[1].i = scratch0.i - scratch1.r; + Fout[3].r = scratch0.r - scratch1.i; + Fout[3].i = 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 = scratch[5].r + scratch[4].i; + Fout[m].i = scratch[5].i - scratch[4].r; + Fout[m3].r = scratch[5].r - scratch[4].i; + Fout[m3].i = 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; + epi3.i = -28378; +#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 = Fout->r - HALF_OF(scratch[3].r); + Fout[m].i = Fout->i - HALF_OF(scratch[3].i); + + C_MULBYSCALAR( scratch[0] , epi3.i ); + + C_ADDTO(*Fout,scratch[3]); + + Fout[m2].r = Fout[m].r + scratch[0].i; + Fout[m2].i = Fout[m].i - scratch[0].r; + + Fout[m].r -= scratch[0].i; + 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 = 10126; + ya.i = -31164; + yb.r = -26510; + yb.i = -19261; +#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 += scratch[7].r + scratch[8].r; + Fout0->i += scratch[7].i + scratch[8].i; + + scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r); + scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r); + + scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i); + scratch[6].i = -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 = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r); + scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r); + scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i); + scratch[12].i = 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; + kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft)); + } +#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); + if (st->nfft == 1<<st->scale_shift) + st->scale = Q15ONE; + else + st->scale = (1073741824+st->nfft/2)/st->nfft>>(15-st->scale_shift); +#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 */ + +void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout) +{ + 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: + kf_bfly2(fout, m, fstride[i]); + break; + case 4: + kf_bfly4(fout,fstride[i]<<shift,st,m, fstride[i], m2); + break; + #ifndef RADIX_TWO_ONLY + case 3: + kf_bfly3(fout,fstride[i]<<shift,st,m, fstride[i], m2); + break; + case 5: + kf_bfly5(fout,fstride[i]<<shift,st,m, fstride[i], m2); + break; + #endif + } + m = m2; + } +} + +void opus_fft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) +{ + int i; + opus_val16 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 = SHR32(MULT16_32_Q16(scale, x.r), scale_shift); + fout[st->bitrev[i]].i = SHR32(MULT16_32_Q16(scale, x.i), scale_shift); + } + opus_fft_impl(st, fout); +} + + +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); + for (i=0;i<st->nfft;i++) + fout[i].i = -fout[i].i; +} diff --git a/thirdparty/opus/celt/kiss_fft.h b/thirdparty/opus/celt/kiss_fft.h new file mode 100644 index 0000000000..bffa2bfad6 --- /dev/null +++ b/thirdparty/opus/celt/kiss_fft.h @@ -0,0 +1,200 @@ +/*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 __cplusplus +extern "C" { +#endif + +#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 +# define kiss_twiddle_scalar opus_int16 + + +#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 + +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; + +#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; + opus_val16 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); +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) */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/opus/celt/laplace.c b/thirdparty/opus/celt/laplace.c new file mode 100644 index 0000000000..a7bca874b6 --- /dev/null +++ b/thirdparty/opus/celt/laplace.c @@ -0,0 +1,134 @@ +/* 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; +} diff --git a/thirdparty/opus/celt/laplace.h b/thirdparty/opus/celt/laplace.h new file mode 100644 index 0000000000..46c14b5da5 --- /dev/null +++ b/thirdparty/opus/celt/laplace.h @@ -0,0 +1,48 @@ +/* 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. +*/ + +#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); diff --git a/thirdparty/opus/celt/mathops.c b/thirdparty/opus/celt/mathops.c new file mode 100644 index 0000000000..3f8c5dcc0e --- /dev/null +++ b/thirdparty/opus/celt/mathops.c @@ -0,0 +1,208 @@ +/* Copyright (c) 2002-2008 Jean-Marc Valin + Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + 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 "mathops.h" + +/*Compute floor(sqrt(_val)) with exact arithmetic. + This has been tested on all possible 32-bit inputs.*/ +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(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)); + 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)))); +} + +/** Sqrt approximation (QX input, QX/2 output) */ +opus_val32 celt_sqrt(opus_val32 x) +{ + int k; + opus_val16 n; + opus_val32 rt; + static const opus_val16 C[5] = {23175, 11561, -3011, 1699, -664}; + 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 = 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]))))))))); + rt = VSHR32(rt,7-k); + return rt; +} + +#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 NEG32(_celt_cos_pi_2(EXTRACT16(65536-x))); + } + } else { + if (x&0x0000ffff) + return 0; + else if (x&0x0001ffff) + return -32767; + else + return 32767; + } +} + +/** Reciprocal approximation (Q15 input, Q16 output) */ +opus_val32 celt_rcp(opus_val32 x) +{ + int i; + opus_val16 n; + opus_val16 r; + celt_assert2(x>0, "celt_rcp() only defined for positive values"); + i = celt_ilog2(x); + /* n is Q15 with range [0,1). */ + n = VSHR32(x,i-15)-32768; + /* 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, n)); + /* Perform two Newton iterations: + r -= r*((r*n)-1.Q15) + = r*((r*n)+(r-1.Q15)). */ + r = SUB16(r, MULT16_16_Q15(r, + ADD16(MULT16_16_Q15(r, n), 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. */ + r = SUB16(r, ADD16(1, MULT16_16_Q15(r, + ADD16(MULT16_16_Q15(r, n), ADD16(r, -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 diff --git a/thirdparty/opus/celt/mathops.h b/thirdparty/opus/celt/mathops.h new file mode 100644 index 0000000000..a0525a9610 --- /dev/null +++ b/thirdparty/opus/celt/mathops.h @@ -0,0 +1,258 @@ +/* Copyright (c) 2002-2008 Jean-Marc Valin + Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + 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. +*/ + +#ifndef MATHOPS_H +#define MATHOPS_H + +#include "arch.h" +#include "entcode.h" +#include "os_support.h" + +/* 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); + +#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 + +#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 + +#define PI 3.141592653f +#define celt_sqrt(x) ((float)sqrt(x)) +#define celt_rsqrt(x) (1.f/celt_sqrt(x)) +#define celt_rsqrt_norm(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)) + +#ifdef FLOAT_APPROX + +/* Note: This assumes radix-2 floating point with the exponent at bits 23..30 and an offset of 127 + denorm, +/- inf and NaN are *not* handled */ + +/** Base-2 log approximation (log2(x)). */ +static OPUS_INLINE float celt_log2(float x) +{ + int integer; + float frac; + union { + float f; + opus_uint32 i; + } in; + in.f = x; + integer = (in.i>>23)-127; + in.i -= integer<<23; + frac = in.f - 1.5f; + frac = -0.41445418f + frac*(0.95909232f + + frac*(-0.33951290f + frac*0.16541097f)); + return 1+integer+frac; +} + +/** Base-2 exponential approximation (2^x). */ +static OPUS_INLINE float celt_exp2(float x) +{ + int integer; + float frac; + union { + float f; + opus_uint32 i; + } res; + integer = floor(x); + if (integer < -50) + return 0; + frac = x-integer; + /* K0 = 1, K1 = log(2), K2 = 3-4*log(2), K3 = 3*log(2) - 2 */ + res.f = 0.99992522f + frac * (0.69583354f + + frac * (0.22606716f + 0.078024523f*frac)); + res.i = (res.i + (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 + +#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_assert2(x>0, "celt_ilog2() only defined for strictly positive numbers"); + 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_sqrt(opus_val32 x); + +opus_val16 celt_cos_norm(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-DB_SHIFT)), 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 SHL16(i-13,DB_SHIFT)+SHR16(frac,14-DB_SHIFT); +} + +/* + 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)))))); +} +/** 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); +} + +opus_val32 celt_rcp(opus_val32 x); + +#define celt_div(a,b) MULT32_32_Q31((opus_val32)(a),celt_rcp(b)) + +opus_val32 frac_div32(opus_val32 a, opus_val32 b); + +#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 (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 */ +#endif /* MATHOPS_H */ diff --git a/thirdparty/opus/celt/mdct.c b/thirdparty/opus/celt/mdct.c new file mode 100644 index 0000000000..5315ad11a3 --- /dev/null +++ b/thirdparty/opus/celt/mdct.c @@ -0,0 +1,343 @@ +/* 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(MIPSr1_ASM) +#include "mips/mdct_mipsr1.h" +#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) +#if 1 + 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(-32767,MIN32(32767,floor(.5+32768*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 opus_val16 *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; + opus_val16 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 + 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 opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1); + const opus_val16 * 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++ = MULT16_32_Q15(*wp2, xp1[N2]) + MULT16_32_Q15(*wp1,*xp2); + *yp++ = MULT16_32_Q15(*wp1, *xp1) - MULT16_32_Q15(*wp2, xp2[-N2]); + 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++ = -MULT16_32_Q15(*wp1, xp1[-N2]) + MULT16_32_Q15(*wp2, *xp2); + *yp++ = MULT16_32_Q15(*wp2, *xp1) + MULT16_32_Q15(*wp1, xp2[N2]); + xp1+=2; + xp2-=2; + wp1+=2; + wp2-=2; + } + } + /* Pre-rotation */ + { + kiss_fft_scalar * OPUS_RESTRICT yp = f; + const kiss_twiddle_scalar *t = &trig[0]; + 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); + yc.r = yr; + yc.i = yi; + yc.r = PSHR32(MULT16_32_Q16(scale, yc.r), scale_shift); + yc.i = PSHR32(MULT16_32_Q16(scale, yc.i), scale_shift); + f2[st->bitrev[i]] = yc; + } + } + + /* N/4 complex FFT, does not downscale anymore */ + opus_fft_impl(st, f2); + + /* 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; + yr = S_MUL(fp->i,t[N4+i]) - S_MUL(fp->r,t[i]); + yi = S_MUL(fp->r,t[N4+i]) + S_MUL(fp->i,t[i]); + *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 opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride, int arch) +{ + int i; + int N, N2, N4; + const kiss_twiddle_scalar *trig; + (void) arch; + + N = l->n; + trig = l->trig; + for (i=0;i<shift;i++) + { + N >>= 1; + trig += N; + } + N2 = N>>1; + N4 = N>>2; + + /* 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; + rev = *bitrev++; + yr = S_MUL(*xp2, t[i]) + S_MUL(*xp1, t[N4+i]); + yi = S_MUL(*xp1, t[i]) - S_MUL(*xp2, 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))); + + /* 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 = S_MUL(re,t0) + S_MUL(im,t1); + yi = S_MUL(re,t1) - S_MUL(im,t0); + /* 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 = S_MUL(re,t0) + S_MUL(im,t1); + yi = S_MUL(re,t1) - S_MUL(im,t0); + 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 opus_val16 * OPUS_RESTRICT wp1 = window; + const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1; + + for(i = 0; i < overlap/2; i++) + { + kiss_fft_scalar x1, x2; + x1 = *xp1; + x2 = *yp1; + *yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1); + *xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1); + wp1++; + wp2--; + } + } +} +#endif /* OVERRIDE_clt_mdct_backward */ diff --git a/thirdparty/opus/celt/mdct.h b/thirdparty/opus/celt/mdct.h new file mode 100644 index 0000000000..160ae4e0f3 --- /dev/null +++ b/thirdparty/opus/celt/mdct.h @@ -0,0 +1,112 @@ +/* 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 opus_val16 *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 opus_val16 * 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 opus_val16 *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 opus_val16 *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/thirdparty/opus/celt/mfrngcod.h b/thirdparty/opus/celt/mfrngcod.h new file mode 100644 index 0000000000..809152a59a --- /dev/null +++ b/thirdparty/opus/celt/mfrngcod.h @@ -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/thirdparty/opus/celt/mips/celt_mipsr1.h b/thirdparty/opus/celt/mips/celt_mipsr1.h new file mode 100644 index 0000000000..e85661a661 --- /dev/null +++ b/thirdparty/opus/celt/mips/celt_mipsr1.h @@ -0,0 +1,151 @@ +/* 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. +*/ + +#ifndef __CELT_MIPSR1_H__ +#define __CELT_MIPSR1_H__ + +#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" + +#define 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 opus_val16 *window, int overlap, int arch) +{ + int i; + opus_val32 x0, x1, x2, x3, x4; + + (void)arch; + + /* printf ("%d %d %f %f\n", T0, T1, g0, g1); */ + opus_val16 g00, g01, g02, g10, g11, g12; + 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)}}; + + 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; + } + + g00 = MULT16_16_P15(g0, gains[tapset0][0]); + g01 = MULT16_16_P15(g0, gains[tapset0][1]); + g02 = MULT16_16_P15(g0, gains[tapset0][2]); + g10 = MULT16_16_P15(g1, gains[tapset1][0]); + g11 = MULT16_16_P15(g1, gains[tapset1][1]); + g12 = MULT16_16_P15(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++) + { + opus_val16 f; + opus_val32 res; + f = MULT16_16_Q15(window[i],window[i]); + x0= x[i-T1+2]; + + asm volatile("MULT $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15((Q15ONE-f),g00)), "r" ((int)x[i-T0])); + + asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15((Q15ONE-f),g01)), "r" ((int)ADD32(x[i-T0-1],x[i-T0+1]))); + asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15((Q15ONE-f),g02)), "r" ((int)ADD32(x[i-T0-2],x[i-T0+2]))); + asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15(f,g10)), "r" ((int)x2)); + asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15(f,g11)), "r" ((int)ADD32(x3,x1))); + asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15(f,g12)), "r" ((int)ADD32(x4,x0))); + + asm volatile("EXTR.W %0,$ac1, %1" : "=r" (res): "i" (15)); + + y[i] = x[i] + res; + + x4=x3; + x3=x2; + x2=x1; + x1=x0; + } + + x4 = x[i-T1-2]; + x3 = x[i-T1-1]; + x2 = x[i-T1]; + x1 = x[i-T1+1]; + + 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; + } + + for (i=overlap;i<N;i++) + { + opus_val32 res; + x0=x[i-T1+2]; + + asm volatile("MULT $ac1, %0, %1" : : "r" ((int)g10), "r" ((int)x2)); + + asm volatile("MADD $ac1, %0, %1" : : "r" ((int)g11), "r" ((int)ADD32(x3,x1))); + asm volatile("MADD $ac1, %0, %1" : : "r" ((int)g12), "r" ((int)ADD32(x4,x0))); + asm volatile("EXTR.W %0,$ac1, %1" : "=r" (res): "i" (15)); + y[i] = x[i] + res; + x4=x3; + x3=x2; + x2=x1; + x1=x0; + } +} + +#endif /* __CELT_MIPSR1_H__ */ diff --git a/drivers/opus/celt/mips/fixed_generic_mipsr1.h b/thirdparty/opus/celt/mips/fixed_generic_mipsr1.h index 4a05efbf85..4a05efbf85 100644 --- a/drivers/opus/celt/mips/fixed_generic_mipsr1.h +++ b/thirdparty/opus/celt/mips/fixed_generic_mipsr1.h diff --git a/thirdparty/opus/celt/mips/kiss_fft_mipsr1.h b/thirdparty/opus/celt/mips/kiss_fft_mipsr1.h new file mode 100644 index 0000000000..400ca4de9c --- /dev/null +++ b/thirdparty/opus/celt/mips/kiss_fft_mipsr1.h @@ -0,0 +1,167 @@ +/*Copyright (c) 2013, Xiph.Org Foundation and contributors. + + 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_MIPSR1_H +#define KISS_FFT_MIPSR1_H + +#if !defined(KISS_FFT_GUTS_H) +#error "This file should only be included from _kiss_fft_guts.h" +#endif + +#ifdef FIXED_POINT + +#define S_MUL_ADD(a, b, c, d) (S_MUL(a,b)+S_MUL(c,d)) +#define S_MUL_SUB(a, b, c, d) (S_MUL(a,b)-S_MUL(c,d)) + +#undef S_MUL_ADD +static inline int S_MUL_ADD(int a, int b, int c, int d) { + int m; + asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a), "r" ((int)b)); + asm volatile("madd $ac1, %0, %1" : : "r" ((int)c), "r" ((int)d)); + asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m): "i" (15)); + return m; +} + +#undef S_MUL_SUB +static inline int S_MUL_SUB(int a, int b, int c, int d) { + int m; + asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a), "r" ((int)b)); + asm volatile("msub $ac1, %0, %1" : : "r" ((int)c), "r" ((int)d)); + asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m): "i" (15)); + return m; +} + +#undef C_MUL +# define C_MUL(m,a,b) (m=C_MUL_fun(a,b)) +static inline kiss_fft_cpx C_MUL_fun(kiss_fft_cpx a, kiss_twiddle_cpx b) { + kiss_fft_cpx m; + + asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a.r), "r" ((int)b.r)); + asm volatile("msub $ac1, %0, %1" : : "r" ((int)a.i), "r" ((int)b.i)); + asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m.r): "i" (15)); + asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a.r), "r" ((int)b.i)); + asm volatile("madd $ac1, %0, %1" : : "r" ((int)a.i), "r" ((int)b.r)); + asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m.i): "i" (15)); + + return m; +} +#undef C_MULC +# define C_MULC(m,a,b) (m=C_MULC_fun(a,b)) +static inline kiss_fft_cpx C_MULC_fun(kiss_fft_cpx a, kiss_twiddle_cpx b) { + kiss_fft_cpx m; + + asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a.r), "r" ((int)b.r)); + asm volatile("madd $ac1, %0, %1" : : "r" ((int)a.i), "r" ((int)b.i)); + asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m.r): "i" (15)); + asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a.i), "r" ((int)b.r)); + asm volatile("msub $ac1, %0, %1" : : "r" ((int)a.r), "r" ((int)b.i)); + asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m.i): "i" (15)); + + return m; +} + +#endif /* FIXED_POINT */ + +#define 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 = 10126; + ya.i = -31164; + yb.r = -26510; + yb.i = -19261; +#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 += scratch[7].r + scratch[8].r; + Fout0->i += scratch[7].i + scratch[8].i; + scratch[5].r = scratch[0].r + S_MUL_ADD(scratch[7].r,ya.r,scratch[8].r,yb.r); + scratch[5].i = scratch[0].i + S_MUL_ADD(scratch[7].i,ya.r,scratch[8].i,yb.r); + + scratch[6].r = S_MUL_ADD(scratch[10].i,ya.i,scratch[9].i,yb.i); + scratch[6].i = -S_MUL_ADD(scratch[10].r,ya.i,scratch[9].r,yb.i); + + C_SUB(*Fout1,scratch[5],scratch[6]); + C_ADD(*Fout4,scratch[5],scratch[6]); + + scratch[11].r = scratch[0].r + S_MUL_ADD(scratch[7].r,yb.r,scratch[8].r,ya.r); + scratch[11].i = scratch[0].i + S_MUL_ADD(scratch[7].i,yb.r,scratch[8].i,ya.r); + + scratch[12].r = S_MUL_SUB(scratch[9].i,ya.i,scratch[10].i,yb.i); + scratch[12].i = S_MUL_SUB(scratch[10].r,yb.i,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 /* KISS_FFT_MIPSR1_H */ diff --git a/thirdparty/opus/celt/mips/mdct_mipsr1.h b/thirdparty/opus/celt/mips/mdct_mipsr1.h new file mode 100644 index 0000000000..2934dab776 --- /dev/null +++ b/thirdparty/opus/celt/mips/mdct_mipsr1.h @@ -0,0 +1,288 @@ +/* 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_MIPSR1_H__ +#define __MDCT_MIPSR1_H__ + +#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" + +/* Forward MDCT trashes the input array */ +#define OVERRIDE_clt_mdct_forward +void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out, + const opus_val16 *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; + opus_val16 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 + + (void)arch; + + SAVE_STACK; + 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 opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1); + const opus_val16 * 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_ADD(*wp2, xp1[N2],*wp1,*xp2); + *yp++ = S_MUL_SUB(*wp1, *xp1,*wp2, xp2[-N2]); + 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_SUB(*wp2, *xp2, *wp1, xp1[-N2]); + *yp++ = S_MUL_ADD(*wp2, *xp1, *wp1, xp2[N2]); + xp1+=2; + xp2-=2; + wp1+=2; + wp2-=2; + } + } + /* Pre-rotation */ + { + kiss_fft_scalar * OPUS_RESTRICT yp = f; + const kiss_twiddle_scalar *t = &trig[0]; + 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_SUB(re,t0,im,t1); + yi = S_MUL_ADD(im,t0,re,t1); + + yc.r = yr; + yc.i = yi; + yc.r = PSHR32(MULT16_32_Q16(scale, yc.r), scale_shift); + yc.i = PSHR32(MULT16_32_Q16(scale, yc.i), scale_shift); + f2[st->bitrev[i]] = yc; + } + } + + /* N/4 complex FFT, does not downscale anymore */ + opus_fft_impl(st, f2); + + /* 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; + yr = S_MUL_SUB(fp->i,t[N4+i] , fp->r,t[i]); + yi = S_MUL_ADD(fp->r,t[N4+i] ,fp->i,t[i]); + *yp1 = yr; + *yp2 = yi; + fp++; + yp1 += 2*stride; + yp2 -= 2*stride; + } + } + RESTORE_STACK; +} + +#define OVERRIDE_clt_mdct_backward +void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out, + const opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride, int arch) +{ + int i; + int N, N2, N4; + const kiss_twiddle_scalar *trig; + + (void)arch; + + N = l->n; + trig = l->trig; + for (i=0;i<shift;i++) + { + N >>= 1; + trig += N; + } + N2 = N>>1; + N4 = N>>2; + + /* 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; + rev = *bitrev++; + yr = S_MUL_ADD(*xp2, t[i] , *xp1, t[N4+i]); + yi = S_MUL_SUB(*xp1, t[i] , *xp2, 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))); + + /* Post-rotate and de-shuffle from both ends of the buffer at once to make + it in-place. */ + { + kiss_fft_scalar * OPUS_RESTRICT yp0 = out+(overlap>>1); + kiss_fft_scalar * OPUS_RESTRICT 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 = S_MUL_ADD(re,t0 , im,t1); + yi = S_MUL_SUB(re,t1 , im,t0); + /* 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 = S_MUL_ADD(re,t0,im,t1); + yi = S_MUL_SUB(re,t1,im,t0); + 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 opus_val16 * OPUS_RESTRICT wp1 = window; + const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1; + + for(i = 0; i < overlap/2; i++) + { + kiss_fft_scalar x1, x2; + x1 = *xp1; + x2 = *yp1; + *yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1); + *xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1); + wp1++; + wp2--; + } + } +} +#endif /* __MDCT_MIPSR1_H__ */ diff --git a/drivers/opus/celt/mips/pitch_mipsr1.h b/thirdparty/opus/celt/mips/pitch_mipsr1.h index a9500aff58..a9500aff58 100644 --- a/drivers/opus/celt/mips/pitch_mipsr1.h +++ b/thirdparty/opus/celt/mips/pitch_mipsr1.h diff --git a/thirdparty/opus/celt/mips/vq_mipsr1.h b/thirdparty/opus/celt/mips/vq_mipsr1.h new file mode 100644 index 0000000000..54cef86133 --- /dev/null +++ b/thirdparty/opus/celt/mips/vq_mipsr1.h @@ -0,0 +1,125 @@ +/* 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 __VQ_MIPSR1_H__ +#define __VQ_MIPSR1_H__ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "mathops.h" +#include "arch.h" + +static unsigned extract_collapse_mask(int *iy, int N, int B); +static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X, int N, opus_val32 Ryy, opus_val16 gain); +static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread); +static void renormalise_vector_mips(celt_norm *X, int N, opus_val16 gain, int arch); + +#define 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); + 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)); + } +} + +#define OVERRIDE_renormalise_vector + +#define renormalise_vector(X, N, gain, arch) \ + (renormalise_vector_mips(X, N, gain, arch)) + +void renormalise_vector_mips(celt_norm *X, int N, opus_val16 gain, int arch) +{ + int i; +#ifdef FIXED_POINT + int k; +#endif + opus_val32 E = EPSILON; + opus_val16 g; + opus_val32 t; + celt_norm *xptr = X; + int X0, X1; + + (void)arch; + + asm volatile("mult $ac1, $0, $0"); + asm volatile("MTLO %0, $ac1" : :"r" (E)); + /*if(N %4) + printf("error");*/ + for (i=0;i<N-2;i+=2) + { + X0 = (int)*xptr++; + asm volatile("MADD $ac1, %0, %1" : : "r" (X0), "r" (X0)); + + X1 = (int)*xptr++; + asm volatile("MADD $ac1, %0, %1" : : "r" (X1), "r" (X1)); + } + + for (;i<N;i++) + { + X0 = (int)*xptr++; + asm volatile("MADD $ac1, %0, %1" : : "r" (X0), "r" (X0)); + } + + asm volatile("MFLO %0, $ac1" : "=r" (E)); +#ifdef FIXED_POINT + k = celt_ilog2(E)>>1; +#endif + t = VSHR32(E, 2*(k-7)); + g = MULT16_16_P15(celt_rsqrt_norm(t),gain); + + xptr = X; + for (i=0;i<N;i++) + { + *xptr = EXTRACT16(PSHR32(MULT16_16(g, *xptr), k+1)); + xptr++; + } + /*return celt_sqrt(E);*/ +} + +#endif /* __VQ_MIPSR1_H__ */ diff --git a/thirdparty/opus/celt/modes.c b/thirdparty/opus/celt/modes.c new file mode 100644 index 0000000000..911686e905 --- /dev/null +++ b/thirdparty/opus/celt/modes.c @@ -0,0 +1,442 @@ +/* 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.141592653 +#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) + 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; + opus_val16 *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; + } + if (frame_size < 40 || frame_size > 1024 || frame_size%2!=0) + { + 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. */ + 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 = (opus_val16*)opus_alloc(mode->overlap*sizeof(opus_val16)); + 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 + 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 + 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); + + 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 */ +} + +#ifdef CUSTOM_MODES +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 */ + opus_free((opus_int16*)mode->eBands); + opus_free((opus_int16*)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); +} +#endif diff --git a/thirdparty/opus/celt/modes.h b/thirdparty/opus/celt/modes.h new file mode 100644 index 0000000000..be813ccc8b --- /dev/null +++ b/thirdparty/opus/celt/modes.h @@ -0,0 +1,75 @@ +/* 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 + +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 opus_val16 *window; + mdct_lookup mdct; + PulseCache cache; +}; + + +#endif diff --git a/thirdparty/opus/celt/opus_custom_demo.c b/thirdparty/opus/celt/opus_custom_demo.c new file mode 100644 index 0000000000..ae41c0de5a --- /dev/null +++ b/thirdparty/opus/celt/opus_custom_demo.c @@ -0,0 +1,210 @@ +/* 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 "opus_custom.h" +#include "arch.h" +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> + +#define MAX_PACKET 1275 + +int main(int argc, char *argv[]) +{ + int err; + char *inFile, *outFile; + FILE *fin, *fout; + OpusCustomMode *mode=NULL; + OpusCustomEncoder *enc; + OpusCustomDecoder *dec; + int len; + opus_int32 frame_size, channels, rate; + int bytes_per_packet; + unsigned char data[MAX_PACKET]; + int complexity; +#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH) + int i; + double rmsd = 0; +#endif + int count = 0; + opus_int32 skip; + opus_int16 *in, *out; + if (argc != 9 && argc != 8 && argc != 7) + { + fprintf (stderr, "Usage: test_opus_custom <rate> <channels> <frame size> " + " <bytes per packet> [<complexity> [packet loss rate]] " + "<input> <output>\n"); + return 1; + } + + rate = (opus_int32)atol(argv[1]); + channels = atoi(argv[2]); + frame_size = atoi(argv[3]); + mode = opus_custom_mode_create(rate, frame_size, NULL); + if (mode == NULL) + { + fprintf(stderr, "failed to create a mode\n"); + return 1; + } + + bytes_per_packet = atoi(argv[4]); + if (bytes_per_packet < 0 || bytes_per_packet > MAX_PACKET) + { + fprintf (stderr, "bytes per packet must be between 0 and %d\n", + MAX_PACKET); + return 1; + } + + inFile = argv[argc-2]; + fin = fopen(inFile, "rb"); + if (!fin) + { + fprintf (stderr, "Could not open input file %s\n", argv[argc-2]); + return 1; + } + outFile = argv[argc-1]; + fout = fopen(outFile, "wb+"); + if (!fout) + { + fprintf (stderr, "Could not open output file %s\n", argv[argc-1]); + fclose(fin); + return 1; + } + + enc = opus_custom_encoder_create(mode, channels, &err); + if (err != 0) + { + fprintf(stderr, "Failed to create the encoder: %s\n", opus_strerror(err)); + fclose(fin); + fclose(fout); + return 1; + } + dec = opus_custom_decoder_create(mode, channels, &err); + if (err != 0) + { + fprintf(stderr, "Failed to create the decoder: %s\n", opus_strerror(err)); + fclose(fin); + fclose(fout); + return 1; + } + opus_custom_decoder_ctl(dec, OPUS_GET_LOOKAHEAD(&skip)); + + if (argc>7) + { + complexity=atoi(argv[5]); + opus_custom_encoder_ctl(enc,OPUS_SET_COMPLEXITY(complexity)); + } + + in = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16)); + out = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16)); + + while (!feof(fin)) + { + int ret; + err = fread(in, sizeof(short), frame_size*channels, fin); + if (feof(fin)) + break; + len = opus_custom_encode(enc, in, frame_size, data, bytes_per_packet); + if (len <= 0) + fprintf (stderr, "opus_custom_encode() failed: %s\n", opus_strerror(len)); + + /* This is for simulating bit errors */ +#if 0 + int errors = 0; + int eid = 0; + /* This simulates random bit error */ + for (i=0;i<len*8;i++) + { + if (rand()%atoi(argv[8])==0) + { + if (i<64) + { + errors++; + eid = i; + } + data[i/8] ^= 1<<(7-(i%8)); + } + } + if (errors == 1) + data[eid/8] ^= 1<<(7-(eid%8)); + else if (errors%2 == 1) + data[rand()%8] ^= 1<<rand()%8; +#endif + +#if 1 /* Set to zero to use the encoder's output instead */ + /* This is to simulate packet loss */ + if (argc==9 && rand()%1000<atoi(argv[argc-3])) + /*if (errors && (errors%2==0))*/ + ret = opus_custom_decode(dec, NULL, len, out, frame_size); + else + ret = opus_custom_decode(dec, data, len, out, frame_size); + if (ret < 0) + fprintf(stderr, "opus_custom_decode() failed: %s\n", opus_strerror(ret)); +#else + for (i=0;i<ret*channels;i++) + out[i] = in[i]; +#endif +#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH) + for (i=0;i<ret*channels;i++) + { + rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]); + /*out[i] -= in[i];*/ + } +#endif + count++; + fwrite(out+skip*channels, sizeof(short), (ret-skip)*channels, fout); + skip = 0; + } + PRINT_MIPS(stderr); + + opus_custom_encoder_destroy(enc); + opus_custom_decoder_destroy(dec); + fclose(fin); + fclose(fout); + opus_custom_mode_destroy(mode); + free(in); + free(out); +#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH) + if (rmsd > 0) + { + rmsd = sqrt(rmsd/(1.0*frame_size*channels*count)); + fprintf (stderr, "Error: encoder doesn't match decoder\n"); + fprintf (stderr, "RMS mismatch is %f\n", rmsd); + return 1; + } else { + fprintf (stderr, "Encoder matches decoder!!\n"); + } +#endif + return 0; +} + diff --git a/thirdparty/opus/celt/os_support.h b/thirdparty/opus/celt/os_support.h new file mode 100644 index 0000000000..a2171971e9 --- /dev/null +++ b/thirdparty/opus/celt/os_support.h @@ -0,0 +1,92 @@ +/* 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 <stdio.h> +#include <stdlib.h> + +/** Opus wrapper for malloc(). To do your own dynamic allocation, all you need to do is replace this function and opus_free */ +#ifndef OVERRIDE_OPUS_ALLOC +static OPUS_INLINE void *opus_alloc (size_t size) +{ + return malloc(size); +} +#endif + +/** Same as celt_alloc(), except that the area is only needed inside a CELT call (might cause problem with wideband though) */ +#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, all you need to do is replace this function and opus_alloc */ +#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/thirdparty/opus/celt/pitch.c b/thirdparty/opus/celt/pitch.c new file mode 100644 index 0000000000..1d89cb0342 --- /dev/null +++ b/thirdparty/opus/celt/pitch.c @@ -0,0 +1,544 @@ +/* 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(const opus_val16 *x, + const opus_val16 *num, + opus_val16 *y, + int N, + opus_val16 *mem) +{ + 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=mem[0]; + mem1=mem[1]; + mem2=mem[2]; + mem3=mem[3]; + mem4=mem[4]; + 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]; + y[i] = ROUND16(sum, SIG_SHIFT); + } + mem[0]=mem0; + mem[1]=mem1; + mem[2]=mem2; + mem[3]=mem3; + mem[4]=mem4; +} + + +void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp, + int len, int C, int arch) +{ + int i; + opus_val32 ac[5]; + opus_val16 tmp=Q15ONE; + opus_val16 lpc[4], mem[5]={0,0,0,0,0}; + opus_val16 lpc2[5]; + opus_val16 c1 = QCONST16(.8f,15); +#ifdef FIXED_POINT + int shift; + opus_val32 maxabs = celt_maxabs32(x[0], len); + if (C==2) + { + opus_val32 maxabs_1 = celt_maxabs32(x[1], len); + maxabs = MAX32(maxabs, maxabs_1); + } + if (maxabs<1) + maxabs=1; + shift = celt_ilog2(maxabs)-10; + if (shift<0) + shift=0; + if (C==2) + shift++; +#endif + for (i=1;i<len>>1;i++) + x_lp[i] = SHR32(HALF32(HALF32(x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]), shift); + x_lp[0] = SHR32(HALF32(HALF32(x[0][1])+x[0][0]), shift); + if (C==2) + { + for (i=1;i<len>>1;i++) + x_lp[i] += SHR32(HALF32(HALF32(x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i]), shift); + x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), shift); + } + + _celt_autocorr(x_lp, ac, NULL, 0, + 4, len>>1, 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, x_lp, len>>1, mem); +} + +/* Pure C implementation. */ +#ifdef FIXED_POINT +opus_val32 +#else +void +#endif +#if defined(OVERRIDE_PITCH_XCORR) +celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y, + opus_val32 *xcorr, int len, int max_pitch) +#else +celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y, + opus_val32 *xcorr, int len, int max_pitch, int arch) +#endif +{ + +#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_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0); + for (i=0;i<max_pitch-3;i+=4) + { + opus_val32 sum[4]={0,0,0,0}; +#if defined(OVERRIDE_PITCH_XCORR) + xcorr_kernel_c(_x, _y+i, sum, len); +#else + xcorr_kernel(_x, _y+i, sum, len, arch); +#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; +#if defined(OVERRIDE_PITCH_XCORR) + sum = celt_inner_prod_c(_x, _y+i, len); +#else + sum = celt_inner_prod(_x, _y+i, len, arch); +#endif + 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)))-11; + 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_c(x_lp, y+i, len>>1); +#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; +} + +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; +#ifdef FIXED_POINT + { + opus_val32 x2y2; + int sh, t; + x2y2 = 1+HALF32(MULT32_32_Q31(xx,yy)); + sh = celt_ilog2(x2y2)>>1; + t = VSHR32(x2y2, 2*(sh-7)); + g = g0 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1); + } +#else + g = g0 = xy/celt_sqrt(1+xx*yy); +#endif + /* 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 += xy2; + yy = yy_lookup[T1] + yy_lookup[T1b]; +#ifdef FIXED_POINT + { + opus_val32 x2y2; + int sh, t; + x2y2 = 1+MULT32_32_Q31(xx,yy); + sh = celt_ilog2(x2y2)>>1; + t = VSHR32(x2y2, 2*(sh-7)); + g1 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1); + } +#else + g1 = xy/celt_sqrt(1+2.f*xx*1.f*yy); +#endif + if (abs(T1-prev_period)<=1) + cont = prev_gain; + else if (abs(T1-prev_period)<=2 && 5*k*k < T0) + cont = HALF32(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/thirdparty/opus/celt/pitch.h b/thirdparty/opus/celt/pitch.h new file mode 100644 index 0000000000..65a77a6ecc --- /dev/null +++ b/thirdparty/opus/celt/pitch.h @@ -0,0 +1,220 @@ +/* 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(MIPSr1_ASM) +#include "mips/pitch_mipsr1.h" +#endif + +#if ((defined(OPUS_ARM_ASM) && defined(FIXED_POINT)) \ + || 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 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); + +#if !defined(OVERRIDE_PITCH_XCORR) +/*Is run-time CPU detection enabled on this platform?*/ +# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_ASM) \ + || (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) \ + && !defined(OPUS_ARM_PRESUME_NEON_INTR))) +extern +# if defined(FIXED_POINT) +opus_val32 +# else +void +# endif +(*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *, + const opus_val16 *, opus_val32 *, int, int); + +# define OVERRIDE_PITCH_XCORR +# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \ + ((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \ + xcorr, len, max_pitch)) +# else + +#ifdef FIXED_POINT +opus_val32 +#else +void +#endif +celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y, + opus_val32 *xcorr, int len, int max_pitch, int arch); + +# endif +#endif + +#endif diff --git a/thirdparty/opus/celt/quant_bands.c b/thirdparty/opus/celt/quant_bands.c new file mode 100644 index 0000000000..95076e0af2 --- /dev/null +++ b/thirdparty/opus/celt/quant_bands.c @@ -0,0 +1,556 @@ +/* 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 opus_val16 *eBands, opus_val16 *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++) + { + opus_val16 d = SUB16(SHR16(eBands[i+c*len], 3), SHR16(oldEBands[i+c*len], 3)); + dist = MAC16_16(dist, d,d); + } + } while (++c<C); + return MIN32(200,SHR32(dist,2*DB_SHIFT-6)); +} + +static int quant_coarse_energy_impl(const CELTMode *m, int start, int end, + const opus_val16 *eBands, opus_val16 *oldEBands, + opus_int32 budget, opus_int32 tell, + const unsigned char *prob_model, opus_val16 *error, ec_enc *enc, + int C, int LM, int intra, opus_val16 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; + opus_val16 x; + opus_val32 f, tmp; + opus_val16 oldE; + opus_val16 decay_bound; + x = eBands[i+c*m->nbEBands]; + oldE = MAX16(-QCONST16(9.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]); +#ifdef FIXED_POINT + f = SHL32(EXTEND32(x),7) - PSHR32(MULT16_16(coef,oldE), 8) - prev[c]; + /* Rounding to nearest integer here is really important! */ + qi = (f+QCONST32(.5f,DB_SHIFT+7))>>(DB_SHIFT+7); + decay_bound = EXTRACT16(MAX32(-QCONST16(28.f,DB_SHIFT), + 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 = MAX16(-QCONST16(28.f,DB_SHIFT), 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)SHR16(SUB16(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] = PSHR32(f,7) - SHL16(qi,DB_SHIFT); + badness += abs(qi0-qi); + q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT); + + tmp = PSHR32(MULT16_16(coef,oldE),8) + prev[c] + SHL32(q,7); +#ifdef FIXED_POINT + tmp = MAX32(-QCONST32(28.f, DB_SHIFT+7), tmp); +#endif + oldEBands[i+c*m->nbEBands] = PSHR32(tmp, 7); + prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8)); + } while (++c < C); + } + return lfe ? 0 : badness; +} + +void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd, + const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget, + opus_val16 *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; + opus_val16 max_decay; + VARDECL(opus_val16, oldEBands_intra); + VARDECL(opus_val16, 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 = QCONST16(16.f,DB_SHIFT); + if (end-start>10) + { +#ifdef FIXED_POINT + max_decay = MIN32(max_decay, SHL32(EXTEND32(nbAvailableBytes),DB_SHIFT-3)); +#else + max_decay = MIN32(max_decay, .125f*nbAvailableBytes); +#endif + } + if (lfe) + max_decay = QCONST16(3.f,DB_SHIFT); + enc_start_state = *enc; + + ALLOC(oldEBands_intra, C*m->nbEBands, opus_val16); + ALLOC(error_intra, C*m->nbEBands, opus_val16); + 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, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, ec_enc *enc, int C) +{ + int i, c; + + /* Encode finer resolution */ + for (i=start;i<end;i++) + { + opus_int16 frac = 1<<fine_quant[i]; + if (fine_quant[i] <= 0) + continue; + c=0; + do { + int q2; + opus_val16 offset; +#ifdef FIXED_POINT + /* Has to be without rounding */ + q2 = (error[i+c*m->nbEBands]+QCONST16(.5f,DB_SHIFT))>>(DB_SHIFT-fine_quant[i]); +#else + q2 = (int)floor((error[i+c*m->nbEBands]+.5f)*frac); +#endif + if (q2 > frac-1) + q2 = frac-1; + if (q2<0) + q2 = 0; + ec_enc_bits(enc, q2, fine_quant[i]); +#ifdef FIXED_POINT + offset = SUB16(SHR32(SHL32(EXTEND32(q2),DB_SHIFT)+QCONST16(.5f,DB_SHIFT),fine_quant[i]),QCONST16(.5f,DB_SHIFT)); +#else + offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f; +#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, opus_val16 *oldEBands, opus_val16 *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; + opus_val16 offset; + q2 = error[i+c*m->nbEBands]<0 ? 0 : 1; + ec_enc_bits(enc, q2, 1); +#ifdef FIXED_POINT + offset = SHR16(SHL16(q2,DB_SHIFT)-QCONST16(.5f,DB_SHIFT),fine_quant[i]+1); +#else + offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384); +#endif + oldEBands[i+c*m->nbEBands] += offset; + bits_left--; + } while (++c < C); + } + } +} + +void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM) +{ + const unsigned char *prob_model = e_prob_model[LM][intra]; + int i, c; + opus_val32 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_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] = MAX16(-QCONST16(9.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]); + tmp = PSHR32(MULT16_16(coef,oldEBands[i+c*m->nbEBands]),8) + prev[c] + SHL32(q,7); +#ifdef FIXED_POINT + tmp = MAX32(-QCONST32(28.f, DB_SHIFT+7), tmp); +#endif + oldEBands[i+c*m->nbEBands] = PSHR32(tmp, 7); + prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8)); + } while (++c < C); + } +} + +void unquant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, ec_dec *dec, int C) +{ + int i, c; + /* Decode finer resolution */ + for (i=start;i<end;i++) + { + if (fine_quant[i] <= 0) + continue; + c=0; + do { + int q2; + opus_val16 offset; + q2 = ec_dec_bits(dec, fine_quant[i]); +#ifdef FIXED_POINT + offset = SUB16(SHR32(SHL32(EXTEND32(q2),DB_SHIFT)+QCONST16(.5f,DB_SHIFT),fine_quant[i]),QCONST16(.5f,DB_SHIFT)); +#else + offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f; +#endif + oldEBands[i+c*m->nbEBands] += offset; + } while (++c < C); + } +} + +void unquant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *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; + opus_val16 offset; + q2 = ec_dec_bits(dec, 1); +#ifdef FIXED_POINT + offset = SHR16(SHL16(q2,DB_SHIFT)-QCONST16(.5f,DB_SHIFT),fine_quant[i]+1); +#else + offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384); +#endif + oldEBands[i+c*m->nbEBands] += offset; + bits_left--; + } while (++c < C); + } + } +} + +void amp2Log2(const CELTMode *m, int effEnd, int end, + celt_ener *bandE, opus_val16 *bandLogE, int C) +{ + int c, i; + c=0; + do { + for (i=0;i<effEnd;i++) + bandLogE[i+c*m->nbEBands] = + celt_log2(SHL32(bandE[i+c*m->nbEBands],2)) + - SHL16((opus_val16)eMeans[i],6); + for (i=effEnd;i<end;i++) + bandLogE[c*m->nbEBands+i] = -QCONST16(14.f,DB_SHIFT); + } while (++c < C); +} diff --git a/thirdparty/opus/celt/quant_bands.h b/thirdparty/opus/celt/quant_bands.h new file mode 100644 index 0000000000..0490bca4b4 --- /dev/null +++ b/thirdparty/opus/celt/quant_bands.h @@ -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, opus_val16 *bandLogE, int C); + +void log2Amp(const CELTMode *m, int start, int end, + celt_ener *eBands, const opus_val16 *oldEBands, int C); + +void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd, + const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget, + opus_val16 *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, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, ec_enc *enc, int C); + +void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *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, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM); + +void unquant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, ec_dec *dec, int C); + +void unquant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C); + +#endif /* QUANT_BANDS */ diff --git a/thirdparty/opus/celt/rate.c b/thirdparty/opus/celt/rate.c new file mode 100644 index 0000000000..b28d8feccd --- /dev/null +++ b/thirdparty/opus/celt/rate.c @@ -0,0 +1,639 @@ +/* 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" + +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 +}; + +#ifdef 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]+((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] + (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 cocentrated 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.*/ + /*Choose a threshold with some hysteresis to keep bands from + fluctuating in and out.*/ +#ifdef FUZZING + if ((rand()&0x1) == 0) +#else + if (codedBands<=start+2 || (band_bits > ((j<prev?7:9)*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 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; +} + diff --git a/thirdparty/opus/celt/rate.h b/thirdparty/opus/celt/rate.h new file mode 100644 index 0000000000..515f7687ce --- /dev/null +++ b/thirdparty/opus/celt/rate.h @@ -0,0 +1,101 @@ +/* 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 compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stero, + 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); + +#endif diff --git a/thirdparty/opus/celt/stack_alloc.h b/thirdparty/opus/celt/stack_alloc.h new file mode 100644 index 0000000000..2b51c8d80c --- /dev/null +++ b/thirdparty/opus/celt/stack_alloc.h @@ -0,0 +1,184 @@ +/* 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 */ + +#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),sizeof(type)/sizeof(char)),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=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)) +#define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)/sizeof(char)),(stack)+=(size)*(sizeof(type)/sizeof(char)),(type*)((stack)-(size)*(sizeof(type)/sizeof(char)))) +#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=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/thirdparty/opus/celt/static_modes_fixed.h b/thirdparty/opus/celt/static_modes_fixed.h new file mode 100644 index 0000000000..8717d626cb --- /dev/null +++ b/thirdparty/opus/celt/static_modes_fixed.h @@ -0,0 +1,892 @@ +/* The contents of this file was automatically generated by dump_modes.c + with arguments: 48000 960 + 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 opus_val16 window120[120] = { +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 + +#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 + +#ifndef FFT_TWIDDLES48000_960 +#define FFT_TWIDDLES48000_960 +static const kiss_twiddle_cpx fft_twiddles48000_960[480] = { +{32767, 0}, {32766, -429}, +{32757, -858}, {32743, -1287}, +{32724, -1715}, {32698, -2143}, +{32667, -2570}, {32631, -2998}, +{32588, -3425}, {32541, -3851}, +{32488, -4277}, {32429, -4701}, +{32364, -5125}, {32295, -5548}, +{32219, -5971}, {32138, -6393}, +{32051, -6813}, {31960, -7231}, +{31863, -7650}, {31760, -8067}, +{31652, -8481}, {31539, -8895}, +{31419, -9306}, {31294, -9716}, +{31165, -10126}, {31030, -10532}, +{30889, -10937}, {30743, -11340}, +{30592, -11741}, {30436, -12141}, +{30274, -12540}, {30107, -12935}, +{29936, -13328}, {29758, -13718}, +{29577, -14107}, {29390, -14493}, +{29197, -14875}, {29000, -15257}, +{28797, -15635}, {28590, -16010}, +{28379, -16384}, {28162, -16753}, +{27940, -17119}, {27714, -17484}, +{27482, -17845}, {27246, -18205}, +{27006, -18560}, {26760, -18911}, +{26510, -19260}, {26257, -19606}, +{25997, -19947}, {25734, -20286}, +{25466, -20621}, {25194, -20952}, +{24918, -21281}, {24637, -21605}, +{24353, -21926}, {24063, -22242}, +{23770, -22555}, {23473, -22865}, +{23171, -23171}, {22866, -23472}, +{22557, -23769}, {22244, -24063}, +{21927, -24352}, {21606, -24636}, +{21282, -24917}, {20954, -25194}, +{20622, -25465}, {20288, -25733}, +{19949, -25997}, {19607, -26255}, +{19261, -26509}, {18914, -26760}, +{18561, -27004}, {18205, -27246}, +{17846, -27481}, {17485, -27713}, +{17122, -27940}, {16755, -28162}, +{16385, -28378}, {16012, -28590}, +{15636, -28797}, {15258, -28999}, +{14878, -29197}, {14494, -29389}, +{14108, -29576}, {13720, -29757}, +{13329, -29934}, {12937, -30107}, +{12540, -30274}, {12142, -30435}, +{11744, -30592}, {11342, -30743}, +{10939, -30889}, {10534, -31030}, +{10127, -31164}, {9718, -31294}, +{9307, -31418}, {8895, -31537}, +{8482, -31652}, {8067, -31759}, +{7650, -31862}, {7233, -31960}, +{6815, -32051}, {6393, -32138}, +{5973, -32219}, {5549, -32294}, +{5127, -32364}, {4703, -32429}, +{4278, -32487}, {3852, -32541}, +{3426, -32588}, {2999, -32630}, +{2572, -32667}, {2144, -32698}, +{1716, -32724}, {1287, -32742}, +{860, -32757}, {430, -32766}, +{0, -32767}, {-429, -32766}, +{-858, -32757}, {-1287, -32743}, +{-1715, -32724}, {-2143, -32698}, +{-2570, -32667}, {-2998, -32631}, +{-3425, -32588}, {-3851, -32541}, +{-4277, -32488}, {-4701, -32429}, +{-5125, -32364}, {-5548, -32295}, +{-5971, -32219}, {-6393, -32138}, +{-6813, -32051}, {-7231, -31960}, +{-7650, -31863}, {-8067, -31760}, +{-8481, -31652}, {-8895, -31539}, +{-9306, -31419}, {-9716, -31294}, +{-10126, -31165}, {-10532, -31030}, +{-10937, -30889}, {-11340, -30743}, +{-11741, -30592}, {-12141, -30436}, +{-12540, -30274}, {-12935, -30107}, +{-13328, -29936}, {-13718, -29758}, +{-14107, -29577}, {-14493, -29390}, +{-14875, -29197}, {-15257, -29000}, +{-15635, -28797}, {-16010, -28590}, +{-16384, -28379}, {-16753, -28162}, +{-17119, -27940}, {-17484, -27714}, +{-17845, -27482}, {-18205, -27246}, +{-18560, -27006}, {-18911, -26760}, +{-19260, -26510}, {-19606, -26257}, +{-19947, -25997}, {-20286, -25734}, +{-20621, -25466}, {-20952, -25194}, +{-21281, -24918}, {-21605, -24637}, +{-21926, -24353}, {-22242, -24063}, +{-22555, -23770}, {-22865, -23473}, +{-23171, -23171}, {-23472, -22866}, +{-23769, -22557}, {-24063, -22244}, +{-24352, -21927}, {-24636, -21606}, +{-24917, -21282}, {-25194, -20954}, +{-25465, -20622}, {-25733, -20288}, +{-25997, -19949}, {-26255, -19607}, +{-26509, -19261}, {-26760, -18914}, +{-27004, -18561}, {-27246, -18205}, +{-27481, -17846}, {-27713, -17485}, +{-27940, -17122}, {-28162, -16755}, +{-28378, -16385}, {-28590, -16012}, +{-28797, -15636}, {-28999, -15258}, +{-29197, -14878}, {-29389, -14494}, +{-29576, -14108}, {-29757, -13720}, +{-29934, -13329}, {-30107, -12937}, +{-30274, -12540}, {-30435, -12142}, +{-30592, -11744}, {-30743, -11342}, +{-30889, -10939}, {-31030, -10534}, +{-31164, -10127}, {-31294, -9718}, +{-31418, -9307}, {-31537, -8895}, +{-31652, -8482}, {-31759, -8067}, +{-31862, -7650}, {-31960, -7233}, +{-32051, -6815}, {-32138, -6393}, +{-32219, -5973}, {-32294, -5549}, +{-32364, -5127}, {-32429, -4703}, +{-32487, -4278}, {-32541, -3852}, +{-32588, -3426}, {-32630, -2999}, +{-32667, -2572}, {-32698, -2144}, +{-32724, -1716}, {-32742, -1287}, +{-32757, -860}, {-32766, -430}, +{-32767, 0}, {-32766, 429}, +{-32757, 858}, {-32743, 1287}, +{-32724, 1715}, {-32698, 2143}, +{-32667, 2570}, {-32631, 2998}, +{-32588, 3425}, {-32541, 3851}, +{-32488, 4277}, {-32429, 4701}, +{-32364, 5125}, {-32295, 5548}, +{-32219, 5971}, {-32138, 6393}, +{-32051, 6813}, {-31960, 7231}, +{-31863, 7650}, {-31760, 8067}, +{-31652, 8481}, {-31539, 8895}, +{-31419, 9306}, {-31294, 9716}, +{-31165, 10126}, {-31030, 10532}, +{-30889, 10937}, {-30743, 11340}, +{-30592, 11741}, {-30436, 12141}, +{-30274, 12540}, {-30107, 12935}, +{-29936, 13328}, {-29758, 13718}, +{-29577, 14107}, {-29390, 14493}, +{-29197, 14875}, {-29000, 15257}, +{-28797, 15635}, {-28590, 16010}, +{-28379, 16384}, {-28162, 16753}, +{-27940, 17119}, {-27714, 17484}, +{-27482, 17845}, {-27246, 18205}, +{-27006, 18560}, {-26760, 18911}, +{-26510, 19260}, {-26257, 19606}, +{-25997, 19947}, {-25734, 20286}, +{-25466, 20621}, {-25194, 20952}, +{-24918, 21281}, {-24637, 21605}, +{-24353, 21926}, {-24063, 22242}, +{-23770, 22555}, {-23473, 22865}, +{-23171, 23171}, {-22866, 23472}, +{-22557, 23769}, {-22244, 24063}, +{-21927, 24352}, {-21606, 24636}, +{-21282, 24917}, {-20954, 25194}, +{-20622, 25465}, {-20288, 25733}, +{-19949, 25997}, {-19607, 26255}, +{-19261, 26509}, {-18914, 26760}, +{-18561, 27004}, {-18205, 27246}, +{-17846, 27481}, {-17485, 27713}, +{-17122, 27940}, {-16755, 28162}, +{-16385, 28378}, {-16012, 28590}, +{-15636, 28797}, {-15258, 28999}, +{-14878, 29197}, {-14494, 29389}, +{-14108, 29576}, {-13720, 29757}, +{-13329, 29934}, {-12937, 30107}, +{-12540, 30274}, {-12142, 30435}, +{-11744, 30592}, {-11342, 30743}, +{-10939, 30889}, {-10534, 31030}, +{-10127, 31164}, {-9718, 31294}, +{-9307, 31418}, {-8895, 31537}, +{-8482, 31652}, {-8067, 31759}, +{-7650, 31862}, {-7233, 31960}, +{-6815, 32051}, {-6393, 32138}, +{-5973, 32219}, {-5549, 32294}, +{-5127, 32364}, {-4703, 32429}, +{-4278, 32487}, {-3852, 32541}, +{-3426, 32588}, {-2999, 32630}, +{-2572, 32667}, {-2144, 32698}, +{-1716, 32724}, {-1287, 32742}, +{-860, 32757}, {-430, 32766}, +{0, 32767}, {429, 32766}, +{858, 32757}, {1287, 32743}, +{1715, 32724}, {2143, 32698}, +{2570, 32667}, {2998, 32631}, +{3425, 32588}, {3851, 32541}, +{4277, 32488}, {4701, 32429}, +{5125, 32364}, {5548, 32295}, +{5971, 32219}, {6393, 32138}, +{6813, 32051}, {7231, 31960}, +{7650, 31863}, {8067, 31760}, +{8481, 31652}, {8895, 31539}, +{9306, 31419}, {9716, 31294}, +{10126, 31165}, {10532, 31030}, +{10937, 30889}, {11340, 30743}, +{11741, 30592}, {12141, 30436}, +{12540, 30274}, {12935, 30107}, +{13328, 29936}, {13718, 29758}, +{14107, 29577}, {14493, 29390}, +{14875, 29197}, {15257, 29000}, +{15635, 28797}, {16010, 28590}, +{16384, 28379}, {16753, 28162}, +{17119, 27940}, {17484, 27714}, +{17845, 27482}, {18205, 27246}, +{18560, 27006}, {18911, 26760}, +{19260, 26510}, {19606, 26257}, +{19947, 25997}, {20286, 25734}, +{20621, 25466}, {20952, 25194}, +{21281, 24918}, {21605, 24637}, +{21926, 24353}, {22242, 24063}, +{22555, 23770}, {22865, 23473}, +{23171, 23171}, {23472, 22866}, +{23769, 22557}, {24063, 22244}, +{24352, 21927}, {24636, 21606}, +{24917, 21282}, {25194, 20954}, +{25465, 20622}, {25733, 20288}, +{25997, 19949}, {26255, 19607}, +{26509, 19261}, {26760, 18914}, +{27004, 18561}, {27246, 18205}, +{27481, 17846}, {27713, 17485}, +{27940, 17122}, {28162, 16755}, +{28378, 16385}, {28590, 16012}, +{28797, 15636}, {28999, 15258}, +{29197, 14878}, {29389, 14494}, +{29576, 14108}, {29757, 13720}, +{29934, 13329}, {30107, 12937}, +{30274, 12540}, {30435, 12142}, +{30592, 11744}, {30743, 11342}, +{30889, 10939}, {31030, 10534}, +{31164, 10127}, {31294, 9718}, +{31418, 9307}, {31537, 8895}, +{31652, 8482}, {31759, 8067}, +{31862, 7650}, {31960, 7233}, +{32051, 6815}, {32138, 6393}, +{32219, 5973}, {32294, 5549}, +{32364, 5127}, {32429, 4703}, +{32487, 4278}, {32541, 3852}, +{32588, 3426}, {32630, 2999}, +{32667, 2572}, {32698, 2144}, +{32724, 1716}, {32742, 1287}, +{32757, 860}, {32766, 430}, +}; +#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 */ +17476, /* scale */ +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 */ +17476, /* scale */ +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 */ +17476, /* scale */ +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 */ +17476, /* scale */ +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 opus_val16 mdct_twiddles960[1800] = { +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 + +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 */ +}; + +/* List of all the available modes */ +#define TOTAL_MODES 1 +static const CELTMode * const static_mode_list[TOTAL_MODES] = { +&mode48000_960_120, +}; diff --git a/drivers/opus/celt/static_modes_fixed_arm_ne10.h b/thirdparty/opus/celt/static_modes_fixed_arm_ne10.h index b8ef0cee98..b8ef0cee98 100644 --- a/drivers/opus/celt/static_modes_fixed_arm_ne10.h +++ b/thirdparty/opus/celt/static_modes_fixed_arm_ne10.h diff --git a/thirdparty/opus/celt/static_modes_float.h b/thirdparty/opus/celt/static_modes_float.h new file mode 100644 index 0000000000..e102a38391 --- /dev/null +++ b/thirdparty/opus/celt/static_modes_float.h @@ -0,0 +1,888 @@ +/* The contents of this file was automatically generated by dump_modes.c + with arguments: 48000 960 + 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 opus_val16 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.75605424f, 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 + +#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.1230318e-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.2246064e-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.8369095e-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.002083333f, /* 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.004166667f, /* 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.008333333f, /* 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.016666667f, /* 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 opus_val16 mdct_twiddles960[1800] = { +0.99999994f, 0.99999321f, 0.99997580f, 0.99994773f, 0.99990886f, +0.99985933f, 0.99979913f, 0.99972820f, 0.99964654f, 0.99955416f, +0.99945110f, 0.99933738f, 0.99921292f, 0.99907774f, 0.99893188f, +0.99877530f, 0.99860805f, 0.99843007f, 0.99824142f, 0.99804211f, +0.99783206f, 0.99761140f, 0.99737996f, 0.99713790f, 0.99688518f, +0.99662173f, 0.99634761f, 0.99606287f, 0.99576741f, 0.99546129f, +0.99514455f, 0.99481714f, 0.99447906f, 0.99413031f, 0.99377096f, +0.99340093f, 0.99302030f, 0.99262899f, 0.99222708f, 0.99181455f, +0.99139136f, 0.99095762f, 0.99051321f, 0.99005818f, 0.98959261f, +0.98911643f, 0.98862964f, 0.98813224f, 0.98762429f, 0.98710573f, +0.98657662f, 0.98603696f, 0.98548669f, 0.98492593f, 0.98435456f, +0.98377270f, 0.98318028f, 0.98257732f, 0.98196387f, 0.98133987f, +0.98070538f, 0.98006040f, 0.97940493f, 0.97873890f, 0.97806245f, +0.97737551f, 0.97667813f, 0.97597027f, 0.97525197f, 0.97452319f, +0.97378403f, 0.97303438f, 0.97227436f, 0.97150391f, 0.97072303f, +0.96993178f, 0.96913016f, 0.96831810f, 0.96749574f, 0.96666300f, +0.96581990f, 0.96496642f, 0.96410263f, 0.96322852f, 0.96234411f, +0.96144938f, 0.96054435f, 0.95962906f, 0.95870346f, 0.95776761f, +0.95682150f, 0.95586514f, 0.95489854f, 0.95392174f, 0.95293468f, +0.95193744f, 0.95093000f, 0.94991243f, 0.94888461f, 0.94784665f, +0.94679856f, 0.94574034f, 0.94467193f, 0.94359344f, 0.94250488f, +0.94140619f, 0.94029742f, 0.93917859f, 0.93804967f, 0.93691075f, +0.93576175f, 0.93460274f, 0.93343377f, 0.93225473f, 0.93106574f, +0.92986679f, 0.92865789f, 0.92743903f, 0.92621022f, 0.92497152f, +0.92372292f, 0.92246443f, 0.92119598f, 0.91991776f, 0.91862965f, +0.91733170f, 0.91602397f, 0.91470635f, 0.91337901f, 0.91204184f, +0.91069490f, 0.90933824f, 0.90797186f, 0.90659571f, 0.90520984f, +0.90381432f, 0.90240908f, 0.90099424f, 0.89956969f, 0.89813554f, +0.89669174f, 0.89523834f, 0.89377540f, 0.89230281f, 0.89082074f, +0.88932908f, 0.88782793f, 0.88631725f, 0.88479710f, 0.88326746f, +0.88172835f, 0.88017982f, 0.87862182f, 0.87705445f, 0.87547767f, +0.87389153f, 0.87229604f, 0.87069118f, 0.86907703f, 0.86745358f, +0.86582077f, 0.86417878f, 0.86252749f, 0.86086690f, 0.85919720f, +0.85751826f, 0.85583007f, 0.85413277f, 0.85242635f, 0.85071075f, +0.84898609f, 0.84725231f, 0.84550947f, 0.84375757f, 0.84199661f, +0.84022665f, 0.83844769f, 0.83665979f, 0.83486289f, 0.83305705f, +0.83124226f, 0.82941860f, 0.82758605f, 0.82574469f, 0.82389444f, +0.82203537f, 0.82016748f, 0.81829083f, 0.81640542f, 0.81451124f, +0.81260836f, 0.81069672f, 0.80877650f, 0.80684757f, 0.80490994f, +0.80296379f, 0.80100900f, 0.79904562f, 0.79707366f, 0.79509324f, +0.79310423f, 0.79110676f, 0.78910083f, 0.78708643f, 0.78506362f, +0.78303236f, 0.78099275f, 0.77894479f, 0.77688843f, 0.77482378f, +0.77275085f, 0.77066964f, 0.76858020f, 0.76648247f, 0.76437658f, +0.76226246f, 0.76014024f, 0.75800985f, 0.75587130f, 0.75372469f, +0.75157005f, 0.74940729f, 0.74723655f, 0.74505776f, 0.74287105f, +0.74067634f, 0.73847371f, 0.73626316f, 0.73404479f, 0.73181850f, +0.72958434f, 0.72734243f, 0.72509271f, 0.72283524f, 0.72057003f, +0.71829706f, 0.71601641f, 0.71372813f, 0.71143216f, 0.70912862f, +0.70681745f, 0.70449871f, 0.70217246f, 0.69983864f, 0.69749737f, +0.69514859f, 0.69279242f, 0.69042879f, 0.68805778f, 0.68567938f, +0.68329364f, 0.68090063f, 0.67850029f, 0.67609268f, 0.67367786f, +0.67125577f, 0.66882652f, 0.66639012f, 0.66394657f, 0.66149592f, +0.65903819f, 0.65657341f, 0.65410155f, 0.65162271f, 0.64913690f, +0.64664418f, 0.64414448f, 0.64163786f, 0.63912445f, 0.63660413f, +0.63407701f, 0.63154310f, 0.62900239f, 0.62645501f, 0.62390089f, +0.62134010f, 0.61877263f, 0.61619854f, 0.61361790f, 0.61103064f, +0.60843682f, 0.60583651f, 0.60322970f, 0.60061646f, 0.59799677f, +0.59537065f, 0.59273821f, 0.59009939f, 0.58745426f, 0.58480281f, +0.58214509f, 0.57948118f, 0.57681108f, 0.57413477f, 0.57145232f, +0.56876373f, 0.56606907f, 0.56336832f, 0.56066155f, 0.55794877f, +0.55523002f, 0.55250537f, 0.54977477f, 0.54703826f, 0.54429591f, +0.54154772f, 0.53879374f, 0.53603399f, 0.53326851f, 0.53049731f, +0.52772039f, 0.52493787f, 0.52214974f, 0.51935595f, 0.51655668f, +0.51375180f, 0.51094145f, 0.50812566f, 0.50530440f, 0.50247771f, +0.49964568f, 0.49680826f, 0.49396557f, 0.49111754f, 0.48826426f, +0.48540577f, 0.48254207f, 0.47967321f, 0.47679919f, 0.47392011f, +0.47103590f, 0.46814668f, 0.46525243f, 0.46235323f, 0.45944905f, +0.45653993f, 0.45362595f, 0.45070711f, 0.44778344f, 0.44485497f, +0.44192174f, 0.43898380f, 0.43604112f, 0.43309379f, 0.43014181f, +0.42718524f, 0.42422408f, 0.42125839f, 0.41828820f, 0.41531351f, +0.41233435f, 0.40935081f, 0.40636289f, 0.40337059f, 0.40037400f, +0.39737311f, 0.39436796f, 0.39135858f, 0.38834500f, 0.38532731f, +0.38230544f, 0.37927949f, 0.37624949f, 0.37321547f, 0.37017745f, +0.36713544f, 0.36408952f, 0.36103970f, 0.35798600f, 0.35492846f, +0.35186714f, 0.34880206f, 0.34573323f, 0.34266070f, 0.33958447f, +0.33650464f, 0.33342120f, 0.33033419f, 0.32724363f, 0.32414958f, +0.32105204f, 0.31795108f, 0.31484672f, 0.31173897f, 0.30862790f, +0.30551350f, 0.30239585f, 0.29927495f, 0.29615086f, 0.29302359f, +0.28989318f, 0.28675964f, 0.28362307f, 0.28048345f, 0.27734083f, +0.27419522f, 0.27104670f, 0.26789525f, 0.26474094f, 0.26158381f, +0.25842386f, 0.25526115f, 0.25209570f, 0.24892756f, 0.24575676f, +0.24258332f, 0.23940729f, 0.23622867f, 0.23304754f, 0.22986393f, +0.22667783f, 0.22348931f, 0.22029841f, 0.21710514f, 0.21390954f, +0.21071166f, 0.20751151f, 0.20430915f, 0.20110460f, 0.19789790f, +0.19468907f, 0.19147816f, 0.18826519f, 0.18505022f, 0.18183327f, +0.17861435f, 0.17539354f, 0.17217083f, 0.16894630f, 0.16571994f, +0.16249183f, 0.15926196f, 0.15603039f, 0.15279715f, 0.14956227f, +0.14632578f, 0.14308774f, 0.13984816f, 0.13660708f, 0.13336454f, +0.13012058f, 0.12687522f, 0.12362850f, 0.12038045f, 0.11713112f, +0.11388054f, 0.11062872f, 0.10737573f, 0.10412160f, 0.10086634f, +0.097609997f, 0.094352618f, 0.091094226f, 0.087834857f, 0.084574550f, +0.081313334f, 0.078051247f, 0.074788325f, 0.071524605f, 0.068260118f, +0.064994894f, 0.061728980f, 0.058462404f, 0.055195201f, 0.051927410f, +0.048659060f, 0.045390189f, 0.042120833f, 0.038851023f, 0.035580799f, +0.032310195f, 0.029039243f, 0.025767982f, 0.022496443f, 0.019224664f, +0.015952680f, 0.012680525f, 0.0094082337f, 0.0061358409f, 0.0028633832f, +-0.00040910527f, -0.0036815894f, -0.0069540343f, -0.010226404f, -0.013498665f, +-0.016770782f, -0.020042717f, -0.023314439f, -0.026585912f, -0.029857099f, +-0.033127967f, -0.036398482f, -0.039668605f, -0.042938303f, -0.046207540f, +-0.049476285f, -0.052744497f, -0.056012146f, -0.059279196f, -0.062545612f, +-0.065811358f, -0.069076397f, -0.072340697f, -0.075604223f, -0.078866936f, +-0.082128808f, -0.085389800f, -0.088649876f, -0.091909006f, -0.095167145f, +-0.098424271f, -0.10168034f, -0.10493532f, -0.10818918f, -0.11144188f, +-0.11469338f, -0.11794366f, -0.12119267f, -0.12444039f, -0.12768677f, +-0.13093179f, -0.13417540f, -0.13741758f, -0.14065829f, -0.14389749f, +-0.14713514f, -0.15037122f, -0.15360570f, -0.15683852f, -0.16006967f, +-0.16329910f, -0.16652679f, -0.16975269f, -0.17297678f, -0.17619900f, +-0.17941935f, -0.18263777f, -0.18585424f, -0.18906870f, -0.19228116f, +-0.19549155f, -0.19869985f, -0.20190603f, -0.20511003f, -0.20831184f, +-0.21151142f, -0.21470875f, -0.21790376f, -0.22109644f, -0.22428675f, +-0.22747467f, -0.23066014f, -0.23384315f, -0.23702365f, -0.24020162f, +-0.24337701f, -0.24654980f, -0.24971995f, -0.25288740f, -0.25605217f, +-0.25921419f, -0.26237345f, -0.26552987f, -0.26868346f, -0.27183419f, +-0.27498198f, -0.27812684f, -0.28126872f, -0.28440759f, -0.28754342f, +-0.29067615f, -0.29380578f, -0.29693225f, -0.30005556f, -0.30317566f, +-0.30629250f, -0.30940607f, -0.31251630f, -0.31562322f, -0.31872672f, +-0.32182685f, -0.32492352f, -0.32801670f, -0.33110636f, -0.33419248f, +-0.33727503f, -0.34035397f, -0.34342924f, -0.34650084f, -0.34956875f, +-0.35263291f, -0.35569328f, -0.35874987f, -0.36180258f, -0.36485144f, +-0.36789638f, -0.37093741f, -0.37397444f, -0.37700745f, -0.38003644f, +-0.38306138f, -0.38608220f, -0.38909888f, -0.39211139f, -0.39511973f, +-0.39812380f, -0.40112361f, -0.40411916f, -0.40711036f, -0.41009718f, +-0.41307965f, -0.41605768f, -0.41903123f, -0.42200032f, -0.42496487f, +-0.42792490f, -0.43088034f, -0.43383113f, -0.43677729f, -0.43971881f, +-0.44265559f, -0.44558764f, -0.44851488f, -0.45143735f, -0.45435500f, +-0.45726776f, -0.46017563f, -0.46307856f, -0.46597654f, -0.46886954f, +-0.47175750f, -0.47464043f, -0.47751826f, -0.48039100f, -0.48325855f, +-0.48612097f, -0.48897815f, -0.49183011f, -0.49467680f, -0.49751821f, +-0.50035429f, -0.50318497f, -0.50601029f, -0.50883019f, -0.51164466f, +-0.51445359f, -0.51725709f, -0.52005500f, -0.52284735f, -0.52563411f, +-0.52841520f, -0.53119069f, -0.53396046f, -0.53672451f, -0.53948283f, +-0.54223537f, -0.54498214f, -0.54772300f, -0.55045801f, -0.55318713f, +-0.55591035f, -0.55862761f, -0.56133890f, -0.56404412f, -0.56674337f, +-0.56943649f, -0.57212353f, -0.57480448f, -0.57747924f, -0.58014780f, +-0.58281022f, -0.58546633f, -0.58811617f, -0.59075975f, -0.59339696f, +-0.59602785f, -0.59865236f, -0.60127044f, -0.60388207f, -0.60648727f, +-0.60908598f, -0.61167812f, -0.61426371f, -0.61684275f, -0.61941516f, +-0.62198097f, -0.62454009f, -0.62709254f, -0.62963831f, -0.63217729f, +-0.63470948f, -0.63723493f, -0.63975352f, -0.64226526f, -0.64477009f, +-0.64726806f, -0.64975911f, -0.65224314f, -0.65472025f, -0.65719032f, +-0.65965337f, -0.66210932f, -0.66455823f, -0.66700000f, -0.66943461f, +-0.67186207f, -0.67428231f, -0.67669535f, -0.67910111f, -0.68149966f, +-0.68389088f, -0.68627477f, -0.68865126f, -0.69102043f, -0.69338220f, +-0.69573659f, -0.69808346f, -0.70042288f, -0.70275480f, -0.70507920f, +-0.70739603f, -0.70970529f, -0.71200693f, -0.71430099f, -0.71658736f, +-0.71886611f, -0.72113711f, -0.72340041f, -0.72565591f, -0.72790372f, +-0.73014367f, -0.73237586f, -0.73460019f, -0.73681659f, -0.73902518f, +-0.74122584f, -0.74341851f, -0.74560326f, -0.74778003f, -0.74994880f, +-0.75210953f, -0.75426215f, -0.75640678f, -0.75854325f, -0.76067162f, +-0.76279181f, -0.76490390f, -0.76700771f, -0.76910341f, -0.77119076f, +-0.77326995f, -0.77534080f, -0.77740335f, -0.77945763f, -0.78150350f, +-0.78354102f, -0.78557014f, -0.78759086f, -0.78960317f, -0.79160696f, +-0.79360235f, -0.79558921f, -0.79756755f, -0.79953730f, -0.80149853f, +-0.80345118f, -0.80539525f, -0.80733067f, -0.80925739f, -0.81117553f, +-0.81308490f, -0.81498563f, -0.81687760f, -0.81876087f, -0.82063532f, +-0.82250100f, -0.82435787f, -0.82620591f, -0.82804507f, -0.82987541f, +-0.83169687f, -0.83350939f, -0.83531296f, -0.83710766f, -0.83889335f, +-0.84067005f, -0.84243774f, -0.84419644f, -0.84594607f, -0.84768665f, +-0.84941816f, -0.85114056f, -0.85285389f, -0.85455805f, -0.85625303f, +-0.85793889f, -0.85961550f, -0.86128294f, -0.86294121f, -0.86459017f, +-0.86622989f, -0.86786032f, -0.86948150f, -0.87109333f, -0.87269586f, +-0.87428904f, -0.87587279f, -0.87744725f, -0.87901229f, -0.88056785f, +-0.88211405f, -0.88365078f, -0.88517809f, -0.88669586f, -0.88820416f, +-0.88970292f, -0.89119220f, -0.89267188f, -0.89414203f, -0.89560264f, +-0.89705360f, -0.89849502f, -0.89992678f, -0.90134889f, -0.90276134f, +-0.90416414f, -0.90555727f, -0.90694070f, -0.90831441f, -0.90967834f, +-0.91103262f, -0.91237706f, -0.91371179f, -0.91503674f, -0.91635185f, +-0.91765714f, -0.91895264f, -0.92023826f, -0.92151409f, -0.92277998f, +-0.92403603f, -0.92528218f, -0.92651838f, -0.92774469f, -0.92896110f, +-0.93016750f, -0.93136400f, -0.93255049f, -0.93372697f, -0.93489349f, +-0.93604994f, -0.93719643f, -0.93833286f, -0.93945926f, -0.94057560f, +-0.94168180f, -0.94277799f, -0.94386405f, -0.94494003f, -0.94600588f, +-0.94706154f, -0.94810712f, -0.94914252f, -0.95016778f, -0.95118284f, +-0.95218778f, -0.95318246f, -0.95416695f, -0.95514119f, -0.95610523f, +-0.95705903f, -0.95800257f, -0.95893586f, -0.95985889f, -0.96077162f, +-0.96167403f, -0.96256620f, -0.96344805f, -0.96431959f, -0.96518075f, +-0.96603161f, -0.96687216f, -0.96770233f, -0.96852213f, -0.96933156f, +-0.97013056f, -0.97091925f, -0.97169751f, -0.97246534f, -0.97322279f, +-0.97396982f, -0.97470641f, -0.97543252f, -0.97614825f, -0.97685349f, +-0.97754824f, -0.97823256f, -0.97890645f, -0.97956979f, -0.98022264f, +-0.98086500f, -0.98149687f, -0.98211825f, -0.98272908f, -0.98332942f, +-0.98391914f, -0.98449844f, -0.98506713f, -0.98562527f, -0.98617285f, +-0.98670989f, -0.98723638f, -0.98775226f, -0.98825759f, -0.98875231f, +-0.98923647f, -0.98971003f, -0.99017298f, -0.99062532f, -0.99106705f, +-0.99149817f, -0.99191868f, -0.99232858f, -0.99272782f, -0.99311644f, +-0.99349445f, -0.99386179f, -0.99421853f, -0.99456459f, -0.99489999f, +-0.99522477f, -0.99553883f, -0.99584228f, -0.99613506f, -0.99641716f, +-0.99668860f, -0.99694937f, -0.99719942f, -0.99743885f, -0.99766755f, +-0.99788558f, -0.99809295f, -0.99828959f, -0.99847561f, -0.99865085f, +-0.99881548f, -0.99896932f, -0.99911255f, -0.99924499f, -0.99936682f, +-0.99947786f, -0.99957830f, -0.99966794f, -0.99974692f, -0.99981517f, +-0.99987274f, -0.99991959f, -0.99995571f, -0.99998116f, -0.99999589f, +0.99999964f, 0.99997288f, 0.99990326f, 0.99979085f, 0.99963558f, +0.99943751f, 0.99919659f, 0.99891287f, 0.99858636f, 0.99821711f, +0.99780506f, 0.99735034f, 0.99685282f, 0.99631262f, 0.99572974f, +0.99510419f, 0.99443603f, 0.99372530f, 0.99297196f, 0.99217612f, +0.99133772f, 0.99045694f, 0.98953366f, 0.98856801f, 0.98756003f, +0.98650974f, 0.98541719f, 0.98428243f, 0.98310548f, 0.98188645f, +0.98062533f, 0.97932225f, 0.97797716f, 0.97659022f, 0.97516143f, +0.97369087f, 0.97217858f, 0.97062469f, 0.96902919f, 0.96739221f, +0.96571374f, 0.96399397f, 0.96223283f, 0.96043050f, 0.95858705f, +0.95670253f, 0.95477700f, 0.95281059f, 0.95080340f, 0.94875544f, +0.94666684f, 0.94453770f, 0.94236809f, 0.94015813f, 0.93790787f, +0.93561745f, 0.93328691f, 0.93091643f, 0.92850608f, 0.92605597f, +0.92356616f, 0.92103678f, 0.91846794f, 0.91585976f, 0.91321236f, +0.91052586f, 0.90780038f, 0.90503591f, 0.90223277f, 0.89939094f, +0.89651060f, 0.89359182f, 0.89063478f, 0.88763964f, 0.88460642f, +0.88153529f, 0.87842643f, 0.87527996f, 0.87209594f, 0.86887461f, +0.86561602f, 0.86232042f, 0.85898781f, 0.85561842f, 0.85221243f, +0.84876984f, 0.84529096f, 0.84177583f, 0.83822471f, 0.83463764f, +0.83101481f, 0.82735640f, 0.82366252f, 0.81993335f, 0.81616908f, +0.81236988f, 0.80853581f, 0.80466717f, 0.80076402f, 0.79682660f, +0.79285502f, 0.78884947f, 0.78481019f, 0.78073722f, 0.77663082f, +0.77249116f, 0.76831841f, 0.76411277f, 0.75987434f, 0.75560343f, +0.75130010f, 0.74696463f, 0.74259710f, 0.73819780f, 0.73376691f, +0.72930455f, 0.72481096f, 0.72028631f, 0.71573079f, 0.71114463f, +0.70652801f, 0.70188117f, 0.69720417f, 0.69249737f, 0.68776089f, +0.68299496f, 0.67819971f, 0.67337549f, 0.66852236f, 0.66364062f, +0.65873051f, 0.65379208f, 0.64882571f, 0.64383155f, 0.63880974f, +0.63376063f, 0.62868434f, 0.62358117f, 0.61845124f, 0.61329484f, +0.60811216f, 0.60290343f, 0.59766883f, 0.59240872f, 0.58712316f, +0.58181250f, 0.57647687f, 0.57111657f, 0.56573176f, 0.56032276f, +0.55488980f, 0.54943299f, 0.54395270f, 0.53844911f, 0.53292239f, +0.52737290f, 0.52180082f, 0.51620632f, 0.51058978f, 0.50495136f, +0.49929130f, 0.49360985f, 0.48790723f, 0.48218375f, 0.47643960f, +0.47067502f, 0.46489030f, 0.45908567f, 0.45326138f, 0.44741765f, +0.44155475f, 0.43567297f, 0.42977250f, 0.42385364f, 0.41791660f, +0.41196167f, 0.40598908f, 0.39999911f, 0.39399201f, 0.38796803f, +0.38192743f, 0.37587047f, 0.36979741f, 0.36370850f, 0.35760403f, +0.35148421f, 0.34534934f, 0.33919969f, 0.33303553f, 0.32685706f, +0.32066461f, 0.31445843f, 0.30823877f, 0.30200592f, 0.29576012f, +0.28950164f, 0.28323078f, 0.27694780f, 0.27065292f, 0.26434645f, +0.25802869f, 0.25169984f, 0.24536023f, 0.23901010f, 0.23264973f, +0.22627939f, 0.21989937f, 0.21350993f, 0.20711134f, 0.20070387f, +0.19428782f, 0.18786344f, 0.18143101f, 0.17499080f, 0.16854310f, +0.16208819f, 0.15562633f, 0.14915779f, 0.14268288f, 0.13620184f, +0.12971498f, 0.12322257f, 0.11672486f, 0.11022217f, 0.10371475f, +0.097202882f, 0.090686858f, 0.084166944f, 0.077643424f, 0.071116582f, +0.064586692f, 0.058054037f, 0.051518895f, 0.044981543f, 0.038442269f, +0.031901345f, 0.025359053f, 0.018815678f, 0.012271495f, 0.0057267868f, +-0.00081816671f, -0.0073630852f, -0.013907688f, -0.020451695f, -0.026994826f, +-0.033536803f, -0.040077340f, -0.046616159f, -0.053152986f, -0.059687532f, +-0.066219524f, -0.072748676f, -0.079274714f, -0.085797355f, -0.092316322f, +-0.098831341f, -0.10534211f, -0.11184838f, -0.11834986f, -0.12484626f, +-0.13133731f, -0.13782275f, -0.14430228f, -0.15077563f, -0.15724251f, +-0.16370267f, -0.17015581f, -0.17660165f, -0.18303993f, -0.18947038f, +-0.19589271f, -0.20230664f, -0.20871192f, -0.21510825f, -0.22149536f, +-0.22787298f, -0.23424086f, -0.24059868f, -0.24694622f, -0.25328314f, +-0.25960925f, -0.26592422f, -0.27222782f, -0.27851975f, -0.28479972f, +-0.29106751f, -0.29732284f, -0.30356544f, -0.30979502f, -0.31601134f, +-0.32221413f, -0.32840309f, -0.33457801f, -0.34073856f, -0.34688455f, +-0.35301566f, -0.35913166f, -0.36523229f, -0.37131724f, -0.37738630f, +-0.38343921f, -0.38947567f, -0.39549544f, -0.40149832f, -0.40748394f, +-0.41345215f, -0.41940263f, -0.42533514f, -0.43124944f, -0.43714526f, +-0.44302234f, -0.44888046f, -0.45471936f, -0.46053877f, -0.46633846f, +-0.47211814f, -0.47787762f, -0.48361665f, -0.48933494f, -0.49503228f, +-0.50070840f, -0.50636309f, -0.51199609f, -0.51760709f, -0.52319598f, +-0.52876246f, -0.53430629f, -0.53982723f, -0.54532504f, -0.55079949f, +-0.55625033f, -0.56167740f, -0.56708032f, -0.57245898f, -0.57781315f, +-0.58314258f, -0.58844697f, -0.59372622f, -0.59897995f, -0.60420811f, +-0.60941035f, -0.61458647f, -0.61973625f, -0.62485951f, -0.62995601f, +-0.63502556f, -0.64006782f, -0.64508271f, -0.65007001f, -0.65502942f, +-0.65996075f, -0.66486382f, -0.66973841f, -0.67458433f, -0.67940134f, +-0.68418926f, -0.68894786f, -0.69367695f, -0.69837630f, -0.70304573f, +-0.70768511f, -0.71229410f, -0.71687263f, -0.72142041f, -0.72593731f, +-0.73042315f, -0.73487765f, -0.73930067f, -0.74369204f, -0.74805158f, +-0.75237900f, -0.75667429f, -0.76093709f, -0.76516730f, -0.76936477f, +-0.77352923f, -0.77766061f, -0.78175867f, -0.78582323f, -0.78985411f, +-0.79385114f, -0.79781419f, -0.80174309f, -0.80563760f, -0.80949765f, +-0.81332302f, -0.81711352f, -0.82086903f, -0.82458937f, -0.82827437f, +-0.83192390f, -0.83553779f, -0.83911592f, -0.84265804f, -0.84616417f, +-0.84963393f, -0.85306740f, -0.85646427f, -0.85982448f, -0.86314780f, +-0.86643422f, -0.86968350f, -0.87289548f, -0.87607014f, -0.87920725f, +-0.88230664f, -0.88536829f, -0.88839203f, -0.89137769f, -0.89432514f, +-0.89723432f, -0.90010506f, -0.90293723f, -0.90573072f, -0.90848541f, +-0.91120118f, -0.91387796f, -0.91651553f, -0.91911387f, -0.92167282f, +-0.92419231f, -0.92667222f, -0.92911243f, -0.93151283f, -0.93387336f, +-0.93619382f, -0.93847424f, -0.94071442f, -0.94291431f, -0.94507378f, +-0.94719279f, -0.94927126f, -0.95130903f, -0.95330608f, -0.95526224f, +-0.95717752f, -0.95905179f, -0.96088499f, -0.96267700f, -0.96442777f, +-0.96613729f, -0.96780539f, -0.96943200f, -0.97101706f, -0.97256058f, +-0.97406244f, -0.97552258f, -0.97694093f, -0.97831738f, -0.97965199f, +-0.98094457f, -0.98219514f, -0.98340368f, -0.98457009f, -0.98569429f, +-0.98677629f, -0.98781598f, -0.98881340f, -0.98976845f, -0.99068111f, +-0.99155134f, -0.99237907f, -0.99316430f, -0.99390697f, -0.99460709f, +-0.99526459f, -0.99587947f, -0.99645168f, -0.99698120f, -0.99746799f, +-0.99791211f, -0.99831343f, -0.99867201f, -0.99898779f, -0.99926084f, +-0.99949104f, -0.99967843f, -0.99982297f, -0.99992472f, -0.99998361f, +0.99999869f, 0.99989158f, 0.99961317f, 0.99916345f, 0.99854255f, +0.99775058f, 0.99678761f, 0.99565387f, 0.99434954f, 0.99287480f, +0.99122995f, 0.98941529f, 0.98743105f, 0.98527765f, 0.98295540f, +0.98046476f, 0.97780609f, 0.97497988f, 0.97198665f, 0.96882683f, +0.96550101f, 0.96200979f, 0.95835376f, 0.95453346f, 0.95054960f, +0.94640291f, 0.94209403f, 0.93762374f, 0.93299282f, 0.92820197f, +0.92325211f, 0.91814411f, 0.91287869f, 0.90745693f, 0.90187967f, +0.89614785f, 0.89026248f, 0.88422459f, 0.87803519f, 0.87169534f, +0.86520612f, 0.85856867f, 0.85178405f, 0.84485358f, 0.83777827f, +0.83055943f, 0.82319832f, 0.81569612f, 0.80805415f, 0.80027372f, +0.79235619f, 0.78430289f, 0.77611518f, 0.76779449f, 0.75934225f, +0.75075996f, 0.74204898f, 0.73321080f, 0.72424710f, 0.71515924f, +0.70594883f, 0.69661748f, 0.68716675f, 0.67759830f, 0.66791373f, +0.65811473f, 0.64820296f, 0.63818014f, 0.62804794f, 0.61780810f, +0.60746247f, 0.59701276f, 0.58646071f, 0.57580817f, 0.56505698f, +0.55420899f, 0.54326600f, 0.53222996f, 0.52110273f, 0.50988621f, +0.49858227f, 0.48719296f, 0.47572014f, 0.46416581f, 0.45253196f, +0.44082057f, 0.42903364f, 0.41717321f, 0.40524128f, 0.39323992f, +0.38117120f, 0.36903715f, 0.35683987f, 0.34458145f, 0.33226398f, +0.31988961f, 0.30746040f, 0.29497850f, 0.28244606f, 0.26986524f, +0.25723818f, 0.24456702f, 0.23185398f, 0.21910121f, 0.20631088f, +0.19348522f, 0.18062639f, 0.16773662f, 0.15481812f, 0.14187308f, +0.12890373f, 0.11591230f, 0.10290100f, 0.089872077f, 0.076827750f, +0.063770257f, 0.050701842f, 0.037624735f, 0.024541186f, 0.011453429f, +-0.0016362892f, -0.014725727f, -0.027812643f, -0.040894791f, -0.053969935f, +-0.067035832f, -0.080090240f, -0.093130924f, -0.10615565f, -0.11916219f, +-0.13214831f, -0.14511178f, -0.15805040f, -0.17096193f, -0.18384418f, +-0.19669491f, -0.20951195f, -0.22229309f, -0.23503613f, -0.24773891f, +-0.26039925f, -0.27301496f, -0.28558388f, -0.29810387f, -0.31057280f, +-0.32298848f, -0.33534884f, -0.34765175f, -0.35989508f, -0.37207675f, +-0.38419467f, -0.39624676f, -0.40823093f, -0.42014518f, -0.43198743f, +-0.44375566f, -0.45544785f, -0.46706200f, -0.47859612f, -0.49004826f, +-0.50141639f, -0.51269865f, -0.52389306f, -0.53499764f, -0.54601061f, +-0.55693001f, -0.56775403f, -0.57848072f, -0.58910829f, -0.59963489f, +-0.61005878f, -0.62037814f, -0.63059121f, -0.64069623f, -0.65069145f, +-0.66057515f, -0.67034572f, -0.68000144f, -0.68954057f, -0.69896162f, +-0.70826286f, -0.71744281f, -0.72649974f, -0.73543227f, -0.74423873f, +-0.75291771f, -0.76146764f, -0.76988715f, -0.77817470f, -0.78632891f, +-0.79434842f, -0.80223179f, -0.80997771f, -0.81758487f, -0.82505190f, +-0.83237761f, -0.83956063f, -0.84659988f, -0.85349399f, -0.86024189f, +-0.86684239f, -0.87329435f, -0.87959671f, -0.88574833f, -0.89174819f, +-0.89759529f, -0.90328854f, -0.90882701f, -0.91420978f, -0.91943592f, +-0.92450452f, -0.92941469f, -0.93416560f, -0.93875647f, -0.94318646f, +-0.94745487f, -0.95156091f, -0.95550388f, -0.95928317f, -0.96289814f, +-0.96634805f, -0.96963239f, -0.97275060f, -0.97570217f, -0.97848648f, +-0.98110318f, -0.98355180f, -0.98583186f, -0.98794299f, -0.98988485f, +-0.99165714f, -0.99325943f, -0.99469161f, -0.99595332f, -0.99704438f, +-0.99796462f, -0.99871385f, -0.99929196f, -0.99969882f, -0.99993443f, +0.99999464f, 0.99956632f, 0.99845290f, 0.99665523f, 0.99417448f, +0.99101239f, 0.98717111f, 0.98265326f, 0.97746199f, 0.97160077f, +0.96507365f, 0.95788515f, 0.95004016f, 0.94154406f, 0.93240267f, +0.92262226f, 0.91220951f, 0.90117162f, 0.88951606f, 0.87725091f, +0.86438453f, 0.85092574f, 0.83688372f, 0.82226819f, 0.80708915f, +0.79135692f, 0.77508235f, 0.75827658f, 0.74095112f, 0.72311783f, +0.70478898f, 0.68597710f, 0.66669506f, 0.64695615f, 0.62677377f, +0.60616189f, 0.58513457f, 0.56370622f, 0.54189157f, 0.51970547f, +0.49716324f, 0.47428027f, 0.45107225f, 0.42755505f, 0.40374488f, +0.37965798f, 0.35531086f, 0.33072025f, 0.30590299f, 0.28087607f, +0.25565663f, 0.23026201f, 0.20470956f, 0.17901683f, 0.15320139f, +0.12728097f, 0.10127331f, 0.075196236f, 0.049067631f, 0.022905400f, +-0.0032725304f, -0.029448219f, -0.055603724f, -0.081721120f, -0.10778251f, +-0.13377003f, -0.15966587f, -0.18545228f, -0.21111161f, -0.23662624f, +-0.26197869f, -0.28715160f, -0.31212771f, -0.33688989f, -0.36142120f, +-0.38570482f, -0.40972409f, -0.43346253f, -0.45690393f, -0.48003218f, +-0.50283146f, -0.52528608f, -0.54738069f, -0.56910020f, -0.59042966f, +-0.61135447f, -0.63186026f, -0.65193301f, -0.67155898f, -0.69072473f, +-0.70941705f, -0.72762316f, -0.74533063f, -0.76252723f, -0.77920127f, +-0.79534131f, -0.81093621f, -0.82597536f, -0.84044844f, -0.85434550f, +-0.86765707f, -0.88037395f, -0.89248747f, -0.90398932f, -0.91487163f, +-0.92512697f, -0.93474823f, -0.94372886f, -0.95206273f, -0.95974404f, +-0.96676767f, -0.97312868f, -0.97882277f, -0.98384601f, -0.98819500f, +-0.99186671f, -0.99485862f, -0.99716878f, -0.99879545f, -0.99973762f, +}; +#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 */ +}; + +/* List of all the available modes */ +#define TOTAL_MODES 1 +static const CELTMode * const static_mode_list[TOTAL_MODES] = { +&mode48000_960_120, +}; diff --git a/drivers/opus/celt/static_modes_float_arm_ne10.h b/thirdparty/opus/celt/static_modes_float_arm_ne10.h index 934a82a420..934a82a420 100644 --- a/drivers/opus/celt/static_modes_float_arm_ne10.h +++ b/thirdparty/opus/celt/static_modes_float_arm_ne10.h diff --git a/thirdparty/opus/celt/tests/test_unit_cwrs32.c b/thirdparty/opus/celt/tests/test_unit_cwrs32.c new file mode 100644 index 0000000000..36dd8af5f5 --- /dev/null +++ b/thirdparty/opus/celt/tests/test_unit_cwrs32.c @@ -0,0 +1,161 @@ +/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation, + Gregory Maxwell + Written by Jean-Marc Valin, Gregory Maxwell, and 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 <stdio.h> +#include <string.h> + +#ifndef CUSTOM_MODES +#define CUSTOM_MODES +#else +#define TEST_CUSTOM_MODES +#endif + +#define CELT_C +#include "stack_alloc.h" +#include "entenc.c" +#include "entdec.c" +#include "entcode.c" +#include "cwrs.c" +#include "mathops.c" +#include "rate.h" + +#define NMAX (240) +#define KMAX (128) + +#ifdef TEST_CUSTOM_MODES + +#define NDIMS (44) +static const int pn[NDIMS]={ + 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 18, 20, 22, + 24, 26, 28, 30, 32, 36, 40, 44, 48, + 52, 56, 60, 64, 72, 80, 88, 96, 104, + 112, 120, 128, 144, 160, 176, 192, 208 +}; +static const int pkmax[NDIMS]={ + 128, 128, 128, 128, 88, 52, 36, 26, 22, + 18, 16, 15, 13, 12, 12, 11, 10, 9, + 9, 8, 8, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 5, 5, 5, 5, 5, 5, + 4, 4, 4, 4, 4, 4, 4, 4 +}; + +#else /* TEST_CUSTOM_MODES */ + +#define NDIMS (22) +static const int pn[NDIMS]={ + 2, 3, 4, 6, 8, 9, 11, 12, 16, + 18, 22, 24, 32, 36, 44, 48, 64, 72, + 88, 96, 144, 176 +}; +static const int pkmax[NDIMS]={ + 128, 128, 128, 88, 36, 26, 18, 16, 12, + 11, 9, 9, 7, 7, 6, 6, 5, 5, + 5, 5, 4, 4 +}; + +#endif + +int main(void){ + int t; + int n; + ALLOC_STACK; + for(t=0;t<NDIMS;t++){ + int pseudo; + n=pn[t]; + for(pseudo=1;pseudo<41;pseudo++) + { + int k; +#if defined(SMALL_FOOTPRINT) + opus_uint32 uu[KMAX+2U]; +#endif + opus_uint32 inc; + opus_uint32 nc; + opus_uint32 i; + k=get_pulses(pseudo); + if (k>pkmax[t])break; + printf("Testing CWRS with N=%i, K=%i...\n",n,k); +#if defined(SMALL_FOOTPRINT) + nc=ncwrs_urow(n,k,uu); +#else + nc=CELT_PVQ_V(n,k); +#endif + inc=nc/20000; + if(inc<1)inc=1; + for(i=0;i<nc;i+=inc){ +#if defined(SMALL_FOOTPRINT) + opus_uint32 u[KMAX+2U]; +#endif + int y[NMAX]; + int sy; + opus_uint32 v; + opus_uint32 ii; + int j; +#if defined(SMALL_FOOTPRINT) + memcpy(u,uu,(k+2U)*sizeof(*u)); + cwrsi(n,k,i,y,u); +#else + cwrsi(n,k,i,y); +#endif + sy=0; + for(j=0;j<n;j++)sy+=abs(y[j]); + if(sy!=k){ + fprintf(stderr,"N=%d Pulse count mismatch in cwrsi (%d!=%d).\n", + n,sy,k); + return 99; + } + /*printf("%6u of %u:",i,nc); + for(j=0;j<n;j++)printf(" %+3i",y[j]); + printf(" ->");*/ +#if defined(SMALL_FOOTPRINT) + ii=icwrs(n,k,&v,y,u); +#else + ii=icwrs(n,y); + v=CELT_PVQ_V(n,k); +#endif + if(ii!=i){ + fprintf(stderr,"Combination-index mismatch (%lu!=%lu).\n", + (long)ii,(long)i); + return 1; + } + if(v!=nc){ + fprintf(stderr,"Combination count mismatch (%lu!=%lu).\n", + (long)v,(long)nc); + return 2; + } + /*printf(" %6u\n",i);*/ + } + /*printf("\n");*/ + } + } + return 0; +} diff --git a/thirdparty/opus/celt/tests/test_unit_dft.c b/thirdparty/opus/celt/tests/test_unit_dft.c new file mode 100644 index 0000000000..6166eb0e4f --- /dev/null +++ b/thirdparty/opus/celt/tests/test_unit_dft.c @@ -0,0 +1,189 @@ +/* Copyright (c) 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define SKIP_CONFIG_H + +#ifndef CUSTOM_MODES +#define CUSTOM_MODES +#endif + +#include <stdio.h> + +#define CELT_C +#define TEST_UNIT_DFT_C +#include "stack_alloc.h" +#include "kiss_fft.h" +#include "kiss_fft.c" +#include "mathops.c" +#include "entcode.c" + +#if defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1) +# include "x86/x86cpu.c" +#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/armcpu.c" +# include "celt_lpc.c" +# include "pitch.c" +# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/celt_neon_intr.c" +# if defined(HAVE_ARM_NE10) +# include "mdct.c" +# include "arm/celt_ne10_fft.c" +# include "arm/celt_ne10_mdct.c" +# endif +# endif +# include "arm/arm_celt_map.c" +#endif + +#ifndef M_PI +#define M_PI 3.141592653 +#endif + +int ret = 0; + +void check(kiss_fft_cpx * in,kiss_fft_cpx * out,int nfft,int isinverse) +{ + int bin,k; + double errpow=0,sigpow=0, snr; + + for (bin=0;bin<nfft;++bin) { + double ansr = 0; + double ansi = 0; + double difr; + double difi; + + for (k=0;k<nfft;++k) { + double phase = -2*M_PI*bin*k/nfft; + double re = cos(phase); + double im = sin(phase); + if (isinverse) + im = -im; + + if (!isinverse) + { + re /= nfft; + im /= nfft; + } + + ansr += in[k].r * re - in[k].i * im; + ansi += in[k].r * im + in[k].i * re; + } + /*printf ("%d %d ", (int)ansr, (int)ansi);*/ + difr = ansr - out[bin].r; + difi = ansi - out[bin].i; + errpow += difr*difr + difi*difi; + sigpow += ansr*ansr+ansi*ansi; + } + snr = 10*log10(sigpow/errpow); + printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr ); + if (snr<60) { + printf( "** poor snr: %f ** \n", snr); + ret = 1; + } +} + +void test1d(int nfft,int isinverse,int arch) +{ + size_t buflen = sizeof(kiss_fft_cpx)*nfft; + + kiss_fft_cpx * in = (kiss_fft_cpx*)malloc(buflen); + kiss_fft_cpx * out= (kiss_fft_cpx*)malloc(buflen); + kiss_fft_state *cfg = opus_fft_alloc(nfft,0,0,arch); + int k; + + for (k=0;k<nfft;++k) { + in[k].r = (rand() % 32767) - 16384; + in[k].i = (rand() % 32767) - 16384; + } + + for (k=0;k<nfft;++k) { + in[k].r *= 32768; + in[k].i *= 32768; + } + + if (isinverse) + { + for (k=0;k<nfft;++k) { + in[k].r /= nfft; + in[k].i /= nfft; + } + } + + /*for (k=0;k<nfft;++k) printf("%d %d ", in[k].r, in[k].i);printf("\n");*/ + + if (isinverse) + opus_ifft(cfg,in,out, arch); + else + opus_fft(cfg,in,out, arch); + + /*for (k=0;k<nfft;++k) printf("%d %d ", out[k].r, out[k].i);printf("\n");*/ + + check(in,out,nfft,isinverse); + + free(in); + free(out); + opus_fft_free(cfg, arch); +} + +int main(int argc,char ** argv) +{ + ALLOC_STACK; + int arch = opus_select_arch(); + + if (argc>1) { + int k; + for (k=1;k<argc;++k) { + test1d(atoi(argv[k]),0,arch); + test1d(atoi(argv[k]),1,arch); + } + }else{ + test1d(32,0,arch); + test1d(32,1,arch); + test1d(128,0,arch); + test1d(128,1,arch); + test1d(256,0,arch); + test1d(256,1,arch); +#ifndef RADIX_TWO_ONLY + test1d(36,0,arch); + test1d(36,1,arch); + test1d(50,0,arch); + test1d(50,1,arch); + test1d(60,0,arch); + test1d(60,1,arch); + test1d(120,0,arch); + test1d(120,1,arch); + test1d(240,0,arch); + test1d(240,1,arch); + test1d(480,0,arch); + test1d(480,1,arch); +#endif + } + return ret; +} diff --git a/thirdparty/opus/celt/tests/test_unit_entropy.c b/thirdparty/opus/celt/tests/test_unit_entropy.c new file mode 100644 index 0000000000..ff9265864c --- /dev/null +++ b/thirdparty/opus/celt/tests/test_unit_entropy.c @@ -0,0 +1,382 @@ +/* Copyright (c) 2007-2011 Xiph.Org Foundation, Mozilla Corporation, + Gregory Maxwell + Written by Jean-Marc Valin, Gregory Maxwell, and 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 <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <time.h> +#include "entcode.h" +#include "entenc.h" +#include "entdec.h" +#include <string.h> + +#include "entenc.c" +#include "entdec.c" +#include "entcode.c" + +#ifndef M_LOG2E +# define M_LOG2E 1.4426950408889634074 +#endif +#define DATA_SIZE 10000000 +#define DATA_SIZE2 10000 + +int main(int _argc,char **_argv){ + ec_enc enc; + ec_dec dec; + long nbits; + long nbits2; + double entropy; + int ft; + int ftb; + int sz; + int i; + int ret; + unsigned int sym; + unsigned int seed; + unsigned char *ptr; + const char *env_seed; + ret=0; + entropy=0; + if (_argc > 2) { + fprintf(stderr, "Usage: %s [<seed>]\n", _argv[0]); + return 1; + } + env_seed = getenv("SEED"); + if (_argc > 1) + seed = atoi(_argv[1]); + else if (env_seed) + seed = atoi(env_seed); + else + seed = time(NULL); + /*Testing encoding of raw bit values.*/ + ptr = (unsigned char *)malloc(DATA_SIZE); + ec_enc_init(&enc,ptr, DATA_SIZE); + for(ft=2;ft<1024;ft++){ + for(i=0;i<ft;i++){ + entropy+=log(ft)*M_LOG2E; + ec_enc_uint(&enc,i,ft); + } + } + /*Testing encoding of raw bit values.*/ + for(ftb=1;ftb<16;ftb++){ + for(i=0;i<(1<<ftb);i++){ + entropy+=ftb; + nbits=ec_tell(&enc); + ec_enc_bits(&enc,i,ftb); + nbits2=ec_tell(&enc); + if(nbits2-nbits!=ftb){ + fprintf(stderr,"Used %li bits to encode %i bits directly.\n", + nbits2-nbits,ftb); + ret=-1; + } + } + } + nbits=ec_tell_frac(&enc); + ec_enc_done(&enc); + fprintf(stderr, + "Encoded %0.2lf bits of entropy to %0.2lf bits (%0.3lf%% wasted).\n", + entropy,ldexp(nbits,-3),100*(nbits-ldexp(entropy,3))/nbits); + fprintf(stderr,"Packed to %li bytes.\n",(long)ec_range_bytes(&enc)); + ec_dec_init(&dec,ptr,DATA_SIZE); + for(ft=2;ft<1024;ft++){ + for(i=0;i<ft;i++){ + sym=ec_dec_uint(&dec,ft); + if(sym!=(unsigned)i){ + fprintf(stderr,"Decoded %i instead of %i with ft of %i.\n",sym,i,ft); + ret=-1; + } + } + } + for(ftb=1;ftb<16;ftb++){ + for(i=0;i<(1<<ftb);i++){ + sym=ec_dec_bits(&dec,ftb); + if(sym!=(unsigned)i){ + fprintf(stderr,"Decoded %i instead of %i with ftb of %i.\n",sym,i,ftb); + ret=-1; + } + } + } + nbits2=ec_tell_frac(&dec); + if(nbits!=nbits2){ + fprintf(stderr, + "Reported number of bits used was %0.2lf, should be %0.2lf.\n", + ldexp(nbits2,-3),ldexp(nbits,-3)); + ret=-1; + } + /*Testing an encoder bust prefers range coder data over raw bits. + This isn't a general guarantee, will only work for data that is buffered in + the encoder state and not yet stored in the user buffer, and should never + get used in practice. + It's mostly here for code coverage completeness.*/ + /*Start with a 16-bit buffer.*/ + ec_enc_init(&enc,ptr,2); + /*Write 7 raw bits.*/ + ec_enc_bits(&enc,0x55,7); + /*Write 12.3 bits of range coder data.*/ + ec_enc_uint(&enc,1,2); + ec_enc_uint(&enc,1,3); + ec_enc_uint(&enc,1,4); + ec_enc_uint(&enc,1,5); + ec_enc_uint(&enc,2,6); + ec_enc_uint(&enc,6,7); + ec_enc_done(&enc); + ec_dec_init(&dec,ptr,2); + if(!enc.error + /*The raw bits should have been overwritten by the range coder data.*/ + ||ec_dec_bits(&dec,7)!=0x05 + /*And all the range coder data should have been encoded correctly.*/ + ||ec_dec_uint(&dec,2)!=1 + ||ec_dec_uint(&dec,3)!=1 + ||ec_dec_uint(&dec,4)!=1 + ||ec_dec_uint(&dec,5)!=1 + ||ec_dec_uint(&dec,6)!=2 + ||ec_dec_uint(&dec,7)!=6){ + fprintf(stderr,"Encoder bust overwrote range coder data with raw bits.\n"); + ret=-1; + } + srand(seed); + fprintf(stderr,"Testing random streams... Random seed: %u (%.4X)\n", seed, rand() % 65536); + for(i=0;i<409600;i++){ + unsigned *data; + unsigned *tell; + unsigned tell_bits; + int j; + int zeros; + ft=rand()/((RAND_MAX>>(rand()%11U))+1U)+10; + sz=rand()/((RAND_MAX>>(rand()%9U))+1U); + data=(unsigned *)malloc(sz*sizeof(*data)); + tell=(unsigned *)malloc((sz+1)*sizeof(*tell)); + ec_enc_init(&enc,ptr,DATA_SIZE2); + zeros = rand()%13==0; + tell[0]=ec_tell_frac(&enc); + for(j=0;j<sz;j++){ + if (zeros) + data[j]=0; + else + data[j]=rand()%ft; + ec_enc_uint(&enc,data[j],ft); + tell[j+1]=ec_tell_frac(&enc); + } + if (rand()%2==0) + while(ec_tell(&enc)%8 != 0) + ec_enc_uint(&enc, rand()%2, 2); + tell_bits = ec_tell(&enc); + ec_enc_done(&enc); + if(tell_bits!=(unsigned)ec_tell(&enc)){ + fprintf(stderr,"ec_tell() changed after ec_enc_done(): %i instead of %i (Random seed: %u)\n", + ec_tell(&enc),tell_bits,seed); + ret=-1; + } + if ((tell_bits+7)/8 < ec_range_bytes(&enc)) + { + fprintf (stderr, "ec_tell() lied, there's %i bytes instead of %d (Random seed: %u)\n", + ec_range_bytes(&enc), (tell_bits+7)/8,seed); + ret=-1; + } + ec_dec_init(&dec,ptr,DATA_SIZE2); + if(ec_tell_frac(&dec)!=tell[0]){ + fprintf(stderr, + "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n", + 0,ec_tell_frac(&dec),tell[0],seed); + } + for(j=0;j<sz;j++){ + sym=ec_dec_uint(&dec,ft); + if(sym!=data[j]){ + fprintf(stderr, + "Decoded %i instead of %i with ft of %i at position %i of %i (Random seed: %u).\n", + sym,data[j],ft,j,sz,seed); + ret=-1; + } + if(ec_tell_frac(&dec)!=tell[j+1]){ + fprintf(stderr, + "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n", + j+1,ec_tell_frac(&dec),tell[j+1],seed); + } + } + free(tell); + free(data); + } + /*Test compatibility between multiple different encode/decode routines.*/ + for(i=0;i<409600;i++){ + unsigned *logp1; + unsigned *data; + unsigned *tell; + unsigned *enc_method; + int j; + sz=rand()/((RAND_MAX>>(rand()%9U))+1U); + logp1=(unsigned *)malloc(sz*sizeof(*logp1)); + data=(unsigned *)malloc(sz*sizeof(*data)); + tell=(unsigned *)malloc((sz+1)*sizeof(*tell)); + enc_method=(unsigned *)malloc(sz*sizeof(*enc_method)); + ec_enc_init(&enc,ptr,DATA_SIZE2); + tell[0]=ec_tell_frac(&enc); + for(j=0;j<sz;j++){ + data[j]=rand()/((RAND_MAX>>1)+1); + logp1[j]=(rand()%15)+1; + enc_method[j]=rand()/((RAND_MAX>>2)+1); + switch(enc_method[j]){ + case 0:{ + ec_encode(&enc,data[j]?(1<<logp1[j])-1:0, + (1<<logp1[j])-(data[j]?0:1),1<<logp1[j]); + }break; + case 1:{ + ec_encode_bin(&enc,data[j]?(1<<logp1[j])-1:0, + (1<<logp1[j])-(data[j]?0:1),logp1[j]); + }break; + case 2:{ + ec_enc_bit_logp(&enc,data[j],logp1[j]); + }break; + case 3:{ + unsigned char icdf[2]; + icdf[0]=1; + icdf[1]=0; + ec_enc_icdf(&enc,data[j],icdf,logp1[j]); + }break; + } + tell[j+1]=ec_tell_frac(&enc); + } + ec_enc_done(&enc); + if((ec_tell(&enc)+7U)/8U<ec_range_bytes(&enc)){ + fprintf(stderr,"tell() lied, there's %i bytes instead of %d (Random seed: %u)\n", + ec_range_bytes(&enc),(ec_tell(&enc)+7)/8,seed); + ret=-1; + } + ec_dec_init(&dec,ptr,DATA_SIZE2); + if(ec_tell_frac(&dec)!=tell[0]){ + fprintf(stderr, + "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n", + 0,ec_tell_frac(&dec),tell[0],seed); + } + for(j=0;j<sz;j++){ + int fs; + int dec_method; + dec_method=rand()/((RAND_MAX>>2)+1); + switch(dec_method){ + case 0:{ + fs=ec_decode(&dec,1<<logp1[j]); + sym=fs>=(1<<logp1[j])-1; + ec_dec_update(&dec,sym?(1<<logp1[j])-1:0, + (1<<logp1[j])-(sym?0:1),1<<logp1[j]); + }break; + case 1:{ + fs=ec_decode_bin(&dec,logp1[j]); + sym=fs>=(1<<logp1[j])-1; + ec_dec_update(&dec,sym?(1<<logp1[j])-1:0, + (1<<logp1[j])-(sym?0:1),1<<logp1[j]); + }break; + case 2:{ + sym=ec_dec_bit_logp(&dec,logp1[j]); + }break; + case 3:{ + unsigned char icdf[2]; + icdf[0]=1; + icdf[1]=0; + sym=ec_dec_icdf(&dec,icdf,logp1[j]); + }break; + } + if(sym!=data[j]){ + fprintf(stderr, + "Decoded %i instead of %i with logp1 of %i at position %i of %i (Random seed: %u).\n", + sym,data[j],logp1[j],j,sz,seed); + fprintf(stderr,"Encoding method: %i, decoding method: %i\n", + enc_method[j],dec_method); + ret=-1; + } + if(ec_tell_frac(&dec)!=tell[j+1]){ + fprintf(stderr, + "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n", + j+1,ec_tell_frac(&dec),tell[j+1],seed); + } + } + free(enc_method); + free(tell); + free(data); + free(logp1); + } + ec_enc_init(&enc,ptr,DATA_SIZE2); + ec_enc_bit_logp(&enc,0,1); + ec_enc_bit_logp(&enc,0,1); + ec_enc_bit_logp(&enc,0,1); + ec_enc_bit_logp(&enc,0,1); + ec_enc_bit_logp(&enc,0,2); + ec_enc_patch_initial_bits(&enc,3,2); + if(enc.error){ + fprintf(stderr,"patch_initial_bits failed"); + ret=-1; + } + ec_enc_patch_initial_bits(&enc,0,5); + if(!enc.error){ + fprintf(stderr,"patch_initial_bits didn't fail when it should have"); + ret=-1; + } + ec_enc_done(&enc); + if(ec_range_bytes(&enc)!=1||ptr[0]!=192){ + fprintf(stderr,"Got %d when expecting 192 for patch_initial_bits",ptr[0]); + ret=-1; + } + ec_enc_init(&enc,ptr,DATA_SIZE2); + ec_enc_bit_logp(&enc,0,1); + ec_enc_bit_logp(&enc,0,1); + ec_enc_bit_logp(&enc,1,6); + ec_enc_bit_logp(&enc,0,2); + ec_enc_patch_initial_bits(&enc,0,2); + if(enc.error){ + fprintf(stderr,"patch_initial_bits failed"); + ret=-1; + } + ec_enc_done(&enc); + if(ec_range_bytes(&enc)!=2||ptr[0]!=63){ + fprintf(stderr,"Got %d when expecting 63 for patch_initial_bits",ptr[0]); + ret=-1; + } + ec_enc_init(&enc,ptr,2); + ec_enc_bit_logp(&enc,0,2); + for(i=0;i<48;i++){ + ec_enc_bits(&enc,0,1); + } + ec_enc_done(&enc); + if(!enc.error){ + fprintf(stderr,"Raw bits overfill didn't fail when it should have"); + ret=-1; + } + ec_enc_init(&enc,ptr,2); + for(i=0;i<17;i++){ + ec_enc_bits(&enc,0,1); + } + ec_enc_done(&enc); + if(!enc.error){ + fprintf(stderr,"17 raw bits encoded in two bytes"); + ret=-1; + } + free(ptr); + return ret; +} diff --git a/thirdparty/opus/celt/tests/test_unit_laplace.c b/thirdparty/opus/celt/tests/test_unit_laplace.c new file mode 100644 index 0000000000..22951e29ee --- /dev/null +++ b/thirdparty/opus/celt/tests/test_unit_laplace.c @@ -0,0 +1,93 @@ +/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation + Written by Jean-Marc Valin and 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 <stdio.h> +#include <stdlib.h> +#include "laplace.h" +#define CELT_C +#include "stack_alloc.h" + +#include "entenc.c" +#include "entdec.c" +#include "entcode.c" +#include "laplace.c" + +#define DATA_SIZE 40000 + +int ec_laplace_get_start_freq(int decay) +{ + opus_uint32 ft = 32768 - LAPLACE_MINP*(2*LAPLACE_NMIN+1); + int fs = (ft*(16384-decay))/(16384+decay); + return fs+LAPLACE_MINP; +} + +int main(void) +{ + int i; + int ret = 0; + ec_enc enc; + ec_dec dec; + unsigned char *ptr; + int val[10000], decay[10000]; + ALLOC_STACK; + ptr = (unsigned char *)malloc(DATA_SIZE); + ec_enc_init(&enc,ptr,DATA_SIZE); + + val[0] = 3; decay[0] = 6000; + val[1] = 0; decay[1] = 5800; + val[2] = -1; decay[2] = 5600; + for (i=3;i<10000;i++) + { + val[i] = rand()%15-7; + decay[i] = rand()%11000+5000; + } + for (i=0;i<10000;i++) + ec_laplace_encode(&enc, &val[i], + ec_laplace_get_start_freq(decay[i]), decay[i]); + + ec_enc_done(&enc); + + ec_dec_init(&dec,ec_get_buffer(&enc),ec_range_bytes(&enc)); + + for (i=0;i<10000;i++) + { + int d = ec_laplace_decode(&dec, + ec_laplace_get_start_freq(decay[i]), decay[i]); + if (d != val[i]) + { + fprintf (stderr, "Got %d instead of %d\n", d, val[i]); + ret = 1; + } + } + + free(ptr); + return ret; +} diff --git a/thirdparty/opus/celt/tests/test_unit_mathops.c b/thirdparty/opus/celt/tests/test_unit_mathops.c new file mode 100644 index 0000000000..fd3319da91 --- /dev/null +++ b/thirdparty/opus/celt/tests/test_unit_mathops.c @@ -0,0 +1,304 @@ +/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation, + Gregory Maxwell + Written by Jean-Marc Valin, Gregory Maxwell, and 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 + +#ifndef CUSTOM_MODES +#define CUSTOM_MODES +#endif + +#define CELT_C + +#include <stdio.h> +#include <math.h> +#include "mathops.c" +#include "entenc.c" +#include "entdec.c" +#include "entcode.c" +#include "bands.c" +#include "quant_bands.c" +#include "laplace.c" +#include "vq.c" +#include "cwrs.c" +#include "pitch.c" +#include "celt_lpc.c" +#include "celt.c" + +#if defined(OPUS_X86_MAY_HAVE_SSE) || defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1) +# if defined(OPUS_X86_MAY_HAVE_SSE) +# include "x86/pitch_sse.c" +# endif +# if defined(OPUS_X86_MAY_HAVE_SSE2) +# include "x86/pitch_sse2.c" +# endif +# if defined(OPUS_X86_MAY_HAVE_SSE4_1) +# include "x86/pitch_sse4_1.c" +# include "x86/celt_lpc_sse.c" +# endif +# include "x86/x86_celt_map.c" +#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/armcpu.c" +# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/celt_neon_intr.c" +# if defined(HAVE_ARM_NE10) +# include "kiss_fft.c" +# include "mdct.c" +# include "arm/celt_ne10_fft.c" +# include "arm/celt_ne10_mdct.c" +# endif +# endif +# include "arm/arm_celt_map.c" +#endif + +#ifdef FIXED_POINT +#define WORD "%d" +#else +#define WORD "%f" +#endif + +int ret = 0; + +void testdiv(void) +{ + opus_int32 i; + for (i=1;i<=327670;i++) + { + double prod; + opus_val32 val; + val = celt_rcp(i); +#ifdef FIXED_POINT + prod = (1./32768./65526.)*val*i; +#else + prod = val*i; +#endif + if (fabs(prod-1) > .00025) + { + fprintf (stderr, "div failed: 1/%d="WORD" (product = %f)\n", i, val, prod); + ret = 1; + } + } +} + +void testsqrt(void) +{ + opus_int32 i; + for (i=1;i<=1000000000;i++) + { + double ratio; + opus_val16 val; + val = celt_sqrt(i); + ratio = val/sqrt(i); + if (fabs(ratio - 1) > .0005 && fabs(val-sqrt(i)) > 2) + { + fprintf (stderr, "sqrt failed: sqrt(%d)="WORD" (ratio = %f)\n", i, val, ratio); + ret = 1; + } + i+= i>>10; + } +} + +void testbitexactcos(void) +{ + int i; + opus_int32 min_d,max_d,last,chk; + chk=max_d=0; + last=min_d=32767; + for(i=64;i<=16320;i++) + { + opus_int32 d; + opus_int32 q=bitexact_cos(i); + chk ^= q*i; + d = last - q; + if (d>max_d)max_d=d; + if (d<min_d)min_d=d; + last = q; + } + if ((chk!=89408644)||(max_d!=5)||(min_d!=0)||(bitexact_cos(64)!=32767)|| + (bitexact_cos(16320)!=200)||(bitexact_cos(8192)!=23171)) + { + fprintf (stderr, "bitexact_cos failed\n"); + ret = 1; + } +} + +void testbitexactlog2tan(void) +{ + int i,fail; + opus_int32 min_d,max_d,last,chk; + fail=chk=max_d=0; + last=min_d=15059; + for(i=64;i<8193;i++) + { + opus_int32 d; + opus_int32 mid=bitexact_cos(i); + opus_int32 side=bitexact_cos(16384-i); + opus_int32 q=bitexact_log2tan(mid,side); + chk ^= q*i; + d = last - q; + if (q!=-1*bitexact_log2tan(side,mid)) + fail = 1; + if (d>max_d)max_d=d; + if (d<min_d)min_d=d; + last = q; + } + if ((chk!=15821257)||(max_d!=61)||(min_d!=-2)||fail|| + (bitexact_log2tan(32767,200)!=15059)||(bitexact_log2tan(30274,12540)!=2611)|| + (bitexact_log2tan(23171,23171)!=0)) + { + fprintf (stderr, "bitexact_log2tan failed\n"); + ret = 1; + } +} + +#ifndef FIXED_POINT +void testlog2(void) +{ + float x; + for (x=0.001;x<1677700.0;x+=(x/8.0)) + { + float error = fabs((1.442695040888963387*log(x))-celt_log2(x)); + if (error>0.0009) + { + fprintf (stderr, "celt_log2 failed: fabs((1.442695040888963387*log(x))-celt_log2(x))>0.001 (x = %f, error = %f)\n", x,error); + ret = 1; + } + } +} + +void testexp2(void) +{ + float x; + for (x=-11.0;x<24.0;x+=0.0007) + { + float error = fabs(x-(1.442695040888963387*log(celt_exp2(x)))); + if (error>0.0002) + { + fprintf (stderr, "celt_exp2 failed: fabs(x-(1.442695040888963387*log(celt_exp2(x))))>0.0005 (x = %f, error = %f)\n", x,error); + ret = 1; + } + } +} + +void testexp2log2(void) +{ + float x; + for (x=-11.0;x<24.0;x+=0.0007) + { + float error = fabs(x-(celt_log2(celt_exp2(x)))); + if (error>0.001) + { + fprintf (stderr, "celt_log2/celt_exp2 failed: fabs(x-(celt_log2(celt_exp2(x))))>0.001 (x = %f, error = %f)\n", x,error); + ret = 1; + } + } +} +#else +void testlog2(void) +{ + opus_val32 x; + for (x=8;x<1073741824;x+=(x>>3)) + { + float error = fabs((1.442695040888963387*log(x/16384.0))-celt_log2(x)/1024.0); + if (error>0.003) + { + fprintf (stderr, "celt_log2 failed: x = %ld, error = %f\n", (long)x,error); + ret = 1; + } + } +} + +void testexp2(void) +{ + opus_val16 x; + for (x=-32768;x<15360;x++) + { + float error1 = fabs(x/1024.0-(1.442695040888963387*log(celt_exp2(x)/65536.0))); + float error2 = fabs(exp(0.6931471805599453094*x/1024.0)-celt_exp2(x)/65536.0); + if (error1>0.0002&&error2>0.00004) + { + fprintf (stderr, "celt_exp2 failed: x = "WORD", error1 = %f, error2 = %f\n", x,error1,error2); + ret = 1; + } + } +} + +void testexp2log2(void) +{ + opus_val32 x; + for (x=8;x<65536;x+=(x>>3)) + { + float error = fabs(x-0.25*celt_exp2(celt_log2(x)))/16384; + if (error>0.004) + { + fprintf (stderr, "celt_log2/celt_exp2 failed: fabs(x-(celt_exp2(celt_log2(x))))>0.001 (x = %ld, error = %f)\n", (long)x,error); + ret = 1; + } + } +} + +void testilog2(void) +{ + opus_val32 x; + for (x=1;x<=268435455;x+=127) + { + opus_val32 lg; + opus_val32 y; + + lg = celt_ilog2(x); + if (lg<0 || lg>=31) + { + printf("celt_ilog2 failed: 0<=celt_ilog2(x)<31 (x = %d, celt_ilog2(x) = %d)\n",x,lg); + ret = 1; + } + y = 1<<lg; + + if (x<y || (x>>1)>=y) + { + printf("celt_ilog2 failed: 2**celt_ilog2(x)<=x<2**(celt_ilog2(x)+1) (x = %d, 2**celt_ilog2(x) = %d)\n",x,y); + ret = 1; + } + } +} +#endif + +int main(void) +{ + testbitexactcos(); + testbitexactlog2tan(); + testdiv(); + testsqrt(); + testlog2(); + testexp2(); + testexp2log2(); +#ifdef FIXED_POINT + testilog2(); +#endif + return ret; +} diff --git a/thirdparty/opus/celt/tests/test_unit_mdct.c b/thirdparty/opus/celt/tests/test_unit_mdct.c new file mode 100644 index 0000000000..8dbb9caa2e --- /dev/null +++ b/thirdparty/opus/celt/tests/test_unit_mdct.c @@ -0,0 +1,230 @@ +/* Copyright (c) 2008-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 + +#define SKIP_CONFIG_H + +#ifndef CUSTOM_MODES +#define CUSTOM_MODES +#endif + +#include <stdio.h> + +#define CELT_C +#include "mdct.h" +#include "stack_alloc.h" + +#include "kiss_fft.c" +#include "mdct.c" +#include "mathops.c" +#include "entcode.c" + +#if defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1) +# include "x86/x86cpu.c" +#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/armcpu.c" +# include "pitch.c" +# include "celt_lpc.c" +# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/celt_neon_intr.c" +# if defined(HAVE_ARM_NE10) +# include "arm/celt_ne10_fft.c" +# include "arm/celt_ne10_mdct.c" +# endif +# endif +# include "arm/arm_celt_map.c" +#endif + +#ifndef M_PI +#define M_PI 3.141592653 +#endif + +int ret = 0; +void check(kiss_fft_scalar * in,kiss_fft_scalar * out,int nfft,int isinverse) +{ + int bin,k; + double errpow=0,sigpow=0; + double snr; + for (bin=0;bin<nfft/2;++bin) { + double ansr = 0; + double difr; + + for (k=0;k<nfft;++k) { + double phase = 2*M_PI*(k+.5+.25*nfft)*(bin+.5)/nfft; + double re = cos(phase); + + re /= nfft/4; + + ansr += in[k] * re; + } + /*printf ("%f %f\n", ansr, out[bin]);*/ + difr = ansr - out[bin]; + errpow += difr*difr; + sigpow += ansr*ansr; + } + snr = 10*log10(sigpow/errpow); + printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr ); + if (snr<60) { + printf( "** poor snr: %f **\n", snr); + ret = 1; + } +} + +void check_inv(kiss_fft_scalar * in,kiss_fft_scalar * out,int nfft,int isinverse) +{ + int bin,k; + double errpow=0,sigpow=0; + double snr; + for (bin=0;bin<nfft;++bin) { + double ansr = 0; + double difr; + + for (k=0;k<nfft/2;++k) { + double phase = 2*M_PI*(bin+.5+.25*nfft)*(k+.5)/nfft; + double re = cos(phase); + + /*re *= 2;*/ + + ansr += in[k] * re; + } + /*printf ("%f %f\n", ansr, out[bin]);*/ + difr = ansr - out[bin]; + errpow += difr*difr; + sigpow += ansr*ansr; + } + snr = 10*log10(sigpow/errpow); + printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr ); + if (snr<60) { + printf( "** poor snr: %f **\n", snr); + ret = 1; + } +} + + +void test1d(int nfft,int isinverse,int arch) +{ + mdct_lookup cfg; + size_t buflen = sizeof(kiss_fft_scalar)*nfft; + + kiss_fft_scalar * in = (kiss_fft_scalar*)malloc(buflen); + kiss_fft_scalar * in_copy = (kiss_fft_scalar*)malloc(buflen); + kiss_fft_scalar * out= (kiss_fft_scalar*)malloc(buflen); + opus_val16 * window= (opus_val16*)malloc(sizeof(opus_val16)*nfft/2); + int k; + + clt_mdct_init(&cfg, nfft, 0, arch); + for (k=0;k<nfft;++k) { + in[k] = (rand() % 32768) - 16384; + } + + for (k=0;k<nfft/2;++k) { + window[k] = Q15ONE; + } + for (k=0;k<nfft;++k) { + in[k] *= 32768; + } + + if (isinverse) + { + for (k=0;k<nfft;++k) { + in[k] /= nfft; + } + } + + for (k=0;k<nfft;++k) + in_copy[k] = in[k]; + /*for (k=0;k<nfft;++k) printf("%d %d ", in[k].r, in[k].i);printf("\n");*/ + + if (isinverse) + { + for (k=0;k<nfft;++k) + out[k] = 0; + clt_mdct_backward(&cfg,in,out, window, nfft/2, 0, 1, arch); + /* apply TDAC because clt_mdct_backward() no longer does that */ + for (k=0;k<nfft/4;++k) + out[nfft-k-1] = out[nfft/2+k]; + check_inv(in,out,nfft,isinverse); + } else { + clt_mdct_forward(&cfg,in,out,window, nfft/2, 0, 1, arch); + check(in_copy,out,nfft,isinverse); + } + /*for (k=0;k<nfft;++k) printf("%d %d ", out[k].r, out[k].i);printf("\n");*/ + + + free(in); + free(in_copy); + free(out); + free(window); + clt_mdct_clear(&cfg, arch); +} + +int main(int argc,char ** argv) +{ + ALLOC_STACK; + int arch = opus_select_arch(); + + if (argc>1) { + int k; + for (k=1;k<argc;++k) { + test1d(atoi(argv[k]),0,arch); + test1d(atoi(argv[k]),1,arch); + } + }else{ + test1d(32,0,arch); + test1d(32,1,arch); + test1d(256,0,arch); + test1d(256,1,arch); + test1d(512,0,arch); + test1d(512,1,arch); + test1d(1024,0,arch); + test1d(1024,1,arch); + test1d(2048,0,arch); + test1d(2048,1,arch); +#ifndef RADIX_TWO_ONLY + test1d(36,0,arch); + test1d(36,1,arch); + test1d(40,0,arch); + test1d(40,1,arch); + test1d(60,0,arch); + test1d(60,1,arch); + test1d(120,0,arch); + test1d(120,1,arch); + test1d(240,0,arch); + test1d(240,1,arch); + test1d(480,0,arch); + test1d(480,1,arch); + test1d(960,0,arch); + test1d(960,1,arch); + test1d(1920,0,arch); + test1d(1920,1,arch); +#endif + } + return ret; +} diff --git a/thirdparty/opus/celt/tests/test_unit_rotation.c b/thirdparty/opus/celt/tests/test_unit_rotation.c new file mode 100644 index 0000000000..1080c2085d --- /dev/null +++ b/thirdparty/opus/celt/tests/test_unit_rotation.c @@ -0,0 +1,120 @@ +/* Copyright (c) 2008-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 + +#ifndef CUSTOM_MODES +#define CUSTOM_MODES +#endif + +#define CELT_C + +#include <stdio.h> +#include <stdlib.h> +#include "vq.c" +#include "cwrs.c" +#include "entcode.c" +#include "entenc.c" +#include "entdec.c" +#include "mathops.c" +#include "bands.h" +#include "pitch.c" +#include "celt_lpc.c" +#include "celt.c" +#include <math.h> + +#if defined(OPUS_X86_MAY_HAVE_SSE) || defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1) +# if defined(OPUS_X86_MAY_HAVE_SSE) +# include "x86/pitch_sse.c" +# endif +# if defined(OPUS_X86_MAY_HAVE_SSE2) +# include "x86/pitch_sse2.c" +# endif +# if defined(OPUS_X86_MAY_HAVE_SSE4_1) +# include "x86/pitch_sse4_1.c" +# include "x86/celt_lpc_sse.c" +# endif +# include "x86/x86_celt_map.c" +#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/armcpu.c" +# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) +# include "arm/celt_neon_intr.c" +# if defined(HAVE_ARM_NE10) +# include "kiss_fft.c" +# include "mdct.c" +# include "arm/celt_ne10_fft.c" +# include "arm/celt_ne10_mdct.c" +# endif +# endif +# include "arm/arm_celt_map.c" +#endif + +#define MAX_SIZE 100 + +int ret=0; +void test_rotation(int N, int K) +{ + int i; + double err = 0, ener = 0, snr, snr0; + opus_val16 x0[MAX_SIZE]; + opus_val16 x1[MAX_SIZE]; + for (i=0;i<N;i++) + x1[i] = x0[i] = rand()%32767-16384; + exp_rotation(x1, N, 1, 1, K, SPREAD_NORMAL); + for (i=0;i<N;i++) + { + err += (x0[i]-(double)x1[i])*(x0[i]-(double)x1[i]); + ener += x0[i]*(double)x0[i]; + } + snr0 = 20*log10(ener/err); + err = ener = 0; + exp_rotation(x1, N, -1, 1, K, SPREAD_NORMAL); + for (i=0;i<N;i++) + { + err += (x0[i]-(double)x1[i])*(x0[i]-(double)x1[i]); + ener += x0[i]*(double)x0[i]; + } + snr = 20*log10(ener/err); + printf ("SNR for size %d (%d pulses) is %f (was %f without inverse)\n", N, K, snr, snr0); + if (snr < 60 || snr0 > 20) + { + fprintf(stderr, "FAIL!\n"); + ret = 1; + } +} + +int main(void) +{ + ALLOC_STACK; + test_rotation(15, 3); + test_rotation(23, 5); + test_rotation(50, 3); + test_rotation(80, 1); + return ret; +} diff --git a/thirdparty/opus/celt/tests/test_unit_types.c b/thirdparty/opus/celt/tests/test_unit_types.c new file mode 100644 index 0000000000..67a0fb8ed3 --- /dev/null +++ b/thirdparty/opus/celt/tests/test_unit_types.c @@ -0,0 +1,50 @@ +/* Copyright (c) 2008-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_types.h" +#include <stdio.h> + +int main(void) +{ + opus_int16 i = 1; + i <<= 14; + if (i>>14 != 1) + { + fprintf(stderr, "opus_int16 isn't 16 bits\n"); + return 1; + } + if (sizeof(opus_int16)*2 != sizeof(opus_int32)) + { + fprintf(stderr, "16*2 != 32\n"); + return 1; + } + return 0; +} diff --git a/thirdparty/opus/celt/vq.c b/thirdparty/opus/celt/vq.c new file mode 100644 index 0000000000..f358396065 --- /dev/null +++ b/thirdparty/opus/celt/vq.c @@ -0,0 +1,408 @@ +/* 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" + +#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); + 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)); + } +} +#endif /* OVERRIDE_vq_exp_rotation1 */ + +static 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); + } + } +} + +/** Takes the pitch vector and the decoded residual vector, computes the gain + that will give ||p+g*y||=1 and mixes the residual with the pitch. */ +static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X, + int N, opus_val32 Ryy, opus_val16 gain) +{ + int i; +#ifdef FIXED_POINT + int k; +#endif + opus_val32 t; + opus_val16 g; + +#ifdef FIXED_POINT + k = celt_ilog2(Ryy)>>1; +#endif + t = VSHR32(Ryy, 2*(k-7)); + g = MULT16_16_P15(celt_rsqrt_norm(t),gain); + + i=0; + do + X[i] = EXTRACT16(PSHR32(MULT16_16(g, iy[i]), k+1)); + 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; +} + +unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc +#ifdef RESYNTH + , opus_val16 gain +#endif + ) +{ + VARDECL(celt_norm, y); + VARDECL(int, iy); + VARDECL(opus_val16, signx); + int i, j; + opus_val16 s; + int pulsesLeft; + opus_val32 sum; + opus_val32 xy; + opus_val16 yy; + unsigned collapse_mask; + SAVE_STACK; + + celt_assert2(K>0, "alg_quant() needs at least one pulse"); + celt_assert2(N>1, "alg_quant() needs at least two dimensions"); + + ALLOC(y, N, celt_norm); + ALLOC(iy, N, int); + ALLOC(signx, N, opus_val16); + + exp_rotation(X, N, 1, B, K, spread); + + /* Get rid of the sign */ + sum = 0; + j=0; do { + if (X[j]>0) + signx[j]=1; + else { + signx[j]=-1; + X[j]=-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); + } + rcp = EXTRACT16(MULT16_32_Q16(K-1, celt_rcp(sum))); + 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_assert2(pulsesLeft>=1, "Allocated too many pulses in the quick pass"); + + /* 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_assert2(pulsesLeft<=N+3, "Not enough pulses in the quick pass"); +#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; + } + + s = 1; + for (i=0;i<pulsesLeft;i++) + { + int best_id; + opus_val32 best_num = -VERY_LARGE16; + opus_val16 best_den = 0; +#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 = ADD32(yy, 1); + j=0; + do { + opus_val16 Rxy, Ryy; + /* 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: Make sure to use conditional moves here */ + if (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*s; + iy[best_id]++; + } + + /* Put the original sign back */ + j=0; + do { + X[j] = MULT16_16(signx[j],X[j]); + if (signx[j] < 0) + iy[j] = -iy[j]; + } while (++j<N); + encode_pulses(iy, N, K, enc); + +#ifdef RESYNTH + normalise_residual(iy, X, N, yy, gain); + exp_rotation(X, N, -1, B, K, spread); +#endif + + collapse_mask = extract_collapse_mask(iy, N, B); + 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_val16 gain) +{ + opus_val32 Ryy; + unsigned collapse_mask; + VARDECL(int, iy); + 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); + normalise_residual(iy, X, N, Ryy, gain); + 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_val16 gain, int arch) +{ + int i; +#ifdef FIXED_POINT + int k; +#endif + opus_val32 E; + opus_val16 g; + opus_val32 t; + celt_norm *xptr; + E = EPSILON + celt_inner_prod(X, X, N, arch); +#ifdef FIXED_POINT + k = celt_ilog2(E)>>1; +#endif + t = VSHR32(E, 2*(k-7)); + g = MULT16_16_P15(celt_rsqrt_norm(t),gain); + + xptr = X; + for (i=0;i<N;i++) + { + *xptr = EXTRACT16(PSHR32(MULT16_16(g, *xptr), k+1)); + xptr++; + } + /*return celt_sqrt(E);*/ +} +#endif /* OVERRIDE_renormalise_vector */ + +int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch) +{ + int i; + int itheta; + opus_val16 mid, side; + opus_val32 Emid, Eside; + + Emid = Eside = EPSILON; + if (stereo) + { + for (i=0;i<N;i++) + { + celt_norm m, s; + m = ADD16(SHR16(X[i],1),SHR16(Y[i],1)); + s = SUB16(SHR16(X[i],1),SHR16(Y[i],1)); + Emid = MAC16_16(Emid, m, m); + Eside = MAC16_16(Eside, s, s); + } + } else { + Emid += celt_inner_prod(X, X, N, arch); + Eside += celt_inner_prod(Y, Y, N, arch); + } + mid = celt_sqrt(Emid); + side = celt_sqrt(Eside); +#ifdef FIXED_POINT + /* 0.63662 = 2/pi */ + itheta = MULT16_16_Q15(QCONST16(0.63662f,15),celt_atan2p(side, mid)); +#else + itheta = (int)floor(.5f+16384*0.63662f*atan2(side,mid)); +#endif + + return itheta; +} diff --git a/thirdparty/opus/celt/vq.h b/thirdparty/opus/celt/vq.h new file mode 100644 index 0000000000..5cfcbe50ea --- /dev/null +++ b/thirdparty/opus/celt/vq.h @@ -0,0 +1,75 @@ +/* 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(MIPSr1_ASM) +#include "mips/vq_mipsr1.h" +#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 +#ifdef RESYNTH + , opus_val16 gain +#endif + ); + +/** 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_val16 gain); + +void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch); + +int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch); + +#endif /* VQ_H */ diff --git a/thirdparty/opus/celt/x86/celt_lpc_sse.c b/thirdparty/opus/celt/x86/celt_lpc_sse.c new file mode 100644 index 0000000000..67e5592acf --- /dev/null +++ b/thirdparty/opus/celt/x86/celt_lpc_sse.c @@ -0,0 +1,132 @@ +/* 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, + opus_val16 *mem, + int arch) +{ + int i,j; + VARDECL(opus_val16, rnum); + VARDECL(opus_val16, x); + + __m128i vecNoA; + opus_int32 noA ; + SAVE_STACK; + + ALLOC(rnum, ord, opus_val16); + ALLOC(x, N+ord, opus_val16); + for(i=0;i<ord;i++) + rnum[i] = num[ord-i-1]; + for(i=0;i<ord;i++) + x[i] = mem[ord-i-1]; + + for (i=0;i<N-7;i+=8) + { + x[i+ord ]=_x[i ]; + x[i+ord+1]=_x[i+1]; + x[i+ord+2]=_x[i+2]; + x[i+ord+3]=_x[i+3]; + x[i+ord+4]=_x[i+4]; + x[i+ord+5]=_x[i+5]; + x[i+ord+6]=_x[i+6]; + x[i+ord+7]=_x[i+7]; + } + + for (;i<N-3;i+=4) + { + x[i+ord ]=_x[i ]; + x[i+ord+1]=_x[i+1]; + x[i+ord+2]=_x[i+2]; + x[i+ord+3]=_x[i+3]; + } + + for (;i<N;i++) + x[i+ord]=_x[i]; + + for(i=0;i<ord;i++) + mem[i] = _x[N-i-1]; +#ifdef SMALL_FOOTPRINT + for (i=0;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]); + } + _y[i] = SATURATE16(PSHR32(sum, SIG_SHIFT)); + } +#else + 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; + + xcorr_kernel(rnum, x+i, sums, ord, arch); + + vecSum = _mm_loadu_si128((__m128i *)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 *)(_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]); + _y[i] = SATURATE16(ADD32(EXTEND32(_x[i]), PSHR32(sum, SIG_SHIFT))); + } + +#endif + RESTORE_STACK; +} + +#endif diff --git a/thirdparty/opus/celt/x86/celt_lpc_sse.h b/thirdparty/opus/celt/x86/celt_lpc_sse.h new file mode 100644 index 0000000000..c5ec796ed5 --- /dev/null +++ b/thirdparty/opus/celt/x86/celt_lpc_sse.h @@ -0,0 +1,68 @@ +/* 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) +#define OVERRIDE_CELT_FIR + +void celt_fir_sse4_1( + const opus_val16 *x, + const opus_val16 *num, + opus_val16 *y, + int N, + int ord, + opus_val16 *mem, + int arch); + +#if defined(OPUS_X86_PRESUME_SSE4_1) +#define celt_fir(x, num, y, N, ord, mem, arch) \ + ((void)arch, celt_fir_sse4_1(x, num, y, N, ord, mem, arch)) + +#else + +extern void (*const CELT_FIR_IMPL[OPUS_ARCHMASK + 1])( + const opus_val16 *x, + const opus_val16 *num, + opus_val16 *y, + int N, + int ord, + opus_val16 *mem, + int arch); + +# define celt_fir(x, num, y, N, ord, mem, arch) \ + ((*CELT_FIR_IMPL[(arch) & OPUS_ARCHMASK])(x, num, y, N, ord, mem, arch)) + +#endif +#endif + +#endif diff --git a/thirdparty/opus/celt/x86/pitch_sse.c b/thirdparty/opus/celt/x86/pitch_sse.c new file mode 100644 index 0000000000..20e73126b6 --- /dev/null +++ b/thirdparty/opus/celt/x86/pitch_sse.c @@ -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/thirdparty/opus/celt/x86/pitch_sse.h b/thirdparty/opus/celt/x86/pitch_sse.h new file mode 100644 index 0000000000..d4cbeb8b9c --- /dev/null +++ b/thirdparty/opus/celt/x86/pitch_sse.h @@ -0,0 +1,192 @@ +/* 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_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_SSE2) && !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_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) + +#define OVERRIDE_DUAL_INNER_PROD +#define OVERRIDE_COMB_FILTER_CONST + +#undef dual_inner_prod +#undef comb_filter_const + +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 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)) +#else + +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 +#endif + +#endif diff --git a/thirdparty/opus/celt/x86/pitch_sse2.c b/thirdparty/opus/celt/x86/pitch_sse2.c new file mode 100644 index 0000000000..a0e7d1beaf --- /dev/null +++ b/thirdparty/opus/celt/x86/pitch_sse2.c @@ -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 *)(&x[i + 0])); + inVec2_76543210 = _mm_loadu_si128((__m128i *)(&y[i + 0])); + + inVec1_FEDCBA98 = _mm_loadu_si128((__m128i *)(&x[i + 8])); + inVec2_FEDCBA98 = _mm_loadu_si128((__m128i *)(&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 *)(&x[i + 0])); + inVec2_76543210 = _mm_loadu_si128((__m128i *)(&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/thirdparty/opus/celt/x86/pitch_sse4_1.c b/thirdparty/opus/celt/x86/pitch_sse4_1.c new file mode 100644 index 0000000000..a092c68b24 --- /dev/null +++ b/thirdparty/opus/celt/x86/pitch_sse4_1.c @@ -0,0 +1,195 @@ +/* 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 *)(&x[i + 0])); + inVec2_76543210 = _mm_loadu_si128((__m128i *)(&y[i + 0])); + + inVec1_FEDCBA98 = _mm_loadu_si128((__m128i *)(&x[i + 8])); + inVec2_FEDCBA98 = _mm_loadu_si128((__m128i *)(&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 *)(&x[i + 0])); + inVec2_76543210 = _mm_loadu_si128((__m128i *)(&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; + + 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 *)(&x[j + 0])); + vecY0 = _mm_loadu_si128((__m128i *)(&y[j + 0])); + vecY1 = _mm_loadu_si128((__m128i *)(&y[j + 1])); + vecY2 = _mm_loadu_si128((__m128i *)(&y[j + 2])); + vecY3 = _mm_loadu_si128((__m128i *)(&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); + } + + for (;j<len;j++) + { + vecX = OP_CVTEPI16_EPI32_M64(&x[j + 0]); + vecX0 = _mm_shuffle_epi32(vecX, 0x00); + + 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 *)(&sum[0])); + initSum = _mm_add_epi32(initSum, vecSum); + _mm_storeu_si128((__m128i *)sum, initSum); +} +#endif diff --git a/thirdparty/opus/celt/x86/x86_celt_map.c b/thirdparty/opus/celt/x86/x86_celt_map.c new file mode 100644 index 0000000000..8e5e449275 --- /dev/null +++ b/thirdparty/opus/celt/x86/x86_celt_map.c @@ -0,0 +1,155 @@ +/* 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" + +#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, + opus_val16 *mem, + 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_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 + +#endif +#endif diff --git a/thirdparty/opus/celt/x86/x86cpu.c b/thirdparty/opus/celt/x86/x86cpu.c new file mode 100644 index 0000000000..555a576b8a --- /dev/null +++ b/thirdparty/opus/celt/x86/x86cpu.c @@ -0,0 +1,157 @@ +/* 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_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_AVX) && !defined(OPUS_X86_PRESUME_AVX)) + + +#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]) : + "0" (InfoType) + ); +#else + __asm__ __volatile__ ( + "cpuid": + "=a" (CPUInfo[0]), + "=b" (CPUInfo[1]), + "=c" (CPUInfo[2]), + "=d" (CPUInfo[3]) : + "0" (InfoType) + ); +#endif +#elif defined(CPU_INFO_BY_C) + __get_cpuid(InfoType, &(CPUInfo[0]), &(CPUInfo[1]), &(CPUInfo[2]), &(CPUInfo[3])); +#endif +} + +#endif + +typedef struct CPU_Feature{ + /* SIMD: 128-bit */ + int HW_SSE; + int HW_SSE2; + int HW_SSE41; + /* SIMD: 256-bit */ + int HW_AVX; +} CPU_Feature; + +static void opus_cpu_feature_check(CPU_Feature *cpu_feature) +{ + unsigned int info[4] = {0}; + 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_AVX = (info[2] & (1 << 28)) != 0; + } + else { + cpu_feature->HW_SSE = 0; + cpu_feature->HW_SSE2 = 0; + cpu_feature->HW_SSE41 = 0; + cpu_feature->HW_AVX = 0; + } +} + +int opus_select_arch(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_AVX) + { + return arch; + } + arch++; + + return arch; +} + +#endif diff --git a/drivers/opus/celt/x86/x86cpu.h b/thirdparty/opus/celt/x86/x86cpu.h index 04fd48aac4..04fd48aac4 100644 --- a/drivers/opus/celt/x86/x86cpu.h +++ b/thirdparty/opus/celt/x86/x86cpu.h diff --git a/drivers/opus/opus_config.h b/thirdparty/opus/config.h index 7b9c92c6a8..7b9c92c6a8 100644 --- a/drivers/opus/opus_config.h +++ b/thirdparty/opus/config.h diff --git a/thirdparty/opus/http.c b/thirdparty/opus/http.c new file mode 100644 index 0000000000..cfd4e626a4 --- /dev/null +++ b/thirdparty/opus/http.c @@ -0,0 +1,3429 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ********************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "internal.h" +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <string.h> + +/*RFCs referenced in this file: + RFC 761: DOD Standard Transmission Control Protocol + RFC 1535: A Security Problem and Proposed Correction With Widely Deployed DNS + Software + RFC 1738: Uniform Resource Locators (URL) + RFC 1945: Hypertext Transfer Protocol -- HTTP/1.0 + RFC 2068: Hypertext Transfer Protocol -- HTTP/1.1 + RFC 2145: Use and Interpretation of HTTP Version Numbers + RFC 2246: The TLS Protocol Version 1.0 + RFC 2459: Internet X.509 Public Key Infrastructure Certificate and + Certificate Revocation List (CRL) Profile + RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1 + RFC 2617: HTTP Authentication: Basic and Digest Access Authentication + RFC 2817: Upgrading to TLS Within HTTP/1.1 + RFC 2818: HTTP Over TLS + RFC 3492: Punycode: A Bootstring encoding of Unicode for Internationalized + Domain Names in Applications (IDNA) + RFC 3986: Uniform Resource Identifier (URI): Generic Syntax + RFC 3987: Internationalized Resource Identifiers (IRIs) + RFC 4343: Domain Name System (DNS) Case Insensitivity Clarification + RFC 5894: Internationalized Domain Names for Applications (IDNA): + Background, Explanation, and Rationale + RFC 6066: Transport Layer Security (TLS) Extensions: Extension Definitions + RFC 6125: Representation and Verification of Domain-Based Application Service + Identity within Internet Public Key Infrastructure Using X.509 (PKIX) + Certificates in the Context of Transport Layer Security (TLS) + RFC 6555: Happy Eyeballs: Success with Dual-Stack Hosts*/ + +typedef struct OpusParsedURL OpusParsedURL; +typedef struct OpusStringBuf OpusStringBuf; +typedef struct OpusHTTPConn OpusHTTPConn; +typedef struct OpusHTTPStream OpusHTTPStream; + +static char *op_string_range_dup(const char *_start,const char *_end){ + size_t len; + char *ret; + OP_ASSERT(_start<=_end); + len=_end-_start; + /*This is to help avoid overflow elsewhere, later.*/ + if(OP_UNLIKELY(len>=INT_MAX))return NULL; + ret=(char *)_ogg_malloc(sizeof(*ret)*(len+1)); + if(OP_LIKELY(ret!=NULL)){ + ret=(char *)memcpy(ret,_start,sizeof(*ret)*(len)); + ret[len]='\0'; + } + return ret; +} + +static char *op_string_dup(const char *_s){ + return op_string_range_dup(_s,_s+strlen(_s)); +} + +static char *op_string_tolower(char *_s){ + int i; + for(i=0;_s[i]!='\0';i++){ + int c; + c=_s[i]; + if(c>='A'&&c<='Z')c+='a'-'A'; + _s[i]=(char)c; + } + return _s; +} + +/*URI character classes (from RFC 3986).*/ +#define OP_URL_ALPHA \ + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +#define OP_URL_DIGIT "0123456789" +#define OP_URL_HEXDIGIT "0123456789ABCDEFabcdef" +/*Not a character class, but the characters allowed in <scheme>.*/ +#define OP_URL_SCHEME OP_URL_ALPHA OP_URL_DIGIT "+-." +#define OP_URL_GEN_DELIMS "#/:?@[]" +#define OP_URL_SUB_DELIMS "!$&'()*+,;=" +#define OP_URL_RESERVED OP_URL_GEN_DELIMS OP_URL_SUB_DELIMS +#define OP_URL_UNRESERVED OP_URL_ALPHA OP_URL_DIGIT "-._~" +/*Not a character class, but the characters allowed in <pct-encoded>.*/ +#define OP_URL_PCT_ENCODED "%" +/*Not a character class or production rule, but for convenience.*/ +#define OP_URL_PCHAR_BASE \ + OP_URL_UNRESERVED OP_URL_PCT_ENCODED OP_URL_SUB_DELIMS +#define OP_URL_PCHAR OP_URL_PCHAR_BASE ":@" +/*Not a character class, but the characters allowed in <userinfo> and + <IP-literal>.*/ +#define OP_URL_PCHAR_NA OP_URL_PCHAR_BASE ":" +/*Not a character class, but the characters allowed in <segment-nz-nc>.*/ +#define OP_URL_PCHAR_NC OP_URL_PCHAR_BASE "@" +/*Not a character clsss, but the characters allowed in <path>.*/ +#define OP_URL_PATH OP_URL_PCHAR "/" +/*Not a character class, but the characters allowed in <query> / <fragment>.*/ +#define OP_URL_QUERY_FRAG OP_URL_PCHAR "/?" + +/*Check the <% HEXDIG HEXDIG> escapes of a URL for validity. + Return: 0 if valid, or a negative value on failure.*/ +static int op_validate_url_escapes(const char *_s){ + int i; + for(i=0;_s[i];i++){ + if(_s[i]=='%'){ + if(OP_UNLIKELY(!isxdigit(_s[i+1])) + ||OP_UNLIKELY(!isxdigit(_s[i+2])) + /*RFC 3986 says %00 "should be rejected if the application is not + expecting to receive raw data within a component."*/ + ||OP_UNLIKELY(_s[i+1]=='0'&&_s[i+2]=='0')){ + return OP_FALSE; + } + i+=2; + } + } + return 0; +} + +/*Convert a hex digit to its actual value. + _c: The hex digit to convert. + Presumed to be valid ('0'...'9', 'A'...'F', or 'a'...'f'). + Return: The value of the digit, in the range [0,15].*/ +static int op_hex_value(int _c){ + return _c>='a'?_c-'a'+10:_c>='A'?_c-'A'+10:_c-'0'; +} + +/*Unescape all the <% HEXDIG HEXDIG> sequences in a string in-place. + This does no validity checking.*/ +static char *op_unescape_url_component(char *_s){ + int i; + int j; + for(i=j=0;_s[i];i++,j++){ + if(_s[i]=='%'){ + _s[i]=(char)(op_hex_value(_s[i+1])<<4|op_hex_value(_s[i+2])); + i+=2; + } + } + return _s; +} + +/*Parse a file: URL. + This code is not meant to be fast: strspn() with large sets is likely to be + slow, but it is very convenient. + It is meant to be RFC 1738-compliant (as updated by RFC 3986).*/ +static const char *op_parse_file_url(const char *_src){ + const char *scheme_end; + const char *path; + const char *path_end; + scheme_end=_src+strspn(_src,OP_URL_SCHEME); + if(OP_UNLIKELY(*scheme_end!=':') + ||scheme_end-_src!=4||op_strncasecmp(_src,"file",4)!=0){ + /*Unsupported protocol.*/ + return NULL; + } + /*Make sure all escape sequences are valid to simplify unescaping later.*/ + if(OP_UNLIKELY(op_validate_url_escapes(scheme_end+1)<0))return NULL; + if(scheme_end[1]=='/'&&scheme_end[2]=='/'){ + const char *host; + /*file: URLs can have a host! + Yeah, I was surprised, too, but that's what RFC 1738 says. + It also says, "The file URL scheme is unusual in that it does not specify + an Internet protocol or access method for such files; as such, its + utility in network protocols between hosts is limited," which is a mild + understatement.*/ + host=scheme_end+3; + /*The empty host is what we expect.*/ + if(OP_LIKELY(*host=='/'))path=host; + else{ + const char *host_end; + char host_buf[28]; + /*RFC 1738 says localhost "is interpreted as `the machine from which the + URL is being interpreted,'" so let's check for it.*/ + host_end=host+strspn(host,OP_URL_PCHAR_BASE); + /*No <port> allowed. + This also rejects IP-Literals.*/ + if(*host_end!='/')return NULL; + /*An escaped "localhost" can take at most 27 characters.*/ + if(OP_UNLIKELY(host_end-host>27))return NULL; + memcpy(host_buf,host,sizeof(*host_buf)*(host_end-host)); + host_buf[host_end-host]='\0'; + op_unescape_url_component(host_buf); + op_string_tolower(host_buf); + /*Some other host: give up.*/ + if(OP_UNLIKELY(strcmp(host_buf,"localhost")!=0))return NULL; + path=host_end; + } + } + else path=scheme_end+1; + path_end=path+strspn(path,OP_URL_PATH); + /*This will reject a <query> or <fragment> component, too. + I don't know what to do with queries, but a temporal fragment would at + least make sense. + RFC 1738 pretty clearly defines a <searchpart> that's equivalent to the + RFC 3986 <query> component for other schemes, but not the file: scheme, + so I'm going to just reject it.*/ + if(*path_end!='\0')return NULL; + return path; +} + +#if defined(OP_ENABLE_HTTP) +# if defined(_WIN32) +# include <winsock2.h> +# include <ws2tcpip.h> +# include <openssl/ssl.h> +# include "winerrno.h" + +typedef SOCKET op_sock; + +# define OP_INVALID_SOCKET (INVALID_SOCKET) + +/*Vista and later support WSAPoll(), but we don't want to rely on that. + Instead we re-implement it badly using select(). + Unfortunately, they define a conflicting struct pollfd, so we only define our + own if it looks like that one has not already been defined.*/ +# if !defined(POLLIN) +/*Equivalent to POLLIN.*/ +# define POLLRDNORM (0x0100) +/*Priority band data can be read.*/ +# define POLLRDBAND (0x0200) +/*There is data to read.*/ +# define POLLIN (POLLRDNORM|POLLRDBAND) +/* There is urgent data to read.*/ +# define POLLPRI (0x0400) +/*Equivalent to POLLOUT.*/ +# define POLLWRNORM (0x0010) +/*Writing now will not block.*/ +# define POLLOUT (POLLWRNORM) +/*Priority data may be written.*/ +# define POLLWRBAND (0x0020) +/*Error condition (output only).*/ +# define POLLERR (0x0001) +/*Hang up (output only).*/ +# define POLLHUP (0x0002) +/*Invalid request: fd not open (output only).*/ +# define POLLNVAL (0x0004) + +struct pollfd{ + /*File descriptor.*/ + op_sock fd; + /*Requested events.*/ + short events; + /*Returned events.*/ + short revents; +}; +# endif + +/*But Winsock never defines nfds_t (it's simply hard-coded to ULONG).*/ +typedef unsigned long nfds_t; + +/*The usage of FD_SET() below is O(N^2). + This is okay because select() is limited to 64 sockets in Winsock, anyway. + In practice, we only ever call it with one or two sockets.*/ +static int op_poll_win32(struct pollfd *_fds,nfds_t _nfds,int _timeout){ + struct timeval tv; + fd_set ifds; + fd_set ofds; + fd_set efds; + nfds_t i; + int ret; + FD_ZERO(&ifds); + FD_ZERO(&ofds); + FD_ZERO(&efds); + for(i=0;i<_nfds;i++){ + _fds[i].revents=0; + if(_fds[i].events&POLLIN)FD_SET(_fds[i].fd,&ifds); + if(_fds[i].events&POLLOUT)FD_SET(_fds[i].fd,&ofds); + FD_SET(_fds[i].fd,&efds); + } + if(_timeout>=0){ + tv.tv_sec=_timeout/1000; + tv.tv_usec=(_timeout%1000)*1000; + } + ret=select(-1,&ifds,&ofds,&efds,_timeout<0?NULL:&tv); + if(ret>0){ + for(i=0;i<_nfds;i++){ + if(FD_ISSET(_fds[i].fd,&ifds))_fds[i].revents|=POLLIN; + if(FD_ISSET(_fds[i].fd,&ofds))_fds[i].revents|=POLLOUT; + /*This isn't correct: there are several different things that might have + happened to a fd in efds, but I don't know a good way to distinguish + them without more context from the caller. + It's okay, because we don't actually check any of these bits, we just + need _some_ bit set.*/ + if(FD_ISSET(_fds[i].fd,&efds))_fds[i].revents|=POLLHUP; + } + } + return ret; +} + +/*We define op_errno() to make it clear that it's not an l-value like normal + errno is.*/ +# define op_errno() (WSAGetLastError()?WSAGetLastError()-WSABASEERR:0) +# define op_reset_errno() (WSASetLastError(0)) + +/*The remaining functions don't get an op_ prefix even though they only + operate on sockets, because we don't use non-socket I/O here, and this + minimizes the changes needed to deal with Winsock.*/ +# define close(_fd) closesocket(_fd) +/*This relies on sizeof(u_long)==sizeof(int), which is always true on both + Win32 and Win64.*/ +# define ioctl(_fd,_req,_arg) ioctlsocket(_fd,_req,(u_long *)(_arg)) +# define getsockopt(_fd,_level,_name,_val,_len) \ + getsockopt(_fd,_level,_name,(char *)(_val),_len) +# define setsockopt(_fd,_level,_name,_val,_len) \ + setsockopt(_fd,_level,_name,(const char *)(_val),_len) +# define poll(_fds,_nfds,_timeout) op_poll_win32(_fds,_nfds,_timeout) + +# if defined(_MSC_VER) +typedef ptrdiff_t ssize_t; +# endif + +/*Load certificates from the built-in certificate store.*/ +int SSL_CTX_set_default_verify_paths_win32(SSL_CTX *_ssl_ctx); +# define SSL_CTX_set_default_verify_paths \ + SSL_CTX_set_default_verify_paths_win32 + +# else +/*Normal Berkeley sockets.*/ +# include <sys/ioctl.h> +# include <sys/types.h> +# include <sys/socket.h> +# include <arpa/inet.h> +# include <netinet/in.h> +# include <netinet/tcp.h> +# include <fcntl.h> +# include <netdb.h> +# include <poll.h> +# include <unistd.h> +# include <openssl/ssl.h> + +typedef int op_sock; + +# define OP_INVALID_SOCKET (-1) + +# define op_errno() (errno) +# define op_reset_errno() (errno=0) + +# endif +# include <sys/timeb.h> +# include <openssl/x509v3.h> + +/*The maximum number of simultaneous connections. + RFC 2616 says this SHOULD NOT be more than 2, but everyone on the modern web + ignores that (e.g., IE 8 bumped theirs up from 2 to 6, Firefox uses 15). + If it makes you feel better, we'll only ever actively read from one of these + at a time. + The others are kept around mainly to avoid slow-starting a new connection + when seeking, and time out rapidly.*/ +# define OP_NCONNS_MAX (4) + +/*The amount of time before we attempt to re-resolve the host. + This is 10 minutes, as recommended in RFC 6555 for expiring cached connection + results for dual-stack hosts.*/ +# define OP_RESOLVE_CACHE_TIMEOUT_MS (10*60*(opus_int32)1000) + +/*The number of redirections at which we give up. + The value here is the current default in Firefox. + RFC 2068 mandated a maximum of 5, but RFC 2616 relaxed that to "a client + SHOULD detect infinite redirection loops." + Fortunately, 20 is less than infinity.*/ +# define OP_REDIRECT_LIMIT (20) + +/*The initial size of the buffer used to read a response message (before the + body).*/ +# define OP_RESPONSE_SIZE_MIN (510) +/*The maximum size of a response message (before the body). + Responses larger than this will be discarded. + I've seen a real server return 20 kB of data for a 302 Found response. + Increasing this beyond 32kB will cause problems on platforms with a 16-bit + int.*/ +# define OP_RESPONSE_SIZE_MAX (32766) + +/*The number of milliseconds we will allow a connection to sit idle before we + refuse to resurrect it. + Apache as of 2.2 has reduced its default timeout to 5 seconds (from 15), so + that's what we'll use here.*/ +# define OP_CONNECTION_IDLE_TIMEOUT_MS (5*1000) + +/*The number of milliseconds we will wait to send or receive data before giving + up.*/ +# define OP_POLL_TIMEOUT_MS (30*1000) + +/*We will always attempt to read ahead at least this much in preference to + opening a new connection.*/ +# define OP_READAHEAD_THRESH_MIN (32*(opus_int32)1024) + +/*The amount of data to request after a seek. + This is a trade-off between read throughput after a seek vs. the the ability + to quickly perform another seek with the same connection.*/ +# define OP_PIPELINE_CHUNK_SIZE (32*(opus_int32)1024) +/*Subsequent chunks are requested with larger and larger sizes until they pass + this threshold, after which we just ask for the rest of the resource.*/ +# define OP_PIPELINE_CHUNK_SIZE_MAX (1024*(opus_int32)1024) +/*This is the maximum number of requests we'll make with a single connection. + Many servers will simply disconnect after we attempt some number of requests, + possibly without sending a Connection: close header, meaning we won't + discover it until we try to read beyond the end of the current chunk. + We can reconnect when that happens, but this is slow. + Instead, we impose a limit ourselves (set to the default for Apache + installations and thus likely the most common value in use).*/ +# define OP_PIPELINE_MAX_REQUESTS (100) +/*This should be the number of requests, starting from a chunk size of + OP_PIPELINE_CHUNK_SIZE and doubling each time, until we exceed + OP_PIPELINE_CHUNK_SIZE_MAX and just request the rest of the file. + We won't reuse a connection when seeking unless it has at least this many + requests left, to reduce the chances we'll have to open a new connection + while reading forward afterwards.*/ +# define OP_PIPELINE_MIN_REQUESTS (7) + +/*Is this an https URL? + For now we can simply check the last letter of the scheme.*/ +# define OP_URL_IS_SSL(_url) ((_url)->scheme[4]=='s') + +/*Does this URL use the default port for its scheme?*/ +# define OP_URL_IS_DEFAULT_PORT(_url) \ + (!OP_URL_IS_SSL(_url)&&(_url)->port==80 \ + ||OP_URL_IS_SSL(_url)&&(_url)->port==443) + +struct OpusParsedURL{ + /*Either "http" or "https".*/ + char *scheme; + /*The user name from the <userinfo> component, or NULL.*/ + char *user; + /*The password from the <userinfo> component, or NULL.*/ + char *pass; + /*The <host> component. + This may not be NULL.*/ + char *host; + /*The <path> and <query> components. + This may not be NULL.*/ + char *path; + /*The <port> component. + This is set to the default port if the URL did not contain one.*/ + unsigned port; +}; + +/*Parse a URL. + This code is not meant to be fast: strspn() with large sets is likely to be + slow, but it is very convenient. + It is meant to be RFC 3986-compliant. + We currently do not support IRIs (Internationalized Resource Identifiers, + RFC 3987). + Callers should translate them to URIs first.*/ +static int op_parse_url_impl(OpusParsedURL *_dst,const char *_src){ + const char *scheme_end; + const char *authority; + const char *userinfo_end; + const char *user; + const char *user_end; + const char *pass; + const char *hostport; + const char *hostport_end; + const char *host_end; + const char *port; + opus_int32 port_num; + const char *port_end; + const char *path; + const char *path_end; + const char *uri_end; + scheme_end=_src+strspn(_src,OP_URL_SCHEME); + if(OP_UNLIKELY(*scheme_end!=':') + ||OP_UNLIKELY(scheme_end-_src<4)||OP_UNLIKELY(scheme_end-_src>5) + ||OP_UNLIKELY(op_strncasecmp(_src,"https",scheme_end-_src)!=0)){ + /*Unsupported protocol.*/ + return OP_EIMPL; + } + if(OP_UNLIKELY(scheme_end[1]!='/')||OP_UNLIKELY(scheme_end[2]!='/')){ + /*We require an <authority> component.*/ + return OP_EINVAL; + } + authority=scheme_end+3; + /*Make sure all escape sequences are valid to simplify unescaping later.*/ + if(OP_UNLIKELY(op_validate_url_escapes(authority)<0))return OP_EINVAL; + /*Look for a <userinfo> component.*/ + userinfo_end=authority+strspn(authority,OP_URL_PCHAR_NA); + if(*userinfo_end=='@'){ + /*Found one.*/ + user=authority; + /*Look for a password (yes, clear-text passwords are deprecated, I know, + but what else are people supposed to use? use SSL if you care).*/ + user_end=authority+strspn(authority,OP_URL_PCHAR_BASE); + if(*user_end==':')pass=user_end+1; + else pass=NULL; + hostport=userinfo_end+1; + } + else{ + /*We shouldn't have to initialize user_end, but gcc is too dumb to figure + out that user!=NULL below means we didn't take this else branch.*/ + user=user_end=NULL; + pass=NULL; + hostport=authority; + } + /*Try to figure out where the <host> component ends.*/ + if(hostport[0]=='['){ + hostport++; + /*We have an <IP-literal>, which can contain colons.*/ + hostport_end=host_end=hostport+strspn(hostport,OP_URL_PCHAR_NA); + if(OP_UNLIKELY(*hostport_end++!=']'))return OP_EINVAL; + } + /*Currently we don't support IDNA (RFC 5894), because I don't want to deal + with the policy about which domains should not be internationalized to + avoid confusing similarities. + Give this API Punycode (RFC 3492) domain names instead.*/ + else hostport_end=host_end=hostport+strspn(hostport,OP_URL_PCHAR_BASE); + /*TODO: Validate host.*/ + /*Is there a port number?*/ + port_num=-1; + if(*hostport_end==':'){ + int i; + port=hostport_end+1; + port_end=port+strspn(port,OP_URL_DIGIT); + path=port_end; + /*Not part of RFC 3986, but require port numbers in the range 0...65535.*/ + if(OP_LIKELY(port_end-port>0)){ + while(*port=='0')port++; + if(OP_UNLIKELY(port_end-port>5))return OP_EINVAL; + port_num=0; + for(i=0;i<port_end-port;i++)port_num=port_num*10+port[i]-'0'; + if(OP_UNLIKELY(port_num>65535))return OP_EINVAL; + } + } + else path=hostport_end; + path_end=path+strspn(path,OP_URL_PATH); + /*If the path is not empty, it must begin with a '/'.*/ + if(OP_LIKELY(path_end>path)&&OP_UNLIKELY(path[0]!='/'))return OP_EINVAL; + /*Consume the <query> component, if any (right now we don't split this out + from the <path> component).*/ + if(*path_end=='?')path_end=path_end+strspn(path_end,OP_URL_QUERY_FRAG); + /*Discard the <fragment> component, if any. + This doesn't get sent to the server. + Some day we should add support for Media Fragment URIs + <http://www.w3.org/TR/media-frags/>.*/ + if(*path_end=='#')uri_end=path_end+1+strspn(path_end+1,OP_URL_QUERY_FRAG); + else uri_end=path_end; + /*If there's anything left, this was not a valid URL.*/ + if(OP_UNLIKELY(*uri_end!='\0'))return OP_EINVAL; + _dst->scheme=op_string_range_dup(_src,scheme_end); + if(OP_UNLIKELY(_dst->scheme==NULL))return OP_EFAULT; + op_string_tolower(_dst->scheme); + if(user!=NULL){ + _dst->user=op_string_range_dup(user,user_end); + if(OP_UNLIKELY(_dst->user==NULL))return OP_EFAULT; + op_unescape_url_component(_dst->user); + /*Unescaping might have created a ':' in the username. + That's not allowed by RFC 2617's Basic Authentication Scheme.*/ + if(OP_UNLIKELY(strchr(_dst->user,':')!=NULL))return OP_EINVAL; + } + else _dst->user=NULL; + if(pass!=NULL){ + _dst->pass=op_string_range_dup(pass,userinfo_end); + if(OP_UNLIKELY(_dst->pass==NULL))return OP_EFAULT; + op_unescape_url_component(_dst->pass); + } + else _dst->pass=NULL; + _dst->host=op_string_range_dup(hostport,host_end); + if(OP_UNLIKELY(_dst->host==NULL))return OP_EFAULT; + if(port_num<0){ + if(_src[4]=='s')port_num=443; + else port_num=80; + } + _dst->port=(unsigned)port_num; + /*RFC 2616 says an empty <abs-path> component is equivalent to "/", and we + MUST use the latter in the Request-URI. + Reserve space for the slash here.*/ + if(path==path_end||path[0]=='?')path--; + _dst->path=op_string_range_dup(path,path_end); + if(OP_UNLIKELY(_dst->path==NULL))return OP_EFAULT; + /*And force-set it here.*/ + _dst->path[0]='/'; + return 0; +} + +static void op_parsed_url_init(OpusParsedURL *_url){ + memset(_url,0,sizeof(*_url)); +} + +static void op_parsed_url_clear(OpusParsedURL *_url){ + _ogg_free(_url->scheme); + _ogg_free(_url->user); + _ogg_free(_url->pass); + _ogg_free(_url->host); + _ogg_free(_url->path); +} + +static int op_parse_url(OpusParsedURL *_dst,const char *_src){ + OpusParsedURL url; + int ret; + op_parsed_url_init(&url); + ret=op_parse_url_impl(&url,_src); + if(OP_UNLIKELY(ret<0))op_parsed_url_clear(&url); + else *_dst=*&url; + return ret; +} + +/*A buffer to hold growing strings. + The main purpose of this is to consolidate allocation checks and simplify + cleanup on a failed allocation.*/ +struct OpusStringBuf{ + char *buf; + int nbuf; + int cbuf; +}; + +static void op_sb_init(OpusStringBuf *_sb){ + _sb->buf=NULL; + _sb->nbuf=0; + _sb->cbuf=0; +} + +static void op_sb_clear(OpusStringBuf *_sb){ + _ogg_free(_sb->buf); +} + +/*Make sure we have room for at least _capacity characters (plus 1 more for the + terminating NUL).*/ +static int op_sb_ensure_capacity(OpusStringBuf *_sb,int _capacity){ + char *buf; + int cbuf; + buf=_sb->buf; + cbuf=_sb->cbuf; + if(_capacity>=cbuf-1){ + if(OP_UNLIKELY(cbuf>INT_MAX-1>>1))return OP_EFAULT; + if(OP_UNLIKELY(_capacity>=INT_MAX-1))return OP_EFAULT; + cbuf=OP_MAX(2*cbuf+1,_capacity+1); + buf=_ogg_realloc(buf,sizeof(*buf)*cbuf); + if(OP_UNLIKELY(buf==NULL))return OP_EFAULT; + _sb->buf=buf; + _sb->cbuf=cbuf; + } + return 0; +} + +/*Increase the capacity of the buffer, but not to more than _max_size + characters (plus 1 more for the terminating NUL).*/ +static int op_sb_grow(OpusStringBuf *_sb,int _max_size){ + char *buf; + int cbuf; + buf=_sb->buf; + cbuf=_sb->cbuf; + OP_ASSERT(_max_size<=INT_MAX-1); + cbuf=cbuf<=_max_size-1>>1?2*cbuf+1:_max_size+1; + buf=_ogg_realloc(buf,sizeof(*buf)*cbuf); + if(OP_UNLIKELY(buf==NULL))return OP_EFAULT; + _sb->buf=buf; + _sb->cbuf=cbuf; + return 0; +} + +static int op_sb_append(OpusStringBuf *_sb,const char *_s,int _len){ + char *buf; + int nbuf; + int ret; + nbuf=_sb->nbuf; + if(OP_UNLIKELY(nbuf>INT_MAX-_len))return OP_EFAULT; + ret=op_sb_ensure_capacity(_sb,nbuf+_len); + if(OP_UNLIKELY(ret<0))return ret; + buf=_sb->buf; + memcpy(buf+nbuf,_s,sizeof(*buf)*_len); + nbuf+=_len; + buf[nbuf]='\0'; + _sb->nbuf=nbuf; + return 0; +} + +static int op_sb_append_string(OpusStringBuf *_sb,const char *_s){ + return op_sb_append(_sb,_s,strlen(_s)); +} + +static int op_sb_append_port(OpusStringBuf *_sb,unsigned _port){ + char port_buf[7]; + OP_ASSERT(_port<=65535U); + sprintf(port_buf,":%u",_port); + return op_sb_append_string(_sb,port_buf); +} + +static int op_sb_append_nonnegative_int64(OpusStringBuf *_sb,opus_int64 _i){ + char digit; + int nbuf_start; + int ret; + OP_ASSERT(_i>=0); + nbuf_start=_sb->nbuf; + ret=0; + do{ + digit='0'+_i%10; + ret|=op_sb_append(_sb,&digit,1); + _i/=10; + } + while(_i>0); + if(OP_LIKELY(ret>=0)){ + char *buf; + int nbuf_end; + buf=_sb->buf; + nbuf_end=_sb->nbuf-1; + /*We've added the digits backwards. + Reverse them.*/ + while(nbuf_start<nbuf_end){ + digit=buf[nbuf_start]; + buf[nbuf_start]=buf[nbuf_end]; + buf[nbuf_end]=digit; + nbuf_start++; + nbuf_end--; + } + } + return ret; +} + +static struct addrinfo *op_resolve(const char *_host,unsigned _port){ + struct addrinfo *addrs; + struct addrinfo hints; + char service[6]; + memset(&hints,0,sizeof(hints)); + hints.ai_socktype=SOCK_STREAM; +#if defined(AI_NUMERICSERV) + hints.ai_flags=AI_NUMERICSERV; +#endif + OP_ASSERT(_port<=65535U); + sprintf(service,"%u",_port); + if(OP_LIKELY(!getaddrinfo(_host,service,&hints,&addrs)))return addrs; + return NULL; +} + +static int op_sock_set_nonblocking(op_sock _fd,int _nonblocking){ +#if !defined(_WIN32) + int flags; + flags=fcntl(_fd,F_GETFL); + if(OP_UNLIKELY(flags<0))return flags; + if(_nonblocking)flags|=O_NONBLOCK; + else flags&=~O_NONBLOCK; + return fcntl(_fd,F_SETFL,flags); +#else + return ioctl(_fd,FIONBIO,&_nonblocking); +#endif +} + +/*Disable/enable write coalescing if we can. + We always send whole requests at once and always parse the response headers + before sending another one, so normally write coalescing just causes added + delay.*/ +static void op_sock_set_tcp_nodelay(op_sock _fd,int _nodelay){ +# if defined(TCP_NODELAY)&&(defined(IPPROTO_TCP)||defined(SOL_TCP)) +# if defined(IPPROTO_TCP) +# define OP_SO_LEVEL IPPROTO_TCP +# else +# define OP_SO_LEVEL SOL_TCP +# endif + /*It doesn't really matter if this call fails, but it would be interesting + to hit a case where it does.*/ + OP_ALWAYS_TRUE(!setsockopt(_fd,OP_SO_LEVEL,TCP_NODELAY, + &_nodelay,sizeof(_nodelay))); +# endif +} + +#if defined(_WIN32) +static void op_init_winsock(){ + static LONG count; + static WSADATA wsadata; + if(InterlockedIncrement(&count)==1)WSAStartup(0x0202,&wsadata); +} +#endif + +/*A single physical connection to an HTTP server. + We may have several of these open at once.*/ +struct OpusHTTPConn{ + /*The current position indicator for this connection.*/ + opus_int64 pos; + /*The position where the current request will end, or -1 if we're reading + until EOF (an unseekable stream or the initial HTTP/1.0 request).*/ + opus_int64 end_pos; + /*The position where next request we've sent will start, or -1 if we haven't + sent the next request yet.*/ + opus_int64 next_pos; + /*The end of the next request or -1 if we requested the rest of the resource. + This is only set to a meaningful value if next_pos is not -1.*/ + opus_int64 next_end; + /*The SSL connection, if this is https.*/ + SSL *ssl_conn; + /*The next connection in either the LRU or free list.*/ + OpusHTTPConn *next; + /*The last time we blocked for reading from this connection.*/ + struct timeb read_time; + /*The number of bytes we've read since the last time we blocked.*/ + opus_int64 read_bytes; + /*The estimated throughput of this connection, in bytes/s.*/ + opus_int64 read_rate; + /*The socket we're reading from.*/ + op_sock fd; + /*The number of remaining requests we are allowed on this connection.*/ + int nrequests_left; + /*The chunk size to use for pipelining requests.*/ + opus_int32 chunk_size; +}; + +static void op_http_conn_init(OpusHTTPConn *_conn){ + _conn->next_pos=-1; + _conn->ssl_conn=NULL; + _conn->next=NULL; + _conn->fd=OP_INVALID_SOCKET; +} + +static void op_http_conn_clear(OpusHTTPConn *_conn){ + if(_conn->ssl_conn!=NULL)SSL_free(_conn->ssl_conn); + /*SSL frees the BIO for us.*/ + if(_conn->fd!=OP_INVALID_SOCKET)close(_conn->fd); +} + +/*The global stream state.*/ +struct OpusHTTPStream{ + /*The list of connections.*/ + OpusHTTPConn conns[OP_NCONNS_MAX]; + /*The context object used as a framework for TLS/SSL functions.*/ + SSL_CTX *ssl_ctx; + /*The cached session to reuse for future connections.*/ + SSL_SESSION *ssl_session; + /*The LRU list (ordered from MRU to LRU) of currently connected + connections.*/ + OpusHTTPConn *lru_head; + /*The free list.*/ + OpusHTTPConn *free_head; + /*The URL to connect to.*/ + OpusParsedURL url; + /*Information about the address we connected to.*/ + struct addrinfo addr_info; + /*The address we connected to.*/ + union{ + struct sockaddr s; + struct sockaddr_in v4; + struct sockaddr_in6 v6; + } addr; + /*The last time we re-resolved the host.*/ + struct timeb resolve_time; + /*A buffer used to build HTTP requests.*/ + OpusStringBuf request; + /*A buffer used to build proxy CONNECT requests.*/ + OpusStringBuf proxy_connect; + /*A buffer used to receive the response headers.*/ + OpusStringBuf response; + /*The Content-Length, if specified, or -1 otherwise. + This will always be specified for seekable streams.*/ + opus_int64 content_length; + /*The position indicator used when no connection is active.*/ + opus_int64 pos; + /*The host we actually connected to.*/ + char *connect_host; + /*The port we actually connected to.*/ + unsigned connect_port; + /*The connection we're currently reading from. + This can be -1 if no connection is active.*/ + int cur_conni; + /*Whether or not the server supports range requests.*/ + int seekable; + /*Whether or not the server supports HTTP/1.1 with persistent connections.*/ + int pipeline; + /*Whether or not we should skip certificate checks.*/ + int skip_certificate_check; + /*The offset of the tail of the request. + Only the offset in the Range: header appears after this, allowing us to + quickly edit the request to ask for a new range.*/ + int request_tail; + /*The estimated time required to open a new connection, in milliseconds.*/ + opus_int32 connect_rate; +}; + +static void op_http_stream_init(OpusHTTPStream *_stream){ + OpusHTTPConn **pnext; + int ci; + pnext=&_stream->free_head; + for(ci=0;ci<OP_NCONNS_MAX;ci++){ + op_http_conn_init(_stream->conns+ci); + *pnext=_stream->conns+ci; + pnext=&_stream->conns[ci].next; + } + _stream->ssl_ctx=NULL; + _stream->ssl_session=NULL; + _stream->lru_head=NULL; + op_parsed_url_init(&_stream->url); + op_sb_init(&_stream->request); + op_sb_init(&_stream->proxy_connect); + op_sb_init(&_stream->response); + _stream->connect_host=NULL; + _stream->seekable=0; +} + +/*Close the connection and move it to the free list. + _stream: The stream containing the free list. + _conn: The connection to close. + _penxt: The linked-list pointer currently pointing to this connection. + _gracefully: Whether or not to shut down cleanly.*/ +static void op_http_conn_close(OpusHTTPStream *_stream,OpusHTTPConn *_conn, + OpusHTTPConn **_pnext,int _gracefully){ + /*If we don't shut down gracefully, the server MUST NOT re-use our session + according to RFC 2246, because it can't tell the difference between an + abrupt close and a truncation attack. + So we shut down gracefully if we can. + However, we will not wait if this would block (it's not worth the savings + from session resumption to do so). + Clients (that's us) MAY resume a TLS session that ended with an incomplete + close, according to RFC 2818, so there's no reason to make sure the server + shut things down gracefully.*/ + if(_gracefully&&_conn->ssl_conn!=NULL)SSL_shutdown(_conn->ssl_conn); + op_http_conn_clear(_conn); + _conn->next_pos=-1; + _conn->ssl_conn=NULL; + _conn->fd=OP_INVALID_SOCKET; + OP_ASSERT(*_pnext==_conn); + *_pnext=_conn->next; + _conn->next=_stream->free_head; + _stream->free_head=_conn; +} + +static void op_http_stream_clear(OpusHTTPStream *_stream){ + while(_stream->lru_head!=NULL){ + op_http_conn_close(_stream,_stream->lru_head,&_stream->lru_head,0); + } + if(_stream->ssl_session!=NULL)SSL_SESSION_free(_stream->ssl_session); + if(_stream->ssl_ctx!=NULL)SSL_CTX_free(_stream->ssl_ctx); + op_sb_clear(&_stream->response); + op_sb_clear(&_stream->proxy_connect); + op_sb_clear(&_stream->request); + if(_stream->connect_host!=_stream->url.host)_ogg_free(_stream->connect_host); + op_parsed_url_clear(&_stream->url); +} + +static int op_http_conn_write_fully(OpusHTTPConn *_conn, + const char *_buf,int _buf_size){ + struct pollfd fd; + SSL *ssl_conn; + fd.fd=_conn->fd; + ssl_conn=_conn->ssl_conn; + while(_buf_size>0){ + int err; + if(ssl_conn!=NULL){ + int ret; + ret=SSL_write(ssl_conn,_buf,_buf_size); + if(ret>0){ + /*Wrote some data.*/ + _buf+=ret; + _buf_size-=ret; + continue; + } + /*Connection closed.*/ + else if(ret==0)return OP_FALSE; + err=SSL_get_error(ssl_conn,ret); + /*Yes, renegotiations can cause SSL_write() to block for reading.*/ + if(err==SSL_ERROR_WANT_READ)fd.events=POLLIN; + else if(err==SSL_ERROR_WANT_WRITE)fd.events=POLLOUT; + else return OP_FALSE; + } + else{ + ssize_t ret; + op_reset_errno(); + ret=send(fd.fd,_buf,_buf_size,0); + if(ret>0){ + _buf+=ret; + _buf_size-=ret; + continue; + } + err=op_errno(); + if(err!=EAGAIN&&err!=EWOULDBLOCK)return OP_FALSE; + fd.events=POLLOUT; + } + if(poll(&fd,1,OP_POLL_TIMEOUT_MS)<=0)return OP_FALSE; + } + return 0; +} + +static int op_http_conn_estimate_available(OpusHTTPConn *_conn){ + int available; + int ret; + ret=ioctl(_conn->fd,FIONREAD,&available); + if(ret<0)available=0; + /*This requires the SSL read_ahead flag to be unset to work. + We ignore partial records as well as the protocol overhead for any pending + bytes. + This means we might return somewhat less than can truly be read without + blocking (if there's a partial record). + This is okay, because we're using this value to estimate network transfer + time, and we _have_ already received those bytes. + We also might return slightly more (due to protocol overhead), but that's + small enough that it probably doesn't matter.*/ + if(_conn->ssl_conn!=NULL)available+=SSL_pending(_conn->ssl_conn); + return available; +} + +static opus_int32 op_time_diff_ms(const struct timeb *_end, + const struct timeb *_start){ + opus_int64 dtime; + dtime=_end->time-(opus_int64)_start->time; + OP_ASSERT(_end->millitm<1000); + OP_ASSERT(_start->millitm<1000); + if(OP_UNLIKELY(dtime>(OP_INT32_MAX-1000)/1000))return OP_INT32_MAX; + if(OP_UNLIKELY(dtime<(OP_INT32_MIN+1000)/1000))return OP_INT32_MIN; + return (opus_int32)dtime*1000+_end->millitm-_start->millitm; +} + +/*Update the read rate estimate for this connection.*/ +static void op_http_conn_read_rate_update(OpusHTTPConn *_conn){ + struct timeb read_time; + opus_int32 read_delta_ms; + opus_int64 read_delta_bytes; + opus_int64 read_rate; + read_delta_bytes=_conn->read_bytes; + if(read_delta_bytes<=0)return; + ftime(&read_time); + read_delta_ms=op_time_diff_ms(&read_time,&_conn->read_time); + read_rate=_conn->read_rate; + read_delta_ms=OP_MAX(read_delta_ms,1); + read_rate+=read_delta_bytes*1000/read_delta_ms-read_rate+4>>3; + *&_conn->read_time=*&read_time; + _conn->read_bytes=0; + _conn->read_rate=read_rate; +} + +/*Tries to read from the given connection. + [out] _buf: Returns the data read. + _buf_size: The size of the buffer. + _blocking: Whether or not to block until some data is retrieved. + Return: A positive number of bytes read on success. + 0: The read would block, or the connection was closed. + OP_EREAD: There was a fatal read error.*/ +static int op_http_conn_read(OpusHTTPConn *_conn, + char *_buf,int _buf_size,int _blocking){ + struct pollfd fd; + SSL *ssl_conn; + int nread; + int nread_unblocked; + fd.fd=_conn->fd; + ssl_conn=_conn->ssl_conn; + nread=nread_unblocked=0; + /*RFC 2818 says "client implementations MUST treat any premature closes as + errors and the data received as potentially truncated," so we make very + sure to report read errors upwards.*/ + do{ + int err; + if(ssl_conn!=NULL){ + int ret; + ret=SSL_read(ssl_conn,_buf+nread,_buf_size-nread); + OP_ASSERT(ret<=_buf_size-nread); + if(ret>0){ + /*Read some data. + Keep going to see if there's more.*/ + nread+=ret; + nread_unblocked+=ret; + continue; + } + /*If we already read some data, return it right now.*/ + if(nread>0)break; + err=SSL_get_error(ssl_conn,ret); + if(ret==0){ + /*Connection close. + Check for a clean shutdown to prevent truncation attacks. + This check always succeeds for SSLv2, as it has no "close notify" + message and thus can't verify an orderly shutdown.*/ + return err==SSL_ERROR_ZERO_RETURN?0:OP_EREAD; + } + if(err==SSL_ERROR_WANT_READ)fd.events=POLLIN; + /*Yes, renegotiations can cause SSL_read() to block for writing.*/ + else if(err==SSL_ERROR_WANT_WRITE)fd.events=POLLOUT; + /*Some other error.*/ + else return OP_EREAD; + } + else{ + ssize_t ret; + op_reset_errno(); + ret=recv(fd.fd,_buf+nread,_buf_size-nread,0); + OP_ASSERT(ret<=_buf_size-nread); + if(ret>0){ + /*Read some data. + Keep going to see if there's more.*/ + nread+=ret; + nread_unblocked+=ret; + continue; + } + /*If we already read some data or the connection was closed, return + right now.*/ + if(ret==0||nread>0)break; + err=op_errno(); + if(err!=EAGAIN&&err!=EWOULDBLOCK)return OP_EREAD; + fd.events=POLLIN; + } + _conn->read_bytes+=nread_unblocked; + op_http_conn_read_rate_update(_conn); + nread_unblocked=0; + if(!_blocking)break; + /*Need to wait to get any data at all.*/ + if(poll(&fd,1,OP_POLL_TIMEOUT_MS)<=0)return OP_EREAD; + } + while(nread<_buf_size); + _conn->read_bytes+=nread_unblocked; + return nread; +} + +/*Tries to look at the pending data for a connection without consuming it. + [out] _buf: Returns the data at which we're peeking. + _buf_size: The size of the buffer.*/ +static int op_http_conn_peek(OpusHTTPConn *_conn,char *_buf,int _buf_size){ + struct pollfd fd; + SSL *ssl_conn; + int ret; + fd.fd=_conn->fd; + ssl_conn=_conn->ssl_conn; + for(;;){ + int err; + if(ssl_conn!=NULL){ + ret=SSL_peek(ssl_conn,_buf,_buf_size); + /*Either saw some data or the connection was closed.*/ + if(ret>=0)return ret; + err=SSL_get_error(ssl_conn,ret); + if(err==SSL_ERROR_WANT_READ)fd.events=POLLIN; + /*Yes, renegotiations can cause SSL_peek() to block for writing.*/ + else if(err==SSL_ERROR_WANT_WRITE)fd.events=POLLOUT; + else return 0; + } + else{ + op_reset_errno(); + ret=(int)recv(fd.fd,_buf,_buf_size,MSG_PEEK); + /*Either saw some data or the connection was closed.*/ + if(ret>=0)return ret; + err=op_errno(); + if(err!=EAGAIN&&err!=EWOULDBLOCK)return 0; + fd.events=POLLIN; + } + /*Need to wait to get any data at all.*/ + if(poll(&fd,1,OP_POLL_TIMEOUT_MS)<=0)return 0; + } +} + +/*When parsing response headers, RFC 2616 mandates that all lines end in CR LF. + However, even in the year 2012, I have seen broken servers use just a LF. + This is the evil that Postel's advice from RFC 761 breeds.*/ + +/*Reads the entirety of a response to an HTTP request into the response buffer. + Actual parsing and validation is done later. + Return: The number of bytes in the response on success, OP_EREAD if the + connection was closed before reading any data, or another negative + value on any other error.*/ +static int op_http_conn_read_response(OpusHTTPConn *_conn, + OpusStringBuf *_response){ + int ret; + _response->nbuf=0; + ret=op_sb_ensure_capacity(_response,OP_RESPONSE_SIZE_MIN); + if(OP_UNLIKELY(ret<0))return ret; + for(;;){ + char *buf; + int size; + int capacity; + int read_limit; + int terminated; + size=_response->nbuf; + capacity=_response->cbuf-1; + if(OP_UNLIKELY(size>=capacity)){ + ret=op_sb_grow(_response,OP_RESPONSE_SIZE_MAX); + if(OP_UNLIKELY(ret<0))return ret; + capacity=_response->cbuf-1; + /*The response was too large. + This prevents a bad server from running us out of memory.*/ + if(OP_UNLIKELY(size>=capacity))return OP_EIMPL; + } + buf=_response->buf; + ret=op_http_conn_peek(_conn,buf+size,capacity-size); + if(OP_UNLIKELY(ret<=0))return size<=0?OP_EREAD:OP_FALSE; + /*We read some data.*/ + /*Make sure the starting characters are "HTTP". + Otherwise we could wind up waiting forever for a response from + something that is not an HTTP server.*/ + if(size<4&&op_strncasecmp(buf,"HTTP",OP_MIN(size+ret,4))!=0){ + return OP_FALSE; + } + /*How far can we read without passing the "\r\n\r\n" terminator?*/ + buf[size+ret]='\0'; + terminated=0; + for(read_limit=OP_MAX(size-3,0);read_limit<size+ret;read_limit++){ + /*We don't look for the leading '\r' thanks to broken servers.*/ + if(buf[read_limit]=='\n'){ + if(buf[read_limit+1]=='\r'&&OP_LIKELY(buf[read_limit+2]=='\n')){ + terminated=3; + break; + } + /*This case is for broken servers.*/ + else if(OP_UNLIKELY(buf[read_limit+1]=='\n')){ + terminated=2; + break; + } + } + } + read_limit+=terminated; + OP_ASSERT(size<=read_limit); + OP_ASSERT(read_limit<=size+ret); + /*Actually consume that data.*/ + ret=op_http_conn_read(_conn,buf+size,read_limit-size,1); + if(OP_UNLIKELY(ret<=0))return OP_FALSE; + size+=ret; + buf[size]='\0'; + _response->nbuf=size; + /*We found the terminator and read all the data up to and including it.*/ + if(terminated&&OP_LIKELY(size>=read_limit))return size; + } + return OP_EIMPL; +} + +# define OP_HTTP_DIGIT "0123456789" + +/*The Reason-Phrase is not allowed to contain control characters, except + horizontal tab (HT: \011).*/ +# define OP_HTTP_CREASON_PHRASE \ + "\001\002\003\004\005\006\007\010\012\013\014\015\016\017\020\021" \ + "\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177" + +# define OP_HTTP_CTLS \ + "\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020" \ + "\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177" + +/*This also includes '\t', but we get that from OP_HTTP_CTLS.*/ +# define OP_HTTP_SEPARATORS " \"(),/:;<=>?@[\\]{}" + +/*TEXT can also include LWS, but that has structure, so we parse it + separately.*/ +# define OP_HTTP_CTOKEN OP_HTTP_CTLS OP_HTTP_SEPARATORS + +/*Return: The amount of linear white space (LWS) at the start of _s.*/ +static int op_http_lwsspn(const char *_s){ + int i; + for(i=0;;){ + if(_s[0]=='\r'&&_s[1]=='\n'&&(_s[2]=='\t'||_s[2]==' '))i+=3; + /*This case is for broken servers.*/ + else if(_s[0]=='\n'&&(_s[1]=='\t'||_s[1]==' '))i+=2; + else if(_s[i]=='\t'||_s[i]==' ')i++; + else return i; + } +} + +static char *op_http_parse_status_line(int *_v1_1_compat, + char **_status_code,char *_response){ + char *next; + char *status_code; + int v1_1_compat; + size_t d; + /*RFC 2616 Section 6.1 does not say that the tokens in the Status-Line cannot + be separated by optional LWS, but since it specifically calls out where + spaces are to be placed and that CR and LF are not allowed except at the + end, I am assuming this to be true.*/ + /*We already validated that this starts with "HTTP"*/ + OP_ASSERT(op_strncasecmp(_response,"HTTP",4)==0); + next=_response+4; + if(OP_UNLIKELY(*next++!='/'))return NULL; + d=strspn(next,OP_HTTP_DIGIT); + /*"Leading zeros MUST be ignored by recipients."*/ + while(*next=='0'){ + next++; + OP_ASSERT(d>0); + d--; + } + /*We only support version 1.x*/ + if(OP_UNLIKELY(d!=1)||OP_UNLIKELY(*next++!='1'))return NULL; + if(OP_UNLIKELY(*next++!='.'))return NULL; + d=strspn(next,OP_HTTP_DIGIT); + if(OP_UNLIKELY(d<=0))return NULL; + /*"Leading zeros MUST be ignored by recipients."*/ + while(*next=='0'){ + next++; + OP_ASSERT(d>0); + d--; + } + /*We don't need to parse the version number. + Any non-zero digit means it's greater than 1.*/ + v1_1_compat=d>0; + next+=d; + if(OP_UNLIKELY(*next++!=' '))return NULL; + status_code=next; + d=strspn(next,OP_HTTP_DIGIT); + if(OP_UNLIKELY(d!=3))return NULL; + next+=d; + /*The Reason-Phrase can be empty, but the space must be here.*/ + if(OP_UNLIKELY(*next++!=' '))return NULL; + next+=strcspn(next,OP_HTTP_CREASON_PHRASE); + /*We are not mandating this be present thanks to broken servers.*/ + if(OP_LIKELY(*next=='\r'))next++; + if(OP_UNLIKELY(*next++!='\n'))return NULL; + if(_v1_1_compat!=NULL)*_v1_1_compat=v1_1_compat; + *_status_code=status_code; + return next; +} + +/*Get the next response header. + [out] _header: The header token, NUL-terminated, with leading and trailing + whitespace stripped, and converted to lower case (to simplify + case-insensitive comparisons), or NULL if there are no more + response headers. + [out] _cdr: The remaining contents of the header, excluding the initial + colon (':') and the terminating CRLF ("\r\n"), + NUL-terminated, and with leading and trailing whitespace + stripped, or NULL if there are no more response headers. + [inout] _s: On input, this points to the start of the current line of the + response headers. + On output, it points to the start of the first line following + this header, or NULL if there are no more response headers. + Return: 0 on success, or a negative value on failure.*/ +static int op_http_get_next_header(char **_header,char **_cdr,char **_s){ + char *header; + char *header_end; + char *cdr; + char *cdr_end; + char *next; + size_t d; + next=*_s; + /*The second case is for broken servers.*/ + if(next[0]=='\r'&&next[1]=='\n'||OP_UNLIKELY(next[0]=='\n')){ + /*No more headers.*/ + *_header=NULL; + *_cdr=NULL; + *_s=NULL; + return 0; + } + header=next+op_http_lwsspn(next); + d=strcspn(header,OP_HTTP_CTOKEN); + if(OP_UNLIKELY(d<=0))return OP_FALSE; + header_end=header+d; + next=header_end+op_http_lwsspn(header_end); + if(OP_UNLIKELY(*next++!=':'))return OP_FALSE; + next+=op_http_lwsspn(next); + cdr=next; + do{ + cdr_end=next+strcspn(next,OP_HTTP_CTLS); + next=cdr_end+op_http_lwsspn(cdr_end); + } + while(next>cdr_end); + /*We are not mandating this be present thanks to broken servers.*/ + if(OP_LIKELY(*next=='\r'))next++; + if(OP_UNLIKELY(*next++!='\n'))return OP_FALSE; + *header_end='\0'; + *cdr_end='\0'; + /*Field names are case-insensitive.*/ + op_string_tolower(header); + *_header=header; + *_cdr=cdr; + *_s=next; + return 0; +} + +static opus_int64 op_http_parse_nonnegative_int64(const char **_next, + const char *_cdr){ + const char *next; + opus_int64 ret; + int i; + next=_cdr+strspn(_cdr,OP_HTTP_DIGIT); + *_next=next; + if(OP_UNLIKELY(next<=_cdr))return OP_FALSE; + while(*_cdr=='0')_cdr++; + if(OP_UNLIKELY(next-_cdr>19))return OP_EIMPL; + ret=0; + for(i=0;i<next-_cdr;i++){ + int digit; + digit=_cdr[i]-'0'; + /*Check for overflow.*/ + if(OP_UNLIKELY(ret>(OP_INT64_MAX-9)/10+(digit<=7)))return OP_EIMPL; + ret=ret*10+digit; + } + return ret; +} + +static opus_int64 op_http_parse_content_length(const char *_cdr){ + const char *next; + opus_int64 content_length; + content_length=op_http_parse_nonnegative_int64(&next,_cdr); + if(OP_UNLIKELY(*next!='\0'))return OP_FALSE; + return content_length; +} + +static int op_http_parse_content_range(opus_int64 *_first,opus_int64 *_last, + opus_int64 *_length,const char *_cdr){ + opus_int64 first; + opus_int64 last; + opus_int64 length; + size_t d; + if(OP_UNLIKELY(op_strncasecmp(_cdr,"bytes",5)!=0))return OP_FALSE; + _cdr+=5; + d=op_http_lwsspn(_cdr); + if(OP_UNLIKELY(d<=0))return OP_FALSE; + _cdr+=d; + if(*_cdr!='*'){ + first=op_http_parse_nonnegative_int64(&_cdr,_cdr); + if(OP_UNLIKELY(first<0))return (int)first; + _cdr+=op_http_lwsspn(_cdr); + if(*_cdr++!='-')return OP_FALSE; + _cdr+=op_http_lwsspn(_cdr); + last=op_http_parse_nonnegative_int64(&_cdr,_cdr); + if(OP_UNLIKELY(last<0))return (int)last; + _cdr+=op_http_lwsspn(_cdr); + } + else{ + /*This is for a 416 response (Requested range not satisfiable).*/ + first=last=-1; + _cdr++; + } + if(OP_UNLIKELY(*_cdr++!='/'))return OP_FALSE; + if(*_cdr!='*'){ + length=op_http_parse_nonnegative_int64(&_cdr,_cdr); + if(OP_UNLIKELY(length<0))return (int)length; + } + else{ + /*The total length is unspecified.*/ + _cdr++; + length=-1; + } + if(OP_UNLIKELY(*_cdr!='\0'))return OP_FALSE; + if(OP_UNLIKELY(last<first))return OP_FALSE; + if(length>=0&&OP_UNLIKELY(last>=length))return OP_FALSE; + *_first=first; + *_last=last; + *_length=length; + return 0; +} + +/*Parse the Connection response header and look for a "close" token. + Return: 1 if a "close" token is found, 0 if it's not found, and a negative + value on error.*/ +static int op_http_parse_connection(char *_cdr){ + size_t d; + int ret; + ret=0; + for(;;){ + d=strcspn(_cdr,OP_HTTP_CTOKEN); + if(OP_UNLIKELY(d<=0))return OP_FALSE; + if(op_strncasecmp(_cdr,"close",(int)d)==0)ret=1; + /*We're supposed to strip and ignore any headers mentioned in the + Connection header if this response is from an HTTP/1.0 server (to + work around forwarding of hop-by-hop headers by old proxies), but the + only hop-by-hop header we look at is Connection itself. + Everything else is a well-defined end-to-end header, and going back and + undoing the things we did based on already-examined headers would be + hard (since we only scan them once, in a destructive manner). + Therefore we just ignore all the other tokens.*/ + _cdr+=d; + d=op_http_lwsspn(_cdr); + if(d<=0)break; + _cdr+=d; + } + return OP_UNLIKELY(*_cdr!='\0')?OP_FALSE:ret; +} + +typedef int (*op_ssl_step_func)(SSL *_ssl_conn); + +/*Try to run an SSL function to completion (blocking if necessary).*/ +static int op_do_ssl_step(SSL *_ssl_conn,op_sock _fd,op_ssl_step_func _step){ + struct pollfd fd; + fd.fd=_fd; + for(;;){ + int ret; + int err; + ret=(*_step)(_ssl_conn); + if(ret>=0)return ret; + err=SSL_get_error(_ssl_conn,ret); + if(err==SSL_ERROR_WANT_READ)fd.events=POLLIN; + else if(err==SSL_ERROR_WANT_WRITE)fd.events=POLLOUT; + else return OP_FALSE; + if(poll(&fd,1,OP_POLL_TIMEOUT_MS)<=0)return OP_FALSE; + } +} + +/*Implement a BIO type that just indicates every operation should be retried. + We use this when initializing an SSL connection via a proxy to allow the + initial handshake to proceed all the way up to the first read attempt, and + then return. + This allows the TLS client hello message to be pipelined with the HTTP + CONNECT request.*/ + +static int op_bio_retry_write(BIO *_b,const char *_buf,int _num){ + (void)_buf; + (void)_num; + BIO_clear_retry_flags(_b); + BIO_set_retry_write(_b); + return -1; +} + +static int op_bio_retry_read(BIO *_b,char *_buf,int _num){ + (void)_buf; + (void)_num; + BIO_clear_retry_flags(_b); + BIO_set_retry_read(_b); + return -1; +} + +static int op_bio_retry_puts(BIO *_b,const char *_str){ + return op_bio_retry_write(_b,_str,0); +} + +static long op_bio_retry_ctrl(BIO *_b,int _cmd,long _num,void *_ptr){ + long ret; + (void)_b; + (void)_num; + (void)_ptr; + ret=0; + switch(_cmd){ + case BIO_CTRL_RESET: + case BIO_C_RESET_READ_REQUEST:{ + BIO_clear_retry_flags(_b); + /*Fall through.*/ + } + case BIO_CTRL_EOF: + case BIO_CTRL_SET: + case BIO_CTRL_SET_CLOSE: + case BIO_CTRL_FLUSH: + case BIO_CTRL_DUP:{ + ret=1; + }break; + } + return ret; +} + +static int op_bio_retry_new(BIO *_b){ + _b->init=1; + _b->num=0; + _b->ptr=NULL; + return 1; +} + +static int op_bio_retry_free(BIO *_b){ + return _b!=NULL; +} + +/*This is not const because OpenSSL doesn't allow it, even though it won't + write to it.*/ +static BIO_METHOD op_bio_retry_method={ + BIO_TYPE_NULL, + "retry", + op_bio_retry_write, + op_bio_retry_read, + op_bio_retry_puts, + NULL, + op_bio_retry_ctrl, + op_bio_retry_new, + op_bio_retry_free, + NULL +}; + +/*Establish a CONNECT tunnel and pipeline the start of the TLS handshake for + proxying https URL requests.*/ +static int op_http_conn_establish_tunnel(OpusHTTPStream *_stream, + OpusHTTPConn *_conn,op_sock _fd,SSL *_ssl_conn,BIO *_ssl_bio){ + BIO *retry_bio; + char *status_code; + char *next; + int ret; + _conn->ssl_conn=NULL; + _conn->fd=_fd; + OP_ASSERT(_stream->proxy_connect.nbuf>0); + ret=op_http_conn_write_fully(_conn, + _stream->proxy_connect.buf,_stream->proxy_connect.nbuf); + if(OP_UNLIKELY(ret<0))return ret; + retry_bio=BIO_new(&op_bio_retry_method); + if(OP_UNLIKELY(retry_bio==NULL))return OP_EFAULT; + SSL_set_bio(_ssl_conn,retry_bio,_ssl_bio); + SSL_set_connect_state(_ssl_conn); + /*This shouldn't succeed, since we can't read yet.*/ + OP_ALWAYS_TRUE(SSL_connect(_ssl_conn)<0); + SSL_set_bio(_ssl_conn,_ssl_bio,_ssl_bio); + /*Only now do we disable write coalescing, to allow the CONNECT + request and the start of the TLS handshake to be combined.*/ + op_sock_set_tcp_nodelay(_fd,1); + ret=op_http_conn_read_response(_conn,&_stream->response); + if(OP_UNLIKELY(ret<0))return ret; + next=op_http_parse_status_line(NULL,&status_code,_stream->response.buf); + /*According to RFC 2817, "Any successful (2xx) response to a + CONNECT request indicates that the proxy has established a + connection to the requested host and port.*/ + if(OP_UNLIKELY(next==NULL)||OP_UNLIKELY(status_code[0]!='2'))return OP_FALSE; + return 0; +} + +/*Match a host name against a host with a possible wildcard pattern according + to the rules of RFC 6125 Section 6.4.3. + Return: 0 if the pattern doesn't match, and a non-zero value if it does.*/ +static int op_http_hostname_match(const char *_host,size_t _host_len, + ASN1_STRING *_pattern){ + const char *pattern; + size_t host_label_len; + size_t host_suffix_len; + size_t pattern_len; + size_t pattern_label_len; + size_t pattern_prefix_len; + size_t pattern_suffix_len; + pattern=(const char *)ASN1_STRING_data(_pattern); + pattern_len=strlen(pattern); + /*Check the pattern for embedded NULs.*/ + if(OP_UNLIKELY(pattern_len!=(size_t)ASN1_STRING_length(_pattern)))return 0; + pattern_label_len=strcspn(pattern,"."); + OP_ASSERT(pattern_label_len<=pattern_len); + pattern_prefix_len=strcspn(pattern,"*"); + if(pattern_prefix_len>=pattern_label_len){ + /*"The client SHOULD NOT attempt to match a presented identifier in which + the wildcard character comprises a label other than the left-most label + (e.g., do not match bar.*.example.net)." [RFC 6125 Section 6.4.3]*/ + if(pattern_prefix_len<pattern_len)return 0; + /*If the pattern does not contain a wildcard in the first element, do an + exact match. + Don't use the system strcasecmp here, as that uses the locale and + RFC 4343 makes clear that DNS's case-insensitivity only applies to + the ASCII range.*/ + return _host_len==pattern_len&&op_strncasecmp(_host,pattern,_host_len)==0; + } + /*"However, the client SHOULD NOT attempt to match a presented identifier + where the wildcard character is embedded within an A-label or U-label of + an internationalized domain name." [RFC 6125 Section 6.4.3]*/ + if(op_strncasecmp(pattern,"xn--",4)==0)return 0; + host_label_len=strcspn(_host,"."); + /*Make sure the host has at least two dots, to prevent the wildcard match + from being ridiculously wide. + We should have already checked to ensure it had at least one.*/ + if(OP_UNLIKELY(_host[host_label_len]!='.') + ||strchr(_host+host_label_len+1,'.')==NULL){ + return 0; + } + OP_ASSERT(host_label_len<_host_len); + /*"If the wildcard character is the only character of the left-most label in + the presented identifier, the client SHOULD NOT compare against anything + but the left-most label of the reference identifier (e.g., *.example.com + would match foo.example.com but not bar.foo.example.com)." [RFC 6125 + Section 6.4.3] + This is really confusingly worded, as we check this by actually comparing + the rest of the pattern for an exact match. + We also use the fact that the wildcard must match at least one character, + so the left-most label of the hostname must be at least as large as the + left-most label of the pattern.*/ + if(host_label_len<pattern_label_len)return 0; + OP_ASSERT(pattern[pattern_prefix_len]=='*'); + /*"The client MAY match a presented identifier in which the wildcard + character is not the only character of the label (e.g., baz*.example.net + and *baz.example.net and b*z.example.net would be taken to match + baz1.example.net and foobaz.example.net and buzz.example.net, + respectively)." [RFC 6125 Section 6.4.3]*/ + pattern_suffix_len=pattern_len-pattern_prefix_len-1; + host_suffix_len=_host_len-host_label_len + +pattern_label_len-pattern_prefix_len-1; + return pattern_suffix_len==host_suffix_len + &&op_strncasecmp(_host,pattern,pattern_prefix_len)==0 + &&op_strncasecmp(_host+_host_len-host_suffix_len, + pattern+pattern_prefix_len+1,host_suffix_len)==0; +} + +/*Convert a host to a numeric address, if possible. + Return: A struct addrinfo containing the address, if it was numeric, and NULL + otherise.*/ +static struct addrinfo *op_inet_pton(const char *_host){ + struct addrinfo *addrs; + struct addrinfo hints; + memset(&hints,0,sizeof(hints)); + hints.ai_socktype=SOCK_STREAM; + hints.ai_flags=AI_NUMERICHOST; + if(!getaddrinfo(_host,NULL,&hints,&addrs))return addrs; + return NULL; +} + +/*Verify the server's hostname matches the certificate they presented using + the procedure from Section 6 of RFC 6125. + Return: 0 if the certificate doesn't match, and a non-zero value if it does.*/ +static int op_http_verify_hostname(OpusHTTPStream *_stream,SSL *_ssl_conn){ + X509 *peer_cert; + STACK_OF(GENERAL_NAME) *san_names; + char *host; + size_t host_len; + int ret; + host=_stream->url.host; + host_len=strlen(host); + peer_cert=SSL_get_peer_certificate(_ssl_conn); + /*We set VERIFY_PEER, so we shouldn't get here without a certificate.*/ + if(OP_UNLIKELY(peer_cert==NULL))return 0; + ret=0; + OP_ASSERT(host_len<INT_MAX); + /*RFC 2818 says (after correcting for Eratta 1077): "If a subjectAltName + extension of type dNSName is present, that MUST be used as the identity. + Otherwise, the (most specific) Common Name field in the Subject field of + the certificate MUST be used. + Although the use of the Common Name is existing practice, it is deprecated + and Certification Authorities are encouraged to use the dNSName + instead." + "Matching is performed using the matching rules specified by RFC 2459. + If more than one identity of a given type is present in the certificate + (e.g., more than one dNSName name), a match in any one of the set is + considered acceptable. + Names may contain the wildcard character * which is condered to match any + single domain name component or component fragment. + E.g., *.a.com matches foo.a.com but not bar.foo.a.com. + f*.com matches foo.com but not bar.com." + "In some cases, the URI is specified as an IP address rather than a + hostname. + In this case, the iPAddress subjectAltName must be present in the + certificate and must exactly match the IP in the URI."*/ + san_names=X509_get_ext_d2i(peer_cert,NID_subject_alt_name,NULL,NULL); + if(san_names!=NULL){ + struct addrinfo *addr; + unsigned char *ip; + int ip_len; + int nsan_names; + int sni; + /*Check to see if the host was specified as a simple IP address.*/ + addr=op_inet_pton(host); + ip=NULL; + ip_len=0; + if(addr!=NULL){ + switch(addr->ai_family){ + case AF_INET:{ + struct sockaddr_in *s; + s=(struct sockaddr_in *)addr->ai_addr; + OP_ASSERT(addr->ai_addrlen>=sizeof(*s)); + ip=(unsigned char *)&s->sin_addr; + ip_len=sizeof(s->sin_addr); + }break; + case AF_INET6:{ + struct sockaddr_in6 *s; + s=(struct sockaddr_in6 *)addr->ai_addr; + OP_ASSERT(addr->ai_addrlen>=sizeof(*s)); + ip=(unsigned char *)&s->sin6_addr; + ip_len=sizeof(s->sin6_addr); + }break; + } + } + /*We can only verify fully-qualified domain names. + To quote RFC 6125: "The extracted data MUST include only information that + can be securely parsed out of the inputs (e.g., parsing the fully + qualified DNS domain name out of the "host" component (or its + equivalent) of a URI or deriving the application service type from the + scheme of a URI) ..." + We don't have a way to check (without relying on DNS records, which might + be subverted) if this address is fully-qualified. + This is particularly problematic when using a CONNECT tunnel, as it is + the server that does DNS lookup, not us. + However, we are certain that if the hostname has no '.', it is definitely + not a fully-qualified domain name (with the exception of crazy TLDs that + actually resolve, like "uz", but I am willing to ignore those). + RFC 1535 says "...in any event where a '.' exists in a specified name it + should be assumed to be a fully qualified domain name (FQDN) and SHOULD + be tried as a rooted name first." + That doesn't give us any security guarantees, of course (a subverted DNS + could fail the original query and our resolver might still retry with a + local domain appended). + If we don't have a FQDN, just set the number of names to 0, so we'll fail + and clean up any resources we allocated.*/ + if(ip==NULL&&strchr(host,'.')==NULL)nsan_names=0; + /*RFC 2459 says there MUST be at least one, but we don't depend on it.*/ + else nsan_names=sk_GENERAL_NAME_num(san_names); + for(sni=0;sni<nsan_names;sni++){ + const GENERAL_NAME *name; + name=sk_GENERAL_NAME_value(san_names,sni); + if(ip==NULL){ + if(name->type==GEN_DNS + &&op_http_hostname_match(host,host_len,name->d.dNSName)){ + ret=1; + break; + } + } + else if(name->type==GEN_IPADD){ + unsigned char *cert_ip; + /*If we do have an IP address, compare it directly. + RFC 6125: "When the reference identity is an IP address, the identity + MUST be converted to the 'network byte order' octet string + representation. + For IP Version 4, as specified in RFC 791, the octet string will + contain exactly four octets. + For IP Version 6, as specified in RFC 2460, the octet string will + contain exactly sixteen octets. + This octet string is then compared against subjectAltName values of + type iPAddress. + A match occurs if the reference identity octet string and the value + octet strings are identical."*/ + cert_ip=ASN1_STRING_data(name->d.iPAddress); + if(ip_len==ASN1_STRING_length(name->d.iPAddress) + &&memcmp(ip,cert_ip,ip_len)==0){ + ret=1; + break; + } + } + } + sk_GENERAL_NAME_pop_free(san_names,GENERAL_NAME_free); + if(addr!=NULL)freeaddrinfo(addr); + } + /*Do the same FQDN check we did above. + We don't do this once in advance for both cases, because in the + subjectAltName case we might have an IPv6 address without a dot.*/ + else if(strchr(host,'.')!=NULL){ + int last_cn_loc; + int cn_loc; + /*If there is no subjectAltName, match against commonName. + RFC 6125 says that at least one significant CA is known to issue certs + with multiple CNs, although it SHOULD NOT. + It also says: "The server's identity may also be verified by comparing + the reference identity to the Common Name (CN) value in the last + Relative Distinguished Name (RDN) of the subject field of the server's + certificate (where "last" refers to the DER-encoded order...)." + So find the last one and check it.*/ + cn_loc=-1; + do{ + last_cn_loc=cn_loc; + cn_loc=X509_NAME_get_index_by_NID(X509_get_subject_name(peer_cert), + NID_commonName,last_cn_loc); + } + while(cn_loc>=0); + ret=last_cn_loc>=0 + &&op_http_hostname_match(host,host_len, + X509_NAME_ENTRY_get_data( + X509_NAME_get_entry(X509_get_subject_name(peer_cert),last_cn_loc))); + } + X509_free(peer_cert); + return ret; +} + +/*Perform the TLS handshake on a new connection.*/ +static int op_http_conn_start_tls(OpusHTTPStream *_stream,OpusHTTPConn *_conn, + op_sock _fd,SSL *_ssl_conn){ + SSL_SESSION *ssl_session; + BIO *ssl_bio; + int skip_certificate_check; + int ret; + ssl_bio=BIO_new_socket(_fd,BIO_NOCLOSE); + if(OP_LIKELY(ssl_bio==NULL))return OP_FALSE; +# if !defined(OPENSSL_NO_TLSEXT) + /*Support for RFC 6066 Server Name Indication.*/ + SSL_set_tlsext_host_name(_ssl_conn,_stream->url.host); +# endif + /*Resume a previous session if available.*/ + if(_stream->ssl_session!=NULL){ + SSL_set_session(_ssl_conn,_stream->ssl_session); + } + /*If we're proxying, establish the CONNECT tunnel.*/ + if(_stream->proxy_connect.nbuf>0){ + ret=op_http_conn_establish_tunnel(_stream,_conn, + _fd,_ssl_conn,ssl_bio); + if(OP_UNLIKELY(ret<0))return ret; + } + else{ + /*Otherwise, just use this socket directly.*/ + op_sock_set_tcp_nodelay(_fd,1); + SSL_set_bio(_ssl_conn,ssl_bio,ssl_bio); + SSL_set_connect_state(_ssl_conn); + } + ret=op_do_ssl_step(_ssl_conn,_fd,SSL_connect); + if(OP_UNLIKELY(ret<=0))return OP_FALSE; + ssl_session=_stream->ssl_session; + skip_certificate_check=_stream->skip_certificate_check; + if(ssl_session==NULL||!skip_certificate_check){ + ret=op_do_ssl_step(_ssl_conn,_fd,SSL_do_handshake); + if(OP_UNLIKELY(ret<=0))return OP_FALSE; + /*OpenSSL does not do hostname verification, despite the fact that we just + passed it the hostname above in the call to SSL_set_tlsext_host_name(), + because they are morons. + Do it for them.*/ + if(!skip_certificate_check&&!op_http_verify_hostname(_stream,_ssl_conn)){ + return OP_FALSE; + } + if(ssl_session==NULL){ + /*Save the session for later resumption.*/ + _stream->ssl_session=SSL_get1_session(_ssl_conn); + } + } + _conn->ssl_conn=_ssl_conn; + _conn->fd=_fd; + _conn->nrequests_left=OP_PIPELINE_MAX_REQUESTS; + return 0; +} + +/*Try to start a connection to the next address in the given list of a given + type. + _fd: The socket to connect with. + [inout] _addr: A pointer to the list of addresses. + This will be advanced to the first one that matches the given + address family (possibly the current one). + _ai_family: The address family to connect to. + Return: 1 If the connection was successful. + 0 If the connection is in progress. + OP_FALSE If the connection failed and there were no more addresses + left to try. + *_addr will be set to NULL in this case.*/ +static int op_sock_connect_next(op_sock _fd, + const struct addrinfo **_addr,int _ai_family){ + const struct addrinfo *addr; + int err; + addr=*_addr; + for(;;){ + /*Move to the next address of the requested type.*/ + for(;addr!=NULL&&addr->ai_family!=_ai_family;addr=addr->ai_next); + *_addr=addr; + /*No more: failure.*/ + if(addr==NULL)return OP_FALSE; + if(connect(_fd,addr->ai_addr,addr->ai_addrlen)>=0)return 1; + err=op_errno(); + /*Winsock will set WSAEWOULDBLOCK.*/ + if(OP_LIKELY(err==EINPROGRESS||err==EWOULDBLOCK))return 0; + addr=addr->ai_next; + } +} + +/*The number of address families to try connecting to simultaneously.*/ +# define OP_NPROTOS (2) + +static int op_http_connect_impl(OpusHTTPStream *_stream,OpusHTTPConn *_conn, + const struct addrinfo *_addrs,struct timeb *_start_time){ + const struct addrinfo *addr; + const struct addrinfo *addrs[OP_NPROTOS]; + struct pollfd fds[OP_NPROTOS]; + int ai_family; + int nprotos; + int ret; + int pi; + int pj; + for(pi=0;pi<OP_NPROTOS;pi++)addrs[pi]=NULL; + /*Try connecting via both IPv4 and IPv6 simultaneously, and keep the first + one that succeeds. + Start by finding the first address from each family. + We order the first connection attempts in the same order the address + families were returned in the DNS records in accordance with RFC 6555.*/ + for(addr=_addrs,nprotos=0;addr!=NULL&&nprotos<OP_NPROTOS;addr=addr->ai_next){ + if(addr->ai_family==AF_INET6||addr->ai_family==AF_INET){ + OP_ASSERT(addr->ai_addrlen<=sizeof(struct sockaddr_in6)); + OP_ASSERT(addr->ai_addrlen<=sizeof(struct sockaddr_in)); + /*If we've seen this address family before, skip this address for now.*/ + for(pi=0;pi<nprotos;pi++)if(addrs[pi]->ai_family==addr->ai_family)break; + if(pi<nprotos)continue; + addrs[nprotos++]=addr; + } + } + /*Pop the connection off the free list and put it on the LRU list.*/ + OP_ASSERT(_stream->free_head==_conn); + _stream->free_head=_conn->next; + _conn->next=_stream->lru_head; + _stream->lru_head=_conn; + ftime(_start_time); + *&_conn->read_time=*_start_time; + _conn->read_bytes=0; + _conn->read_rate=0; + /*Try to start a connection to each protocol. + RFC 6555 says it is RECOMMENDED that connection attempts be paced + 150...250 ms apart "to balance human factors against network load", but + that "stateful algorithms" (that's us) "are expected to be more + aggressive". + We are definitely more aggressive: we don't pace at all.*/ + for(pi=0;pi<nprotos;pi++){ + ai_family=addrs[pi]->ai_family; + fds[pi].fd=socket(ai_family,SOCK_STREAM,addrs[pi]->ai_protocol); + fds[pi].events=POLLOUT; + if(OP_LIKELY(fds[pi].fd!=OP_INVALID_SOCKET)){ + if(OP_LIKELY(op_sock_set_nonblocking(fds[pi].fd,1)>=0)){ + ret=op_sock_connect_next(fds[pi].fd,addrs+pi,ai_family); + if(OP_UNLIKELY(ret>0)){ + /*It succeeded right away (technically possible), so stop.*/ + nprotos=pi+1; + break; + } + /*Otherwise go on to the next protocol, and skip the clean-up below.*/ + else if(ret==0)continue; + /*Tried all the addresses for this protocol.*/ + } + /*Clean up the socket.*/ + close(fds[pi].fd); + } + /*Remove this protocol from the list.*/ + memmove(addrs+pi,addrs+pi+1,sizeof(*addrs)*(nprotos-pi-1)); + nprotos--; + pi--; + } + /*Wait for one of the connections to finish.*/ + while(pi>=nprotos&&nprotos>0&&poll(fds,nprotos,OP_POLL_TIMEOUT_MS)>0){ + for(pi=0;pi<nprotos;pi++){ + socklen_t errlen; + int err; + /*Still waiting...*/ + if(!fds[pi].revents)continue; + errlen=sizeof(err); + /*Some platforms will return the pending error in &err and return 0. + Others will put it in errno and return -1.*/ + ret=getsockopt(fds[pi].fd,SOL_SOCKET,SO_ERROR,&err,&errlen); + if(ret<0)err=op_errno(); + /*Success!*/ + if(err==0||err==EISCONN)break; + /*Move on to the next address for this protocol.*/ + ai_family=addrs[pi]->ai_family; + addrs[pi]=addrs[pi]->ai_next; + ret=op_sock_connect_next(fds[pi].fd,addrs+pi,ai_family); + /*It succeeded right away, so stop.*/ + if(ret>0)break; + /*Otherwise go on to the next protocol, and skip the clean-up below.*/ + else if(ret==0)continue; + /*Tried all the addresses for this protocol. + Remove it from the list.*/ + close(fds[pi].fd); + memmove(fds+pi,fds+pi+1,sizeof(*fds)*(nprotos-pi-1)); + memmove(addrs+pi,addrs+pi+1,sizeof(*addrs)*(nprotos-pi-1)); + nprotos--; + pi--; + } + } + /*Close all the other sockets.*/ + for(pj=0;pj<nprotos;pj++)if(pi!=pj)close(fds[pj].fd); + /*If none of them succeeded, we're done.*/ + if(pi>=nprotos)return OP_FALSE; + /*Save this address for future connection attempts.*/ + if(addrs[pi]!=&_stream->addr_info){ + memcpy(&_stream->addr_info,addrs[pi],sizeof(_stream->addr_info)); + _stream->addr_info.ai_addr=&_stream->addr.s; + _stream->addr_info.ai_next=NULL; + memcpy(&_stream->addr,addrs[pi]->ai_addr,addrs[pi]->ai_addrlen); + } + if(OP_URL_IS_SSL(&_stream->url)){ + SSL *ssl_conn; + /*Start the SSL connection.*/ + OP_ASSERT(_stream->ssl_ctx!=NULL); + ssl_conn=SSL_new(_stream->ssl_ctx); + if(OP_LIKELY(ssl_conn!=NULL)){ + ret=op_http_conn_start_tls(_stream,_conn,fds[pi].fd,ssl_conn); + if(OP_LIKELY(ret>=0))return ret; + SSL_free(ssl_conn); + } + close(fds[pi].fd); + _conn->fd=OP_INVALID_SOCKET; + return OP_FALSE; + } + /*Just a normal non-SSL connection.*/ + _conn->ssl_conn=NULL; + _conn->fd=fds[pi].fd; + _conn->nrequests_left=OP_PIPELINE_MAX_REQUESTS; + /*Disable write coalescing. + We always send whole requests at once and always parse the response headers + before sending another one.*/ + op_sock_set_tcp_nodelay(fds[pi].fd,1); + return 0; +} + +static int op_http_connect(OpusHTTPStream *_stream,OpusHTTPConn *_conn, + const struct addrinfo *_addrs,struct timeb *_start_time){ + struct timeb resolve_time; + struct addrinfo *new_addrs; + int ret; + /*Re-resolve the host if we need to (RFC 6555 says we MUST do so + occasionally).*/ + new_addrs=NULL; + ftime(&resolve_time); + if(_addrs!=&_stream->addr_info||op_time_diff_ms(&resolve_time, + &_stream->resolve_time)>=OP_RESOLVE_CACHE_TIMEOUT_MS){ + new_addrs=op_resolve(_stream->connect_host,_stream->connect_port); + if(OP_LIKELY(new_addrs!=NULL)){ + _addrs=new_addrs; + *&_stream->resolve_time=*&resolve_time; + } + else if(OP_LIKELY(_addrs==NULL))return OP_FALSE; + } + ret=op_http_connect_impl(_stream,_conn,_addrs,_start_time); + if(new_addrs!=NULL)freeaddrinfo(new_addrs); + return ret; +} + +# define OP_BASE64_LENGTH(_len) (((_len)+2)/3*4) + +static const char BASE64_TABLE[64]={ + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', + 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', + 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' +}; + +static char *op_base64_encode(char *_dst,const char *_src,int _len){ + unsigned s0; + unsigned s1; + unsigned s2; + int ngroups; + int i; + ngroups=_len/3; + for(i=0;i<ngroups;i++){ + s0=_src[3*i+0]; + s1=_src[3*i+1]; + s2=_src[3*i+2]; + _dst[4*i+0]=BASE64_TABLE[s0>>2]; + _dst[4*i+1]=BASE64_TABLE[(s0&3)<<4|s1>>4]; + _dst[4*i+2]=BASE64_TABLE[(s1&15)<<2|s2>>6]; + _dst[4*i+3]=BASE64_TABLE[s2&63]; + } + _len-=3*i; + if(_len==1){ + s0=_src[3*i+0]; + _dst[4*i+0]=BASE64_TABLE[s0>>2]; + _dst[4*i+1]=BASE64_TABLE[(s0&3)<<4]; + _dst[4*i+2]='='; + _dst[4*i+3]='='; + i++; + } + else if(_len==2){ + s0=_src[3*i+0]; + s1=_src[3*i+1]; + _dst[4*i+0]=BASE64_TABLE[s0>>2]; + _dst[4*i+1]=BASE64_TABLE[(s0&3)<<4|s1>>4]; + _dst[4*i+2]=BASE64_TABLE[(s1&15)<<2]; + _dst[4*i+3]='='; + i++; + } + _dst[4*i]='\0'; + return _dst+4*i; +} + +/*Construct an HTTP authorization header using RFC 2617's Basic Authentication + Scheme and append it to the given string buffer.*/ +static int op_sb_append_basic_auth_header(OpusStringBuf *_sb, + const char *_header,const char *_user,const char *_pass){ + int user_len; + int pass_len; + int user_pass_len; + int base64_len; + int nbuf_total; + int ret; + ret=op_sb_append_string(_sb,_header); + ret|=op_sb_append(_sb,": Basic ",8); + user_len=strlen(_user); + pass_len=strlen(_pass); + if(OP_UNLIKELY(pass_len>INT_MAX-user_len))return OP_EFAULT; + if(OP_UNLIKELY(user_len+pass_len>(INT_MAX>>2)*3-3))return OP_EFAULT; + user_pass_len=user_len+1+pass_len; + base64_len=OP_BASE64_LENGTH(user_pass_len); + /*Stick "user:pass" at the end of the buffer so we can Base64 encode it + in-place.*/ + nbuf_total=_sb->nbuf; + if(OP_UNLIKELY(base64_len>INT_MAX-nbuf_total))return OP_EFAULT; + nbuf_total+=base64_len; + ret|=op_sb_ensure_capacity(_sb,nbuf_total); + if(OP_UNLIKELY(ret<0))return ret; + _sb->nbuf=nbuf_total-user_pass_len; + OP_ALWAYS_TRUE(!op_sb_append(_sb,_user,user_len)); + OP_ALWAYS_TRUE(!op_sb_append(_sb,":",1)); + OP_ALWAYS_TRUE(!op_sb_append(_sb,_pass,pass_len)); + op_base64_encode(_sb->buf+nbuf_total-base64_len, + _sb->buf+nbuf_total-user_pass_len,user_pass_len); + return op_sb_append(_sb,"\r\n",2); +} + +static int op_http_allow_pipelining(const char *_server){ + /*Servers known to do bad things with pipelined requests. + This list is taken from Gecko's nsHttpConnection::SupportsPipelining() (in + netwerk/protocol/http/nsHttpConnection.cpp).*/ + static const char *BAD_SERVERS[]={ + "EFAServer/", + "Microsoft-IIS/4.", + "Microsoft-IIS/5.", + "Netscape-Enterprise/3.", + "Netscape-Enterprise/4.", + "Netscape-Enterprise/5.", + "Netscape-Enterprise/6.", + "WebLogic 3.", + "WebLogic 4.", + "WebLogic 5.", + "WebLogic 6.", + "Winstone Servlet Engine v0." + }; +# define NBAD_SERVERS ((int)(sizeof(BAD_SERVERS)/sizeof(*BAD_SERVERS))) + if(*_server>='E'&&*_server<='W'){ + int si; + for(si=0;si<NBAD_SERVERS;si++){ + if(strncmp(_server,BAD_SERVERS[si],strlen(BAD_SERVERS[si]))==0){ + return 0; + } + } + } + return 1; +# undef NBAD_SERVERS +} + +static int op_http_stream_open(OpusHTTPStream *_stream,const char *_url, + int _skip_certificate_check,const char *_proxy_host,unsigned _proxy_port, + const char *_proxy_user,const char *_proxy_pass,OpusServerInfo *_info){ + struct addrinfo *addrs; + int nredirs; + int ret; +#if defined(_WIN32) + op_init_winsock(); +#endif + ret=op_parse_url(&_stream->url,_url); + if(OP_UNLIKELY(ret<0))return ret; + if(_proxy_host!=NULL){ + if(OP_UNLIKELY(_proxy_port>65535U))return OP_EINVAL; + _stream->connect_host=op_string_dup(_proxy_host); + _stream->connect_port=_proxy_port; + } + else{ + _stream->connect_host=_stream->url.host; + _stream->connect_port=_stream->url.port; + } + addrs=NULL; + for(nredirs=0;nredirs<OP_REDIRECT_LIMIT;nredirs++){ + OpusParsedURL next_url; + struct timeb start_time; + struct timeb end_time; + char *next; + char *status_code; + int minor_version_pos; + int v1_1_compat; + /*Initialize the SSL library if necessary.*/ + if(OP_URL_IS_SSL(&_stream->url)&&_stream->ssl_ctx==NULL){ + SSL_CTX *ssl_ctx; +# if !defined(OPENSSL_NO_LOCKING) + /*The documentation says SSL_library_init() is not reentrant. + We don't want to add our own depenencies on a threading library, and it + appears that it's safe to call OpenSSL's locking functions before the + library is initialized, so that's what we'll do (really OpenSSL should + do this for us). + This doesn't guarantee that _other_ threads in the application aren't + calling SSL_library_init() at the same time, but there's not much we + can do about that.*/ + CRYPTO_w_lock(CRYPTO_LOCK_SSL); +# endif + SSL_library_init(); + /*Needed to get SHA2 algorithms with old OpenSSL versions.*/ + OpenSSL_add_ssl_algorithms(); +# if !defined(OPENSSL_NO_LOCKING) + CRYPTO_w_unlock(CRYPTO_LOCK_SSL); +# endif + ssl_ctx=SSL_CTX_new(SSLv23_client_method()); + if(ssl_ctx==NULL)return OP_EFAULT; + if(!_skip_certificate_check){ + /*We don't do anything if this fails, since it just means we won't load + any certificates (and thus all checks will fail). + However, as that is probably the result of a system + mis-configuration, assert here to make it easier to identify.*/ + OP_ALWAYS_TRUE(SSL_CTX_set_default_verify_paths(ssl_ctx)); + SSL_CTX_set_verify(ssl_ctx,SSL_VERIFY_PEER,NULL); + } + _stream->ssl_ctx=ssl_ctx; + _stream->skip_certificate_check=_skip_certificate_check; + if(_proxy_host!=NULL){ + /*We need to establish a CONNECT tunnel to handle https proxying. + Build the request we'll send to do so.*/ + _stream->proxy_connect.nbuf=0; + ret=op_sb_append(&_stream->proxy_connect,"CONNECT ",8); + ret|=op_sb_append_string(&_stream->proxy_connect,_stream->url.host); + ret|=op_sb_append_port(&_stream->proxy_connect,_stream->url.port); + /*CONNECT requires at least HTTP 1.1.*/ + ret|=op_sb_append(&_stream->proxy_connect," HTTP/1.1\r\n",11); + ret|=op_sb_append(&_stream->proxy_connect,"Host: ",6); + ret|=op_sb_append_string(&_stream->proxy_connect,_stream->url.host); + /*The example in RFC 2817 Section 5.2 specifies an explicit port even + when connecting to the default port. + Given that the proxy doesn't know whether we're trying to connect to + an http or an https URL except by the port number, this seems like a + good idea.*/ + ret|=op_sb_append_port(&_stream->proxy_connect,_stream->url.port); + ret|=op_sb_append(&_stream->proxy_connect,"\r\n",2); + ret|=op_sb_append(&_stream->proxy_connect,"User-Agent: .\r\n",15); + if(_proxy_user!=NULL&&_proxy_pass!=NULL){ + ret|=op_sb_append_basic_auth_header(&_stream->proxy_connect, + "Proxy-Authorization",_proxy_user,_proxy_pass); + } + /*For backwards compatibility.*/ + ret|=op_sb_append(&_stream->proxy_connect, + "Proxy-Connection: keep-alive\r\n",30); + ret|=op_sb_append(&_stream->proxy_connect,"\r\n",2); + if(OP_UNLIKELY(ret<0))return ret; + } + } + /*Actually make the connection.*/ + ret=op_http_connect(_stream,_stream->conns+0,addrs,&start_time); + if(OP_UNLIKELY(ret<0))return ret; + /*Build the request to send.*/ + _stream->request.nbuf=0; + ret=op_sb_append(&_stream->request,"GET ",4); + ret|=op_sb_append_string(&_stream->request, + _proxy_host!=NULL?_url:_stream->url.path); + /*Send HTTP/1.0 by default for maximum compatibility (so we don't have to + re-try if HTTP/1.1 fails, though it shouldn't, even for a 1.0 server). + This means we aren't conditionally compliant with RFC 2145, because we + violate the requirement that "An HTTP client SHOULD send a request + version equal to the highest version for which the client is at least + conditionally compliant...". + According to RFC 2145, that means we can't claim any compliance with any + IETF HTTP specification.*/ + ret|=op_sb_append(&_stream->request," HTTP/1.0\r\n",11); + /*Remember where this is so we can upgrade to HTTP/1.1 if the server + supports it.*/ + minor_version_pos=_stream->request.nbuf-3; + ret|=op_sb_append(&_stream->request,"Host: ",6); + ret|=op_sb_append_string(&_stream->request,_stream->url.host); + if(!OP_URL_IS_DEFAULT_PORT(&_stream->url)){ + ret|=op_sb_append_port(&_stream->request,_stream->url.port); + } + ret|=op_sb_append(&_stream->request,"\r\n",2); + /*User-Agents have been a bad idea, so send as little as possible. + RFC 2616 requires at least one token in the User-Agent, which must have + at least one character.*/ + ret|=op_sb_append(&_stream->request,"User-Agent: .\r\n",15); + if(_proxy_host!=NULL&&!OP_URL_IS_SSL(&_stream->url) + &&_proxy_user!=NULL&&_proxy_pass!=NULL){ + ret|=op_sb_append_basic_auth_header(&_stream->request, + "Proxy-Authorization",_proxy_user,_proxy_pass); + } + if(_stream->url.user!=NULL&&_stream->url.pass!=NULL){ + ret|=op_sb_append_basic_auth_header(&_stream->request, + "Authorization",_stream->url.user,_stream->url.pass); + } + /*Always send a Referer [sic] header. + It's common to refuse to serve a resource unless one is present. + We just use the relative "/" URI to suggest we came from the same domain, + as this is the most common check. + This might violate RFC 2616's mandate that the field "MUST NOT be sent if + the Request-URI was obtained from a source that does not have its own + URI, such as input from the user keyboard," but we don't really have any + way to know.*/ + /*TODO: Should we update this on redirects?*/ + ret|=op_sb_append(&_stream->request,"Referer: /\r\n",12); + /*Always send a Range request header to find out if we're seekable. + This requires an HTTP/1.1 server to succeed, but we'll still get what we + want with an HTTP/1.0 server that ignores this request header.*/ + ret|=op_sb_append(&_stream->request,"Range: bytes=0-\r\n",17); + /*Remember where this is so we can append offsets to it later.*/ + _stream->request_tail=_stream->request.nbuf-4; + ret|=op_sb_append(&_stream->request,"\r\n",2); + if(OP_UNLIKELY(ret<0))return ret; + ret=op_http_conn_write_fully(_stream->conns+0, + _stream->request.buf,_stream->request.nbuf); + if(OP_UNLIKELY(ret<0))return ret; + ret=op_http_conn_read_response(_stream->conns+0,&_stream->response); + if(OP_UNLIKELY(ret<0))return ret; + ftime(&end_time); + next=op_http_parse_status_line(&v1_1_compat,&status_code, + _stream->response.buf); + if(OP_UNLIKELY(next==NULL))return OP_FALSE; + if(status_code[0]=='2'){ + opus_int64 content_length; + opus_int64 range_length; + int pipeline_supported; + int pipeline_disabled; + /*We only understand 20x codes.*/ + if(status_code[1]!='0')return OP_FALSE; + content_length=-1; + range_length=-1; + /*Pipelining must be explicitly enabled.*/ + pipeline_supported=0; + pipeline_disabled=0; + for(;;){ + char *header; + char *cdr; + ret=op_http_get_next_header(&header,&cdr,&next); + if(OP_UNLIKELY(ret<0))return ret; + if(header==NULL)break; + if(strcmp(header,"content-length")==0){ + /*Two Content-Length headers?*/ + if(OP_UNLIKELY(content_length>=0))return OP_FALSE; + content_length=op_http_parse_content_length(cdr); + if(OP_UNLIKELY(content_length<0))return (int)content_length; + /*Make sure the Content-Length and Content-Range headers match.*/ + if(range_length>=0&&OP_UNLIKELY(content_length!=range_length)){ + return OP_FALSE; + } + } + else if(strcmp(header,"content-range")==0){ + opus_int64 range_first; + opus_int64 range_last; + /*Two Content-Range headers?*/ + if(OP_UNLIKELY(range_length>=0))return OP_FALSE; + ret=op_http_parse_content_range(&range_first,&range_last, + &range_length,cdr); + if(OP_UNLIKELY(ret<0))return ret; + /*"A response with satus code 206 (Partial Content) MUST NOT + include a Content-Range field with a byte-range-resp-spec of + '*'."*/ + if(status_code[2]=='6' + &&(OP_UNLIKELY(range_first<0)||OP_UNLIKELY(range_last<0))){ + return OP_FALSE; + } + /*We asked for the entire resource.*/ + if(range_length>=0){ + /*Quit if we didn't get it.*/ + if(range_last>=0&&OP_UNLIKELY(range_last!=range_length-1)){ + return OP_FALSE; + } + } + /*If there was no length, use the end of the range.*/ + else if(range_last>=0)range_length=range_last+1; + /*Make sure the Content-Length and Content-Range headers match.*/ + if(content_length>=0&&OP_UNLIKELY(content_length!=range_length)){ + return OP_FALSE; + } + } + else if(strcmp(header,"connection")==0){ + /*According to RFC 2616, if an HTTP/1.1 application does not support + pipelining, it "MUST include the 'close' connection option in + every message." + Therefore, if we receive one in the initial response, disable + pipelining entirely. + The server still might support it (e.g., we might just have hit the + request limit for a temporary child process), but if it doesn't + and we assume it does, every time we cross a chunk boundary we'll + error out and reconnect, adding lots of latency.*/ + ret=op_http_parse_connection(cdr); + if(OP_UNLIKELY(ret<0))return ret; + pipeline_disabled|=ret; + } + else if(strcmp(header,"server")==0){ + /*If we got a Server response header, and it wasn't from a known-bad + server, enable pipelining, as long as it's at least HTTP/1.1. + According to RFC 2145, the server is supposed to respond with the + highest minor version number it supports unless it is known or + suspected that we incorrectly implement the HTTP specification. + So it should send back at least HTTP/1.1, despite our HTTP/1.0 + request.*/ + pipeline_supported=v1_1_compat; + if(v1_1_compat)pipeline_disabled|=!op_http_allow_pipelining(cdr); + if(_info!=NULL&&_info->server==NULL)_info->server=op_string_dup(cdr); + } + /*Collect station information headers if the caller requested it. + If there's more than one copy of a header, the first one wins.*/ + else if(_info!=NULL){ + if(strcmp(header,"content-type")==0){ + if(_info->content_type==NULL){ + _info->content_type=op_string_dup(cdr); + } + } + else if(header[0]=='i'&&header[1]=='c' + &&(header[2]=='e'||header[2]=='y')&&header[3]=='-'){ + if(strcmp(header+4,"name")==0){ + if(_info->name==NULL)_info->name=op_string_dup(cdr); + } + else if(strcmp(header+4,"description")==0){ + if(_info->description==NULL)_info->description=op_string_dup(cdr); + } + else if(strcmp(header+4,"genre")==0){ + if(_info->genre==NULL)_info->genre=op_string_dup(cdr); + } + else if(strcmp(header+4,"url")==0){ + if(_info->url==NULL)_info->url=op_string_dup(cdr); + } + else if(strcmp(header,"icy-br")==0 + ||strcmp(header,"ice-bitrate")==0){ + if(_info->bitrate_kbps<0){ + opus_int64 bitrate_kbps; + /*Just re-using this function to parse a random unsigned + integer field.*/ + bitrate_kbps=op_http_parse_content_length(cdr); + if(bitrate_kbps>=0&&bitrate_kbps<=OP_INT32_MAX){ + _info->bitrate_kbps=(opus_int32)bitrate_kbps; + } + } + } + else if(strcmp(header,"icy-pub")==0 + ||strcmp(header,"ice-public")==0){ + if(_info->is_public<0&&(cdr[0]=='0'||cdr[0]=='1')&&cdr[1]=='\0'){ + _info->is_public=cdr[0]-'0'; + } + } + } + } + } + switch(status_code[2]){ + /*200 OK*/ + case '0':break; + /*203 Non-Authoritative Information*/ + case '3':break; + /*204 No Content*/ + case '4':{ + if(content_length>=0&&OP_UNLIKELY(content_length!=0)){ + return OP_FALSE; + } + }break; + /*206 Partial Content*/ + case '6':{ + /*No Content-Range header.*/ + if(OP_UNLIKELY(range_length<0))return OP_FALSE; + content_length=range_length; + /*The server supports range requests for this resource. + We can seek.*/ + _stream->seekable=1; + }break; + /*201 Created: the response "SHOULD include an entity containing a list + of resource characteristics and location(s)," but not an Opus file. + 202 Accepted: the response "SHOULD include an indication of request's + current status and either a pointer to a status monitor or some + estimate of when the user can expect the request to be fulfilled," + but not an Opus file. + 205 Reset Content: this "MUST NOT include an entity," meaning no Opus + file. + 207...209 are not yet defined, so we don't know how to handle them.*/ + default:return OP_FALSE; + } + _stream->content_length=content_length; + _stream->pipeline=pipeline_supported&&!pipeline_disabled; + /*Pipelining requires HTTP/1.1 persistent connections.*/ + if(_stream->pipeline)_stream->request.buf[minor_version_pos]='1'; + _stream->conns[0].pos=0; + _stream->conns[0].end_pos=_stream->seekable?content_length:-1; + _stream->conns[0].chunk_size=-1; + _stream->cur_conni=0; + _stream->connect_rate=op_time_diff_ms(&end_time,&start_time); + _stream->connect_rate=OP_MAX(_stream->connect_rate,1); + if(_info!=NULL)_info->is_ssl=OP_URL_IS_SSL(&_stream->url); + /*The URL has been successfully opened.*/ + return 0; + } + /*Shouldn't get 1xx; 4xx and 5xx are both failures (and we don't retry). + Everything else is undefined.*/ + else if(status_code[0]!='3')return OP_FALSE; + /*We have some form of redirect request.*/ + /*We only understand 30x codes.*/ + if(status_code[1]!='0')return OP_FALSE; + switch(status_code[2]){ + /*300 Multiple Choices: "If the server has a preferred choice of + representation, it SHOULD include the specific URI for that + representation in the Location field," otherwise we'll fail.*/ + case '0': + /*301 Moved Permanently*/ + case '1': + /*302 Found*/ + case '2': + /*307 Temporary Redirect*/ + case '7': + /*308 Permanent Redirect (defined by draft-reschke-http-status-308-07).*/ + case '8':break; + /*305 Use Proxy: "The Location field gives the URI of the proxy." + TODO: This shouldn't actually be that hard to do.*/ + case '5':return OP_EIMPL; + /*303 See Other: "The new URI is not a substitute reference for the + originally requested resource." + 304 Not Modified: "The 304 response MUST NOT contain a message-body." + 306 (Unused) + 309 is not yet defined, so we don't know how to handle it.*/ + default:return OP_FALSE; + } + _url=NULL; + for(;;){ + char *header; + char *cdr; + ret=op_http_get_next_header(&header,&cdr,&next); + if(OP_UNLIKELY(ret<0))return ret; + if(header==NULL)break; + if(strcmp(header,"location")==0&&OP_LIKELY(_url==NULL))_url=cdr; + } + if(OP_UNLIKELY(_url==NULL))return OP_FALSE; + ret=op_parse_url(&next_url,_url); + if(OP_UNLIKELY(ret<0))return ret; + if(_proxy_host==NULL||_stream->ssl_session!=NULL){ + if(strcmp(_stream->url.host,next_url.host)==0 + &&_stream->url.port==next_url.port){ + /*Try to skip re-resolve when connecting to the same host.*/ + addrs=&_stream->addr_info; + } + else{ + if(_stream->ssl_session!=NULL){ + /*Forget any cached SSL session from the last host.*/ + SSL_SESSION_free(_stream->ssl_session); + _stream->ssl_session=NULL; + } + } + } + if(_proxy_host==NULL){ + OP_ASSERT(_stream->connect_host==_stream->url.host); + _stream->connect_host=next_url.host; + _stream->connect_port=next_url.port; + } + /*Always try to skip re-resolve for proxy connections.*/ + else addrs=&_stream->addr_info; + op_parsed_url_clear(&_stream->url); + *&_stream->url=*&next_url; + /*TODO: On servers/proxies that support pipelining, we might be able to + re-use this connection.*/ + op_http_conn_close(_stream,_stream->conns+0,&_stream->lru_head,1); + } + /*Redirection limit reached.*/ + return OP_FALSE; +} + +static int op_http_conn_send_request(OpusHTTPStream *_stream, + OpusHTTPConn *_conn,opus_int64 _pos,opus_int32 _chunk_size, + int _try_not_to_block){ + opus_int64 next_end; + int ret; + /*We shouldn't have another request outstanding.*/ + OP_ASSERT(_conn->next_pos<0); + /*Build the request to send.*/ + OP_ASSERT(_stream->request.nbuf>=_stream->request_tail); + _stream->request.nbuf=_stream->request_tail; + ret=op_sb_append_nonnegative_int64(&_stream->request,_pos); + ret|=op_sb_append(&_stream->request,"-",1); + if(_chunk_size>0&&OP_ADV_OFFSET(_pos,2*_chunk_size)<_stream->content_length){ + /*We shouldn't be pipelining requests with non-HTTP/1.1 servers.*/ + OP_ASSERT(_stream->pipeline); + next_end=_pos+_chunk_size; + ret|=op_sb_append_nonnegative_int64(&_stream->request,next_end-1); + /*Use a larger chunk size for our next request.*/ + _chunk_size<<=1; + /*But after a while, just request the rest of the resource.*/ + if(_chunk_size>OP_PIPELINE_CHUNK_SIZE_MAX)_chunk_size=-1; + } + else{ + /*Either this was a non-pipelined request or we were close enough to the + end to just ask for the rest.*/ + next_end=-1; + _chunk_size=-1; + } + ret|=op_sb_append(&_stream->request,"\r\n\r\n",4); + if(OP_UNLIKELY(ret<0))return ret; + /*If we don't want to block, check to see if there's enough space in the send + queue. + There's still a chance we might block, even if there is enough space, but + it's a much slimmer one. + Blocking at all is pretty unlikely, as we won't have any requests queued + when _try_not_to_block is set, so if FIONSPACE isn't available (e.g., on + Linux), just skip the test.*/ + if(_try_not_to_block){ +# if defined(FIONSPACE) + int available; + ret=ioctl(_conn->fd,FIONSPACE,&available); + if(ret<0||available<_stream->request.nbuf)return 1; +# endif + } + ret=op_http_conn_write_fully(_conn, + _stream->request.buf,_stream->request.nbuf); + if(OP_UNLIKELY(ret<0))return ret; + _conn->next_pos=_pos; + _conn->next_end=next_end; + /*Save the chunk size to use for the next request.*/ + _conn->chunk_size=_chunk_size; + _conn->nrequests_left--; + return ret; +} + +/*Handles the response to all requests after the first one. + Return: 1 if the connection was closed or timed out, 0 on success, or a + negative value on any other error.*/ +static int op_http_conn_handle_response(OpusHTTPStream *_stream, + OpusHTTPConn *_conn){ + char *next; + char *status_code; + opus_int64 range_length; + opus_int64 next_pos; + opus_int64 next_end; + int ret; + ret=op_http_conn_read_response(_conn,&_stream->response); + /*If the server just closed the connection on us, we may have just hit a + connection re-use limit, so we might want to retry.*/ + if(OP_UNLIKELY(ret<0))return ret==OP_EREAD?1:ret; + next=op_http_parse_status_line(NULL,&status_code,_stream->response.buf); + if(OP_UNLIKELY(next==NULL))return OP_FALSE; + /*We _need_ a 206 Partial Content response. + Nothing else will do.*/ + if(strncmp(status_code,"206",3)!=0){ + /*But on a 408 Request Timeout, we might want to re-try.*/ + return strncmp(status_code,"408",3)==0?1:OP_FALSE; + } + next_pos=_conn->next_pos; + next_end=_conn->next_end; + range_length=-1; + for(;;){ + char *header; + char *cdr; + ret=op_http_get_next_header(&header,&cdr,&next); + if(OP_UNLIKELY(ret<0))return ret; + if(header==NULL)break; + if(strcmp(header,"content-range")==0){ + opus_int64 range_first; + opus_int64 range_last; + /*Two Content-Range headers?*/ + if(OP_UNLIKELY(range_length>=0))return OP_FALSE; + ret=op_http_parse_content_range(&range_first,&range_last, + &range_length,cdr); + if(OP_UNLIKELY(ret<0))return ret; + /*"A response with satus code 206 (Partial Content) MUST NOT + include a Content-Range field with a byte-range-resp-spec of + '*'."*/ + if(OP_UNLIKELY(range_first<0)||OP_UNLIKELY(range_last<0))return OP_FALSE; + /*We also don't want range_last to overflow.*/ + if(OP_UNLIKELY(range_last>=OP_INT64_MAX))return OP_FALSE; + range_last++; + /*Quit if we didn't get the offset we asked for.*/ + if(range_first!=next_pos)return OP_FALSE; + if(next_end<0){ + /*We asked for the rest of the resource.*/ + if(range_length>=0){ + /*Quit if we didn't get it.*/ + if(OP_UNLIKELY(range_last!=range_length))return OP_FALSE; + } + /*If there was no length, use the end of the range.*/ + else range_length=range_last; + next_end=range_last; + } + else{ + if(range_last!=next_end)return OP_FALSE; + /*If there was no length, use the larger of the content length or the + end of this chunk.*/ + if(range_length<0){ + range_length=OP_MAX(range_last,_stream->content_length); + } + } + } + else if(strcmp(header,"content-length")==0){ + opus_int64 content_length; + /*Validate the Content-Length header, if present, against the request we + made.*/ + content_length=op_http_parse_content_length(cdr); + if(OP_UNLIKELY(content_length<0))return (int)content_length; + if(next_end<0){ + /*If we haven't seen the Content-Range header yet and we asked for the + rest of the resource, set next_end, so we can make sure they match + when we do find the Content-Range header.*/ + if(OP_UNLIKELY(next_pos>OP_INT64_MAX-content_length))return OP_FALSE; + next_end=next_pos+content_length; + } + /*Otherwise, make sure they match now.*/ + else if(OP_UNLIKELY(next_end-next_pos!=content_length))return OP_FALSE; + } + else if(strcmp(header,"connection")==0){ + ret=op_http_parse_connection(cdr); + if(OP_UNLIKELY(ret<0))return ret; + /*If the server told us it was going to close the connection, don't make + any more requests.*/ + if(OP_UNLIKELY(ret>0))_conn->nrequests_left=0; + } + } + /*No Content-Range header.*/ + if(OP_UNLIKELY(range_length<0))return OP_FALSE; + /*Update the content_length if necessary.*/ + _stream->content_length=range_length; + _conn->pos=next_pos; + _conn->end_pos=next_end; + _conn->next_pos=-1; + return 0; +} + +/*Open a new connection that will start reading at byte offset _pos. + _pos: The byte offset to start reading from. + _chunk_size: The number of bytes to ask for in the initial request, or -1 to + request the rest of the resource. + This may be more bytes than remain, in which case it will be + converted into a request for the rest.*/ +static int op_http_conn_open_pos(OpusHTTPStream *_stream, + OpusHTTPConn *_conn,opus_int64 _pos,opus_int32 _chunk_size){ + struct timeb start_time; + struct timeb end_time; + opus_int32 connect_rate; + opus_int32 connect_time; + int ret; + ret=op_http_connect(_stream,_conn,&_stream->addr_info,&start_time); + if(OP_UNLIKELY(ret<0))return ret; + ret=op_http_conn_send_request(_stream,_conn,_pos,_chunk_size,0); + if(OP_UNLIKELY(ret<0))return ret; + ret=op_http_conn_handle_response(_stream,_conn); + if(OP_UNLIKELY(ret!=0))return OP_FALSE; + ftime(&end_time); + _stream->cur_conni=_conn-_stream->conns; + OP_ASSERT(_stream->cur_conni>=0&&_stream->cur_conni<OP_NCONNS_MAX); + /*The connection has been successfully opened. + Update the connection time estimate.*/ + connect_time=op_time_diff_ms(&end_time,&start_time); + connect_rate=_stream->connect_rate; + connect_rate+=OP_MAX(connect_time,1)-connect_rate+8>>4; + _stream->connect_rate=connect_rate; + return 0; +} + +/*Read data from the current response body. + If we're pipelining and we get close to the end of this response, queue + another request. + If we've reached the end of this response body, parse the next response and + keep going. + [out] _buf: Returns the data read. + _buf_size: The size of the buffer. + Return: A positive number of bytes read on success. + 0: The connection was closed. + OP_EREAD: There was a fatal read error.*/ +static int op_http_conn_read_body(OpusHTTPStream *_stream, + OpusHTTPConn *_conn,unsigned char *_buf,int _buf_size){ + opus_int64 pos; + opus_int64 end_pos; + opus_int64 next_pos; + opus_int64 content_length; + int nread; + int pipeline; + int ret; + /*Currently this function can only be called on the LRU head. + Otherwise, we'd need a _pnext pointer if we needed to close the connection, + and re-opening it would re-organize the lists.*/ + OP_ASSERT(_stream->lru_head==_conn); + /*We should have filterd out empty reads by this point.*/ + OP_ASSERT(_buf_size>0); + pos=_conn->pos; + end_pos=_conn->end_pos; + next_pos=_conn->next_pos; + pipeline=_stream->pipeline; + content_length=_stream->content_length; + if(end_pos>=0){ + /*Have we reached the end of the current response body?*/ + if(pos>=end_pos){ + OP_ASSERT(content_length>=0); + /*If this was the end of the stream, we're done. + Also return early if a non-blocking read was requested (regardless of + whether we might be able to parse the next response without + blocking).*/ + if(content_length<=end_pos)return 0; + /*Otherwise, start on the next response.*/ + if(next_pos<0){ + /*We haven't issued another request yet.*/ + if(!pipeline||_conn->nrequests_left<=0){ + /*There are two ways to get here: either the server told us it was + going to close the connection after the last request, or we + thought we were reading the whole resource, but it grew while we + were reading it. + The only way the latter could have happened is if content_length + changed while seeking. + Open a new request to read the rest.*/ + OP_ASSERT(_stream->seekable); + /*Try to open a new connection to read another chunk.*/ + op_http_conn_close(_stream,_conn,&_stream->lru_head,1); + /*If we're not pipelining, we should be requesting the rest.*/ + OP_ASSERT(pipeline||_conn->chunk_size==-1); + ret=op_http_conn_open_pos(_stream,_conn,end_pos,_conn->chunk_size); + if(OP_UNLIKELY(ret<0))return OP_EREAD; + } + else{ + /*Issue the request now (better late than never).*/ + ret=op_http_conn_send_request(_stream,_conn,pos,_conn->chunk_size,0); + if(OP_UNLIKELY(ret<0))return OP_EREAD; + next_pos=_conn->next_pos; + OP_ASSERT(next_pos>=0); + } + } + if(next_pos>=0){ + /*We shouldn't be trying to read past the current request body if we're + seeking somewhere else.*/ + OP_ASSERT(next_pos==end_pos); + ret=op_http_conn_handle_response(_stream,_conn); + if(OP_UNLIKELY(ret<0))return OP_EREAD; + if(OP_UNLIKELY(ret>0)&&pipeline){ + opus_int64 next_end; + next_end=_conn->next_end; + /*Our request timed out or the server closed the connection. + Try re-connecting.*/ + op_http_conn_close(_stream,_conn,&_stream->lru_head,1); + /*Unless there's a bug, we should be able to convert + (next_pos,next_end) into valid (_pos,_chunk_size) parameters.*/ + OP_ASSERT(next_end<0 + ||next_end-next_pos>=0&&next_end-next_pos<=OP_INT32_MAX); + ret=op_http_conn_open_pos(_stream,_conn,next_pos, + next_end<0?-1:(opus_int32)(next_end-next_pos)); + if(OP_UNLIKELY(ret<0))return OP_EREAD; + } + else if(OP_UNLIKELY(ret!=0))return OP_EREAD; + } + pos=_conn->pos; + end_pos=_conn->end_pos; + content_length=_stream->content_length; + } + OP_ASSERT(end_pos>pos); + _buf_size=OP_MIN(_buf_size,end_pos-pos); + } + nread=op_http_conn_read(_conn,(char *)_buf,_buf_size,1); + if(OP_UNLIKELY(nread<0))return nread; + pos+=nread; + _conn->pos=pos; + OP_ASSERT(end_pos<0||content_length>=0); + /*TODO: If nrequests_left<=0, we can't make a new request, and there will be + a big pause after we hit the end of the chunk while we open a new + connection. + It would be nice to be able to start that process now, but we have no way + to do it in the background without blocking (even if we could start it, we + have no guarantee the application will return control to us in a + sufficiently timely manner to allow us to complete it, and this is + uncommon enough that it's not worth using threads just for this).*/ + if(end_pos>=0&&end_pos<content_length&&next_pos<0 + &&pipeline&&OP_LIKELY(_conn->nrequests_left>0)){ + opus_int64 request_thresh; + opus_int32 chunk_size; + /*Are we getting close to the end of the current response body? + If so, we should request more data.*/ + request_thresh=_stream->connect_rate*_conn->read_rate>>12; + /*But don't commit ourselves too quickly.*/ + chunk_size=_conn->chunk_size; + if(chunk_size>=0)request_thresh=OP_MIN(chunk_size>>2,request_thresh); + if(end_pos-pos<request_thresh){ + ret=op_http_conn_send_request(_stream,_conn,end_pos,_conn->chunk_size,1); + if(OP_UNLIKELY(ret<0))return OP_EREAD; + } + } + return nread; +} + +static int op_http_stream_read(void *_stream, + unsigned char *_ptr,int _buf_size){ + OpusHTTPStream *stream; + ptrdiff_t nread; + opus_int64 size; + opus_int64 pos; + int ci; + stream=(OpusHTTPStream *)_stream; + /*Check for an empty read.*/ + if(_buf_size<=0)return 0; + ci=stream->cur_conni; + /*No current connection => EOF.*/ + if(ci<0)return 0; + pos=stream->conns[ci].pos; + size=stream->content_length; + /*Check for EOF.*/ + if(size>=0){ + if(pos>=size)return 0; + /*Check for a short read.*/ + if(_buf_size>size-pos)_buf_size=(int)(size-pos); + } + nread=op_http_conn_read_body(stream,stream->conns+ci,_ptr,_buf_size); + if(OP_UNLIKELY(nread<=0)){ + /*We hit an error or EOF. + Either way, we're done with this connection.*/ + op_http_conn_close(stream,stream->conns+ci,&stream->lru_head,1); + stream->cur_conni=-1; + stream->pos=pos; + } + return nread; +} + +/*Discard data until we reach the _target position. + This destroys the contents of _stream->response.buf, as we need somewhere to + read this data, and that is a convenient place. + _just_read_ahead: Whether or not this is a plain fast-forward. + If 0, we need to issue a new request for a chunk at _target + and discard all the data from our current request(s). + Otherwise, we should be able to reach _target without + issuing any new requests. + _target: The stream position to which to read ahead.*/ +static int op_http_conn_read_ahead(OpusHTTPStream *_stream, + OpusHTTPConn *_conn,int _just_read_ahead,opus_int64 _target){ + opus_int64 pos; + opus_int64 end_pos; + opus_int64 next_pos; + opus_int64 next_end; + ptrdiff_t nread; + int ret; + pos=_conn->pos; + end_pos=_conn->end_pos; + next_pos=_conn->next_pos; + next_end=_conn->next_end; + if(!_just_read_ahead){ + /*We need to issue a new pipelined request. + This is the only case where we allow more than one outstanding request + at a time, so we need to reset next_pos (we'll restore it below if we + did have an outstanding request).*/ + OP_ASSERT(_stream->pipeline); + _conn->next_pos=-1; + ret=op_http_conn_send_request(_stream,_conn,_target, + OP_PIPELINE_CHUNK_SIZE,0); + if(OP_UNLIKELY(ret<0))return ret; + } + /*We can reach the target position by reading forward in the current chunk.*/ + if(_just_read_ahead&&(end_pos<0||_target<end_pos))end_pos=_target; + else if(next_pos>=0){ + opus_int64 next_next_pos; + opus_int64 next_next_end; + /*We already have a request outstanding. + Finish off the current chunk.*/ + while(pos<end_pos){ + nread=op_http_conn_read(_conn,_stream->response.buf, + (int)OP_MIN(end_pos-pos,_stream->response.cbuf),1); + /*We failed to read ahead.*/ + if(nread<=0)return OP_FALSE; + pos+=nread; + } + OP_ASSERT(pos==end_pos); + if(_just_read_ahead){ + next_next_pos=next_next_end=-1; + end_pos=_target; + } + else{ + OP_ASSERT(_conn->next_pos==_target); + next_next_pos=_target; + next_next_end=_conn->next_end; + _conn->next_pos=next_pos; + _conn->next_end=next_end; + end_pos=next_end; + } + ret=op_http_conn_handle_response(_stream,_conn); + if(OP_UNLIKELY(ret!=0))return OP_FALSE; + _conn->next_pos=next_next_pos; + _conn->next_end=next_next_end; + } + while(pos<end_pos){ + nread=op_http_conn_read(_conn,_stream->response.buf, + (int)OP_MIN(end_pos-pos,_stream->response.cbuf),1); + /*We failed to read ahead.*/ + if(nread<=0)return OP_FALSE; + pos+=nread; + } + OP_ASSERT(pos==end_pos); + if(!_just_read_ahead){ + ret=op_http_conn_handle_response(_stream,_conn); + if(OP_UNLIKELY(ret!=0))return OP_FALSE; + } + else _conn->pos=end_pos; + OP_ASSERT(_conn->pos==_target); + return 0; +} + +static int op_http_stream_seek(void *_stream,opus_int64 _offset,int _whence){ + struct timeb seek_time; + OpusHTTPStream *stream; + OpusHTTPConn *conn; + OpusHTTPConn **pnext; + OpusHTTPConn *close_conn; + OpusHTTPConn **close_pnext; + opus_int64 content_length; + opus_int64 pos; + int pipeline; + int ci; + int ret; + stream=(OpusHTTPStream *)_stream; + if(!stream->seekable)return -1; + content_length=stream->content_length; + /*If we're seekable, we should have gotten a Content-Length.*/ + OP_ASSERT(content_length>=0); + ci=stream->cur_conni; + pos=ci<0?content_length:stream->conns[ci].pos; + switch(_whence){ + case SEEK_SET:{ + /*Check for overflow:*/ + if(_offset<0)return -1; + pos=_offset; + }break; + case SEEK_CUR:{ + /*Check for overflow:*/ + if(_offset<-pos||_offset>OP_INT64_MAX-pos)return -1; + pos+=_offset; + }break; + case SEEK_END:{ + /*Check for overflow:*/ + if(_offset>content_length||_offset<content_length-OP_INT64_MAX)return -1; + pos=content_length-_offset; + }break; + default:return -1; + } + /*Mark when we deactivated the active connection.*/ + if(ci>=0){ + op_http_conn_read_rate_update(stream->conns+ci); + *&seek_time=*&stream->conns[ci].read_time; + } + else ftime(&seek_time); + /*If we seeked past the end of the stream, just disable the active + connection.*/ + if(pos>=content_length){ + stream->cur_conni=-1; + stream->pos=pos; + return 0; + } + /*First try to find a connection we can use without waiting.*/ + pnext=&stream->lru_head; + conn=stream->lru_head; + while(conn!=NULL){ + opus_int64 conn_pos; + opus_int64 end_pos; + int available; + /*If this connection has been dormant too long or has made too many + requests, close it. + This is to prevent us from hitting server limits/firewall timeouts.*/ + if(op_time_diff_ms(&seek_time,&conn->read_time)> + OP_CONNECTION_IDLE_TIMEOUT_MS + ||conn->nrequests_left<OP_PIPELINE_MIN_REQUESTS){ + op_http_conn_close(stream,conn,pnext,1); + conn=*pnext; + continue; + } + available=op_http_conn_estimate_available(conn); + conn_pos=conn->pos; + end_pos=conn->end_pos; + if(conn->next_pos>=0){ + OP_ASSERT(end_pos>=0); + OP_ASSERT(conn->next_pos==end_pos); + end_pos=conn->next_end; + } + OP_ASSERT(end_pos<0||conn_pos<=end_pos); + /*Can we quickly read ahead without issuing a new request or waiting for + any more data? + If we have an oustanding request, we'll over-estimate the amount of data + it has available (because we'll count the response headers, too), but + that probably doesn't matter.*/ + if(conn_pos<=pos&&pos-conn_pos<=available&&(end_pos<0||pos<end_pos)){ + /*Found a suitable connection to re-use.*/ + ret=op_http_conn_read_ahead(stream,conn,1,pos); + if(OP_UNLIKELY(ret<0)){ + /*The connection might have become stale, so close it and keep going.*/ + op_http_conn_close(stream,conn,pnext,1); + conn=*pnext; + continue; + } + /*Sucessfully resurrected this connection.*/ + *pnext=conn->next; + conn->next=stream->lru_head; + stream->lru_head=conn; + stream->cur_conni=conn-stream->conns; + return 0; + } + pnext=&conn->next; + conn=conn->next; + } + /*Chances are that didn't work, so now try to find one we can use by reading + ahead a reasonable amount and/or by issuing a new request.*/ + close_pnext=NULL; + close_conn=NULL; + pnext=&stream->lru_head; + conn=stream->lru_head; + pipeline=stream->pipeline; + while(conn!=NULL){ + opus_int64 conn_pos; + opus_int64 end_pos; + opus_int64 read_ahead_thresh; + int available; + int just_read_ahead; + /*Dividing by 2048 instead of 1000 scales this by nearly 1/2, biasing away + from connection re-use (and roughly compensating for the lag required to + reopen the TCP window of a connection that's been idle). + There's no overflow checking here, because it's vanishingly unlikely, and + all it would do is cause us to make poor decisions.*/ + read_ahead_thresh=OP_MAX(OP_READAHEAD_THRESH_MIN, + stream->connect_rate*conn->read_rate>>11); + available=op_http_conn_estimate_available(conn); + conn_pos=conn->pos; + end_pos=conn->end_pos; + if(conn->next_pos>=0){ + OP_ASSERT(end_pos>=0); + OP_ASSERT(conn->next_pos==end_pos); + end_pos=conn->next_end; + } + OP_ASSERT(end_pos<0||conn_pos<=end_pos); + /*Can we quickly read ahead without issuing a new request?*/ + just_read_ahead=conn_pos<=pos&&pos-conn_pos-available<=read_ahead_thresh + &&(end_pos<0||pos<end_pos); + if(just_read_ahead||pipeline&&end_pos>=0 + &&end_pos-conn_pos-available<=read_ahead_thresh){ + /*Found a suitable connection to re-use.*/ + ret=op_http_conn_read_ahead(stream,conn,just_read_ahead,pos); + if(OP_UNLIKELY(ret<0)){ + /*The connection might have become stale, so close it and keep going.*/ + op_http_conn_close(stream,conn,pnext,1); + conn=*pnext; + continue; + } + /*Sucessfully resurrected this connection.*/ + *pnext=conn->next; + conn->next=stream->lru_head; + stream->lru_head=conn; + stream->cur_conni=conn-stream->conns; + return 0; + } + close_pnext=pnext; + close_conn=conn; + pnext=&conn->next; + conn=conn->next; + } + /*No suitable connections. + Open a new one.*/ + if(stream->free_head==NULL){ + /*All connections in use. + Expire one of them (we should have already picked which one when scanning + the list).*/ + OP_ASSERT(close_conn!=NULL); + OP_ASSERT(close_pnext!=NULL); + op_http_conn_close(stream,close_conn,close_pnext,1); + } + OP_ASSERT(stream->free_head!=NULL); + conn=stream->free_head; + /*If we can pipeline, only request a chunk of data. + If we're seeking now, there's a good chance we will want to seek again + soon, and this avoids committing this connection to reading the rest of + the stream. + Particularly with SSL or proxies, issuing a new request on the same + connection can be substantially faster than opening a new one. + This also limits the amount of data the server will blast at us on this + connection if we later seek elsewhere and start reading from a different + connection.*/ + ret=op_http_conn_open_pos(stream,conn,pos, + pipeline?OP_PIPELINE_CHUNK_SIZE:-1); + if(OP_UNLIKELY(ret<0)){ + op_http_conn_close(stream,conn,&stream->lru_head,1); + return -1; + } + return 0; +} + +static opus_int64 op_http_stream_tell(void *_stream){ + OpusHTTPStream *stream; + int ci; + stream=(OpusHTTPStream *)_stream; + ci=stream->cur_conni; + return ci<0?stream->pos:stream->conns[ci].pos; +} + +static int op_http_stream_close(void *_stream){ + OpusHTTPStream *stream; + stream=(OpusHTTPStream *)_stream; + if(OP_LIKELY(stream!=NULL)){ + op_http_stream_clear(stream); + _ogg_free(stream); + } + return 0; +} + +static const OpusFileCallbacks OP_HTTP_CALLBACKS={ + op_http_stream_read, + op_http_stream_seek, + op_http_stream_tell, + op_http_stream_close +}; +#endif + +void opus_server_info_init(OpusServerInfo *_info){ + _info->name=NULL; + _info->description=NULL; + _info->genre=NULL; + _info->url=NULL; + _info->server=NULL; + _info->content_type=NULL; + _info->bitrate_kbps=-1; + _info->is_public=-1; + _info->is_ssl=0; +} + +void opus_server_info_clear(OpusServerInfo *_info){ + _ogg_free(_info->content_type); + _ogg_free(_info->server); + _ogg_free(_info->url); + _ogg_free(_info->genre); + _ogg_free(_info->description); + _ogg_free(_info->name); +} + +/*The actual URL stream creation function. + This one isn't extensible like the application-level interface, but because + it isn't public, we're free to change it in the future.*/ +static void *op_url_stream_create_impl(OpusFileCallbacks *_cb,const char *_url, + int _skip_certificate_check,const char *_proxy_host,unsigned _proxy_port, + const char *_proxy_user,const char *_proxy_pass,OpusServerInfo *_info){ + const char *path; + /*Check to see if this is a valid file: URL.*/ + path=op_parse_file_url(_url); + if(path!=NULL){ + char *unescaped_path; + void *ret; + unescaped_path=op_string_dup(path); + if(OP_UNLIKELY(unescaped_path==NULL))return NULL; + ret=op_fopen(_cb,op_unescape_url_component(unescaped_path),"rb"); + _ogg_free(unescaped_path); + return ret; + } +#if defined(OP_ENABLE_HTTP) + /*If not, try http/https.*/ + else{ + OpusHTTPStream *stream; + int ret; + stream=(OpusHTTPStream *)_ogg_malloc(sizeof(*stream)); + if(OP_UNLIKELY(stream==NULL))return NULL; + op_http_stream_init(stream); + ret=op_http_stream_open(stream,_url,_skip_certificate_check, + _proxy_host,_proxy_port,_proxy_user,_proxy_pass,_info); + if(OP_UNLIKELY(ret<0)){ + op_http_stream_clear(stream); + _ogg_free(stream); + return NULL; + } + *_cb=*&OP_HTTP_CALLBACKS; + return stream; + } +#else + (void)_skip_certificate_check; + (void)_proxy_host; + (void)_proxy_port; + (void)_proxy_user; + (void)_proxy_pass; + (void)_info; + return NULL; +#endif +} + +/*The actual implementation of op_url_stream_vcreate(). + We have to do a careful dance here to avoid potential memory leaks if + OpusServerInfo is requested, since this function is also used by + op_vopen_url() and op_vtest_url(). + Even if this function succeeds, those functions might ultimately fail. + If they do, they should return without having touched the OpusServerInfo + passed by the application. + Therefore, if this function succeeds and OpusServerInfo is requested, the + actual info will be stored in *_info and a pointer to the application's + storage will be placed in *_pinfo. + If this function fails or if the application did not request OpusServerInfo, + *_pinfo will be NULL. + Our caller is responsible for copying *_info to **_pinfo if it ultimately + succeeds, or for clearing *_info if it ultimately fails.*/ +void *op_url_stream_vcreate_impl(OpusFileCallbacks *_cb, + const char *_url,OpusServerInfo *_info,OpusServerInfo **_pinfo,va_list _ap){ + int skip_certificate_check; + const char *proxy_host; + opus_int32 proxy_port; + const char *proxy_user; + const char *proxy_pass; + OpusServerInfo *pinfo; + skip_certificate_check=0; + proxy_host=NULL; + proxy_port=8080; + proxy_user=NULL; + proxy_pass=NULL; + pinfo=NULL; + for(;;){ + ptrdiff_t request; + request=va_arg(_ap,char *)-(char *)NULL; + /*If we hit NULL, we're done processing options.*/ + if(!request)break; + switch(request){ + case OP_SSL_SKIP_CERTIFICATE_CHECK_REQUEST:{ + skip_certificate_check=!!va_arg(_ap,opus_int32); + }break; + case OP_HTTP_PROXY_HOST_REQUEST:{ + proxy_host=va_arg(_ap,const char *); + }break; + case OP_HTTP_PROXY_PORT_REQUEST:{ + proxy_port=va_arg(_ap,opus_int32); + if(proxy_port<0||proxy_port>(opus_int32)65535)return NULL; + }break; + case OP_HTTP_PROXY_USER_REQUEST:{ + proxy_user=va_arg(_ap,const char *); + }break; + case OP_HTTP_PROXY_PASS_REQUEST:{ + proxy_pass=va_arg(_ap,const char *); + }break; + case OP_GET_SERVER_INFO_REQUEST:{ + pinfo=va_arg(_ap,OpusServerInfo *); + }break; + /*Some unknown option.*/ + default:return NULL; + } + } + /*If the caller has requested server information, proxy it to a local copy to + simplify error handling.*/ + *_pinfo=NULL; + if(pinfo!=NULL){ + void *ret; + opus_server_info_init(_info); + ret=op_url_stream_create_impl(_cb,_url,skip_certificate_check, + proxy_host,proxy_port,proxy_user,proxy_pass,_info); + if(ret!=NULL)*_pinfo=pinfo; + else opus_server_info_clear(_info); + return ret; + } + return op_url_stream_create_impl(_cb,_url,skip_certificate_check, + proxy_host,proxy_port,proxy_user,proxy_pass,NULL); +} + +void *op_url_stream_vcreate(OpusFileCallbacks *_cb, + const char *_url,va_list _ap){ + OpusServerInfo info; + OpusServerInfo *pinfo; + void *ret; + ret=op_url_stream_vcreate_impl(_cb,_url,&info,&pinfo,_ap); + if(pinfo!=NULL)*pinfo=*&info; + return ret; +} + +void *op_url_stream_create(OpusFileCallbacks *_cb, + const char *_url,...){ + va_list ap; + void *ret; + va_start(ap,_url); + ret=op_url_stream_vcreate(_cb,_url,ap); + va_end(ap); + return ret; +} + +/*Convenience routines to open/test URLs in a single step.*/ + +OggOpusFile *op_vopen_url(const char *_url,int *_error,va_list _ap){ + OpusFileCallbacks cb; + OggOpusFile *of; + OpusServerInfo info; + OpusServerInfo *pinfo; + void *source; + source=op_url_stream_vcreate_impl(&cb,_url,&info,&pinfo,_ap); + if(OP_UNLIKELY(source==NULL)){ + OP_ASSERT(pinfo==NULL); + if(_error!=NULL)*_error=OP_EFAULT; + return NULL; + } + of=op_open_callbacks(source,&cb,NULL,0,_error); + if(OP_UNLIKELY(of==NULL)){ + if(pinfo!=NULL)opus_server_info_clear(&info); + (*cb.close)(source); + } + else if(pinfo!=NULL)*pinfo=*&info; + return of; +} + +OggOpusFile *op_open_url(const char *_url,int *_error,...){ + OggOpusFile *ret; + va_list ap; + va_start(ap,_error); + ret=op_vopen_url(_url,_error,ap); + va_end(ap); + return ret; +} + +OggOpusFile *op_vtest_url(const char *_url,int *_error,va_list _ap){ + OpusFileCallbacks cb; + OggOpusFile *of; + OpusServerInfo info; + OpusServerInfo *pinfo; + void *source; + source=op_url_stream_vcreate_impl(&cb,_url,&info,&pinfo,_ap); + if(OP_UNLIKELY(source==NULL)){ + OP_ASSERT(pinfo==NULL); + if(_error!=NULL)*_error=OP_EFAULT; + return NULL; + } + of=op_test_callbacks(source,&cb,NULL,0,_error); + if(OP_UNLIKELY(of==NULL)){ + if(pinfo!=NULL)opus_server_info_clear(&info); + (*cb.close)(source); + } + else if(pinfo!=NULL)*pinfo=*&info; + return of; +} + +OggOpusFile *op_test_url(const char *_url,int *_error,...){ + OggOpusFile *ret; + va_list ap; + va_start(ap,_error); + ret=op_vtest_url(_url,_error,ap); + va_end(ap); + return ret; +} diff --git a/thirdparty/opus/info.c b/thirdparty/opus/info.c new file mode 100644 index 0000000000..55e2906d5f --- /dev/null +++ b/thirdparty/opus/info.c @@ -0,0 +1,753 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ********************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "internal.h" +#include <limits.h> +#include <string.h> + +static unsigned op_parse_uint16le(const unsigned char *_data){ + return _data[0]|_data[1]<<8; +} + +static int op_parse_int16le(const unsigned char *_data){ + int ret; + ret=_data[0]|_data[1]<<8; + return (ret^0x8000)-0x8000; +} + +static opus_uint32 op_parse_uint32le(const unsigned char *_data){ + return _data[0]|(opus_uint32)_data[1]<<8| + (opus_uint32)_data[2]<<16|(opus_uint32)_data[3]<<24; +} + +static opus_uint32 op_parse_uint32be(const unsigned char *_data){ + return _data[3]|(opus_uint32)_data[2]<<8| + (opus_uint32)_data[1]<<16|(opus_uint32)_data[0]<<24; +} + +int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ + OpusHead head; + if(_len<8)return OP_ENOTFORMAT; + if(memcmp(_data,"OpusHead",8)!=0)return OP_ENOTFORMAT; + if(_len<9)return OP_EBADHEADER; + head.version=_data[8]; + if(head.version>15)return OP_EVERSION; + if(_len<19)return OP_EBADHEADER; + head.channel_count=_data[9]; + head.pre_skip=op_parse_uint16le(_data+10); + head.input_sample_rate=op_parse_uint32le(_data+12); + head.output_gain=op_parse_int16le(_data+16); + head.mapping_family=_data[18]; + if(head.mapping_family==0){ + if(head.channel_count<1||head.channel_count>2)return OP_EBADHEADER; + if(head.version<=1&&_len>19)return OP_EBADHEADER; + head.stream_count=1; + head.coupled_count=head.channel_count-1; + if(_head!=NULL){ + _head->mapping[0]=0; + _head->mapping[1]=1; + } + } + else if(head.mapping_family==1){ + size_t size; + int ci; + if(head.channel_count<1||head.channel_count>8)return OP_EBADHEADER; + size=21+head.channel_count; + if(_len<size||head.version<=1&&_len>size)return OP_EBADHEADER; + head.stream_count=_data[19]; + if(head.stream_count<1)return OP_EBADHEADER; + head.coupled_count=_data[20]; + if(head.coupled_count>head.stream_count)return OP_EBADHEADER; + for(ci=0;ci<head.channel_count;ci++){ + if(_data[21+ci]>=head.stream_count+head.coupled_count + &&_data[21+ci]!=255){ + return OP_EBADHEADER; + } + } + if(_head!=NULL)memcpy(_head->mapping,_data+21,head.channel_count); + } + /*General purpose players should not attempt to play back content with + channel mapping family 255.*/ + else if(head.mapping_family==255)return OP_EIMPL; + /*No other channel mapping families are currently defined.*/ + else return OP_EBADHEADER; + if(_head!=NULL)memcpy(_head,&head,head.mapping-(unsigned char *)&head); + return 0; +} + +void opus_tags_init(OpusTags *_tags){ + memset(_tags,0,sizeof(*_tags)); +} + +void opus_tags_clear(OpusTags *_tags){ + int ncomments; + int ci; + ncomments=_tags->comments; + if(_tags->user_comments!=NULL)ncomments++; + for(ci=ncomments;ci-->0;)_ogg_free(_tags->user_comments[ci]); + _ogg_free(_tags->user_comments); + _ogg_free(_tags->comment_lengths); + _ogg_free(_tags->vendor); +} + +/*Ensure there's room for up to _ncomments comments.*/ +static int op_tags_ensure_capacity(OpusTags *_tags,size_t _ncomments){ + char **user_comments; + int *comment_lengths; + int cur_ncomments; + char *binary_suffix_data; + int binary_suffix_len; + size_t size; + if(OP_UNLIKELY(_ncomments>=(size_t)INT_MAX))return OP_EFAULT; + size=sizeof(*_tags->comment_lengths)*(_ncomments+1); + if(size/sizeof(*_tags->comment_lengths)!=_ncomments+1)return OP_EFAULT; + cur_ncomments=_tags->comments; + comment_lengths=_tags->comment_lengths; + binary_suffix_len=comment_lengths==NULL?0:comment_lengths[cur_ncomments]; + comment_lengths=(int *)_ogg_realloc(_tags->comment_lengths,size); + if(OP_UNLIKELY(comment_lengths==NULL))return OP_EFAULT; + comment_lengths[_ncomments]=binary_suffix_len; + _tags->comment_lengths=comment_lengths; + size=sizeof(*_tags->user_comments)*(_ncomments+1); + if(size/sizeof(*_tags->user_comments)!=_ncomments+1)return OP_EFAULT; + user_comments=_tags->user_comments; + binary_suffix_data=user_comments==NULL?NULL:user_comments[cur_ncomments]; + user_comments=(char **)_ogg_realloc(_tags->user_comments,size); + if(OP_UNLIKELY(user_comments==NULL))return OP_EFAULT; + user_comments[_ncomments]=binary_suffix_data; + _tags->user_comments=user_comments; + return 0; +} + +/*Duplicate a (possibly non-NUL terminated) string with a known length.*/ +static char *op_strdup_with_len(const char *_s,size_t _len){ + size_t size; + char *ret; + size=sizeof(*ret)*(_len+1); + if(OP_UNLIKELY(size<_len))return NULL; + ret=(char *)_ogg_malloc(size); + if(OP_LIKELY(ret!=NULL)){ + ret=(char *)memcpy(ret,_s,sizeof(*ret)*_len); + ret[_len]='\0'; + } + return ret; +} + +/*The actual implementation of opus_tags_parse(). + Unlike the public API, this function requires _tags to already be + initialized, modifies its contents before success is guaranteed, and assumes + the caller will clear it on error.*/ +static int opus_tags_parse_impl(OpusTags *_tags, + const unsigned char *_data,size_t _len){ + opus_uint32 count; + size_t len; + int ncomments; + int ci; + len=_len; + if(len<8)return OP_ENOTFORMAT; + if(memcmp(_data,"OpusTags",8)!=0)return OP_ENOTFORMAT; + if(len<16)return OP_EBADHEADER; + _data+=8; + len-=8; + count=op_parse_uint32le(_data); + _data+=4; + len-=4; + if(count>len)return OP_EBADHEADER; + if(_tags!=NULL){ + _tags->vendor=op_strdup_with_len((char *)_data,count); + if(_tags->vendor==NULL)return OP_EFAULT; + } + _data+=count; + len-=count; + if(len<4)return OP_EBADHEADER; + count=op_parse_uint32le(_data); + _data+=4; + len-=4; + /*Check to make sure there's minimally sufficient data left in the packet.*/ + if(count>len>>2)return OP_EBADHEADER; + /*Check for overflow (the API limits this to an int).*/ + if(count>(opus_uint32)INT_MAX-1)return OP_EFAULT; + if(_tags!=NULL){ + int ret; + ret=op_tags_ensure_capacity(_tags,count); + if(ret<0)return ret; + } + ncomments=(int)count; + for(ci=0;ci<ncomments;ci++){ + /*Check to make sure there's minimally sufficient data left in the packet.*/ + if((size_t)(ncomments-ci)>len>>2)return OP_EBADHEADER; + count=op_parse_uint32le(_data); + _data+=4; + len-=4; + if(count>len)return OP_EBADHEADER; + /*Check for overflow (the API limits this to an int).*/ + if(count>(opus_uint32)INT_MAX)return OP_EFAULT; + if(_tags!=NULL){ + _tags->user_comments[ci]=op_strdup_with_len((char *)_data,count); + if(_tags->user_comments[ci]==NULL)return OP_EFAULT; + _tags->comment_lengths[ci]=(int)count; + _tags->comments=ci+1; + } + _data+=count; + len-=count; + } + if(len>0&&(_data[0]&1)){ + if(len>(opus_uint32)INT_MAX)return OP_EFAULT; + _tags->user_comments[ncomments]=(char *)_ogg_malloc(len); + if(OP_UNLIKELY(_tags->user_comments[ncomments]==NULL))return OP_EFAULT; + memcpy(_tags->user_comments[ncomments],_data,len); + _tags->comment_lengths[ncomments]=(int)len; + } + return 0; +} + +int opus_tags_parse(OpusTags *_tags,const unsigned char *_data,size_t _len){ + if(_tags!=NULL){ + OpusTags tags; + int ret; + opus_tags_init(&tags); + ret=opus_tags_parse_impl(&tags,_data,_len); + if(ret<0)opus_tags_clear(&tags); + else *_tags=*&tags; + return ret; + } + else return opus_tags_parse_impl(NULL,_data,_len); +} + +/*The actual implementation of opus_tags_copy(). + Unlike the public API, this function requires _dst to already be + initialized, modifies its contents before success is guaranteed, and assumes + the caller will clear it on error.*/ +static int opus_tags_copy_impl(OpusTags *_dst,const OpusTags *_src){ + char *vendor; + int ncomments; + int ret; + int ci; + vendor=_src->vendor; + _dst->vendor=op_strdup_with_len(vendor,strlen(vendor)); + if(OP_UNLIKELY(_dst->vendor==NULL))return OP_EFAULT; + ncomments=_src->comments; + ret=op_tags_ensure_capacity(_dst,ncomments); + if(OP_UNLIKELY(ret<0))return ret; + for(ci=0;ci<ncomments;ci++){ + int len; + len=_src->comment_lengths[ci]; + OP_ASSERT(len>=0); + _dst->user_comments[ci]=op_strdup_with_len(_src->user_comments[ci],len); + if(OP_UNLIKELY(_dst->user_comments[ci]==NULL))return OP_EFAULT; + _dst->comment_lengths[ci]=len; + _dst->comments=ci+1; + } + if(_src->comment_lengths!=NULL){ + int len; + len=_src->comment_lengths[ncomments]; + if(len>0){ + _dst->user_comments[ncomments]=(char *)_ogg_malloc(len); + if(OP_UNLIKELY(_dst->user_comments[ncomments]==NULL))return OP_EFAULT; + memcpy(_dst->user_comments[ncomments],_src->user_comments[ncomments],len); + _dst->comment_lengths[ncomments]=len; + } + } + return 0; +} + +int opus_tags_copy(OpusTags *_dst,const OpusTags *_src){ + OpusTags dst; + int ret; + opus_tags_init(&dst); + ret=opus_tags_copy_impl(&dst,_src); + if(OP_UNLIKELY(ret<0))opus_tags_clear(&dst); + else *_dst=*&dst; + return 0; +} + +int opus_tags_add(OpusTags *_tags,const char *_tag,const char *_value){ + char *comment; + int tag_len; + int value_len; + int ncomments; + int ret; + ncomments=_tags->comments; + ret=op_tags_ensure_capacity(_tags,ncomments+1); + if(OP_UNLIKELY(ret<0))return ret; + tag_len=strlen(_tag); + value_len=strlen(_value); + /*+2 for '=' and '\0'.*/ + comment=(char *)_ogg_malloc(sizeof(*comment)*(tag_len+value_len+2)); + if(OP_UNLIKELY(comment==NULL))return OP_EFAULT; + memcpy(comment,_tag,sizeof(*comment)*tag_len); + comment[tag_len]='='; + memcpy(comment+tag_len+1,_value,sizeof(*comment)*(value_len+1)); + _tags->user_comments[ncomments]=comment; + _tags->comment_lengths[ncomments]=tag_len+value_len+1; + _tags->comments=ncomments+1; + return 0; +} + +int opus_tags_add_comment(OpusTags *_tags,const char *_comment){ + char *comment; + int comment_len; + int ncomments; + int ret; + ncomments=_tags->comments; + ret=op_tags_ensure_capacity(_tags,ncomments+1); + if(OP_UNLIKELY(ret<0))return ret; + comment_len=(int)strlen(_comment); + comment=op_strdup_with_len(_comment,comment_len); + if(OP_UNLIKELY(_tags->user_comments[ncomments]==NULL))return OP_EFAULT; + _tags->user_comments[ncomments]=comment; + _tags->comment_lengths[ncomments]=comment_len; + _tags->comments=ncomments+1; + return 0; +} + +int opus_tags_set_binary_suffix(OpusTags *_tags, + const unsigned char *_data,int _len){ + unsigned char *binary_suffix_data; + int ncomments; + int ret; + if(_len<0||_len>0&&(_data==NULL||!(_data[0]&1)))return OP_EINVAL; + ncomments=_tags->comments; + ret=op_tags_ensure_capacity(_tags,ncomments); + if(OP_UNLIKELY(ret<0))return ret; + binary_suffix_data= + (unsigned char *)_ogg_realloc(_tags->user_comments[ncomments],_len); + if(OP_UNLIKELY(binary_suffix_data==NULL))return OP_EFAULT; + memcpy(binary_suffix_data,_data,_len); + _tags->user_comments[ncomments]=(char *)binary_suffix_data; + _tags->comment_lengths[ncomments]=_len; + return 0; +} + +int opus_tagcompare(const char *_tag_name,const char *_comment){ + return opus_tagncompare(_tag_name,strlen(_tag_name),_comment); +} + +int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment){ + int ret; + OP_ASSERT(_tag_len>=0); + ret=op_strncasecmp(_tag_name,_comment,_tag_len); + return ret?ret:'='-_comment[_tag_len]; +} + +const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count){ + char **user_comments; + int tag_len; + int found; + int ncomments; + int ci; + tag_len=strlen(_tag); + ncomments=_tags->comments; + user_comments=_tags->user_comments; + found=0; + for(ci=0;ci<ncomments;ci++){ + if(!opus_tagncompare(_tag,tag_len,user_comments[ci])){ + /*We return a pointer to the data, not a copy.*/ + if(_count==found++)return user_comments[ci]+tag_len+1; + } + } + /*Didn't find anything.*/ + return NULL; +} + +int opus_tags_query_count(const OpusTags *_tags,const char *_tag){ + char **user_comments; + int tag_len; + int found; + int ncomments; + int ci; + tag_len=strlen(_tag); + ncomments=_tags->comments; + user_comments=_tags->user_comments; + found=0; + for(ci=0;ci<ncomments;ci++){ + if(!opus_tagncompare(_tag,tag_len,user_comments[ci]))found++; + } + return found; +} + +const unsigned char *opus_tags_get_binary_suffix(const OpusTags *_tags, + int *_len){ + int ncomments; + int len; + ncomments=_tags->comments; + len=_tags->comment_lengths==NULL?0:_tags->comment_lengths[ncomments]; + *_len=len; + OP_ASSERT(len==0||_tags->user_comments!=NULL); + return len>0?(const unsigned char *)_tags->user_comments[ncomments]:NULL; +} + +static int opus_tags_get_gain(const OpusTags *_tags,int *_gain_q8, + const char *_tag_name,size_t _tag_len){ + char **comments; + int ncomments; + int ci; + comments=_tags->user_comments; + ncomments=_tags->comments; + /*Look for the first valid tag with the name _tag_name and use that.*/ + for(ci=0;ci<ncomments;ci++){ + if(opus_tagncompare(_tag_name,_tag_len,comments[ci])==0){ + char *p; + opus_int32 gain_q8; + int negative; + p=comments[ci]+_tag_len+1; + negative=0; + if(*p=='-'){ + negative=-1; + p++; + } + else if(*p=='+')p++; + gain_q8=0; + while(*p>='0'&&*p<='9'){ + gain_q8=10*gain_q8+*p-'0'; + if(gain_q8>32767-negative)break; + p++; + } + /*This didn't look like a signed 16-bit decimal integer. + Not a valid gain tag.*/ + if(*p!='\0')continue; + *_gain_q8=(int)(gain_q8+negative^negative); + return 0; + } + } + return OP_FALSE; +} + +int opus_tags_get_album_gain(const OpusTags *_tags,int *_gain_q8){ + return opus_tags_get_gain(_tags,_gain_q8,"R128_ALBUM_GAIN",15); +} + +int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8){ + return opus_tags_get_gain(_tags,_gain_q8,"R128_TRACK_GAIN",15); +} + +static int op_is_jpeg(const unsigned char *_buf,size_t _buf_sz){ + return _buf_sz>=11&&memcmp(_buf,"\xFF\xD8\xFF\xE0",4)==0 + &&(_buf[4]<<8|_buf[5])>=16&&memcmp(_buf+6,"JFIF",5)==0; +} + +/*Tries to extract the width, height, bits per pixel, and palette size of a + JPEG. + On failure, simply leaves its outputs unmodified.*/ +static void op_extract_jpeg_params(const unsigned char *_buf,size_t _buf_sz, + opus_uint32 *_width,opus_uint32 *_height, + opus_uint32 *_depth,opus_uint32 *_colors,int *_has_palette){ + if(op_is_jpeg(_buf,_buf_sz)){ + size_t offs; + offs=2; + for(;;){ + size_t segment_len; + int marker; + while(offs<_buf_sz&&_buf[offs]!=0xFF)offs++; + while(offs<_buf_sz&&_buf[offs]==0xFF)offs++; + marker=_buf[offs]; + offs++; + /*If we hit EOI* (end of image), or another SOI* (start of image), + or SOS (start of scan), then stop now.*/ + if(offs>=_buf_sz||(marker>=0xD8&&marker<=0xDA))break; + /*RST* (restart markers): skip (no segment length).*/ + else if(marker>=0xD0&&marker<=0xD7)continue; + /*Read the length of the marker segment.*/ + if(_buf_sz-offs<2)break; + segment_len=_buf[offs]<<8|_buf[offs+1]; + if(segment_len<2||_buf_sz-offs<segment_len)break; + if(marker==0xC0||(marker>0xC0&&marker<0xD0&&(marker&3)!=0)){ + /*Found a SOFn (start of frame) marker segment:*/ + if(segment_len>=8){ + *_height=_buf[offs+3]<<8|_buf[offs+4]; + *_width=_buf[offs+5]<<8|_buf[offs+6]; + *_depth=_buf[offs+2]*_buf[offs+7]; + *_colors=0; + *_has_palette=0; + } + break; + } + /*Other markers: skip the whole marker segment.*/ + offs+=segment_len; + } + } +} + +static int op_is_png(const unsigned char *_buf,size_t _buf_sz){ + return _buf_sz>=8&&memcmp(_buf,"\x89PNG\x0D\x0A\x1A\x0A",8)==0; +} + +/*Tries to extract the width, height, bits per pixel, and palette size of a + PNG. + On failure, simply leaves its outputs unmodified.*/ +static void op_extract_png_params(const unsigned char *_buf,size_t _buf_sz, + opus_uint32 *_width,opus_uint32 *_height, + opus_uint32 *_depth,opus_uint32 *_colors,int *_has_palette){ + if(op_is_png(_buf,_buf_sz)){ + size_t offs; + offs=8; + while(_buf_sz-offs>=12){ + ogg_uint32_t chunk_len; + chunk_len=op_parse_uint32be(_buf+offs); + if(chunk_len>_buf_sz-(offs+12))break; + else if(chunk_len==13&&memcmp(_buf+offs+4,"IHDR",4)==0){ + int color_type; + *_width=op_parse_uint32be(_buf+offs+8); + *_height=op_parse_uint32be(_buf+offs+12); + color_type=_buf[offs+17]; + if(color_type==3){ + *_depth=24; + *_has_palette=1; + } + else{ + int sample_depth; + sample_depth=_buf[offs+16]; + if(color_type==0)*_depth=sample_depth; + else if(color_type==2)*_depth=sample_depth*3; + else if(color_type==4)*_depth=sample_depth*2; + else if(color_type==6)*_depth=sample_depth*4; + *_colors=0; + *_has_palette=0; + break; + } + } + else if(*_has_palette>0&&memcmp(_buf+offs+4,"PLTE",4)==0){ + *_colors=chunk_len/3; + break; + } + offs+=12+chunk_len; + } + } +} + +static int op_is_gif(const unsigned char *_buf,size_t _buf_sz){ + return _buf_sz>=6&&(memcmp(_buf,"GIF87a",6)==0||memcmp(_buf,"GIF89a",6)==0); +} + +/*Tries to extract the width, height, bits per pixel, and palette size of a + GIF. + On failure, simply leaves its outputs unmodified.*/ +static void op_extract_gif_params(const unsigned char *_buf,size_t _buf_sz, + opus_uint32 *_width,opus_uint32 *_height, + opus_uint32 *_depth,opus_uint32 *_colors,int *_has_palette){ + if(op_is_gif(_buf,_buf_sz)&&_buf_sz>=14){ + *_width=_buf[6]|_buf[7]<<8; + *_height=_buf[8]|_buf[9]<<8; + /*libFLAC hard-codes the depth to 24.*/ + *_depth=24; + *_colors=1<<((_buf[10]&7)+1); + *_has_palette=1; + } +} + +/*The actual implementation of opus_picture_tag_parse(). + Unlike the public API, this function requires _pic to already be + initialized, modifies its contents before success is guaranteed, and assumes + the caller will clear it on error.*/ +static int opus_picture_tag_parse_impl(OpusPictureTag *_pic,const char *_tag, + unsigned char *_buf,size_t _buf_sz,size_t _base64_sz){ + opus_int32 picture_type; + opus_uint32 mime_type_length; + char *mime_type; + opus_uint32 description_length; + char *description; + opus_uint32 width; + opus_uint32 height; + opus_uint32 depth; + opus_uint32 colors; + opus_uint32 data_length; + opus_uint32 file_width; + opus_uint32 file_height; + opus_uint32 file_depth; + opus_uint32 file_colors; + int format; + int has_palette; + int colors_set; + size_t i; + /*Decode the BASE64 data.*/ + for(i=0;i<_base64_sz;i++){ + opus_uint32 value; + int j; + value=0; + for(j=0;j<4;j++){ + unsigned c; + unsigned d; + c=(unsigned char)_tag[4*i+j]; + if(c=='+')d=62; + else if(c=='/')d=63; + else if(c>='0'&&c<='9')d=52+c-'0'; + else if(c>='a'&&c<='z')d=26+c-'a'; + else if(c>='A'&&c<='Z')d=c-'A'; + else if(c=='='&&3*i+j>_buf_sz)d=0; + else return OP_ENOTFORMAT; + value=value<<6|d; + } + _buf[3*i]=(unsigned char)(value>>16); + if(3*i+1<_buf_sz){ + _buf[3*i+1]=(unsigned char)(value>>8); + if(3*i+2<_buf_sz)_buf[3*i+2]=(unsigned char)value; + } + } + i=0; + picture_type=op_parse_uint32be(_buf+i); + i+=4; + /*Extract the MIME type.*/ + mime_type_length=op_parse_uint32be(_buf+i); + i+=4; + if(mime_type_length>_buf_sz-32)return OP_ENOTFORMAT; + mime_type=(char *)_ogg_malloc(sizeof(*_pic->mime_type)*(mime_type_length+1)); + if(mime_type==NULL)return OP_EFAULT; + memcpy(mime_type,_buf+i,sizeof(*mime_type)*mime_type_length); + mime_type[mime_type_length]='\0'; + _pic->mime_type=mime_type; + i+=mime_type_length; + /*Extract the description string.*/ + description_length=op_parse_uint32be(_buf+i); + i+=4; + if(description_length>_buf_sz-mime_type_length-32)return OP_ENOTFORMAT; + description= + (char *)_ogg_malloc(sizeof(*_pic->mime_type)*(description_length+1)); + if(description==NULL)return OP_EFAULT; + memcpy(description,_buf+i,sizeof(*description)*description_length); + description[description_length]='\0'; + _pic->description=description; + i+=description_length; + /*Extract the remaining fields.*/ + width=op_parse_uint32be(_buf+i); + i+=4; + height=op_parse_uint32be(_buf+i); + i+=4; + depth=op_parse_uint32be(_buf+i); + i+=4; + colors=op_parse_uint32be(_buf+i); + i+=4; + /*If one of these is set, they all must be, but colors==0 is a valid value.*/ + colors_set=width!=0||height!=0||depth!=0||colors!=0; + if((width==0||height==0||depth==0)&&colors_set)return OP_ENOTFORMAT; + data_length=op_parse_uint32be(_buf+i); + i+=4; + if(data_length>_buf_sz-i)return OP_ENOTFORMAT; + /*Trim extraneous data so we don't copy it below.*/ + _buf_sz=i+data_length; + /*Attempt to determine the image format.*/ + format=OP_PIC_FORMAT_UNKNOWN; + if(mime_type_length==3&&strcmp(mime_type,"-->")==0){ + format=OP_PIC_FORMAT_URL; + /*Picture type 1 must be a 32x32 PNG.*/ + if(picture_type==1&&(width!=0||height!=0)&&(width!=32||height!=32)){ + return OP_ENOTFORMAT; + } + /*Append a terminating NUL for the convenience of our callers.*/ + _buf[_buf_sz++]='\0'; + } + else{ + if(mime_type_length==10 + &&op_strncasecmp(mime_type,"image/jpeg",mime_type_length)==0){ + if(op_is_jpeg(_buf+i,data_length))format=OP_PIC_FORMAT_JPEG; + } + else if(mime_type_length==9 + &&op_strncasecmp(mime_type,"image/png",mime_type_length)==0){ + if(op_is_png(_buf+i,data_length))format=OP_PIC_FORMAT_PNG; + } + else if(mime_type_length==9 + &&op_strncasecmp(mime_type,"image/gif",mime_type_length)==0){ + if(op_is_gif(_buf+i,data_length))format=OP_PIC_FORMAT_GIF; + } + else if(mime_type_length==0||(mime_type_length==6 + &&op_strncasecmp(mime_type,"image/",mime_type_length)==0)){ + if(op_is_jpeg(_buf+i,data_length))format=OP_PIC_FORMAT_JPEG; + else if(op_is_png(_buf+i,data_length))format=OP_PIC_FORMAT_PNG; + else if(op_is_gif(_buf+i,data_length))format=OP_PIC_FORMAT_GIF; + } + file_width=file_height=file_depth=file_colors=0; + has_palette=-1; + switch(format){ + case OP_PIC_FORMAT_JPEG:{ + op_extract_jpeg_params(_buf+i,data_length, + &file_width,&file_height,&file_depth,&file_colors,&has_palette); + }break; + case OP_PIC_FORMAT_PNG:{ + op_extract_png_params(_buf+i,data_length, + &file_width,&file_height,&file_depth,&file_colors,&has_palette); + }break; + case OP_PIC_FORMAT_GIF:{ + op_extract_gif_params(_buf+i,data_length, + &file_width,&file_height,&file_depth,&file_colors,&has_palette); + }break; + } + if(has_palette>=0){ + /*If we successfully extracted these parameters from the image, override + any declared values.*/ + width=file_width; + height=file_height; + depth=file_depth; + colors=file_colors; + } + /*Picture type 1 must be a 32x32 PNG.*/ + if(picture_type==1&&(format!=OP_PIC_FORMAT_PNG||width!=32||height!=32)){ + return OP_ENOTFORMAT; + } + } + /*Adjust _buf_sz instead of using data_length to capture the terminating NUL + for URLs.*/ + _buf_sz-=i; + memmove(_buf,_buf+i,sizeof(*_buf)*_buf_sz); + _buf=(unsigned char *)_ogg_realloc(_buf,_buf_sz); + if(_buf_sz>0&&_buf==NULL)return OP_EFAULT; + _pic->type=picture_type; + _pic->width=width; + _pic->height=height; + _pic->depth=depth; + _pic->colors=colors; + _pic->data_length=data_length; + _pic->data=_buf; + _pic->format=format; + return 0; +} + +int opus_picture_tag_parse(OpusPictureTag *_pic,const char *_tag){ + OpusPictureTag pic; + unsigned char *buf; + size_t base64_sz; + size_t buf_sz; + size_t tag_length; + int ret; + if(opus_tagncompare("METADATA_BLOCK_PICTURE",22,_tag)==0)_tag+=23; + /*Figure out how much BASE64-encoded data we have.*/ + tag_length=strlen(_tag); + if(tag_length&3)return OP_ENOTFORMAT; + base64_sz=tag_length>>2; + buf_sz=3*base64_sz; + if(buf_sz<32)return OP_ENOTFORMAT; + if(_tag[tag_length-1]=='=')buf_sz--; + if(_tag[tag_length-2]=='=')buf_sz--; + if(buf_sz<32)return OP_ENOTFORMAT; + /*Allocate an extra byte to allow appending a terminating NUL to URL data.*/ + buf=(unsigned char *)_ogg_malloc(sizeof(*buf)*(buf_sz+1)); + if(buf==NULL)return OP_EFAULT; + opus_picture_tag_init(&pic); + ret=opus_picture_tag_parse_impl(&pic,_tag,buf,buf_sz,base64_sz); + if(ret<0){ + opus_picture_tag_clear(&pic); + _ogg_free(buf); + } + else *_pic=*&pic; + return ret; +} + +void opus_picture_tag_init(OpusPictureTag *_pic){ + memset(_pic,0,sizeof(*_pic)); +} + +void opus_picture_tag_clear(OpusPictureTag *_pic){ + _ogg_free(_pic->description); + _ogg_free(_pic->mime_type); + _ogg_free(_pic->data); +} diff --git a/thirdparty/opus/internal.c b/thirdparty/opus/internal.c new file mode 100644 index 0000000000..96c80def82 --- /dev/null +++ b/thirdparty/opus/internal.c @@ -0,0 +1,42 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ********************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "internal.h" + +#if defined(OP_ENABLE_ASSERTIONS) +void op_fatal_impl(const char *_str,const char *_file,int _line){ + fprintf(stderr,"Fatal (internal) error in %s, line %i: %s\n", + _file,_line,_str); + abort(); +} +#endif + +/*A version of strncasecmp() that is guaranteed to only ignore the case of + ASCII characters.*/ +int op_strncasecmp(const char *_a,const char *_b,int _n){ + int i; + for(i=0;i<_n;i++){ + int a; + int b; + int d; + a=_a[i]; + b=_b[i]; + if(a>='a'&&a<='z')a-='a'-'A'; + if(b>='a'&&b<='z')b-='a'-'A'; + d=a-b; + if(d)return d; + } + return 0; +} diff --git a/thirdparty/opus/internal.h b/thirdparty/opus/internal.h new file mode 100644 index 0000000000..ee48ea34c9 --- /dev/null +++ b/thirdparty/opus/internal.h @@ -0,0 +1,254 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ********************************************************************/ +#if !defined(_opusfile_internal_h) +# define _opusfile_internal_h (1) + +# if !defined(_REENTRANT) +# define _REENTRANT +# endif +# if !defined(_GNU_SOURCE) +# define _GNU_SOURCE +# endif +# if !defined(_LARGEFILE_SOURCE) +# define _LARGEFILE_SOURCE +# endif +# if !defined(_LARGEFILE64_SOURCE) +# define _LARGEFILE64_SOURCE +# endif +# if !defined(_FILE_OFFSET_BITS) +# define _FILE_OFFSET_BITS 64 +# endif + +# include <stdlib.h> +# include <opusfile.h> + +typedef struct OggOpusLink OggOpusLink; + +# if defined(OP_FIXED_POINT) + +typedef opus_int16 op_sample; + +# else + +typedef float op_sample; + +/*We're using this define to test for libopus 1.1 or later until libopus + provides a better mechanism.*/ +# if defined(OPUS_GET_EXPERT_FRAME_DURATION_REQUEST) +/*Enable soft clipping prevention in 16-bit decodes.*/ +# define OP_SOFT_CLIP (1) +# endif + +# endif + +# if OP_GNUC_PREREQ(4,2) +/*Disable excessive warnings about the order of operations.*/ +# pragma GCC diagnostic ignored "-Wparentheses" +# elif defined(_MSC_VER) +/*Disable excessive warnings about the order of operations.*/ +# pragma warning(disable:4554) +/*Disable warnings about "deprecated" POSIX functions.*/ +# pragma warning(disable:4996) +# endif + +# if OP_GNUC_PREREQ(3,0) +/*Another alternative is + (__builtin_constant_p(_x)?!!(_x):__builtin_expect(!!(_x),1)) + but that evaluates _x multiple times, which may be bad.*/ +# define OP_LIKELY(_x) (__builtin_expect(!!(_x),1)) +# define OP_UNLIKELY(_x) (__builtin_expect(!!(_x),0)) +# else +# define OP_LIKELY(_x) (!!(_x)) +# define OP_UNLIKELY(_x) (!!(_x)) +# endif + +# if defined(OP_ENABLE_ASSERTIONS) +# if OP_GNUC_PREREQ(2,5)||__SUNPRO_C>=0x590 +__attribute__((noreturn)) +# endif +void op_fatal_impl(const char *_str,const char *_file,int _line); + +# define OP_FATAL(_str) (op_fatal_impl(_str,__FILE__,__LINE__)) + +# define OP_ASSERT(_cond) \ + do{ \ + if(OP_UNLIKELY(!(_cond)))OP_FATAL("assertion failed: " #_cond); \ + } \ + while(0) +# define OP_ALWAYS_TRUE(_cond) OP_ASSERT(_cond) + +# else +# define OP_FATAL(_str) abort() +# define OP_ASSERT(_cond) +# define OP_ALWAYS_TRUE(_cond) ((void)(_cond)) +# endif + +# define OP_INT64_MAX (2*(((ogg_int64_t)1<<62)-1)|1) +# define OP_INT64_MIN (-OP_INT64_MAX-1) +# define OP_INT32_MAX (2*(((ogg_int32_t)1<<30)-1)|1) +# define OP_INT32_MIN (-OP_INT32_MAX-1) + +# define OP_MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) +# define OP_MAX(_a,_b) ((_a)>(_b)?(_a):(_b)) +# define OP_CLAMP(_lo,_x,_hi) (OP_MAX(_lo,OP_MIN(_x,_hi))) + +/*Advance a file offset by the given amount, clamping against OP_INT64_MAX. + This is used to advance a known offset by things like OP_CHUNK_SIZE or + OP_PAGE_SIZE_MAX, while making sure to avoid signed overflow. + It assumes that both _offset and _amount are non-negative.*/ +#define OP_ADV_OFFSET(_offset,_amount) \ + (OP_MIN(_offset,OP_INT64_MAX-(_amount))+(_amount)) + +/*The maximum channel count for any mapping we'll actually decode.*/ +# define OP_NCHANNELS_MAX (8) + +/*Initial state.*/ +# define OP_NOTOPEN (0) +/*We've found the first Opus stream in the first link.*/ +# define OP_PARTOPEN (1) +# define OP_OPENED (2) +/*We've found the first Opus stream in the current link.*/ +# define OP_STREAMSET (3) +/*We've initialized the decoder for the chosen Opus stream in the current + link.*/ +# define OP_INITSET (4) + +/*Information cached for a single link in a chained Ogg Opus file. + We choose the first Opus stream encountered in each link to play back (and + require at least one).*/ +struct OggOpusLink{ + /*The byte offset of the first header page in this link.*/ + opus_int64 offset; + /*The byte offset of the first data page from the chosen Opus stream in this + link (after the headers).*/ + opus_int64 data_offset; + /*The byte offset of the last page from the chosen Opus stream in this link. + This is used when seeking to ensure we find a page before the last one, so + that end-trimming calculations work properly. + This is only valid for seekable sources.*/ + opus_int64 end_offset; + /*The granule position of the last sample. + This is only valid for seekable sources.*/ + ogg_int64_t pcm_end; + /*The granule position before the first sample.*/ + ogg_int64_t pcm_start; + /*The serial number.*/ + ogg_uint32_t serialno; + /*The contents of the info header.*/ + OpusHead head; + /*The contents of the comment header.*/ + OpusTags tags; +}; + +struct OggOpusFile{ + /*The callbacks used to access the data source.*/ + OpusFileCallbacks callbacks; + /*A FILE *, memory bufer, etc.*/ + void *source; + /*Whether or not we can seek with this data source.*/ + int seekable; + /*The number of links in this chained Ogg Opus file.*/ + int nlinks; + /*The cached information from each link in a chained Ogg Opus file. + If source isn't seekable (e.g., it's a pipe), only the current link + appears.*/ + OggOpusLink *links; + /*The number of serial numbers from a single link.*/ + int nserialnos; + /*The capacity of the list of serial numbers from a single link.*/ + int cserialnos; + /*Storage for the list of serial numbers from a single link.*/ + ogg_uint32_t *serialnos; + /*This is the current offset of the data processed by the ogg_sync_state. + After a seek, this should be set to the target offset so that we can track + the byte offsets of subsequent pages. + After a call to op_get_next_page(), this will point to the first byte after + that page.*/ + opus_int64 offset; + /*The total size of this data source, or -1 if it's unseekable.*/ + opus_int64 end; + /*Used to locate pages in the data source.*/ + ogg_sync_state oy; + /*One of OP_NOTOPEN, OP_PARTOPEN, OP_OPENED, OP_STREAMSET, OP_INITSET.*/ + int ready_state; + /*The current link being played back.*/ + int cur_link; + /*The number of decoded samples to discard from the start of decoding.*/ + opus_int32 cur_discard_count; + /*The granule position of the previous packet (current packet start time).*/ + ogg_int64_t prev_packet_gp; + /*The stream offset of the most recent page with completed packets, or -1. + This is only needed to recover continued packet data in the seeking logic, + when we use the current position as one of our bounds, only to later + discover it was the correct starting point.*/ + opus_int64 prev_page_offset; + /*The number of bytes read since the last bitrate query, including framing.*/ + opus_int64 bytes_tracked; + /*The number of samples decoded since the last bitrate query.*/ + ogg_int64_t samples_tracked; + /*Takes physical pages and welds them into a logical stream of packets.*/ + ogg_stream_state os; + /*Re-timestamped packets from a single page. + Buffering these relies on the undocumented libogg behavior that ogg_packet + pointers remain valid until the next page is submitted to the + ogg_stream_state they came from.*/ + ogg_packet op[255]; + /*The index of the next packet to return.*/ + int op_pos; + /*The total number of packets available.*/ + int op_count; + /*Central working state for the packet-to-PCM decoder.*/ + OpusMSDecoder *od; + /*The application-provided packet decode callback.*/ + op_decode_cb_func decode_cb; + /*The application-provided packet decode callback context.*/ + void *decode_cb_ctx; + /*The stream count used to initialize the decoder.*/ + int od_stream_count; + /*The coupled stream count used to initialize the decoder.*/ + int od_coupled_count; + /*The channel count used to initialize the decoder.*/ + int od_channel_count; + /*The channel mapping used to initialize the decoder.*/ + unsigned char od_mapping[OP_NCHANNELS_MAX]; + /*The buffered data for one decoded packet.*/ + op_sample *od_buffer; + /*The current position in the decoded buffer.*/ + int od_buffer_pos; + /*The number of valid samples in the decoded buffer.*/ + int od_buffer_size; + /*The type of gain offset to apply. + One of OP_HEADER_GAIN, OP_TRACK_GAIN, or OP_ABSOLUTE_GAIN.*/ + int gain_type; + /*The offset to apply to the gain.*/ + opus_int32 gain_offset_q8; + /*Internal state for soft clipping and dithering float->short output.*/ +#if !defined(OP_FIXED_POINT) +# if defined(OP_SOFT_CLIP) + float clip_state[OP_NCHANNELS_MAX]; +# endif + float dither_a[OP_NCHANNELS_MAX*4]; + float dither_b[OP_NCHANNELS_MAX*4]; + opus_uint32 dither_seed; + int dither_mute; + int dither_disabled; + /*The number of channels represented by the internal state. + This gets set to 0 whenever anything that would prevent state propagation + occurs (switching between the float/short APIs, or between the + stereo/multistream APIs).*/ + int state_channel_count; +#endif +}; + +int op_strncasecmp(const char *_a,const char *_b,int _n); + +#endif diff --git a/thirdparty/opus/mlp.c b/thirdparty/opus/mlp.c new file mode 100644 index 0000000000..ff9e50df47 --- /dev/null +++ b/thirdparty/opus/mlp.c @@ -0,0 +1,145 @@ +/* Copyright (c) 2008-2011 Octasic Inc. + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "opus_types.h" +#include "opus_defines.h" + +#include <math.h> +#include "mlp.h" +#include "arch.h" +#include "tansig_table.h" +#define MAX_NEURONS 100 + +#if 0 +static OPUS_INLINE opus_val16 tansig_approx(opus_val32 _x) /* Q19 */ +{ + int i; + opus_val16 xx; /* Q11 */ + /*double x, y;*/ + opus_val16 dy, yy; /* Q14 */ + /*x = 1.9073e-06*_x;*/ + if (_x>=QCONST32(8,19)) + return QCONST32(1.,14); + if (_x<=-QCONST32(8,19)) + return -QCONST32(1.,14); + xx = EXTRACT16(SHR32(_x, 8)); + /*i = lrint(25*x);*/ + i = SHR32(ADD32(1024,MULT16_16(25, xx)),11); + /*x -= .04*i;*/ + xx -= EXTRACT16(SHR32(MULT16_16(20972,i),8)); + /*x = xx*(1./2048);*/ + /*y = tansig_table[250+i];*/ + yy = tansig_table[250+i]; + /*y = yy*(1./16384);*/ + dy = 16384-MULT16_16_Q14(yy,yy); + yy = yy + MULT16_16_Q14(MULT16_16_Q11(xx,dy),(16384 - MULT16_16_Q11(yy,xx))); + return yy; +} +#else +/*extern const float tansig_table[501];*/ +static OPUS_INLINE float tansig_approx(float x) +{ + int i; + float y, dy; + float sign=1; + /* Tests are reversed to catch NaNs */ + if (!(x<8)) + return 1; + if (!(x>-8)) + return -1; +#ifndef FIXED_POINT + /* Another check in case of -ffast-math */ + if (celt_isnan(x)) + return 0; +#endif + if (x<0) + { + x=-x; + sign=-1; + } + i = (int)floor(.5f+25*x); + x -= .04f*i; + y = tansig_table[i]; + dy = 1-y*y; + y = y + x*dy*(1 - y*x); + return sign*y; +} +#endif + +#if 0 +void mlp_process(const MLP *m, const opus_val16 *in, opus_val16 *out) +{ + int j; + opus_val16 hidden[MAX_NEURONS]; + const opus_val16 *W = m->weights; + /* Copy to tmp_in */ + for (j=0;j<m->topo[1];j++) + { + int k; + opus_val32 sum = SHL32(EXTEND32(*W++),8); + for (k=0;k<m->topo[0];k++) + sum = MAC16_16(sum, in[k],*W++); + hidden[j] = tansig_approx(sum); + } + for (j=0;j<m->topo[2];j++) + { + int k; + opus_val32 sum = SHL32(EXTEND32(*W++),14); + for (k=0;k<m->topo[1];k++) + sum = MAC16_16(sum, hidden[k], *W++); + out[j] = tansig_approx(EXTRACT16(PSHR32(sum,17))); + } +} +#else +void mlp_process(const MLP *m, const float *in, float *out) +{ + int j; + float hidden[MAX_NEURONS]; + const float *W = m->weights; + /* Copy to tmp_in */ + for (j=0;j<m->topo[1];j++) + { + int k; + float sum = *W++; + for (k=0;k<m->topo[0];k++) + sum = sum + in[k]**W++; + hidden[j] = tansig_approx(sum); + } + for (j=0;j<m->topo[2];j++) + { + int k; + float sum = *W++; + for (k=0;k<m->topo[1];k++) + sum = sum + hidden[k]**W++; + out[j] = tansig_approx(sum); + } +} +#endif diff --git a/thirdparty/opus/mlp.h b/thirdparty/opus/mlp.h new file mode 100644 index 0000000000..618e246e2c --- /dev/null +++ b/thirdparty/opus/mlp.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2008-2011 Octasic Inc. + 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 _MLP_H_ +#define _MLP_H_ + +#include "arch.h" + +typedef struct { + int layers; + const int *topo; + const float *weights; +} MLP; + +extern const MLP net; + +void mlp_process(const MLP *m, const float *in, float *out); + +#endif /* _MLP_H_ */ diff --git a/thirdparty/opus/mlp_data.c b/thirdparty/opus/mlp_data.c new file mode 100644 index 0000000000..c2fda4e2e5 --- /dev/null +++ b/thirdparty/opus/mlp_data.c @@ -0,0 +1,109 @@ +/* The contents of this file was automatically generated by mlp_train.c + It contains multi-layer perceptron (MLP) weights. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "mlp.h" + +/* RMS error was 0.138320, seed was 1361535663 */ + +static const float weights[422] = { + +/* hidden layer */ +-0.0941125f, -0.302976f, -0.603555f, -0.19393f, -0.185983f, +-0.601617f, -0.0465317f, -0.114563f, -0.103599f, -0.618938f, +-0.317859f, -0.169949f, -0.0702885f, 0.148065f, 0.409524f, +0.548432f, 0.367649f, -0.494393f, 0.764306f, -1.83957f, +0.170849f, 12.786f, -1.08848f, -1.27284f, -16.2606f, +24.1773f, -5.57454f, -0.17276f, -0.163388f, -0.224421f, +-0.0948944f, -0.0728695f, -0.26557f, -0.100283f, -0.0515459f, +-0.146142f, -0.120674f, -0.180655f, 0.12857f, 0.442138f, +-0.493735f, 0.167767f, 0.206699f, -0.197567f, 0.417999f, +1.50364f, -0.773341f, -10.0401f, 0.401872f, 2.97966f, +15.2165f, -1.88905f, -1.19254f, 0.0285397f, -0.00405139f, +0.0707565f, 0.00825699f, -0.0927269f, -0.010393f, -0.00428882f, +-0.00489743f, -0.0709731f, -0.00255992f, 0.0395619f, 0.226424f, +0.0325231f, 0.162175f, -0.100118f, 0.485789f, 0.12697f, +0.285937f, 0.0155637f, 0.10546f, 3.05558f, 1.15059f, +-1.00904f, -1.83088f, 3.31766f, -3.42516f, -0.119135f, +-0.0405654f, 0.00690068f, 0.0179877f, -0.0382487f, 0.00597941f, +-0.0183611f, 0.00190395f, -0.144322f, -0.0435671f, 0.000990594f, +0.221087f, 0.142405f, 0.484066f, 0.404395f, 0.511955f, +-0.237255f, 0.241742f, 0.35045f, -0.699428f, 10.3993f, +2.6507f, -2.43459f, -4.18838f, 1.05928f, 1.71067f, +0.00667811f, -0.0721335f, -0.0397346f, 0.0362704f, -0.11496f, +-0.0235776f, 0.0082161f, -0.0141741f, -0.0329699f, -0.0354253f, +0.00277404f, -0.290654f, -1.14767f, -0.319157f, -0.686544f, +0.36897f, 0.478899f, 0.182579f, -0.411069f, 0.881104f, +-4.60683f, 1.4697f, 0.335845f, -1.81905f, -30.1699f, +5.55225f, 0.0019508f, -0.123576f, -0.0727332f, -0.0641597f, +-0.0534458f, -0.108166f, -0.0937368f, -0.0697883f, -0.0275475f, +-0.192309f, -0.110074f, 0.285375f, -0.405597f, 0.0926724f, +-0.287881f, -0.851193f, -0.099493f, -0.233764f, -1.2852f, +1.13611f, 3.12168f, -0.0699f, -1.86216f, 2.65292f, +-7.31036f, 2.44776f, -0.00111802f, -0.0632786f, -0.0376296f, +-0.149851f, 0.142963f, 0.184368f, 0.123433f, 0.0756158f, +0.117312f, 0.0933395f, 0.0692163f, 0.0842592f, 0.0704683f, +0.0589963f, 0.0942205f, -0.448862f, 0.0262677f, 0.270352f, +-0.262317f, 0.172586f, 2.00227f, -0.159216f, 0.038422f, +10.2073f, 4.15536f, -2.3407f, -0.0550265f, 0.00964792f, +-0.141336f, 0.0274501f, 0.0343921f, -0.0487428f, 0.0950172f, +-0.00775017f, -0.0372492f, -0.00548121f, -0.0663695f, 0.0960506f, +-0.200008f, -0.0412827f, 0.58728f, 0.0515787f, 0.337254f, +0.855024f, 0.668371f, -0.114904f, -3.62962f, -0.467477f, +-0.215472f, 2.61537f, 0.406117f, -1.36373f, 0.0425394f, +0.12208f, 0.0934502f, 0.123055f, 0.0340935f, -0.142466f, +0.035037f, -0.0490666f, 0.0733208f, 0.0576672f, 0.123984f, +-0.0517194f, -0.253018f, 0.590565f, 0.145849f, 0.315185f, +0.221534f, -0.149081f, 0.216161f, -0.349575f, 24.5664f, +-0.994196f, 0.614289f, -18.7905f, -2.83277f, -0.716801f, +-0.347201f, 0.479515f, -0.246027f, 0.0758683f, 0.137293f, +-0.17781f, 0.118751f, -0.00108329f, -0.237334f, 0.355732f, +-0.12991f, -0.0547627f, -0.318576f, -0.325524f, 0.180494f, +-0.0625604f, 0.141219f, 0.344064f, 0.37658f, -0.591772f, +5.8427f, -0.38075f, 0.221894f, -1.41934f, -1.87943e+06f, +1.34114f, 0.0283355f, -0.0447856f, -0.0211466f, -0.0256927f, +0.0139618f, 0.0207934f, -0.0107666f, 0.0110969f, 0.0586069f, +-0.0253545f, -0.0328433f, 0.11872f, -0.216943f, 0.145748f, +0.119808f, -0.0915211f, -0.120647f, -0.0787719f, -0.143644f, +-0.595116f, -1.152f, -1.25335f, -1.17092f, 4.34023f, +-975268.f, -1.37033f, -0.0401123f, 0.210602f, -0.136656f, +0.135962f, -0.0523293f, 0.0444604f, 0.0143928f, 0.00412666f, +-0.0193003f, 0.218452f, -0.110204f, -2.02563f, 0.918238f, +-2.45362f, 1.19542f, -0.061362f, -1.92243f, 0.308111f, +0.49764f, 0.912356f, 0.209272f, -2.34525f, 2.19326f, +-6.47121f, 1.69771f, -0.725123f, 0.0118929f, 0.0377944f, +0.0554003f, 0.0226452f, -0.0704421f, -0.0300309f, 0.0122978f, +-0.0041782f, -0.0686612f, 0.0313115f, 0.039111f, 0.364111f, +-0.0945548f, 0.0229876f, -0.17414f, 0.329795f, 0.114714f, +0.30022f, 0.106997f, 0.132355f, 5.79932f, 0.908058f, +-0.905324f, -3.3561f, 0.190647f, 0.184211f, -0.673648f, +0.231807f, -0.0586222f, 0.230752f, -0.438277f, 0.245857f, +-0.17215f, 0.0876383f, -0.720512f, 0.162515f, 0.0170571f, +0.101781f, 0.388477f, 1.32931f, 1.08548f, -0.936301f, +-2.36958f, -6.71988f, -3.44376f, 2.13818f, 14.2318f, +4.91459f, -3.09052f, -9.69191f, -0.768234f, 1.79604f, +0.0549653f, 0.163399f, 0.0797025f, 0.0343933f, -0.0555876f, +-0.00505673f, 0.0187258f, 0.0326628f, 0.0231486f, 0.15573f, +0.0476223f, -0.254824f, 1.60155f, -0.801221f, 2.55496f, +0.737629f, -1.36249f, -0.695463f, -2.44301f, -1.73188f, +3.95279f, 1.89068f, 0.486087f, -11.3343f, 3.9416e+06f, + +/* output layer */ +-0.381439f, 0.12115f, -0.906927f, 2.93878f, 1.6388f, +0.882811f, 0.874344f, 1.21726f, -0.874545f, 0.321706f, +0.785055f, 0.946558f, -0.575066f, -3.46553f, 0.884905f, +0.0924047f, -9.90712f, 0.391338f, 0.160103f, -2.04954f, +4.1455f, 0.0684029f, -0.144761f, -0.285282f, 0.379244f, +-1.1584f, -0.0277241f, -9.85f, -4.82386f, 3.71333f, +3.87308f, 3.52558f}; + +static const int topo[3] = {25, 15, 2}; + +const MLP net = { + 3, + topo, + weights +}; diff --git a/thirdparty/opus/opus.c b/thirdparty/opus/opus.c new file mode 100644 index 0000000000..e9ce93b308 --- /dev/null +++ b/thirdparty/opus/opus.c @@ -0,0 +1,350 @@ +/* Copyright (c) 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "opus.h" +#include "opus_private.h" + +#ifndef DISABLE_FLOAT_API +OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem) +{ + int c; + int i; + float *x; + + if (C<1 || N<1 || !_x || !declip_mem) return; + + /* First thing: saturate everything to +/- 2 which is the highest level our + non-linearity can handle. At the point where the signal reaches +/-2, + the derivative will be zero anyway, so this doesn't introduce any + discontinuity in the derivative. */ + for (i=0;i<N*C;i++) + _x[i] = MAX16(-2.f, MIN16(2.f, _x[i])); + 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; + 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); + 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; + } +} +#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) +{ + 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; + + if (size==NULL) + return OPUS_BAD_ARG; + + 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*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 (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); +} + diff --git a/thirdparty/opus/opus.h b/thirdparty/opus/opus.h new file mode 100644 index 0000000000..b0bdf6f2df --- /dev/null +++ b/thirdparty/opus/opus.h @@ -0,0 +1,981 @@ +/* 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 assuptions 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 1 byte, 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. + */ +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 (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@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 (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/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 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 assuptions 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; + +/** 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 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 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 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); + +/** 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(4); + +/** 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); + +/** 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 manipualte 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/drivers/opus/opus_compare.c b/thirdparty/opus/opus_compare.c index 06c67d752f..06c67d752f 100644 --- a/drivers/opus/opus_compare.c +++ b/thirdparty/opus/opus_compare.c diff --git a/thirdparty/opus/opus_custom.h b/thirdparty/opus/opus_custom.h new file mode 100644 index 0000000000..41f36bf2fb --- /dev/null +++ b/thirdparty/opus/opus_custom.h @@ -0,0 +1,342 @@ +/* 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 + +#ifdef CUSTOM_MODES +# 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. + @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); + +# ifdef CUSTOM_MODES +/** 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 a 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); + +/** 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 an 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); + +/** 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/thirdparty/opus/opus_decoder.c b/thirdparty/opus/opus_decoder.c new file mode 100644 index 0000000000..080bec5072 --- /dev/null +++ b/thirdparty/opus/opus_decoder.c @@ -0,0 +1,981 @@ +/* Copyright (c) 2010 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. +*/ + +#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" + +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 arch; + + /* 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; +}; + + +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) + || (channels!=1&&channels!=2)) + return OPUS_BAD_ARG; + + OPUS_CLEAR((char*)st, opus_decoder_get_size(channels)); + /* Initialize SILK encoder */ + 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->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; + 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) + || (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; +} + +static void smooth_fade(const opus_val16 *in1, const opus_val16 *in2, + opus_val16 *out, int overlap, int channels, + const opus_val16 *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 = MULT16_16_Q15(window[i*inc], window[i*inc]); + out[i*channels+c] = SHR32(MAC16_16(MULT16_16(w,in2[i*channels+c]), + Q15ONE-w, in1[i*channels+c]), 15); + } + } +} + +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_val16 *pcm, int frame_size, int decode_fec) +{ + void *silk_dec; + CELTDecoder *celt_dec; + int i, silk_ret=0, celt_ret=0; + ec_dec dec; + opus_int32 silk_frame_size; + int pcm_silk_size; + VARDECL(opus_int16, pcm_silk); + int pcm_transition_silk_size; + VARDECL(opus_val16, pcm_transition_silk); + int pcm_transition_celt_size; + VARDECL(opus_val16, pcm_transition_celt); + opus_val16 *pcm_transition=NULL; + int redundant_audio_size; + VARDECL(opus_val16, redundant_audio); + + int audiosize; + int mode; + 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 opus_val16 *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; + ec_dec_init(&dec,(unsigned char*)data,len); + } else { + audiosize = frame_size; + mode = st->prev_mode; + + 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); + 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. */ +#ifdef FIXED_POINT + celt_accum = (mode != MODE_CELT_ONLY) && (frame_size >= F10); +#else + celt_accum = 0; +#endif + + 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_val16); + if (transition && mode == MODE_CELT_ONLY) + { + pcm_transition = pcm_transition_celt; + opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0); + } + 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; + } + + /* Don't allocate any memory when in CELT-only mode */ + pcm_silk_size = (mode != MODE_CELT_ONLY && !celt_accum) ? IMAX(F10, frame_size)*st->channels : ALLOC_NONE; + ALLOC(pcm_silk, pcm_silk_size, opus_int16); + + /* SILK processing */ + if (mode != MODE_CELT_ONLY) + { + int lost_flag, decoded_samples; + opus_int16 *pcm_ptr; +#ifdef FIXED_POINT + if (celt_accum) + pcm_ptr = pcm; + else +#endif + pcm_ptr = pcm_silk; + + if (st->prev_mode==MODE_CELT_ONLY) + silk_InitDecoder( 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( st->bandwidth == OPUS_BANDWIDTH_NARROWBAND ) { + st->DecControl.internalSampleRate = 8000; + } else if( st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) { + st->DecControl.internalSampleRate = 12000; + } else if( st->bandwidth == OPUS_BANDWIDTH_WIDEBAND ) { + st->DecControl.internalSampleRate = 16000; + } else { + st->DecControl.internalSampleRate = 16000; + silk_assert( 0 ); + } + } else { + /* Hybrid mode */ + st->DecControl.internalSampleRate = 16000; + } + } + + 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, 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 ); + } + + start_band = 0; + if (!decode_fec && mode != MODE_CELT_ONLY && data != NULL + && ec_tell(&dec)+17+20*(st->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; + + { + int endband=21; + + switch(st->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; + } + celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband)); + celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels)); + } + + if (redundancy) + { + transition = 0; + pcm_transition_silk_size=ALLOC_NONE; + } + + ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16); + + if (transition && mode != MODE_CELT_ONLY) + { + pcm_transition = pcm_transition_silk; + opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0); + } + + /* Only allocation memory for redundancy if/when needed */ + redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE; + ALLOC(redundant_audio, redundant_audio_size, opus_val16); + + /* 5 ms redundant frame for CELT->SILK*/ + if (redundancy && celt_to_silk) + { + 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); + celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)); + } + + /* MUST be after PLC */ + celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band)); + + if (mode != MODE_SILK_ONLY) + { + 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) + celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); + /* Decode CELT */ + celt_ret = celt_decode_with_ec(celt_dec, decode_fec ? NULL : data, + len, pcm, celt_frame_size, &dec, celt_accum); + } 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) ) + { + celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); + celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL, celt_accum); + } + } + + if (mode != MODE_CELT_ONLY && !celt_accum) + { +#ifdef FIXED_POINT + for (i=0;i<frame_size*st->channels;i++) + pcm[i] = SAT16(ADD32(pcm[i], pcm_silk[i])); +#else + for (i=0;i<frame_size*st->channels;i++) + pcm[i] = pcm[i] + (opus_val16)((1.f/32768.f)*pcm_silk[i]); +#endif + } + + { + const CELTMode *celt_mode; + 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) + { + celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); + 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); + 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); + } + if (redundancy && celt_to_silk) + { + 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; + x = MULT16_32_P16(pcm[i],gain); + pcm[i] = SATURATE(x, 32767); + } + } + + if (len <= 1) + st->rangeFinal = 0; + else + st->rangeFinal = dec.rng ^ 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_val16 *pcm, int frame_size, int decode_fec, + int self_delimited, opus_int32 *packet_offset, int soft_clip) +{ + 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]; + 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; + 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); + 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); + if (count<0) + return 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); + /* 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); + 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); + 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; + ret = opus_decode_frame(st, data, size[i], pcm+nb_samples*st->channels, frame_size-nb_samples, 0); + 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(pcm, nb_samples, st->channels, st->softclip_mem); + else + st->softclip_mem[0]=st->softclip_mem[1]=0; +#endif + return nb_samples; +} + +#ifdef FIXED_POINT + +int opus_decode(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); +} + +#ifndef DISABLE_FLOAT_API +int opus_decode_float(OpusDecoder *st, const unsigned char *data, + opus_int32 len, float *pcm, int frame_size, int decode_fec) +{ + VARDECL(opus_int16, 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; + } + ALLOC(out, frame_size*st->channels, opus_int16); + + ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0); + if (ret > 0) + { + for (i=0;i<ret*st->channels;i++) + pcm[i] = (1.f/32768.f)*(out[i]); + } + RESTORE_STACK; + return ret; +} +#endif + + +#else +int opus_decode(OpusDecoder *st, const unsigned char *data, + opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec) +{ + VARDECL(float, 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; + } + ALLOC(out, frame_size*st->channels, float); + + ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1); + if (ret > 0) + { + for (i=0;i<ret*st->channels;i++) + pcm[i] = FLOAT2INT16(out[i]); + } + RESTORE_STACK; + return ret; +} + +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); +} + +#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_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_InitDecoder( silk_dec ); + st->stream_channels = st->channels; + st->frame_size = st->Fs/400; + } + 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) + 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_uint32 *value = va_arg(ap, opus_uint32*); + if (!value) + { + goto bad_arg; + } + *value = st->last_packet_duration; + } + break; + 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_decoder_get_nb_samples(const OpusDecoder *dec, + const unsigned char packet[], opus_int32 len) +{ + return opus_packet_get_nb_samples(packet, len, dec->Fs); +} diff --git a/thirdparty/opus/opus_defines.h b/thirdparty/opus/opus_defines.h new file mode 100644 index 0000000000..647ed5d6f2 --- /dev/null +++ b/thirdparty/opus/opus_defines.h @@ -0,0 +1,753 @@ +/* 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) +# ifdef OPUS_BUILD +# 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 */ + +/* 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)) +#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_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr))) +/** @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 + +#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 */ + +/**@}*/ + + +/** @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>Enable inband FEC.</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.</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_VARIABLE</dt><dd>Optimize the frame size dynamically.</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_VARIABLE</dt><dd>Optimize the frame size dynamically.</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) + +/**@}*/ + +/** @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) + +/**@}*/ + +/** @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) + +/**@}*/ + +/** @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/thirdparty/opus/opus_encoder.c b/thirdparty/opus/opus_encoder.c new file mode 100644 index 0000000000..a7e19127d6 --- /dev/null +++ b/thirdparty/opus/opus_encoder.c @@ -0,0 +1,2527 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> +#include "celt.h" +#include "entenc.h" +#include "modes.h" +#include "API.h" +#include "stack_alloc.h" +#include "float_cast.h" +#include "opus.h" +#include "arch.h" +#include "pitch.h" +#include "opus_private.h" +#include "os_support.h" +#include "cpu_support.h" +#include "analysis.h" +#include "mathops.h" +#include "tuning_parameters.h" +#ifdef FIXED_POINT +#include "fixed/structs_FIX.h" +#else +#include "float/structs_FLP.h" +#endif + +#define MAX_ENCODER_BUFFER 480 + +typedef struct { + opus_val32 XX, XY, YY; + opus_val16 smoothed_width; + opus_val16 max_follower; +} StereoWidthState; + +struct OpusEncoder { + int celt_enc_offset; + int silk_enc_offset; + silk_EncControlStruct silk_mode; + int application; + int channels; + int delay_compensation; + int force_channels; + int signal_type; + int user_bandwidth; + int max_bandwidth; + int user_forced_mode; + int voice_ratio; + opus_int32 Fs; + int use_vbr; + int vbr_constraint; + int variable_duration; + opus_int32 bitrate_bps; + opus_int32 user_bitrate_bps; + int lsb_depth; + int encoder_buffer; + int lfe; + int arch; +#ifndef DISABLE_FLOAT_API + TonalityAnalysisState analysis; +#endif + +#define OPUS_ENCODER_RESET_START stream_channels + int stream_channels; + opus_int16 hybrid_stereo_width_Q14; + opus_int32 variable_HP_smth2_Q15; + opus_val16 prev_HB_gain; + opus_val32 hp_mem[4]; + int mode; + int prev_mode; + int prev_channels; + int prev_framesize; + int bandwidth; + int silk_bw_switch; + /* Sampling rate (at the API level) */ + int first; + opus_val16 * energy_masking; + StereoWidthState width_mem; + opus_val16 delay_buffer[MAX_ENCODER_BUFFER*2]; +#ifndef DISABLE_FLOAT_API + int detected_bandwidth; +#endif + opus_uint32 rangeFinal; +}; + +/* Transition tables for the voice and music. First column is the + middle (memoriless) threshold. The second column is the hysteresis + (difference with the middle) */ +static const opus_int32 mono_voice_bandwidth_thresholds[8] = { + 11000, 1000, /* NB<->MB */ + 14000, 1000, /* MB<->WB */ + 17000, 1000, /* WB<->SWB */ + 21000, 2000, /* SWB<->FB */ +}; +static const opus_int32 mono_music_bandwidth_thresholds[8] = { + 12000, 1000, /* NB<->MB */ + 15000, 1000, /* MB<->WB */ + 18000, 2000, /* WB<->SWB */ + 22000, 2000, /* SWB<->FB */ +}; +static const opus_int32 stereo_voice_bandwidth_thresholds[8] = { + 11000, 1000, /* NB<->MB */ + 14000, 1000, /* MB<->WB */ + 21000, 2000, /* WB<->SWB */ + 28000, 2000, /* SWB<->FB */ +}; +static const opus_int32 stereo_music_bandwidth_thresholds[8] = { + 12000, 1000, /* NB<->MB */ + 18000, 2000, /* MB<->WB */ + 21000, 2000, /* WB<->SWB */ + 30000, 2000, /* SWB<->FB */ +}; +/* Threshold bit-rates for switching between mono and stereo */ +static const opus_int32 stereo_voice_threshold = 30000; +static const opus_int32 stereo_music_threshold = 30000; + +/* Threshold bit-rate for switching between SILK/hybrid and CELT-only */ +static const opus_int32 mode_thresholds[2][2] = { + /* voice */ /* music */ + { 64000, 16000}, /* mono */ + { 36000, 16000}, /* stereo */ +}; + +int opus_encoder_get_size(int channels) +{ + int silkEncSizeBytes, celtEncSizeBytes; + int ret; + if (channels<1 || channels > 2) + return 0; + ret = silk_Get_Encoder_Size( &silkEncSizeBytes ); + if (ret) + return 0; + silkEncSizeBytes = align(silkEncSizeBytes); + celtEncSizeBytes = celt_encoder_get_size(channels); + return align(sizeof(OpusEncoder))+silkEncSizeBytes+celtEncSizeBytes; +} + +int opus_encoder_init(OpusEncoder* st, opus_int32 Fs, int channels, int application) +{ + void *silk_enc; + CELTEncoder *celt_enc; + int err; + int ret, silkEncSizeBytes; + + if((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)||(channels!=1&&channels!=2)|| + (application != OPUS_APPLICATION_VOIP && application != OPUS_APPLICATION_AUDIO + && application != OPUS_APPLICATION_RESTRICTED_LOWDELAY)) + return OPUS_BAD_ARG; + + OPUS_CLEAR((char*)st, opus_encoder_get_size(channels)); + /* Create SILK encoder */ + ret = silk_Get_Encoder_Size( &silkEncSizeBytes ); + if (ret) + return OPUS_BAD_ARG; + silkEncSizeBytes = align(silkEncSizeBytes); + st->silk_enc_offset = align(sizeof(OpusEncoder)); + st->celt_enc_offset = st->silk_enc_offset+silkEncSizeBytes; + silk_enc = (char*)st+st->silk_enc_offset; + celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset); + + st->stream_channels = st->channels = channels; + + st->Fs = Fs; + + st->arch = opus_select_arch(); + + ret = silk_InitEncoder( silk_enc, st->arch, &st->silk_mode ); + if(ret)return OPUS_INTERNAL_ERROR; + + /* default SILK parameters */ + st->silk_mode.nChannelsAPI = channels; + st->silk_mode.nChannelsInternal = channels; + st->silk_mode.API_sampleRate = st->Fs; + st->silk_mode.maxInternalSampleRate = 16000; + st->silk_mode.minInternalSampleRate = 8000; + st->silk_mode.desiredInternalSampleRate = 16000; + st->silk_mode.payloadSize_ms = 20; + st->silk_mode.bitRate = 25000; + st->silk_mode.packetLossPercentage = 0; + st->silk_mode.complexity = 9; + st->silk_mode.useInBandFEC = 0; + st->silk_mode.useDTX = 0; + st->silk_mode.useCBR = 0; + st->silk_mode.reducedDependency = 0; + + /* Create CELT encoder */ + /* Initialize CELT encoder */ + err = celt_encoder_init(celt_enc, Fs, channels, st->arch); + if(err!=OPUS_OK)return OPUS_INTERNAL_ERROR; + + celt_encoder_ctl(celt_enc, CELT_SET_SIGNALLING(0)); + celt_encoder_ctl(celt_enc, OPUS_SET_COMPLEXITY(st->silk_mode.complexity)); + + st->use_vbr = 1; + /* Makes constrained VBR the default (safer for real-time use) */ + st->vbr_constraint = 1; + st->user_bitrate_bps = OPUS_AUTO; + st->bitrate_bps = 3000+Fs*channels; + st->application = application; + st->signal_type = OPUS_AUTO; + st->user_bandwidth = OPUS_AUTO; + st->max_bandwidth = OPUS_BANDWIDTH_FULLBAND; + st->force_channels = OPUS_AUTO; + st->user_forced_mode = OPUS_AUTO; + st->voice_ratio = -1; + st->encoder_buffer = st->Fs/100; + st->lsb_depth = 24; + st->variable_duration = OPUS_FRAMESIZE_ARG; + + /* Delay compensation of 4 ms (2.5 ms for SILK's extra look-ahead + + 1.5 ms for SILK resamplers and stereo prediction) */ + st->delay_compensation = st->Fs/250; + + st->hybrid_stereo_width_Q14 = 1 << 14; + st->prev_HB_gain = Q15ONE; + st->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ); + st->first = 1; + st->mode = MODE_HYBRID; + st->bandwidth = OPUS_BANDWIDTH_FULLBAND; + +#ifndef DISABLE_FLOAT_API + tonality_analysis_init(&st->analysis); +#endif + + return OPUS_OK; +} + +static unsigned char gen_toc(int mode, int framerate, int bandwidth, int channels) +{ + int period; + unsigned char toc; + period = 0; + while (framerate < 400) + { + framerate <<= 1; + period++; + } + if (mode == MODE_SILK_ONLY) + { + toc = (bandwidth-OPUS_BANDWIDTH_NARROWBAND)<<5; + toc |= (period-2)<<3; + } else if (mode == MODE_CELT_ONLY) + { + int tmp = bandwidth-OPUS_BANDWIDTH_MEDIUMBAND; + if (tmp < 0) + tmp = 0; + toc = 0x80; + toc |= tmp << 5; + toc |= period<<3; + } else /* Hybrid */ + { + toc = 0x60; + toc |= (bandwidth-OPUS_BANDWIDTH_SUPERWIDEBAND)<<4; + toc |= (period-2)<<3; + } + toc |= (channels==2)<<2; + return toc; +} + +#ifndef FIXED_POINT +static void silk_biquad_float( + const opus_val16 *in, /* I: Input signal */ + const opus_int32 *B_Q28, /* I: MA coefficients [3] */ + const opus_int32 *A_Q28, /* I: AR coefficients [2] */ + opus_val32 *S, /* I/O: State vector [2] */ + opus_val16 *out, /* O: Output signal */ + const opus_int32 len, /* I: Signal length (must be even) */ + int stride +) +{ + /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */ + opus_int k; + opus_val32 vout; + opus_val32 inval; + opus_val32 A[2], B[3]; + + A[0] = (opus_val32)(A_Q28[0] * (1.f/((opus_int32)1<<28))); + A[1] = (opus_val32)(A_Q28[1] * (1.f/((opus_int32)1<<28))); + B[0] = (opus_val32)(B_Q28[0] * (1.f/((opus_int32)1<<28))); + B[1] = (opus_val32)(B_Q28[1] * (1.f/((opus_int32)1<<28))); + B[2] = (opus_val32)(B_Q28[2] * (1.f/((opus_int32)1<<28))); + + /* Negate A_Q28 values and split in two parts */ + + for( k = 0; k < len; k++ ) { + /* S[ 0 ], S[ 1 ]: Q12 */ + inval = in[ k*stride ]; + vout = S[ 0 ] + B[0]*inval; + + S[ 0 ] = S[1] - vout*A[0] + B[1]*inval; + + S[ 1 ] = - vout*A[1] + B[2]*inval + VERY_SMALL; + + /* Scale back to Q0 and saturate */ + out[ k*stride ] = vout; + } +} +#endif + +static void hp_cutoff(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs) +{ + opus_int32 B_Q28[ 3 ], A_Q28[ 2 ]; + opus_int32 Fc_Q19, r_Q28, r_Q22; + + silk_assert( cutoff_Hz <= silk_int32_MAX / SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ) ); + Fc_Q19 = silk_DIV32_16( silk_SMULBB( SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ), cutoff_Hz ), Fs/1000 ); + silk_assert( Fc_Q19 > 0 && Fc_Q19 < 32768 ); + + r_Q28 = SILK_FIX_CONST( 1.0, 28 ) - silk_MUL( SILK_FIX_CONST( 0.92, 9 ), Fc_Q19 ); + + /* b = r * [ 1; -2; 1 ]; */ + /* a = [ 1; -2 * r * ( 1 - 0.5 * Fc^2 ); r^2 ]; */ + B_Q28[ 0 ] = r_Q28; + B_Q28[ 1 ] = silk_LSHIFT( -r_Q28, 1 ); + B_Q28[ 2 ] = r_Q28; + + /* -r * ( 2 - Fc * Fc ); */ + r_Q22 = silk_RSHIFT( r_Q28, 6 ); + A_Q28[ 0 ] = silk_SMULWW( r_Q22, silk_SMULWW( Fc_Q19, Fc_Q19 ) - SILK_FIX_CONST( 2.0, 22 ) ); + A_Q28[ 1 ] = silk_SMULWW( r_Q22, r_Q22 ); + +#ifdef FIXED_POINT + silk_biquad_alt( in, B_Q28, A_Q28, hp_mem, out, len, channels ); + if( channels == 2 ) { + silk_biquad_alt( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels ); + } +#else + silk_biquad_float( in, B_Q28, A_Q28, hp_mem, out, len, channels ); + if( channels == 2 ) { + silk_biquad_float( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels ); + } +#endif +} + +#ifdef FIXED_POINT +static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs) +{ + int c, i; + int shift; + + /* Approximates -round(log2(4.*cutoff_Hz/Fs)) */ + shift=celt_ilog2(Fs/(cutoff_Hz*3)); + for (c=0;c<channels;c++) + { + for (i=0;i<len;i++) + { + opus_val32 x, tmp, y; + x = SHL32(EXTEND32(in[channels*i+c]), 15); + /* First stage */ + tmp = x-hp_mem[2*c]; + hp_mem[2*c] = hp_mem[2*c] + PSHR32(x - hp_mem[2*c], shift); + /* Second stage */ + y = tmp - hp_mem[2*c+1]; + hp_mem[2*c+1] = hp_mem[2*c+1] + PSHR32(tmp - hp_mem[2*c+1], shift); + out[channels*i+c] = EXTRACT16(SATURATE(PSHR32(y, 15), 32767)); + } + } +} + +#else +static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs) +{ + int c, i; + float coef; + + coef = 4.0f*cutoff_Hz/Fs; + for (c=0;c<channels;c++) + { + for (i=0;i<len;i++) + { + opus_val32 x, tmp, y; + x = in[channels*i+c]; + /* First stage */ + tmp = x-hp_mem[2*c]; + hp_mem[2*c] = hp_mem[2*c] + coef*(x - hp_mem[2*c]) + VERY_SMALL; + /* Second stage */ + y = tmp - hp_mem[2*c+1]; + hp_mem[2*c+1] = hp_mem[2*c+1] + coef*(tmp - hp_mem[2*c+1]) + VERY_SMALL; + out[channels*i+c] = y; + } + } +} +#endif + +static void stereo_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus_val16 g2, + int overlap48, int frame_size, int channels, const opus_val16 *window, opus_int32 Fs) +{ + int i; + int overlap; + int inc; + inc = 48000/Fs; + overlap=overlap48/inc; + g1 = Q15ONE-g1; + g2 = Q15ONE-g2; + for (i=0;i<overlap;i++) + { + opus_val32 diff; + opus_val16 g, w; + w = MULT16_16_Q15(window[i*inc], window[i*inc]); + g = SHR32(MAC16_16(MULT16_16(w,g2), + Q15ONE-w, g1), 15); + diff = EXTRACT16(HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1])); + diff = MULT16_16_Q15(g, diff); + out[i*channels] = out[i*channels] - diff; + out[i*channels+1] = out[i*channels+1] + diff; + } + for (;i<frame_size;i++) + { + opus_val32 diff; + diff = EXTRACT16(HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1])); + diff = MULT16_16_Q15(g2, diff); + out[i*channels] = out[i*channels] - diff; + out[i*channels+1] = out[i*channels+1] + diff; + } +} + +static void gain_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus_val16 g2, + int overlap48, int frame_size, int channels, const opus_val16 *window, opus_int32 Fs) +{ + int i; + int inc; + int overlap; + int c; + inc = 48000/Fs; + overlap=overlap48/inc; + if (channels==1) + { + for (i=0;i<overlap;i++) + { + opus_val16 g, w; + w = MULT16_16_Q15(window[i*inc], window[i*inc]); + g = SHR32(MAC16_16(MULT16_16(w,g2), + Q15ONE-w, g1), 15); + out[i] = MULT16_16_Q15(g, in[i]); + } + } else { + for (i=0;i<overlap;i++) + { + opus_val16 g, w; + w = MULT16_16_Q15(window[i*inc], window[i*inc]); + g = SHR32(MAC16_16(MULT16_16(w,g2), + Q15ONE-w, g1), 15); + out[i*2] = MULT16_16_Q15(g, in[i*2]); + out[i*2+1] = MULT16_16_Q15(g, in[i*2+1]); + } + } + c=0;do { + for (i=overlap;i<frame_size;i++) + { + out[i*channels+c] = MULT16_16_Q15(g2, in[i*channels+c]); + } + } + while (++c<channels); +} + +OpusEncoder *opus_encoder_create(opus_int32 Fs, int channels, int application, int *error) +{ + int ret; + OpusEncoder *st; + if((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)||(channels!=1&&channels!=2)|| + (application != OPUS_APPLICATION_VOIP && application != OPUS_APPLICATION_AUDIO + && application != OPUS_APPLICATION_RESTRICTED_LOWDELAY)) + { + if (error) + *error = OPUS_BAD_ARG; + return NULL; + } + st = (OpusEncoder *)opus_alloc(opus_encoder_get_size(channels)); + if (st == NULL) + { + if (error) + *error = OPUS_ALLOC_FAIL; + return NULL; + } + ret = opus_encoder_init(st, Fs, channels, application); + if (error) + *error = ret; + if (ret != OPUS_OK) + { + opus_free(st); + st = NULL; + } + return st; +} + +static opus_int32 user_bitrate_to_bitrate(OpusEncoder *st, int frame_size, int max_data_bytes) +{ + if(!frame_size)frame_size=st->Fs/400; + if (st->user_bitrate_bps==OPUS_AUTO) + return 60*st->Fs/frame_size + st->Fs*st->channels; + else if (st->user_bitrate_bps==OPUS_BITRATE_MAX) + return max_data_bytes*8*st->Fs/frame_size; + else + return st->user_bitrate_bps; +} + +#ifndef DISABLE_FLOAT_API +/* Don't use more than 60 ms for the frame size analysis */ +#define MAX_DYNAMIC_FRAMESIZE 24 +/* Estimates how much the bitrate will be boosted based on the sub-frame energy */ +static float transient_boost(const float *E, const float *E_1, int LM, int maxM) +{ + int i; + int M; + float sumE=0, sumE_1=0; + float metric; + + M = IMIN(maxM, (1<<LM)+1); + for (i=0;i<M;i++) + { + sumE += E[i]; + sumE_1 += E_1[i]; + } + metric = sumE*sumE_1/(M*M); + /*if (LM==3) + printf("%f\n", metric);*/ + /*return metric>10 ? 1 : 0;*/ + /*return MAX16(0,1-exp(-.25*(metric-2.)));*/ + return MIN16(1,(float)sqrt(MAX16(0,.05f*(metric-2)))); +} + +/* Viterbi decoding trying to find the best frame size combination using look-ahead + + State numbering: + 0: unused + 1: 2.5 ms + 2: 5 ms (#1) + 3: 5 ms (#2) + 4: 10 ms (#1) + 5: 10 ms (#2) + 6: 10 ms (#3) + 7: 10 ms (#4) + 8: 20 ms (#1) + 9: 20 ms (#2) + 10: 20 ms (#3) + 11: 20 ms (#4) + 12: 20 ms (#5) + 13: 20 ms (#6) + 14: 20 ms (#7) + 15: 20 ms (#8) +*/ +static int transient_viterbi(const float *E, const float *E_1, int N, int frame_cost, int rate) +{ + int i; + float cost[MAX_DYNAMIC_FRAMESIZE][16]; + int states[MAX_DYNAMIC_FRAMESIZE][16]; + float best_cost; + int best_state; + float factor; + /* Take into account that we damp VBR in the 32 kb/s to 64 kb/s range. */ + if (rate<80) + factor=0; + else if (rate>160) + factor=1; + else + factor = (rate-80.f)/80.f; + /* Makes variable framesize less aggressive at lower bitrates, but I can't + find any valid theoretical justification for this (other than it seems + to help) */ + for (i=0;i<16;i++) + { + /* Impossible state */ + states[0][i] = -1; + cost[0][i] = 1e10; + } + for (i=0;i<4;i++) + { + cost[0][1<<i] = (frame_cost + rate*(1<<i))*(1+factor*transient_boost(E, E_1, i, N+1)); + states[0][1<<i] = i; + } + for (i=1;i<N;i++) + { + int j; + + /* Follow continuations */ + for (j=2;j<16;j++) + { + cost[i][j] = cost[i-1][j-1]; + states[i][j] = j-1; + } + + /* New frames */ + for(j=0;j<4;j++) + { + int k; + float min_cost; + float curr_cost; + states[i][1<<j] = 1; + min_cost = cost[i-1][1]; + for(k=1;k<4;k++) + { + float tmp = cost[i-1][(1<<(k+1))-1]; + if (tmp < min_cost) + { + states[i][1<<j] = (1<<(k+1))-1; + min_cost = tmp; + } + } + curr_cost = (frame_cost + rate*(1<<j))*(1+factor*transient_boost(E+i, E_1+i, j, N-i+1)); + cost[i][1<<j] = min_cost; + /* If part of the frame is outside the analysis window, only count part of the cost */ + if (N-i < (1<<j)) + cost[i][1<<j] += curr_cost*(float)(N-i)/(1<<j); + else + cost[i][1<<j] += curr_cost; + } + } + + best_state=1; + best_cost = cost[N-1][1]; + /* Find best end state (doesn't force a frame to end at N-1) */ + for (i=2;i<16;i++) + { + if (cost[N-1][i]<best_cost) + { + best_cost = cost[N-1][i]; + best_state = i; + } + } + + /* Follow transitions back */ + for (i=N-1;i>=0;i--) + { + /*printf("%d ", best_state);*/ + best_state = states[i][best_state]; + } + /*printf("%d\n", best_state);*/ + return best_state; +} + +static int optimize_framesize(const void *x, int len, int C, opus_int32 Fs, + int bitrate, opus_val16 tonality, float *mem, int buffering, + downmix_func downmix) +{ + int N; + int i; + float e[MAX_DYNAMIC_FRAMESIZE+4]; + float e_1[MAX_DYNAMIC_FRAMESIZE+3]; + opus_val32 memx; + int bestLM=0; + int subframe; + int pos; + int offset; + VARDECL(opus_val32, sub); + + subframe = Fs/400; + ALLOC(sub, subframe, opus_val32); + e[0]=mem[0]; + e_1[0]=1.f/(EPSILON+mem[0]); + if (buffering) + { + /* Consider the CELT delay when not in restricted-lowdelay */ + /* We assume the buffering is between 2.5 and 5 ms */ + offset = 2*subframe - buffering; + celt_assert(offset>=0 && offset <= subframe); + len -= offset; + e[1]=mem[1]; + e_1[1]=1.f/(EPSILON+mem[1]); + e[2]=mem[2]; + e_1[2]=1.f/(EPSILON+mem[2]); + pos = 3; + } else { + pos=1; + offset=0; + } + N=IMIN(len/subframe, MAX_DYNAMIC_FRAMESIZE); + /* Just silencing a warning, it's really initialized later */ + memx = 0; + for (i=0;i<N;i++) + { + float tmp; + opus_val32 tmpx; + int j; + tmp=EPSILON; + + downmix(x, sub, subframe, i*subframe+offset, 0, -2, C); + if (i==0) + memx = sub[0]; + for (j=0;j<subframe;j++) + { + tmpx = sub[j]; + tmp += (tmpx-memx)*(float)(tmpx-memx); + memx = tmpx; + } + e[i+pos] = tmp; + e_1[i+pos] = 1.f/tmp; + } + /* Hack to get 20 ms working with APPLICATION_AUDIO + The real problem is that the corresponding memory needs to use 1.5 ms + from this frame and 1 ms from the next frame */ + e[i+pos] = e[i+pos-1]; + if (buffering) + N=IMIN(MAX_DYNAMIC_FRAMESIZE, N+2); + bestLM = transient_viterbi(e, e_1, N, (int)((1.f+.5f*tonality)*(60*C+40)), bitrate/400); + mem[0] = e[1<<bestLM]; + if (buffering) + { + mem[1] = e[(1<<bestLM)+1]; + mem[2] = e[(1<<bestLM)+2]; + } + return bestLM; +} + +#endif + +#ifndef DISABLE_FLOAT_API +#ifdef FIXED_POINT +#define PCM2VAL(x) FLOAT2INT16(x) +#else +#define PCM2VAL(x) SCALEIN(x) +#endif +void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C) +{ + const float *x; + opus_val32 scale; + int j; + x = (const float *)_x; + for (j=0;j<subframe;j++) + sub[j] = PCM2VAL(x[(j+offset)*C+c1]); + if (c2>-1) + { + for (j=0;j<subframe;j++) + sub[j] += PCM2VAL(x[(j+offset)*C+c2]); + } else if (c2==-2) + { + int c; + for (c=1;c<C;c++) + { + for (j=0;j<subframe;j++) + sub[j] += PCM2VAL(x[(j+offset)*C+c]); + } + } +#ifdef FIXED_POINT + scale = (1<<SIG_SHIFT); +#else + scale = 1.f; +#endif + if (C==-2) + scale /= C; + else + scale /= 2; + for (j=0;j<subframe;j++) + sub[j] *= scale; +} +#endif + +void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C) +{ + const opus_int16 *x; + opus_val32 scale; + int j; + x = (const opus_int16 *)_x; + for (j=0;j<subframe;j++) + sub[j] = x[(j+offset)*C+c1]; + if (c2>-1) + { + for (j=0;j<subframe;j++) + sub[j] += x[(j+offset)*C+c2]; + } else if (c2==-2) + { + int c; + for (c=1;c<C;c++) + { + for (j=0;j<subframe;j++) + sub[j] += x[(j+offset)*C+c]; + } + } +#ifdef FIXED_POINT + scale = (1<<SIG_SHIFT); +#else + scale = 1.f/32768; +#endif + if (C==-2) + scale /= C; + else + scale /= 2; + for (j=0;j<subframe;j++) + sub[j] *= scale; +} + +opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs) +{ + int new_size; + if (frame_size<Fs/400) + return -1; + if (variable_duration == OPUS_FRAMESIZE_ARG) + new_size = frame_size; + else if (variable_duration == OPUS_FRAMESIZE_VARIABLE) + new_size = Fs/50; + else if (variable_duration >= OPUS_FRAMESIZE_2_5_MS && variable_duration <= OPUS_FRAMESIZE_60_MS) + new_size = IMIN(3*Fs/50, (Fs/400)<<(variable_duration-OPUS_FRAMESIZE_2_5_MS)); + else + return -1; + if (new_size>frame_size) + return -1; + if (400*new_size!=Fs && 200*new_size!=Fs && 100*new_size!=Fs && + 50*new_size!=Fs && 25*new_size!=Fs && 50*new_size!=3*Fs) + return -1; + return new_size; +} + +opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size, + int variable_duration, int C, opus_int32 Fs, int bitrate_bps, + int delay_compensation, downmix_func downmix +#ifndef DISABLE_FLOAT_API + , float *subframe_mem +#endif + ) +{ +#ifndef DISABLE_FLOAT_API + if (variable_duration == OPUS_FRAMESIZE_VARIABLE && frame_size >= Fs/200) + { + int LM = 3; + LM = optimize_framesize(analysis_pcm, frame_size, C, Fs, bitrate_bps, + 0, subframe_mem, delay_compensation, downmix); + while ((Fs/400<<LM)>frame_size) + LM--; + frame_size = (Fs/400<<LM); + } else +#else + (void)analysis_pcm; + (void)C; + (void)bitrate_bps; + (void)delay_compensation; + (void)downmix; +#endif + { + frame_size = frame_size_select(frame_size, variable_duration, Fs); + } + if (frame_size<0) + return -1; + return frame_size; +} + +opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int32 Fs, StereoWidthState *mem) +{ + opus_val16 corr; + opus_val16 ldiff; + opus_val16 width; + opus_val32 xx, xy, yy; + opus_val16 sqrt_xx, sqrt_yy; + opus_val16 qrrt_xx, qrrt_yy; + int frame_rate; + int i; + opus_val16 short_alpha; + + frame_rate = Fs/frame_size; + short_alpha = Q15ONE - 25*Q15ONE/IMAX(50,frame_rate); + xx=xy=yy=0; + for (i=0;i<frame_size;i+=4) + { + opus_val32 pxx=0; + opus_val32 pxy=0; + opus_val32 pyy=0; + opus_val16 x, y; + x = pcm[2*i]; + y = pcm[2*i+1]; + pxx = SHR32(MULT16_16(x,x),2); + pxy = SHR32(MULT16_16(x,y),2); + pyy = SHR32(MULT16_16(y,y),2); + x = pcm[2*i+2]; + y = pcm[2*i+3]; + pxx += SHR32(MULT16_16(x,x),2); + pxy += SHR32(MULT16_16(x,y),2); + pyy += SHR32(MULT16_16(y,y),2); + x = pcm[2*i+4]; + y = pcm[2*i+5]; + pxx += SHR32(MULT16_16(x,x),2); + pxy += SHR32(MULT16_16(x,y),2); + pyy += SHR32(MULT16_16(y,y),2); + x = pcm[2*i+6]; + y = pcm[2*i+7]; + pxx += SHR32(MULT16_16(x,x),2); + pxy += SHR32(MULT16_16(x,y),2); + pyy += SHR32(MULT16_16(y,y),2); + + xx += SHR32(pxx, 10); + xy += SHR32(pxy, 10); + yy += SHR32(pyy, 10); + } + mem->XX += MULT16_32_Q15(short_alpha, xx-mem->XX); + mem->XY += MULT16_32_Q15(short_alpha, xy-mem->XY); + mem->YY += MULT16_32_Q15(short_alpha, yy-mem->YY); + mem->XX = MAX32(0, mem->XX); + mem->XY = MAX32(0, mem->XY); + mem->YY = MAX32(0, mem->YY); + if (MAX32(mem->XX, mem->YY)>QCONST16(8e-4f, 18)) + { + sqrt_xx = celt_sqrt(mem->XX); + sqrt_yy = celt_sqrt(mem->YY); + qrrt_xx = celt_sqrt(sqrt_xx); + qrrt_yy = celt_sqrt(sqrt_yy); + /* Inter-channel correlation */ + mem->XY = MIN32(mem->XY, sqrt_xx*sqrt_yy); + corr = SHR32(frac_div32(mem->XY,EPSILON+MULT16_16(sqrt_xx,sqrt_yy)),16); + /* Approximate loudness difference */ + ldiff = Q15ONE*ABS16(qrrt_xx-qrrt_yy)/(EPSILON+qrrt_xx+qrrt_yy); + width = MULT16_16_Q15(celt_sqrt(QCONST32(1.f,30)-MULT16_16(corr,corr)), ldiff); + /* Smoothing over one second */ + mem->smoothed_width += (width-mem->smoothed_width)/frame_rate; + /* Peak follower */ + mem->max_follower = MAX16(mem->max_follower-QCONST16(.02f,15)/frame_rate, mem->smoothed_width); + } else { + width = 0; + corr=Q15ONE; + ldiff=0; + } + /*printf("%f %f %f %f %f ", corr/(float)Q15ONE, ldiff/(float)Q15ONE, width/(float)Q15ONE, mem->smoothed_width/(float)Q15ONE, mem->max_follower/(float)Q15ONE);*/ + return EXTRACT16(MIN32(Q15ONE,20*mem->max_follower)); +} + +opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *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) +{ + void *silk_enc; + CELTEncoder *celt_enc; + int i; + int ret=0; + opus_int32 nBytes; + ec_enc enc; + int bytes_target; + int prefill=0; + int start_band = 0; + int redundancy = 0; + int redundancy_bytes = 0; /* Number of bytes to use for redundancy frame */ + int celt_to_silk = 0; + VARDECL(opus_val16, pcm_buf); + int nb_compr_bytes; + int to_celt = 0; + opus_uint32 redundant_rng = 0; + int cutoff_Hz, hp_freq_smth1; + int voice_est; /* Probability of voice in Q7 */ + opus_int32 equiv_rate; + int delay_compensation; + int frame_rate; + opus_int32 max_rate; /* Max bitrate we're allowed to use */ + int curr_bandwidth; + opus_val16 HB_gain; + opus_int32 max_data_bytes; /* Max number of bytes we're allowed to use */ + int total_buffer; + opus_val16 stereo_width; + const CELTMode *celt_mode; +#ifndef DISABLE_FLOAT_API + AnalysisInfo analysis_info; + int analysis_read_pos_bak=-1; + int analysis_read_subframe_bak=-1; +#endif + VARDECL(opus_val16, tmp_prefill); + + ALLOC_STACK; + + max_data_bytes = IMIN(1276, out_data_bytes); + + st->rangeFinal = 0; + if ((!st->variable_duration && 400*frame_size != st->Fs && 200*frame_size != st->Fs && 100*frame_size != st->Fs && + 50*frame_size != st->Fs && 25*frame_size != st->Fs && 50*frame_size != 3*st->Fs) + || (400*frame_size < st->Fs) + || max_data_bytes<=0 + ) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + silk_enc = (char*)st+st->silk_enc_offset; + celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset); + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + delay_compensation = 0; + else + delay_compensation = st->delay_compensation; + + lsb_depth = IMIN(lsb_depth, st->lsb_depth); + + celt_encoder_ctl(celt_enc, CELT_GET_MODE(&celt_mode)); +#ifndef DISABLE_FLOAT_API + analysis_info.valid = 0; +#ifdef FIXED_POINT + if (st->silk_mode.complexity >= 10 && st->Fs==48000) +#else + if (st->silk_mode.complexity >= 7 && st->Fs==48000) +#endif + { + analysis_read_pos_bak = st->analysis.read_pos; + analysis_read_subframe_bak = st->analysis.read_subframe; + run_analysis(&st->analysis, celt_mode, analysis_pcm, analysis_size, frame_size, + c1, c2, analysis_channels, st->Fs, + lsb_depth, downmix, &analysis_info); + } +#else + (void)analysis_pcm; + (void)analysis_size; +#endif + + st->voice_ratio = -1; + +#ifndef DISABLE_FLOAT_API + st->detected_bandwidth = 0; + if (analysis_info.valid) + { + int analysis_bandwidth; + if (st->signal_type == OPUS_AUTO) + st->voice_ratio = (int)floor(.5+100*(1-analysis_info.music_prob)); + + analysis_bandwidth = analysis_info.bandwidth; + if (analysis_bandwidth<=12) + st->detected_bandwidth = OPUS_BANDWIDTH_NARROWBAND; + else if (analysis_bandwidth<=14) + st->detected_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; + else if (analysis_bandwidth<=16) + st->detected_bandwidth = OPUS_BANDWIDTH_WIDEBAND; + else if (analysis_bandwidth<=18) + st->detected_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; + else + st->detected_bandwidth = OPUS_BANDWIDTH_FULLBAND; + } +#endif + + if (st->channels==2 && st->force_channels!=1) + stereo_width = compute_stereo_width(pcm, frame_size, st->Fs, &st->width_mem); + else + stereo_width = 0; + total_buffer = delay_compensation; + st->bitrate_bps = user_bitrate_to_bitrate(st, frame_size, max_data_bytes); + + frame_rate = st->Fs/frame_size; + if (max_data_bytes<3 || st->bitrate_bps < 3*frame_rate*8 + || (frame_rate<50 && (max_data_bytes*frame_rate<300 || st->bitrate_bps < 2400))) + { + /*If the space is too low to do something useful, emit 'PLC' frames.*/ + int tocmode = st->mode; + int bw = st->bandwidth == 0 ? OPUS_BANDWIDTH_NARROWBAND : st->bandwidth; + if (tocmode==0) + tocmode = MODE_SILK_ONLY; + if (frame_rate>100) + tocmode = MODE_CELT_ONLY; + if (frame_rate < 50) + tocmode = MODE_SILK_ONLY; + if(tocmode==MODE_SILK_ONLY&&bw>OPUS_BANDWIDTH_WIDEBAND) + bw=OPUS_BANDWIDTH_WIDEBAND; + else if (tocmode==MODE_CELT_ONLY&&bw==OPUS_BANDWIDTH_MEDIUMBAND) + bw=OPUS_BANDWIDTH_NARROWBAND; + else if (bw<=OPUS_BANDWIDTH_SUPERWIDEBAND) + bw=OPUS_BANDWIDTH_SUPERWIDEBAND; + data[0] = gen_toc(tocmode, frame_rate, bw, st->stream_channels); + RESTORE_STACK; + return 1; + } + if (!st->use_vbr) + { + int cbrBytes; + cbrBytes = IMIN( (st->bitrate_bps + 4*frame_rate)/(8*frame_rate) , max_data_bytes); + st->bitrate_bps = cbrBytes * (8*frame_rate); + max_data_bytes = cbrBytes; + } + max_rate = frame_rate*max_data_bytes*8; + + /* Equivalent 20-ms rate for mode/channel/bandwidth decisions */ + equiv_rate = st->bitrate_bps - (40*st->channels+20)*(st->Fs/frame_size - 50); + + if (st->signal_type == OPUS_SIGNAL_VOICE) + voice_est = 127; + else if (st->signal_type == OPUS_SIGNAL_MUSIC) + voice_est = 0; + else if (st->voice_ratio >= 0) + { + voice_est = st->voice_ratio*327>>8; + /* For AUDIO, never be more than 90% confident of having speech */ + if (st->application == OPUS_APPLICATION_AUDIO) + voice_est = IMIN(voice_est, 115); + } else if (st->application == OPUS_APPLICATION_VOIP) + voice_est = 115; + else + voice_est = 48; + + if (st->force_channels!=OPUS_AUTO && st->channels == 2) + { + st->stream_channels = st->force_channels; + } else { +#ifdef FUZZING + /* Random mono/stereo decision */ + if (st->channels == 2 && (rand()&0x1F)==0) + st->stream_channels = 3-st->stream_channels; +#else + /* Rate-dependent mono-stereo decision */ + if (st->channels == 2) + { + opus_int32 stereo_threshold; + stereo_threshold = stereo_music_threshold + ((voice_est*voice_est*(stereo_voice_threshold-stereo_music_threshold))>>14); + if (st->stream_channels == 2) + stereo_threshold -= 1000; + else + stereo_threshold += 1000; + st->stream_channels = (equiv_rate > stereo_threshold) ? 2 : 1; + } else { + st->stream_channels = st->channels; + } +#endif + } + equiv_rate = st->bitrate_bps - (40*st->stream_channels+20)*(st->Fs/frame_size - 50); + + /* Mode selection depending on application and signal type */ + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + { + st->mode = MODE_CELT_ONLY; + } else if (st->user_forced_mode == OPUS_AUTO) + { +#ifdef FUZZING + /* Random mode switching */ + if ((rand()&0xF)==0) + { + if ((rand()&0x1)==0) + st->mode = MODE_CELT_ONLY; + else + st->mode = MODE_SILK_ONLY; + } else { + if (st->prev_mode==MODE_CELT_ONLY) + st->mode = MODE_CELT_ONLY; + else + st->mode = MODE_SILK_ONLY; + } +#else + opus_int32 mode_voice, mode_music; + opus_int32 threshold; + + /* Interpolate based on stereo width */ + mode_voice = (opus_int32)(MULT16_32_Q15(Q15ONE-stereo_width,mode_thresholds[0][0]) + + MULT16_32_Q15(stereo_width,mode_thresholds[1][0])); + mode_music = (opus_int32)(MULT16_32_Q15(Q15ONE-stereo_width,mode_thresholds[1][1]) + + MULT16_32_Q15(stereo_width,mode_thresholds[1][1])); + /* Interpolate based on speech/music probability */ + threshold = mode_music + ((voice_est*voice_est*(mode_voice-mode_music))>>14); + /* Bias towards SILK for VoIP because of some useful features */ + if (st->application == OPUS_APPLICATION_VOIP) + threshold += 8000; + + /*printf("%f %d\n", stereo_width/(float)Q15ONE, threshold);*/ + /* Hysteresis */ + if (st->prev_mode == MODE_CELT_ONLY) + threshold -= 4000; + else if (st->prev_mode>0) + threshold += 4000; + + st->mode = (equiv_rate >= threshold) ? MODE_CELT_ONLY: MODE_SILK_ONLY; + + /* When FEC is enabled and there's enough packet loss, use SILK */ + if (st->silk_mode.useInBandFEC && st->silk_mode.packetLossPercentage > (128-voice_est)>>4) + st->mode = MODE_SILK_ONLY; + /* When encoding voice and DTX is enabled, set the encoder to SILK mode (at least for now) */ + if (st->silk_mode.useDTX && voice_est > 100) + st->mode = MODE_SILK_ONLY; +#endif + } else { + st->mode = st->user_forced_mode; + } + + /* Override the chosen mode to make sure we meet the requested frame size */ + if (st->mode != MODE_CELT_ONLY && frame_size < st->Fs/100) + st->mode = MODE_CELT_ONLY; + if (st->lfe) + st->mode = MODE_CELT_ONLY; + /* If max_data_bytes represents less than 8 kb/s, switch to CELT-only mode */ + if (max_data_bytes < (frame_rate > 50 ? 12000 : 8000)*frame_size / (st->Fs * 8)) + st->mode = MODE_CELT_ONLY; + + if (st->stream_channels == 1 && st->prev_channels ==2 && st->silk_mode.toMono==0 + && st->mode != MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY) + { + /* Delay stereo->mono transition by two frames so that SILK can do a smooth downmix */ + st->silk_mode.toMono = 1; + st->stream_channels = 2; + } else { + st->silk_mode.toMono = 0; + } + + if (st->prev_mode > 0 && + ((st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) || + (st->mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY))) + { + redundancy = 1; + celt_to_silk = (st->mode != MODE_CELT_ONLY); + if (!celt_to_silk) + { + /* Switch to SILK/hybrid if frame size is 10 ms or more*/ + if (frame_size >= st->Fs/100) + { + st->mode = st->prev_mode; + to_celt = 1; + } else { + redundancy=0; + } + } + } + /* For the first frame at a new SILK bandwidth */ + if (st->silk_bw_switch) + { + redundancy = 1; + celt_to_silk = 1; + st->silk_bw_switch = 0; + prefill=1; + } + + if (redundancy) + { + /* Fair share of the max size allowed */ + redundancy_bytes = IMIN(257, max_data_bytes*(opus_int32)(st->Fs/200)/(frame_size+st->Fs/200)); + /* For VBR, target the actual bitrate (subject to the limit above) */ + if (st->use_vbr) + redundancy_bytes = IMIN(redundancy_bytes, st->bitrate_bps/1600); + } + + if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) + { + silk_EncControlStruct dummy; + silk_InitEncoder( silk_enc, st->arch, &dummy); + prefill=1; + } + + /* Automatic (rate-dependent) bandwidth selection */ + if (st->mode == MODE_CELT_ONLY || st->first || st->silk_mode.allowBandwidthSwitch) + { + const opus_int32 *voice_bandwidth_thresholds, *music_bandwidth_thresholds; + opus_int32 bandwidth_thresholds[8]; + int bandwidth = OPUS_BANDWIDTH_FULLBAND; + opus_int32 equiv_rate2; + + equiv_rate2 = equiv_rate; + if (st->mode != MODE_CELT_ONLY) + { + /* Adjust the threshold +/- 10% depending on complexity */ + equiv_rate2 = equiv_rate2 * (45+st->silk_mode.complexity)/50; + /* CBR is less efficient by ~1 kb/s */ + if (!st->use_vbr) + equiv_rate2 -= 1000; + } + if (st->channels==2 && st->force_channels!=1) + { + voice_bandwidth_thresholds = stereo_voice_bandwidth_thresholds; + music_bandwidth_thresholds = stereo_music_bandwidth_thresholds; + } else { + voice_bandwidth_thresholds = mono_voice_bandwidth_thresholds; + music_bandwidth_thresholds = mono_music_bandwidth_thresholds; + } + /* Interpolate bandwidth thresholds depending on voice estimation */ + for (i=0;i<8;i++) + { + bandwidth_thresholds[i] = music_bandwidth_thresholds[i] + + ((voice_est*voice_est*(voice_bandwidth_thresholds[i]-music_bandwidth_thresholds[i]))>>14); + } + do { + int threshold, hysteresis; + threshold = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)]; + hysteresis = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)+1]; + if (!st->first) + { + if (st->bandwidth >= bandwidth) + threshold -= hysteresis; + else + threshold += hysteresis; + } + if (equiv_rate2 >= threshold) + break; + } while (--bandwidth>OPUS_BANDWIDTH_NARROWBAND); + st->bandwidth = bandwidth; + /* Prevents any transition to SWB/FB until the SILK layer has fully + switched to WB mode and turned the variable LP filter off */ + if (!st->first && st->mode != MODE_CELT_ONLY && !st->silk_mode.inWBmodeWithoutVariableLP && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND) + st->bandwidth = OPUS_BANDWIDTH_WIDEBAND; + } + + if (st->bandwidth>st->max_bandwidth) + st->bandwidth = st->max_bandwidth; + + if (st->user_bandwidth != OPUS_AUTO) + st->bandwidth = st->user_bandwidth; + + /* This prevents us from using hybrid at unsafe CBR/max rates */ + if (st->mode != MODE_CELT_ONLY && max_rate < 15000) + { + st->bandwidth = IMIN(st->bandwidth, OPUS_BANDWIDTH_WIDEBAND); + } + + /* Prevents Opus from wasting bits on frequencies that are above + the Nyquist rate of the input signal */ + if (st->Fs <= 24000 && st->bandwidth > OPUS_BANDWIDTH_SUPERWIDEBAND) + st->bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; + if (st->Fs <= 16000 && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND) + st->bandwidth = OPUS_BANDWIDTH_WIDEBAND; + if (st->Fs <= 12000 && st->bandwidth > OPUS_BANDWIDTH_MEDIUMBAND) + st->bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; + if (st->Fs <= 8000 && st->bandwidth > OPUS_BANDWIDTH_NARROWBAND) + st->bandwidth = OPUS_BANDWIDTH_NARROWBAND; +#ifndef DISABLE_FLOAT_API + /* Use detected bandwidth to reduce the encoded bandwidth. */ + if (st->detected_bandwidth && st->user_bandwidth == OPUS_AUTO) + { + int min_detected_bandwidth; + /* Makes bandwidth detection more conservative just in case the detector + gets it wrong when we could have coded a high bandwidth transparently. + When operating in SILK/hybrid mode, we don't go below wideband to avoid + more complicated switches that require redundancy. */ + if (equiv_rate <= 18000*st->stream_channels && st->mode == MODE_CELT_ONLY) + min_detected_bandwidth = OPUS_BANDWIDTH_NARROWBAND; + else if (equiv_rate <= 24000*st->stream_channels && st->mode == MODE_CELT_ONLY) + min_detected_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; + else if (equiv_rate <= 30000*st->stream_channels) + min_detected_bandwidth = OPUS_BANDWIDTH_WIDEBAND; + else if (equiv_rate <= 44000*st->stream_channels) + min_detected_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; + else + min_detected_bandwidth = OPUS_BANDWIDTH_FULLBAND; + + st->detected_bandwidth = IMAX(st->detected_bandwidth, min_detected_bandwidth); + st->bandwidth = IMIN(st->bandwidth, st->detected_bandwidth); + } +#endif + celt_encoder_ctl(celt_enc, OPUS_SET_LSB_DEPTH(lsb_depth)); + + /* CELT mode doesn't support mediumband, use wideband instead */ + if (st->mode == MODE_CELT_ONLY && st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) + st->bandwidth = OPUS_BANDWIDTH_WIDEBAND; + if (st->lfe) + st->bandwidth = OPUS_BANDWIDTH_NARROWBAND; + + /* Can't support higher than wideband for >20 ms frames */ + if (frame_size > st->Fs/50 && (st->mode == MODE_CELT_ONLY || st->bandwidth > OPUS_BANDWIDTH_WIDEBAND)) + { + VARDECL(unsigned char, tmp_data); + int nb_frames; + int bak_mode, bak_bandwidth, bak_channels, bak_to_mono; + VARDECL(OpusRepacketizer, rp); + opus_int32 bytes_per_frame; + opus_int32 repacketize_len; + +#ifndef DISABLE_FLOAT_API + if (analysis_read_pos_bak!= -1) + { + st->analysis.read_pos = analysis_read_pos_bak; + st->analysis.read_subframe = analysis_read_subframe_bak; + } +#endif + + nb_frames = frame_size > st->Fs/25 ? 3 : 2; + bytes_per_frame = IMIN(1276,(out_data_bytes-3)/nb_frames); + + ALLOC(tmp_data, nb_frames*bytes_per_frame, unsigned char); + + ALLOC(rp, 1, OpusRepacketizer); + opus_repacketizer_init(rp); + + bak_mode = st->user_forced_mode; + bak_bandwidth = st->user_bandwidth; + bak_channels = st->force_channels; + + st->user_forced_mode = st->mode; + st->user_bandwidth = st->bandwidth; + st->force_channels = st->stream_channels; + bak_to_mono = st->silk_mode.toMono; + + if (bak_to_mono) + st->force_channels = 1; + else + st->prev_channels = st->stream_channels; + for (i=0;i<nb_frames;i++) + { + int tmp_len; + st->silk_mode.toMono = 0; + /* When switching from SILK/Hybrid to CELT, only ask for a switch at the last frame */ + if (to_celt && i==nb_frames-1) + st->user_forced_mode = MODE_CELT_ONLY; + tmp_len = opus_encode_native(st, pcm+i*(st->channels*st->Fs/50), st->Fs/50, + tmp_data+i*bytes_per_frame, bytes_per_frame, lsb_depth, + NULL, 0, c1, c2, analysis_channels, downmix, float_api); + if (tmp_len<0) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + ret = opus_repacketizer_cat(rp, tmp_data+i*bytes_per_frame, tmp_len); + if (ret<0) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + } + if (st->use_vbr) + repacketize_len = out_data_bytes; + else + repacketize_len = IMIN(3*st->bitrate_bps/(3*8*50/nb_frames), out_data_bytes); + ret = opus_repacketizer_out_range_impl(rp, 0, nb_frames, data, repacketize_len, 0, !st->use_vbr); + if (ret<0) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + st->user_forced_mode = bak_mode; + st->user_bandwidth = bak_bandwidth; + st->force_channels = bak_channels; + st->silk_mode.toMono = bak_to_mono; + RESTORE_STACK; + return ret; + } + curr_bandwidth = st->bandwidth; + + /* Chooses the appropriate mode for speech + *NEVER* switch to/from CELT-only mode here as this will invalidate some assumptions */ + if (st->mode == MODE_SILK_ONLY && curr_bandwidth > OPUS_BANDWIDTH_WIDEBAND) + st->mode = MODE_HYBRID; + if (st->mode == MODE_HYBRID && curr_bandwidth <= OPUS_BANDWIDTH_WIDEBAND) + st->mode = MODE_SILK_ONLY; + + /* printf("%d %d %d %d\n", st->bitrate_bps, st->stream_channels, st->mode, curr_bandwidth); */ + bytes_target = IMIN(max_data_bytes-redundancy_bytes, st->bitrate_bps * frame_size / (st->Fs * 8)) - 1; + + data += 1; + + ec_enc_init(&enc, data, max_data_bytes-1); + + ALLOC(pcm_buf, (total_buffer+frame_size)*st->channels, opus_val16); + OPUS_COPY(pcm_buf, &st->delay_buffer[(st->encoder_buffer-total_buffer)*st->channels], total_buffer*st->channels); + + if (st->mode == MODE_CELT_ONLY) + hp_freq_smth1 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ); + else + hp_freq_smth1 = ((silk_encoder*)silk_enc)->state_Fxx[0].sCmn.variable_HP_smth1_Q15; + + st->variable_HP_smth2_Q15 = silk_SMLAWB( st->variable_HP_smth2_Q15, + hp_freq_smth1 - st->variable_HP_smth2_Q15, SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF2, 16 ) ); + + /* convert from log scale to Hertz */ + cutoff_Hz = silk_log2lin( silk_RSHIFT( st->variable_HP_smth2_Q15, 8 ) ); + + if (st->application == OPUS_APPLICATION_VOIP) + { + hp_cutoff(pcm, cutoff_Hz, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs); + } else { + dc_reject(pcm, 3, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs); + } +#ifndef FIXED_POINT + if (float_api) + { + opus_val32 sum; + sum = celt_inner_prod(&pcm_buf[total_buffer*st->channels], &pcm_buf[total_buffer*st->channels], frame_size*st->channels, st->arch); + /* This should filter out both NaNs and ridiculous signals that could + cause NaNs further down. */ + if (!(sum < 1e9f) || celt_isnan(sum)) + { + OPUS_CLEAR(&pcm_buf[total_buffer*st->channels], frame_size*st->channels); + st->hp_mem[0] = st->hp_mem[1] = st->hp_mem[2] = st->hp_mem[3] = 0; + } + } +#endif + + + /* SILK processing */ + HB_gain = Q15ONE; + if (st->mode != MODE_CELT_ONLY) + { + opus_int32 total_bitRate, celt_rate; +#ifdef FIXED_POINT + const opus_int16 *pcm_silk; +#else + VARDECL(opus_int16, pcm_silk); + ALLOC(pcm_silk, st->channels*frame_size, opus_int16); +#endif + + /* Distribute bits between SILK and CELT */ + total_bitRate = 8 * bytes_target * frame_rate; + if( st->mode == MODE_HYBRID ) { + int HB_gain_ref; + /* Base rate for SILK */ + st->silk_mode.bitRate = st->stream_channels * ( 5000 + 1000 * ( st->Fs == 100 * frame_size ) ); + if( curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND ) { + /* SILK gets 2/3 of the remaining bits */ + st->silk_mode.bitRate += ( total_bitRate - st->silk_mode.bitRate ) * 2 / 3; + } else { /* FULLBAND */ + /* SILK gets 3/5 of the remaining bits */ + st->silk_mode.bitRate += ( total_bitRate - st->silk_mode.bitRate ) * 3 / 5; + } + /* Don't let SILK use more than 80% */ + if( st->silk_mode.bitRate > total_bitRate * 4/5 ) { + st->silk_mode.bitRate = total_bitRate * 4/5; + } + if (!st->energy_masking) + { + /* Increasingly attenuate high band when it gets allocated fewer bits */ + celt_rate = total_bitRate - st->silk_mode.bitRate; + HB_gain_ref = (curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND) ? 3000 : 3600; + HB_gain = SHL32((opus_val32)celt_rate, 9) / SHR32((opus_val32)celt_rate + st->stream_channels * HB_gain_ref, 6); + HB_gain = HB_gain < Q15ONE*6/7 ? HB_gain + Q15ONE/7 : Q15ONE; + } + } else { + /* SILK gets all bits */ + st->silk_mode.bitRate = total_bitRate; + } + + /* Surround masking for SILK */ + if (st->energy_masking && st->use_vbr && !st->lfe) + { + opus_val32 mask_sum=0; + opus_val16 masking_depth; + opus_int32 rate_offset; + int c; + int end = 17; + opus_int16 srate = 16000; + if (st->bandwidth == OPUS_BANDWIDTH_NARROWBAND) + { + end = 13; + srate = 8000; + } else if (st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) + { + end = 15; + srate = 12000; + } + for (c=0;c<st->channels;c++) + { + for(i=0;i<end;i++) + { + opus_val16 mask; + mask = MAX16(MIN16(st->energy_masking[21*c+i], + QCONST16(.5f, DB_SHIFT)), -QCONST16(2.0f, DB_SHIFT)); + if (mask > 0) + mask = HALF16(mask); + mask_sum += mask; + } + } + /* Conservative rate reduction, we cut the masking in half */ + masking_depth = mask_sum / end*st->channels; + masking_depth += QCONST16(.2f, DB_SHIFT); + rate_offset = (opus_int32)PSHR32(MULT16_16(srate, masking_depth), DB_SHIFT); + rate_offset = MAX32(rate_offset, -2*st->silk_mode.bitRate/3); + /* Split the rate change between the SILK and CELT part for hybrid. */ + if (st->bandwidth==OPUS_BANDWIDTH_SUPERWIDEBAND || st->bandwidth==OPUS_BANDWIDTH_FULLBAND) + st->silk_mode.bitRate += 3*rate_offset/5; + else + st->silk_mode.bitRate += rate_offset; + bytes_target += rate_offset * frame_size / (8 * st->Fs); + } + + st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs; + st->silk_mode.nChannelsAPI = st->channels; + st->silk_mode.nChannelsInternal = st->stream_channels; + if (curr_bandwidth == OPUS_BANDWIDTH_NARROWBAND) { + st->silk_mode.desiredInternalSampleRate = 8000; + } else if (curr_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) { + st->silk_mode.desiredInternalSampleRate = 12000; + } else { + silk_assert( st->mode == MODE_HYBRID || curr_bandwidth == OPUS_BANDWIDTH_WIDEBAND ); + st->silk_mode.desiredInternalSampleRate = 16000; + } + if( st->mode == MODE_HYBRID ) { + /* Don't allow bandwidth reduction at lowest bitrates in hybrid mode */ + st->silk_mode.minInternalSampleRate = 16000; + } else { + st->silk_mode.minInternalSampleRate = 8000; + } + + if (st->mode == MODE_SILK_ONLY) + { + opus_int32 effective_max_rate = max_rate; + st->silk_mode.maxInternalSampleRate = 16000; + if (frame_rate > 50) + effective_max_rate = effective_max_rate*2/3; + if (effective_max_rate < 13000) + { + st->silk_mode.maxInternalSampleRate = 12000; + st->silk_mode.desiredInternalSampleRate = IMIN(12000, st->silk_mode.desiredInternalSampleRate); + } + if (effective_max_rate < 9600) + { + st->silk_mode.maxInternalSampleRate = 8000; + st->silk_mode.desiredInternalSampleRate = IMIN(8000, st->silk_mode.desiredInternalSampleRate); + } + } else { + st->silk_mode.maxInternalSampleRate = 16000; + } + + st->silk_mode.useCBR = !st->use_vbr; + + /* Call SILK encoder for the low band */ + nBytes = IMIN(1275, max_data_bytes-1-redundancy_bytes); + + st->silk_mode.maxBits = nBytes*8; + /* Only allow up to 90% of the bits for hybrid mode*/ + if (st->mode == MODE_HYBRID) + st->silk_mode.maxBits = (opus_int32)st->silk_mode.maxBits*9/10; + if (st->silk_mode.useCBR) + { + st->silk_mode.maxBits = (st->silk_mode.bitRate * frame_size / (st->Fs * 8))*8; + /* Reduce the initial target to make it easier to reach the CBR rate */ + st->silk_mode.bitRate = IMAX(1, st->silk_mode.bitRate-2000); + } + + if (prefill) + { + opus_int32 zero=0; + int prefill_offset; + /* Use a smooth onset for the SILK prefill to avoid the encoder trying to encode + a discontinuity. The exact location is what we need to avoid leaving any "gap" + in the audio when mixing with the redundant CELT frame. Here we can afford to + overwrite st->delay_buffer because the only thing that uses it before it gets + rewritten is tmp_prefill[] and even then only the part after the ramp really + gets used (rather than sent to the encoder and discarded) */ + prefill_offset = st->channels*(st->encoder_buffer-st->delay_compensation-st->Fs/400); + gain_fade(st->delay_buffer+prefill_offset, st->delay_buffer+prefill_offset, + 0, Q15ONE, celt_mode->overlap, st->Fs/400, st->channels, celt_mode->window, st->Fs); + OPUS_CLEAR(st->delay_buffer, prefill_offset); +#ifdef FIXED_POINT + pcm_silk = st->delay_buffer; +#else + for (i=0;i<st->encoder_buffer*st->channels;i++) + pcm_silk[i] = FLOAT2INT16(st->delay_buffer[i]); +#endif + silk_Encode( silk_enc, &st->silk_mode, pcm_silk, st->encoder_buffer, NULL, &zero, 1 ); + } + +#ifdef FIXED_POINT + pcm_silk = pcm_buf+total_buffer*st->channels; +#else + for (i=0;i<frame_size*st->channels;i++) + pcm_silk[i] = FLOAT2INT16(pcm_buf[total_buffer*st->channels + i]); +#endif + ret = silk_Encode( silk_enc, &st->silk_mode, pcm_silk, frame_size, &enc, &nBytes, 0 ); + if( ret ) { + /*fprintf (stderr, "SILK encode error: %d\n", ret);*/ + /* Handle error */ + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + if (nBytes==0) + { + st->rangeFinal = 0; + data[-1] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels); + RESTORE_STACK; + return 1; + } + /* Extract SILK internal bandwidth for signaling in first byte */ + if( st->mode == MODE_SILK_ONLY ) { + if( st->silk_mode.internalSampleRate == 8000 ) { + curr_bandwidth = OPUS_BANDWIDTH_NARROWBAND; + } else if( st->silk_mode.internalSampleRate == 12000 ) { + curr_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; + } else if( st->silk_mode.internalSampleRate == 16000 ) { + curr_bandwidth = OPUS_BANDWIDTH_WIDEBAND; + } + } else { + silk_assert( st->silk_mode.internalSampleRate == 16000 ); + } + + st->silk_mode.opusCanSwitch = st->silk_mode.switchReady; + /* FIXME: How do we allocate the redundancy for CBR? */ + if (st->silk_mode.opusCanSwitch) + { + redundancy = 1; + celt_to_silk = 0; + st->silk_bw_switch = 1; + } + } + + /* CELT processing */ + { + int endband=21; + + switch(curr_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; + } + celt_encoder_ctl(celt_enc, CELT_SET_END_BAND(endband)); + celt_encoder_ctl(celt_enc, CELT_SET_CHANNELS(st->stream_channels)); + } + celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(OPUS_BITRATE_MAX)); + if (st->mode != MODE_SILK_ONLY) + { + opus_val32 celt_pred=2; + celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0)); + /* We may still decide to disable prediction later */ + if (st->silk_mode.reducedDependency) + celt_pred = 0; + celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(celt_pred)); + + if (st->mode == MODE_HYBRID) + { + int len; + + len = (ec_tell(&enc)+7)>>3; + if (redundancy) + len += st->mode == MODE_HYBRID ? 3 : 1; + if( st->use_vbr ) { + nb_compr_bytes = len + bytes_target - (st->silk_mode.bitRate * frame_size) / (8 * st->Fs); + } else { + /* check if SILK used up too much */ + nb_compr_bytes = len > bytes_target ? len : bytes_target; + } + } else { + if (st->use_vbr) + { + opus_int32 bonus=0; +#ifndef DISABLE_FLOAT_API + if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != st->Fs/50) + { + bonus = (60*st->stream_channels+40)*(st->Fs/frame_size-50); + if (analysis_info.valid) + bonus = (opus_int32)(bonus*(1.f+.5f*analysis_info.tonality)); + } +#endif + celt_encoder_ctl(celt_enc, OPUS_SET_VBR(1)); + celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(st->vbr_constraint)); + celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps+bonus)); + nb_compr_bytes = max_data_bytes-1-redundancy_bytes; + } else { + nb_compr_bytes = bytes_target; + } + } + + } else { + nb_compr_bytes = 0; + } + + ALLOC(tmp_prefill, st->channels*st->Fs/400, opus_val16); + if (st->mode != MODE_SILK_ONLY && st->mode != st->prev_mode && st->prev_mode > 0) + { + OPUS_COPY(tmp_prefill, &st->delay_buffer[(st->encoder_buffer-total_buffer-st->Fs/400)*st->channels], st->channels*st->Fs/400); + } + + if (st->channels*(st->encoder_buffer-(frame_size+total_buffer)) > 0) + { + OPUS_MOVE(st->delay_buffer, &st->delay_buffer[st->channels*frame_size], st->channels*(st->encoder_buffer-frame_size-total_buffer)); + OPUS_COPY(&st->delay_buffer[st->channels*(st->encoder_buffer-frame_size-total_buffer)], + &pcm_buf[0], + (frame_size+total_buffer)*st->channels); + } else { + OPUS_COPY(st->delay_buffer, &pcm_buf[(frame_size+total_buffer-st->encoder_buffer)*st->channels], st->encoder_buffer*st->channels); + } + /* gain_fade() and stereo_fade() need to be after the buffer copying + because we don't want any of this to affect the SILK part */ + if( st->prev_HB_gain < Q15ONE || HB_gain < Q15ONE ) { + gain_fade(pcm_buf, pcm_buf, + st->prev_HB_gain, HB_gain, celt_mode->overlap, frame_size, st->channels, celt_mode->window, st->Fs); + } + st->prev_HB_gain = HB_gain; + if (st->mode != MODE_HYBRID || st->stream_channels==1) + st->silk_mode.stereoWidth_Q14 = IMIN((1<<14),2*IMAX(0,equiv_rate-30000)); + if( !st->energy_masking && st->channels == 2 ) { + /* Apply stereo width reduction (at low bitrates) */ + if( st->hybrid_stereo_width_Q14 < (1 << 14) || st->silk_mode.stereoWidth_Q14 < (1 << 14) ) { + opus_val16 g1, g2; + g1 = st->hybrid_stereo_width_Q14; + g2 = (opus_val16)(st->silk_mode.stereoWidth_Q14); +#ifdef FIXED_POINT + g1 = g1==16384 ? Q15ONE : SHL16(g1,1); + g2 = g2==16384 ? Q15ONE : SHL16(g2,1); +#else + g1 *= (1.f/16384); + g2 *= (1.f/16384); +#endif + stereo_fade(pcm_buf, pcm_buf, g1, g2, celt_mode->overlap, + frame_size, st->channels, celt_mode->window, st->Fs); + st->hybrid_stereo_width_Q14 = st->silk_mode.stereoWidth_Q14; + } + } + + if ( st->mode != MODE_CELT_ONLY && ec_tell(&enc)+17+20*(st->mode == MODE_HYBRID) <= 8*(max_data_bytes-1)) + { + /* For SILK mode, the redundancy is inferred from the length */ + if (st->mode == MODE_HYBRID && (redundancy || ec_tell(&enc)+37 <= 8*nb_compr_bytes)) + ec_enc_bit_logp(&enc, redundancy, 12); + if (redundancy) + { + int max_redundancy; + ec_enc_bit_logp(&enc, celt_to_silk, 1); + if (st->mode == MODE_HYBRID) + max_redundancy = (max_data_bytes-1)-nb_compr_bytes; + else + max_redundancy = (max_data_bytes-1)-((ec_tell(&enc)+7)>>3); + /* Target the same bit-rate for redundancy as for the rest, + up to a max of 257 bytes */ + redundancy_bytes = IMIN(max_redundancy, st->bitrate_bps/1600); + redundancy_bytes = IMIN(257, IMAX(2, redundancy_bytes)); + if (st->mode == MODE_HYBRID) + ec_enc_uint(&enc, redundancy_bytes-2, 256); + } + } else { + redundancy = 0; + } + + if (!redundancy) + { + st->silk_bw_switch = 0; + redundancy_bytes = 0; + } + if (st->mode != MODE_CELT_ONLY)start_band=17; + + if (st->mode == MODE_SILK_ONLY) + { + ret = (ec_tell(&enc)+7)>>3; + ec_enc_done(&enc); + nb_compr_bytes = ret; + } else { + nb_compr_bytes = IMIN((max_data_bytes-1)-redundancy_bytes, nb_compr_bytes); + ec_enc_shrink(&enc, nb_compr_bytes); + } + +#ifndef DISABLE_FLOAT_API + if (redundancy || st->mode != MODE_SILK_ONLY) + celt_encoder_ctl(celt_enc, CELT_SET_ANALYSIS(&analysis_info)); +#endif + + /* 5 ms redundant frame for CELT->SILK */ + if (redundancy && celt_to_silk) + { + int err; + celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0)); + celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0)); + err = celt_encode_with_ec(celt_enc, pcm_buf, st->Fs/200, data+nb_compr_bytes, redundancy_bytes, NULL); + if (err < 0) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + celt_encoder_ctl(celt_enc, OPUS_GET_FINAL_RANGE(&redundant_rng)); + celt_encoder_ctl(celt_enc, OPUS_RESET_STATE); + } + + celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(start_band)); + + if (st->mode != MODE_SILK_ONLY) + { + if (st->mode != st->prev_mode && st->prev_mode > 0) + { + unsigned char dummy[2]; + celt_encoder_ctl(celt_enc, OPUS_RESET_STATE); + + /* Prefilling */ + celt_encode_with_ec(celt_enc, tmp_prefill, st->Fs/400, dummy, 2, NULL); + celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0)); + } + /* If false, we already busted the budget and we'll end up with a "PLC packet" */ + if (ec_tell(&enc) <= 8*nb_compr_bytes) + { + ret = celt_encode_with_ec(celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc); + if (ret < 0) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + } + } + + /* 5 ms redundant frame for SILK->CELT */ + if (redundancy && !celt_to_silk) + { + int err; + unsigned char dummy[2]; + int N2, N4; + N2 = st->Fs/200; + N4 = st->Fs/400; + + celt_encoder_ctl(celt_enc, OPUS_RESET_STATE); + celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0)); + celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0)); + + /* NOTE: We could speed this up slightly (at the expense of code size) by just adding a function that prefills the buffer */ + celt_encode_with_ec(celt_enc, pcm_buf+st->channels*(frame_size-N2-N4), N4, dummy, 2, NULL); + + err = celt_encode_with_ec(celt_enc, pcm_buf+st->channels*(frame_size-N2), N2, data+nb_compr_bytes, redundancy_bytes, NULL); + if (err < 0) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + celt_encoder_ctl(celt_enc, OPUS_GET_FINAL_RANGE(&redundant_rng)); + } + + + + /* Signalling the mode in the first byte */ + data--; + data[0] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels); + + st->rangeFinal = enc.rng ^ redundant_rng; + + if (to_celt) + st->prev_mode = MODE_CELT_ONLY; + else + st->prev_mode = st->mode; + st->prev_channels = st->stream_channels; + st->prev_framesize = frame_size; + + st->first = 0; + + /* In the unlikely case that the SILK encoder busted its target, tell + the decoder to call the PLC */ + if (ec_tell(&enc) > (max_data_bytes-1)*8) + { + if (max_data_bytes < 2) + { + RESTORE_STACK; + return OPUS_BUFFER_TOO_SMALL; + } + data[1] = 0; + ret = 1; + st->rangeFinal = 0; + } else if (st->mode==MODE_SILK_ONLY&&!redundancy) + { + /*When in LPC only mode it's perfectly + reasonable to strip off trailing zero bytes as + the required range decoder behavior is to + fill these in. This can't be done when the MDCT + modes are used because the decoder needs to know + the actual length for allocation purposes.*/ + while(ret>2&&data[ret]==0)ret--; + } + /* Count ToC and redundancy */ + ret += 1+redundancy_bytes; + if (!st->use_vbr) + { + if (opus_packet_pad(data, ret, max_data_bytes) != OPUS_OK) + + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + ret = max_data_bytes; + } + RESTORE_STACK; + return ret; +} + +#ifdef FIXED_POINT + +#ifndef DISABLE_FLOAT_API +opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size, + unsigned char *data, opus_int32 max_data_bytes) +{ + int i, ret; + int frame_size; + int delay_compensation; + VARDECL(opus_int16, in); + ALLOC_STACK; + + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + delay_compensation = 0; + else + delay_compensation = st->delay_compensation; + frame_size = compute_frame_size(pcm, analysis_frame_size, + st->variable_duration, st->channels, st->Fs, st->bitrate_bps, + delay_compensation, downmix_float, st->analysis.subframe_mem); + + ALLOC(in, frame_size*st->channels, opus_int16); + + for (i=0;i<frame_size*st->channels;i++) + in[i] = FLOAT2INT16(pcm[i]); + ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, + pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1); + RESTORE_STACK; + return ret; +} +#endif + +opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size, + unsigned char *data, opus_int32 out_data_bytes) +{ + int frame_size; + int delay_compensation; + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + delay_compensation = 0; + else + delay_compensation = st->delay_compensation; + frame_size = compute_frame_size(pcm, analysis_frame_size, + st->variable_duration, st->channels, st->Fs, st->bitrate_bps, + delay_compensation, downmix_int +#ifndef DISABLE_FLOAT_API + , st->analysis.subframe_mem +#endif + ); + return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 16, + pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0); +} + +#else +opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size, + unsigned char *data, opus_int32 max_data_bytes) +{ + int i, ret; + int frame_size; + int delay_compensation; + VARDECL(float, in); + ALLOC_STACK; + + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + delay_compensation = 0; + else + delay_compensation = st->delay_compensation; + frame_size = compute_frame_size(pcm, analysis_frame_size, + st->variable_duration, st->channels, st->Fs, st->bitrate_bps, + delay_compensation, downmix_int, st->analysis.subframe_mem); + + ALLOC(in, frame_size*st->channels, float); + + for (i=0;i<frame_size*st->channels;i++) + in[i] = (1.0f/32768)*pcm[i]; + ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, + pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0); + RESTORE_STACK; + return ret; +} +opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size, + unsigned char *data, opus_int32 out_data_bytes) +{ + int frame_size; + int delay_compensation; + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + delay_compensation = 0; + else + delay_compensation = st->delay_compensation; + frame_size = compute_frame_size(pcm, analysis_frame_size, + st->variable_duration, st->channels, st->Fs, st->bitrate_bps, + delay_compensation, downmix_float, st->analysis.subframe_mem); + return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 24, + pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1); +} +#endif + + +int opus_encoder_ctl(OpusEncoder *st, int request, ...) +{ + int ret; + CELTEncoder *celt_enc; + va_list ap; + + ret = OPUS_OK; + va_start(ap, request); + + celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset); + + switch (request) + { + case OPUS_SET_APPLICATION_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if ( (value != OPUS_APPLICATION_VOIP && value != OPUS_APPLICATION_AUDIO + && value != OPUS_APPLICATION_RESTRICTED_LOWDELAY) + || (!st->first && st->application != value)) + { + ret = OPUS_BAD_ARG; + break; + } + st->application = value; + } + break; + case OPUS_GET_APPLICATION_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->application; + } + break; + case OPUS_SET_BITRATE_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX) + { + if (value <= 0) + goto bad_arg; + else if (value <= 500) + value = 500; + else if (value > (opus_int32)300000*st->channels) + value = (opus_int32)300000*st->channels; + } + st->user_bitrate_bps = value; + } + break; + case OPUS_GET_BITRATE_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = user_bitrate_to_bitrate(st, st->prev_framesize, 1276); + } + break; + case OPUS_SET_FORCE_CHANNELS_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if((value<1 || value>st->channels) && value != OPUS_AUTO) + { + goto bad_arg; + } + st->force_channels = value; + } + break; + case OPUS_GET_FORCE_CHANNELS_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->force_channels; + } + break; + case OPUS_SET_MAX_BANDWIDTH_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND) + { + goto bad_arg; + } + st->max_bandwidth = value; + if (st->max_bandwidth == OPUS_BANDWIDTH_NARROWBAND) { + st->silk_mode.maxInternalSampleRate = 8000; + } else if (st->max_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) { + st->silk_mode.maxInternalSampleRate = 12000; + } else { + st->silk_mode.maxInternalSampleRate = 16000; + } + } + break; + case OPUS_GET_MAX_BANDWIDTH_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->max_bandwidth; + } + break; + case OPUS_SET_BANDWIDTH_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if ((value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND) && value != OPUS_AUTO) + { + goto bad_arg; + } + st->user_bandwidth = value; + if (st->user_bandwidth == OPUS_BANDWIDTH_NARROWBAND) { + st->silk_mode.maxInternalSampleRate = 8000; + } else if (st->user_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) { + st->silk_mode.maxInternalSampleRate = 12000; + } else { + st->silk_mode.maxInternalSampleRate = 16000; + } + } + break; + 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_DTX_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if(value<0 || value>1) + { + goto bad_arg; + } + st->silk_mode.useDTX = value; + } + break; + case OPUS_GET_DTX_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->silk_mode.useDTX; + } + break; + case OPUS_SET_COMPLEXITY_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if(value<0 || value>10) + { + goto bad_arg; + } + st->silk_mode.complexity = value; + celt_encoder_ctl(celt_enc, 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->silk_mode.complexity; + } + break; + case OPUS_SET_INBAND_FEC_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if(value<0 || value>1) + { + goto bad_arg; + } + st->silk_mode.useInBandFEC = value; + } + break; + case OPUS_GET_INBAND_FEC_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->silk_mode.useInBandFEC; + } + break; + case OPUS_SET_PACKET_LOSS_PERC_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value < 0 || value > 100) + { + goto bad_arg; + } + st->silk_mode.packetLossPercentage = value; + celt_encoder_ctl(celt_enc, OPUS_SET_PACKET_LOSS_PERC(value)); + } + break; + case OPUS_GET_PACKET_LOSS_PERC_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->silk_mode.packetLossPercentage; + } + break; + case OPUS_SET_VBR_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if(value<0 || value>1) + { + goto bad_arg; + } + st->use_vbr = value; + st->silk_mode.useCBR = 1-value; + } + break; + case OPUS_GET_VBR_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->use_vbr; + } + break; + case OPUS_SET_VOICE_RATIO_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<-1 || value>100) + { + goto bad_arg; + } + st->voice_ratio = value; + } + break; + case OPUS_GET_VOICE_RATIO_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->voice_ratio; + } + break; + case OPUS_SET_VBR_CONSTRAINT_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if(value<0 || value>1) + { + goto bad_arg; + } + st->vbr_constraint = value; + } + break; + case OPUS_GET_VBR_CONSTRAINT_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->vbr_constraint; + } + break; + case OPUS_SET_SIGNAL_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if(value!=OPUS_AUTO && value!=OPUS_SIGNAL_VOICE && value!=OPUS_SIGNAL_MUSIC) + { + goto bad_arg; + } + st->signal_type = value; + } + break; + case OPUS_GET_SIGNAL_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->signal_type; + } + break; + case OPUS_GET_LOOKAHEAD_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->Fs/400; + if (st->application != OPUS_APPLICATION_RESTRICTED_LOWDELAY) + *value += st->delay_compensation; + } + 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_FINAL_RANGE_REQUEST: + { + opus_uint32 *value = va_arg(ap, opus_uint32*); + if (!value) + { + goto bad_arg; + } + *value = st->rangeFinal; + } + break; + case OPUS_SET_LSB_DEPTH_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<8 || value>24) + { + goto bad_arg; + } + st->lsb_depth=value; + } + break; + case OPUS_GET_LSB_DEPTH_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->lsb_depth; + } + break; + case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value != OPUS_FRAMESIZE_ARG && value != OPUS_FRAMESIZE_2_5_MS && + value != OPUS_FRAMESIZE_5_MS && value != OPUS_FRAMESIZE_10_MS && + value != OPUS_FRAMESIZE_20_MS && value != OPUS_FRAMESIZE_40_MS && + value != OPUS_FRAMESIZE_60_MS && value != OPUS_FRAMESIZE_VARIABLE) + { + goto bad_arg; + } + st->variable_duration = value; + celt_encoder_ctl(celt_enc, OPUS_SET_EXPERT_FRAME_DURATION(value)); + } + break; + case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->variable_duration; + } + break; + case OPUS_SET_PREDICTION_DISABLED_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value > 1 || value < 0) + goto bad_arg; + st->silk_mode.reducedDependency = value; + } + break; + case OPUS_GET_PREDICTION_DISABLED_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + goto bad_arg; + *value = st->silk_mode.reducedDependency; + } + break; + case OPUS_RESET_STATE: + { + void *silk_enc; + silk_EncControlStruct dummy; + char *start; + silk_enc = (char*)st+st->silk_enc_offset; +#ifndef DISABLE_FLOAT_API + tonality_analysis_reset(&st->analysis); +#endif + + start = (char*)&st->OPUS_ENCODER_RESET_START; + OPUS_CLEAR(start, sizeof(OpusEncoder) - (start - (char*)st)); + + celt_encoder_ctl(celt_enc, OPUS_RESET_STATE); + silk_InitEncoder( silk_enc, st->arch, &dummy ); + st->stream_channels = st->channels; + st->hybrid_stereo_width_Q14 = 1 << 14; + st->prev_HB_gain = Q15ONE; + st->first = 1; + st->mode = MODE_HYBRID; + st->bandwidth = OPUS_BANDWIDTH_FULLBAND; + st->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ); + } + break; + case OPUS_SET_FORCE_MODE_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if ((value < MODE_SILK_ONLY || value > MODE_CELT_ONLY) && value != OPUS_AUTO) + { + goto bad_arg; + } + st->user_forced_mode = value; + } + break; + case OPUS_SET_LFE_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->lfe = value; + ret = celt_encoder_ctl(celt_enc, OPUS_SET_LFE(value)); + } + break; + case OPUS_SET_ENERGY_MASK_REQUEST: + { + opus_val16 *value = va_arg(ap, opus_val16*); + st->energy_masking = value; + ret = celt_encoder_ctl(celt_enc, OPUS_SET_ENERGY_MASK(value)); + } + break; + + case CELT_GET_MODE_REQUEST: + { + const CELTMode ** value = va_arg(ap, const CELTMode**); + if (!value) + { + goto bad_arg; + } + ret = celt_encoder_ctl(celt_enc, CELT_GET_MODE(value)); + } + break; + default: + /* fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);*/ + ret = OPUS_UNIMPLEMENTED; + break; + } + va_end(ap); + return ret; +bad_arg: + va_end(ap); + return OPUS_BAD_ARG; +} + +void opus_encoder_destroy(OpusEncoder *st) +{ + opus_free(st); +} diff --git a/thirdparty/opus/opus_multistream.c b/thirdparty/opus/opus_multistream.c new file mode 100644 index 0000000000..09c3639b7f --- /dev/null +++ b/thirdparty/opus/opus_multistream.c @@ -0,0 +1,92 @@ +/* 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" + + +int validate_layout(const ChannelLayout *layout) +{ + int i, max_channel; + + max_channel = layout->nb_streams+layout->nb_coupled_streams; + if (max_channel>255) + return 0; + for (i=0;i<layout->nb_channels;i++) + { + if (layout->mapping[i] >= max_channel && layout->mapping[i] != 255) + return 0; + } + return 1; +} + + +int get_left_channel(const ChannelLayout *layout, int stream_id, int prev) +{ + int i; + i = (prev<0) ? 0 : prev+1; + for (;i<layout->nb_channels;i++) + { + if (layout->mapping[i]==stream_id*2) + return i; + } + return -1; +} + +int get_right_channel(const ChannelLayout *layout, int stream_id, int prev) +{ + int i; + i = (prev<0) ? 0 : prev+1; + for (;i<layout->nb_channels;i++) + { + if (layout->mapping[i]==stream_id*2+1) + return i; + } + return -1; +} + +int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev) +{ + int i; + i = (prev<0) ? 0 : prev+1; + for (;i<layout->nb_channels;i++) + { + if (layout->mapping[i]==stream_id+layout->nb_coupled_streams) + return i; + } + return -1; +} + diff --git a/thirdparty/opus/opus_multistream.h b/thirdparty/opus/opus_multistream.h new file mode 100644 index 0000000000..47e03900bd --- /dev/null +++ b/thirdparty/opus/opus_multistream.h @@ -0,0 +1,660 @@ +/* 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 the + * <a href="https://tools.ietf.org/html/draft-ietf-codec-oggopus">Ogg + * encapsulation specification</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 outputing 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(5); + +/** 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(6); + +/** 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 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); + +/** Intialize 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 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/thirdparty/opus/opus_multistream_decoder.c b/thirdparty/opus/opus_multistream_decoder.c new file mode 100644 index 0000000000..b95eaa6eac --- /dev/null +++ b/thirdparty/opus/opus_multistream_decoder.c @@ -0,0 +1,537 @@ +/* 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" + +struct OpusMSDecoder { + ChannelLayout layout; + /* Decoder states go here */ +}; + + + + +/* DECODER */ + +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; +} + +typedef void (*opus_copy_channel_out_func)( + void *dst, + int dst_stride, + int dst_channel, + const opus_val16 *src, + int src_stride, + int frame_size +); + +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); + 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; +} + +static 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 +) +{ + opus_int32 Fs; + int coupled_size; + int mono_size; + int s, c; + char *ptr; + int do_plc=0; + VARDECL(opus_val16, buf); + ALLOC_STACK; + + /* Limit frame_size to avoid excessive stack allocations. */ + opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)); + frame_size = IMIN(frame_size, Fs/25*3); + ALLOC(buf, 2*frame_size, opus_val16); + 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; + int packet_offset, 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); + 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); + 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); + 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); + 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); + } + } + 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_val16 *src, + int src_stride, + int frame_size +) +{ + float *float_dst; + opus_int32 i; + float_dst = (float*)dst; + if (src != NULL) + { + for (i=0;i<frame_size;i++) +#if defined(FIXED_POINT) + float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride]; +#else + float_dst[i*dst_stride+dst_channel] = src[i*src_stride]; +#endif + } + 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_val16 *src, + int src_stride, + int frame_size +) +{ + opus_int16 *short_dst; + opus_int32 i; + short_dst = (opus_int16*)dst; + if (src != NULL) + { + for (i=0;i<frame_size;i++) +#if defined(FIXED_POINT) + short_dst[i*dst_stride+dst_channel] = src[i*src_stride]; +#else + short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]); +#endif + } + else + { + for (i=0;i<frame_size;i++) + short_dst[i*dst_stride+dst_channel] = 0; + } +} + + + +#ifdef FIXED_POINT +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, 0); +} + +#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); +} +#endif + +#else + +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, 1); +} + +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); +} +#endif + +int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) +{ + va_list ap; + int coupled_size, mono_size; + char *ptr; + int ret = OPUS_OK; + + va_start(ap, request); + + 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: + { + 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) + ret = OPUS_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: + { + 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; + } + + va_end(ap); + return ret; +bad_arg: + va_end(ap); + return OPUS_BAD_ARG; +} + + +void opus_multistream_decoder_destroy(OpusMSDecoder *st) +{ + opus_free(st); +} diff --git a/thirdparty/opus/opus_multistream_encoder.c b/thirdparty/opus/opus_multistream_encoder.c new file mode 100644 index 0000000000..9e85773573 --- /dev/null +++ b/thirdparty/opus/opus_multistream_encoder.c @@ -0,0 +1,1220 @@ +/* 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" +#include "mathops.h" +#include "mdct.h" +#include "modes.h" +#include "bands.h" +#include "quant_bands.h" +#include "pitch.h" + +typedef struct { + int nb_streams; + int nb_coupled_streams; + unsigned char mapping[8]; +} VorbisLayout; + +/* Index is nb_channel-1*/ +static const VorbisLayout vorbis_mappings[8] = { + {1, 0, {0}}, /* 1: mono */ + {1, 1, {0, 1}}, /* 2: stereo */ + {2, 1, {0, 2, 1}}, /* 3: 1-d surround */ + {2, 2, {0, 1, 2, 3}}, /* 4: quadraphonic surround */ + {3, 2, {0, 4, 1, 2, 3}}, /* 5: 5-channel surround */ + {4, 2, {0, 4, 1, 2, 3, 5}}, /* 6: 5.1 surround */ + {4, 3, {0, 4, 1, 2, 3, 5, 6}}, /* 7: 6.1 surround */ + {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */ +}; + +typedef void (*opus_copy_channel_in_func)( + opus_val16 *dst, + int dst_stride, + const void *src, + int src_stride, + int src_channel, + int frame_size +); + +struct OpusMSEncoder { + ChannelLayout layout; + int arch; + int lfe_stream; + int application; + int variable_duration; + int surround; + opus_int32 bitrate_bps; + float subframe_mem[3]; + /* Encoder states go here */ + /* then opus_val32 window_mem[channels*120]; */ + /* then opus_val32 preemph_mem[channels]; */ +}; + +static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st) +{ + int s; + char *ptr; + int coupled_size, mono_size; + + coupled_size = opus_encoder_get_size(2); + mono_size = opus_encoder_get_size(1); + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + for (s=0;s<st->layout.nb_streams;s++) + { + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + } + /* void* cast avoids clang -Wcast-align warning */ + return (opus_val32*)(void*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32)); +} + +static opus_val32 *ms_get_window_mem(OpusMSEncoder *st) +{ + int s; + char *ptr; + int coupled_size, mono_size; + + coupled_size = opus_encoder_get_size(2); + mono_size = opus_encoder_get_size(1); + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + for (s=0;s<st->layout.nb_streams;s++) + { + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + } + /* void* cast avoids clang -Wcast-align warning */ + return (opus_val32*)(void*)ptr; +} + +static int validate_encoder_layout(const ChannelLayout *layout) +{ + int s; + for (s=0;s<layout->nb_streams;s++) + { + if (s < layout->nb_coupled_streams) + { + if (get_left_channel(layout, s, -1)==-1) + return 0; + if (get_right_channel(layout, s, -1)==-1) + return 0; + } else { + if (get_mono_channel(layout, s, -1)==-1) + return 0; + } + } + return 1; +} + +static void channel_pos(int channels, int pos[8]) +{ + /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */ + if (channels==4) + { + pos[0]=1; + pos[1]=3; + pos[2]=1; + pos[3]=3; + } else if (channels==3||channels==5||channels==6) + { + pos[0]=1; + pos[1]=2; + pos[2]=3; + pos[3]=1; + pos[4]=3; + pos[5]=0; + } else if (channels==7) + { + pos[0]=1; + pos[1]=2; + pos[2]=3; + pos[3]=1; + pos[4]=3; + pos[5]=2; + pos[6]=0; + } else if (channels==8) + { + pos[0]=1; + pos[1]=2; + pos[2]=3; + pos[3]=1; + pos[4]=3; + pos[5]=1; + pos[6]=3; + pos[7]=0; + } +} + +#if 1 +/* Computes a rough approximation of log2(2^a + 2^b) */ +static opus_val16 logSum(opus_val16 a, opus_val16 b) +{ + opus_val16 max; + opus_val32 diff; + opus_val16 frac; + static const opus_val16 diff_table[17] = { + QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT), + QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT), + QCONST16(0.0028123f, DB_SHIFT) + }; + int low; + if (a>b) + { + max = a; + diff = SUB32(EXTEND32(a),EXTEND32(b)); + } else { + max = b; + diff = SUB32(EXTEND32(b),EXTEND32(a)); + } + if (!(diff < QCONST16(8.f, DB_SHIFT))) /* inverted to catch NaNs */ + return max; +#ifdef FIXED_POINT + low = SHR32(diff, DB_SHIFT-1); + frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT); +#else + low = (int)floor(2*diff); + frac = 2*diff - low; +#endif + return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low])); +} +#else +opus_val16 logSum(opus_val16 a, opus_val16 b) +{ + return log2(pow(4, a)+ pow(4, b))/2; +} +#endif + +void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem, + int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in, int arch +) +{ + int c; + int i; + int LM; + int pos[8] = {0}; + int upsample; + int frame_size; + opus_val16 channel_offset; + opus_val32 bandE[21]; + opus_val16 maskLogE[3][21]; + VARDECL(opus_val32, in); + VARDECL(opus_val16, x); + VARDECL(opus_val32, freq); + SAVE_STACK; + + upsample = resampling_factor(rate); + frame_size = len*upsample; + + for (LM=0;LM<celt_mode->maxLM;LM++) + if (celt_mode->shortMdctSize<<LM==frame_size) + break; + + ALLOC(in, frame_size+overlap, opus_val32); + ALLOC(x, len, opus_val16); + ALLOC(freq, frame_size, opus_val32); + + channel_pos(channels, pos); + + for (c=0;c<3;c++) + for (i=0;i<21;i++) + maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT); + + for (c=0;c<channels;c++) + { + OPUS_COPY(in, mem+c*overlap, overlap); + (*copy_channel_in)(x, 1, pcm, channels, c, len); + celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0); +#ifndef FIXED_POINT + { + opus_val32 sum; + sum = celt_inner_prod(in, in, frame_size+overlap, 0); + /* This should filter out both NaNs and ridiculous signals that could + cause NaNs further down. */ + if (!(sum < 1e9f) || celt_isnan(sum)) + { + OPUS_CLEAR(in, frame_size+overlap); + preemph_mem[c] = 0; + } + } +#endif + clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, + overlap, celt_mode->maxLM-LM, 1, arch); + if (upsample != 1) + { + int bound = len; + for (i=0;i<bound;i++) + freq[i] *= upsample; + for (;i<frame_size;i++) + freq[i] = 0; + } + + compute_band_energies(celt_mode, freq, bandE, 21, 1, LM); + amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1); + /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */ + for (i=1;i<21;i++) + bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT)); + for (i=19;i>=0;i--) + bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i+1]-QCONST16(2.f, DB_SHIFT)); + if (pos[c]==1) + { + for (i=0;i<21;i++) + maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]); + } else if (pos[c]==3) + { + for (i=0;i<21;i++) + maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]); + } else if (pos[c]==2) + { + for (i=0;i<21;i++) + { + maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT)); + maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT)); + } + } +#if 0 + for (i=0;i<21;i++) + printf("%f ", bandLogE[21*c+i]); + float sum=0; + for (i=0;i<21;i++) + sum += bandLogE[21*c+i]; + printf("%f ", sum/21); +#endif + OPUS_COPY(mem+c*overlap, in+frame_size, overlap); + } + for (i=0;i<21;i++) + maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]); + channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1))); + for (c=0;c<3;c++) + for (i=0;i<21;i++) + maskLogE[c][i] += channel_offset; +#if 0 + for (c=0;c<3;c++) + { + for (i=0;i<21;i++) + printf("%f ", maskLogE[c][i]); + } +#endif + for (c=0;c<channels;c++) + { + opus_val16 *mask; + if (pos[c]!=0) + { + mask = &maskLogE[pos[c]-1][0]; + for (i=0;i<21;i++) + bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i]; + } else { + for (i=0;i<21;i++) + bandLogE[21*c+i] = 0; + } +#if 0 + for (i=0;i<21;i++) + printf("%f ", bandLogE[21*c+i]); + printf("\n"); +#endif +#if 0 + float sum=0; + for (i=0;i<21;i++) + sum += bandLogE[21*c+i]; + printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT)); + printf("\n"); +#endif + } + RESTORE_STACK; +} + +opus_int32 opus_multistream_encoder_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_encoder_get_size(2); + mono_size = opus_encoder_get_size(1); + return align(sizeof(OpusMSEncoder)) + + nb_coupled_streams * align(coupled_size) + + (nb_streams-nb_coupled_streams) * align(mono_size); +} + +opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family) +{ + int nb_streams; + int nb_coupled_streams; + opus_int32 size; + + if (mapping_family==0) + { + if (channels==1) + { + nb_streams=1; + nb_coupled_streams=0; + } else if (channels==2) + { + nb_streams=1; + nb_coupled_streams=1; + } else + return 0; + } else if (mapping_family==1 && channels<=8 && channels>=1) + { + nb_streams=vorbis_mappings[channels-1].nb_streams; + nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams; + } else if (mapping_family==255) + { + nb_streams=channels; + nb_coupled_streams=0; + } else + return 0; + size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams); + if (channels>2) + { + size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32)); + } + return size; +} + + +static int opus_multistream_encoder_init_impl( + OpusMSEncoder *st, + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int application, + int surround +) +{ + 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->arch = opus_select_arch(); + st->layout.nb_channels = channels; + st->layout.nb_streams = streams; + st->layout.nb_coupled_streams = coupled_streams; + st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0; + if (!surround) + st->lfe_stream = -1; + st->bitrate_bps = OPUS_AUTO; + st->application = application; + st->variable_duration = OPUS_FRAMESIZE_ARG; + for (i=0;i<st->layout.nb_channels;i++) + st->layout.mapping[i] = mapping[i]; + if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout)) + return OPUS_BAD_ARG; + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + coupled_size = opus_encoder_get_size(2); + mono_size = opus_encoder_get_size(1); + + for (i=0;i<st->layout.nb_coupled_streams;i++) + { + ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application); + if(ret!=OPUS_OK)return ret; + if (i==st->lfe_stream) + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1)); + ptr += align(coupled_size); + } + for (;i<st->layout.nb_streams;i++) + { + ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application); + if (i==st->lfe_stream) + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1)); + if(ret!=OPUS_OK)return ret; + ptr += align(mono_size); + } + if (surround) + { + OPUS_CLEAR(ms_get_preemph_mem(st), channels); + OPUS_CLEAR(ms_get_window_mem(st), channels*120); + } + st->surround = surround; + return OPUS_OK; +} + +int opus_multistream_encoder_init( + OpusMSEncoder *st, + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int application +) +{ + return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0); +} + +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 +) +{ + if ((channels>255) || (channels<1)) + return OPUS_BAD_ARG; + st->lfe_stream = -1; + if (mapping_family==0) + { + if (channels==1) + { + *streams=1; + *coupled_streams=0; + mapping[0]=0; + } else if (channels==2) + { + *streams=1; + *coupled_streams=1; + mapping[0]=0; + mapping[1]=1; + } else + return OPUS_UNIMPLEMENTED; + } else if (mapping_family==1 && channels<=8 && channels>=1) + { + int i; + *streams=vorbis_mappings[channels-1].nb_streams; + *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams; + for (i=0;i<channels;i++) + mapping[i] = vorbis_mappings[channels-1].mapping[i]; + if (channels>=6) + st->lfe_stream = *streams-1; + } else if (mapping_family==255) + { + int i; + *streams=channels; + *coupled_streams=0; + for(i=0;i<channels;i++) + mapping[i] = i; + } else + return OPUS_UNIMPLEMENTED; + return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams, + mapping, application, channels>2&&mapping_family==1); +} + +OpusMSEncoder *opus_multistream_encoder_create( + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int application, + int *error +) +{ + int ret; + OpusMSEncoder *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 = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams)); + if (st==NULL) + { + if (error) + *error = OPUS_ALLOC_FAIL; + return NULL; + } + ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application); + if (ret != OPUS_OK) + { + opus_free(st); + st = NULL; + } + if (error) + *error = ret; + return st; +} + +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 +) +{ + int ret; + opus_int32 size; + OpusMSEncoder *st; + if ((channels>255) || (channels<1)) + { + if (error) + *error = OPUS_BAD_ARG; + return NULL; + } + size = opus_multistream_surround_encoder_get_size(channels, mapping_family); + if (!size) + { + if (error) + *error = OPUS_UNIMPLEMENTED; + return NULL; + } + st = (OpusMSEncoder *)opus_alloc(size); + if (st==NULL) + { + if (error) + *error = OPUS_ALLOC_FAIL; + return NULL; + } + ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application); + if (ret != OPUS_OK) + { + opus_free(st); + st = NULL; + } + if (error) + *error = ret; + return st; +} + +static opus_int32 surround_rate_allocation( + OpusMSEncoder *st, + opus_int32 *rate, + int frame_size + ) +{ + int i; + opus_int32 channel_rate; + opus_int32 Fs; + char *ptr; + int stream_offset; + int lfe_offset; + int coupled_ratio; /* Q8 */ + int lfe_ratio; /* Q8 */ + opus_int32 rate_sum=0; + + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs)); + + if (st->bitrate_bps > st->layout.nb_channels*40000) + stream_offset = 20000; + else + stream_offset = st->bitrate_bps/st->layout.nb_channels/2; + stream_offset += 60*(Fs/frame_size-50); + /* We start by giving each stream (coupled or uncoupled) the same bitrate. + This models the main saving of coupled channels over uncoupled. */ + /* The LFE stream is an exception to the above and gets fewer bits. */ + lfe_offset = 3500 + 60*(Fs/frame_size-50); + /* Coupled streams get twice the mono rate after the first 20 kb/s. */ + coupled_ratio = 512; + /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */ + lfe_ratio = 32; + + /* Compute bitrate allocation between streams */ + if (st->bitrate_bps==OPUS_AUTO) + { + channel_rate = Fs+60*Fs/frame_size; + } else if (st->bitrate_bps==OPUS_BITRATE_MAX) + { + channel_rate = 300000; + } else { + int nb_lfe; + int nb_uncoupled; + int nb_coupled; + int total; + nb_lfe = (st->lfe_stream!=-1); + nb_coupled = st->layout.nb_coupled_streams; + nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe; + total = (nb_uncoupled<<8) /* mono */ + + coupled_ratio*nb_coupled /* stereo */ + + nb_lfe*lfe_ratio; + channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total; + } +#ifndef FIXED_POINT + if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50) + { + opus_int32 bonus; + bonus = 60*(Fs/frame_size-50); + channel_rate += bonus; + } +#endif + + for (i=0;i<st->layout.nb_streams;i++) + { + if (i<st->layout.nb_coupled_streams) + rate[i] = stream_offset+(channel_rate*coupled_ratio>>8); + else if (i!=st->lfe_stream) + rate[i] = stream_offset+channel_rate; + else + rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8); + rate[i] = IMAX(rate[i], 500); + rate_sum += rate[i]; + } + return rate_sum; +} + +/* Max size in case the encoder decides to return three frames */ +#define MS_FRAME_TMP (3*1275+7) +static int opus_multistream_encode_native +( + 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 +) +{ + opus_int32 Fs; + int coupled_size; + int mono_size; + int s; + char *ptr; + int tot_size; + VARDECL(opus_val16, buf); + VARDECL(opus_val16, bandSMR); + unsigned char tmp_data[MS_FRAME_TMP]; + OpusRepacketizer rp; + opus_int32 vbr; + const CELTMode *celt_mode; + opus_int32 bitrates[256]; + opus_val16 bandLogE[42]; + opus_val32 *mem = NULL; + opus_val32 *preemph_mem=NULL; + int frame_size; + opus_int32 rate_sum; + opus_int32 smallest_packet; + ALLOC_STACK; + + if (st->surround) + { + preemph_mem = ms_get_preemph_mem(st); + mem = ms_get_window_mem(st); + } + + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs)); + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr)); + opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode)); + + { + opus_int32 delay_compensation; + int channels; + + channels = st->layout.nb_streams + st->layout.nb_coupled_streams; + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation)); + delay_compensation -= Fs/400; + frame_size = compute_frame_size(pcm, analysis_frame_size, + st->variable_duration, channels, Fs, st->bitrate_bps, + delay_compensation, downmix +#ifndef DISABLE_FLOAT_API + , st->subframe_mem +#endif + ); + } + + if (400*frame_size < Fs) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + /* Validate frame_size before using it to allocate stack space. + This mirrors the checks in opus_encode[_float](). */ + if (400*frame_size != Fs && 200*frame_size != Fs && + 100*frame_size != Fs && 50*frame_size != Fs && + 25*frame_size != Fs && 50*frame_size != 3*Fs) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + + /* Smallest packet the encoder can produce. */ + smallest_packet = st->layout.nb_streams*2-1; + if (max_data_bytes < smallest_packet) + { + RESTORE_STACK; + return OPUS_BUFFER_TOO_SMALL; + } + ALLOC(buf, 2*frame_size, opus_val16); + coupled_size = opus_encoder_get_size(2); + mono_size = opus_encoder_get_size(1); + + ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16); + if (st->surround) + { + surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in, st->arch); + } + + /* Compute bitrate allocation between streams (this could be a lot better) */ + rate_sum = surround_rate_allocation(st, bitrates, frame_size); + + if (!vbr) + { + if (st->bitrate_bps == OPUS_AUTO) + { + max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size)); + } else if (st->bitrate_bps != OPUS_BITRATE_MAX) + { + max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet, + 3*st->bitrate_bps/(3*8*Fs/frame_size))); + } + } + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + for (s=0;s<st->layout.nb_streams;s++) + { + OpusEncoder *enc; + enc = (OpusEncoder*)ptr; + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s])); + if (st->surround) + { + opus_int32 equiv_rate; + equiv_rate = st->bitrate_bps; + if (frame_size*50 < Fs) + equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels; + if (equiv_rate > 10000*st->layout.nb_channels) + opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND)); + else if (equiv_rate > 7000*st->layout.nb_channels) + opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND)); + else if (equiv_rate > 5000*st->layout.nb_channels) + opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND)); + else + opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND)); + if (s < st->layout.nb_coupled_streams) + { + /* To preserve the spatial image, force stereo CELT on coupled streams */ + opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY)); + opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2)); + } + } + } + + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + /* Counting ToC */ + tot_size = 0; + for (s=0;s<st->layout.nb_streams;s++) + { + OpusEncoder *enc; + int len; + int curr_max; + int c1, c2; + + opus_repacketizer_init(&rp); + enc = (OpusEncoder*)ptr; + if (s < st->layout.nb_coupled_streams) + { + int i; + int left, right; + left = get_left_channel(&st->layout, s, -1); + right = get_right_channel(&st->layout, s, -1); + (*copy_channel_in)(buf, 2, + pcm, st->layout.nb_channels, left, frame_size); + (*copy_channel_in)(buf+1, 2, + pcm, st->layout.nb_channels, right, frame_size); + ptr += align(coupled_size); + if (st->surround) + { + for (i=0;i<21;i++) + { + bandLogE[i] = bandSMR[21*left+i]; + bandLogE[21+i] = bandSMR[21*right+i]; + } + } + c1 = left; + c2 = right; + } else { + int i; + int chan = get_mono_channel(&st->layout, s, -1); + (*copy_channel_in)(buf, 1, + pcm, st->layout.nb_channels, chan, frame_size); + ptr += align(mono_size); + if (st->surround) + { + for (i=0;i<21;i++) + bandLogE[i] = bandSMR[21*chan+i]; + } + c1 = chan; + c2 = -1; + } + if (st->surround) + opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE)); + /* number of bytes left (+Toc) */ + curr_max = max_data_bytes - tot_size; + /* Reserve one byte for the last stream and two for the others */ + curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1); + curr_max = IMIN(curr_max,MS_FRAME_TMP); + /* Repacketizer will add one or two bytes for self-delimited frames */ + if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1; + if (!vbr && s == st->layout.nb_streams-1) + opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size))); + len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth, + pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api); + if (len<0) + { + RESTORE_STACK; + return len; + } + /* We need to use the repacketizer to add the self-delimiting lengths + while taking into account the fact that the encoder can now return + more than one frame at a time (e.g. 60 ms CELT-only) */ + opus_repacketizer_cat(&rp, tmp_data, len); + len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp), + data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1); + data += len; + tot_size += len; + } + /*printf("\n");*/ + RESTORE_STACK; + return tot_size; +} + +#if !defined(DISABLE_FLOAT_API) +static void opus_copy_channel_in_float( + opus_val16 *dst, + int dst_stride, + const void *src, + int src_stride, + int src_channel, + int frame_size +) +{ + const float *float_src; + opus_int32 i; + float_src = (const float *)src; + for (i=0;i<frame_size;i++) +#if defined(FIXED_POINT) + dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]); +#else + dst[i*dst_stride] = float_src[i*src_stride+src_channel]; +#endif +} +#endif + +static void opus_copy_channel_in_short( + opus_val16 *dst, + int dst_stride, + const void *src, + int src_stride, + int src_channel, + int frame_size +) +{ + const opus_int16 *short_src; + opus_int32 i; + short_src = (const opus_int16 *)src; + for (i=0;i<frame_size;i++) +#if defined(FIXED_POINT) + dst[i*dst_stride] = short_src[i*src_stride+src_channel]; +#else + dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel]; +#endif +} + + +#ifdef FIXED_POINT +int opus_multistream_encode( + OpusMSEncoder *st, + const opus_val16 *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) +{ + return opus_multistream_encode_native(st, opus_copy_channel_in_short, + pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0); +} + +#ifndef DISABLE_FLOAT_API +int opus_multistream_encode_float( + OpusMSEncoder *st, + const float *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) +{ + return opus_multistream_encode_native(st, opus_copy_channel_in_float, + pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1); +} +#endif + +#else + +int opus_multistream_encode_float +( + OpusMSEncoder *st, + const opus_val16 *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) +{ + return opus_multistream_encode_native(st, opus_copy_channel_in_float, + pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1); +} + +int opus_multistream_encode( + OpusMSEncoder *st, + const opus_int16 *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) +{ + return opus_multistream_encode_native(st, opus_copy_channel_in_short, + pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0); +} +#endif + +int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) +{ + va_list ap; + int coupled_size, mono_size; + char *ptr; + int ret = OPUS_OK; + + va_start(ap, request); + + coupled_size = opus_encoder_get_size(2); + mono_size = opus_encoder_get_size(1); + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + switch (request) + { + case OPUS_SET_BITRATE_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX) + { + goto bad_arg; + } + st->bitrate_bps = value; + } + break; + case OPUS_GET_BITRATE_REQUEST: + { + int s; + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = 0; + for (s=0;s<st->layout.nb_streams;s++) + { + opus_int32 rate; + OpusEncoder *enc; + enc = (OpusEncoder*)ptr; + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + opus_encoder_ctl(enc, request, &rate); + *value += rate; + } + } + break; + case OPUS_GET_LSB_DEPTH_REQUEST: + case OPUS_GET_VBR_REQUEST: + case OPUS_GET_APPLICATION_REQUEST: + case OPUS_GET_BANDWIDTH_REQUEST: + case OPUS_GET_COMPLEXITY_REQUEST: + case OPUS_GET_PACKET_LOSS_PERC_REQUEST: + case OPUS_GET_DTX_REQUEST: + case OPUS_GET_VOICE_RATIO_REQUEST: + case OPUS_GET_VBR_CONSTRAINT_REQUEST: + case OPUS_GET_SIGNAL_REQUEST: + case OPUS_GET_LOOKAHEAD_REQUEST: + case OPUS_GET_SAMPLE_RATE_REQUEST: + case OPUS_GET_INBAND_FEC_REQUEST: + case OPUS_GET_FORCE_CHANNELS_REQUEST: + case OPUS_GET_PREDICTION_DISABLED_REQUEST: + { + OpusEncoder *enc; + /* For int32* GET params, just query the first stream */ + opus_int32 *value = va_arg(ap, opus_int32*); + enc = (OpusEncoder*)ptr; + ret = opus_encoder_ctl(enc, 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++) + { + OpusEncoder *enc; + enc = (OpusEncoder*)ptr; + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + ret = opus_encoder_ctl(enc, request, &tmp); + if (ret != OPUS_OK) break; + *value ^= tmp; + } + } + break; + case OPUS_SET_LSB_DEPTH_REQUEST: + case OPUS_SET_COMPLEXITY_REQUEST: + case OPUS_SET_VBR_REQUEST: + case OPUS_SET_VBR_CONSTRAINT_REQUEST: + case OPUS_SET_MAX_BANDWIDTH_REQUEST: + case OPUS_SET_BANDWIDTH_REQUEST: + case OPUS_SET_SIGNAL_REQUEST: + case OPUS_SET_APPLICATION_REQUEST: + case OPUS_SET_INBAND_FEC_REQUEST: + case OPUS_SET_PACKET_LOSS_PERC_REQUEST: + case OPUS_SET_DTX_REQUEST: + case OPUS_SET_FORCE_MODE_REQUEST: + case OPUS_SET_FORCE_CHANNELS_REQUEST: + case OPUS_SET_PREDICTION_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++) + { + OpusEncoder *enc; + + enc = (OpusEncoder*)ptr; + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + ret = opus_encoder_ctl(enc, request, value); + if (ret != OPUS_OK) + break; + } + } + break; + case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST: + { + int s; + opus_int32 stream_id; + OpusEncoder **value; + stream_id = va_arg(ap, opus_int32); + if (stream_id<0 || stream_id >= st->layout.nb_streams) + ret = OPUS_BAD_ARG; + value = va_arg(ap, OpusEncoder**); + 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 = (OpusEncoder*)ptr; + } + break; + case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->variable_duration = value; + } + break; + case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->variable_duration; + } + break; + case OPUS_RESET_STATE: + { + int s; + st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0; + if (st->surround) + { + OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels); + OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120); + } + for (s=0;s<st->layout.nb_streams;s++) + { + OpusEncoder *enc; + enc = (OpusEncoder*)ptr; + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + ret = opus_encoder_ctl(enc, OPUS_RESET_STATE); + if (ret != OPUS_OK) + break; + } + } + break; + default: + ret = OPUS_UNIMPLEMENTED; + break; + } + + va_end(ap); + return ret; +bad_arg: + va_end(ap); + return OPUS_BAD_ARG; +} + +void opus_multistream_encoder_destroy(OpusMSEncoder *st) +{ + opus_free(st); +} diff --git a/thirdparty/opus/opus_private.h b/thirdparty/opus/opus_private.h new file mode 100644 index 0000000000..3b62eed096 --- /dev/null +++ b/thirdparty/opus/opus_private.h @@ -0,0 +1,134 @@ +/* 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 <stddef.h> /* offsetof */ + +struct OpusRepacketizer { + unsigned char toc; + int nb_frames; + const unsigned char *frames[48]; + opus_int16 len[48]; + int framesize; +}; + +typedef struct ChannelLayout { + int nb_channels; + int nb_streams; + int nb_coupled_streams; + unsigned char mapping[256]; +} ChannelLayout; + +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); + + + +#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); + +int encode_size(int size, unsigned char *data); + +opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs); + +opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size, + int variable_duration, int C, opus_int32 Fs, int bitrate_bps, + int delay_compensation, downmix_func downmix +#ifndef DISABLE_FLOAT_API + , float *subframe_mem +#endif + ); + +opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *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_val16 *pcm, int frame_size, int decode_fec, int self_delimited, + opus_int32 *packet_offset, int soft_clip); + +/* 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); + +opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end, + unsigned char *data, opus_int32 maxlen, int self_delimited, int pad); + +int pad_frame(unsigned char *data, opus_int32 len, opus_int32 new_len); + +#endif /* OPUS_PRIVATE_H */ diff --git a/drivers/opus/opus_types.h b/thirdparty/opus/opus_types.h index b28e03aea2..b28e03aea2 100644 --- a/drivers/opus/opus_types.h +++ b/thirdparty/opus/opus_types.h diff --git a/thirdparty/opus/opusfile.c b/thirdparty/opus/opusfile.c new file mode 100644 index 0000000000..9c9b684ca4 --- /dev/null +++ b/thirdparty/opus/opusfile.c @@ -0,0 +1,3277 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: stdio-based convenience library for opening/seeking/decoding + last mod: $Id: vorbisfile.c 17573 2010-10-27 14:53:59Z xiphmont $ + + ********************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "internal.h" +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <limits.h> +#include <string.h> +#include <math.h> + +#include "opusfile.h" + +/*This implementation is largely based off of libvorbisfile. + All of the Ogg bits work roughly the same, though I have made some + "improvements" that have not been folded back there, yet.*/ + +/*A 'chained bitstream' is an Ogg Opus bitstream that contains more than one + logical bitstream arranged end to end (the only form of Ogg multiplexing + supported by this library. + Grouping (parallel multiplexing) is not supported, except to the extent that + if there are multiple logical Ogg streams in a single link of the chain, we + will ignore all but the first Opus stream we find.*/ + +/*An Ogg Opus file can be played beginning to end (streamed) without worrying + ahead of time about chaining (see opusdec from the opus-tools package). + If we have the whole file, however, and want random access + (seeking/scrubbing) or desire to know the total length/time of a file, we + need to account for the possibility of chaining.*/ + +/*We can handle things a number of ways. + We can determine the entire bitstream structure right off the bat, or find + pieces on demand. + This library determines and caches structure for the entire bitstream, but + builds a virtual decoder on the fly when moving between links in the chain.*/ + +/*There are also different ways to implement seeking. + Enough information exists in an Ogg bitstream to seek to sample-granularity + positions in the output. + Or, one can seek by picking some portion of the stream roughly in the desired + area if we only want coarse navigation through the stream. + We implement and expose both strategies.*/ + +/*The maximum number of bytes in a page (including the page headers).*/ +#define OP_PAGE_SIZE_MAX (65307) +/*The default amount to seek backwards per step when trying to find the + previous page. + This must be at least as large as the maximum size of a page.*/ +#define OP_CHUNK_SIZE (65536) +/*The maximum amount to seek backwards per step when trying to find the + previous page.*/ +#define OP_CHUNK_SIZE_MAX (1024*(opus_int32)1024) +/*A smaller read size is needed for low-rate streaming.*/ +#define OP_READ_SIZE (2048) + +int op_test(OpusHead *_head, + const unsigned char *_initial_data,size_t _initial_bytes){ + ogg_sync_state oy; + char *data; + int err; + /*The first page of a normal Opus file will be at most 57 bytes (27 Ogg + page header bytes + 1 lacing value + 21 Opus header bytes + 8 channel + mapping bytes). + It will be at least 47 bytes (27 Ogg page header bytes + 1 lacing value + + 19 Opus header bytes using channel mapping family 0). + If we don't have at least that much data, give up now.*/ + if(_initial_bytes<47)return OP_FALSE; + /*Only proceed if we start with the magic OggS string. + This is to prevent us spending a lot of time allocating memory and looking + for Ogg pages in non-Ogg files.*/ + if(memcmp(_initial_data,"OggS",4)!=0)return OP_ENOTFORMAT; + ogg_sync_init(&oy); + data=ogg_sync_buffer(&oy,_initial_bytes); + if(data!=NULL){ + ogg_stream_state os; + ogg_page og; + int ret; + memcpy(data,_initial_data,_initial_bytes); + ogg_sync_wrote(&oy,_initial_bytes); + ogg_stream_init(&os,-1); + err=OP_FALSE; + do{ + ogg_packet op; + ret=ogg_sync_pageout(&oy,&og); + /*Ignore holes.*/ + if(ret<0)continue; + /*Stop if we run out of data.*/ + if(!ret)break; + ogg_stream_reset_serialno(&os,ogg_page_serialno(&og)); + ogg_stream_pagein(&os,&og); + /*Only process the first packet on this page (if it's a BOS packet, + it's required to be the only one).*/ + if(ogg_stream_packetout(&os,&op)==1){ + if(op.b_o_s){ + ret=opus_head_parse(_head,op.packet,op.bytes); + /*If this didn't look like Opus, keep going.*/ + if(ret==OP_ENOTFORMAT)continue; + /*Otherwise we're done, one way or another.*/ + err=ret; + } + /*We finished parsing the headers. + There is no Opus to be found.*/ + else err=OP_ENOTFORMAT; + } + } + while(err==OP_FALSE); + ogg_stream_clear(&os); + } + else err=OP_EFAULT; + ogg_sync_clear(&oy); + return err; +} + +/*Many, many internal helpers. + The intention is not to be confusing. + Rampant duplication and monolithic function implementation (though we do have + some large, omnibus functions still) would be harder to understand anyway. + The high level functions are last. + Begin grokking near the end of the file if you prefer to read things + top-down.*/ + +/*The read/seek functions track absolute position within the stream.*/ + +/*Read a little more data from the file/pipe into the ogg_sync framer. + _nbytes: The maximum number of bytes to read. + Return: A positive number of bytes read on success, 0 on end-of-file, or a + negative value on failure.*/ +static int op_get_data(OggOpusFile *_of,int _nbytes){ + unsigned char *buffer; + int nbytes; + OP_ASSERT(_nbytes>0); + buffer=(unsigned char *)ogg_sync_buffer(&_of->oy,_nbytes); + nbytes=(int)(*_of->callbacks.read)(_of->source,buffer,_nbytes); + OP_ASSERT(nbytes<=_nbytes); + if(OP_LIKELY(nbytes>0))ogg_sync_wrote(&_of->oy,nbytes); + return nbytes; +} + +/*Save a tiny smidge of verbosity to make the code more readable.*/ +static int op_seek_helper(OggOpusFile *_of,opus_int64 _offset){ + if(_offset==_of->offset)return 0; + if(_of->callbacks.seek==NULL + ||(*_of->callbacks.seek)(_of->source,_offset,SEEK_SET)){ + return OP_EREAD; + } + _of->offset=_offset; + ogg_sync_reset(&_of->oy); + return 0; +} + +/*Get the current position indicator of the underlying source. + This should be the same as the value reported by tell().*/ +static opus_int64 op_position(const OggOpusFile *_of){ + /*The current position indicator is _not_ simply offset. + We may also have unprocessed, buffered data in the sync state.*/ + return _of->offset+_of->oy.fill-_of->oy.returned; +} + +/*From the head of the stream, get the next page. + _boundary specifies if the function is allowed to fetch more data from the + stream (and how much) or only use internally buffered data. + _boundary: -1: Unbounded search. + 0: Read no additional data. + Use only cached data. + n: Search for the start of a new page up to file position n. + Return: n>=0: Found a page at absolute offset n. + OP_FALSE: Hit the _boundary limit. + OP_EREAD: An underlying read operation failed. + OP_BADLINK: We hit end-of-file before reaching _boundary.*/ +static opus_int64 op_get_next_page(OggOpusFile *_of,ogg_page *_og, + opus_int64 _boundary){ + while(_boundary<=0||_of->offset<_boundary){ + int more; + more=ogg_sync_pageseek(&_of->oy,_og); + /*Skipped (-more) bytes.*/ + if(OP_UNLIKELY(more<0))_of->offset-=more; + else if(more==0){ + int read_nbytes; + int ret; + /*Send more paramedics.*/ + if(!_boundary)return OP_FALSE; + if(_boundary<0)read_nbytes=OP_READ_SIZE; + else{ + opus_int64 position; + position=op_position(_of); + if(position>=_boundary)return OP_FALSE; + read_nbytes=(int)OP_MIN(_boundary-position,OP_READ_SIZE); + } + ret=op_get_data(_of,read_nbytes); + if(OP_UNLIKELY(ret<0))return OP_EREAD; + if(OP_UNLIKELY(ret==0)){ + /*Only fail cleanly on EOF if we didn't have a known boundary. + Otherwise, we should have been able to reach that boundary, and this + is a fatal error.*/ + return OP_UNLIKELY(_boundary<0)?OP_FALSE:OP_EBADLINK; + } + } + else{ + /*Got a page. + Return the page start offset and advance the internal offset past the + page end.*/ + opus_int64 page_offset; + page_offset=_of->offset; + _of->offset+=more; + OP_ASSERT(page_offset>=0); + return page_offset; + } + } + return OP_FALSE; +} + +static int op_add_serialno(const ogg_page *_og, + ogg_uint32_t **_serialnos,int *_nserialnos,int *_cserialnos){ + ogg_uint32_t *serialnos; + int nserialnos; + int cserialnos; + ogg_uint32_t s; + s=ogg_page_serialno(_og); + serialnos=*_serialnos; + nserialnos=*_nserialnos; + cserialnos=*_cserialnos; + if(OP_UNLIKELY(nserialnos>=cserialnos)){ + if(OP_UNLIKELY(cserialnos>INT_MAX/(int)sizeof(*serialnos)-1>>1)){ + return OP_EFAULT; + } + cserialnos=2*cserialnos+1; + OP_ASSERT(nserialnos<cserialnos); + serialnos=(ogg_uint32_t *)_ogg_realloc(serialnos, + sizeof(*serialnos)*cserialnos); + if(OP_UNLIKELY(serialnos==NULL))return OP_EFAULT; + } + serialnos[nserialnos++]=s; + *_serialnos=serialnos; + *_nserialnos=nserialnos; + *_cserialnos=cserialnos; + return 0; +} + +/*Returns nonzero if found.*/ +static int op_lookup_serialno(ogg_uint32_t _s, + const ogg_uint32_t *_serialnos,int _nserialnos){ + int i; + for(i=0;i<_nserialnos&&_serialnos[i]!=_s;i++); + return i<_nserialnos; +} + +static int op_lookup_page_serialno(const ogg_page *_og, + const ogg_uint32_t *_serialnos,int _nserialnos){ + return op_lookup_serialno(ogg_page_serialno(_og),_serialnos,_nserialnos); +} + +typedef struct OpusSeekRecord OpusSeekRecord; + +/*We use this to remember the pages we found while enumerating the links of a + chained stream. + We keep track of the starting and ending offsets, as well as the point we + started searching from, so we know where to bisect. + We also keep the serial number, so we can tell if the page belonged to the + current link or not, as well as the granule position, to aid in estimating + the start of the link.*/ +struct OpusSeekRecord{ + /*The earliest byte we know of such that reading forward from it causes + capture to be regained at this page.*/ + opus_int64 search_start; + /*The offset of this page.*/ + opus_int64 offset; + /*The size of this page.*/ + opus_int32 size; + /*The serial number of this page.*/ + ogg_uint32_t serialno; + /*The granule position of this page.*/ + ogg_int64_t gp; +}; + +/*Find the last page beginning before _offset with a valid granule position. + There is no '_boundary' parameter as it will always have to read more data. + This is much dirtier than the above, as Ogg doesn't have any backward search + linkage. + This search prefers pages of the specified serial number. + If a page of the specified serial number is spotted during the + seek-back-and-read-forward, it will return the info of last page of the + matching serial number, instead of the very last page, unless the very last + page belongs to a different link than preferred serial number. + If no page of the specified serial number is seen, it will return the info of + the last page. + [out] _sr: Returns information about the page that was found on success. + _offset: The _offset before which to find a page. + Any page returned will consist of data entirely before _offset. + _serialno: The preferred serial number. + If a page with this serial number is found, it will be returned + even if another page in the same link is found closer to + _offset. + This is purely opportunistic: there is no guarantee such a page + will be found if it exists. + _serialnos: The list of serial numbers in the link that contains the + preferred serial number. + _nserialnos: The number of serial numbers in the current link. + Return: 0 on success, or a negative value on failure. + OP_EREAD: Failed to read more data (error or EOF). + OP_EBADLINK: We couldn't find a page even after seeking back to the + start of the stream.*/ +static int op_get_prev_page_serial(OggOpusFile *_of,OpusSeekRecord *_sr, + opus_int64 _offset,ogg_uint32_t _serialno, + const ogg_uint32_t *_serialnos,int _nserialnos){ + OpusSeekRecord preferred_sr; + ogg_page og; + opus_int64 begin; + opus_int64 end; + opus_int64 original_end; + opus_int32 chunk_size; + int preferred_found; + original_end=end=begin=_offset; + preferred_found=0; + _offset=-1; + chunk_size=OP_CHUNK_SIZE; + do{ + opus_int64 search_start; + int ret; + OP_ASSERT(chunk_size>=OP_PAGE_SIZE_MAX); + begin=OP_MAX(begin-chunk_size,0); + ret=op_seek_helper(_of,begin); + if(OP_UNLIKELY(ret<0))return ret; + search_start=begin; + while(_of->offset<end){ + opus_int64 llret; + ogg_uint32_t serialno; + llret=op_get_next_page(_of,&og,end); + if(OP_UNLIKELY(llret<OP_FALSE))return (int)llret; + else if(llret==OP_FALSE)break; + serialno=ogg_page_serialno(&og); + /*Save the information for this page. + We're not interested in the page itself... just the serial number, byte + offset, page size, and granule position.*/ + _sr->search_start=search_start; + _sr->offset=_offset=llret; + _sr->serialno=serialno; + OP_ASSERT(_of->offset-_offset>=0); + OP_ASSERT(_of->offset-_offset<=OP_PAGE_SIZE_MAX); + _sr->size=(opus_int32)(_of->offset-_offset); + _sr->gp=ogg_page_granulepos(&og); + /*If this page is from the stream we're looking for, remember it.*/ + if(serialno==_serialno){ + preferred_found=1; + *&preferred_sr=*_sr; + } + if(!op_lookup_serialno(serialno,_serialnos,_nserialnos)){ + /*We fell off the end of the link, which means we seeked back too far + and shouldn't have been looking in that link to begin with. + If we found the preferred serial number, forget that we saw it.*/ + preferred_found=0; + } + search_start=llret+1; + } + /*We started from the beginning of the stream and found nothing. + This should be impossible unless the contents of the source changed out + from under us after we read from it.*/ + if(OP_UNLIKELY(!begin)&&OP_UNLIKELY(_offset<0))return OP_EBADLINK; + /*Bump up the chunk size. + This is mildly helpful when seeks are very expensive (http).*/ + chunk_size=OP_MIN(2*chunk_size,OP_CHUNK_SIZE_MAX); + /*Avoid quadratic complexity if we hit an invalid patch of the file.*/ + end=OP_MIN(begin+OP_PAGE_SIZE_MAX-1,original_end); + } + while(_offset<0); + if(preferred_found)*_sr=*&preferred_sr; + return 0; +} + +/*Find the last page beginning before _offset with the given serial number and + a valid granule position. + Unlike the above search, this continues until it finds such a page, but does + not stray outside the current link. + We could implement it (inefficiently) by calling op_get_prev_page_serial() + repeatedly until it returned a page that had both our preferred serial + number and a valid granule position, but doing it with a separate function + allows us to avoid repeatedly re-scanning valid pages from other streams as + we seek-back-and-read-forward. + [out] _gp: Returns the granule position of the page that was found on + success. + _offset: The _offset before which to find a page. + Any page returned will consist of data entirely before _offset. + _serialno: The target serial number. + _serialnos: The list of serial numbers in the link that contains the + preferred serial number. + _nserialnos: The number of serial numbers in the current link. + Return: The offset of the page on success, or a negative value on failure. + OP_EREAD: Failed to read more data (error or EOF). + OP_EBADLINK: We couldn't find a page even after seeking back past the + beginning of the link.*/ +static opus_int64 op_get_last_page(OggOpusFile *_of,ogg_int64_t *_gp, + opus_int64 _offset,ogg_uint32_t _serialno, + const ogg_uint32_t *_serialnos,int _nserialnos){ + ogg_page og; + ogg_int64_t gp; + opus_int64 begin; + opus_int64 end; + opus_int64 original_end; + opus_int32 chunk_size; + /*The target serial number must belong to the current link.*/ + OP_ASSERT(op_lookup_serialno(_serialno,_serialnos,_nserialnos)); + original_end=end=begin=_offset; + _offset=-1; + /*We shouldn't have to initialize gp, but gcc is too dumb to figure out that + ret>=0 implies we entered the if(page_gp!=-1) block at least once.*/ + gp=-1; + chunk_size=OP_CHUNK_SIZE; + do{ + int left_link; + int ret; + OP_ASSERT(chunk_size>=OP_PAGE_SIZE_MAX); + begin=OP_MAX(begin-chunk_size,0); + ret=op_seek_helper(_of,begin); + if(OP_UNLIKELY(ret<0))return ret; + left_link=0; + while(_of->offset<end){ + opus_int64 llret; + ogg_uint32_t serialno; + llret=op_get_next_page(_of,&og,end); + if(OP_UNLIKELY(llret<OP_FALSE))return llret; + else if(llret==OP_FALSE)break; + serialno=ogg_page_serialno(&og); + if(serialno==_serialno){ + ogg_int64_t page_gp; + /*The page is from the right stream...*/ + page_gp=ogg_page_granulepos(&og); + if(page_gp!=-1){ + /*And has a valid granule position. + Let's remember it.*/ + _offset=llret; + gp=page_gp; + } + } + else if(OP_UNLIKELY(!op_lookup_serialno(serialno, + _serialnos,_nserialnos))){ + /*We fell off the start of the link, which means we don't need to keep + seeking any farther back.*/ + left_link=1; + } + } + /*We started from at or before the beginning of the link and found nothing. + This should be impossible unless the contents of the source changed out + from under us after we read from it.*/ + if((OP_UNLIKELY(left_link)||OP_UNLIKELY(!begin))&&OP_UNLIKELY(_offset<0)){ + return OP_EBADLINK; + } + /*Bump up the chunk size. + This is mildly helpful when seeks are very expensive (http).*/ + chunk_size=OP_MIN(2*chunk_size,OP_CHUNK_SIZE_MAX); + /*Avoid quadratic complexity if we hit an invalid patch of the file.*/ + end=OP_MIN(begin+OP_PAGE_SIZE_MAX-1,original_end); + } + while(_offset<0); + *_gp=gp; + return _offset; +} + +/*Uses the local ogg_stream storage in _of. + This is important for non-streaming input sources.*/ +static int op_fetch_headers_impl(OggOpusFile *_of,OpusHead *_head, + OpusTags *_tags,ogg_uint32_t **_serialnos,int *_nserialnos, + int *_cserialnos,ogg_page *_og){ + ogg_packet op; + int ret; + if(_serialnos!=NULL)*_nserialnos=0; + /*Extract the serialnos of all BOS pages plus the first set of Opus headers + we see in the link.*/ + while(ogg_page_bos(_og)){ + if(_serialnos!=NULL){ + if(OP_UNLIKELY(op_lookup_page_serialno(_og,*_serialnos,*_nserialnos))){ + /*A dupe serialnumber in an initial header packet set==invalid stream.*/ + return OP_EBADHEADER; + } + ret=op_add_serialno(_og,_serialnos,_nserialnos,_cserialnos); + if(OP_UNLIKELY(ret<0))return ret; + } + if(_of->ready_state<OP_STREAMSET){ + /*We don't have an Opus stream in this link yet, so begin prospective + stream setup. + We need a stream to get packets.*/ + ogg_stream_reset_serialno(&_of->os,ogg_page_serialno(_og)); + ogg_stream_pagein(&_of->os,_og); + if(OP_LIKELY(ogg_stream_packetout(&_of->os,&op)>0)){ + ret=opus_head_parse(_head,op.packet,op.bytes); + /*Found a valid Opus header. + Continue setup.*/ + if(OP_LIKELY(ret>=0))_of->ready_state=OP_STREAMSET; + /*If it's just a stream type we don't recognize, ignore it. + Everything else is fatal.*/ + else if(ret!=OP_ENOTFORMAT)return ret; + } + } + /*Get the next page. + No need to clamp the boundary offset against _of->end, as all errors + become OP_ENOTFORMAT or OP_EBADHEADER.*/ + if(OP_UNLIKELY(op_get_next_page(_of,_og, + OP_ADV_OFFSET(_of->offset,OP_CHUNK_SIZE))<0)){ + return _of->ready_state<OP_STREAMSET?OP_ENOTFORMAT:OP_EBADHEADER; + } + } + if(OP_UNLIKELY(_of->ready_state!=OP_STREAMSET))return OP_ENOTFORMAT; + /*If the first non-header page belonged to our Opus stream, submit it.*/ + if(_of->os.serialno==ogg_page_serialno(_og))ogg_stream_pagein(&_of->os,_og); + /*Loop getting packets.*/ + for(;;){ + switch(ogg_stream_packetout(&_of->os,&op)){ + case 0:{ + /*Loop getting pages.*/ + for(;;){ + /*No need to clamp the boundary offset against _of->end, as all + errors become OP_EBADHEADER.*/ + if(OP_UNLIKELY(op_get_next_page(_of,_og, + OP_ADV_OFFSET(_of->offset,OP_CHUNK_SIZE))<0)){ + return OP_EBADHEADER; + } + /*If this page belongs to the correct stream, go parse it.*/ + if(_of->os.serialno==ogg_page_serialno(_og)){ + ogg_stream_pagein(&_of->os,_og); + break; + } + /*If the link ends before we see the Opus comment header, abort.*/ + if(OP_UNLIKELY(ogg_page_bos(_og)))return OP_EBADHEADER; + /*Otherwise, keep looking.*/ + } + }break; + /*We shouldn't get a hole in the headers!*/ + case -1:return OP_EBADHEADER; + default:{ + /*Got a packet. + It should be the comment header.*/ + ret=opus_tags_parse(_tags,op.packet,op.bytes); + if(OP_UNLIKELY(ret<0))return ret; + /*Make sure the page terminated at the end of the comment header. + If there is another packet on the page, or part of a packet, then + reject the stream. + Otherwise seekable sources won't be able to seek back to the start + properly.*/ + ret=ogg_stream_packetout(&_of->os,&op); + if(OP_UNLIKELY(ret!=0) + ||OP_UNLIKELY(_og->header[_og->header_len-1]==255)){ + /*If we fail, the caller assumes our tags are uninitialized.*/ + opus_tags_clear(_tags); + return OP_EBADHEADER; + } + return 0; + } + } + } +} + +static int op_fetch_headers(OggOpusFile *_of,OpusHead *_head, + OpusTags *_tags,ogg_uint32_t **_serialnos,int *_nserialnos, + int *_cserialnos,ogg_page *_og){ + ogg_page og; + int ret; + if(!_og){ + /*No need to clamp the boundary offset against _of->end, as all errors + become OP_ENOTFORMAT.*/ + if(OP_UNLIKELY(op_get_next_page(_of,&og, + OP_ADV_OFFSET(_of->offset,OP_CHUNK_SIZE))<0)){ + return OP_ENOTFORMAT; + } + _og=&og; + } + _of->ready_state=OP_OPENED; + ret=op_fetch_headers_impl(_of,_head,_tags,_serialnos,_nserialnos, + _cserialnos,_og); + /*Revert back from OP_STREAMSET to OP_OPENED on failure, to prevent + double-free of the tags in an unseekable stream.*/ + if(OP_UNLIKELY(ret<0))_of->ready_state=OP_OPENED; + return ret; +} + +/*Granule position manipulation routines. + A granule position is defined to be an unsigned 64-bit integer, with the + special value -1 in two's complement indicating an unset or invalid granule + position. + We are not guaranteed to have an unsigned 64-bit type, so we construct the + following routines that + a) Properly order negative numbers as larger than positive numbers, and + b) Check for underflow or overflow past the special -1 value. + This lets us operate on the full, valid range of granule positions in a + consistent and safe manner. + This full range is organized into distinct regions: + [ -1 (invalid) ][ 0 ... OP_INT64_MAX ][ OP_INT64_MIN ... -2 ][-1 (invalid) ] + + No one should actually use granule positions so large that they're negative, + even if they are technically valid, as very little software handles them + correctly (including most of Xiph.Org's). + This library also refuses to support durations so large they won't fit in a + signed 64-bit integer (to avoid exposing this mess to the application, and + to simplify a good deal of internal arithmetic), so the only way to use them + successfully is if pcm_start is very large. + This means there isn't anything you can do with negative granule positions + that you couldn't have done with purely non-negative ones. + The main purpose of these routines is to allow us to think very explicitly + about the possible failure cases of all granule position manipulations.*/ + +/*Safely adds a small signed integer to a valid (not -1) granule position. + The result can use the full 64-bit range of values (both positive and + negative), but will fail on overflow (wrapping past -1; wrapping past + OP_INT64_MAX is explicitly okay). + [out] _dst_gp: The resulting granule position. + Only modified on success. + _src_gp: The granule position to add to. + This must not be -1. + _delta: The amount to add. + This is allowed to be up to 32 bits to support the maximum + duration of a single Ogg page (255 packets * 120 ms per + packet == 1,468,800 samples at 48 kHz). + Return: 0 on success, or OP_EINVAL if the result would wrap around past -1.*/ +static int op_granpos_add(ogg_int64_t *_dst_gp,ogg_int64_t _src_gp, + opus_int32 _delta){ + /*The code below handles this case correctly, but there's no reason we + should ever be called with these values, so make sure we aren't.*/ + OP_ASSERT(_src_gp!=-1); + if(_delta>0){ + /*Adding this amount to the granule position would overflow its 64-bit + range.*/ + if(OP_UNLIKELY(_src_gp<0)&&OP_UNLIKELY(_src_gp>=-1-_delta))return OP_EINVAL; + if(OP_UNLIKELY(_src_gp>OP_INT64_MAX-_delta)){ + /*Adding this amount to the granule position would overflow the positive + half of its 64-bit range. + Since signed overflow is undefined in C, do it in a way the compiler + isn't allowed to screw up.*/ + _delta-=(opus_int32)(OP_INT64_MAX-_src_gp)+1; + _src_gp=OP_INT64_MIN; + } + } + else if(_delta<0){ + /*Subtracting this amount from the granule position would underflow its + 64-bit range.*/ + if(_src_gp>=0&&OP_UNLIKELY(_src_gp<-_delta))return OP_EINVAL; + if(OP_UNLIKELY(_src_gp<OP_INT64_MIN-_delta)){ + /*Subtracting this amount from the granule position would underflow the + negative half of its 64-bit range. + Since signed underflow is undefined in C, do it in a way the compiler + isn't allowed to screw up.*/ + _delta+=(opus_int32)(_src_gp-OP_INT64_MIN)+1; + _src_gp=OP_INT64_MAX; + } + } + *_dst_gp=_src_gp+_delta; + return 0; +} + +/*Safely computes the difference between two granule positions. + The difference must fit in a signed 64-bit integer, or the function fails. + It correctly handles the case where the granule position has wrapped around + from positive values to negative ones. + [out] _delta: The difference between the granule positions. + Only modified on success. + _gp_a: The granule position to subtract from. + This must not be -1. + _gp_b: The granule position to subtract. + This must not be -1. + Return: 0 on success, or OP_EINVAL if the result would not fit in a signed + 64-bit integer.*/ +static int op_granpos_diff(ogg_int64_t *_delta, + ogg_int64_t _gp_a,ogg_int64_t _gp_b){ + int gp_a_negative; + int gp_b_negative; + /*The code below handles these cases correctly, but there's no reason we + should ever be called with these values, so make sure we aren't.*/ + OP_ASSERT(_gp_a!=-1); + OP_ASSERT(_gp_b!=-1); + gp_a_negative=OP_UNLIKELY(_gp_a<0); + gp_b_negative=OP_UNLIKELY(_gp_b<0); + if(OP_UNLIKELY(gp_a_negative^gp_b_negative)){ + ogg_int64_t da; + ogg_int64_t db; + if(gp_a_negative){ + /*_gp_a has wrapped to a negative value but _gp_b hasn't: the difference + should be positive.*/ + /*Step 1: Handle wrapping.*/ + /*_gp_a < 0 => da < 0.*/ + da=(OP_INT64_MIN-_gp_a)-1; + /*_gp_b >= 0 => db >= 0.*/ + db=OP_INT64_MAX-_gp_b; + /*Step 2: Check for overflow.*/ + if(OP_UNLIKELY(OP_INT64_MAX+da<db))return OP_EINVAL; + *_delta=db-da; + } + else{ + /*_gp_b has wrapped to a negative value but _gp_a hasn't: the difference + should be negative.*/ + /*Step 1: Handle wrapping.*/ + /*_gp_a >= 0 => da <= 0*/ + da=_gp_a+OP_INT64_MIN; + /*_gp_b < 0 => db <= 0*/ + db=OP_INT64_MIN-_gp_b; + /*Step 2: Check for overflow.*/ + if(OP_UNLIKELY(da<OP_INT64_MIN-db))return OP_EINVAL; + *_delta=da+db; + } + } + else *_delta=_gp_a-_gp_b; + return 0; +} + +static int op_granpos_cmp(ogg_int64_t _gp_a,ogg_int64_t _gp_b){ + /*The invalid granule position -1 should behave like NaN: neither greater + than nor less than any other granule position, nor equal to any other + granule position, including itself. + However, that means there isn't anything we could sensibly return from this + function for it.*/ + OP_ASSERT(_gp_a!=-1); + OP_ASSERT(_gp_b!=-1); + /*Handle the wrapping cases.*/ + if(OP_UNLIKELY(_gp_a<0)){ + if(_gp_b>=0)return 1; + /*Else fall through.*/ + } + else if(OP_UNLIKELY(_gp_b<0))return -1; + /*No wrapping case.*/ + return (_gp_a>_gp_b)-(_gp_b>_gp_a); +} + +/*Returns the duration of the packet (in samples at 48 kHz), or a negative + value on error.*/ +static int op_get_packet_duration(const unsigned char *_data,int _len){ + int nframes; + int frame_size; + int nsamples; + nframes=opus_packet_get_nb_frames(_data,_len); + if(OP_UNLIKELY(nframes<0))return OP_EBADPACKET; + frame_size=opus_packet_get_samples_per_frame(_data,48000); + nsamples=nframes*frame_size; + if(OP_UNLIKELY(nsamples>120*48))return OP_EBADPACKET; + return nsamples; +} + +/*This function more properly belongs in info.c, but we define it here to allow + the static granule position manipulation functions to remain static.*/ +ogg_int64_t opus_granule_sample(const OpusHead *_head,ogg_int64_t _gp){ + opus_int32 pre_skip; + pre_skip=_head->pre_skip; + if(_gp!=-1&&op_granpos_add(&_gp,_gp,-pre_skip))_gp=-1; + return _gp; +} + +/*Grab all the packets currently in the stream state, and compute their + durations. + _of->op_count is set to the number of packets collected. + [out] _durations: Returns the durations of the individual packets. + Return: The total duration of all packets, or OP_HOLE if there was a hole.*/ +static opus_int32 op_collect_audio_packets(OggOpusFile *_of, + int _durations[255]){ + opus_int32 total_duration; + int op_count; + /*Count the durations of all packets in the page.*/ + op_count=0; + total_duration=0; + for(;;){ + int ret; + /*This takes advantage of undocumented libogg behavior that returned + ogg_packet buffers are valid at least until the next page is + submitted. + Relying on this is not too terrible, as _none_ of the Ogg memory + ownership/lifetime rules are well-documented. + But I can read its code and know this will work.*/ + ret=ogg_stream_packetout(&_of->os,_of->op+op_count); + if(!ret)break; + if(OP_UNLIKELY(ret<0)){ + /*We shouldn't get holes in the middle of pages.*/ + OP_ASSERT(op_count==0); + /*Set the return value and break out of the loop. + We want to make sure op_count gets set to 0, because we've ingested a + page, so any previously loaded packets are now invalid.*/ + total_duration=OP_HOLE; + break; + } + /*Unless libogg is broken, we can't get more than 255 packets from a + single page.*/ + OP_ASSERT(op_count<255); + _durations[op_count]=op_get_packet_duration(_of->op[op_count].packet, + _of->op[op_count].bytes); + if(OP_LIKELY(_durations[op_count]>0)){ + /*With at most 255 packets on a page, this can't overflow.*/ + total_duration+=_durations[op_count++]; + } + /*Ignore packets with an invalid TOC sequence.*/ + else if(op_count>0){ + /*But save the granule position, if there was one.*/ + _of->op[op_count-1].granulepos=_of->op[op_count].granulepos; + } + } + _of->op_pos=0; + _of->op_count=op_count; + return total_duration; +} + +/*Starting from current cursor position, get the initial PCM offset of the next + page. + This also validates the granule position on the first page with a completed + audio data packet, as required by the spec. + If this link is completely empty (no pages with completed packets), then this + function sets pcm_start=pcm_end=0 and returns the BOS page of the next link + (if any). + In the seekable case, we initialize pcm_end=-1 before calling this function, + so that later we can detect that the link was empty before calling + op_find_final_pcm_offset(). + [inout] _link: The link for which to find pcm_start. + [out] _og: Returns the BOS page of the next link if this link was empty. + In the unseekable case, we can then feed this to + op_fetch_headers() to start the next link. + The caller may pass NULL (e.g., for seekable streams), in + which case this page will be discarded. + Return: 0 on success, 1 if there is a buffered BOS page available, or a + negative value on unrecoverable error.*/ +static int op_find_initial_pcm_offset(OggOpusFile *_of, + OggOpusLink *_link,ogg_page *_og){ + ogg_page og; + opus_int64 page_offset; + ogg_int64_t pcm_start; + ogg_int64_t prev_packet_gp; + ogg_int64_t cur_page_gp; + ogg_uint32_t serialno; + opus_int32 total_duration; + int durations[255]; + int cur_page_eos; + int op_count; + int pi; + if(_og==NULL)_og=&og; + serialno=_of->os.serialno; + op_count=0; + /*We shouldn't have to initialize total_duration, but gcc is too dumb to + figure out that op_count>0 implies we've been through the whole loop at + least once.*/ + total_duration=0; + do{ + page_offset=op_get_next_page(_of,_og,_of->end); + /*We should get a page unless the file is truncated or mangled. + Otherwise there are no audio data packets in the whole logical stream.*/ + if(OP_UNLIKELY(page_offset<0)){ + /*Fail if there was a read error.*/ + if(page_offset<OP_FALSE)return (int)page_offset; + /*Fail if the pre-skip is non-zero, since it's asking us to skip more + samples than exist.*/ + if(_link->head.pre_skip>0)return OP_EBADTIMESTAMP; + /*Set pcm_end and end_offset so we can skip the call to + op_find_final_pcm_offset().*/ + _link->pcm_start=_link->pcm_end=0; + _link->end_offset=_link->data_offset; + return 0; + } + /*Similarly, if we hit the next link in the chain, we've gone too far.*/ + if(OP_UNLIKELY(ogg_page_bos(_og))){ + if(_link->head.pre_skip>0)return OP_EBADTIMESTAMP; + /*Set pcm_end and end_offset so we can skip the call to + op_find_final_pcm_offset().*/ + _link->pcm_end=_link->pcm_start=0; + _link->end_offset=_link->data_offset; + /*Tell the caller we've got a buffered page for them.*/ + return 1; + } + /*Ignore pages from other streams (not strictly necessary, because of the + checks in ogg_stream_pagein(), but saves some work).*/ + if(serialno!=(ogg_uint32_t)ogg_page_serialno(_og))continue; + ogg_stream_pagein(&_of->os,_og); + /*Bitrate tracking: add the header's bytes here. + The body bytes are counted when we consume the packets.*/ + _of->bytes_tracked+=_og->header_len; + /*Count the durations of all packets in the page.*/ + do total_duration=op_collect_audio_packets(_of,durations); + /*Ignore holes.*/ + while(OP_UNLIKELY(total_duration<0)); + op_count=_of->op_count; + } + while(op_count<=0); + /*We found the first page with a completed audio data packet: actually look + at the granule position. + RFC 3533 says, "A special value of -1 (in two's complement) indicates that + no packets finish on this page," which does not say that a granule + position that is NOT -1 indicates that some packets DO finish on that page + (even though this was the intention, libogg itself violated this intention + for years before we fixed it). + The Ogg Opus specification only imposes its start-time requirements + on the granule position of the first page with completed packets, + so we ignore any set granule positions until then.*/ + cur_page_gp=_of->op[op_count-1].granulepos; + /*But getting a packet without a valid granule position on the page is not + okay.*/ + if(cur_page_gp==-1)return OP_EBADTIMESTAMP; + cur_page_eos=_of->op[op_count-1].e_o_s; + if(OP_LIKELY(!cur_page_eos)){ + /*The EOS flag wasn't set. + Work backwards from the provided granule position to get the starting PCM + offset.*/ + if(OP_UNLIKELY(op_granpos_add(&pcm_start,cur_page_gp,-total_duration)<0)){ + /*The starting granule position MUST not be smaller than the amount of + audio on the first page with completed packets.*/ + return OP_EBADTIMESTAMP; + } + } + else{ + /*The first page with completed packets was also the last.*/ + if(OP_LIKELY(op_granpos_add(&pcm_start,cur_page_gp,-total_duration)<0)){ + /*If there's less audio on the page than indicated by the granule + position, then we're doing end-trimming, and the starting PCM offset + is zero by spec mandate.*/ + pcm_start=0; + /*However, the end-trimming MUST not ask us to trim more samples than + exist after applying the pre-skip.*/ + if(OP_UNLIKELY(op_granpos_cmp(cur_page_gp,_link->head.pre_skip)<0)){ + return OP_EBADTIMESTAMP; + } + } + } + /*Timestamp the individual packets.*/ + prev_packet_gp=pcm_start; + for(pi=0;pi<op_count;pi++){ + if(cur_page_eos){ + ogg_int64_t diff; + OP_ALWAYS_TRUE(!op_granpos_diff(&diff,cur_page_gp,prev_packet_gp)); + diff=durations[pi]-diff; + /*If we have samples to trim...*/ + if(diff>0){ + /*If we trimmed the entire packet, stop (the spec says encoders + shouldn't do this, but we support it anyway).*/ + if(OP_UNLIKELY(diff>durations[pi]))break; + _of->op[pi].granulepos=prev_packet_gp=cur_page_gp; + /*Move the EOS flag to this packet, if necessary, so we'll trim the + samples.*/ + _of->op[pi].e_o_s=1; + continue; + } + } + /*Update the granule position as normal.*/ + OP_ALWAYS_TRUE(!op_granpos_add(&_of->op[pi].granulepos, + prev_packet_gp,durations[pi])); + prev_packet_gp=_of->op[pi].granulepos; + } + /*Update the packet count after end-trimming.*/ + _of->op_count=pi; + _of->cur_discard_count=_link->head.pre_skip; + _of->prev_packet_gp=_link->pcm_start=pcm_start; + _of->prev_page_offset=page_offset; + return 0; +} + +/*Starting from current cursor position, get the final PCM offset of the + previous page. + This also validates the duration of the link, which, while not strictly + required by the spec, we need to ensure duration calculations don't + overflow. + This is only done for seekable sources. + We must validate that op_find_initial_pcm_offset() succeeded for this link + before calling this function, otherwise it will scan the entire stream + backwards until it reaches the start, and then fail.*/ +static int op_find_final_pcm_offset(OggOpusFile *_of, + const ogg_uint32_t *_serialnos,int _nserialnos,OggOpusLink *_link, + opus_int64 _offset,ogg_uint32_t _end_serialno,ogg_int64_t _end_gp, + ogg_int64_t *_total_duration){ + ogg_int64_t total_duration; + ogg_int64_t duration; + ogg_uint32_t cur_serialno; + /*For the time being, fetch end PCM offset the simple way.*/ + cur_serialno=_link->serialno; + if(_end_serialno!=cur_serialno||_end_gp==-1){ + _offset=op_get_last_page(_of,&_end_gp,_offset, + cur_serialno,_serialnos,_nserialnos); + if(OP_UNLIKELY(_offset<0))return (int)_offset; + } + /*At worst we should have found the first page with completed packets.*/ + if(OP_UNLIKELY(_offset<_link->data_offset))return OP_EBADLINK; + /*This implementation requires that the difference between the first and last + granule positions in each link be representable in a signed, 64-bit + number, and that each link also have at least as many samples as the + pre-skip requires.*/ + if(OP_UNLIKELY(op_granpos_diff(&duration,_end_gp,_link->pcm_start)<0) + ||OP_UNLIKELY(duration<_link->head.pre_skip)){ + return OP_EBADTIMESTAMP; + } + /*We also require that the total duration be representable in a signed, + 64-bit number.*/ + duration-=_link->head.pre_skip; + total_duration=*_total_duration; + if(OP_UNLIKELY(OP_INT64_MAX-duration<total_duration))return OP_EBADTIMESTAMP; + *_total_duration=total_duration+duration; + _link->pcm_end=_end_gp; + _link->end_offset=_offset; + return 0; +} + +/*Rescale the number _x from the range [0,_from] to [0,_to]. + _from and _to must be positive.*/ +static opus_int64 op_rescale64(opus_int64 _x,opus_int64 _from,opus_int64 _to){ + opus_int64 frac; + opus_int64 ret; + int i; + if(_x>=_from)return _to; + if(_x<=0)return 0; + frac=0; + for(i=0;i<63;i++){ + frac<<=1; + OP_ASSERT(_x<=_from); + if(_x>=_from>>1){ + _x-=_from-_x; + frac|=1; + } + else _x<<=1; + } + ret=0; + for(i=0;i<63;i++){ + if(frac&1)ret=(ret&_to&1)+(ret>>1)+(_to>>1); + else ret>>=1; + frac>>=1; + } + return ret; +} + +/*The minimum granule position spacing allowed for making predictions. + This corresponds to about 1 second of audio at 48 kHz for both Opus and + Vorbis, or one keyframe interval in Theora with the default keyframe spacing + of 256.*/ +#define OP_GP_SPACING_MIN (48000) + +/*Try to estimate the location of the next link using the current seek + records, assuming the initial granule position of any streams we've found is + 0.*/ +static opus_int64 op_predict_link_start(const OpusSeekRecord *_sr,int _nsr, + opus_int64 _searched,opus_int64 _end_searched,opus_int32 _bias){ + opus_int64 bisect; + int sri; + int srj; + /*Require that we be at least OP_CHUNK_SIZE from the end. + We don't require that we be at least OP_CHUNK_SIZE from the beginning, + because if we are we'll just scan forward without seeking.*/ + _end_searched-=OP_CHUNK_SIZE; + if(_searched>=_end_searched)return -1; + bisect=_end_searched; + for(sri=0;sri<_nsr;sri++){ + ogg_int64_t gp1; + ogg_int64_t gp2_min; + ogg_uint32_t serialno1; + opus_int64 offset1; + /*If the granule position is negative, either it's invalid or we'd cause + overflow.*/ + gp1=_sr[sri].gp; + if(gp1<0)continue; + /*We require some minimum distance between granule positions to make an + estimate. + We don't actually know what granule position scheme is being used, + because we have no idea what kind of stream these came from. + Therefore we require a minimum spacing between them, with the + expectation that while bitrates and granule position increments might + vary locally in quite complex ways, they are globally smooth.*/ + if(OP_UNLIKELY(op_granpos_add(&gp2_min,gp1,OP_GP_SPACING_MIN)<0)){ + /*No granule position would satisfy us.*/ + continue; + } + offset1=_sr[sri].offset; + serialno1=_sr[sri].serialno; + for(srj=sri;srj-->0;){ + ogg_int64_t gp2; + opus_int64 offset2; + opus_int64 num; + ogg_int64_t den; + ogg_int64_t ipart; + gp2=_sr[srj].gp; + if(gp2<gp2_min)continue; + /*Oh, and also make sure these came from the same stream.*/ + if(_sr[srj].serialno!=serialno1)continue; + offset2=_sr[srj].offset; + /*For once, we can subtract with impunity.*/ + den=gp2-gp1; + ipart=gp2/den; + num=offset2-offset1; + OP_ASSERT(num>0); + if(ipart>0&&(offset2-_searched)/ipart<num)continue; + offset2-=ipart*num; + gp2-=ipart*den; + offset2-=op_rescale64(gp2,den,num)-_bias; + if(offset2<_searched)continue; + bisect=OP_MIN(bisect,offset2); + break; + } + } + return bisect>=_end_searched?-1:bisect; +} + +/*Finds each bitstream link, one at a time, using a bisection search. + This has to begin by knowing the offset of the first link's initial page.*/ +static int op_bisect_forward_serialno(OggOpusFile *_of, + opus_int64 _searched,OpusSeekRecord *_sr,int _csr, + ogg_uint32_t **_serialnos,int *_nserialnos,int *_cserialnos){ + ogg_page og; + OggOpusLink *links; + int nlinks; + int clinks; + ogg_uint32_t *serialnos; + int nserialnos; + ogg_int64_t total_duration; + int nsr; + int ret; + links=_of->links; + nlinks=clinks=_of->nlinks; + total_duration=0; + /*We start with one seek record, for the last page in the file. + We build up a list of records for places we seek to during link + enumeration. + This list is kept sorted in reverse order. + We only care about seek locations that were _not_ in the current link, + therefore we can add them one at a time to the end of the list as we + improve the lower bound on the location where the next link starts.*/ + nsr=1; + for(;;){ + opus_int64 end_searched; + opus_int64 bisect; + opus_int64 next; + opus_int64 last; + ogg_int64_t end_offset; + ogg_int64_t end_gp; + int sri; + serialnos=*_serialnos; + nserialnos=*_nserialnos; + if(OP_UNLIKELY(nlinks>=clinks)){ + if(OP_UNLIKELY(clinks>INT_MAX-1>>1))return OP_EFAULT; + clinks=2*clinks+1; + OP_ASSERT(nlinks<clinks); + links=(OggOpusLink *)_ogg_realloc(links,sizeof(*links)*clinks); + if(OP_UNLIKELY(links==NULL))return OP_EFAULT; + _of->links=links; + } + /*Invariants: + We have the headers and serial numbers for the link beginning at 'begin'. + We have the offset and granule position of the last page in the file + (potentially not a page we care about).*/ + /*Scan the seek records we already have to save us some bisection.*/ + for(sri=0;sri<nsr;sri++){ + if(op_lookup_serialno(_sr[sri].serialno,serialnos,nserialnos))break; + } + /*Is the last page in our current list of serial numbers?*/ + if(sri<=0)break; + /*Last page wasn't found. + We have at least one more link.*/ + last=-1; + end_searched=_sr[sri-1].search_start; + next=_sr[sri-1].offset; + end_gp=-1; + if(sri<nsr){ + _searched=_sr[sri].offset+_sr[sri].size; + if(_sr[sri].serialno==links[nlinks-1].serialno){ + end_gp=_sr[sri].gp; + end_offset=_sr[sri].offset; + } + } + nsr=sri; + bisect=-1; + /*If we've already found the end of at least one link, try to pick the + first bisection point at twice the average link size. + This is a good choice for files with lots of links that are all about the + same size.*/ + if(nlinks>1){ + opus_int64 last_offset; + opus_int64 avg_link_size; + opus_int64 upper_limit; + last_offset=links[nlinks-1].offset; + avg_link_size=last_offset/(nlinks-1); + upper_limit=end_searched-OP_CHUNK_SIZE-avg_link_size; + if(OP_LIKELY(last_offset>_searched-avg_link_size) + &&OP_LIKELY(last_offset<upper_limit)){ + bisect=last_offset+avg_link_size; + if(OP_LIKELY(bisect<upper_limit))bisect+=avg_link_size; + } + } + /*We guard against garbage separating the last and first pages of two + links below.*/ + while(_searched<end_searched){ + opus_int32 next_bias; + /*If we don't have a better estimate, use simple bisection.*/ + if(bisect==-1)bisect=_searched+(end_searched-_searched>>1); + /*If we're within OP_CHUNK_SIZE of the start, scan forward.*/ + if(bisect-_searched<OP_CHUNK_SIZE)bisect=_searched; + /*Otherwise we're skipping data. + Forget the end page, if we saw one, as we might miss a later one.*/ + else end_gp=-1; + ret=op_seek_helper(_of,bisect); + if(OP_UNLIKELY(ret<0))return ret; + last=op_get_next_page(_of,&og,_sr[nsr-1].offset); + if(OP_UNLIKELY(last<OP_FALSE))return (int)last; + next_bias=0; + if(last==OP_FALSE)end_searched=bisect; + else{ + ogg_uint32_t serialno; + ogg_int64_t gp; + serialno=ogg_page_serialno(&og); + gp=ogg_page_granulepos(&og); + if(!op_lookup_serialno(serialno,serialnos,nserialnos)){ + end_searched=bisect; + next=last; + /*In reality we should always have enough room, but be paranoid.*/ + if(OP_LIKELY(nsr<_csr)){ + _sr[nsr].search_start=bisect; + _sr[nsr].offset=last; + OP_ASSERT(_of->offset-last>=0); + OP_ASSERT(_of->offset-last<=OP_PAGE_SIZE_MAX); + _sr[nsr].size=(opus_int32)(_of->offset-last); + _sr[nsr].serialno=serialno; + _sr[nsr].gp=gp; + nsr++; + } + } + else{ + _searched=_of->offset; + next_bias=OP_CHUNK_SIZE; + if(serialno==links[nlinks-1].serialno){ + /*This page was from the stream we want, remember it. + If it's the last such page in the link, we won't have to go back + looking for it later.*/ + end_gp=gp; + end_offset=last; + } + } + } + bisect=op_predict_link_start(_sr,nsr,_searched,end_searched,next_bias); + } + /*Bisection point found. + Get the final granule position of the previous link, assuming + op_find_initial_pcm_offset() didn't already determine the link was + empty.*/ + if(OP_LIKELY(links[nlinks-1].pcm_end==-1)){ + if(end_gp==-1){ + /*If we don't know where the end page is, we'll have to seek back and + look for it, starting from the end of the link.*/ + end_offset=next; + /*Also forget the last page we read. + It won't be available after the seek.*/ + last=-1; + } + ret=op_find_final_pcm_offset(_of,serialnos,nserialnos, + links+nlinks-1,end_offset,links[nlinks-1].serialno,end_gp, + &total_duration); + if(OP_UNLIKELY(ret<0))return ret; + } + if(last!=next){ + /*The last page we read was not the first page the next link. + Move the cursor position to the offset of that first page. + This only performs an actual seek if the first page of the next link + does not start at the end of the last page from the current Opus + stream with a valid granule position.*/ + ret=op_seek_helper(_of,next); + if(OP_UNLIKELY(ret<0))return ret; + } + ret=op_fetch_headers(_of,&links[nlinks].head,&links[nlinks].tags, + _serialnos,_nserialnos,_cserialnos,last!=next?NULL:&og); + if(OP_UNLIKELY(ret<0))return ret; + links[nlinks].offset=next; + links[nlinks].data_offset=_of->offset; + links[nlinks].serialno=_of->os.serialno; + links[nlinks].pcm_end=-1; + /*This might consume a page from the next link, however the next bisection + always starts with a seek.*/ + ret=op_find_initial_pcm_offset(_of,links+nlinks,NULL); + if(OP_UNLIKELY(ret<0))return ret; + _searched=_of->offset; + /*Mark the current link count so it can be cleaned up on error.*/ + _of->nlinks=++nlinks; + } + /*Last page is in the starting serialno list, so we've reached the last link. + Now find the last granule position for it (if we didn't the first time we + looked at the end of the stream, and if op_find_initial_pcm_offset() + didn't already determine the link was empty).*/ + if(OP_LIKELY(links[nlinks-1].pcm_end==-1)){ + ret=op_find_final_pcm_offset(_of,serialnos,nserialnos, + links+nlinks-1,_sr[0].offset,_sr[0].serialno,_sr[0].gp,&total_duration); + if(OP_UNLIKELY(ret<0))return ret; + } + /*Trim back the links array if necessary.*/ + links=(OggOpusLink *)_ogg_realloc(links,sizeof(*links)*nlinks); + if(OP_LIKELY(links!=NULL))_of->links=links; + /*We also don't need these anymore.*/ + _ogg_free(*_serialnos); + *_serialnos=NULL; + *_cserialnos=*_nserialnos=0; + return 0; +} + +static void op_update_gain(OggOpusFile *_of){ + OpusHead *head; + opus_int32 gain_q8; + int li; + /*If decode isn't ready, then we'll apply the gain when we initialize the + decoder.*/ + if(_of->ready_state<OP_INITSET)return; + gain_q8=_of->gain_offset_q8; + li=_of->seekable?_of->cur_link:0; + head=&_of->links[li].head; + /*We don't have to worry about overflow here because the header gain and + track gain must lie in the range [-32768,32767], and the user-supplied + offset has been pre-clamped to [-98302,98303].*/ + switch(_of->gain_type){ + case OP_ALBUM_GAIN:{ + int album_gain_q8; + album_gain_q8=0; + opus_tags_get_album_gain(&_of->links[li].tags,&album_gain_q8); + gain_q8+=album_gain_q8; + gain_q8+=head->output_gain; + }break; + case OP_TRACK_GAIN:{ + int track_gain_q8; + track_gain_q8=0; + opus_tags_get_track_gain(&_of->links[li].tags,&track_gain_q8); + gain_q8+=track_gain_q8; + gain_q8+=head->output_gain; + }break; + case OP_HEADER_GAIN:gain_q8+=head->output_gain;break; + case OP_ABSOLUTE_GAIN:break; + default:OP_ASSERT(0); + } + gain_q8=OP_CLAMP(-32768,gain_q8,32767); + OP_ASSERT(_of->od!=NULL); +#if defined(OPUS_SET_GAIN) + opus_multistream_decoder_ctl(_of->od,OPUS_SET_GAIN(gain_q8)); +#else +/*A fallback that works with both float and fixed-point is a bunch of work, + so just force people to use a sufficiently new version. + This is deployed well enough at this point that this shouldn't be a burden.*/ +# error "libopus 1.0.1 or later required" +#endif +} + +static int op_make_decode_ready(OggOpusFile *_of){ + const OpusHead *head; + int li; + int stream_count; + int coupled_count; + int channel_count; + if(_of->ready_state>OP_STREAMSET)return 0; + if(OP_UNLIKELY(_of->ready_state<OP_STREAMSET))return OP_EFAULT; + li=_of->seekable?_of->cur_link:0; + head=&_of->links[li].head; + stream_count=head->stream_count; + coupled_count=head->coupled_count; + channel_count=head->channel_count; + /*Check to see if the current decoder is compatible with the current link.*/ + if(_of->od!=NULL&&_of->od_stream_count==stream_count + &&_of->od_coupled_count==coupled_count&&_of->od_channel_count==channel_count + &&memcmp(_of->od_mapping,head->mapping, + sizeof(*head->mapping)*channel_count)==0){ + opus_multistream_decoder_ctl(_of->od,OPUS_RESET_STATE); + } + else{ + int err; + opus_multistream_decoder_destroy(_of->od); + _of->od=opus_multistream_decoder_create(48000,channel_count, + stream_count,coupled_count,head->mapping,&err); + if(_of->od==NULL)return OP_EFAULT; + _of->od_stream_count=stream_count; + _of->od_coupled_count=coupled_count; + _of->od_channel_count=channel_count; + memcpy(_of->od_mapping,head->mapping,sizeof(*head->mapping)*channel_count); + } + _of->ready_state=OP_INITSET; + _of->bytes_tracked=0; + _of->samples_tracked=0; +#if !defined(OP_FIXED_POINT) + _of->state_channel_count=0; + /*Use the serial number for the PRNG seed to get repeatable output for + straight play-throughs.*/ + _of->dither_seed=_of->links[li].serialno; +#endif + op_update_gain(_of); + return 0; +} + +static int op_open_seekable2_impl(OggOpusFile *_of){ + /*64 seek records should be enough for anybody. + Actually, with a bisection search in a 63-bit range down to OP_CHUNK_SIZE + granularity, much more than enough.*/ + OpusSeekRecord sr[64]; + opus_int64 data_offset; + int ret; + /*We can seek, so set out learning all about this file.*/ + (*_of->callbacks.seek)(_of->source,0,SEEK_END); + _of->offset=_of->end=(*_of->callbacks.tell)(_of->source); + if(OP_UNLIKELY(_of->end<0))return OP_EREAD; + data_offset=_of->links[0].data_offset; + if(OP_UNLIKELY(_of->end<data_offset))return OP_EBADLINK; + /*Get the offset of the last page of the physical bitstream, or, if we're + lucky, the last Opus page of the first link, as most Ogg Opus files will + contain a single logical bitstream.*/ + ret=op_get_prev_page_serial(_of,sr,_of->end, + _of->links[0].serialno,_of->serialnos,_of->nserialnos); + if(OP_UNLIKELY(ret<0))return ret; + /*If there's any trailing junk, forget about it.*/ + _of->end=sr[0].offset+sr[0].size; + if(OP_UNLIKELY(_of->end<data_offset))return OP_EBADLINK; + /*Now enumerate the bitstream structure.*/ + return op_bisect_forward_serialno(_of,data_offset,sr,sizeof(sr)/sizeof(*sr), + &_of->serialnos,&_of->nserialnos,&_of->cserialnos); +} + +static int op_open_seekable2(OggOpusFile *_of){ + ogg_sync_state oy_start; + ogg_stream_state os_start; + ogg_packet *op_start; + opus_int64 prev_page_offset; + opus_int64 start_offset; + int start_op_count; + int ret; + /*We're partially open and have a first link header state in storage in _of. + Save off that stream state so we can come back to it. + It would be simpler to just dump all this state and seek back to + links[0].data_offset when we're done. + But we do the extra work to allow us to seek back to _exactly_ the same + stream position we're at now. + This allows, e.g., the HTTP backend to continue reading from the original + connection (if it's still available), instead of opening a new one. + This means we can open and start playing a normal Opus file with a single + link and reasonable packet sizes using only two HTTP requests.*/ + start_op_count=_of->op_count; + /*This is a bit too large to put on the stack unconditionally.*/ + op_start=(ogg_packet *)_ogg_malloc(sizeof(*op_start)*start_op_count); + if(op_start==NULL)return OP_EFAULT; + *&oy_start=_of->oy; + *&os_start=_of->os; + prev_page_offset=_of->prev_page_offset; + start_offset=_of->offset; + memcpy(op_start,_of->op,sizeof(*op_start)*start_op_count); + OP_ASSERT((*_of->callbacks.tell)(_of->source)==op_position(_of)); + ogg_sync_init(&_of->oy); + ogg_stream_init(&_of->os,-1); + ret=op_open_seekable2_impl(_of); + /*Restore the old stream state.*/ + ogg_stream_clear(&_of->os); + ogg_sync_clear(&_of->oy); + *&_of->oy=*&oy_start; + *&_of->os=*&os_start; + _of->offset=start_offset; + _of->op_count=start_op_count; + memcpy(_of->op,op_start,sizeof(*_of->op)*start_op_count); + _ogg_free(op_start); + _of->prev_packet_gp=_of->links[0].pcm_start; + _of->prev_page_offset=prev_page_offset; + _of->cur_discard_count=_of->links[0].head.pre_skip; + if(OP_UNLIKELY(ret<0))return ret; + /*And restore the position indicator.*/ + ret=(*_of->callbacks.seek)(_of->source,op_position(_of),SEEK_SET); + return OP_UNLIKELY(ret<0)?OP_EREAD:0; +} + +/*Clear out the current logical bitstream decoder.*/ +static void op_decode_clear(OggOpusFile *_of){ + /*We don't actually free the decoder. + We might be able to re-use it for the next link.*/ + _of->op_count=0; + _of->od_buffer_size=0; + _of->prev_packet_gp=-1; + _of->prev_page_offset=-1; + if(!_of->seekable){ + OP_ASSERT(_of->ready_state>=OP_INITSET); + opus_tags_clear(&_of->links[0].tags); + } + _of->ready_state=OP_OPENED; +} + +static void op_clear(OggOpusFile *_of){ + OggOpusLink *links; + _ogg_free(_of->od_buffer); + if(_of->od!=NULL)opus_multistream_decoder_destroy(_of->od); + links=_of->links; + if(!_of->seekable){ + if(_of->ready_state>OP_OPENED||_of->ready_state==OP_PARTOPEN){ + opus_tags_clear(&links[0].tags); + } + } + else if(OP_LIKELY(links!=NULL)){ + int nlinks; + int link; + nlinks=_of->nlinks; + for(link=0;link<nlinks;link++)opus_tags_clear(&links[link].tags); + } + _ogg_free(links); + _ogg_free(_of->serialnos); + ogg_stream_clear(&_of->os); + ogg_sync_clear(&_of->oy); + if(_of->callbacks.close!=NULL)(*_of->callbacks.close)(_of->source); +} + +static int op_open1(OggOpusFile *_of, + void *_source,const OpusFileCallbacks *_cb, + const unsigned char *_initial_data,size_t _initial_bytes){ + ogg_page og; + ogg_page *pog; + int seekable; + int ret; + memset(_of,0,sizeof(*_of)); + _of->end=-1; + _of->source=_source; + *&_of->callbacks=*_cb; + /*At a minimum, we need to be able to read data.*/ + if(OP_UNLIKELY(_of->callbacks.read==NULL))return OP_EREAD; + /*Initialize the framing state.*/ + ogg_sync_init(&_of->oy); + /*Perhaps some data was previously read into a buffer for testing against + other stream types. + Allow initialization from this previously read data (especially as we may + be reading from a non-seekable stream). + This requires copying it into a buffer allocated by ogg_sync_buffer() and + doesn't support seeking, so this is not a good mechanism to use for + decoding entire files from RAM.*/ + if(_initial_bytes>0){ + char *buffer; + buffer=ogg_sync_buffer(&_of->oy,_initial_bytes); + memcpy(buffer,_initial_data,_initial_bytes*sizeof(*buffer)); + ogg_sync_wrote(&_of->oy,_initial_bytes); + } + /*Can we seek? + Stevens suggests the seek test is portable.*/ + seekable=_cb->seek!=NULL&&(*_cb->seek)(_source,0,SEEK_CUR)!=-1; + /*If seek is implemented, tell must also be implemented.*/ + if(seekable){ + opus_int64 pos; + if(OP_UNLIKELY(_of->callbacks.tell==NULL))return OP_EINVAL; + pos=(*_of->callbacks.tell)(_of->source); + /*If the current position is not equal to the initial bytes consumed, + absolute seeking will not work.*/ + if(OP_UNLIKELY(pos!=(opus_int64)_initial_bytes))return OP_EINVAL; + } + _of->seekable=seekable; + /*Don't seek yet. + Set up a 'single' (current) logical bitstream entry for partial open.*/ + _of->links=(OggOpusLink *)_ogg_malloc(sizeof(*_of->links)); + /*The serialno gets filled in later by op_fetch_headers().*/ + ogg_stream_init(&_of->os,-1); + pog=NULL; + for(;;){ + /*Fetch all BOS pages, store the Opus header and all seen serial numbers, + and load subsequent Opus setup headers.*/ + ret=op_fetch_headers(_of,&_of->links[0].head,&_of->links[0].tags, + &_of->serialnos,&_of->nserialnos,&_of->cserialnos,pog); + if(OP_UNLIKELY(ret<0))break; + _of->nlinks=1; + _of->links[0].offset=0; + _of->links[0].data_offset=_of->offset; + _of->links[0].pcm_end=-1; + _of->links[0].serialno=_of->os.serialno; + /*Fetch the initial PCM offset.*/ + ret=op_find_initial_pcm_offset(_of,_of->links,&og); + if(seekable||OP_LIKELY(ret<=0))break; + /*This link was empty, but we already have the BOS page for the next one in + og. + We can't seek, so start processing the next link right now.*/ + opus_tags_clear(&_of->links[0].tags); + _of->nlinks=0; + if(!seekable)_of->cur_link++; + pog=&og; + } + if(OP_LIKELY(ret>=0))_of->ready_state=OP_PARTOPEN; + return ret; +} + +static int op_open2(OggOpusFile *_of){ + int ret; + OP_ASSERT(_of->ready_state==OP_PARTOPEN); + if(_of->seekable){ + _of->ready_state=OP_OPENED; + ret=op_open_seekable2(_of); + } + else ret=0; + if(OP_LIKELY(ret>=0)){ + /*We have buffered packets from op_find_initial_pcm_offset(). + Move to OP_INITSET so we can use them.*/ + _of->ready_state=OP_STREAMSET; + ret=op_make_decode_ready(_of); + if(OP_LIKELY(ret>=0))return 0; + } + /*Don't auto-close the stream on failure.*/ + _of->callbacks.close=NULL; + op_clear(_of); + return ret; +} + +OggOpusFile *op_test_callbacks(void *_source,const OpusFileCallbacks *_cb, + const unsigned char *_initial_data,size_t _initial_bytes,int *_error){ + OggOpusFile *of; + int ret; + of=(OggOpusFile *)_ogg_malloc(sizeof(*of)); + ret=OP_EFAULT; + if(OP_LIKELY(of!=NULL)){ + ret=op_open1(of,_source,_cb,_initial_data,_initial_bytes); + if(OP_LIKELY(ret>=0)){ + if(_error!=NULL)*_error=0; + return of; + } + /*Don't auto-close the stream on failure.*/ + of->callbacks.close=NULL; + op_clear(of); + _ogg_free(of); + } + if(_error!=NULL)*_error=ret; + return NULL; +} + +OggOpusFile *op_open_callbacks(void *_source,const OpusFileCallbacks *_cb, + const unsigned char *_initial_data,size_t _initial_bytes,int *_error){ + OggOpusFile *of; + of=op_test_callbacks(_source,_cb,_initial_data,_initial_bytes,_error); + if(OP_LIKELY(of!=NULL)){ + int ret; + ret=op_open2(of); + if(OP_LIKELY(ret>=0))return of; + if(_error!=NULL)*_error=ret; + _ogg_free(of); + } + return NULL; +} + +/*Convenience routine to clean up from failure for the open functions that + create their own streams.*/ +static OggOpusFile *op_open_close_on_failure(void *_source, + const OpusFileCallbacks *_cb,int *_error){ + OggOpusFile *of; + if(OP_UNLIKELY(_source==NULL)){ + if(_error!=NULL)*_error=OP_EFAULT; + return NULL; + } + of=op_open_callbacks(_source,_cb,NULL,0,_error); + if(OP_UNLIKELY(of==NULL))(*_cb->close)(_source); + return of; +} + +OggOpusFile *op_open_file(const char *_path,int *_error){ + OpusFileCallbacks cb; + return op_open_close_on_failure(op_fopen(&cb,_path,"rb"),&cb,_error); +} + +OggOpusFile *op_open_memory(const unsigned char *_data,size_t _size, + int *_error){ + OpusFileCallbacks cb; + return op_open_close_on_failure(op_mem_stream_create(&cb,_data,_size),&cb, + _error); +} + +/*Convenience routine to clean up from failure for the open functions that + create their own streams.*/ +static OggOpusFile *op_test_close_on_failure(void *_source, + const OpusFileCallbacks *_cb,int *_error){ + OggOpusFile *of; + if(OP_UNLIKELY(_source==NULL)){ + if(_error!=NULL)*_error=OP_EFAULT; + return NULL; + } + of=op_test_callbacks(_source,_cb,NULL,0,_error); + if(OP_UNLIKELY(of==NULL))(*_cb->close)(_source); + return of; +} + +OggOpusFile *op_test_file(const char *_path,int *_error){ + OpusFileCallbacks cb; + return op_test_close_on_failure(op_fopen(&cb,_path,"rb"),&cb,_error); +} + +OggOpusFile *op_test_memory(const unsigned char *_data,size_t _size, + int *_error){ + OpusFileCallbacks cb; + return op_test_close_on_failure(op_mem_stream_create(&cb,_data,_size),&cb, + _error); +} + +int op_test_open(OggOpusFile *_of){ + int ret; + if(OP_UNLIKELY(_of->ready_state!=OP_PARTOPEN))return OP_EINVAL; + ret=op_open2(_of); + /*op_open2() will clear this structure on failure. + Reset its contents to prevent double-frees in op_free().*/ + if(OP_UNLIKELY(ret<0))memset(_of,0,sizeof(*_of)); + return ret; +} + +void op_free(OggOpusFile *_of){ + if(OP_LIKELY(_of!=NULL)){ + op_clear(_of); + _ogg_free(_of); + } +} + +int op_seekable(const OggOpusFile *_of){ + return _of->seekable; +} + +int op_link_count(const OggOpusFile *_of){ + return _of->nlinks; +} + +ogg_uint32_t op_serialno(const OggOpusFile *_of,int _li){ + if(OP_UNLIKELY(_li>=_of->nlinks))_li=_of->nlinks-1; + if(!_of->seekable)_li=0; + return _of->links[_li<0?_of->cur_link:_li].serialno; +} + +int op_channel_count(const OggOpusFile *_of,int _li){ + return op_head(_of,_li)->channel_count; +} + +opus_int64 op_raw_total(const OggOpusFile *_of,int _li){ + if(OP_UNLIKELY(_of->ready_state<OP_OPENED) + ||OP_UNLIKELY(!_of->seekable) + ||OP_UNLIKELY(_li>=_of->nlinks)){ + return OP_EINVAL; + } + if(_li<0)return _of->end-_of->links[0].offset; + return (_li+1>=_of->nlinks?_of->end:_of->links[_li+1].offset) + -_of->links[_li].offset; +} + +ogg_int64_t op_pcm_total(const OggOpusFile *_of,int _li){ + OggOpusLink *links; + ogg_int64_t diff; + int nlinks; + nlinks=_of->nlinks; + if(OP_UNLIKELY(_of->ready_state<OP_OPENED) + ||OP_UNLIKELY(!_of->seekable) + ||OP_UNLIKELY(_li>=nlinks)){ + return OP_EINVAL; + } + links=_of->links; + /*We verify that the granule position differences are larger than the + pre-skip and that the total duration does not overflow during link + enumeration, so we don't have to check here.*/ + if(_li<0){ + ogg_int64_t pcm_total; + int li; + pcm_total=0; + for(li=0;li<nlinks;li++){ + OP_ALWAYS_TRUE(!op_granpos_diff(&diff, + links[li].pcm_end,links[li].pcm_start)); + pcm_total+=diff-links[li].head.pre_skip; + } + return pcm_total; + } + OP_ALWAYS_TRUE(!op_granpos_diff(&diff, + links[_li].pcm_end,links[_li].pcm_start)); + return diff-links[_li].head.pre_skip; +} + +const OpusHead *op_head(const OggOpusFile *_of,int _li){ + if(OP_UNLIKELY(_li>=_of->nlinks))_li=_of->nlinks-1; + if(!_of->seekable)_li=0; + return &_of->links[_li<0?_of->cur_link:_li].head; +} + +const OpusTags *op_tags(const OggOpusFile *_of,int _li){ + if(OP_UNLIKELY(_li>=_of->nlinks))_li=_of->nlinks-1; + if(!_of->seekable){ + if(_of->ready_state<OP_STREAMSET&&_of->ready_state!=OP_PARTOPEN){ + return NULL; + } + _li=0; + } + else if(_li<0)_li=_of->ready_state>=OP_STREAMSET?_of->cur_link:0; + return &_of->links[_li].tags; +} + +int op_current_link(const OggOpusFile *_of){ + if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL; + return _of->cur_link; +} + +/*Compute an average bitrate given a byte and sample count. + Return: The bitrate in bits per second.*/ +static opus_int32 op_calc_bitrate(opus_int64 _bytes,ogg_int64_t _samples){ + /*These rates are absurd, but let's handle them anyway.*/ + if(OP_UNLIKELY(_bytes>(OP_INT64_MAX-(_samples>>1))/(48000*8))){ + ogg_int64_t den; + if(OP_UNLIKELY(_bytes/(OP_INT32_MAX/(48000*8))>=_samples)){ + return OP_INT32_MAX; + } + den=_samples/(48000*8); + return (opus_int32)((_bytes+(den>>1))/den); + } + if(OP_UNLIKELY(_samples<=0))return OP_INT32_MAX; + /*This can't actually overflow in normal operation: even with a pre-skip of + 545 2.5 ms frames with 8 streams running at 1282*8+1 bytes per packet + (1275 byte frames + Opus framing overhead + Ogg lacing values), that all + produce a single sample of decoded output, we still don't top 45 Mbps. + The only way to get bitrates larger than that is with excessive Opus + padding, more encoded streams than output channels, or lots and lots of + Ogg pages with no packets on them.*/ + return (opus_int32)OP_MIN((_bytes*48000*8+(_samples>>1))/_samples, + OP_INT32_MAX); +} + +opus_int32 op_bitrate(const OggOpusFile *_of,int _li){ + if(OP_UNLIKELY(_of->ready_state<OP_OPENED)||OP_UNLIKELY(!_of->seekable) + ||OP_UNLIKELY(_li>=_of->nlinks)){ + return OP_EINVAL; + } + return op_calc_bitrate(op_raw_total(_of,_li),op_pcm_total(_of,_li)); +} + +opus_int32 op_bitrate_instant(OggOpusFile *_of){ + ogg_int64_t samples_tracked; + opus_int32 ret; + if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL; + samples_tracked=_of->samples_tracked; + if(OP_UNLIKELY(samples_tracked==0))return OP_FALSE; + ret=op_calc_bitrate(_of->bytes_tracked,samples_tracked); + _of->bytes_tracked=0; + _of->samples_tracked=0; + return ret; +} + +/*Fetch and process a page. + This handles the case where we're at a bitstream boundary and dumps the + decoding machine. + If the decoding machine is unloaded, it loads it. + It also keeps prev_packet_gp up to date (seek and read both use this; seek + uses a special hack with _readp). + Return: <0) Error, OP_HOLE (lost packet), or OP_EOF. + 0) Need more data (only if _readp==0). + 1) Got at least one audio data packet.*/ +static int op_fetch_and_process_page(OggOpusFile *_of, + ogg_page *_og,opus_int64 _page_offset, + int _readp,int _spanp,int _ignore_holes){ + OggOpusLink *links; + ogg_uint32_t cur_serialno; + int seekable; + int cur_link; + int ret; + /*We shouldn't get here if we have unprocessed packets.*/ + OP_ASSERT(_of->ready_state<OP_INITSET||_of->op_pos>=_of->op_count); + if(!_readp)return 0; + seekable=_of->seekable; + links=_of->links; + cur_link=seekable?_of->cur_link:0; + cur_serialno=links[cur_link].serialno; + /*Handle one page.*/ + for(;;){ + ogg_page og; + OP_ASSERT(_of->ready_state>=OP_OPENED); + /*This loop is not strictly necessary, but there's no sense in doing the + extra checks of the larger loop for the common case in a multiplexed + bistream where the page is simply part of a different logical + bitstream.*/ + do{ + /*If we were given a page to use, use it.*/ + if(_og!=NULL){ + *&og=*_og; + _og=NULL; + } + /*Keep reading until we get a page with the correct serialno.*/ + else _page_offset=op_get_next_page(_of,&og,_of->end); + /*EOF: Leave uninitialized.*/ + if(_page_offset<0)return _page_offset<OP_FALSE?(int)_page_offset:OP_EOF; + if(OP_LIKELY(_of->ready_state>=OP_STREAMSET)){ + if(cur_serialno!=(ogg_uint32_t)ogg_page_serialno(&og)){ + /*Two possibilities: + 1) Another stream is multiplexed into this logical section, or*/ + if(OP_LIKELY(!ogg_page_bos(&og)))continue; + /* 2) Our decoding just traversed a bitstream boundary.*/ + if(!_spanp)return OP_EOF; + if(OP_LIKELY(_of->ready_state>=OP_INITSET))op_decode_clear(_of); + break; + } + } + /*Bitrate tracking: add the header's bytes here. + The body bytes are counted when we consume the packets.*/ + _of->bytes_tracked+=og.header_len; + } + while(0); + /*Do we need to load a new machine before submitting the page? + This is different in the seekable and non-seekable cases. + In the seekable case, we already have all the header information loaded + and cached. + We just initialize the machine with it and continue on our merry way. + In the non-seekable (streaming) case, we'll only be at a boundary if we + just left the previous logical bitstream, and we're now nominally at the + header of the next bitstream.*/ + if(OP_UNLIKELY(_of->ready_state<OP_STREAMSET)){ + if(seekable){ + ogg_uint32_t serialno; + int nlinks; + int li; + serialno=ogg_page_serialno(&og); + /*Match the serialno to bitstream section. + We use this rather than offset positions to avoid problems near + logical bitstream boundaries.*/ + nlinks=_of->nlinks; + for(li=0;li<nlinks&&links[li].serialno!=serialno;li++); + /*Not a desired Opus bitstream section. + Keep trying.*/ + if(li>=nlinks)continue; + cur_serialno=serialno; + _of->cur_link=cur_link=li; + ogg_stream_reset_serialno(&_of->os,serialno); + _of->ready_state=OP_STREAMSET; + /*If we're at the start of this link, initialize the granule position + and pre-skip tracking.*/ + if(_page_offset<=links[cur_link].data_offset){ + _of->prev_packet_gp=links[cur_link].pcm_start; + _of->prev_page_offset=-1; + _of->cur_discard_count=links[cur_link].head.pre_skip; + /*Ignore a hole at the start of a new link (this is common for + streams joined in the middle) or after seeking.*/ + _ignore_holes=1; + } + } + else{ + do{ + /*We're streaming. + Fetch the two header packets, build the info struct.*/ + ret=op_fetch_headers(_of,&links[0].head,&links[0].tags, + NULL,NULL,NULL,&og); + if(OP_UNLIKELY(ret<0))return ret; + /*op_find_initial_pcm_offset() will suppress any initial hole for us, + so no need to set _ignore_holes.*/ + ret=op_find_initial_pcm_offset(_of,links,&og); + if(OP_UNLIKELY(ret<0))return ret; + _of->links[0].serialno=cur_serialno=_of->os.serialno; + _of->cur_link++; + } + /*If the link was empty, keep going, because we already have the + BOS page of the next one in og.*/ + while(OP_UNLIKELY(ret>0)); + /*If we didn't get any packets out of op_find_initial_pcm_offset(), + keep going (this is possible if end-trimming trimmed them all).*/ + if(_of->op_count<=0)continue; + /*Otherwise, we're done.*/ + ret=op_make_decode_ready(_of); + if(OP_UNLIKELY(ret<0))return ret; + return 1; + } + } + /*The buffered page is the data we want, and we're ready for it. + Add it to the stream state.*/ + if(OP_UNLIKELY(_of->ready_state==OP_STREAMSET)){ + ret=op_make_decode_ready(_of); + if(OP_UNLIKELY(ret<0))return ret; + } + /*Extract all the packets from the current page.*/ + ogg_stream_pagein(&_of->os,&og); + if(OP_LIKELY(_of->ready_state>=OP_INITSET)){ + opus_int32 total_duration; + int durations[255]; + int op_count; + total_duration=op_collect_audio_packets(_of,durations); + if(OP_UNLIKELY(total_duration<0)){ + /*Drain the packets from the page anyway.*/ + total_duration=op_collect_audio_packets(_of,durations); + OP_ASSERT(total_duration>=0); + /*Report holes to the caller.*/ + if(!_ignore_holes)return OP_HOLE; + } + op_count=_of->op_count; + /*If we found at least one audio data packet, compute per-packet granule + positions for them.*/ + if(op_count>0){ + ogg_int64_t diff; + ogg_int64_t prev_packet_gp; + ogg_int64_t cur_packet_gp; + ogg_int64_t cur_page_gp; + int cur_page_eos; + int pi; + cur_page_gp=_of->op[op_count-1].granulepos; + cur_page_eos=_of->op[op_count-1].e_o_s; + prev_packet_gp=_of->prev_packet_gp; + if(OP_UNLIKELY(prev_packet_gp==-1)){ + opus_int32 cur_discard_count; + /*This is the first call after a raw seek. + Try to reconstruct prev_packet_gp from scratch.*/ + OP_ASSERT(seekable); + if(OP_UNLIKELY(cur_page_eos)){ + /*If the first page we hit after our seek was the EOS page, and + we didn't start from data_offset or before, we don't have + enough information to do end-trimming. + Proceed to the next link, rather than risk playing back some + samples that shouldn't have been played.*/ + _of->op_count=0; + continue; + } + /*By default discard 80 ms of data after a seek, unless we seek + into the pre-skip region.*/ + cur_discard_count=80*48; + cur_page_gp=_of->op[op_count-1].granulepos; + /*Try to initialize prev_packet_gp. + If the current page had packets but didn't have a granule + position, or the granule position it had was too small (both + illegal), just use the starting granule position for the link.*/ + prev_packet_gp=links[cur_link].pcm_start; + if(OP_LIKELY(cur_page_gp!=-1)){ + op_granpos_add(&prev_packet_gp,cur_page_gp,-total_duration); + } + if(OP_LIKELY(!op_granpos_diff(&diff, + prev_packet_gp,links[cur_link].pcm_start))){ + opus_int32 pre_skip; + /*If we start at the beginning of the pre-skip region, or we're + at least 80 ms from the end of the pre-skip region, we discard + to the end of the pre-skip region. + Otherwise, we still use the 80 ms default, which will discard + past the end of the pre-skip region.*/ + pre_skip=links[cur_link].head.pre_skip; + if(diff>=0&&diff<=OP_MAX(0,pre_skip-80*48)){ + cur_discard_count=pre_skip-(int)diff; + } + } + _of->cur_discard_count=cur_discard_count; + } + if(OP_UNLIKELY(cur_page_gp==-1)){ + /*This page had completed packets but didn't have a valid granule + position. + This is illegal, but we'll try to handle it by continuing to count + forwards from the previous page.*/ + if(op_granpos_add(&cur_page_gp,prev_packet_gp,total_duration)<0){ + /*The timestamp for this page overflowed.*/ + cur_page_gp=links[cur_link].pcm_end; + } + } + /*If we hit the last page, handle end-trimming.*/ + if(OP_UNLIKELY(cur_page_eos) + &&OP_LIKELY(!op_granpos_diff(&diff,cur_page_gp,prev_packet_gp)) + &&OP_LIKELY(diff<total_duration)){ + cur_packet_gp=prev_packet_gp; + for(pi=0;pi<op_count;pi++){ + diff=durations[pi]-diff; + /*If we have samples to trim...*/ + if(diff>0){ + /*If we trimmed the entire packet, stop (the spec says encoders + shouldn't do this, but we support it anyway).*/ + if(OP_UNLIKELY(diff>durations[pi]))break; + cur_packet_gp=cur_page_gp; + /*Move the EOS flag to this packet, if necessary, so we'll trim + the samples during decode.*/ + _of->op[pi].e_o_s=1; + } + else{ + /*Update the granule position as normal.*/ + OP_ALWAYS_TRUE(!op_granpos_add(&cur_packet_gp, + cur_packet_gp,durations[pi])); + } + _of->op[pi].granulepos=cur_packet_gp; + OP_ALWAYS_TRUE(!op_granpos_diff(&diff,cur_page_gp,cur_packet_gp)); + } + } + else{ + /*Propagate timestamps to earlier packets. + op_granpos_add(&prev_packet_gp,prev_packet_gp,total_duration) + should succeed and give prev_packet_gp==cur_page_gp. + But we don't bother to check that, as there isn't much we can do + if it's not true, and it actually will not be true on the first + page after a seek, if there was a continued packet. + The only thing we guarantee is that the start and end granule + positions of the packets are valid, and that they are monotonic + within a page. + They might be completely out of range for this link (we'll check + that elsewhere), or non-monotonic between pages.*/ + if(OP_UNLIKELY(op_granpos_add(&prev_packet_gp, + cur_page_gp,-total_duration)<0)){ + /*The starting timestamp for the first packet on this page + underflowed. + This is illegal, but we ignore it.*/ + prev_packet_gp=0; + } + for(pi=0;pi<op_count;pi++){ + if(OP_UNLIKELY(op_granpos_add(&cur_packet_gp, + cur_page_gp,-total_duration)<0)){ + /*The start timestamp for this packet underflowed. + This is illegal, but we ignore it.*/ + cur_packet_gp=0; + } + total_duration-=durations[pi]; + OP_ASSERT(total_duration>=0); + OP_ALWAYS_TRUE(!op_granpos_add(&cur_packet_gp, + cur_packet_gp,durations[pi])); + _of->op[pi].granulepos=cur_packet_gp; + } + OP_ASSERT(total_duration==0); + } + _of->prev_packet_gp=prev_packet_gp; + _of->prev_page_offset=_page_offset; + _of->op_count=pi; + /*If end-trimming didn't trim all the packets, we're done.*/ + if(OP_LIKELY(pi>0))return 1; + } + } + } +} + +int op_raw_seek(OggOpusFile *_of,opus_int64 _pos){ + int ret; + if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL; + /*Don't dump the decoder state if we can't seek.*/ + if(OP_UNLIKELY(!_of->seekable))return OP_ENOSEEK; + if(OP_UNLIKELY(_pos<0)||OP_UNLIKELY(_pos>_of->end))return OP_EINVAL; + /*Clear out any buffered, decoded data.*/ + op_decode_clear(_of); + _of->bytes_tracked=0; + _of->samples_tracked=0; + ret=op_seek_helper(_of,_pos); + if(OP_UNLIKELY(ret<0))return OP_EREAD; + ret=op_fetch_and_process_page(_of,NULL,-1,1,1,1); + /*If we hit EOF, op_fetch_and_process_page() leaves us uninitialized. + Instead, jump to the end.*/ + if(ret==OP_EOF){ + int cur_link; + op_decode_clear(_of); + cur_link=_of->nlinks-1; + _of->cur_link=cur_link; + _of->prev_packet_gp=_of->links[cur_link].pcm_end; + _of->cur_discard_count=0; + ret=0; + } + else if(ret>0)ret=0; + return ret; +} + +/*Convert a PCM offset relative to the start of the whole stream to a granule + position in an individual link.*/ +static ogg_int64_t op_get_granulepos(const OggOpusFile *_of, + ogg_int64_t _pcm_offset,int *_li){ + const OggOpusLink *links; + ogg_int64_t duration; + int nlinks; + int li; + OP_ASSERT(_pcm_offset>=0); + nlinks=_of->nlinks; + links=_of->links; + for(li=0;OP_LIKELY(li<nlinks);li++){ + ogg_int64_t pcm_start; + opus_int32 pre_skip; + pcm_start=links[li].pcm_start; + pre_skip=links[li].head.pre_skip; + OP_ALWAYS_TRUE(!op_granpos_diff(&duration,links[li].pcm_end,pcm_start)); + duration-=pre_skip; + if(_pcm_offset<duration){ + _pcm_offset+=pre_skip; + if(OP_UNLIKELY(pcm_start>OP_INT64_MAX-_pcm_offset)){ + /*Adding this amount to the granule position would overflow the positive + half of its 64-bit range. + Since signed overflow is undefined in C, do it in a way the compiler + isn't allowed to screw up.*/ + _pcm_offset-=OP_INT64_MAX-pcm_start+1; + pcm_start=OP_INT64_MIN; + } + pcm_start+=_pcm_offset; + *_li=li; + return pcm_start; + } + _pcm_offset-=duration; + } + return -1; +} + +/*A small helper to determine if an Ogg page contains data that continues onto + a subsequent page.*/ +static int op_page_continues(const ogg_page *_og){ + int nlacing; + OP_ASSERT(_og->header_len>=27); + nlacing=_og->header[26]; + OP_ASSERT(_og->header_len>=27+nlacing); + /*This also correctly handles the (unlikely) case of nlacing==0, because + 0!=255.*/ + return _og->header[27+nlacing-1]==255; +} + +/*A small helper to buffer the continued packet data from a page.*/ +static void op_buffer_continued_data(OggOpusFile *_of,ogg_page *_og){ + ogg_packet op; + ogg_stream_pagein(&_of->os,_og); + /*Drain any packets that did end on this page (and ignore holes). + We only care about the continued packet data.*/ + while(ogg_stream_packetout(&_of->os,&op)); +} + +/*This controls how close the target has to be to use the current stream + position to subdivide the initial range. + Two minutes seems to be a good default.*/ +#define OP_CUR_TIME_THRESH (120*48*(opus_int32)1000) + +/*Note: The OP_SMALL_FOOTPRINT #define doesn't (currently) save much code size, + but it's meant to serve as documentation for portions of the seeking + algorithm that are purely optional, to aid others learning from/porting this + code to other contexts.*/ +/*#define OP_SMALL_FOOTPRINT (1)*/ + +/*Search within link _li for the page with the highest granule position + preceding (or equal to) _target_gp. + There is a danger here: missing pages or incorrect frame number information + in the bitstream could make our task impossible. + Account for that (and report it as an error condition).*/ +static int op_pcm_seek_page(OggOpusFile *_of, + ogg_int64_t _target_gp,int _li){ + const OggOpusLink *link; + ogg_page og; + ogg_int64_t pcm_pre_skip; + ogg_int64_t pcm_start; + ogg_int64_t pcm_end; + ogg_int64_t best_gp; + ogg_int64_t diff; + ogg_uint32_t serialno; + opus_int32 pre_skip; + opus_int64 begin; + opus_int64 end; + opus_int64 boundary; + opus_int64 best; + opus_int64 best_start; + opus_int64 page_offset; + opus_int64 d0; + opus_int64 d1; + opus_int64 d2; + int force_bisect; + int buffering; + int ret; + _of->bytes_tracked=0; + _of->samples_tracked=0; + link=_of->links+_li; + best_gp=pcm_start=link->pcm_start; + pcm_end=link->pcm_end; + serialno=link->serialno; + best=best_start=begin=link->data_offset; + page_offset=-1; + buffering=0; + /*We discard the first 80 ms of data after a seek, so seek back that much + farther. + If we can't, simply seek to the beginning of the link.*/ + if(OP_UNLIKELY(op_granpos_add(&_target_gp,_target_gp,-80*48)<0) + ||OP_UNLIKELY(op_granpos_cmp(_target_gp,pcm_start)<0)){ + _target_gp=pcm_start; + } + /*Special case seeking to the start of the link.*/ + pre_skip=link->head.pre_skip; + OP_ALWAYS_TRUE(!op_granpos_add(&pcm_pre_skip,pcm_start,pre_skip)); + if(op_granpos_cmp(_target_gp,pcm_pre_skip)<0)end=boundary=begin; + else{ + end=boundary=link->end_offset; +#if !defined(OP_SMALL_FOOTPRINT) + /*If we were decoding from this link, we can narrow the range a bit.*/ + if(_li==_of->cur_link&&_of->ready_state>=OP_INITSET){ + opus_int64 offset; + int op_count; + op_count=_of->op_count; + /*The only way the offset can be invalid _and_ we can fail the granule + position checks below is if someone changed the contents of the last + page since we read it. + We'd be within our rights to just return OP_EBADLINK in that case, but + we'll simply ignore the current position instead.*/ + offset=_of->offset; + if(op_count>0&&OP_LIKELY(offset<=end)){ + ogg_int64_t gp; + /*Make sure the timestamp is valid. + The granule position might be -1 if we collected the packets from a + page without a granule position after reporting a hole.*/ + gp=_of->op[op_count-1].granulepos; + if(OP_LIKELY(gp!=-1)&&OP_LIKELY(op_granpos_cmp(pcm_start,gp)<0) + &&OP_LIKELY(op_granpos_cmp(pcm_end,gp)>0)){ + OP_ALWAYS_TRUE(!op_granpos_diff(&diff,gp,_target_gp)); + /*We only actually use the current time if either + a) We can cut off at least half the range, or + b) We're seeking sufficiently close to the current position that + it's likely to be informative. + Otherwise it appears using the whole link range to estimate the + first seek location gives better results, on average.*/ + if(diff<0){ + OP_ASSERT(offset>=begin); + if(offset-begin>=end-begin>>1||diff>-OP_CUR_TIME_THRESH){ + best=begin=offset; + best_gp=pcm_start=gp; + /*If we have buffered data from a continued packet, remember the + offset of the previous page's start, so that if we do wind up + having to seek back here later, we can prime the stream with + the continued packet data. + With no continued packet, we remember the end of the page.*/ + best_start=_of->os.body_returned<_of->os.body_fill? + _of->prev_page_offset:best; + /*If there's completed packets and data in the stream state, + prev_page_offset should always be set.*/ + OP_ASSERT(best_start>=0); + /*Buffer any continued packet data starting from here.*/ + buffering=1; + } + } + else{ + ogg_int64_t prev_page_gp; + /*We might get lucky and already have the packet with the target + buffered. + Worth checking. + For very small files (with all of the data in a single page, + generally 1 second or less), we can loop them continuously + without seeking at all.*/ + OP_ALWAYS_TRUE(!op_granpos_add(&prev_page_gp,_of->op[0].granulepos, + -op_get_packet_duration(_of->op[0].packet,_of->op[0].bytes))); + if(op_granpos_cmp(prev_page_gp,_target_gp)<=0){ + /*Don't call op_decode_clear(), because it will dump our + packets.*/ + _of->op_pos=0; + _of->od_buffer_size=0; + _of->prev_packet_gp=prev_page_gp; + /*_of->prev_page_offset already points to the right place.*/ + _of->ready_state=OP_STREAMSET; + return op_make_decode_ready(_of); + } + /*No such luck. + Check if we can cut off at least half the range, though.*/ + if(offset-begin<=end-begin>>1||diff<OP_CUR_TIME_THRESH){ + /*We really want the page start here, but this will do.*/ + end=boundary=offset; + pcm_end=gp; + } + } + } + } + } +#endif + } + /*This code was originally based on the "new search algorithm by HB (Nicholas + Vinen)" from libvorbisfile. + It has been modified substantially since.*/ + op_decode_clear(_of); + if(!buffering)ogg_stream_reset_serialno(&_of->os,serialno); + _of->cur_link=_li; + _of->ready_state=OP_STREAMSET; + /*Initialize the interval size history.*/ + d2=d1=d0=end-begin; + force_bisect=0; + while(begin<end){ + opus_int64 bisect; + opus_int64 next_boundary; + opus_int32 chunk_size; + if(end-begin<OP_CHUNK_SIZE)bisect=begin; + else{ + /*Update the interval size history.*/ + d0=d1>>1; + d1=d2>>1; + d2=end-begin>>1; + if(force_bisect)bisect=begin+(end-begin>>1); + else{ + ogg_int64_t diff2; + OP_ALWAYS_TRUE(!op_granpos_diff(&diff,_target_gp,pcm_start)); + OP_ALWAYS_TRUE(!op_granpos_diff(&diff2,pcm_end,pcm_start)); + /*Take a (pretty decent) guess.*/ + bisect=begin+op_rescale64(diff,diff2,end-begin)-OP_CHUNK_SIZE; + } + if(bisect-OP_CHUNK_SIZE<begin)bisect=begin; + force_bisect=0; + } + if(bisect!=_of->offset){ + /*Discard any buffered continued packet data.*/ + if(buffering)ogg_stream_reset(&_of->os); + buffering=0; + page_offset=-1; + ret=op_seek_helper(_of,bisect); + if(OP_UNLIKELY(ret<0))return ret; + } + chunk_size=OP_CHUNK_SIZE; + next_boundary=boundary; + /*Now scan forward and figure out where we landed. + In the ideal case, we will see a page with a granule position at or + before our target, followed by a page with a granule position after our + target (or the end of the search interval). + Then we can just drop out and will have all of the data we need with no + additional seeking. + If we landed too far before, or after, we'll break out and do another + bisection.*/ + while(begin<end){ + page_offset=op_get_next_page(_of,&og,boundary); + if(page_offset<0){ + if(page_offset<OP_FALSE)return (int)page_offset; + /*There are no more pages in our interval from our stream with a valid + timestamp that start at position bisect or later.*/ + /*If we scanned the whole interval, we're done.*/ + if(bisect<=begin+1)end=begin; + else{ + /*Otherwise, back up one chunk. + First, discard any data from a continued packet.*/ + if(buffering)ogg_stream_reset(&_of->os); + buffering=0; + bisect=OP_MAX(bisect-chunk_size,begin); + ret=op_seek_helper(_of,bisect); + if(OP_UNLIKELY(ret<0))return ret; + /*Bump up the chunk size.*/ + chunk_size=OP_MIN(2*chunk_size,OP_CHUNK_SIZE_MAX); + /*If we did find a page from another stream or without a timestamp, + don't read past it.*/ + boundary=next_boundary; + } + } + else{ + ogg_int64_t gp; + int has_packets; + /*Save the offset of the first page we found after the seek, regardless + of the stream it came from or whether or not it has a timestamp.*/ + next_boundary=OP_MIN(page_offset,next_boundary); + if(serialno!=(ogg_uint32_t)ogg_page_serialno(&og))continue; + has_packets=ogg_page_packets(&og)>0; + /*Force the gp to -1 (as it should be per spec) if no packets end on + this page. + Otherwise we might get confused when we try to pull out a packet + with that timestamp and can't find it.*/ + gp=has_packets?ogg_page_granulepos(&og):-1; + if(gp==-1){ + if(buffering){ + if(OP_LIKELY(!has_packets))ogg_stream_pagein(&_of->os,&og); + else{ + /*If packets did end on this page, but we still didn't have a + valid granule position (in violation of the spec!), stop + buffering continued packet data. + Otherwise we might continue past the packet we actually + wanted.*/ + ogg_stream_reset(&_of->os); + buffering=0; + } + } + continue; + } + if(op_granpos_cmp(gp,_target_gp)<0){ + /*We found a page that ends before our target. + Advance to the raw offset of the next page.*/ + begin=_of->offset; + if(OP_UNLIKELY(op_granpos_cmp(pcm_start,gp)>0) + ||OP_UNLIKELY(op_granpos_cmp(pcm_end,gp)<0)){ + /*Don't let pcm_start get out of range! + That could happen with an invalid timestamp.*/ + break; + } + /*Save the byte offset of the end of the page with this granule + position.*/ + best=best_start=begin; + /*Buffer any data from a continued packet, if necessary. + This avoids the need to seek back here if the next timestamp we + encounter while scanning forward lies after our target.*/ + if(buffering)ogg_stream_reset(&_of->os); + if(op_page_continues(&og)){ + op_buffer_continued_data(_of,&og); + /*If we have a continued packet, remember the offset of this + page's start, so that if we do wind up having to seek back here + later, we can prime the stream with the continued packet data. + With no continued packet, we remember the end of the page.*/ + best_start=page_offset; + } + /*Then force buffering on, so that if a packet starts (but does not + end) on the next page, we still avoid the extra seek back.*/ + buffering=1; + best_gp=pcm_start=gp; + OP_ALWAYS_TRUE(!op_granpos_diff(&diff,_target_gp,pcm_start)); + /*If we're more than a second away from our target, break out and + do another bisection.*/ + if(diff>48000)break; + /*Otherwise, keep scanning forward (do NOT use begin+1).*/ + bisect=begin; + } + else{ + /*We found a page that ends after our target.*/ + /*If we scanned the whole interval before we found it, we're done.*/ + if(bisect<=begin+1)end=begin; + else{ + end=bisect; + /*In later iterations, don't read past the first page we found.*/ + boundary=next_boundary; + /*If we're not making much progress shrinking the interval size, + start forcing straight bisection to limit the worst case.*/ + force_bisect=end-begin>d0*2; + /*Don't let pcm_end get out of range! + That could happen with an invalid timestamp.*/ + if(OP_LIKELY(op_granpos_cmp(pcm_end,gp)>0) + &&OP_LIKELY(op_granpos_cmp(pcm_start,gp)<=0)){ + pcm_end=gp; + } + break; + } + } + } + } + } + /*Found our page.*/ + OP_ASSERT(op_granpos_cmp(best_gp,pcm_start)>=0); + /*Seek, if necessary. + If we were buffering data from a continued packet, we should be able to + continue to scan forward to get the rest of the data (even if + page_offset==-1). + Otherwise, we need to seek back to best_start.*/ + if(!buffering){ + if(best_start!=page_offset){ + page_offset=-1; + ret=op_seek_helper(_of,best_start); + if(OP_UNLIKELY(ret<0))return ret; + } + if(best_start<best){ + /*Retrieve the page at best_start, if we do not already have it.*/ + if(page_offset<0){ + page_offset=op_get_next_page(_of,&og,link->end_offset); + if(OP_UNLIKELY(page_offset<OP_FALSE))return (int)page_offset; + if(OP_UNLIKELY(page_offset!=best_start))return OP_EBADLINK; + } + op_buffer_continued_data(_of,&og); + page_offset=-1; + } + } + /*Update prev_packet_gp to allow per-packet granule position assignment.*/ + _of->prev_packet_gp=best_gp; + _of->prev_page_offset=best_start; + ret=op_fetch_and_process_page(_of,page_offset<0?NULL:&og,page_offset,1,0,1); + if(OP_UNLIKELY(ret<=0))return OP_EBADLINK; + /*Verify result.*/ + if(OP_UNLIKELY(op_granpos_cmp(_of->prev_packet_gp,_target_gp)>0)){ + return OP_EBADLINK; + } + /*Our caller will set cur_discard_count to handle pre-roll.*/ + return 0; +} + +int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset){ + const OggOpusLink *link; + ogg_int64_t pcm_start; + ogg_int64_t target_gp; + ogg_int64_t prev_packet_gp; + ogg_int64_t skip; + ogg_int64_t diff; + int op_count; + int op_pos; + int ret; + int li; + if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL; + if(OP_UNLIKELY(!_of->seekable))return OP_ENOSEEK; + if(OP_UNLIKELY(_pcm_offset<0))return OP_EINVAL; + target_gp=op_get_granulepos(_of,_pcm_offset,&li); + if(OP_UNLIKELY(target_gp==-1))return OP_EINVAL; + link=_of->links+li; + pcm_start=link->pcm_start; + OP_ALWAYS_TRUE(!op_granpos_diff(&_pcm_offset,target_gp,pcm_start)); +#if !defined(OP_SMALL_FOOTPRINT) + /*For small (90 ms or less) forward seeks within the same link, just decode + forward. + This also optimizes the case of seeking to the current position.*/ + if(li==_of->cur_link&&_of->ready_state>=OP_INITSET){ + ogg_int64_t gp; + gp=_of->prev_packet_gp; + if(OP_LIKELY(gp!=-1)){ + int nbuffered; + nbuffered=OP_MAX(_of->od_buffer_size-_of->od_buffer_pos,0); + OP_ALWAYS_TRUE(!op_granpos_add(&gp,gp,-nbuffered)); + /*We do _not_ add cur_discard_count to gp. + Otherwise the total amount to discard could grow without bound, and it + would be better just to do a full seek.*/ + if(OP_LIKELY(!op_granpos_diff(&diff,gp,pcm_start))){ + ogg_int64_t discard_count; + discard_count=_pcm_offset-diff; + /*We use a threshold of 90 ms instead of 80, since 80 ms is the + _minimum_ we would have discarded after a full seek. + Assuming 20 ms frames (the default), we'd discard 90 ms on average.*/ + if(discard_count>=0&&OP_UNLIKELY(discard_count<90*48)){ + _of->cur_discard_count=(opus_int32)discard_count; + return 0; + } + } + } + } +#endif + ret=op_pcm_seek_page(_of,target_gp,li); + if(OP_UNLIKELY(ret<0))return ret; + /*Now skip samples until we actually get to our target.*/ + /*Figure out where we should skip to.*/ + if(_pcm_offset<=link->head.pre_skip)skip=0; + else skip=OP_MAX(_pcm_offset-80*48,0); + OP_ASSERT(_pcm_offset-skip>=0); + OP_ASSERT(_pcm_offset-skip<OP_INT32_MAX-120*48); + /*Skip packets until we find one with samples past our skip target.*/ + for(;;){ + op_count=_of->op_count; + prev_packet_gp=_of->prev_packet_gp; + for(op_pos=_of->op_pos;op_pos<op_count;op_pos++){ + ogg_int64_t cur_packet_gp; + cur_packet_gp=_of->op[op_pos].granulepos; + if(OP_LIKELY(!op_granpos_diff(&diff,cur_packet_gp,pcm_start)) + &&diff>skip){ + break; + } + prev_packet_gp=cur_packet_gp; + } + _of->prev_packet_gp=prev_packet_gp; + _of->op_pos=op_pos; + if(op_pos<op_count)break; + /*We skipped all the packets on this page. + Fetch another.*/ + ret=op_fetch_and_process_page(_of,NULL,-1,1,0,1); + if(OP_UNLIKELY(ret<=0))return OP_EBADLINK; + } + OP_ALWAYS_TRUE(!op_granpos_diff(&diff,prev_packet_gp,pcm_start)); + /*We skipped too far. + Either the timestamps were illegal or there was a hole in the data.*/ + if(diff>skip)return OP_EBADLINK; + OP_ASSERT(_pcm_offset-diff<OP_INT32_MAX); + /*TODO: If there are further holes/illegal timestamps, we still won't decode + to the correct sample. + However, at least op_pcm_tell() will report the correct value immediately + after returning.*/ + _of->cur_discard_count=(opus_int32)(_pcm_offset-diff); + return 0; +} + +opus_int64 op_raw_tell(const OggOpusFile *_of){ + if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL; + return _of->offset; +} + +/*Convert a granule position from a given link to a PCM offset relative to the + start of the whole stream. + For unseekable sources, this gets reset to 0 at the beginning of each link.*/ +static ogg_int64_t op_get_pcm_offset(const OggOpusFile *_of, + ogg_int64_t _gp,int _li){ + const OggOpusLink *links; + ogg_int64_t pcm_offset; + ogg_int64_t delta; + int li; + links=_of->links; + pcm_offset=0; + OP_ASSERT(_li<_of->nlinks); + for(li=0;li<_li;li++){ + OP_ALWAYS_TRUE(!op_granpos_diff(&delta, + links[li].pcm_end,links[li].pcm_start)); + delta-=links[li].head.pre_skip; + pcm_offset+=delta; + } + OP_ASSERT(_li>=0); + if(_of->seekable&&OP_UNLIKELY(op_granpos_cmp(_gp,links[_li].pcm_end)>0)){ + _gp=links[_li].pcm_end; + } + if(OP_LIKELY(op_granpos_cmp(_gp,links[_li].pcm_start)>0)){ + if(OP_UNLIKELY(op_granpos_diff(&delta,_gp,links[_li].pcm_start)<0)){ + /*This means an unseekable stream claimed to have a page from more than + 2 billion days after we joined.*/ + OP_ASSERT(!_of->seekable); + return OP_INT64_MAX; + } + if(delta<links[_li].head.pre_skip)delta=0; + else delta-=links[_li].head.pre_skip; + /*In the seekable case, _gp was limited by pcm_end. + In the unseekable case, pcm_offset should be 0.*/ + OP_ASSERT(pcm_offset<=OP_INT64_MAX-delta); + pcm_offset+=delta; + } + return pcm_offset; +} + +ogg_int64_t op_pcm_tell(const OggOpusFile *_of){ + ogg_int64_t gp; + int nbuffered; + int li; + if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL; + gp=_of->prev_packet_gp; + if(gp==-1)return 0; + nbuffered=OP_MAX(_of->od_buffer_size-_of->od_buffer_pos,0); + OP_ALWAYS_TRUE(!op_granpos_add(&gp,gp,-nbuffered)); + li=_of->seekable?_of->cur_link:0; + if(op_granpos_add(&gp,gp,_of->cur_discard_count)<0){ + gp=_of->links[li].pcm_end; + } + return op_get_pcm_offset(_of,gp,li); +} + +void op_set_decode_callback(OggOpusFile *_of, + op_decode_cb_func _decode_cb,void *_ctx){ + _of->decode_cb=_decode_cb; + _of->decode_cb_ctx=_ctx; +} + +int op_set_gain_offset(OggOpusFile *_of, + int _gain_type,opus_int32 _gain_offset_q8){ + if(_gain_type!=OP_HEADER_GAIN&&_gain_type!=OP_ALBUM_GAIN + &&_gain_type!=OP_TRACK_GAIN&&_gain_type!=OP_ABSOLUTE_GAIN){ + return OP_EINVAL; + } + _of->gain_type=_gain_type; + /*The sum of header gain and track gain lies in the range [-65536,65534]. + These bounds allow the offset to set the final value to anywhere in the + range [-32768,32767], which is what we'll clamp it to before applying.*/ + _of->gain_offset_q8=OP_CLAMP(-98302,_gain_offset_q8,98303); + op_update_gain(_of); + return 0; +} + +void op_set_dither_enabled(OggOpusFile *_of,int _enabled){ +#if !defined(OP_FIXED_POINT) + _of->dither_disabled=!_enabled; + if(!_enabled)_of->dither_mute=65; +#endif +} + +/*Allocate the decoder scratch buffer. + This is done lazily, since if the user provides large enough buffers, we'll + never need it.*/ +static int op_init_buffer(OggOpusFile *_of){ + int nchannels_max; + if(_of->seekable){ + const OggOpusLink *links; + int nlinks; + int li; + links=_of->links; + nlinks=_of->nlinks; + nchannels_max=1; + for(li=0;li<nlinks;li++){ + nchannels_max=OP_MAX(nchannels_max,links[li].head.channel_count); + } + } + else nchannels_max=OP_NCHANNELS_MAX; + _of->od_buffer=(op_sample *)_ogg_malloc( + sizeof(*_of->od_buffer)*nchannels_max*120*48); + if(_of->od_buffer==NULL)return OP_EFAULT; + return 0; +} + +/*Decode a single packet into the target buffer.*/ +static int op_decode(OggOpusFile *_of,op_sample *_pcm, + const ogg_packet *_op,int _nsamples,int _nchannels){ + int ret; + /*First we try using the application-provided decode callback.*/ + if(_of->decode_cb!=NULL){ +#if defined(OP_FIXED_POINT) + ret=(*_of->decode_cb)(_of->decode_cb_ctx,_of->od,_pcm,_op, + _nsamples,_nchannels,OP_DEC_FORMAT_SHORT,_of->cur_link); +#else + ret=(*_of->decode_cb)(_of->decode_cb_ctx,_of->od,_pcm,_op, + _nsamples,_nchannels,OP_DEC_FORMAT_FLOAT,_of->cur_link); +#endif + } + else ret=OP_DEC_USE_DEFAULT; + /*If the application didn't want to handle decoding, do it ourselves.*/ + if(ret==OP_DEC_USE_DEFAULT){ +#if defined(OP_FIXED_POINT) + ret=opus_multistream_decode(_of->od, + _op->packet,_op->bytes,_pcm,_nsamples,0); +#else + ret=opus_multistream_decode_float(_of->od, + _op->packet,_op->bytes,_pcm,_nsamples,0); +#endif + OP_ASSERT(ret<0||ret==_nsamples); + } + /*If the application returned a positive value other than 0 or + OP_DEC_USE_DEFAULT, fail.*/ + else if(OP_UNLIKELY(ret>0))return OP_EBADPACKET; + if(OP_UNLIKELY(ret<0))return OP_EBADPACKET; + return ret; +} + +/*Read more samples from the stream, using the same API as op_read() or + op_read_float().*/ +static int op_read_native(OggOpusFile *_of, + op_sample *_pcm,int _buf_size,int *_li){ + if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL; + for(;;){ + int ret; + if(OP_LIKELY(_of->ready_state>=OP_INITSET)){ + int nchannels; + int od_buffer_pos; + int nsamples; + int op_pos; + nchannels=_of->links[_of->seekable?_of->cur_link:0].head.channel_count; + od_buffer_pos=_of->od_buffer_pos; + nsamples=_of->od_buffer_size-od_buffer_pos; + /*If we have buffered samples, return them.*/ + if(nsamples>0){ + if(nsamples*nchannels>_buf_size)nsamples=_buf_size/nchannels; + memcpy(_pcm,_of->od_buffer+nchannels*od_buffer_pos, + sizeof(*_pcm)*nchannels*nsamples); + od_buffer_pos+=nsamples; + _of->od_buffer_pos=od_buffer_pos; + if(_li!=NULL)*_li=_of->cur_link; + return nsamples; + } + /*If we have buffered packets, decode one.*/ + op_pos=_of->op_pos; + if(OP_LIKELY(op_pos<_of->op_count)){ + const ogg_packet *pop; + ogg_int64_t diff; + opus_int32 cur_discard_count; + int duration; + int trimmed_duration; + pop=_of->op+op_pos++; + _of->op_pos=op_pos; + cur_discard_count=_of->cur_discard_count; + duration=op_get_packet_duration(pop->packet,pop->bytes); + /*We don't buffer packets with an invalid TOC sequence.*/ + OP_ASSERT(duration>0); + trimmed_duration=duration; + /*Perform end-trimming.*/ + if(OP_UNLIKELY(pop->e_o_s)){ + if(OP_UNLIKELY(op_granpos_cmp(pop->granulepos, + _of->prev_packet_gp)<=0)){ + trimmed_duration=0; + } + else if(OP_LIKELY(!op_granpos_diff(&diff, + pop->granulepos,_of->prev_packet_gp))){ + trimmed_duration=(int)OP_MIN(diff,trimmed_duration); + } + } + _of->prev_packet_gp=pop->granulepos; + if(OP_UNLIKELY(duration*nchannels>_buf_size)){ + op_sample *buf; + /*If the user's buffer is too small, decode into a scratch buffer.*/ + buf=_of->od_buffer; + if(OP_UNLIKELY(buf==NULL)){ + ret=op_init_buffer(_of); + if(OP_UNLIKELY(ret<0))return ret; + buf=_of->od_buffer; + } + ret=op_decode(_of,buf,pop,duration,nchannels); + if(OP_UNLIKELY(ret<0))return ret; + /*Perform pre-skip/pre-roll.*/ + od_buffer_pos=(int)OP_MIN(trimmed_duration,cur_discard_count); + cur_discard_count-=od_buffer_pos; + _of->cur_discard_count=cur_discard_count; + _of->od_buffer_pos=od_buffer_pos; + _of->od_buffer_size=trimmed_duration; + /*Update bitrate tracking based on the actual samples we used from + what was decoded.*/ + _of->bytes_tracked+=pop->bytes; + _of->samples_tracked+=trimmed_duration-od_buffer_pos; + } + else{ + /*Otherwise decode directly into the user's buffer.*/ + ret=op_decode(_of,_pcm,pop,duration,nchannels); + if(OP_UNLIKELY(ret<0))return ret; + if(OP_LIKELY(trimmed_duration>0)){ + /*Perform pre-skip/pre-roll.*/ + od_buffer_pos=(int)OP_MIN(trimmed_duration,cur_discard_count); + cur_discard_count-=od_buffer_pos; + _of->cur_discard_count=cur_discard_count; + trimmed_duration-=od_buffer_pos; + if(OP_LIKELY(trimmed_duration>0) + &&OP_UNLIKELY(od_buffer_pos>0)){ + memmove(_pcm,_pcm+od_buffer_pos*nchannels, + sizeof(*_pcm)*trimmed_duration*nchannels); + } + /*Update bitrate tracking based on the actual samples we used from + what was decoded.*/ + _of->bytes_tracked+=pop->bytes; + _of->samples_tracked+=trimmed_duration; + if(OP_LIKELY(trimmed_duration>0)){ + if(_li!=NULL)*_li=_of->cur_link; + return trimmed_duration; + } + } + } + /*Don't grab another page yet. + This one might have more packets, or might have buffered data now.*/ + continue; + } + } + /*Suck in another page.*/ + ret=op_fetch_and_process_page(_of,NULL,-1,1,1,0); + if(OP_UNLIKELY(ret==OP_EOF)){ + if(_li!=NULL)*_li=_of->cur_link; + return 0; + } + if(OP_UNLIKELY(ret<0))return ret; + } +} + +/*A generic filter to apply to the decoded audio data. + _src is non-const because we will destructively modify the contents of the + source buffer that we consume in some cases.*/ +typedef int (*op_read_filter_func)(OggOpusFile *_of,void *_dst,int _dst_sz, + op_sample *_src,int _nsamples,int _nchannels); + +/*Decode some samples and then apply a custom filter to them. + This is used to convert to different output formats.*/ +static int op_filter_read_native(OggOpusFile *_of,void *_dst,int _dst_sz, + op_read_filter_func _filter,int *_li){ + int ret; + /*Ensure we have some decoded samples in our buffer.*/ + ret=op_read_native(_of,NULL,0,_li); + /*Now apply the filter to them.*/ + if(OP_LIKELY(ret>=0)&&OP_LIKELY(_of->ready_state>=OP_INITSET)){ + int od_buffer_pos; + od_buffer_pos=_of->od_buffer_pos; + ret=_of->od_buffer_size-od_buffer_pos; + if(OP_LIKELY(ret>0)){ + int nchannels; + nchannels=_of->links[_of->seekable?_of->cur_link:0].head.channel_count; + ret=(*_filter)(_of,_dst,_dst_sz, + _of->od_buffer+nchannels*od_buffer_pos,ret,nchannels); + OP_ASSERT(ret>=0); + OP_ASSERT(ret<=_of->od_buffer_size-od_buffer_pos); + od_buffer_pos+=ret; + _of->od_buffer_pos=od_buffer_pos; + } + } + return ret; +} + +#if !defined(OP_FIXED_POINT)||!defined(OP_DISABLE_FLOAT_API) + +/*Matrices for downmixing from the supported channel counts to stereo. + The matrices with 5 or more channels are normalized to a total volume of 2.0, + since most mixes sound too quiet if normalized to 1.0 (as there is generally + little volume in the side/rear channels).*/ +static const float OP_STEREO_DOWNMIX[OP_NCHANNELS_MAX-2][OP_NCHANNELS_MAX][2]={ + /*3.0*/ + { + {0.5858F,0.0F},{0.4142F,0.4142F},{0.0F,0.5858F} + }, + /*quadrophonic*/ + { + {0.4226F,0.0F},{0.0F,0.4226F},{0.366F,0.2114F},{0.2114F,0.336F} + }, + /*5.0*/ + { + {0.651F,0.0F},{0.46F,0.46F},{0.0F,0.651F},{0.5636F,0.3254F}, + {0.3254F,0.5636F} + }, + /*5.1*/ + { + {0.529F,0.0F},{0.3741F,0.3741F},{0.0F,0.529F},{0.4582F,0.2645F}, + {0.2645F,0.4582F},{0.3741F,0.3741F} + }, + /*6.1*/ + { + {0.4553F,0.0F},{0.322F,0.322F},{0.0F,0.4553F},{0.3943F,0.2277F}, + {0.2277F,0.3943F},{0.2788F,0.2788F},{0.322F,0.322F} + }, + /*7.1*/ + { + {0.3886F,0.0F},{0.2748F,0.2748F},{0.0F,0.3886F},{0.3366F,0.1943F}, + {0.1943F,0.3366F},{0.3366F,0.1943F},{0.1943F,0.3366F},{0.2748F,0.2748F} + } +}; + +#endif + +#if defined(OP_FIXED_POINT) + +/*Matrices for downmixing from the supported channel counts to stereo. + The matrices with 5 or more channels are normalized to a total volume of 2.0, + since most mixes sound too quiet if normalized to 1.0 (as there is generally + little volume in the side/rear channels). + Hence we keep the coefficients in Q14, so the downmix values won't overflow a + 32-bit number.*/ +static const opus_int16 OP_STEREO_DOWNMIX_Q14 + [OP_NCHANNELS_MAX-2][OP_NCHANNELS_MAX][2]={ + /*3.0*/ + { + {9598,0},{6786,6786},{0,9598} + }, + /*quadrophonic*/ + { + {6924,0},{0,6924},{5996,3464},{3464,5996} + }, + /*5.0*/ + { + {10666,0},{7537,7537},{0,10666},{9234,5331},{5331,9234} + }, + /*5.1*/ + { + {8668,0},{6129,6129},{0,8668},{7507,4335},{4335,7507},{6129,6129} + }, + /*6.1*/ + { + {7459,0},{5275,5275},{0,7459},{6460,3731},{3731,6460},{4568,4568}, + {5275,5275} + }, + /*7.1*/ + { + {6368,0},{4502,4502},{0,6368},{5515,3183},{3183,5515},{5515,3183}, + {3183,5515},{4502,4502} + } +}; + +int op_read(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size,int *_li){ + return op_read_native(_of,_pcm,_buf_size,_li); +} + +static int op_stereo_filter(OggOpusFile *_of,void *_dst,int _dst_sz, + op_sample *_src,int _nsamples,int _nchannels){ + (void)_of; + _nsamples=OP_MIN(_nsamples,_dst_sz>>1); + if(_nchannels==2)memcpy(_dst,_src,_nsamples*2*sizeof(*_src)); + else{ + opus_int16 *dst; + int i; + dst=(opus_int16 *)_dst; + if(_nchannels==1){ + for(i=0;i<_nsamples;i++)dst[2*i+0]=dst[2*i+1]=_src[i]; + } + else{ + for(i=0;i<_nsamples;i++){ + opus_int32 l; + opus_int32 r; + int ci; + l=r=0; + for(ci=0;ci<_nchannels;ci++){ + opus_int32 s; + s=_src[_nchannels*i+ci]; + l+=OP_STEREO_DOWNMIX_Q14[_nchannels-3][ci][0]*s; + r+=OP_STEREO_DOWNMIX_Q14[_nchannels-3][ci][1]*s; + } + /*TODO: For 5 or more channels, we should do soft clipping here.*/ + dst[2*i+0]=(opus_int16)OP_CLAMP(-32768,l+8192>>14,32767); + dst[2*i+1]=(opus_int16)OP_CLAMP(-32768,r+8192>>14,32767); + } + } + } + return _nsamples; +} + +int op_read_stereo(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size){ + return op_filter_read_native(_of,_pcm,_buf_size,op_stereo_filter,NULL); +} + +# if !defined(OP_DISABLE_FLOAT_API) + +static int op_short2float_filter(OggOpusFile *_of,void *_dst,int _dst_sz, + op_sample *_src,int _nsamples,int _nchannels){ + float *dst; + int i; + (void)_of; + dst=(float *)_dst; + if(OP_UNLIKELY(_nsamples*_nchannels>_dst_sz))_nsamples=_dst_sz/_nchannels; + _dst_sz=_nsamples*_nchannels; + for(i=0;i<_dst_sz;i++)dst[i]=(1.0F/32768)*_src[i]; + return _nsamples; +} + +int op_read_float(OggOpusFile *_of,float *_pcm,int _buf_size,int *_li){ + return op_filter_read_native(_of,_pcm,_buf_size,op_short2float_filter,_li); +} + +static int op_short2float_stereo_filter(OggOpusFile *_of, + void *_dst,int _dst_sz,op_sample *_src,int _nsamples,int _nchannels){ + float *dst; + int i; + dst=(float *)_dst; + _nsamples=OP_MIN(_nsamples,_dst_sz>>1); + if(_nchannels==1){ + _nsamples=op_short2float_filter(_of,dst,_nsamples,_src,_nsamples,1); + for(i=_nsamples;i-->0;)dst[2*i+0]=dst[2*i+1]=dst[i]; + } + else if(_nchannels<5){ + /*For 3 or 4 channels, we can downmix in fixed point without risk of + clipping.*/ + if(_nchannels>2){ + _nsamples=op_stereo_filter(_of,_src,_nsamples*2, + _src,_nsamples,_nchannels); + } + return op_short2float_filter(_of,dst,_dst_sz,_src,_nsamples,2); + } + else{ + /*For 5 or more channels, we convert to floats and then downmix (so that we + don't risk clipping).*/ + for(i=0;i<_nsamples;i++){ + float l; + float r; + int ci; + l=r=0; + for(ci=0;ci<_nchannels;ci++){ + float s; + s=(1.0F/32768)*_src[_nchannels*i+ci]; + l+=OP_STEREO_DOWNMIX[_nchannels-3][ci][0]*s; + r+=OP_STEREO_DOWNMIX[_nchannels-3][ci][1]*s; + } + dst[2*i+0]=l; + dst[2*i+1]=r; + } + } + return _nsamples; +} + +int op_read_float_stereo(OggOpusFile *_of,float *_pcm,int _buf_size){ + return op_filter_read_native(_of,_pcm,_buf_size, + op_short2float_stereo_filter,NULL); +} + +# endif + +#else + +# if defined(OP_HAVE_LRINTF) +# include <math.h> +# define op_float2int(_x) (lrintf(_x)) +# else +# define op_float2int(_x) ((int)((_x)+((_x)<0?-0.5F:0.5F))) +# endif + +/*The dithering code here is adapted from opusdec, part of opus-tools. + It was originally written by Greg Maxwell.*/ + +static opus_uint32 op_rand(opus_uint32 _seed){ + return _seed*96314165+907633515&0xFFFFFFFFU; +} + +/*This implements 16-bit quantization with full triangular dither and IIR noise + shaping. + The noise shaping filters were designed by Sebastian Gesemann, and are based + on the LAME ATH curves with flattening to limit their peak gain to 20 dB. + Everyone else's noise shaping filters are mildly crazy. + The 48 kHz version of this filter is just a warped version of the 44.1 kHz + filter and probably could be improved by shifting the HF shelf up in + frequency a little bit, since 48 kHz has a bit more room and being more + conservative against bat-ears is probably more important than more noise + suppression. + This process can increase the peak level of the signal (in theory by the peak + error of 1.5 +20 dB, though that is unobservably rare). + To avoid clipping, the signal is attenuated by a couple thousandths of a dB. + Initially, the approach taken here was to only attenuate by the 99.9th + percentile, making clipping rare but not impossible (like SoX), but the + limited gain of the filter means that the worst case was only two + thousandths of a dB more, so this just uses the worst case. + The attenuation is probably also helpful to prevent clipping in the DAC + reconstruction filters or downstream resampling, in any case.*/ + +# define OP_GAIN (32753.0F) + +# define OP_PRNG_GAIN (1.0F/0xFFFFFFFF) + +/*48 kHz noise shaping filter, sd=2.34.*/ + +static const float OP_FCOEF_B[4]={ + 2.2374F,-0.7339F,-0.1251F,-0.6033F +}; + +static const float OP_FCOEF_A[4]={ + 0.9030F,0.0116F,-0.5853F,-0.2571F +}; + +static int op_float2short_filter(OggOpusFile *_of,void *_dst,int _dst_sz, + float *_src,int _nsamples,int _nchannels){ + opus_int16 *dst; + int ci; + int i; + dst=(opus_int16 *)_dst; + if(OP_UNLIKELY(_nsamples*_nchannels>_dst_sz))_nsamples=_dst_sz/_nchannels; +# if defined(OP_SOFT_CLIP) + if(_of->state_channel_count!=_nchannels){ + for(ci=0;ci<_nchannels;ci++)_of->clip_state[ci]=0; + } + opus_pcm_soft_clip(_src,_nsamples,_nchannels,_of->clip_state); +# endif + if(_of->dither_disabled){ + for(i=0;i<_nchannels*_nsamples;i++){ + dst[i]=op_float2int(OP_CLAMP(-32768,32768.0F*_src[i],32767)); + } + } + else{ + opus_uint32 seed; + int mute; + seed=_of->dither_seed; + mute=_of->dither_mute; + if(_of->state_channel_count!=_nchannels)mute=65; + /*In order to avoid replacing digital silence with quiet dither noise, we + mute if the output has been silent for a while.*/ + if(mute>64)memset(_of->dither_a,0,sizeof(*_of->dither_a)*4*_nchannels); + for(i=0;i<_nsamples;i++){ + int silent; + silent=1; + for(ci=0;ci<_nchannels;ci++){ + float r; + float s; + float err; + int si; + int j; + s=_src[_nchannels*i+ci]; + silent&=s==0; + s*=OP_GAIN; + err=0; + for(j=0;j<4;j++){ + err+=OP_FCOEF_B[j]*_of->dither_b[ci*4+j] + -OP_FCOEF_A[j]*_of->dither_a[ci*4+j]; + } + for(j=3;j-->0;)_of->dither_a[ci*4+j+1]=_of->dither_a[ci*4+j]; + for(j=3;j-->0;)_of->dither_b[ci*4+j+1]=_of->dither_b[ci*4+j]; + _of->dither_a[ci*4]=err; + s-=err; + if(mute>16)r=0; + else{ + seed=op_rand(seed); + r=seed*OP_PRNG_GAIN; + seed=op_rand(seed); + r-=seed*OP_PRNG_GAIN; + } + /*Clamp in float out of paranoia that the input will be > 96 dBFS and + wrap if the integer is clamped.*/ + si=op_float2int(OP_CLAMP(-32768,s+r,32767)); + dst[_nchannels*i+ci]=(opus_int16)si; + /*Including clipping in the noise shaping is generally disastrous: the + futile effort to restore the clipped energy results in more clipping. + However, small amounts---at the level which could normally be created + by dither and rounding---are harmless and can even reduce clipping + somewhat due to the clipping sometimes reducing the dither + rounding + error.*/ + _of->dither_b[ci*4]=mute>16?0:OP_CLAMP(-1.5F,si-s,1.5F); + } + mute++; + if(!silent)mute=0; + } + _of->dither_mute=OP_MIN(mute,65); + _of->dither_seed=seed; + } + _of->state_channel_count=_nchannels; + return _nsamples; +} + +int op_read(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size,int *_li){ + return op_filter_read_native(_of,_pcm,_buf_size,op_float2short_filter,_li); +} + +int op_read_float(OggOpusFile *_of,float *_pcm,int _buf_size,int *_li){ + _of->state_channel_count=0; + return op_read_native(_of,_pcm,_buf_size,_li); +} + +static int op_stereo_filter(OggOpusFile *_of,void *_dst,int _dst_sz, + op_sample *_src,int _nsamples,int _nchannels){ + (void)_of; + _nsamples=OP_MIN(_nsamples,_dst_sz>>1); + if(_nchannels==2)memcpy(_dst,_src,_nsamples*2*sizeof(*_src)); + else{ + float *dst; + int i; + dst=(float *)_dst; + if(_nchannels==1){ + for(i=0;i<_nsamples;i++)dst[2*i+0]=dst[2*i+1]=_src[i]; + } + else{ + for(i=0;i<_nsamples;i++){ + float l; + float r; + int ci; + l=r=0; + for(ci=0;ci<_nchannels;ci++){ + l+=OP_STEREO_DOWNMIX[_nchannels-3][ci][0]*_src[_nchannels*i+ci]; + r+=OP_STEREO_DOWNMIX[_nchannels-3][ci][1]*_src[_nchannels*i+ci]; + } + dst[2*i+0]=l; + dst[2*i+1]=r; + } + } + } + return _nsamples; +} + +static int op_float2short_stereo_filter(OggOpusFile *_of, + void *_dst,int _dst_sz,op_sample *_src,int _nsamples,int _nchannels){ + opus_int16 *dst; + dst=(opus_int16 *)_dst; + if(_nchannels==1){ + int i; + _nsamples=op_float2short_filter(_of,dst,_dst_sz>>1,_src,_nsamples,1); + for(i=_nsamples;i-->0;)dst[2*i+0]=dst[2*i+1]=dst[i]; + } + else{ + if(_nchannels>2){ + _nsamples=OP_MIN(_nsamples,_dst_sz>>1); + _nsamples=op_stereo_filter(_of,_src,_nsamples*2, + _src,_nsamples,_nchannels); + } + _nsamples=op_float2short_filter(_of,dst,_dst_sz,_src,_nsamples,2); + } + return _nsamples; +} + +int op_read_stereo(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size){ + return op_filter_read_native(_of,_pcm,_buf_size, + op_float2short_stereo_filter,NULL); +} + +int op_read_float_stereo(OggOpusFile *_of,float *_pcm,int _buf_size){ + _of->state_channel_count=0; + return op_filter_read_native(_of,_pcm,_buf_size,op_stereo_filter,NULL); +} + +#endif diff --git a/thirdparty/opus/opusfile.h b/thirdparty/opus/opusfile.h new file mode 100644 index 0000000000..3604115c31 --- /dev/null +++ b/thirdparty/opus/opusfile.h @@ -0,0 +1,2148 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: stdio-based convenience library for opening/seeking/decoding + last mod: $Id: vorbisfile.h 17182 2010-04-29 03:48:32Z xiphmont $ + + ********************************************************************/ +#if !defined(_opusfile_h) +# define _opusfile_h (1) + +/**\mainpage + \section Introduction + + This is the documentation for the <tt>libopusfile</tt> C API. + + The <tt>libopusfile</tt> package provides a convenient high-level API for + decoding and basic manipulation of all Ogg Opus audio streams. + <tt>libopusfile</tt> is implemented as a layer on top of Xiph.Org's + reference + <tt><a href="https://www.xiph.org/ogg/doc/libogg/reference.html">libogg</a></tt> + and + <tt><a href="https://mf4.xiph.org/jenkins/view/opus/job/opus/ws/doc/html/index.html">libopus</a></tt> + libraries. + + <tt>libopusfile</tt> provides several sets of built-in routines for + file/stream access, and may also use custom stream I/O routines provided by + the embedded environment. + There are built-in I/O routines provided for ANSI-compliant + <code>stdio</code> (<code>FILE *</code>), memory buffers, and URLs + (including <file:> URLs, plus optionally <http:> and <https:> URLs). + + \section Organization + + The main API is divided into several sections: + - \ref stream_open_close + - \ref stream_info + - \ref stream_decoding + - \ref stream_seeking + + Several additional sections are not tied to the main API. + - \ref stream_callbacks + - \ref header_info + - \ref error_codes + + \section Overview + + The <tt>libopusfile</tt> API always decodes files to 48 kHz. + The original sample rate is not preserved by the lossy compression, though + it is stored in the header to allow you to resample to it after decoding + (the <tt>libopusfile</tt> API does not currently provide a resampler, + but the + <a href="http://www.speex.org/docs/manual/speex-manual/node7.html#SECTION00760000000000000000">the + Speex resampler</a> is a good choice if you need one). + In general, if you are playing back the audio, you should leave it at + 48 kHz, provided your audio hardware supports it. + When decoding to a file, it may be worth resampling back to the original + sample rate, so as not to surprise users who might not expect the sample + rate to change after encoding to Opus and decoding. + + Opus files can contain anywhere from 1 to 255 channels of audio. + The channel mappings for up to 8 channels are the same as the + <a href="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">Vorbis + mappings</a>. + A special stereo API can convert everything to 2 channels, making it simple + to support multichannel files in an application which only has stereo + output. + Although the <tt>libopusfile</tt> ABI provides support for the theoretical + maximum number of channels, the current implementation does not support + files with more than 8 channels, as they do not have well-defined channel + mappings. + + Like all Ogg files, Opus files may be "chained". + That is, multiple Opus files may be combined into a single, longer file just + by concatenating the original files. + This is commonly done in internet radio streaming, as it allows the title + and artist to be updated each time the song changes, since each link in the + chain includes its own set of metadata. + + <tt>libopusfile</tt> fully supports chained files. + It will decode the first Opus stream found in each link of a chained file + (ignoring any other streams that might be concurrently multiplexed with it, + such as a video stream). + + The channel count can also change between links. + If your application is not prepared to deal with this, it can use the stereo + API to ensure the audio from all links will always get decoded into a + common format. + Since <tt>libopusfile</tt> always decodes to 48 kHz, you do not have to + worry about the sample rate changing between links (as was possible with + Vorbis). + This makes application support for chained files with <tt>libopusfile</tt> + very easy.*/ + +# if defined(__cplusplus) +extern "C" { +# endif + +# include <stdarg.h> +# include <stdio.h> +# include <ogg/ogg.h> +# include <opus_multistream.h> + +/**@cond PRIVATE*/ + +/*Enable special features for gcc and gcc-compatible compilers.*/ +# if !defined(OP_GNUC_PREREQ) +# if defined(__GNUC__)&&defined(__GNUC_MINOR__) +# define OP_GNUC_PREREQ(_maj,_min) \ + ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) +# else +# define OP_GNUC_PREREQ(_maj,_min) 0 +# endif +# endif + +# if OP_GNUC_PREREQ(4,0) +# pragma GCC visibility push(default) +# endif + +typedef struct OpusHead OpusHead; +typedef struct OpusTags OpusTags; +typedef struct OpusPictureTag OpusPictureTag; +typedef struct OpusServerInfo OpusServerInfo; +typedef struct OpusFileCallbacks OpusFileCallbacks; +typedef struct OggOpusFile OggOpusFile; + +/*Warning attributes for libopusfile functions.*/ +# if OP_GNUC_PREREQ(3,4) +# define OP_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) +# else +# define OP_WARN_UNUSED_RESULT +# endif +# if OP_GNUC_PREREQ(3,4) +# define OP_ARG_NONNULL(_x) __attribute__((__nonnull__(_x))) +# else +# define OP_ARG_NONNULL(_x) +# endif + +/**@endcond*/ + +/**\defgroup error_codes Error Codes*/ +/*@{*/ +/**\name List of possible error codes + Many of the functions in this library return a negative error code when a + function fails. + This list provides a brief explanation of the common errors. + See each individual function for more details on what a specific error code + means in that context.*/ +/*@{*/ + +/**A request did not succeed.*/ +#define OP_FALSE (-1) +/*Currently not used externally.*/ +#define OP_EOF (-2) +/**There was a hole in the page sequence numbers (e.g., a page was corrupt or + missing).*/ +#define OP_HOLE (-3) +/**An underlying read, seek, or tell operation failed when it should have + succeeded.*/ +#define OP_EREAD (-128) +/**A <code>NULL</code> pointer was passed where one was unexpected, or an + internal memory allocation failed, or an internal library error was + encountered.*/ +#define OP_EFAULT (-129) +/**The stream used a feature that is not implemented, such as an unsupported + channel family.*/ +#define OP_EIMPL (-130) +/**One or more parameters to a function were invalid.*/ +#define OP_EINVAL (-131) +/**A purported Ogg Opus stream did not begin with an Ogg page, a purported + header packet did not start with one of the required strings, "OpusHead" or + "OpusTags", or a link in a chained file was encountered that did not + contain any logical Opus streams.*/ +#define OP_ENOTFORMAT (-132) +/**A required header packet was not properly formatted, contained illegal + values, or was missing altogether.*/ +#define OP_EBADHEADER (-133) +/**The ID header contained an unrecognized version number.*/ +#define OP_EVERSION (-134) +/*Currently not used at all.*/ +#define OP_ENOTAUDIO (-135) +/**An audio packet failed to decode properly. + This is usually caused by a multistream Ogg packet where the durations of + the individual Opus packets contained in it are not all the same.*/ +#define OP_EBADPACKET (-136) +/**We failed to find data we had seen before, or the bitstream structure was + sufficiently malformed that seeking to the target destination was + impossible.*/ +#define OP_EBADLINK (-137) +/**An operation that requires seeking was requested on an unseekable stream.*/ +#define OP_ENOSEEK (-138) +/**The first or last granule position of a link failed basic validity checks.*/ +#define OP_EBADTIMESTAMP (-139) + +/*@}*/ +/*@}*/ + +/**\defgroup header_info Header Information*/ +/*@{*/ + +/**The maximum number of channels in an Ogg Opus stream.*/ +#define OPUS_CHANNEL_COUNT_MAX (255) + +/**Ogg Opus bitstream information. + This contains the basic playback parameters for a stream, and corresponds to + the initial ID header packet of an Ogg Opus stream.*/ +struct OpusHead{ + /**The Ogg Opus format version, in the range 0...255. + The top 4 bits represent a "major" version, and the bottom four bits + represent backwards-compatible "minor" revisions. + The current specification describes version 1. + This library will recognize versions up through 15 as backwards compatible + with the current specification. + An earlier draft of the specification described a version 0, but the only + difference between version 1 and version 0 is that version 0 did + not specify the semantics for handling the version field.*/ + int version; + /**The number of channels, in the range 1...255.*/ + int channel_count; + /**The number of samples that should be discarded from the beginning of the + stream.*/ + unsigned pre_skip; + /**The sampling rate of the original input. + All Opus audio is coded at 48 kHz, and should also be decoded at 48 kHz + for playback (unless the target hardware does not support this sampling + rate). + However, this field may be used to resample the audio back to the original + sampling rate, for example, when saving the output to a file.*/ + opus_uint32 input_sample_rate; + /**The gain to apply to the decoded output, in dB, as a Q8 value in the range + -32768...32767. + The <tt>libopusfile</tt> API will automatically apply this gain to the + decoded output before returning it, scaling it by + <code>pow(10,output_gain/(20.0*256))</code>.*/ + int output_gain; + /**The channel mapping family, in the range 0...255. + Channel mapping family 0 covers mono or stereo in a single stream. + Channel mapping family 1 covers 1 to 8 channels in one or more streams, + using the Vorbis speaker assignments. + Channel mapping family 255 covers 1 to 255 channels in one or more + streams, but without any defined speaker assignment.*/ + int mapping_family; + /**The number of Opus streams in each Ogg packet, in the range 1...255.*/ + int stream_count; + /**The number of coupled Opus streams in each Ogg packet, in the range + 0...127. + This must satisfy <code>0 <= coupled_count <= stream_count</code> and + <code>coupled_count + stream_count <= 255</code>. + The coupled streams appear first, before all uncoupled streams, in an Ogg + Opus packet.*/ + int coupled_count; + /**The mapping from coded stream channels to output channels. + Let <code>index=mapping[k]</code> be the value for channel <code>k</code>. + If <code>index<2*coupled_count</code>, then it refers to the left channel + from stream <code>(index/2)</code> if even, and the right channel from + stream <code>(index/2)</code> if odd. + Otherwise, it refers to the output of the uncoupled stream + <code>(index-coupled_count)</code>.*/ + unsigned char mapping[OPUS_CHANNEL_COUNT_MAX]; +}; + +/**The metadata from an Ogg Opus stream. + + This structure holds the in-stream metadata corresponding to the 'comment' + header packet of an Ogg Opus stream. + The comment header is meant to be used much like someone jotting a quick + note on the label of a CD. + It should be a short, to the point text note that can be more than a couple + words, but not more than a short paragraph. + + The metadata is stored as a series of (tag, value) pairs, in length-encoded + string vectors, using the same format as Vorbis (without the final "framing + bit"), Theora, and Speex, except for the packet header. + The first occurrence of the '=' character delimits the tag and value. + A particular tag may occur more than once, and order is significant. + The character set encoding for the strings is always UTF-8, but the tag + names are limited to ASCII, and treated as case-insensitive. + See <a href="http://www.xiph.org/vorbis/doc/v-comment.html">the Vorbis + comment header specification</a> for details. + + In filling in this structure, <tt>libopusfile</tt> will null-terminate the + #user_comments strings for safety. + However, the bitstream format itself treats them as 8-bit clean vectors, + possibly containing NUL characters, so the #comment_lengths array should be + treated as their authoritative length. + + This structure is binary and source-compatible with a + <code>vorbis_comment</code>, and pointers to it may be freely cast to + <code>vorbis_comment</code> pointers, and vice versa. + It is provided as a separate type to avoid introducing a compile-time + dependency on the libvorbis headers.*/ +struct OpusTags{ + /**The array of comment string vectors.*/ + char **user_comments; + /**An array of the corresponding length of each vector, in bytes.*/ + int *comment_lengths; + /**The total number of comment streams.*/ + int comments; + /**The null-terminated vendor string. + This identifies the software used to encode the stream.*/ + char *vendor; +}; + +/**\name Picture tag image formats*/ +/*@{*/ + +/**The MIME type was not recognized, or the image data did not match the + declared MIME type.*/ +#define OP_PIC_FORMAT_UNKNOWN (-1) +/**The MIME type indicates the image data is really a URL.*/ +#define OP_PIC_FORMAT_URL (0) +/**The image is a JPEG.*/ +#define OP_PIC_FORMAT_JPEG (1) +/**The image is a PNG.*/ +#define OP_PIC_FORMAT_PNG (2) +/**The image is a GIF.*/ +#define OP_PIC_FORMAT_GIF (3) + +/*@}*/ + +/**The contents of a METADATA_BLOCK_PICTURE tag.*/ +struct OpusPictureTag{ + /**The picture type according to the ID3v2 APIC frame: + <ol start="0"> + <li>Other</li> + <li>32x32 pixels 'file icon' (PNG only)</li> + <li>Other file icon</li> + <li>Cover (front)</li> + <li>Cover (back)</li> + <li>Leaflet page</li> + <li>Media (e.g. label side of CD)</li> + <li>Lead artist/lead performer/soloist</li> + <li>Artist/performer</li> + <li>Conductor</li> + <li>Band/Orchestra</li> + <li>Composer</li> + <li>Lyricist/text writer</li> + <li>Recording Location</li> + <li>During recording</li> + <li>During performance</li> + <li>Movie/video screen capture</li> + <li>A bright colored fish</li> + <li>Illustration</li> + <li>Band/artist logotype</li> + <li>Publisher/Studio logotype</li> + </ol> + Others are reserved and should not be used. + There may only be one each of picture type 1 and 2 in a file.*/ + opus_int32 type; + /**The MIME type of the picture, in printable ASCII characters 0x20-0x7E. + The MIME type may also be <code>"-->"</code> to signify that the data part + is a URL pointing to the picture instead of the picture data itself. + In this case, a terminating NUL is appended to the URL string in #data, + but #data_length is set to the length of the string excluding that + terminating NUL.*/ + char *mime_type; + /**The description of the picture, in UTF-8.*/ + char *description; + /**The width of the picture in pixels.*/ + opus_uint32 width; + /**The height of the picture in pixels.*/ + opus_uint32 height; + /**The color depth of the picture in bits-per-pixel (<em>not</em> + bits-per-channel).*/ + opus_uint32 depth; + /**For indexed-color pictures (e.g., GIF), the number of colors used, or 0 + for non-indexed pictures.*/ + opus_uint32 colors; + /**The length of the picture data in bytes.*/ + opus_uint32 data_length; + /**The binary picture data.*/ + unsigned char *data; + /**The format of the picture data, if known. + One of + <ul> + <li>#OP_PIC_FORMAT_UNKNOWN,</li> + <li>#OP_PIC_FORMAT_URL,</li> + <li>#OP_PIC_FORMAT_JPEG,</li> + <li>#OP_PIC_FORMAT_PNG, or</li> + <li>#OP_PIC_FORMAT_GIF.</li> + </ul>*/ + int format; +}; + +/**\name Functions for manipulating header data + + These functions manipulate the #OpusHead and #OpusTags structures, + which describe the audio parameters and tag-value metadata, respectively. + These can be used to query the headers returned by <tt>libopusfile</tt>, or + to parse Opus headers from sources other than an Ogg Opus stream, provided + they use the same format.*/ +/*@{*/ + +/**Parses the contents of the ID header packet of an Ogg Opus stream. + \param[out] _head Returns the contents of the parsed packet. + The contents of this structure are untouched on error. + This may be <code>NULL</code> to merely test the header + for validity. + \param[in] _data The contents of the ID header packet. + \param _len The number of bytes of data in the ID header packet. + \return 0 on success or a negative value on error. + \retval #OP_ENOTFORMAT If the data does not start with the "OpusHead" + string. + \retval #OP_EVERSION If the version field signaled a version this library + does not know how to parse. + \retval #OP_EIMPL If the channel mapping family was 255, which general + purpose players should not attempt to play. + \retval #OP_EBADHEADER If the contents of the packet otherwise violate the + Ogg Opus specification: + <ul> + <li>Insufficient data,</li> + <li>Too much data for the known minor versions,</li> + <li>An unrecognized channel mapping family,</li> + <li>Zero channels or too many channels,</li> + <li>Zero coded streams,</li> + <li>Too many coupled streams, or</li> + <li>An invalid channel mapping index.</li> + </ul>*/ +OP_WARN_UNUSED_RESULT int opus_head_parse(OpusHead *_head, + const unsigned char *_data,size_t _len) OP_ARG_NONNULL(2); + +/**Converts a granule position to a sample offset for a given Ogg Opus stream. + The sample offset is simply <code>_gp-_head->pre_skip</code>. + Granule position values smaller than OpusHead#pre_skip correspond to audio + that should never be played, and thus have no associated sample offset. + This function returns -1 for such values. + This function also correctly handles extremely large granule positions, + which may have wrapped around to a negative number when stored in a signed + ogg_int64_t value. + \param _head The #OpusHead information from the ID header of the stream. + \param _gp The granule position to convert. + \return The sample offset associated with the given granule position + (counting at a 48 kHz sampling rate), or the special value -1 on + error (i.e., the granule position was smaller than the pre-skip + amount).*/ +ogg_int64_t opus_granule_sample(const OpusHead *_head,ogg_int64_t _gp) + OP_ARG_NONNULL(1); + +/**Parses the contents of the 'comment' header packet of an Ogg Opus stream. + \param[out] _tags An uninitialized #OpusTags structure. + This returns the contents of the parsed packet. + The contents of this structure are untouched on error. + This may be <code>NULL</code> to merely test the header + for validity. + \param[in] _data The contents of the 'comment' header packet. + \param _len The number of bytes of data in the 'info' header packet. + \retval 0 Success. + \retval #OP_ENOTFORMAT If the data does not start with the "OpusTags" + string. + \retval #OP_EBADHEADER If the contents of the packet otherwise violate the + Ogg Opus specification. + \retval #OP_EFAULT If there wasn't enough memory to store the tags.*/ +OP_WARN_UNUSED_RESULT int opus_tags_parse(OpusTags *_tags, + const unsigned char *_data,size_t _len) OP_ARG_NONNULL(2); + +/**Performs a deep copy of an #OpusTags structure. + \param _dst The #OpusTags structure to copy into. + If this function fails, the contents of this structure remain + untouched. + \param _src The #OpusTags structure to copy from. + \retval 0 Success. + \retval #OP_EFAULT If there wasn't enough memory to copy the tags.*/ +int opus_tags_copy(OpusTags *_dst,const OpusTags *_src) OP_ARG_NONNULL(1); + +/**Initializes an #OpusTags structure. + This should be called on a freshly allocated #OpusTags structure before + attempting to use it. + \param _tags The #OpusTags structure to initialize.*/ +void opus_tags_init(OpusTags *_tags) OP_ARG_NONNULL(1); + +/**Add a (tag, value) pair to an initialized #OpusTags structure. + \note Neither opus_tags_add() nor opus_tags_add_comment() support values + containing embedded NULs, although the bitstream format does support them. + To add such tags, you will need to manipulate the #OpusTags structure + directly. + \param _tags The #OpusTags structure to add the (tag, value) pair to. + \param _tag A NUL-terminated, case-insensitive, ASCII string containing + the tag to add (without an '=' character). + \param _value A NUL-terminated UTF-8 containing the corresponding value. + \return 0 on success, or a negative value on failure. + \retval #OP_EFAULT An internal memory allocation failed.*/ +int opus_tags_add(OpusTags *_tags,const char *_tag,const char *_value) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2) OP_ARG_NONNULL(3); + +/**Add a comment to an initialized #OpusTags structure. + \note Neither opus_tags_add_comment() nor opus_tags_add() support comments + containing embedded NULs, although the bitstream format does support them. + To add such tags, you will need to manipulate the #OpusTags structure + directly. + \param _tags The #OpusTags structure to add the comment to. + \param _comment A NUL-terminated UTF-8 string containing the comment in + "TAG=value" form. + \return 0 on success, or a negative value on failure. + \retval #OP_EFAULT An internal memory allocation failed.*/ +int opus_tags_add_comment(OpusTags *_tags,const char *_comment) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Replace the binary suffix data at the end of the packet (if any). + \param _tags An initialized #OpusTags structure. + \param _data A buffer of binary data to append after the encoded user + comments. + The least significant bit of the first byte of this data must + be set (to ensure the data is preserved by other editors). + \param _len The number of bytes of binary data to append. + This may be zero to remove any existing binary suffix data. + \return 0 on success, or a negative value on error. + \retval #OP_EINVAL \a _len was negative, or \a _len was positive but + \a _data was <code>NULL</code> or the least significant + bit of the first byte was not set. + \retval #OP_EFAULT An internal memory allocation failed.*/ +int opus_tags_set_binary_suffix(OpusTags *_tags, + const unsigned char *_data,int _len) OP_ARG_NONNULL(1); + +/**Look up a comment value by its tag. + \param _tags An initialized #OpusTags structure. + \param _tag The tag to look up. + \param _count The instance of the tag. + The same tag can appear multiple times, each with a distinct + value, so an index is required to retrieve them all. + The order in which these values appear is significant and + should be preserved. + Use opus_tags_query_count() to get the legal range for the + \a _count parameter. + \return A pointer to the queried tag's value. + This points directly to data in the #OpusTags structure. + It should not be modified or freed by the application, and + modifications to the structure may invalidate the pointer. + \retval NULL If no matching tag is found.*/ +const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Look up the number of instances of a tag. + Call this first when querying for a specific tag and then iterate over the + number of instances with separate calls to opus_tags_query() to retrieve + all the values for that tag in order. + \param _tags An initialized #OpusTags structure. + \param _tag The tag to look up. + \return The number of instances of this particular tag.*/ +int opus_tags_query_count(const OpusTags *_tags,const char *_tag) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Retrieve the binary suffix data at the end of the packet (if any). + \param _tags An initialized #OpusTags structure. + \param[out] _len Returns the number of bytes of binary suffix data returned. + \return A pointer to the binary suffix data, or <code>NULL</code> if none + was present.*/ +const unsigned char *opus_tags_get_binary_suffix(const OpusTags *_tags, + int *_len) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Get the album gain from an R128_ALBUM_GAIN tag, if one was specified. + This searches for the first R128_ALBUM_GAIN tag with a valid signed, + 16-bit decimal integer value and returns the value. + This routine is exposed merely for convenience for applications which wish + to do something special with the album gain (i.e., display it). + If you simply wish to apply the album gain instead of the header gain, you + can use op_set_gain_offset() with an #OP_ALBUM_GAIN type and no offset. + \param _tags An initialized #OpusTags structure. + \param[out] _gain_q8 The album gain, in 1/256ths of a dB. + This will lie in the range [-32768,32767], and should + be applied in <em>addition</em> to the header gain. + On error, no value is returned, and the previous + contents remain unchanged. + \return 0 on success, or a negative value on error. + \retval #OP_FALSE There was no album gain available in the given tags.*/ +int opus_tags_get_album_gain(const OpusTags *_tags,int *_gain_q8) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Get the track gain from an R128_TRACK_GAIN tag, if one was specified. + This searches for the first R128_TRACK_GAIN tag with a valid signed, + 16-bit decimal integer value and returns the value. + This routine is exposed merely for convenience for applications which wish + to do something special with the track gain (i.e., display it). + If you simply wish to apply the track gain instead of the header gain, you + can use op_set_gain_offset() with an #OP_TRACK_GAIN type and no offset. + \param _tags An initialized #OpusTags structure. + \param[out] _gain_q8 The track gain, in 1/256ths of a dB. + This will lie in the range [-32768,32767], and should + be applied in <em>addition</em> to the header gain. + On error, no value is returned, and the previous + contents remain unchanged. + \return 0 on success, or a negative value on error. + \retval #OP_FALSE There was no track gain available in the given tags.*/ +int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Clears the #OpusTags structure. + This should be called on an #OpusTags structure after it is no longer + needed. + It will free all memory used by the structure members. + \param _tags The #OpusTags structure to clear.*/ +void opus_tags_clear(OpusTags *_tags) OP_ARG_NONNULL(1); + +/**Check if \a _comment is an instance of a \a _tag_name tag. + \see opus_tagncompare + \param _tag_name A NUL-terminated, case-insensitive, ASCII string containing + the name of the tag to check for (without the terminating + '=' character). + \param _comment The comment string to check. + \return An integer less than, equal to, or greater than zero if \a _comment + is found respectively, to be less than, to match, or be greater + than a "tag=value" string whose tag matches \a _tag_name.*/ +int opus_tagcompare(const char *_tag_name,const char *_comment); + +/**Check if \a _comment is an instance of a \a _tag_name tag. + This version is slightly more efficient than opus_tagcompare() if the length + of the tag name is already known (e.g., because it is a constant). + \see opus_tagcompare + \param _tag_name A case-insensitive ASCII string containing the name of the + tag to check for (without the terminating '=' character). + \param _tag_len The number of characters in the tag name. + This must be non-negative. + \param _comment The comment string to check. + \return An integer less than, equal to, or greater than zero if \a _comment + is found respectively, to be less than, to match, or be greater + than a "tag=value" string whose tag matches the first \a _tag_len + characters of \a _tag_name.*/ +int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment); + +/**Parse a single METADATA_BLOCK_PICTURE tag. + This decodes the BASE64-encoded content of the tag and returns a structure + with the MIME type, description, image parameters (if known), and the + compressed image data. + If the MIME type indicates the presence of an image format we recognize + (JPEG, PNG, or GIF) and the actual image data contains the magic signature + associated with that format, then the OpusPictureTag::format field will be + set to the corresponding format. + This is provided as a convenience to avoid requiring applications to parse + the MIME type and/or do their own format detection for the commonly used + formats. + In this case, we also attempt to extract the image parameters directly from + the image data (overriding any that were present in the tag, which the + specification says applications are not meant to rely on). + The application must still provide its own support for actually decoding the + image data and, if applicable, retrieving that data from URLs. + \param[out] _pic Returns the parsed picture data. + No sanitation is done on the type, MIME type, or + description fields, so these might return invalid values. + The contents of this structure are left unmodified on + failure. + \param _tag The METADATA_BLOCK_PICTURE tag contents. + The leading "METADATA_BLOCK_PICTURE=" portion is optional, + to allow the function to be used on either directly on the + values in OpusTags::user_comments or on the return value + of opus_tags_query(). + \return 0 on success or a negative value on error. + \retval #OP_ENOTFORMAT The METADATA_BLOCK_PICTURE contents were not valid. + \retval #OP_EFAULT There was not enough memory to store the picture tag + contents.*/ +OP_WARN_UNUSED_RESULT int opus_picture_tag_parse(OpusPictureTag *_pic, + const char *_tag) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Initializes an #OpusPictureTag structure. + This should be called on a freshly allocated #OpusPictureTag structure + before attempting to use it. + \param _pic The #OpusPictureTag structure to initialize.*/ +void opus_picture_tag_init(OpusPictureTag *_pic) OP_ARG_NONNULL(1); + +/**Clears the #OpusPictureTag structure. + This should be called on an #OpusPictureTag structure after it is no longer + needed. + It will free all memory used by the structure members. + \param _pic The #OpusPictureTag structure to clear.*/ +void opus_picture_tag_clear(OpusPictureTag *_pic) OP_ARG_NONNULL(1); + +/*@}*/ + +/*@}*/ + +/**\defgroup url_options URL Reading Options*/ +/*@{*/ +/**\name URL reading options + Options for op_url_stream_create() and associated functions. + These allow you to provide proxy configuration parameters, skip SSL + certificate checks, etc. + Options are processed in order, and if the same option is passed multiple + times, only the value specified by the last occurrence has an effect + (unless otherwise specified). + They may be expanded in the future.*/ +/*@{*/ + +/**@cond PRIVATE*/ + +/*These are the raw numbers used to define the request codes. + They should not be used directly.*/ +#define OP_SSL_SKIP_CERTIFICATE_CHECK_REQUEST (6464) +#define OP_HTTP_PROXY_HOST_REQUEST (6528) +#define OP_HTTP_PROXY_PORT_REQUEST (6592) +#define OP_HTTP_PROXY_USER_REQUEST (6656) +#define OP_HTTP_PROXY_PASS_REQUEST (6720) +#define OP_GET_SERVER_INFO_REQUEST (6784) + +#define OP_URL_OPT(_request) ((_request)+(char *)0) + +/*These macros trigger compilation errors or warnings if the wrong types are + provided to one of the URL options.*/ +#define OP_CHECK_INT(_x) ((void)((_x)==(opus_int32)0),(opus_int32)(_x)) +#define OP_CHECK_CONST_CHAR_PTR(_x) ((_x)+((_x)-(const char *)(_x))) +#define OP_CHECK_SERVER_INFO_PTR(_x) ((_x)+((_x)-(OpusServerInfo *)(_x))) + +/**@endcond*/ + +/**HTTP/Shoutcast/Icecast server information associated with a URL.*/ +struct OpusServerInfo{ + /**The name of the server (icy-name/ice-name). + This is <code>NULL</code> if there was no <code>icy-name</code> or + <code>ice-name</code> header.*/ + char *name; + /**A short description of the server (icy-description/ice-description). + This is <code>NULL</code> if there was no <code>icy-description</code> or + <code>ice-description</code> header.*/ + char *description; + /**The genre the server falls under (icy-genre/ice-genre). + This is <code>NULL</code> if there was no <code>icy-genre</code> or + <code>ice-genre</code> header.*/ + char *genre; + /**The homepage for the server (icy-url/ice-url). + This is <code>NULL</code> if there was no <code>icy-url</code> or + <code>ice-url</code> header.*/ + char *url; + /**The software used by the origin server (Server). + This is <code>NULL</code> if there was no <code>Server</code> header.*/ + char *server; + /**The media type of the entity sent to the recepient (Content-Type). + This is <code>NULL</code> if there was no <code>Content-Type</code> + header.*/ + char *content_type; + /**The nominal stream bitrate in kbps (icy-br/ice-bitrate). + This is <code>-1</code> if there was no <code>icy-br</code> or + <code>ice-bitrate</code> header.*/ + opus_int32 bitrate_kbps; + /**Flag indicating whether the server is public (<code>1</code>) or not + (<code>0</code>) (icy-pub/ice-public). + This is <code>-1</code> if there was no <code>icy-pub</code> or + <code>ice-public</code> header.*/ + int is_public; + /**Flag indicating whether the server is using HTTPS instead of HTTP. + This is <code>0</code> unless HTTPS is being used. + This may not match the protocol used in the original URL if there were + redirections.*/ + int is_ssl; +}; + +/**Initializes an #OpusServerInfo structure. + All fields are set as if the corresponding header was not available. + \param _info The #OpusServerInfo structure to initialize. + \note If you use this function, you must link against <tt>libopusurl</tt>.*/ +void opus_server_info_init(OpusServerInfo *_info) OP_ARG_NONNULL(1); + +/**Clears the #OpusServerInfo structure. + This should be called on an #OpusServerInfo structure after it is no longer + needed. + It will free all memory used by the structure members. + \param _info The #OpusServerInfo structure to clear. + \note If you use this function, you must link against <tt>libopusurl</tt>.*/ +void opus_server_info_clear(OpusServerInfo *_info) OP_ARG_NONNULL(1); + +/**Skip the certificate check when connecting via TLS/SSL (https). + \param _b <code>opus_int32</code>: Whether or not to skip the certificate + check. + The check will be skipped if \a _b is non-zero, and will not be + skipped if \a _b is zero. + \hideinitializer*/ +#define OP_SSL_SKIP_CERTIFICATE_CHECK(_b) \ + OP_URL_OPT(OP_SSL_SKIP_CERTIFICATE_CHECK_REQUEST),OP_CHECK_INT(_b) + +/**Proxy connections through the given host. + If no port is specified via #OP_HTTP_PROXY_PORT, the port number defaults + to 8080 (http-alt). + All proxy parameters are ignored for non-http and non-https URLs. + \param _host <code>const char *</code>: The proxy server hostname. + This may be <code>NULL</code> to disable the use of a proxy + server. + \hideinitializer*/ +#define OP_HTTP_PROXY_HOST(_host) \ + OP_URL_OPT(OP_HTTP_PROXY_HOST_REQUEST),OP_CHECK_CONST_CHAR_PTR(_host) + +/**Use the given port when proxying connections. + This option only has an effect if #OP_HTTP_PROXY_HOST is specified with a + non-<code>NULL</code> \a _host. + If this option is not provided, the proxy port number defaults to 8080 + (http-alt). + All proxy parameters are ignored for non-http and non-https URLs. + \param _port <code>opus_int32</code>: The proxy server port. + This must be in the range 0...65535 (inclusive), or the + URL function this is passed to will fail. + \hideinitializer*/ +#define OP_HTTP_PROXY_PORT(_port) \ + OP_URL_OPT(OP_HTTP_PROXY_PORT_REQUEST),OP_CHECK_INT(_port) + +/**Use the given user name for authentication when proxying connections. + All proxy parameters are ignored for non-http and non-https URLs. + \param _user const char *: The proxy server user name. + This may be <code>NULL</code> to disable proxy + authentication. + A non-<code>NULL</code> value only has an effect + if #OP_HTTP_PROXY_HOST and #OP_HTTP_PROXY_PASS + are also specified with non-<code>NULL</code> + arguments. + \hideinitializer*/ +#define OP_HTTP_PROXY_USER(_user) \ + OP_URL_OPT(OP_HTTP_PROXY_USER_REQUEST),OP_CHECK_CONST_CHAR_PTR(_user) + +/**Use the given password for authentication when proxying connections. + All proxy parameters are ignored for non-http and non-https URLs. + \param _pass const char *: The proxy server password. + This may be <code>NULL</code> to disable proxy + authentication. + A non-<code>NULL</code> value only has an effect + if #OP_HTTP_PROXY_HOST and #OP_HTTP_PROXY_USER + are also specified with non-<code>NULL</code> + arguments. + \hideinitializer*/ +#define OP_HTTP_PROXY_PASS(_pass) \ + OP_URL_OPT(OP_HTTP_PROXY_PASS_REQUEST),OP_CHECK_CONST_CHAR_PTR(_pass) + +/**Parse information about the streaming server (if any) and return it. + Very little validation is done. + In particular, OpusServerInfo::url may not be a valid URL, + OpusServerInfo::bitrate_kbps may not really be in kbps, and + OpusServerInfo::content_type may not be a valid MIME type. + The character set of the string fields is not specified anywhere, and should + not be assumed to be valid UTF-8. + \param _info OpusServerInfo *: Returns information about the server. + If there is any error opening the stream, the + contents of this structure remain + unmodified. + On success, fills in the structure with the + server information that was available, if + any. + After a successful return, the contents of + this structure should be freed by calling + opus_server_info_clear(). + \hideinitializer*/ +#define OP_GET_SERVER_INFO(_info) \ + OP_URL_OPT(OP_GET_SERVER_INFO_REQUEST),OP_CHECK_SERVER_INFO_PTR(_info) + +/*@}*/ +/*@}*/ + +/**\defgroup stream_callbacks Abstract Stream Reading Interface*/ +/*@{*/ +/**\name Functions for reading from streams + These functions define the interface used to read from and seek in a stream + of data. + A stream does not need to implement seeking, but the decoder will not be + able to seek if it does not do so. + These functions also include some convenience routines for working with + standard <code>FILE</code> pointers, complete streams stored in a single + block of memory, or URLs.*/ +/*@{*/ + +/**Reads up to \a _nbytes bytes of data from \a _stream. + \param _stream The stream to read from. + \param[out] _ptr The buffer to store the data in. + \param _nbytes The maximum number of bytes to read. + This function may return fewer, though it will not + return zero unless it reaches end-of-file. + \return The number of bytes successfully read, or a negative value on + error.*/ +typedef int (*op_read_func)(void *_stream,unsigned char *_ptr,int _nbytes); + +/**Sets the position indicator for \a _stream. + The new position, measured in bytes, is obtained by adding \a _offset + bytes to the position specified by \a _whence. + If \a _whence is set to <code>SEEK_SET</code>, <code>SEEK_CUR</code>, or + <code>SEEK_END</code>, the offset is relative to the start of the stream, + the current position indicator, or end-of-file, respectively. + \retval 0 Success. + \retval -1 Seeking is not supported or an error occurred. + <code>errno</code> need not be set.*/ +typedef int (*op_seek_func)(void *_stream,opus_int64 _offset,int _whence); + +/**Obtains the current value of the position indicator for \a _stream. + \return The current position indicator.*/ +typedef opus_int64 (*op_tell_func)(void *_stream); + +/**Closes the underlying stream. + \retval 0 Success. + \retval EOF An error occurred. + <code>errno</code> need not be set.*/ +typedef int (*op_close_func)(void *_stream); + +/**The callbacks used to access non-<code>FILE</code> stream resources. + The function prototypes are basically the same as for the stdio functions + <code>fread()</code>, <code>fseek()</code>, <code>ftell()</code>, and + <code>fclose()</code>. + The differences are that the <code>FILE *</code> arguments have been + replaced with a <code>void *</code>, which is to be used as a pointer to + whatever internal data these functions might need, that #seek and #tell + take and return 64-bit offsets, and that #seek <em>must</em> return -1 if + the stream is unseekable.*/ +struct OpusFileCallbacks{ + /**Used to read data from the stream. + This must not be <code>NULL</code>.*/ + op_read_func read; + /**Used to seek in the stream. + This may be <code>NULL</code> if seeking is not implemented.*/ + op_seek_func seek; + /**Used to return the current read position in the stream. + This may be <code>NULL</code> if seeking is not implemented.*/ + op_tell_func tell; + /**Used to close the stream when the decoder is freed. + This may be <code>NULL</code> to leave the stream open.*/ + op_close_func close; +}; + +/**Opens a stream with <code>fopen()</code> and fills in a set of callbacks + that can be used to access it. + This is useful to avoid writing your own portable 64-bit seeking wrappers, + and also avoids cross-module linking issues on Windows, where a + <code>FILE *</code> must be accessed by routines defined in the same module + that opened it. + \param[out] _cb The callbacks to use for this file. + If there is an error opening the file, nothing will be + filled in here. + \param _path The path to the file to open. + On Windows, this string must be UTF-8 (to allow access to + files whose names cannot be represented in the current + MBCS code page). + All other systems use the native character encoding. + \param _mode The mode to open the file in. + \return A stream handle to use with the callbacks, or <code>NULL</code> on + error.*/ +OP_WARN_UNUSED_RESULT void *op_fopen(OpusFileCallbacks *_cb, + const char *_path,const char *_mode) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2) + OP_ARG_NONNULL(3); + +/**Opens a stream with <code>fdopen()</code> and fills in a set of callbacks + that can be used to access it. + This is useful to avoid writing your own portable 64-bit seeking wrappers, + and also avoids cross-module linking issues on Windows, where a + <code>FILE *</code> must be accessed by routines defined in the same module + that opened it. + \param[out] _cb The callbacks to use for this file. + If there is an error opening the file, nothing will be + filled in here. + \param _fd The file descriptor to open. + \param _mode The mode to open the file in. + \return A stream handle to use with the callbacks, or <code>NULL</code> on + error.*/ +OP_WARN_UNUSED_RESULT void *op_fdopen(OpusFileCallbacks *_cb, + int _fd,const char *_mode) OP_ARG_NONNULL(1) OP_ARG_NONNULL(3); + +/**Opens a stream with <code>freopen()</code> and fills in a set of callbacks + that can be used to access it. + This is useful to avoid writing your own portable 64-bit seeking wrappers, + and also avoids cross-module linking issues on Windows, where a + <code>FILE *</code> must be accessed by routines defined in the same module + that opened it. + \param[out] _cb The callbacks to use for this file. + If there is an error opening the file, nothing will be + filled in here. + \param _path The path to the file to open. + On Windows, this string must be UTF-8 (to allow access + to files whose names cannot be represented in the + current MBCS code page). + All other systems use the native character encoding. + \param _mode The mode to open the file in. + \param _stream A stream previously returned by op_fopen(), op_fdopen(), + or op_freopen(). + \return A stream handle to use with the callbacks, or <code>NULL</code> on + error.*/ +OP_WARN_UNUSED_RESULT void *op_freopen(OpusFileCallbacks *_cb, + const char *_path,const char *_mode,void *_stream) OP_ARG_NONNULL(1) + OP_ARG_NONNULL(2) OP_ARG_NONNULL(3) OP_ARG_NONNULL(4); + +/**Creates a stream that reads from the given block of memory. + This block of memory must contain the complete stream to decode. + This is useful for caching small streams (e.g., sound effects) in RAM. + \param[out] _cb The callbacks to use for this stream. + If there is an error creating the stream, nothing will be + filled in here. + \param _data The block of memory to read from. + \param _size The size of the block of memory. + \return A stream handle to use with the callbacks, or <code>NULL</code> on + error.*/ +OP_WARN_UNUSED_RESULT void *op_mem_stream_create(OpusFileCallbacks *_cb, + const unsigned char *_data,size_t _size) OP_ARG_NONNULL(1); + +/**Creates a stream that reads from the given URL. + This function behaves identically to op_url_stream_create(), except that it + takes a va_list instead of a variable number of arguments. + It does not call the <code>va_end</code> macro, and because it invokes the + <code>va_arg</code> macro, the value of \a _ap is undefined after the call. + \note If you use this function, you must link against <tt>libopusurl</tt>. + \param[out] _cb The callbacks to use for this stream. + If there is an error creating the stream, nothing will + be filled in here. + \param _url The URL to read from. + Currently only the <file:>, <http:>, and <https:> + schemes are supported. + Both <http:> and <https:> may be disabled at compile + time, in which case opening such URLs will always fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, with + internationalized domain names encoded in punycode, + before passing them to this function. + \param[in,out] _ap A list of the \ref url_options "optional flags" to use. + This is a variable-length list of options terminated + with <code>NULL</code>. + \return A stream handle to use with the callbacks, or <code>NULL</code> on + error.*/ +OP_WARN_UNUSED_RESULT void *op_url_stream_vcreate(OpusFileCallbacks *_cb, + const char *_url,va_list _ap) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Creates a stream that reads from the given URL. + \note If you use this function, you must link against <tt>libopusurl</tt>. + \param[out] _cb The callbacks to use for this stream. + If there is an error creating the stream, nothing will be + filled in here. + \param _url The URL to read from. + Currently only the <file:>, <http:>, and <https:> schemes + are supported. + Both <http:> and <https:> may be disabled at compile time, + in which case opening such URLs will always fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, with + internationalized domain names encoded in punycode, before + passing them to this function. + \param ... The \ref url_options "optional flags" to use. + This is a variable-length list of options terminated with + <code>NULL</code>. + \return A stream handle to use with the callbacks, or <code>NULL</code> on + error.*/ +OP_WARN_UNUSED_RESULT void *op_url_stream_create(OpusFileCallbacks *_cb, + const char *_url,...) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/*@}*/ +/*@}*/ + +/**\defgroup stream_open_close Opening and Closing*/ +/*@{*/ +/**\name Functions for opening and closing streams + + These functions allow you to test a stream to see if it is Opus, open it, + and close it. + Several flavors are provided for each of the built-in stream types, plus a + more general version which takes a set of application-provided callbacks.*/ +/*@{*/ + +/**Test to see if this is an Opus stream. + For good results, you will need at least 57 bytes (for a pure Opus-only + stream). + Something like 512 bytes will give more reliable results for multiplexed + streams. + This function is meant to be a quick-rejection filter. + Its purpose is not to guarantee that a stream is a valid Opus stream, but to + ensure that it looks enough like Opus that it isn't going to be recognized + as some other format (except possibly an Opus stream that is also + multiplexed with other codecs, such as video). + \param[out] _head The parsed ID header contents. + You may pass <code>NULL</code> if you do not need + this information. + If the function fails, the contents of this structure + remain untouched. + \param _initial_data An initial buffer of data from the start of the + stream. + \param _initial_bytes The number of bytes in \a _initial_data. + \return 0 if the data appears to be Opus, or a negative value on error. + \retval #OP_FALSE There was not enough data to tell if this was an Opus + stream or not. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL The stream used a feature that is not implemented, + such as an unsupported channel family. + \retval #OP_ENOTFORMAT If the data did not contain a recognizable ID + header for an Opus stream. + \retval #OP_EVERSION If the version field signaled a version this library + does not know how to parse. + \retval #OP_EBADHEADER The ID header was not properly formatted or contained + illegal values.*/ +int op_test(OpusHead *_head, + const unsigned char *_initial_data,size_t _initial_bytes); + +/**Open a stream from the given file path. + \param _path The path to the file to open. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in <code>NULL</code> if you don't want the + failure code. + The failure code will be #OP_EFAULT if the file could not + be opened, or one of the other failure codes from + op_open_callbacks() otherwise. + \return A freshly opened \c OggOpusFile, or <code>NULL</code> on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_open_file(const char *_path,int *_error) + OP_ARG_NONNULL(1); + +/**Open a stream from a memory buffer. + \param _data The memory buffer to open. + \param _size The number of bytes in the buffer. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in <code>NULL</code> if you don't want the + failure code. + See op_open_callbacks() for a full list of failure codes. + \return A freshly opened \c OggOpusFile, or <code>NULL</code> on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_open_memory(const unsigned char *_data, + size_t _size,int *_error); + +/**Open a stream from a URL. + This function behaves identically to op_open_url(), except that it + takes a va_list instead of a variable number of arguments. + It does not call the <code>va_end</code> macro, and because it invokes the + <code>va_arg</code> macro, the value of \a _ap is undefined after the call. + \note If you use this function, you must link against <tt>libopusurl</tt>. + \param _url The URL to open. + Currently only the <file:>, <http:>, and <https:> + schemes are supported. + Both <http:> and <https:> may be disabled at compile + time, in which case opening such URLs will always + fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, + with internationalized domain names encoded in + punycode, before passing them to this function. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in <code>NULL</code> if you don't want + the failure code. + See op_open_callbacks() for a full list of failure + codes. + \param[in,out] _ap A list of the \ref url_options "optional flags" to + use. + This is a variable-length list of options terminated + with <code>NULL</code>. + \return A freshly opened \c OggOpusFile, or <code>NULL</code> on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_vopen_url(const char *_url, + int *_error,va_list _ap) OP_ARG_NONNULL(1); + +/**Open a stream from a URL. + \note If you use this function, you must link against <tt>libopusurl</tt>. + \param _url The URL to open. + Currently only the <file:>, <http:>, and <https:> schemes + are supported. + Both <http:> and <https:> may be disabled at compile + time, in which case opening such URLs will always fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, with + internationalized domain names encoded in punycode, + before passing them to this function. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in <code>NULL</code> if you don't want the + failure code. + See op_open_callbacks() for a full list of failure codes. + \param ... The \ref url_options "optional flags" to use. + This is a variable-length list of options terminated with + <code>NULL</code>. + \return A freshly opened \c OggOpusFile, or <code>NULL</code> on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_open_url(const char *_url, + int *_error,...) OP_ARG_NONNULL(1); + +/**Open a stream using the given set of callbacks to access it. + \param _source The stream to read from (e.g., a <code>FILE *</code>). + \param _cb The callbacks with which to access the stream. + <code><a href="#op_read_func">read()</a></code> must + be implemented. + <code><a href="#op_seek_func">seek()</a></code> and + <code><a href="#op_tell_func">tell()</a></code> may + be <code>NULL</code>, or may always return -1 to + indicate a source is unseekable, but if + <code><a href="#op_seek_func">seek()</a></code> is + implemented and succeeds on a particular source, then + <code><a href="#op_tell_func">tell()</a></code> must + also. + <code><a href="#op_close_func">close()</a></code> may + be <code>NULL</code>, but if it is not, it will be + called when the \c OggOpusFile is destroyed by + op_free(). + It will not be called if op_open_callbacks() fails + with an error. + \param _initial_data An initial buffer of data from the start of the + stream. + Applications can read some number of bytes from the + start of the stream to help identify this as an Opus + stream, and then provide them here to allow the + stream to be opened, even if it is unseekable. + \param _initial_bytes The number of bytes in \a _initial_data. + If the stream is seekable, its current position (as + reported by + <code><a href="#opus_tell_func">tell()</a></code> + at the start of this function) must be equal to + \a _initial_bytes. + Otherwise, seeking to absolute positions will + generate inconsistent results. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in <code>NULL</code> if you don't want + the failure code. + The failure code will be one of + <dl> + <dt>#OP_EREAD</dt> + <dd>An underlying read, seek, or tell operation + failed when it should have succeeded, or we failed + to find data in the stream we had seen before.</dd> + <dt>#OP_EFAULT</dt> + <dd>There was a memory allocation failure, or an + internal library error.</dd> + <dt>#OP_EIMPL</dt> + <dd>The stream used a feature that is not + implemented, such as an unsupported channel + family.</dd> + <dt>#OP_EINVAL</dt> + <dd><code><a href="#op_seek_func">seek()</a></code> + was implemented and succeeded on this source, but + <code><a href="#op_tell_func">tell()</a></code> + did not, or the starting position indicator was + not equal to \a _initial_bytes.</dd> + <dt>#OP_ENOTFORMAT</dt> + <dd>The stream contained a link that did not have + any logical Opus streams in it.</dd> + <dt>#OP_EBADHEADER</dt> + <dd>A required header packet was not properly + formatted, contained illegal values, or was missing + altogether.</dd> + <dt>#OP_EVERSION</dt> + <dd>An ID header contained an unrecognized version + number.</dd> + <dt>#OP_EBADLINK</dt> + <dd>We failed to find data we had seen before after + seeking.</dd> + <dt>#OP_EBADTIMESTAMP</dt> + <dd>The first or last timestamp in a link failed + basic validity checks.</dd> + </dl> + \return A freshly opened \c OggOpusFile, or <code>NULL</code> on error. + <tt>libopusfile</tt> does <em>not</em> take ownership of the source + if the call fails. + The calling application is responsible for closing the source if + this call returns an error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_open_callbacks(void *_source, + const OpusFileCallbacks *_cb,const unsigned char *_initial_data, + size_t _initial_bytes,int *_error) OP_ARG_NONNULL(2); + +/**Partially open a stream from the given file path. + \see op_test_callbacks + \param _path The path to the file to open. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in <code>NULL</code> if you don't want the + failure code. + The failure code will be #OP_EFAULT if the file could not + be opened, or one of the other failure codes from + op_open_callbacks() otherwise. + \return A partially opened \c OggOpusFile, or <code>NULL</code> on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_test_file(const char *_path,int *_error) + OP_ARG_NONNULL(1); + +/**Partially open a stream from a memory buffer. + \see op_test_callbacks + \param _data The memory buffer to open. + \param _size The number of bytes in the buffer. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in <code>NULL</code> if you don't want the + failure code. + See op_open_callbacks() for a full list of failure codes. + \return A partially opened \c OggOpusFile, or <code>NULL</code> on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_test_memory(const unsigned char *_data, + size_t _size,int *_error); + +/**Partially open a stream from a URL. + This function behaves identically to op_test_url(), except that it + takes a va_list instead of a variable number of arguments. + It does not call the <code>va_end</code> macro, and because it invokes the + <code>va_arg</code> macro, the value of \a _ap is undefined after the call. + \note If you use this function, you must link against <tt>libopusurl</tt>. + \see op_test_url + \see op_test_callbacks + \param _url The URL to open. + Currently only the <file:>, <http:>, and <https:> + schemes are supported. + Both <http:> and <https:> may be disabled at compile + time, in which case opening such URLs will always + fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, + with internationalized domain names encoded in + punycode, before passing them to this function. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in <code>NULL</code> if you don't want + the failure code. + See op_open_callbacks() for a full list of failure + codes. + \param[in,out] _ap A list of the \ref url_options "optional flags" to + use. + This is a variable-length list of options terminated + with <code>NULL</code>. + \return A partially opened \c OggOpusFile, or <code>NULL</code> on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_vtest_url(const char *_url, + int *_error,va_list _ap) OP_ARG_NONNULL(1); + +/**Partially open a stream from a URL. + \note If you use this function, you must link against <tt>libopusurl</tt>. + \see op_test_callbacks + \param _url The URL to open. + Currently only the <file:>, <http:>, and <https:> + schemes are supported. + Both <http:> and <https:> may be disabled at compile + time, in which case opening such URLs will always fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, with + internationalized domain names encoded in punycode, + before passing them to this function. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in <code>NULL</code> if you don't want the + failure code. + See op_open_callbacks() for a full list of failure + codes. + \param ... The \ref url_options "optional flags" to use. + This is a variable-length list of options terminated + with <code>NULL</code>. + \return A partially opened \c OggOpusFile, or <code>NULL</code> on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_test_url(const char *_url, + int *_error,...) OP_ARG_NONNULL(1); + +/**Partially open a stream using the given set of callbacks to access it. + This tests for Opusness and loads the headers for the first link. + It does not seek (although it tests for seekability). + You can query a partially open stream for the few pieces of basic + information returned by op_serialno(), op_channel_count(), op_head(), and + op_tags() (but only for the first link). + You may also determine if it is seekable via a call to op_seekable(). + You cannot read audio from the stream, seek, get the size or duration, + get information from links other than the first one, or even get the total + number of links until you finish opening the stream with op_test_open(). + If you do not need to do any of these things, you can dispose of it with + op_free() instead. + + This function is provided mostly to simplify porting existing code that used + <tt>libvorbisfile</tt>. + For new code, you are likely better off using op_test() instead, which + is less resource-intensive, requires less data to succeed, and imposes a + hard limit on the amount of data it examines (important for unseekable + sources, where all such data must be buffered until you are sure of the + stream type). + \param _source The stream to read from (e.g., a <code>FILE *</code>). + \param _cb The callbacks with which to access the stream. + <code><a href="#op_read_func">read()</a></code> must + be implemented. + <code><a href="#op_seek_func">seek()</a></code> and + <code><a href="#op_tell_func">tell()</a></code> may + be <code>NULL</code>, or may always return -1 to + indicate a source is unseekable, but if + <code><a href="#op_seek_func">seek()</a></code> is + implemented and succeeds on a particular source, then + <code><a href="#op_tell_func">tell()</a></code> must + also. + <code><a href="#op_close_func">close()</a></code> may + be <code>NULL</code>, but if it is not, it will be + called when the \c OggOpusFile is destroyed by + op_free(). + It will not be called if op_open_callbacks() fails + with an error. + \param _initial_data An initial buffer of data from the start of the + stream. + Applications can read some number of bytes from the + start of the stream to help identify this as an Opus + stream, and then provide them here to allow the + stream to be tested more thoroughly, even if it is + unseekable. + \param _initial_bytes The number of bytes in \a _initial_data. + If the stream is seekable, its current position (as + reported by + <code><a href="#opus_tell_func">tell()</a></code> + at the start of this function) must be equal to + \a _initial_bytes. + Otherwise, seeking to absolute positions will + generate inconsistent results. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in <code>NULL</code> if you don't want + the failure code. + See op_open_callbacks() for a full list of failure + codes. + \return A partially opened \c OggOpusFile, or <code>NULL</code> on error. + <tt>libopusfile</tt> does <em>not</em> take ownership of the source + if the call fails. + The calling application is responsible for closing the source if + this call returns an error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_test_callbacks(void *_source, + const OpusFileCallbacks *_cb,const unsigned char *_initial_data, + size_t _initial_bytes,int *_error) OP_ARG_NONNULL(2); + +/**Finish opening a stream partially opened with op_test_callbacks() or one of + the associated convenience functions. + If this function fails, you are still responsible for freeing the + \c OggOpusFile with op_free(). + \param _of The \c OggOpusFile to finish opening. + \return 0 on success, or a negative value on error. + \retval #OP_EREAD An underlying read, seek, or tell operation failed + when it should have succeeded. + \retval #OP_EFAULT There was a memory allocation failure, or an + internal library error. + \retval #OP_EIMPL The stream used a feature that is not implemented, + such as an unsupported channel family. + \retval #OP_EINVAL The stream was not partially opened with + op_test_callbacks() or one of the associated + convenience functions. + \retval #OP_ENOTFORMAT The stream contained a link that did not have any + logical Opus streams in it. + \retval #OP_EBADHEADER A required header packet was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An ID header contained an unrecognized version + number. + \retval #OP_EBADLINK We failed to find data we had seen before after + seeking. + \retval #OP_EBADTIMESTAMP The first or last timestamp in a link failed basic + validity checks.*/ +int op_test_open(OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Release all memory used by an \c OggOpusFile. + \param _of The \c OggOpusFile to free.*/ +void op_free(OggOpusFile *_of); + +/*@}*/ +/*@}*/ + +/**\defgroup stream_info Stream Information*/ +/*@{*/ +/**\name Functions for obtaining information about streams + + These functions allow you to get basic information about a stream, including + seekability, the number of links (for chained streams), plus the size, + duration, bitrate, header parameters, and meta information for each link + (or, where available, the stream as a whole). + Some of these (size, duration) are only available for seekable streams. + You can also query the current stream position, link, and playback time, + and instantaneous bitrate during playback. + + Some of these functions may be used successfully on the partially open + streams returned by op_test_callbacks() or one of the associated + convenience functions. + Their documention will indicate so explicitly.*/ +/*@{*/ + +/**Returns whether or not the data source being read is seekable. + This is true if + <ol> + <li>The <code><a href="#op_seek_func">seek()</a></code> and + <code><a href="#op_tell_func">tell()</a></code> callbacks are both + non-<code>NULL</code>,</li> + <li>The <code><a href="#op_seek_func">seek()</a></code> callback was + successfully executed at least once, and</li> + <li>The <code><a href="#op_tell_func">tell()</a></code> callback was + successfully able to report the position indicator afterwards.</li> + </ol> + This function may be called on partially-opened streams. + \param _of The \c OggOpusFile whose seekable status is to be returned. + \return A non-zero value if seekable, and 0 if unseekable.*/ +int op_seekable(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Returns the number of links in this chained stream. + This function may be called on partially-opened streams, but it will always + return 1. + The actual number of links is not known until the stream is fully opened. + \param _of The \c OggOpusFile from which to retrieve the link count. + \return For fully-open seekable sources, this returns the total number of + links in the whole stream, which will be at least 1. + For partially-open or unseekable sources, this always returns 1.*/ +int op_link_count(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Get the serial number of the given link in a (possibly-chained) Ogg Opus + stream. + This function may be called on partially-opened streams, but it will always + return the serial number of the Opus stream in the first link. + \param _of The \c OggOpusFile from which to retrieve the serial number. + \param _li The index of the link whose serial number should be retrieved. + Use a negative number to get the serial number of the current + link. + \return The serial number of the given link. + If \a _li is greater than the total number of links, this returns + the serial number of the last link. + If the source is not seekable, this always returns the serial number + of the current link.*/ +opus_uint32 op_serialno(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the channel count of the given link in a (possibly-chained) Ogg Opus + stream. + This is equivalent to <code>op_head(_of,_li)->channel_count</code>, but + is provided for convenience. + This function may be called on partially-opened streams, but it will always + return the channel count of the Opus stream in the first link. + \param _of The \c OggOpusFile from which to retrieve the channel count. + \param _li The index of the link whose channel count should be retrieved. + Use a negative number to get the channel count of the current + link. + \return The channel count of the given link. + If \a _li is greater than the total number of links, this returns + the channel count of the last link. + If the source is not seekable, this always returns the channel count + of the current link.*/ +int op_channel_count(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the total (compressed) size of the stream, or of an individual link in + a (possibly-chained) Ogg Opus stream, including all headers and Ogg muxing + overhead. + \warning If the Opus stream (or link) is concurrently multiplexed with other + logical streams (e.g., video), this returns the size of the entire stream + (or link), not just the number of bytes in the first logical Opus stream. + Returning the latter would require scanning the entire file. + \param _of The \c OggOpusFile from which to retrieve the compressed size. + \param _li The index of the link whose compressed size should be computed. + Use a negative number to get the compressed size of the entire + stream. + \return The compressed size of the entire stream if \a _li is negative, the + compressed size of link \a _li if it is non-negative, or a negative + value on error. + The compressed size of the entire stream may be smaller than that + of the underlying source if trailing garbage was detected in the + file. + \retval #OP_EINVAL The source is not seekable (so we can't know the length), + \a _li wasn't less than the total number of links in + the stream, or the stream was only partially open.*/ +opus_int64 op_raw_total(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the total PCM length (number of samples at 48 kHz) of the stream, or of + an individual link in a (possibly-chained) Ogg Opus stream. + Users looking for <code>op_time_total()</code> should use op_pcm_total() + instead. + Because timestamps in Opus are fixed at 48 kHz, there is no need for a + separate function to convert this to seconds (and leaving it out avoids + introducing floating point to the API, for those that wish to avoid it). + \param _of The \c OggOpusFile from which to retrieve the PCM offset. + \param _li The index of the link whose PCM length should be computed. + Use a negative number to get the PCM length of the entire stream. + \return The PCM length of the entire stream if \a _li is negative, the PCM + length of link \a _li if it is non-negative, or a negative value on + error. + \retval #OP_EINVAL The source is not seekable (so we can't know the length), + \a _li wasn't less than the total number of links in + the stream, or the stream was only partially open.*/ +ogg_int64_t op_pcm_total(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the ID header information for the given link in a (possibly chained) Ogg + Opus stream. + This function may be called on partially-opened streams, but it will always + return the ID header information of the Opus stream in the first link. + \param _of The \c OggOpusFile from which to retrieve the ID header + information. + \param _li The index of the link whose ID header information should be + retrieved. + Use a negative number to get the ID header information of the + current link. + For an unseekable stream, \a _li is ignored, and the ID header + information for the current link is always returned, if + available. + \return The contents of the ID header for the given link.*/ +const OpusHead *op_head(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the comment header information for the given link in a (possibly + chained) Ogg Opus stream. + This function may be called on partially-opened streams, but it will always + return the tags from the Opus stream in the first link. + \param _of The \c OggOpusFile from which to retrieve the comment header + information. + \param _li The index of the link whose comment header information should be + retrieved. + Use a negative number to get the comment header information of + the current link. + For an unseekable stream, \a _li is ignored, and the comment + header information for the current link is always returned, if + available. + \return The contents of the comment header for the given link, or + <code>NULL</code> if this is an unseekable stream that encountered + an invalid link.*/ +const OpusTags *op_tags(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Retrieve the index of the current link. + This is the link that produced the data most recently read by + op_read_float() or its associated functions, or, after a seek, the link + that the seek target landed in. + Reading more data may advance the link index (even on the first read after a + seek). + \param _of The \c OggOpusFile from which to retrieve the current link index. + \return The index of the current link on success, or a negative value on + failure. + For seekable streams, this is a number between 0 and the value + returned by op_link_count(). + For unseekable streams, this value starts at 0 and increments by one + each time a new link is encountered (even though op_link_count() + always returns 1). + \retval #OP_EINVAL The stream was only partially open.*/ +int op_current_link(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Computes the bitrate of the stream, or of an individual link in a + (possibly-chained) Ogg Opus stream. + The stream must be seekable to compute the bitrate. + For unseekable streams, use op_bitrate_instant() to get periodic estimates. + \warning If the Opus stream (or link) is concurrently multiplexed with other + logical streams (e.g., video), this uses the size of the entire stream (or + link) to compute the bitrate, not just the number of bytes in the first + logical Opus stream. + Returning the latter requires scanning the entire file, but this may be done + by decoding the whole file and calling op_bitrate_instant() once at the + end. + Install a trivial decoding callback with op_set_decode_callback() if you + wish to skip actual decoding during this process. + \param _of The \c OggOpusFile from which to retrieve the bitrate. + \param _li The index of the link whose bitrate should be computed. + Use a negative number to get the bitrate of the whole stream. + \return The bitrate on success, or a negative value on error. + \retval #OP_EINVAL The stream was only partially open, the stream was not + seekable, or \a _li was larger than the number of + links.*/ +opus_int32 op_bitrate(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Compute the instantaneous bitrate, measured as the ratio of bits to playable + samples decoded since a) the last call to op_bitrate_instant(), b) the last + seek, or c) the start of playback, whichever was most recent. + This will spike somewhat after a seek or at the start/end of a chain + boundary, as pre-skip, pre-roll, and end-trimming causes samples to be + decoded but not played. + \param _of The \c OggOpusFile from which to retrieve the bitrate. + \return The bitrate, in bits per second, or a negative value on error. + \retval #OP_FALSE No data has been decoded since any of the events + described above. + \retval #OP_EINVAL The stream was only partially open.*/ +opus_int32 op_bitrate_instant(OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Obtain the current value of the position indicator for \a _of. + \param _of The \c OggOpusFile from which to retrieve the position indicator. + \return The byte position that is currently being read from. + \retval #OP_EINVAL The stream was only partially open.*/ +opus_int64 op_raw_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Obtain the PCM offset of the next sample to be read. + If the stream is not properly timestamped, this might not increment by the + proper amount between reads, or even return monotonically increasing + values. + \param _of The \c OggOpusFile from which to retrieve the PCM offset. + \return The PCM offset of the next sample to be read. + \retval #OP_EINVAL The stream was only partially open.*/ +ogg_int64_t op_pcm_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/*@}*/ +/*@}*/ + +/**\defgroup stream_seeking Seeking*/ +/*@{*/ +/**\name Functions for seeking in Opus streams + + These functions let you seek in Opus streams, if the underlying source + support it. + Seeking is implemented for all built-in stream I/O routines, though some + individual sources may not be seekable (pipes, live HTTP streams, or HTTP + streams from a server that does not support <code>Range</code> requests). + + op_raw_seek() is the fastest: it is guaranteed to perform at most one + physical seek, but, since the target is a byte position, makes no guarantee + how close to a given time it will come. + op_pcm_seek() provides sample-accurate seeking. + The number of physical seeks it requires is still quite small (often 1 or + 2, even in highly variable bitrate streams). + + Seeking in Opus requires decoding some pre-roll amount before playback to + allow the internal state to converge (as if recovering from packet loss). + This is handled internally by <tt>libopusfile</tt>, but means there is + little extra overhead for decoding up to the exact position requested + (since it must decode some amount of audio anyway). + It also means that decoding after seeking may not return exactly the same + values as would be obtained by decoding the stream straight through. + However, such differences are expected to be smaller than the loss + introduced by Opus's lossy compression.*/ +/*@{*/ + +/**Seek to a byte offset relative to the <b>compressed</b> data. + This also scans packets to update the PCM cursor. + It will cross a logical bitstream boundary, but only if it can't get any + packets out of the tail of the link to which it seeks. + \param _of The \c OggOpusFile in which to seek. + \param _byte_offset The byte position to seek to. + \return 0 on success, or a negative error code on failure. + \retval #OP_EREAD The underlying seek operation failed. + \retval #OP_EINVAL The stream was only partially open, or the target was + outside the valid range for the stream. + \retval #OP_ENOSEEK This stream is not seekable. + \retval #OP_EBADLINK Failed to initialize a decoder for a stream for an + unknown reason.*/ +int op_raw_seek(OggOpusFile *_of,opus_int64 _byte_offset) OP_ARG_NONNULL(1); + +/**Seek to the specified PCM offset, such that decoding will begin at exactly + the requested position. + \param _of The \c OggOpusFile in which to seek. + \param _pcm_offset The PCM offset to seek to. + This is in samples at 48 kHz relative to the start of the + stream. + \return 0 on success, or a negative value on error. + \retval #OP_EREAD An underlying read or seek operation failed. + \retval #OP_EINVAL The stream was only partially open, or the target was + outside the valid range for the stream. + \retval #OP_ENOSEEK This stream is not seekable. + \retval #OP_EBADLINK We failed to find data we had seen before, or the + bitstream structure was sufficiently malformed that + seeking to the target destination was impossible.*/ +int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset) OP_ARG_NONNULL(1); + +/*@}*/ +/*@}*/ + +/**\defgroup stream_decoding Decoding*/ +/*@{*/ +/**\name Functions for decoding audio data + + These functions retrieve actual decoded audio data from the stream. + The general functions, op_read() and op_read_float() return 16-bit or + floating-point output, both using native endian ordering. + The number of channels returned can change from link to link in a chained + stream. + There are special functions, op_read_stereo() and op_read_float_stereo(), + which always output two channels, to simplify applications which do not + wish to handle multichannel audio. + These downmix multichannel files to two channels, so they can always return + samples in the same format for every link in a chained file. + + If the rest of your audio processing chain can handle floating point, those + routines should be preferred, as floating point output avoids introducing + clipping and other issues which might be avoided entirely if, e.g., you + scale down the volume at some other stage. + However, if you intend to direct consume 16-bit samples, the conversion in + <tt>libopusfile</tt> provides noise-shaping dithering and, if compiled + against <tt>libopus</tt> 1.1 or later, soft-clipping prevention. + + <tt>libopusfile</tt> can also be configured at compile time to use the + fixed-point <tt>libopus</tt> API. + If so, <tt>libopusfile</tt>'s floating-point API may also be disabled. + In that configuration, nothing in <tt>libopusfile</tt> will use any + floating-point operations, to simplify support on devices without an + adequate FPU. + + \warning HTTPS streams may be be vulnerable to truncation attacks if you do + not check the error return code from op_read_float() or its associated + functions. + If the remote peer does not close the connection gracefully (with a TLS + "close notify" message), these functions will return #OP_EREAD instead of 0 + when they reach the end of the file. + If you are reading from an <https:> URL (particularly if seeking is not + supported), you should make sure to check for this error and warn the user + appropriately.*/ +/*@{*/ + +/**Indicates that the decoding callback should produce signed 16-bit + native-endian output samples.*/ +#define OP_DEC_FORMAT_SHORT (7008) +/**Indicates that the decoding callback should produce 32-bit native-endian + float samples.*/ +#define OP_DEC_FORMAT_FLOAT (7040) + +/**Indicates that the decoding callback did not decode anything, and that + <tt>libopusfile</tt> should decode normally instead.*/ +#define OP_DEC_USE_DEFAULT (6720) + +/**Called to decode an Opus packet. + This should invoke the functional equivalent of opus_multistream_decode() or + opus_multistream_decode_float(), except that it returns 0 on success + instead of the number of decoded samples (which is known a priori). + \param _ctx The application-provided callback context. + \param _decoder The decoder to use to decode the packet. + \param[out] _pcm The buffer to decode into. + This will always have enough room for \a _nchannels of + \a _nsamples samples, which should be placed into this + buffer interleaved. + \param _op The packet to decode. + This will always have its granule position set to a valid + value. + \param _nsamples The number of samples expected from the packet. + \param _nchannels The number of channels expected from the packet. + \param _format The desired sample output format. + This is either #OP_DEC_FORMAT_SHORT or + #OP_DEC_FORMAT_FLOAT. + \param _li The index of the link from which this packet was decoded. + \return A non-negative value on success, or a negative value on error. + The error codes should be the same as those returned by + opus_multistream_decode() or opus_multistream_decode_float(). + \retval 0 Decoding was successful. + The application has filled the buffer with + exactly <code>\a _nsamples*\a + _nchannels</code> samples in the requested + format. + \retval #OP_DEC_USE_DEFAULT No decoding was done. + <tt>libopusfile</tt> should decode normally + instead.*/ +typedef int (*op_decode_cb_func)(void *_ctx,OpusMSDecoder *_decoder,void *_pcm, + const ogg_packet *_op,int _nsamples,int _nchannels,int _format,int _li); + +/**Sets the packet decode callback function. + This is called once for each packet that needs to be decoded. + A call to this function is no guarantee that the audio will eventually be + delivered to the application. + Some or all of the data from the packet may be discarded (i.e., at the + beginning or end of a link, or after a seek), however the callback is + required to provide all of it. + \param _of The \c OggOpusFile on which to set the decode callback. + \param _decode_cb The callback function to call. + This may be <code>NULL</code> to disable calling the + callback. + \param _ctx The application-provided context pointer to pass to the + callback on each call.*/ +void op_set_decode_callback(OggOpusFile *_of, + op_decode_cb_func _decode_cb,void *_ctx) OP_ARG_NONNULL(1); + +/**Gain offset type that indicates that the provided offset is relative to the + header gain. + This is the default.*/ +#define OP_HEADER_GAIN (0) + +/**Gain offset type that indicates that the provided offset is relative to the + R128_ALBUM_GAIN value (if any), in addition to the header gain.*/ +#define OP_ALBUM_GAIN (3007) + +/**Gain offset type that indicates that the provided offset is relative to the + R128_TRACK_GAIN value (if any), in addition to the header gain.*/ +#define OP_TRACK_GAIN (3008) + +/**Gain offset type that indicates that the provided offset should be used as + the gain directly, without applying any the header or track gains.*/ +#define OP_ABSOLUTE_GAIN (3009) + +/**Sets the gain to be used for decoded output. + By default, the gain in the header is applied with no additional offset. + The total gain (including header gain and/or track gain, if applicable, and + this offset), will be clamped to [-32768,32767]/256 dB. + This is more than enough to saturate or underflow 16-bit PCM. + \note The new gain will not be applied to any already buffered, decoded + output. + This means you cannot change it sample-by-sample, as at best it will be + updated packet-by-packet. + It is meant for setting a target volume level, rather than applying smooth + fades, etc. + \param _of The \c OggOpusFile on which to set the gain offset. + \param _gain_type One of #OP_HEADER_GAIN, #OP_ALBUM_GAIN, + #OP_TRACK_GAIN, or #OP_ABSOLUTE_GAIN. + \param _gain_offset_q8 The gain offset to apply, in 1/256ths of a dB. + \return 0 on success or a negative value on error. + \retval #OP_EINVAL The \a _gain_type was unrecognized.*/ +int op_set_gain_offset(OggOpusFile *_of, + int _gain_type,opus_int32 _gain_offset_q8) OP_ARG_NONNULL(1); + +/**Sets whether or not dithering is enabled for 16-bit decoding. + By default, when <tt>libopusfile</tt> is compiled to use floating-point + internally, calling op_read() or op_read_stereo() will first decode to + float, and then convert to fixed-point using noise-shaping dithering. + This flag can be used to disable that dithering. + When the application uses op_read_float() or op_read_float_stereo(), or when + the library has been compiled to decode directly to fixed point, this flag + has no effect. + \param _of The \c OggOpusFile on which to enable or disable dithering. + \param _enabled A non-zero value to enable dithering, or 0 to disable it.*/ +void op_set_dither_enabled(OggOpusFile *_of,int _enabled) OP_ARG_NONNULL(1); + +/**Reads more samples from the stream. + \note Although \a _buf_size must indicate the total number of values that + can be stored in \a _pcm, the return value is the number of samples + <em>per channel</em>. + This is done because + <ol> + <li>The channel count cannot be known a priori (reading more samples might + advance us into the next link, with a different channel count), so + \a _buf_size cannot also be in units of samples per channel,</li> + <li>Returning the samples per channel matches the <code>libopus</code> API + as closely as we're able,</li> + <li>Returning the total number of values instead of samples per channel + would mean the caller would need a division to compute the samples per + channel, and might worry about the possibility of getting back samples + for some channels and not others, and</li> + <li>This approach is relatively fool-proof: if an application passes too + small a value to \a _buf_size, they will simply get fewer samples back, + and if they assume the return value is the total number of values, then + they will simply read too few (rather than reading too many and going + off the end of the buffer).</li> + </ol> + \param _of The \c OggOpusFile from which to read. + \param[out] _pcm A buffer in which to store the output PCM samples, as + signed native-endian 16-bit values at 48 kHz + with a nominal range of <code>[-32768,32767)</code>. + Multiple channels are interleaved using the + <a href="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">Vorbis + channel ordering</a>. + This must have room for at least \a _buf_size values. + \param _buf_size The number of values that can be stored in \a _pcm. + It is recommended that this be large enough for at + least 120 ms of data at 48 kHz per channel (5760 + values per channel). + Smaller buffers will simply return less data, possibly + consuming more memory to buffer the data internally. + <tt>libopusfile</tt> may return less data than + requested. + If so, there is no guarantee that the remaining data + in \a _pcm will be unmodified. + \param[out] _li The index of the link this data was decoded from. + You may pass <code>NULL</code> if you do not need this + information. + If this function fails (returning a negative value), + this parameter is left unset. + \return The number of samples read per channel on success, or a negative + value on failure. + The channel count can be retrieved on success by calling + <code>op_head(_of,*_li)</code>. + The number of samples returned may be 0 if the buffer was too small + to store even a single sample for all channels, or if end-of-file + was reached. + The list of possible failure codes follows. + Most of them can only be returned by unseekable, chained streams + that encounter a new link. + \retval #OP_HOLE There was a hole in the data, and some samples + may have been skipped. + Call this function again to continue decoding + past the hole. + \retval #OP_EREAD An underlying read operation failed. + This may signal a truncation attack from an + <https:> source. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL An unseekable stream encountered a new link that + used a feature that is not implemented, such as + an unsupported channel family. + \retval #OP_EINVAL The stream was only partially open. + \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that + did not have any logical Opus streams in it. + \retval #OP_EBADHEADER An unseekable stream encountered a new link with a + required header packet that was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An unseekable stream encountered a new link with + an ID header that contained an unrecognized + version number. + \retval #OP_EBADPACKET Failed to properly decode the next packet. + \retval #OP_EBADLINK We failed to find data we had seen before. + \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with + a starting timestamp that failed basic validity + checks.*/ +OP_WARN_UNUSED_RESULT int op_read(OggOpusFile *_of, + opus_int16 *_pcm,int _buf_size,int *_li) OP_ARG_NONNULL(1); + +/**Reads more samples from the stream. + \note Although \a _buf_size must indicate the total number of values that + can be stored in \a _pcm, the return value is the number of samples + <em>per channel</em>. + <ol> + <li>The channel count cannot be known a priori (reading more samples might + advance us into the next link, with a different channel count), so + \a _buf_size cannot also be in units of samples per channel,</li> + <li>Returning the samples per channel matches the <code>libopus</code> API + as closely as we're able,</li> + <li>Returning the total number of values instead of samples per channel + would mean the caller would need a division to compute the samples per + channel, and might worry about the possibility of getting back samples + for some channels and not others, and</li> + <li>This approach is relatively fool-proof: if an application passes too + small a value to \a _buf_size, they will simply get fewer samples back, + and if they assume the return value is the total number of values, then + they will simply read too few (rather than reading too many and going + off the end of the buffer).</li> + </ol> + \param _of The \c OggOpusFile from which to read. + \param[out] _pcm A buffer in which to store the output PCM samples as + signed floats at 48 kHz with a nominal range of + <code>[-1.0,1.0]</code>. + Multiple channels are interleaved using the + <a href="http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9">Vorbis + channel ordering</a>. + This must have room for at least \a _buf_size floats. + \param _buf_size The number of floats that can be stored in \a _pcm. + It is recommended that this be large enough for at + least 120 ms of data at 48 kHz per channel (5760 + samples per channel). + Smaller buffers will simply return less data, possibly + consuming more memory to buffer the data internally. + If less than \a _buf_size values are returned, + <tt>libopusfile</tt> makes no guarantee that the + remaining data in \a _pcm will be unmodified. + \param[out] _li The index of the link this data was decoded from. + You may pass <code>NULL</code> if you do not need this + information. + If this function fails (returning a negative value), + this parameter is left unset. + \return The number of samples read per channel on success, or a negative + value on failure. + The channel count can be retrieved on success by calling + <code>op_head(_of,*_li)</code>. + The number of samples returned may be 0 if the buffer was too small + to store even a single sample for all channels, or if end-of-file + was reached. + The list of possible failure codes follows. + Most of them can only be returned by unseekable, chained streams + that encounter a new link. + \retval #OP_HOLE There was a hole in the data, and some samples + may have been skipped. + Call this function again to continue decoding + past the hole. + \retval #OP_EREAD An underlying read operation failed. + This may signal a truncation attack from an + <https:> source. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL An unseekable stream encountered a new link that + used a feature that is not implemented, such as + an unsupported channel family. + \retval #OP_EINVAL The stream was only partially open. + \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that + did not have any logical Opus streams in it. + \retval #OP_EBADHEADER An unseekable stream encountered a new link with a + required header packet that was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An unseekable stream encountered a new link with + an ID header that contained an unrecognized + version number. + \retval #OP_EBADPACKET Failed to properly decode the next packet. + \retval #OP_EBADLINK We failed to find data we had seen before. + \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with + a starting timestamp that failed basic validity + checks.*/ +OP_WARN_UNUSED_RESULT int op_read_float(OggOpusFile *_of, + float *_pcm,int _buf_size,int *_li) OP_ARG_NONNULL(1); + +/**Reads more samples from the stream and downmixes to stereo, if necessary. + This function is intended for simple players that want a uniform output + format, even if the channel count changes between links in a chained + stream. + \note \a _buf_size indicates the total number of values that can be stored + in \a _pcm, while the return value is the number of samples <em>per + channel</em>, even though the channel count is known, for consistency with + op_read(). + \param _of The \c OggOpusFile from which to read. + \param[out] _pcm A buffer in which to store the output PCM samples, as + signed native-endian 16-bit values at 48 kHz + with a nominal range of <code>[-32768,32767)</code>. + The left and right channels are interleaved in the + buffer. + This must have room for at least \a _buf_size values. + \param _buf_size The number of values that can be stored in \a _pcm. + It is recommended that this be large enough for at + least 120 ms of data at 48 kHz per channel (11520 + values total). + Smaller buffers will simply return less data, possibly + consuming more memory to buffer the data internally. + If less than \a _buf_size values are returned, + <tt>libopusfile</tt> makes no guarantee that the + remaining data in \a _pcm will be unmodified. + \return The number of samples read per channel on success, or a negative + value on failure. + The number of samples returned may be 0 if the buffer was too small + to store even a single sample for both channels, or if end-of-file + was reached. + The list of possible failure codes follows. + Most of them can only be returned by unseekable, chained streams + that encounter a new link. + \retval #OP_HOLE There was a hole in the data, and some samples + may have been skipped. + Call this function again to continue decoding + past the hole. + \retval #OP_EREAD An underlying read operation failed. + This may signal a truncation attack from an + <https:> source. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL An unseekable stream encountered a new link that + used a feature that is not implemented, such as + an unsupported channel family. + \retval #OP_EINVAL The stream was only partially open. + \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that + did not have any logical Opus streams in it. + \retval #OP_EBADHEADER An unseekable stream encountered a new link with a + required header packet that was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An unseekable stream encountered a new link with + an ID header that contained an unrecognized + version number. + \retval #OP_EBADPACKET Failed to properly decode the next packet. + \retval #OP_EBADLINK We failed to find data we had seen before. + \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with + a starting timestamp that failed basic validity + checks.*/ +OP_WARN_UNUSED_RESULT int op_read_stereo(OggOpusFile *_of, + opus_int16 *_pcm,int _buf_size) OP_ARG_NONNULL(1); + +/**Reads more samples from the stream and downmixes to stereo, if necessary. + This function is intended for simple players that want a uniform output + format, even if the channel count changes between links in a chained + stream. + \note \a _buf_size indicates the total number of values that can be stored + in \a _pcm, while the return value is the number of samples <em>per + channel</em>, even though the channel count is known, for consistency with + op_read_float(). + \param _of The \c OggOpusFile from which to read. + \param[out] _pcm A buffer in which to store the output PCM samples, as + signed floats at 48 kHz with a nominal range of + <code>[-1.0,1.0]</code>. + The left and right channels are interleaved in the + buffer. + This must have room for at least \a _buf_size values. + \param _buf_size The number of values that can be stored in \a _pcm. + It is recommended that this be large enough for at + least 120 ms of data at 48 kHz per channel (11520 + values total). + Smaller buffers will simply return less data, possibly + consuming more memory to buffer the data internally. + If less than \a _buf_size values are returned, + <tt>libopusfile</tt> makes no guarantee that the + remaining data in \a _pcm will be unmodified. + \return The number of samples read per channel on success, or a negative + value on failure. + The number of samples returned may be 0 if the buffer was too small + to store even a single sample for both channels, or if end-of-file + was reached. + The list of possible failure codes follows. + Most of them can only be returned by unseekable, chained streams + that encounter a new link. + \retval #OP_HOLE There was a hole in the data, and some samples + may have been skipped. + Call this function again to continue decoding + past the hole. + \retval #OP_EREAD An underlying read operation failed. + This may signal a truncation attack from an + <https:> source. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL An unseekable stream encountered a new link that + used a feature that is not implemented, such as + an unsupported channel family. + \retval #OP_EINVAL The stream was only partially open. + \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that + that did not have any logical Opus streams in it. + \retval #OP_EBADHEADER An unseekable stream encountered a new link with a + required header packet that was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An unseekable stream encountered a new link with + an ID header that contained an unrecognized + version number. + \retval #OP_EBADPACKET Failed to properly decode the next packet. + \retval #OP_EBADLINK We failed to find data we had seen before. + \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with + a starting timestamp that failed basic validity + checks.*/ +OP_WARN_UNUSED_RESULT int op_read_float_stereo(OggOpusFile *_of, + float *_pcm,int _buf_size) OP_ARG_NONNULL(1); + +/*@}*/ +/*@}*/ + +# if OP_GNUC_PREREQ(4,0) +# pragma GCC visibility pop +# endif + +# if defined(__cplusplus) +} +# endif + +#endif diff --git a/thirdparty/opus/repacketizer.c b/thirdparty/opus/repacketizer.c new file mode 100644 index 0000000000..f27e9ab958 --- /dev/null +++ b/thirdparty/opus/repacketizer.c @@ -0,0 +1,346 @@ +/* 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" + + +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); + if(ret<1)return ret; + + rp->nb_frames += curr_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) +{ + int i, count; + opus_int32 tot_size; + opus_int16 *len; + const unsigned char **frames; + unsigned char * ptr; + + if (begin<0 || begin>=end || end>rp->nb_frames) + { + /*fprintf(stderr, "%d %d %d\n", begin, end, rp->nb_frames);*/ + 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; + + ptr = data; + if (count==1) + { + /* Code 0 */ + tot_size += len[0]+1; + if (tot_size > maxlen) + 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) + 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) + return OPUS_BUFFER_TOO_SMALL; + *ptr++ = (rp->toc&0xFC) | 0x2; + ptr += encode_size(len[0], ptr); + } + } + if (count > 2 || (pad && tot_size < maxlen)) + { + /* 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) + return OPUS_BUFFER_TOO_SMALL; + *ptr++ = (rp->toc&0xFC) | 0x3; + *ptr++ = count | 0x80; + } else { + tot_size += count*len[0]+2; + if (tot_size > maxlen) + return OPUS_BUFFER_TOO_SMALL; + *ptr++ = (rp->toc&0xFC) | 0x3; + *ptr++ = count; + } + pad_amount = pad ? (maxlen-tot_size) : 0; + if (pad_amount != 0) + { + int nb_255s; + data[1] |= 0x40; + nb_255s = (pad_amount-1)/255; + 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(). */ + celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]); + OPUS_MOVE(ptr, frames[i], len[i]); + ptr += len[i]; + } + if (pad) + { + /* Fill padding with zeros. */ + while (ptr<data+maxlen) + *ptr++=0; + } + 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); +} + +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); +} + +int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len) +{ + OpusRepacketizer rp; + opus_int32 ret; + if (len < 1) + return OPUS_BAD_ARG; + if (len==new_len) + return OPUS_OK; + else if (len > new_len) + return OPUS_BAD_ARG; + opus_repacketizer_init(&rp); + /* Moving payload to the end of the packet so we can do in-place padding */ + OPUS_MOVE(data+new_len-len, data, len); + opus_repacketizer_cat(&rp, data+new_len-len, len); + ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, 1); + 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; + if (len < 1) + return OPUS_BAD_ARG; + opus_repacketizer_init(&rp); + ret = opus_repacketizer_cat(&rp, data, len); + if (ret < 0) + return ret; + ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, len, 0, 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); + 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 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); + if (ret<0) + return ret; + ret = opus_repacketizer_cat_impl(&rp, data, packet_offset, self_delimited); + if (ret < 0) + return ret; + ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, dst, len, self_delimited, 0); + if (ret < 0) + return ret; + else + dst_len += ret; + dst += ret; + data += packet_offset; + len -= packet_offset; + } + return dst_len; +} + diff --git a/thirdparty/opus/repacketizer_demo.c b/thirdparty/opus/repacketizer_demo.c new file mode 100644 index 0000000000..dc05c1b359 --- /dev/null +++ b/thirdparty/opus/repacketizer_demo.c @@ -0,0 +1,217 @@ +/* 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define MAX_PACKETOUT 32000 + +void usage(char *argv0) +{ + fprintf(stderr, "usage: %s [options] input_file output_file\n", argv0); +} + +static void int_to_char(opus_uint32 i, unsigned char ch[4]) +{ + ch[0] = i>>24; + ch[1] = (i>>16)&0xFF; + ch[2] = (i>>8)&0xFF; + ch[3] = i&0xFF; +} + +static opus_uint32 char_to_int(unsigned char ch[4]) +{ + return ((opus_uint32)ch[0]<<24) | ((opus_uint32)ch[1]<<16) + | ((opus_uint32)ch[2]<< 8) | (opus_uint32)ch[3]; +} + +int main(int argc, char *argv[]) +{ + int i, eof=0; + FILE *fin, *fout; + unsigned char packets[48][1500]; + int len[48]; + int rng[48]; + OpusRepacketizer *rp; + unsigned char output_packet[MAX_PACKETOUT]; + int merge = 1, split=0; + + if (argc < 3) + { + usage(argv[0]); + return EXIT_FAILURE; + } + for (i=1;i<argc-2;i++) + { + if (strcmp(argv[i], "-merge")==0) + { + merge = atoi(argv[i+1]); + if(merge<1) + { + fprintf(stderr, "-merge parameter must be at least 1.\n"); + return EXIT_FAILURE; + } + if(merge>48) + { + fprintf(stderr, "-merge parameter must be less than 48.\n"); + return EXIT_FAILURE; + } + i++; + } else if (strcmp(argv[i], "-split")==0) + split = 1; + else + { + fprintf(stderr, "Unknown option: %s\n", argv[i]); + usage(argv[0]); + return EXIT_FAILURE; + } + } + fin = fopen(argv[argc-2], "r"); + if(fin==NULL) + { + fprintf(stderr, "Error opening input file: %s\n", argv[argc-2]); + return EXIT_FAILURE; + } + fout = fopen(argv[argc-1], "w"); + if(fout==NULL) + { + fprintf(stderr, "Error opening output file: %s\n", argv[argc-1]); + fclose(fin); + return EXIT_FAILURE; + } + + rp = opus_repacketizer_create(); + while (!eof) + { + int err; + int nb_packets=merge; + opus_repacketizer_init(rp); + for (i=0;i<nb_packets;i++) + { + unsigned char ch[4]; + err = fread(ch, 1, 4, fin); + len[i] = char_to_int(ch); + /*fprintf(stderr, "in len = %d\n", len[i]);*/ + if (len[i]>1500 || len[i]<0) + { + if (feof(fin)) + { + eof = 1; + } else { + fprintf(stderr, "Invalid payload length\n"); + fclose(fin); + fclose(fout); + return EXIT_FAILURE; + } + break; + } + err = fread(ch, 1, 4, fin); + rng[i] = char_to_int(ch); + err = fread(packets[i], 1, len[i], fin); + if (feof(fin)) + { + eof = 1; + break; + } + err = opus_repacketizer_cat(rp, packets[i], len[i]); + if (err!=OPUS_OK) + { + fprintf(stderr, "opus_repacketizer_cat() failed: %s\n", opus_strerror(err)); + break; + } + } + nb_packets = i; + + if (eof) + break; + + if (!split) + { + err = opus_repacketizer_out(rp, output_packet, MAX_PACKETOUT); + if (err>0) { + unsigned char int_field[4]; + int_to_char(err, int_field); + if(fwrite(int_field, 1, 4, fout)!=4){ + fprintf(stderr, "Error writing.\n"); + return EXIT_FAILURE; + } + int_to_char(rng[nb_packets-1], int_field); + if (fwrite(int_field, 1, 4, fout)!=4) { + fprintf(stderr, "Error writing.\n"); + return EXIT_FAILURE; + } + if (fwrite(output_packet, 1, err, fout)!=(unsigned)err) { + fprintf(stderr, "Error writing.\n"); + return EXIT_FAILURE; + } + /*fprintf(stderr, "out len = %d\n", err);*/ + } else { + fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err)); + } + } else { + int nb_frames = opus_repacketizer_get_nb_frames(rp); + for (i=0;i<nb_frames;i++) + { + err = opus_repacketizer_out_range(rp, i, i+1, output_packet, MAX_PACKETOUT); + if (err>0) { + unsigned char int_field[4]; + int_to_char(err, int_field); + if (fwrite(int_field, 1, 4, fout)!=4) { + fprintf(stderr, "Error writing.\n"); + return EXIT_FAILURE; + } + if (i==nb_frames-1) + int_to_char(rng[nb_packets-1], int_field); + else + int_to_char(0, int_field); + if (fwrite(int_field, 1, 4, fout)!=4) { + fprintf(stderr, "Error writing.\n"); + return EXIT_FAILURE; + } + if (fwrite(output_packet, 1, err, fout)!=(unsigned)err) { + fprintf(stderr, "Error writing.\n"); + return EXIT_FAILURE; + } + /*fprintf(stderr, "out len = %d\n", err);*/ + } else { + fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err)); + } + + } + } + } + + fclose(fin); + fclose(fout); + return EXIT_SUCCESS; +} diff --git a/thirdparty/opus/silk/A2NLSF.c b/thirdparty/opus/silk/A2NLSF.c new file mode 100644 index 0000000000..b6e9e5ffcc --- /dev/null +++ b/thirdparty/opus/silk/A2NLSF.c @@ -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 30 + +/* 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_SMULBB( k + 1, NLSF[ 0 ] ); + } + return; + } + + /* Error: Apply progressively more bandwidth expansion and run again */ + silk_bwexpander_32( a_Q16, d, 65536 - silk_SMULBB( 10 + i, i ) ); /* 10_Q16 = 0.00015*/ + + 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/thirdparty/opus/silk/API.h b/thirdparty/opus/silk/API.h new file mode 100644 index 0000000000..0131acbb08 --- /dev/null +++ b/thirdparty/opus/silk/API.h @@ -0,0 +1,134 @@ +/*********************************************************************** +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 __cplusplus +extern "C" +{ +#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 */ +); + +/*************************/ +/* Init or reset encoder */ +/*************************/ +opus_int silk_InitEncoder( /* O Returns error code */ + void *encState, /* I/O State */ + 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_int16 *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 */ +); + +/****************************************/ +/* Decoder functions */ +/****************************************/ + +/***********************************************/ +/* 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 or Reset decoder */ +/*************************/ +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_int16 *samplesOut, /* O Decoded output speech vector */ + opus_int32 *nSamplesOut, /* O Number of samples decoded */ + 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 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/opus/silk/CNG.c b/thirdparty/opus/silk/CNG.c new file mode 100644 index 0000000000..61787c2302 --- /dev/null +++ b/thirdparty/opus/silk/CNG.c @@ -0,0 +1,181 @@ +/*********************************************************************** +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_Q10[], /* O CNG excitation signal Q10 */ + opus_int32 exc_buf_Q14[], /* I Random samples buffer Q10 */ + opus_int32 Gain_Q16, /* I Gain to apply */ + 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_Q10[ i ] = (opus_int16)silk_SAT16( silk_SMULWW( exc_buf_Q14[ idx ], Gain_Q16 >> 4 ) ); + } + *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 sum_Q6, max_Gain_Q16, gain_Q16; + 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 ); + } + } + + /* Add CNG when packet is lost or during DTX */ + if( psDec->lossCnt ) { + VARDECL( opus_int32, CNG_sig_Q10 ); + ALLOC( CNG_sig_Q10, 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 ); + } + silk_CNG_exc( CNG_sig_Q10 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, gain_Q16, length, &psCNG->rand_seed ); + + /* Convert CNG NLSF to filter representation */ + silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order ); + + /* Generate CNG signal, by synthesis filtering */ + silk_memcpy( CNG_sig_Q10, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) ); + for( i = 0; i < length; i++ ) { + silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 ); + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + sum_Q6 = silk_RSHIFT( psDec->LPC_order, 1 ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] ); + if( psDec->LPC_order == 16 ) { + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] ); + } + + /* Update states */ + CNG_sig_Q10[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q10[ MAX_LPC_ORDER + i ], sum_Q6, 4 ); + + frame[ i ] = silk_ADD_SAT16( frame[ i ], silk_RSHIFT_ROUND( CNG_sig_Q10[ MAX_LPC_ORDER + i ], 10 ) ); + } + silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q10[ 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/thirdparty/opus/silk/HP_variable_cutoff.c b/thirdparty/opus/silk/HP_variable_cutoff.c new file mode 100644 index 0000000000..bbe10f04ce --- /dev/null +++ b/thirdparty/opus/silk/HP_variable_cutoff.c @@ -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/drivers/opus/silk/Inlines.h b/thirdparty/opus/silk/Inlines.h index ec986cdfdd..ec986cdfdd 100644 --- a/drivers/opus/silk/Inlines.h +++ b/thirdparty/opus/silk/Inlines.h diff --git a/thirdparty/opus/silk/LPC_analysis_filter.c b/thirdparty/opus/silk/LPC_analysis_filter.c new file mode 100644 index 0000000000..20906673ff --- /dev/null +++ b/thirdparty/opus/silk/LPC_analysis_filter.c @@ -0,0 +1,108 @@ +/*********************************************************************** +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 */ +/*******************************************/ + +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; +#ifdef FIXED_POINT + opus_int16 mem[SILK_MAX_ORDER_LPC]; + opus_int16 num[SILK_MAX_ORDER_LPC]; +#else + int ix; + opus_int32 out32_Q12, out32; + const opus_int16 *in_ptr; +#endif + + silk_assert( d >= 6 ); + silk_assert( (d & 1) == 0 ); + silk_assert( d <= len ); + +#ifdef FIXED_POINT + silk_assert( d <= SILK_MAX_ORDER_LPC ); + for ( j = 0; j < d; j++ ) { + num[ j ] = -B[ j ]; + } + for (j=0;j<d;j++) { + mem[ j ] = in[ d - j - 1 ]; + } + celt_fir( in + d, num, out + d, len - d, d, mem, 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/thirdparty/opus/silk/LPC_inv_pred_gain.c b/thirdparty/opus/silk/LPC_inv_pred_gain.c new file mode 100644 index 0000000000..4af89aa5fa --- /dev/null +++ b/thirdparty/opus/silk/LPC_inv_pred_gain.c @@ -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 + +#include "SigProc_FIX.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( /* O Returns inverse prediction gain in energy domain, Q30 */ + opus_int32 A_QA[ 2 ][ 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, tmp_QA; + opus_int32 *Aold_QA, *Anew_QA; + + Anew_QA = A_QA[ order & 1 ]; + + invGain_Q30 = (opus_int32)1 << 30; + for( k = order - 1; k > 0; k-- ) { + /* Check for stability */ + if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) { + return 0; + } + + /* Set RC equal to negated AR coef */ + rc_Q31 = -silk_LSHIFT( Anew_QA[ k ], 31 - QA ); + + /* rc_mult1_Q30 range: [ 1 : 2^30 ] */ + rc_mult1_Q30 = ( (opus_int32)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 ) ); + + /* 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 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 ) ); + + /* Swap pointers */ + Aold_QA = Anew_QA; + Anew_QA = A_QA[ k & 1 ]; + + /* Update AR coefficient */ + for( n = 0; n < k; n++ ) { + tmp_QA = Aold_QA[ n ] - MUL32_FRAC_Q( Aold_QA[ k - n - 1 ], rc_Q31, 31 ); + Anew_QA[ n ] = MUL32_FRAC_Q( tmp_QA, rc_mult2 , mult2Q ); + } + } + + /* Check for stability */ + if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) { + return 0; + } + + /* Set RC equal to negated AR coef */ + rc_Q31 = -silk_LSHIFT( Anew_QA[ 0 ], 31 - QA ); + + /* Range: [ 1 : 2^30 ] */ + rc_mult1_Q30 = ( (opus_int32)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 ); + + return invGain_Q30; +} + +/* For input in Q12 domain */ +opus_int32 silk_LPC_inverse_pred_gain( /* 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[ 2 ][ SILK_MAX_ORDER_LPC ]; + opus_int32 *Anew_QA; + opus_int32 DC_resp = 0; + + Anew_QA = Atmp_QA[ order & 1 ]; + + /* Increase Q domain of the AR coefficients */ + for( k = 0; k < order; k++ ) { + DC_resp += (opus_int32)A_Q12[ k ]; + Anew_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( Atmp_QA, order ); +} + +#ifdef FIXED_POINT + +/* For input in Q24 domain */ +opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */ + const opus_int32 *A_Q24, /* I Prediction coefficients [order] */ + const opus_int order /* I Prediction order */ +) +{ + opus_int k; + opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ]; + opus_int32 *Anew_QA; + + Anew_QA = Atmp_QA[ order & 1 ]; + + /* Increase Q domain of the AR coefficients */ + for( k = 0; k < order; k++ ) { + Anew_QA[ k ] = silk_RSHIFT32( A_Q24[ k ], 24 - QA ); + } + + return LPC_inverse_pred_gain_QA( Atmp_QA, order ); +} +#endif diff --git a/thirdparty/opus/silk/LP_variable_cutoff.c b/thirdparty/opus/silk/LP_variable_cutoff.c new file mode 100644 index 0000000000..f639e1f899 --- /dev/null +++ b/thirdparty/opus/silk/LP_variable_cutoff.c @@ -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( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length, 1); + } +} diff --git a/drivers/opus/silk/MacroCount.h b/thirdparty/opus/silk/MacroCount.h index 834817d058..834817d058 100644 --- a/drivers/opus/silk/MacroCount.h +++ b/thirdparty/opus/silk/MacroCount.h diff --git a/drivers/opus/silk/MacroDebug.h b/thirdparty/opus/silk/MacroDebug.h index 35aedc5c5f..35aedc5c5f 100644 --- a/drivers/opus/silk/MacroDebug.h +++ b/thirdparty/opus/silk/MacroDebug.h diff --git a/thirdparty/opus/silk/NLSF2A.c b/thirdparty/opus/silk/NLSF2A.c new file mode 100644 index 0000000000..b1c559ea68 --- /dev/null +++ b/thirdparty/opus/silk/NLSF2A.c @@ -0,0 +1,178 @@ +/*********************************************************************** +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) */ +) +{ + /* 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 ]; + opus_int32 maxabs, absval, idx=0, sc_Q16; + + silk_assert( LSF_COS_TAB_SZ_FIX == 128 ); + silk_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 */ + } + + /* 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( a32_QA1[k] ); + if( absval > maxabs ) { + maxabs = absval; + idx = k; + } + } + maxabs = silk_RSHIFT_ROUND( maxabs, QA + 1 - 12 ); /* QA+1 -> Q12 */ + + if( maxabs > silk_int16_MAX ) { + /* Reduce magnitude of prediction coefficients */ + maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */ + sc_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( a32_QA1, d, sc_Q16 ); + } else { + break; + } + } + + if( i == 10 ) { + /* Reached the last iteration, clip the coefficients */ + for( k = 0; k < d; k++ ) { + a_Q12[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) ); /* QA+1 -> Q12 */ + a32_QA1[ k ] = silk_LSHIFT( (opus_int32)a_Q12[ k ], QA + 1 - 12 ); + } + } else { + for( k = 0; k < d; k++ ) { + a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */ + } + } + + for( i = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) { + if( silk_LPC_inverse_pred_gain( a_Q12, d ) < SILK_FIX_CONST( 1.0 / MAX_PREDICTION_POWER_GAIN, 30 ) ) { + /* 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 */ + } + } else { + break; + } + } +} + diff --git a/thirdparty/opus/silk/NLSF_VQ.c b/thirdparty/opus/silk/NLSF_VQ.c new file mode 100644 index 0000000000..69b6e22e18 --- /dev/null +++ b/thirdparty/opus/silk/NLSF_VQ.c @@ -0,0 +1,68 @@ +/*********************************************************************** +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" + +/* 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_int K, /* I Number of codebook vectors */ + const opus_int LPC_order /* I Number of LPCs */ +) +{ + opus_int i, m; + opus_int32 diff_Q15, sum_error_Q30, sum_error_Q26; + + silk_assert( LPC_order <= 16 ); + silk_assert( ( LPC_order & 1 ) == 0 ); + + /* Loop over codebook */ + for( i = 0; i < K; i++ ) { + sum_error_Q26 = 0; + for( m = 0; m < LPC_order; m += 2 ) { + /* Compute weighted squared quantization error for index m */ + diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/ + sum_error_Q30 = silk_SMULBB( diff_Q15, diff_Q15 ); + + /* Compute weighted squared quantization error for index m + 1 */ + diff_Q15 = silk_SUB_LSHIFT32( in_Q15[m + 1], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/ + sum_error_Q30 = silk_SMLABB( sum_error_Q30, diff_Q15, diff_Q15 ); + + sum_error_Q26 = silk_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 ); + + silk_assert( sum_error_Q26 >= 0 ); + silk_assert( sum_error_Q30 >= 0 ); + } + err_Q26[ i ] = sum_error_Q26; + } +} diff --git a/thirdparty/opus/silk/NLSF_VQ_weights_laroia.c b/thirdparty/opus/silk/NLSF_VQ_weights_laroia.c new file mode 100644 index 0000000000..04894c59ab --- /dev/null +++ b/thirdparty/opus/silk/NLSF_VQ_weights_laroia.c @@ -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; + + silk_assert( D > 0 ); + silk_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/thirdparty/opus/silk/NLSF_decode.c b/thirdparty/opus/silk/NLSF_decode.c new file mode 100644 index 0000000000..9f715060b8 --- /dev/null +++ b/thirdparty/opus/silk/NLSF_decode.c @@ -0,0 +1,101 @@ +/*********************************************************************** +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_int16 W_tmp_QW[ MAX_LPC_ORDER ]; + opus_int32 W_tmp_Q9, NLSF_Q15_tmp; + const opus_uint8 *pCB_element; + + /* Decode first stage */ + pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ]; + for( i = 0; i < psNLSF_CB->order; i++ ) { + pNLSF_Q15[ i ] = silk_LSHIFT( (opus_int16)pCB_element[ i ], 7 ); + } + + /* 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 ); + + /* Weights from codebook vector */ + silk_NLSF_VQ_weights_laroia( W_tmp_QW, pNLSF_Q15, psNLSF_CB->order ); + + /* Apply inverse square-rooted weights and add to output */ + for( i = 0; i < psNLSF_CB->order; i++ ) { + W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) ); + NLSF_Q15_tmp = silk_ADD32( pNLSF_Q15[ i ], silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), W_tmp_Q9 ) ); + 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/thirdparty/opus/silk/NLSF_del_dec_quant.c b/thirdparty/opus/silk/NLSF_del_dec_quant.c new file mode 100644 index 0000000000..c3b9efccfa --- /dev/null +++ b/thirdparty/opus/silk/NLSF_del_dec_quant.c @@ -0,0 +1,217 @@ +/*********************************************************************** +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" + +/* 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 */ +) +{ + opus_int i, j, nStates, ind_tmp, ind_min_max, ind_max_min, in_Q10, res_Q10; + opus_int pred_Q10, diff_Q10, out0_Q10, out1_Q10, rate0_Q5, rate1_Q5; + opus_int32 RD_tmp_Q25, min_Q25, min_max_Q25, max_min_Q25, pred_coef_Q16; + opus_int ind_sort[ NLSF_QUANT_DEL_DEC_STATES ]; + opus_int8 ind[ NLSF_QUANT_DEL_DEC_STATES ][ MAX_LPC_ORDER ]; + opus_int16 prev_out_Q10[ 2 * NLSF_QUANT_DEL_DEC_STATES ]; + opus_int32 RD_Q25[ 2 * NLSF_QUANT_DEL_DEC_STATES ]; + opus_int32 RD_min_Q25[ NLSF_QUANT_DEL_DEC_STATES ]; + opus_int32 RD_max_Q25[ NLSF_QUANT_DEL_DEC_STATES ]; + const opus_uint8 *rates_Q5; + + opus_int out0_Q10_table[2 * NLSF_QUANT_MAX_AMPLITUDE_EXT]; + opus_int out1_Q10_table[2 * NLSF_QUANT_MAX_AMPLITUDE_EXT]; + + for (i = -NLSF_QUANT_MAX_AMPLITUDE_EXT; i <= NLSF_QUANT_MAX_AMPLITUDE_EXT-1; i++) + { + out0_Q10 = silk_LSHIFT( i, 10 ); + out1_Q10 = silk_ADD16( out0_Q10, 1024 ); + if( i > 0 ) { + out0_Q10 = silk_SUB16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } else if( i == 0 ) { + out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } else if( i == -1 ) { + out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } else { + out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + out1_Q10 = silk_ADD16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } + out0_Q10_table[ i + NLSF_QUANT_MAX_AMPLITUDE_EXT ] = silk_SMULWB( (opus_int32)out0_Q10, quant_step_size_Q16 ); + out1_Q10_table[ i + NLSF_QUANT_MAX_AMPLITUDE_EXT ] = silk_SMULWB( (opus_int32)out1_Q10, quant_step_size_Q16 ); + } + + silk_assert( (NLSF_QUANT_DEL_DEC_STATES & (NLSF_QUANT_DEL_DEC_STATES-1)) == 0 ); /* must be power of two */ + + nStates = 1; + RD_Q25[ 0 ] = 0; + prev_out_Q10[ 0 ] = 0; + for( i = order - 1; ; i-- ) { + rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ]; + pred_coef_Q16 = silk_LSHIFT( (opus_int32)pred_coef_Q8[ i ], 8 ); + in_Q10 = x_Q10[ i ]; + for( j = 0; j < nStates; j++ ) { + pred_Q10 = silk_SMULWB( pred_coef_Q16, prev_out_Q10[ j ] ); + res_Q10 = silk_SUB16( in_Q10, pred_Q10 ); + ind_tmp = silk_SMULWB( (opus_int32)inv_quant_step_size_Q6, res_Q10 ); + ind_tmp = silk_LIMIT( ind_tmp, -NLSF_QUANT_MAX_AMPLITUDE_EXT, NLSF_QUANT_MAX_AMPLITUDE_EXT-1 ); + ind[ j ][ i ] = (opus_int8)ind_tmp; + + /* compute outputs for ind_tmp and ind_tmp + 1 */ + out0_Q10 = out0_Q10_table[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE_EXT ]; + out1_Q10 = out1_Q10_table[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE_EXT ]; + + out0_Q10 = silk_ADD16( out0_Q10, pred_Q10 ); + out1_Q10 = silk_ADD16( out1_Q10, pred_Q10 ); + prev_out_Q10[ j ] = out0_Q10; + prev_out_Q10[ j + nStates ] = out1_Q10; + + /* compute RD for ind_tmp and ind_tmp + 1 */ + if( ind_tmp + 1 >= NLSF_QUANT_MAX_AMPLITUDE ) { + if( ind_tmp + 1 == NLSF_QUANT_MAX_AMPLITUDE ) { + rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ]; + rate1_Q5 = 280; + } else { + rate0_Q5 = silk_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, 43, ind_tmp ); + rate1_Q5 = silk_ADD16( rate0_Q5, 43 ); + } + } else if( ind_tmp <= -NLSF_QUANT_MAX_AMPLITUDE ) { + if( ind_tmp == -NLSF_QUANT_MAX_AMPLITUDE ) { + rate0_Q5 = 280; + rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ]; + } else { + rate0_Q5 = silk_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, -43, ind_tmp ); + rate1_Q5 = silk_SUB16( rate0_Q5, 43 ); + } + } else { + rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ]; + rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ]; + } + RD_tmp_Q25 = RD_Q25[ j ]; + diff_Q10 = silk_SUB16( in_Q10, out0_Q10 ); + RD_Q25[ j ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate0_Q5 ); + diff_Q10 = silk_SUB16( in_Q10, out1_Q10 ); + RD_Q25[ j + nStates ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate1_Q5 ); + } + + if( nStates <= ( NLSF_QUANT_DEL_DEC_STATES >> 1 ) ) { + /* double number of states and copy */ + for( j = 0; j < nStates; j++ ) { + ind[ j + nStates ][ i ] = ind[ j ][ i ] + 1; + } + nStates = silk_LSHIFT( nStates, 1 ); + for( j = nStates; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { + ind[ j ][ i ] = ind[ j - nStates ][ i ]; + } + } else if( i > 0 ) { + /* sort lower and upper half of RD_Q25, pairwise */ + for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { + if( RD_Q25[ j ] > RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] ) { + RD_max_Q25[ j ] = RD_Q25[ j ]; + RD_min_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ]; + RD_Q25[ j ] = RD_min_Q25[ j ]; + RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] = RD_max_Q25[ j ]; + /* swap prev_out values */ + out0_Q10 = prev_out_Q10[ j ]; + prev_out_Q10[ j ] = prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ]; + prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ] = out0_Q10; + ind_sort[ j ] = j + NLSF_QUANT_DEL_DEC_STATES; + } else { + RD_min_Q25[ j ] = RD_Q25[ j ]; + RD_max_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ]; + ind_sort[ j ] = j; + } + } + /* compare the highest RD values of the winning half with the lowest one in the losing half, and copy if necessary */ + /* afterwards ind_sort[] will contain the indices of the NLSF_QUANT_DEL_DEC_STATES winning RD values */ + while( 1 ) { + min_max_Q25 = silk_int32_MAX; + max_min_Q25 = 0; + ind_min_max = 0; + ind_max_min = 0; + for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { + if( min_max_Q25 > RD_max_Q25[ j ] ) { + min_max_Q25 = RD_max_Q25[ j ]; + ind_min_max = j; + } + if( max_min_Q25 < RD_min_Q25[ j ] ) { + max_min_Q25 = RD_min_Q25[ j ]; + ind_max_min = j; + } + } + if( min_max_Q25 >= max_min_Q25 ) { + break; + } + /* copy ind_min_max to ind_max_min */ + ind_sort[ ind_max_min ] = ind_sort[ ind_min_max ] ^ NLSF_QUANT_DEL_DEC_STATES; + RD_Q25[ ind_max_min ] = RD_Q25[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ]; + prev_out_Q10[ ind_max_min ] = prev_out_Q10[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ]; + RD_min_Q25[ ind_max_min ] = 0; + RD_max_Q25[ ind_min_max ] = silk_int32_MAX; + silk_memcpy( ind[ ind_max_min ], ind[ ind_min_max ], MAX_LPC_ORDER * sizeof( opus_int8 ) ); + } + /* increment index if it comes from the upper half */ + for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { + ind[ j ][ i ] += silk_RSHIFT( ind_sort[ j ], NLSF_QUANT_DEL_DEC_STATES_LOG2 ); + } + } else { /* i == 0 */ + break; + } + } + + /* last sample: find winner, copy indices and return RD value */ + ind_tmp = 0; + min_Q25 = silk_int32_MAX; + for( j = 0; j < 2 * NLSF_QUANT_DEL_DEC_STATES; j++ ) { + if( min_Q25 > RD_Q25[ j ] ) { + min_Q25 = RD_Q25[ j ]; + ind_tmp = j; + } + } + for( j = 0; j < order; j++ ) { + indices[ j ] = ind[ ind_tmp & ( NLSF_QUANT_DEL_DEC_STATES - 1 ) ][ j ]; + silk_assert( indices[ j ] >= -NLSF_QUANT_MAX_AMPLITUDE_EXT ); + silk_assert( indices[ j ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT ); + } + indices[ 0 ] += silk_RSHIFT( ind_tmp, NLSF_QUANT_DEL_DEC_STATES_LOG2 ); + silk_assert( indices[ 0 ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT ); + silk_assert( min_Q25 >= 0 ); + return min_Q25; +} diff --git a/thirdparty/opus/silk/NLSF_encode.c b/thirdparty/opus/silk/NLSF_encode.c new file mode 100644 index 0000000000..03a036fda2 --- /dev/null +++ b/thirdparty/opus/silk/NLSF_encode.c @@ -0,0 +1,136 @@ +/*********************************************************************** +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" + +/***********************/ +/* NLSF vector encoder */ +/***********************/ +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 */ +) +{ + opus_int i, s, ind1, bestIndex, prob_Q8, bits_q7; + opus_int32 W_tmp_Q9; + VARDECL( opus_int32, err_Q26 ); + VARDECL( opus_int32, RD_Q25 ); + VARDECL( opus_int, tempIndices1 ); + VARDECL( opus_int8, tempIndices2 ); + opus_int16 res_Q15[ MAX_LPC_ORDER ]; + opus_int16 res_Q10[ MAX_LPC_ORDER ]; + opus_int16 NLSF_tmp_Q15[ MAX_LPC_ORDER ]; + opus_int16 W_tmp_QW[ MAX_LPC_ORDER ]; + opus_int16 W_adj_Q5[ MAX_LPC_ORDER ]; + opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; + opus_int16 ec_ix[ MAX_LPC_ORDER ]; + const opus_uint8 *pCB_element, *iCDF_ptr; + SAVE_STACK; + + silk_assert( nSurvivors <= NLSF_VQ_MAX_SURVIVORS ); + silk_assert( signalType >= 0 && signalType <= 2 ); + silk_assert( NLSF_mu_Q20 <= 32767 && NLSF_mu_Q20 >= 0 ); + + /* NLSF stabilization */ + silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order ); + + /* First stage: VQ */ + ALLOC( err_Q26, psNLSF_CB->nVectors, opus_int32 ); + silk_NLSF_VQ( err_Q26, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->nVectors, psNLSF_CB->order ); + + /* Sort the quantization errors */ + ALLOC( tempIndices1, nSurvivors, opus_int ); + silk_insertion_sort_increasing( err_Q26, tempIndices1, psNLSF_CB->nVectors, nSurvivors ); + + ALLOC( RD_Q25, nSurvivors, opus_int32 ); + ALLOC( tempIndices2, nSurvivors * MAX_LPC_ORDER, opus_int8 ); + + /* Loop over survivors */ + for( s = 0; s < nSurvivors; s++ ) { + ind1 = tempIndices1[ s ]; + + /* Residual after first stage */ + pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ]; + for( i = 0; i < psNLSF_CB->order; i++ ) { + NLSF_tmp_Q15[ i ] = silk_LSHIFT16( (opus_int16)pCB_element[ i ], 7 ); + res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ]; + } + + /* Weights from codebook vector */ + silk_NLSF_VQ_weights_laroia( W_tmp_QW, NLSF_tmp_Q15, psNLSF_CB->order ); + + /* Apply square-rooted weights */ + for( i = 0; i < psNLSF_CB->order; i++ ) { + W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) ); + res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 ); + } + + /* Modify input weights accordingly */ + for( i = 0; i < psNLSF_CB->order; i++ ) { + W_adj_Q5[ i ] = silk_DIV32_16( silk_LSHIFT( (opus_int32)pW_QW[ i ], 5 ), W_tmp_QW[ i ] ); + } + + /* Unpack entropy table indices and predictor for current CB1 index */ + silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, ind1 ); + + /* Trellis quantizer */ + RD_Q25[ s ] = silk_NLSF_del_dec_quant( &tempIndices2[ s * MAX_LPC_ORDER ], res_Q10, W_adj_Q5, pred_Q8, ec_ix, + psNLSF_CB->ec_Rates_Q5, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->invQuantStepSize_Q6, NLSF_mu_Q20, psNLSF_CB->order ); + + /* Add rate for first stage */ + iCDF_ptr = &psNLSF_CB->CB1_iCDF[ ( signalType >> 1 ) * psNLSF_CB->nVectors ]; + if( ind1 == 0 ) { + prob_Q8 = 256 - iCDF_ptr[ ind1 ]; + } else { + prob_Q8 = iCDF_ptr[ ind1 - 1 ] - iCDF_ptr[ ind1 ]; + } + bits_q7 = ( 8 << 7 ) - silk_lin2log( prob_Q8 ); + RD_Q25[ s ] = silk_SMLABB( RD_Q25[ s ], bits_q7, silk_RSHIFT( NLSF_mu_Q20, 2 ) ); + } + + /* Find the lowest rate-distortion error */ + silk_insertion_sort_increasing( RD_Q25, &bestIndex, nSurvivors, 1 ); + + NLSFIndices[ 0 ] = (opus_int8)tempIndices1[ bestIndex ]; + silk_memcpy( &NLSFIndices[ 1 ], &tempIndices2[ bestIndex * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) ); + + /* Decode */ + silk_NLSF_decode( pNLSF_Q15, NLSFIndices, psNLSF_CB ); + + RESTORE_STACK; + return RD_Q25[ 0 ]; +} diff --git a/thirdparty/opus/silk/NLSF_stabilize.c b/thirdparty/opus/silk/NLSF_stabilize.c new file mode 100644 index 0000000000..1fa1ea379b --- /dev/null +++ b/thirdparty/opus/silk/NLSF_stabilize.c @@ -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], 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/thirdparty/opus/silk/NLSF_unpack.c b/thirdparty/opus/silk/NLSF_unpack.c new file mode 100644 index 0000000000..17bd23f752 --- /dev/null +++ b/thirdparty/opus/silk/NLSF_unpack.c @@ -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 "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/thirdparty/opus/silk/NSQ.c b/thirdparty/opus/silk/NSQ.c new file mode 100644 index 0000000000..a065884070 --- /dev/null +++ b/thirdparty/opus/silk/NSQ.c @@ -0,0 +1,453 @@ +/*********************************************************************** +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" + +static OPUS_INLINE void silk_nsq_scale_states( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + const opus_int32 x_Q3[], /* I input in Q3 */ + opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */ + const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */ + opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ + opus_int subfr, /* I subframe number */ + const opus_int LTP_scale_Q14, /* I */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ + const opus_int signal_type /* I Signal type */ +); + +#if !defined(OPUS_X86_MAY_HAVE_SSE4_1) +static OPUS_INLINE 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 */ +); +#endif + +void silk_NSQ_c +( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_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 */ +) +{ + opus_int k, lag, start_idx, LSF_interpolation_flag; + const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; + opus_int16 *pxq; + VARDECL( opus_int32, sLTP_Q15 ); + VARDECL( opus_int16, sLTP ); + opus_int32 HarmShapeFIRPacked_Q14; + opus_int offset_Q10; + VARDECL( opus_int32, x_sc_Q10 ); + SAVE_STACK; + + NSQ->rand_seed = psIndices->Seed; + + /* Set unvoiced lag to the previous one, overwrite later for voiced */ + lag = NSQ->lagPrev; + + silk_assert( NSQ->prev_gain_Q16 != 0 ); + + offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; + + if( psIndices->NLSFInterpCoef_Q2 == 4 ) { + LSF_interpolation_flag = 0; + } else { + LSF_interpolation_flag = 1; + } + + ALLOC( sLTP_Q15, + psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 ); + ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 ); + ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 ); + /* Set up pointers to start of sub frame */ + NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; + for( k = 0; k < psEncC->nb_subfr; k++ ) { + A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ]; + B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; + AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; + + /* Noise shape parameters */ + silk_assert( HarmShapeGain_Q14[ k ] >= 0 ); + HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); + HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); + + NSQ->rewhite_flag = 0; + if( psIndices->signalType == TYPE_VOICED ) { + /* Voiced */ + lag = pitchL[ k ]; + + /* Re-whitening */ + if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { + /* Rewhiten with new A coefs */ + start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; + silk_assert( start_idx > 0 ); + + silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], + A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch ); + + NSQ->rewhite_flag = 1; + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + } + } + + silk_nsq_scale_states( psEncC, NSQ, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType ); + + silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14, + AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10, + offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder ); + + x_Q3 += psEncC->subfr_length; + pulses += psEncC->subfr_length; + pxq += psEncC->subfr_length; + } + + /* Update lagPrev for next frame */ + NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; + + /* Save quantized speech and noise shaping signals */ + /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */ + silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); + silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); + RESTORE_STACK; +} + +/***********************************/ +/* silk_noise_shape_quantizer */ +/***********************************/ + +#if !defined(OPUS_X86_MAY_HAVE_SSE4_1) +static OPUS_INLINE +#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 */ +) +{ + opus_int i, j; + opus_int32 LTP_pred_Q13, LPC_pred_Q10, n_AR_Q12, n_LTP_Q13; + opus_int32 n_LF_Q12, r_Q10, rr_Q10, q1_Q0, q1_Q10, q2_Q10, rd1_Q20, rd2_Q20; + opus_int32 exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10; + opus_int32 tmp1, tmp2, sLF_AR_shp_Q14; + opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr; + + shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; + pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 ); + + /* Set up short term AR state */ + psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ]; + + for( i = 0; i < length; i++ ) { + /* Generate dither */ + NSQ->rand_seed = silk_RAND( NSQ->rand_seed ); + + /* Short-term prediction */ + silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 ); + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LPC_pred_Q10 = silk_RSHIFT( predictLPCOrder, 1 ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ 0 ], a_Q12[ 0 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); + if( predictLPCOrder == 16 ) { + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -10 ], a_Q12[ 10 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -11 ], a_Q12[ 11 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -12 ], a_Q12[ 12 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -13 ], a_Q12[ 13 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -14 ], a_Q12[ 14 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -15 ], a_Q12[ 15 ] ); + } + + /* Long-term prediction */ + if( signalType == TYPE_VOICED ) { + /* 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++; + } else { + LTP_pred_Q13 = 0; + } + + /* Noise shape feedback */ + silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ + tmp2 = psLPC_Q14[ 0 ]; + tmp1 = NSQ->sAR2_Q14[ 0 ]; + NSQ->sAR2_Q14[ 0 ] = tmp2; + n_AR_Q12 = silk_RSHIFT( shapingLPCOrder, 1 ); + n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp2, AR_shp_Q13[ 0 ] ); + for( j = 2; j < shapingLPCOrder; j += 2 ) { + tmp2 = NSQ->sAR2_Q14[ j - 1 ]; + NSQ->sAR2_Q14[ j - 1 ] = tmp1; + n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp1, AR_shp_Q13[ j - 1 ] ); + tmp1 = NSQ->sAR2_Q14[ j + 0 ]; + NSQ->sAR2_Q14[ j + 0 ] = tmp2; + n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp2, AR_shp_Q13[ j ] ); + } + NSQ->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1; + n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] ); + + n_AR_Q12 = silk_LSHIFT32( n_AR_Q12, 1 ); /* Q11 -> Q12 */ + n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sLF_AR_shp_Q14, Tilt_Q14 ); + + n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 ); + n_LF_Q12 = silk_SMLAWT( n_LF_Q12, NSQ->sLF_AR_shp_Q14, LF_shp_Q14 ); + + silk_assert( lag > 0 || signalType != TYPE_VOICED ); + + /* Combine prediction and noise shaping signals */ + tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */ + tmp1 = silk_SUB32( tmp1, n_LF_Q12 ); /* Q12 */ + if( lag > 0 ) { + /* Symmetric, packed FIR coefficients */ + n_LTP_Q13 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); + n_LTP_Q13 = silk_SMLAWT( n_LTP_Q13, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); + n_LTP_Q13 = silk_LSHIFT( n_LTP_Q13, 1 ); + shp_lag_ptr++; + + tmp2 = silk_SUB32( LTP_pred_Q13, n_LTP_Q13 ); /* Q13 */ + tmp1 = silk_ADD_LSHIFT32( tmp2, tmp1, 1 ); /* Q13 */ + tmp1 = silk_RSHIFT_ROUND( tmp1, 3 ); /* Q10 */ + } else { + tmp1 = silk_RSHIFT_ROUND( tmp1, 2 ); /* Q10 */ + } + + r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */ + + /* Flip sign depending on dither */ + if ( NSQ->rand_seed < 0 ) { + r_Q10 = -r_Q10; + } + r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 ); + + /* Find two quantization level candidates and measure their rate-distortion */ + q1_Q10 = silk_SUB32( r_Q10, offset_Q10 ); + q1_Q0 = silk_RSHIFT( q1_Q10, 10 ); + if( q1_Q0 > 0 ) { + q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = silk_ADD32( q1_Q10, 1024 ); + rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q0 == 0 ) { + q1_Q10 = offset_Q10; + q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q0 == -1 ) { + q2_Q10 = offset_Q10; + q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q20 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else { /* Q1_Q0 < -1 */ + q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = silk_ADD32( q1_Q10, 1024 ); + rd1_Q20 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q20 = silk_SMULBB( -q2_Q10, Lambda_Q10 ); + } + rr_Q10 = silk_SUB32( r_Q10, q1_Q10 ); + rd1_Q20 = silk_SMLABB( rd1_Q20, rr_Q10, rr_Q10 ); + rr_Q10 = silk_SUB32( r_Q10, q2_Q10 ); + rd2_Q20 = silk_SMLABB( rd2_Q20, rr_Q10, rr_Q10 ); + + if( rd2_Q20 < rd1_Q20 ) { + q1_Q10 = q2_Q10; + } + + pulses[ i ] = (opus_int8)silk_RSHIFT_ROUND( q1_Q10, 10 ); + + /* Excitation */ + exc_Q14 = silk_LSHIFT( q1_Q10, 4 ); + if ( NSQ->rand_seed < 0 ) { + exc_Q14 = -exc_Q14; + } + + /* Add predictions */ + LPC_exc_Q14 = silk_ADD_LSHIFT32( exc_Q14, LTP_pred_Q13, 1 ); + xq_Q14 = silk_ADD_LSHIFT32( LPC_exc_Q14, LPC_pred_Q10, 4 ); + + /* Scale XQ back to normal level before saving */ + xq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( xq_Q14, Gain_Q10 ), 8 ) ); + + /* Update states */ + psLPC_Q14++; + *psLPC_Q14 = xq_Q14; + sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, n_AR_Q12, 2 ); + NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14; + + NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 ); + sLTP_Q15[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q14, 1 ); + NSQ->sLTP_shp_buf_idx++; + NSQ->sLTP_buf_idx++; + + /* Make dither dependent on quantized signal */ + NSQ->rand_seed = silk_ADD32_ovflw( NSQ->rand_seed, pulses[ i ] ); + } + + /* Update LPC synth buffer */ + silk_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); +} + +static OPUS_INLINE void silk_nsq_scale_states( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + const opus_int32 x_Q3[], /* I input in Q3 */ + opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */ + const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */ + opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ + opus_int subfr, /* I subframe number */ + const opus_int LTP_scale_Q14, /* I */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ + const opus_int signal_type /* I Signal type */ +) +{ + opus_int i, lag; + opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23; + + lag = pitchL[ subfr ]; + inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 ); + silk_assert( inv_gain_Q31 != 0 ); + + /* Calculate gain adjustment factor */ + if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) { + gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 ); + } else { + gain_adj_Q16 = (opus_int32)1 << 16; + } + + /* Scale input */ + inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 ); + for( i = 0; i < psEncC->subfr_length; i++ ) { + x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 ); + } + + /* Save inverse gain */ + NSQ->prev_gain_Q16 = Gains_Q16[ subfr ]; + + /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ + if( NSQ->rewhite_flag ) { + if( subfr == 0 ) { + /* Do LTP downscaling */ + inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 ); + } + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { + silk_assert( i < MAX_FRAME_LENGTH ); + sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] ); + } + } + + /* Adjust for changing gain */ + if( gain_adj_Q16 != (opus_int32)1 << 16 ) { + /* Scale long-term shaping state */ + for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) { + NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] ); + } + + /* Scale long-term prediction state */ + if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) { + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { + sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] ); + } + } + + NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 ); + + /* Scale short-term prediction and shaping states */ + for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { + NSQ->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] ); + } + for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { + NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] ); + } + } +} diff --git a/thirdparty/opus/silk/NSQ.h b/thirdparty/opus/silk/NSQ.h new file mode 100644 index 0000000000..971832f660 --- /dev/null +++ b/thirdparty/opus/silk/NSQ.h @@ -0,0 +1,101 @@ +/*********************************************************************** +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 + +#endif /* SILK_NSQ_H */ diff --git a/thirdparty/opus/silk/NSQ_del_dec.c b/thirdparty/opus/silk/NSQ_del_dec.c new file mode 100644 index 0000000000..aff560c221 --- /dev/null +++ b/thirdparty/opus/silk/NSQ_del_dec.c @@ -0,0 +1,724 @@ +/*********************************************************************** +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" + +typedef struct { + opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ]; + opus_int32 RandState[ DECISION_DELAY ]; + opus_int32 Q_Q10[ DECISION_DELAY ]; + opus_int32 Xq_Q14[ DECISION_DELAY ]; + opus_int32 Pred_Q15[ DECISION_DELAY ]; + opus_int32 Shape_Q14[ DECISION_DELAY ]; + opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ]; + opus_int32 LF_AR_Q14; + opus_int32 Seed; + opus_int32 SeedInit; + opus_int32 RD_Q10; +} NSQ_del_dec_struct; + +typedef struct { + opus_int32 Q_Q10; + opus_int32 RD_Q10; + opus_int32 xq_Q14; + opus_int32 LF_AR_Q14; + opus_int32 sLTP_shp_Q14; + opus_int32 LPC_exc_Q14; +} NSQ_sample_struct; + +typedef NSQ_sample_struct NSQ_sample_pair[ 2 ]; + +#if defined(MIPSr1_ASM) +#include "mips/NSQ_del_dec_mipsr1.h" +#endif +static OPUS_INLINE void silk_nsq_del_dec_scale_states( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + const opus_int32 x_Q3[], /* I Input in Q3 */ + opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */ + const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ + opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ + opus_int subfr, /* I Subframe number */ + opus_int nStatesDelayedDecision, /* I Number of del dec states */ + const opus_int LTP_scale_Q14, /* I LTP state scaling */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ + const opus_int signal_type, /* I Signal type */ + const opus_int decisionDelay /* I Decision delay */ +); + +/******************************************/ +/* Noise shape quantizer for one subframe */ +/******************************************/ +static OPUS_INLINE void silk_noise_shape_quantizer_del_dec( + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + opus_int signalType, /* I Signal type */ + const opus_int32 x_Q10[], /* I */ + opus_int8 pulses[], /* O */ + opus_int16 xq[], /* O */ + opus_int32 sLTP_Q15[], /* I/O LTP filter state */ + opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */ + 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 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 subfr, /* I Subframe number */ + opus_int shapingLPCOrder, /* I Shaping LPC filter order */ + opus_int predictLPCOrder, /* I Prediction filter order */ + opus_int warping_Q16, /* I */ + opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ + opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ + opus_int decisionDelay /* I */ +); + +void silk_NSQ_del_dec_c( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_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 */ +) +{ + opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr; + opus_int last_smple_idx, smpl_buf_idx, decisionDelay; + const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; + opus_int16 *pxq; + VARDECL( opus_int32, sLTP_Q15 ); + VARDECL( opus_int16, sLTP ); + opus_int32 HarmShapeFIRPacked_Q14; + opus_int offset_Q10; + opus_int32 RDmin_Q10, Gain_Q10; + VARDECL( opus_int32, x_sc_Q10 ); + VARDECL( opus_int32, delayedGain_Q10 ); + VARDECL( NSQ_del_dec_struct, psDelDec ); + NSQ_del_dec_struct *psDD; + SAVE_STACK; + + /* Set unvoiced lag to the previous one, overwrite later for voiced */ + lag = NSQ->lagPrev; + + silk_assert( NSQ->prev_gain_Q16 != 0 ); + + /* Initialize delayed decision states */ + ALLOC( psDelDec, psEncC->nStatesDelayedDecision, NSQ_del_dec_struct ); + silk_memset( psDelDec, 0, psEncC->nStatesDelayedDecision * sizeof( NSQ_del_dec_struct ) ); + for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + psDD->Seed = ( k + psIndices->Seed ) & 3; + psDD->SeedInit = psDD->Seed; + psDD->RD_Q10 = 0; + psDD->LF_AR_Q14 = NSQ->sLF_AR_shp_Q14; + psDD->Shape_Q14[ 0 ] = NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ]; + silk_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); + silk_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) ); + } + + offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; + smpl_buf_idx = 0; /* index of oldest samples */ + + decisionDelay = silk_min_int( DECISION_DELAY, psEncC->subfr_length ); + + /* For voiced frames limit the decision delay to lower than the pitch lag */ + if( psIndices->signalType == TYPE_VOICED ) { + for( k = 0; k < psEncC->nb_subfr; k++ ) { + decisionDelay = silk_min_int( decisionDelay, pitchL[ k ] - LTP_ORDER / 2 - 1 ); + } + } else { + if( lag > 0 ) { + decisionDelay = silk_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 ); + } + } + + if( psIndices->NLSFInterpCoef_Q2 == 4 ) { + LSF_interpolation_flag = 0; + } else { + LSF_interpolation_flag = 1; + } + + ALLOC( sLTP_Q15, + psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 ); + ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 ); + ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 ); + ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 ); + /* Set up pointers to start of sub frame */ + pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; + NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + subfr = 0; + for( k = 0; k < psEncC->nb_subfr; k++ ) { + A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ]; + B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; + AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; + + /* Noise shape parameters */ + silk_assert( HarmShapeGain_Q14[ k ] >= 0 ); + HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); + HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); + + NSQ->rewhite_flag = 0; + if( psIndices->signalType == TYPE_VOICED ) { + /* Voiced */ + lag = pitchL[ k ]; + + /* Re-whitening */ + if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { + if( k == 2 ) { + /* RESET DELAYED DECISIONS */ + /* Find winner */ + RDmin_Q10 = psDelDec[ 0 ].RD_Q10; + Winner_ind = 0; + for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) { + if( psDelDec[ i ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psDelDec[ i ].RD_Q10; + Winner_ind = i; + } + } + for( i = 0; i < psEncC->nStatesDelayedDecision; i++ ) { + if( i != Winner_ind ) { + psDelDec[ i ].RD_Q10 += ( silk_int32_MAX >> 4 ); + silk_assert( psDelDec[ i ].RD_Q10 >= 0 ); + } + } + + /* Copy final part of signals from winner state to output and long-term filter states */ + psDD = &psDelDec[ Winner_ind ]; + last_smple_idx = smpl_buf_idx + decisionDelay; + for( i = 0; i < decisionDelay; i++ ) { + last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; + pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); + pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( + silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) ); + NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ]; + } + + subfr = 0; + } + + /* Rewhiten with new A coefs */ + start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; + silk_assert( start_idx > 0 ); + + silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], + A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch ); + + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + NSQ->rewhite_flag = 1; + } + } + + silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, + psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay ); + + silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, + delayedGain_Q10, A_Q12, B_Q14, AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], + Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder, + psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay ); + + x_Q3 += psEncC->subfr_length; + pulses += psEncC->subfr_length; + pxq += psEncC->subfr_length; + } + + /* Find winner */ + RDmin_Q10 = psDelDec[ 0 ].RD_Q10; + Winner_ind = 0; + for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) { + if( psDelDec[ k ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psDelDec[ k ].RD_Q10; + Winner_ind = k; + } + } + + /* Copy final part of signals from winner state to output and long-term filter states */ + psDD = &psDelDec[ Winner_ind ]; + psIndices->Seed = psDD->SeedInit; + last_smple_idx = smpl_buf_idx + decisionDelay; + Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 ); + for( i = 0; i < decisionDelay; i++ ) { + last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; + pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); + pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( + silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) ); + NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ]; + } + silk_memcpy( NSQ->sLPC_Q14, &psDD->sLPC_Q14[ psEncC->subfr_length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); + silk_memcpy( NSQ->sAR2_Q14, psDD->sAR2_Q14, sizeof( psDD->sAR2_Q14 ) ); + + /* Update states */ + NSQ->sLF_AR_shp_Q14 = psDD->LF_AR_Q14; + NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; + + /* Save quantized speech signal */ + /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */ + silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); + silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); + RESTORE_STACK; +} + +/******************************************/ +/* Noise shape quantizer for one subframe */ +/******************************************/ +#ifndef OVERRIDE_silk_noise_shape_quantizer_del_dec +static OPUS_INLINE void silk_noise_shape_quantizer_del_dec( + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + opus_int signalType, /* I Signal type */ + const opus_int32 x_Q10[], /* I */ + opus_int8 pulses[], /* O */ + opus_int16 xq[], /* O */ + opus_int32 sLTP_Q15[], /* I/O LTP filter state */ + opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */ + 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 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 subfr, /* I Subframe number */ + opus_int shapingLPCOrder, /* I Shaping LPC filter order */ + opus_int predictLPCOrder, /* I Prediction filter order */ + opus_int warping_Q16, /* I */ + opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ + opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ + opus_int decisionDelay /* I */ +) +{ + opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx; + opus_int32 Winner_rand_state; + opus_int32 LTP_pred_Q14, LPC_pred_Q14, n_AR_Q14, n_LTP_Q14; + opus_int32 n_LF_Q14, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10; + opus_int32 q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10; + opus_int32 tmp1, tmp2, sLF_AR_shp_Q14; + opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14; + VARDECL( NSQ_sample_pair, psSampleState ); + NSQ_del_dec_struct *psDD; + NSQ_sample_struct *psSS; + SAVE_STACK; + + silk_assert( nStatesDelayedDecision > 0 ); + ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair ); + + shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; + pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 ); + + for( i = 0; i < length; i++ ) { + /* Perform common calculations used in all states */ + + /* Long-term prediction */ + if( signalType == TYPE_VOICED ) { + /* Unrolled loop */ + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LTP_pred_Q14 = 2; + LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ 0 ], b_Q14[ 0 ] ); + LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] ); + LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] ); + LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] ); + LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); + LTP_pred_Q14 = silk_LSHIFT( LTP_pred_Q14, 1 ); /* Q13 -> Q14 */ + pred_lag_ptr++; + } else { + LTP_pred_Q14 = 0; + } + + /* Long-term shaping */ + if( lag > 0 ) { + /* Symmetric, packed FIR coefficients */ + n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); + n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); + n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */ + shp_lag_ptr++; + } else { + n_LTP_Q14 = 0; + } + + for( k = 0; k < nStatesDelayedDecision; k++ ) { + /* Delayed decision state */ + psDD = &psDelDec[ k ]; + + /* Sample state */ + psSS = psSampleState[ k ]; + + /* Generate dither */ + psDD->Seed = silk_RAND( psDD->Seed ); + + /* Pointer used in short term prediction and shaping */ + psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ]; + /* Short-term prediction */ + silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 ); + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LPC_pred_Q14 = silk_RSHIFT( predictLPCOrder, 1 ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ 0 ], a_Q12[ 0 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -1 ], a_Q12[ 1 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -2 ], a_Q12[ 2 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -3 ], a_Q12[ 3 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -4 ], a_Q12[ 4 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -5 ], a_Q12[ 5 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -6 ], a_Q12[ 6 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -7 ], a_Q12[ 7 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -8 ], a_Q12[ 8 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); + if( predictLPCOrder == 16 ) { + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -10 ], a_Q12[ 10 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -11 ], a_Q12[ 11 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -12 ], a_Q12[ 12 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -13 ], a_Q12[ 13 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -14 ], a_Q12[ 14 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -15 ], a_Q12[ 15 ] ); + } + LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */ + + /* Noise shape feedback */ + silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ + /* Output of lowpass section */ + tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 ); + psDD->sAR2_Q14[ 0 ] = tmp2; + n_AR_Q14 = silk_RSHIFT( shapingLPCOrder, 1 ); + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ 0 ] ); + /* Loop over allpass sections */ + for( j = 2; j < shapingLPCOrder; j += 2 ) { + /* Output of allpass section */ + tmp2 = silk_SMLAWB( psDD->sAR2_Q14[ j - 1 ], psDD->sAR2_Q14[ j + 0 ] - tmp1, warping_Q16 ); + psDD->sAR2_Q14[ j - 1 ] = tmp1; + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ j - 1 ] ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ j + 0 ], psDD->sAR2_Q14[ j + 1 ] - tmp2, warping_Q16 ); + psDD->sAR2_Q14[ j + 0 ] = tmp2; + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ j ] ); + } + psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1; + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] ); + + n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 1 ); /* Q11 -> Q12 */ + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, psDD->LF_AR_Q14, Tilt_Q14 ); /* Q12 */ + n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 2 ); /* Q12 -> Q14 */ + + n_LF_Q14 = silk_SMULWB( psDD->Shape_Q14[ *smpl_buf_idx ], LF_shp_Q14 ); /* Q12 */ + n_LF_Q14 = silk_SMLAWT( n_LF_Q14, psDD->LF_AR_Q14, LF_shp_Q14 ); /* Q12 */ + n_LF_Q14 = silk_LSHIFT( n_LF_Q14, 2 ); /* Q12 -> Q14 */ + + /* Input minus prediction plus noise feedback */ + /* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */ + tmp1 = silk_ADD32( n_AR_Q14, n_LF_Q14 ); /* Q14 */ + tmp2 = silk_ADD32( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */ + tmp1 = silk_SUB32( tmp2, tmp1 ); /* Q13 */ + tmp1 = silk_RSHIFT_ROUND( tmp1, 4 ); /* Q10 */ + + r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */ + + /* Flip sign depending on dither */ + if ( psDD->Seed < 0 ) { + r_Q10 = -r_Q10; + } + r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 ); + + /* Find two quantization level candidates and measure their rate-distortion */ + q1_Q10 = silk_SUB32( r_Q10, offset_Q10 ); + q1_Q0 = silk_RSHIFT( q1_Q10, 10 ); + if( q1_Q0 > 0 ) { + q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = silk_ADD32( q1_Q10, 1024 ); + rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q0 == 0 ) { + q1_Q10 = offset_Q10; + q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q0 == -1 ) { + q2_Q10 = offset_Q10; + q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else { /* q1_Q0 < -1 */ + q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = silk_ADD32( q1_Q10, 1024 ); + rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( -q2_Q10, Lambda_Q10 ); + } + rr_Q10 = silk_SUB32( r_Q10, q1_Q10 ); + rd1_Q10 = silk_RSHIFT( silk_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 ); + rr_Q10 = silk_SUB32( r_Q10, q2_Q10 ); + rd2_Q10 = silk_RSHIFT( silk_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 ); + + if( rd1_Q10 < rd2_Q10 ) { + psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 ); + psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 ); + psSS[ 0 ].Q_Q10 = q1_Q10; + psSS[ 1 ].Q_Q10 = q2_Q10; + } else { + psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 ); + psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 ); + psSS[ 0 ].Q_Q10 = q2_Q10; + psSS[ 1 ].Q_Q10 = q1_Q10; + } + + /* Update states for best quantization */ + + /* Quantized excitation */ + exc_Q14 = silk_LSHIFT32( psSS[ 0 ].Q_Q10, 4 ); + if ( psDD->Seed < 0 ) { + exc_Q14 = -exc_Q14; + } + + /* Add predictions */ + LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 ); + xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 ); + + /* Update states */ + sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 ); + psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 ); + psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14; + psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14; + psSS[ 0 ].xq_Q14 = xq_Q14; + + /* Update states for second best quantization */ + + /* Quantized excitation */ + exc_Q14 = silk_LSHIFT32( psSS[ 1 ].Q_Q10, 4 ); + if ( psDD->Seed < 0 ) { + exc_Q14 = -exc_Q14; + } + + + /* Add predictions */ + LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 ); + xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 ); + + /* Update states */ + sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 ); + psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 ); + psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14; + psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14; + psSS[ 1 ].xq_Q14 = xq_Q14; + } + + *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */ + last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */ + + /* Find winner */ + RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; + Winner_ind = 0; + for( k = 1; k < nStatesDelayedDecision; k++ ) { + if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psSampleState[ k ][ 0 ].RD_Q10; + Winner_ind = k; + } + } + + /* Increase RD values of expired states */ + Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ]; + for( k = 0; k < nStatesDelayedDecision; k++ ) { + if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) { + psSampleState[ k ][ 0 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 0 ].RD_Q10, silk_int32_MAX >> 4 ); + psSampleState[ k ][ 1 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 1 ].RD_Q10, silk_int32_MAX >> 4 ); + silk_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 ); + } + } + + /* Find worst in first set and best in second set */ + RDmax_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; + RDmin_Q10 = psSampleState[ 0 ][ 1 ].RD_Q10; + RDmax_ind = 0; + RDmin_ind = 0; + for( k = 1; k < nStatesDelayedDecision; k++ ) { + /* find worst in first set */ + if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) { + RDmax_Q10 = psSampleState[ k ][ 0 ].RD_Q10; + RDmax_ind = k; + } + /* find best in second set */ + if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psSampleState[ k ][ 1 ].RD_Q10; + RDmin_ind = k; + } + } + + /* Replace a state if best from second set outperforms worst in first set */ + if( RDmin_Q10 < RDmax_Q10 ) { + silk_memcpy( ( (opus_int32 *)&psDelDec[ RDmax_ind ] ) + i, + ( (opus_int32 *)&psDelDec[ RDmin_ind ] ) + i, sizeof( NSQ_del_dec_struct ) - i * sizeof( opus_int32) ); + silk_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) ); + } + + /* Write samples from winner to output and long-term filter states */ + psDD = &psDelDec[ Winner_ind ]; + if( subfr > 0 || i >= decisionDelay ) { + pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); + xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( + silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], delayedGain_Q10[ last_smple_idx ] ), 8 ) ); + NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q14[ last_smple_idx ]; + sLTP_Q15[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q15[ last_smple_idx ]; + } + NSQ->sLTP_shp_buf_idx++; + NSQ->sLTP_buf_idx++; + + /* Update states */ + for( k = 0; k < nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + psSS = &psSampleState[ k ][ 0 ]; + psDD->LF_AR_Q14 = psSS->LF_AR_Q14; + psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14; + psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14; + psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10; + psDD->Pred_Q15[ *smpl_buf_idx ] = silk_LSHIFT32( psSS->LPC_exc_Q14, 1 ); + psDD->Shape_Q14[ *smpl_buf_idx ] = psSS->sLTP_shp_Q14; + psDD->Seed = silk_ADD32_ovflw( psDD->Seed, silk_RSHIFT_ROUND( psSS->Q_Q10, 10 ) ); + psDD->RandState[ *smpl_buf_idx ] = psDD->Seed; + psDD->RD_Q10 = psSS->RD_Q10; + } + delayedGain_Q10[ *smpl_buf_idx ] = Gain_Q10; + } + /* Update LPC states */ + for( k = 0; k < nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + silk_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); + } + RESTORE_STACK; +} +#endif /* OVERRIDE_silk_noise_shape_quantizer_del_dec */ + +static OPUS_INLINE void silk_nsq_del_dec_scale_states( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + const opus_int32 x_Q3[], /* I Input in Q3 */ + opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */ + const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ + opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ + opus_int subfr, /* I Subframe number */ + opus_int nStatesDelayedDecision, /* I Number of del dec states */ + const opus_int LTP_scale_Q14, /* I LTP state scaling */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ + const opus_int signal_type, /* I Signal type */ + const opus_int decisionDelay /* I Decision delay */ +) +{ + opus_int i, k, lag; + opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23; + NSQ_del_dec_struct *psDD; + + lag = pitchL[ subfr ]; + inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 ); + silk_assert( inv_gain_Q31 != 0 ); + + /* Calculate gain adjustment factor */ + if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) { + gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 ); + } else { + gain_adj_Q16 = (opus_int32)1 << 16; + } + + /* Scale input */ + inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 ); + for( i = 0; i < psEncC->subfr_length; i++ ) { + x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 ); + } + + /* Save inverse gain */ + NSQ->prev_gain_Q16 = Gains_Q16[ subfr ]; + + /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ + if( NSQ->rewhite_flag ) { + if( subfr == 0 ) { + /* Do LTP downscaling */ + inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 ); + } + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { + silk_assert( i < MAX_FRAME_LENGTH ); + sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] ); + } + } + + /* Adjust for changing gain */ + if( gain_adj_Q16 != (opus_int32)1 << 16 ) { + /* Scale long-term shaping state */ + for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) { + NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] ); + } + + /* Scale long-term prediction state */ + if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) { + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) { + sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] ); + } + } + + for( k = 0; k < nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + + /* Scale scalar states */ + psDD->LF_AR_Q14 = silk_SMULWW( gain_adj_Q16, psDD->LF_AR_Q14 ); + + /* Scale short-term prediction and shaping states */ + for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { + psDD->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sLPC_Q14[ i ] ); + } + for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { + psDD->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sAR2_Q14[ i ] ); + } + for( i = 0; i < DECISION_DELAY; i++ ) { + psDD->Pred_Q15[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Pred_Q15[ i ] ); + psDD->Shape_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Shape_Q14[ i ] ); + } + } + } +} diff --git a/thirdparty/opus/silk/PLC.c b/thirdparty/opus/silk/PLC.c new file mode 100644 index 0000000000..34a94bc313 --- /dev/null +++ b/thirdparty/opus/silk/PLC.c @@ -0,0 +1,445 @@ +/*********************************************************************** +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" + +#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 */ + 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 */ + 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, arch ); + + psDec->lossCnt++; + } else { + /****************************/ + /* Update state */ + /****************************/ + silk_PLC_update( psDec, psDecCtrl ); + } +} + +/**************************************************/ +/* 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 coeficients */ + 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 */ + 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 coeficients 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 ); + + 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; + silk_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 ) ); + + silk_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_LSHIFT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], 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 ) ) ); + } + + /* 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 ); + + 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/thirdparty/opus/silk/PLC.h b/thirdparty/opus/silk/PLC.h new file mode 100644 index 0000000000..6438f51633 --- /dev/null +++ b/thirdparty/opus/silk/PLC.h @@ -0,0 +1,62 @@ +/*********************************************************************** +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 */ + 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/thirdparty/opus/silk/SigProc_FIX.h b/thirdparty/opus/silk/SigProc_FIX.h new file mode 100644 index 0000000000..b63299441e --- /dev/null +++ b/thirdparty/opus/silk/SigProc_FIX.h @@ -0,0 +1,615 @@ +/*********************************************************************** +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 + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*#define silk_MACRO_COUNT */ /* Used to enable WMOPS counting */ + +#define SILK_MAX_ORDER_LPC 16 /* 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 + +/********************************************************************/ +/* 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( + 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) */ + opus_int stride /* I Operate on interleaved signal if > 1 */ +); + +/* 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( /* 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 */ +); + +/* For input in Q24 domain */ +opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */ + const opus_int32 *A_Q24, /* I Prediction coefficients [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 */ +); + +/********************************************************************/ +/* 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) */ +); + +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_aligned_64_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) ((((a)+(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b))) +#define silk_ADD_POS_SAT64(a, b) ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_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 silk_RAND(seed) (silk_MLA_ovflw(907633515, (seed), 196314165)) + +/* Add some multiplication functions that can be easily mapped to ARM. */ + +/* silk_SMMUL: Signed top word multiply. + ARMv6 2 instruction cycles. + ARMv3M+ 3 instruction cycles. use SMULL and ignore LSB registers.(except xM)*/ +/*#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(OPUS_X86_MAY_HAVE_SSE4_1) +#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)) + +#define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \ + ((void)(arch),silk_inner_prod16_aligned_64_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(MIPSr1_ASM) +#include "mips/sigproc_fix_mipsr1.h" +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* SILK_SIGPROC_FIX_H */ diff --git a/thirdparty/opus/silk/VAD.c b/thirdparty/opus/silk/VAD.c new file mode 100644 index 0000000000..0a782af2f1 --- /dev/null +++ b/thirdparty/opus/silk/VAD.c @@ -0,0 +1,362 @@ +/*********************************************************************** +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" + +/* Silk VAD noise level estimation */ +# if !defined(OPUS_X86_MAY_HAVE_SSE4_1) +static OPUS_INLINE 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 */ +); +#endif + +/**********************************/ +/* Initialization of 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 */ +) +{ + opus_int b, ret = 0; + + /* reset state memory */ + silk_memset( psSilk_VAD, 0, sizeof( silk_VAD_state ) ); + + /* init noise levels */ + /* Initialize array with approx pink noise levels (psd proportional to inverse of frequency) */ + for( b = 0; b < VAD_N_BANDS; b++ ) { + psSilk_VAD->NoiseLevelBias[ b ] = silk_max_32( silk_DIV32_16( VAD_NOISE_LEVELS_BIAS, b + 1 ), 1 ); + } + + /* Initialize state */ + for( b = 0; b < VAD_N_BANDS; b++ ) { + psSilk_VAD->NL[ b ] = silk_MUL( 100, psSilk_VAD->NoiseLevelBias[ b ] ); + psSilk_VAD->inv_NL[ b ] = silk_DIV32( silk_int32_MAX, psSilk_VAD->NL[ b ] ); + } + psSilk_VAD->counter = 15; + + /* init smoothed energy-to-noise ratio*/ + for( b = 0; b < VAD_N_BANDS; b++ ) { + psSilk_VAD->NrgRatioSmth_Q8[ b ] = 100 * 256; /* 100 * 256 --> 20 dB SNR */ + } + + return( ret ); +} + +/* Weighting factors for tilt measure */ +static const opus_int32 tiltWeights[ VAD_N_BANDS ] = { 30000, 6000, -12000, -12000 }; + +/***************************************/ +/* Get the 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 */ +) +{ + opus_int SA_Q15, pSNR_dB_Q7, input_tilt; + opus_int decimated_framelength1, decimated_framelength2; + opus_int decimated_framelength; + opus_int dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s; + opus_int32 sumSquared, smooth_coef_Q16; + opus_int16 HPstateTmp; + VARDECL( opus_int16, X ); + opus_int32 Xnrg[ VAD_N_BANDS ]; + opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ]; + opus_int32 speech_nrg, x_tmp; + opus_int X_offset[ VAD_N_BANDS ]; + opus_int ret = 0; + silk_VAD_state *psSilk_VAD = &psEncC->sVAD; + SAVE_STACK; + + /* Safety checks */ + silk_assert( VAD_N_BANDS == 4 ); + silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length ); + silk_assert( psEncC->frame_length <= 512 ); + silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) ); + + /***********************/ + /* Filter and Decimate */ + /***********************/ + decimated_framelength1 = silk_RSHIFT( psEncC->frame_length, 1 ); + decimated_framelength2 = silk_RSHIFT( psEncC->frame_length, 2 ); + decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 ); + /* Decimate into 4 bands: + 0 L 3L L 3L 5L + - -- - -- -- + 8 8 2 4 4 + + [0-1 kHz| temp. |1-2 kHz| 2-4 kHz | 4-8 kHz | + + They're arranged to allow the minimal ( frame_length / 4 ) extra + scratch space during the downsampling process */ + X_offset[ 0 ] = 0; + X_offset[ 1 ] = decimated_framelength + decimated_framelength2; + X_offset[ 2 ] = X_offset[ 1 ] + decimated_framelength; + X_offset[ 3 ] = X_offset[ 2 ] + decimated_framelength2; + ALLOC( X, X_offset[ 3 ] + decimated_framelength1, opus_int16 ); + + /* 0-8 kHz to 0-4 kHz and 4-8 kHz */ + silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ], + X, &X[ X_offset[ 3 ] ], psEncC->frame_length ); + + /* 0-4 kHz to 0-2 kHz and 2-4 kHz */ + silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState1[ 0 ], + X, &X[ X_offset[ 2 ] ], decimated_framelength1 ); + + /* 0-2 kHz to 0-1 kHz and 1-2 kHz */ + silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState2[ 0 ], + X, &X[ X_offset[ 1 ] ], decimated_framelength2 ); + + /*********************************************/ + /* HP filter on lowest band (differentiator) */ + /*********************************************/ + X[ decimated_framelength - 1 ] = silk_RSHIFT( X[ decimated_framelength - 1 ], 1 ); + HPstateTmp = X[ decimated_framelength - 1 ]; + for( i = decimated_framelength - 1; i > 0; i-- ) { + X[ i - 1 ] = silk_RSHIFT( X[ i - 1 ], 1 ); + X[ i ] -= X[ i - 1 ]; + } + X[ 0 ] -= psSilk_VAD->HPstate; + psSilk_VAD->HPstate = HPstateTmp; + + /*************************************/ + /* Calculate the energy in each band */ + /*************************************/ + for( b = 0; b < VAD_N_BANDS; b++ ) { + /* Find the decimated framelength in the non-uniformly divided bands */ + decimated_framelength = silk_RSHIFT( psEncC->frame_length, silk_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) ); + + /* Split length into subframe lengths */ + dec_subframe_length = silk_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 ); + dec_subframe_offset = 0; + + /* Compute energy per sub-frame */ + /* initialize with summed energy of last subframe */ + Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ]; + for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) { + sumSquared = 0; + for( i = 0; i < dec_subframe_length; i++ ) { + /* The energy will be less than dec_subframe_length * ( silk_int16_MIN / 8 ) ^ 2. */ + /* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */ + x_tmp = silk_RSHIFT( + X[ X_offset[ b ] + i + dec_subframe_offset ], 3 ); + sumSquared = silk_SMLABB( sumSquared, x_tmp, x_tmp ); + + /* Safety check */ + silk_assert( sumSquared >= 0 ); + } + + /* Add/saturate summed energy of current subframe */ + if( s < VAD_INTERNAL_SUBFRAMES - 1 ) { + Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], sumSquared ); + } else { + /* Look-ahead subframe */ + Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], silk_RSHIFT( sumSquared, 1 ) ); + } + + dec_subframe_offset += dec_subframe_length; + } + psSilk_VAD->XnrgSubfr[ b ] = sumSquared; + } + + /********************/ + /* Noise estimation */ + /********************/ + silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD ); + + /***********************************************/ + /* Signal-plus-noise to noise ratio estimation */ + /***********************************************/ + sumSquared = 0; + input_tilt = 0; + for( b = 0; b < VAD_N_BANDS; b++ ) { + speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ]; + if( speech_nrg > 0 ) { + /* Divide, with sufficient resolution */ + if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) { + NrgToNoiseRatio_Q8[ b ] = silk_DIV32( silk_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 ); + } else { + NrgToNoiseRatio_Q8[ b ] = silk_DIV32( Xnrg[ b ], silk_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 ); + } + + /* Convert to log domain */ + SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128; + + /* Sum-of-squares */ + sumSquared = silk_SMLABB( sumSquared, SNR_Q7, SNR_Q7 ); /* Q14 */ + + /* Tilt measure */ + if( speech_nrg < ( (opus_int32)1 << 20 ) ) { + /* Scale down SNR value for small subband speech energies */ + SNR_Q7 = silk_SMULWB( silk_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 ); + } + input_tilt = silk_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 ); + } else { + NrgToNoiseRatio_Q8[ b ] = 256; + } + } + + /* Mean-of-squares */ + sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */ + + /* Root-mean-square approximation, scale to dBs, and write to output pointer */ + pSNR_dB_Q7 = (opus_int16)( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */ + + /*********************************/ + /* Speech Probability Estimation */ + /*********************************/ + SA_Q15 = silk_sigm_Q15( silk_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 ); + + /**************************/ + /* Frequency Tilt Measure */ + /**************************/ + psEncC->input_tilt_Q15 = silk_LSHIFT( silk_sigm_Q15( input_tilt ) - 16384, 1 ); + + /**************************************************/ + /* Scale the sigmoid output based on power levels */ + /**************************************************/ + speech_nrg = 0; + for( b = 0; b < VAD_N_BANDS; b++ ) { + /* Accumulate signal-without-noise energies, higher frequency bands have more weight */ + speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 ); + } + + /* Power scaling */ + if( speech_nrg <= 0 ) { + SA_Q15 = silk_RSHIFT( SA_Q15, 1 ); + } else if( speech_nrg < 32768 ) { + if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { + speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 16 ); + } else { + speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 15 ); + } + + /* square-root */ + speech_nrg = silk_SQRT_APPROX( speech_nrg ); + SA_Q15 = silk_SMULWB( 32768 + speech_nrg, SA_Q15 ); + } + + /* Copy the resulting speech activity in Q8 */ + psEncC->speech_activity_Q8 = silk_min_int( silk_RSHIFT( SA_Q15, 7 ), silk_uint8_MAX ); + + /***********************************/ + /* Energy Level and SNR estimation */ + /***********************************/ + /* Smoothing coefficient */ + smooth_coef_Q16 = silk_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, silk_SMULWB( (opus_int32)SA_Q15, SA_Q15 ) ); + + if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { + smooth_coef_Q16 >>= 1; + } + + for( b = 0; b < VAD_N_BANDS; b++ ) { + /* compute smoothed energy-to-noise ratio per band */ + psSilk_VAD->NrgRatioSmth_Q8[ b ] = silk_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ], + NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 ); + + /* signal to noise ratio in dB per band */ + SNR_Q7 = 3 * ( silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 ); + /* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */ + psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( silk_RSHIFT( SNR_Q7 - 16 * 128, 4 ) ); + } + + RESTORE_STACK; + return( ret ); +} + +/**************************/ +/* Noise level estimation */ +/**************************/ +# if !defined(OPUS_X86_MAY_HAVE_SSE4_1) +static OPUS_INLINE +#endif +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 k; + opus_int32 nl, nrg, inv_nrg; + opus_int coef, min_coef; + + /* Initially faster smoothing */ + if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */ + min_coef = silk_DIV32_16( silk_int16_MAX, silk_RSHIFT( psSilk_VAD->counter, 4 ) + 1 ); + } else { + min_coef = 0; + } + + for( k = 0; k < VAD_N_BANDS; k++ ) { + /* Get old noise level estimate for current band */ + nl = psSilk_VAD->NL[ k ]; + silk_assert( nl >= 0 ); + + /* Add bias */ + nrg = silk_ADD_POS_SAT32( pX[ k ], psSilk_VAD->NoiseLevelBias[ k ] ); + silk_assert( nrg > 0 ); + + /* Invert energies */ + inv_nrg = silk_DIV32( silk_int32_MAX, nrg ); + silk_assert( inv_nrg >= 0 ); + + /* Less update when subband energy is high */ + if( nrg > silk_LSHIFT( nl, 3 ) ) { + coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 >> 3; + } else if( nrg < nl ) { + coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16; + } else { + coef = silk_SMULWB( silk_SMULWW( inv_nrg, nl ), VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 << 1 ); + } + + /* Initially faster smoothing */ + coef = silk_max_int( coef, min_coef ); + + /* Smooth inverse energies */ + psSilk_VAD->inv_NL[ k ] = silk_SMLAWB( psSilk_VAD->inv_NL[ k ], inv_nrg - psSilk_VAD->inv_NL[ k ], coef ); + silk_assert( psSilk_VAD->inv_NL[ k ] >= 0 ); + + /* Compute noise level by inverting again */ + nl = silk_DIV32( silk_int32_MAX, psSilk_VAD->inv_NL[ k ] ); + silk_assert( nl >= 0 ); + + /* Limit noise levels (guarantee 7 bits of head room) */ + nl = silk_min( nl, 0x00FFFFFF ); + + /* Store as part of state */ + psSilk_VAD->NL[ k ] = nl; + } + + /* Increment frame counter */ + psSilk_VAD->counter++; +} diff --git a/thirdparty/opus/silk/VQ_WMat_EC.c b/thirdparty/opus/silk/VQ_WMat_EC.c new file mode 100644 index 0000000000..7983f1db80 --- /dev/null +++ b/thirdparty/opus/silk/VQ_WMat_EC.c @@ -0,0 +1,120 @@ +/*********************************************************************** +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" + +/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */ +void silk_VQ_WMat_EC_c( + opus_int8 *ind, /* O index of best codebook vector */ + opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */ + opus_int *gain_Q7, /* O sum of absolute LTP coefficients */ + const opus_int16 *in_Q14, /* I input vector to be quantized */ + const opus_int32 *W_Q18, /* I weighting matrix */ + 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 mu_Q9, /* I tradeoff betw. weighted error and rate */ + const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ + opus_int L /* I number of vectors in codebook */ +) +{ + opus_int k, gain_tmp_Q7; + const opus_int8 *cb_row_Q7; + opus_int16 diff_Q14[ 5 ]; + opus_int32 sum1_Q14, sum2_Q16; + + /* Loop over codebook */ + *rate_dist_Q14 = silk_int32_MAX; + cb_row_Q7 = cb_Q7; + for( k = 0; k < L; k++ ) { + gain_tmp_Q7 = cb_gain_Q7[k]; + + diff_Q14[ 0 ] = in_Q14[ 0 ] - silk_LSHIFT( cb_row_Q7[ 0 ], 7 ); + diff_Q14[ 1 ] = in_Q14[ 1 ] - silk_LSHIFT( cb_row_Q7[ 1 ], 7 ); + diff_Q14[ 2 ] = in_Q14[ 2 ] - silk_LSHIFT( cb_row_Q7[ 2 ], 7 ); + diff_Q14[ 3 ] = in_Q14[ 3 ] - silk_LSHIFT( cb_row_Q7[ 3 ], 7 ); + diff_Q14[ 4 ] = in_Q14[ 4 ] - silk_LSHIFT( cb_row_Q7[ 4 ], 7 ); + + /* Weighted rate */ + sum1_Q14 = silk_SMULBB( mu_Q9, cl_Q5[ k ] ); + + /* Penalty for too large gain */ + sum1_Q14 = silk_ADD_LSHIFT32( sum1_Q14, silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 10 ); + + silk_assert( sum1_Q14 >= 0 ); + + /* first row of W_Q18 */ + sum2_Q16 = silk_SMULWB( W_Q18[ 1 ], diff_Q14[ 1 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 2 ], diff_Q14[ 2 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 3 ], diff_Q14[ 3 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 4 ], diff_Q14[ 4 ] ); + sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] ); + + /* second row of W_Q18 */ + sum2_Q16 = silk_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] ); + sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] ); + + /* third row of W_Q18 */ + sum2_Q16 = silk_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] ); + sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] ); + + /* fourth row of W_Q18 */ + sum2_Q16 = silk_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] ); + sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] ); + + /* last row of W_Q18 */ + sum2_Q16 = silk_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] ); + + silk_assert( sum1_Q14 >= 0 ); + + /* find best */ + if( sum1_Q14 < *rate_dist_Q14 ) { + *rate_dist_Q14 = sum1_Q14; + *ind = (opus_int8)k; + *gain_Q7 = gain_tmp_Q7; + } + + /* Go to next cbk vector */ + cb_row_Q7 += LTP_ORDER; + } +} diff --git a/thirdparty/opus/silk/ana_filt_bank_1.c b/thirdparty/opus/silk/ana_filt_bank_1.c new file mode 100644 index 0000000000..24cfb03fdb --- /dev/null +++ b/thirdparty/opus/silk/ana_filt_bank_1.c @@ -0,0 +1,74 @@ +/*********************************************************************** +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" + +/* Coefficients for 2-band filter bank based on first-order allpass filters */ +static opus_int16 A_fb1_20 = 5394 << 1; +static opus_int16 A_fb1_21 = -24290; /* (opus_int16)(20623 << 1) */ + +/* Split signal into 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 */ +) +{ + opus_int k, N2 = silk_RSHIFT( N, 1 ); + opus_int32 in32, X, Y, out_1, out_2; + + /* Internal variables and state are in Q10 format */ + for( k = 0; k < N2; 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, A_fb1_21 ); + out_1 = 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, A_fb1_20 ); + out_2 = silk_ADD32( S[ 1 ], X ); + S[ 1 ] = silk_ADD32( in32, X ); + + /* Add/subtract, convert back to int16 and store to output */ + outL[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_ADD32( out_2, out_1 ), 11 ) ); + outH[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SUB32( out_2, out_1 ), 11 ) ); + } +} diff --git a/thirdparty/opus/silk/arm/NSQ_neon.c b/thirdparty/opus/silk/arm/NSQ_neon.c new file mode 100644 index 0000000000..9642529973 --- /dev/null +++ b/thirdparty/opus/silk/arm/NSQ_neon.c @@ -0,0 +1,112 @@ +/*********************************************************************** +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. +***********************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <arm_neon.h> +#include "main.h" +#include "stack_alloc.h" +#include "NSQ.h" +#include "celt/cpu_support.h" +#include "celt/arm/armcpu.h" + +opus_int32 silk_noise_shape_quantizer_short_prediction_neon(const opus_int32 *buf32, const opus_int32 *coef32, opus_int order) +{ + int32x4_t coef0 = vld1q_s32(coef32); + int32x4_t coef1 = vld1q_s32(coef32 + 4); + int32x4_t coef2 = vld1q_s32(coef32 + 8); + int32x4_t coef3 = vld1q_s32(coef32 + 12); + + int32x4_t a0 = vld1q_s32(buf32 - 15); + int32x4_t a1 = vld1q_s32(buf32 - 11); + int32x4_t a2 = vld1q_s32(buf32 - 7); + int32x4_t a3 = vld1q_s32(buf32 - 3); + + int32x4_t b0 = vqdmulhq_s32(coef0, a0); + int32x4_t b1 = vqdmulhq_s32(coef1, a1); + int32x4_t b2 = vqdmulhq_s32(coef2, a2); + int32x4_t b3 = vqdmulhq_s32(coef3, a3); + + int32x4_t c0 = vaddq_s32(b0, b1); + int32x4_t c1 = vaddq_s32(b2, b3); + + int32x4_t d = vaddq_s32(c0, c1); + + int64x2_t e = vpaddlq_s32(d); + + int64x1_t f = vadd_s64(vget_low_s64(e), vget_high_s64(e)); + + opus_int32 out = vget_lane_s32(vreinterpret_s32_s64(f), 0); + + out += silk_RSHIFT( order, 1 ); + + return out; +} + + +opus_int32 silk_NSQ_noise_shape_feedback_loop_neon(const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef, opus_int order) +{ + opus_int32 out; + if (order == 8) + { + int32x4_t a00 = vdupq_n_s32(data0[0]); + int32x4_t a01 = vld1q_s32(data1); /* data1[0] ... [3] */ + + int32x4_t a0 = vextq_s32 (a00, a01, 3); /* data0[0] data1[0] ...[2] */ + int32x4_t a1 = vld1q_s32(data1 + 3); /* data1[3] ... [6] */ + + /*TODO: Convert these once in advance instead of once per sample, like + silk_noise_shape_quantizer_short_prediction_neon() does.*/ + int16x8_t coef16 = vld1q_s16(coef); + int32x4_t coef0 = vmovl_s16(vget_low_s16(coef16)); + int32x4_t coef1 = vmovl_s16(vget_high_s16(coef16)); + + /*This is not bit-exact with the C version, since we do not drop the + lower 16 bits of each multiply, but wait until the end to truncate + precision. This is an encoder-specific calculation (and unlike + silk_noise_shape_quantizer_short_prediction_neon(), is not meant to + simulate what the decoder will do). We still could use vqdmulhq_s32() + like silk_noise_shape_quantizer_short_prediction_neon() and save + half the multiplies, but the speed difference is not large, since we + then need two extra adds.*/ + int64x2_t b0 = vmull_s32(vget_low_s32(a0), vget_low_s32(coef0)); + int64x2_t b1 = vmlal_s32(b0, vget_high_s32(a0), vget_high_s32(coef0)); + int64x2_t b2 = vmlal_s32(b1, vget_low_s32(a1), vget_low_s32(coef1)); + int64x2_t b3 = vmlal_s32(b2, vget_high_s32(a1), vget_high_s32(coef1)); + + int64x1_t c = vadd_s64(vget_low_s64(b3), vget_high_s64(b3)); + int64x1_t cS = vrshr_n_s64(c, 15); + int32x2_t d = vreinterpret_s32_s64(cS); + + out = vget_lane_s32(d, 0); + vst1q_s32(data1, a0); + vst1q_s32(data1 + 4, a1); + return out; + } + return silk_NSQ_noise_shape_feedback_loop_c(data0, data1, coef, order); +} diff --git a/thirdparty/opus/silk/arm/NSQ_neon.h b/thirdparty/opus/silk/arm/NSQ_neon.h new file mode 100644 index 0000000000..77c946af85 --- /dev/null +++ b/thirdparty/opus/silk/arm/NSQ_neon.h @@ -0,0 +1,113 @@ +/*********************************************************************** +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" + +#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] = in[0] << 15; + out[14] = in[1] << 15; + out[13] = in[2] << 15; + out[12] = in[3] << 15; + out[11] = in[4] << 15; + out[10] = in[5] << 15; + out[9] = in[6] << 15; + out[8] = in[7] << 15; + out[7] = in[8] << 15; + out[6] = in[9] << 15; + + if (order == 16) + { + out[5] = in[10] << 15; + out[4] = in[11] << 15; + out[3] = in[12] << 15; + out[2] = in[13] << 15; + out[1] = in[14] << 15; + out[0] = 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/drivers/opus/silk/arm/SigProc_FIX_armv4.h b/thirdparty/opus/silk/arm/SigProc_FIX_armv4.h index ff62b1e5d6..ff62b1e5d6 100644 --- a/drivers/opus/silk/arm/SigProc_FIX_armv4.h +++ b/thirdparty/opus/silk/arm/SigProc_FIX_armv4.h diff --git a/drivers/opus/silk/arm/SigProc_FIX_armv5e.h b/thirdparty/opus/silk/arm/SigProc_FIX_armv5e.h index 617a09cab1..617a09cab1 100644 --- a/drivers/opus/silk/arm/SigProc_FIX_armv5e.h +++ b/thirdparty/opus/silk/arm/SigProc_FIX_armv5e.h diff --git a/thirdparty/opus/silk/arm/arm_silk_map.c b/thirdparty/opus/silk/arm/arm_silk_map.c new file mode 100644 index 0000000000..9bd86a7b21 --- /dev/null +++ b/thirdparty/opus/silk/arm/arm_silk_map.c @@ -0,0 +1,55 @@ +/*********************************************************************** +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. +***********************************************************************/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "NSQ.h" + +#if defined(OPUS_HAVE_RTCD) + +# if (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && \ + !defined(OPUS_ARM_PRESUME_NEON_INTR)) + +/*There is no table for silk_noise_shape_quantizer_short_prediction because the + NEON version takes different parameters than the C version. + Instead RTCD is done via if statements at the call sites. + See NSQ_neon.h for details.*/ + +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) = { + silk_NSQ_noise_shape_feedback_loop_c, /* ARMv4 */ + silk_NSQ_noise_shape_feedback_loop_c, /* EDSP */ + silk_NSQ_noise_shape_feedback_loop_c, /* Media */ + silk_NSQ_noise_shape_feedback_loop_neon, /* NEON */ +}; + +# endif + +#endif /* OPUS_HAVE_RTCD */ diff --git a/thirdparty/opus/silk/arm/macros_arm64.h b/thirdparty/opus/silk/arm/macros_arm64.h new file mode 100644 index 0000000000..ed030413c5 --- /dev/null +++ b/thirdparty/opus/silk/arm/macros_arm64.h @@ -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/drivers/opus/silk/arm/macros_armv4.h b/thirdparty/opus/silk/arm/macros_armv4.h index 3f30e97288..3f30e97288 100644 --- a/drivers/opus/silk/arm/macros_armv4.h +++ b/thirdparty/opus/silk/arm/macros_armv4.h diff --git a/drivers/opus/silk/arm/macros_armv5e.h b/thirdparty/opus/silk/arm/macros_armv5e.h index aad4117e46..aad4117e46 100644 --- a/drivers/opus/silk/arm/macros_armv5e.h +++ b/thirdparty/opus/silk/arm/macros_armv5e.h diff --git a/thirdparty/opus/silk/biquad_alt.c b/thirdparty/opus/silk/biquad_alt.c new file mode 100644 index 0000000000..d55f5ee92e --- /dev/null +++ b/thirdparty/opus/silk/biquad_alt.c @@ -0,0 +1,78 @@ +/*********************************************************************** +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( + 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) */ + opus_int stride /* I Operate on interleaved signal if > 1 */ +) +{ + /* 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 * stride ]; + 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 * stride ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) ); + } +} diff --git a/thirdparty/opus/silk/bwexpander.c b/thirdparty/opus/silk/bwexpander.c new file mode 100644 index 0000000000..2eb4456695 --- /dev/null +++ b/thirdparty/opus/silk/bwexpander.c @@ -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/thirdparty/opus/silk/bwexpander_32.c b/thirdparty/opus/silk/bwexpander_32.c new file mode 100644 index 0000000000..d0010f73df --- /dev/null +++ b/thirdparty/opus/silk/bwexpander_32.c @@ -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 */ +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/thirdparty/opus/silk/check_control_input.c b/thirdparty/opus/silk/check_control_input.c new file mode 100644 index 0000000000..b5de9ce48d --- /dev/null +++ b/thirdparty/opus/silk/check_control_input.c @@ -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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "control.h" +#include "errors.h" + +/* Check encoder control struct */ +opus_int check_control_input( + silk_EncControlStruct *encControl /* I Control structure */ +) +{ + silk_assert( encControl != NULL ); + + if( ( ( encControl->API_sampleRate != 8000 ) && + ( encControl->API_sampleRate != 12000 ) && + ( encControl->API_sampleRate != 16000 ) && + ( encControl->API_sampleRate != 24000 ) && + ( encControl->API_sampleRate != 32000 ) && + ( encControl->API_sampleRate != 44100 ) && + ( encControl->API_sampleRate != 48000 ) ) || + ( ( encControl->desiredInternalSampleRate != 8000 ) && + ( encControl->desiredInternalSampleRate != 12000 ) && + ( encControl->desiredInternalSampleRate != 16000 ) ) || + ( ( encControl->maxInternalSampleRate != 8000 ) && + ( encControl->maxInternalSampleRate != 12000 ) && + ( encControl->maxInternalSampleRate != 16000 ) ) || + ( ( encControl->minInternalSampleRate != 8000 ) && + ( encControl->minInternalSampleRate != 12000 ) && + ( encControl->minInternalSampleRate != 16000 ) ) || + ( encControl->minInternalSampleRate > encControl->desiredInternalSampleRate ) || + ( encControl->maxInternalSampleRate < encControl->desiredInternalSampleRate ) || + ( encControl->minInternalSampleRate > encControl->maxInternalSampleRate ) ) { + silk_assert( 0 ); + return SILK_ENC_FS_NOT_SUPPORTED; + } + if( encControl->payloadSize_ms != 10 && + encControl->payloadSize_ms != 20 && + encControl->payloadSize_ms != 40 && + encControl->payloadSize_ms != 60 ) { + silk_assert( 0 ); + return SILK_ENC_PACKET_SIZE_NOT_SUPPORTED; + } + if( encControl->packetLossPercentage < 0 || encControl->packetLossPercentage > 100 ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_LOSS_RATE; + } + if( encControl->useDTX < 0 || encControl->useDTX > 1 ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_DTX_SETTING; + } + if( encControl->useCBR < 0 || encControl->useCBR > 1 ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_CBR_SETTING; + } + if( encControl->useInBandFEC < 0 || encControl->useInBandFEC > 1 ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_INBAND_FEC_SETTING; + } + if( encControl->nChannelsAPI < 1 || encControl->nChannelsAPI > ENCODER_NUM_CHANNELS ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; + } + if( encControl->nChannelsInternal < 1 || encControl->nChannelsInternal > ENCODER_NUM_CHANNELS ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; + } + if( encControl->nChannelsInternal > encControl->nChannelsAPI ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; + } + if( encControl->complexity < 0 || encControl->complexity > 10 ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_COMPLEXITY_SETTING; + } + + return SILK_NO_ERROR; +} diff --git a/thirdparty/opus/silk/code_signs.c b/thirdparty/opus/silk/code_signs.c new file mode 100644 index 0000000000..dfd1dca9a1 --- /dev/null +++ b/thirdparty/opus/silk/code_signs.c @@ -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/thirdparty/opus/silk/control.h b/thirdparty/opus/silk/control.h new file mode 100644 index 0000000000..747e5426a0 --- /dev/null +++ b/thirdparty/opus/silk/control.h @@ -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. +***********************************************************************/ + +#ifndef SILK_CONTROL_H +#define SILK_CONTROL_H + +#include "typedef.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* 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 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; + +} 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; +} silk_DecControlStruct; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/opus/silk/control_SNR.c b/thirdparty/opus/silk/control_SNR.c new file mode 100644 index 0000000000..cee87eb0d8 --- /dev/null +++ b/thirdparty/opus/silk/control_SNR.c @@ -0,0 +1,76 @@ +/*********************************************************************** +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 "tuning_parameters.h" + +/* Control SNR of redidual 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) */ +) +{ + opus_int k, ret = SILK_NO_ERROR; + opus_int32 frac_Q6; + const opus_int32 *rateTable; + + /* Set bitrate/coding quality */ + TargetRate_bps = silk_LIMIT( TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS ); + if( TargetRate_bps != psEncC->TargetRate_bps ) { + psEncC->TargetRate_bps = TargetRate_bps; + + /* If new TargetRate_bps, translate to SNR_dB value */ + if( psEncC->fs_kHz == 8 ) { + rateTable = silk_TargetRate_table_NB; + } else if( psEncC->fs_kHz == 12 ) { + rateTable = silk_TargetRate_table_MB; + } else { + rateTable = silk_TargetRate_table_WB; + } + + /* Reduce bitrate for 10 ms modes in these calculations */ + if( psEncC->nb_subfr == 2 ) { + TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS; + } + + /* Find bitrate interval in table and interpolate */ + for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) { + if( TargetRate_bps <= rateTable[ k ] ) { + frac_Q6 = silk_DIV32( silk_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ), + rateTable[ k ] - rateTable[ k - 1 ] ); + psEncC->SNR_dB_Q7 = silk_LSHIFT( silk_SNR_table_Q1[ k - 1 ], 6 ) + silk_MUL( frac_Q6, silk_SNR_table_Q1[ k ] - silk_SNR_table_Q1[ k - 1 ] ); + break; + } + } + } + + return ret; +} diff --git a/thirdparty/opus/silk/control_audio_bandwidth.c b/thirdparty/opus/silk/control_audio_bandwidth.c new file mode 100644 index 0000000000..4f9bc5cbda --- /dev/null +++ b/thirdparty/opus/silk/control_audio_bandwidth.c @@ -0,0 +1,126 @@ +/*********************************************************************** +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 "tuning_parameters.h" + +/* 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 */ +) +{ + opus_int fs_kHz; + opus_int32 fs_Hz; + + fs_kHz = psEncC->fs_kHz; + fs_Hz = silk_SMULBB( fs_kHz, 1000 ); + if( fs_Hz == 0 ) { + /* Encoder has just been initialized */ + fs_Hz = silk_min( psEncC->desiredInternal_fs_Hz, psEncC->API_fs_Hz ); + fs_kHz = silk_DIV32_16( fs_Hz, 1000 ); + } else if( fs_Hz > psEncC->API_fs_Hz || fs_Hz > psEncC->maxInternal_fs_Hz || fs_Hz < psEncC->minInternal_fs_Hz ) { + /* Make sure internal rate is not higher than external rate or maximum allowed, or lower than minimum allowed */ + fs_Hz = psEncC->API_fs_Hz; + fs_Hz = silk_min( fs_Hz, psEncC->maxInternal_fs_Hz ); + fs_Hz = silk_max( fs_Hz, psEncC->minInternal_fs_Hz ); + fs_kHz = silk_DIV32_16( fs_Hz, 1000 ); + } else { + /* State machine for the internal sampling rate switching */ + if( psEncC->sLP.transition_frame_no >= TRANSITION_FRAMES ) { + /* Stop transition phase */ + psEncC->sLP.mode = 0; + } + if( psEncC->allow_bandwidth_switch || encControl->opusCanSwitch ) { + /* Check if we should switch down */ + if( silk_SMULBB( psEncC->fs_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz ) + { + /* Switch down */ + if( psEncC->sLP.mode == 0 ) { + /* New transition */ + psEncC->sLP.transition_frame_no = TRANSITION_FRAMES; + + /* Reset transition filter state */ + silk_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) ); + } + if( encControl->opusCanSwitch ) { + /* Stop transition phase */ + psEncC->sLP.mode = 0; + + /* Switch to a lower sample frequency */ + fs_kHz = psEncC->fs_kHz == 16 ? 12 : 8; + } else { + if( psEncC->sLP.transition_frame_no <= 0 ) { + encControl->switchReady = 1; + /* Make room for redundancy */ + encControl->maxBits -= encControl->maxBits * 5 / ( encControl->payloadSize_ms + 5 ); + } else { + /* Direction: down (at double speed) */ + psEncC->sLP.mode = -2; + } + } + } + else + /* Check if we should switch up */ + if( silk_SMULBB( psEncC->fs_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz ) + { + /* Switch up */ + if( encControl->opusCanSwitch ) { + /* Switch to a higher sample frequency */ + fs_kHz = psEncC->fs_kHz == 8 ? 12 : 16; + + /* New transition */ + psEncC->sLP.transition_frame_no = 0; + + /* Reset transition filter state */ + silk_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) ); + + /* Direction: up */ + psEncC->sLP.mode = 1; + } else { + if( psEncC->sLP.mode == 0 ) { + encControl->switchReady = 1; + /* Make room for redundancy */ + encControl->maxBits -= encControl->maxBits * 5 / ( encControl->payloadSize_ms + 5 ); + } else { + /* Direction: up */ + psEncC->sLP.mode = 1; + } + } + } else { + if (psEncC->sLP.mode<0) + psEncC->sLP.mode = 1; + } + } + } + + return fs_kHz; +} diff --git a/thirdparty/opus/silk/control_codec.c b/thirdparty/opus/silk/control_codec.c new file mode 100644 index 0000000000..044eea3f2a --- /dev/null +++ b/thirdparty/opus/silk/control_codec.c @@ -0,0 +1,428 @@ +/*********************************************************************** +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" +#define silk_encoder_state_Fxx silk_encoder_state_FIX +#else +#include "main_FLP.h" +#define silk_encoder_state_Fxx silk_encoder_state_FLP +#endif +#include "stack_alloc.h" +#include "tuning_parameters.h" +#include "pitch_est_defines.h" + +static opus_int silk_setup_resamplers( + silk_encoder_state_Fxx *psEnc, /* I/O */ + opus_int fs_kHz /* I */ +); + +static opus_int silk_setup_fs( + silk_encoder_state_Fxx *psEnc, /* I/O */ + opus_int fs_kHz, /* I */ + opus_int PacketSize_ms /* I */ +); + +static opus_int silk_setup_complexity( + silk_encoder_state *psEncC, /* I/O */ + opus_int Complexity /* I */ +); + +static OPUS_INLINE opus_int silk_setup_LBRR( + silk_encoder_state *psEncC, /* I/O */ + const opus_int32 TargetRate_bps /* I */ +); + + +/* Control 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_int32 TargetRate_bps, /* I Target max bitrate (bps) */ + 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 +) +{ + opus_int fs_kHz, ret = 0; + + psEnc->sCmn.useDTX = encControl->useDTX; + psEnc->sCmn.useCBR = encControl->useCBR; + psEnc->sCmn.API_fs_Hz = encControl->API_sampleRate; + psEnc->sCmn.maxInternal_fs_Hz = encControl->maxInternalSampleRate; + psEnc->sCmn.minInternal_fs_Hz = encControl->minInternalSampleRate; + psEnc->sCmn.desiredInternal_fs_Hz = encControl->desiredInternalSampleRate; + psEnc->sCmn.useInBandFEC = encControl->useInBandFEC; + psEnc->sCmn.nChannelsAPI = encControl->nChannelsAPI; + psEnc->sCmn.nChannelsInternal = encControl->nChannelsInternal; + psEnc->sCmn.allow_bandwidth_switch = allow_bw_switch; + psEnc->sCmn.channelNb = channelNb; + + if( psEnc->sCmn.controlled_since_last_payload != 0 && psEnc->sCmn.prefillFlag == 0 ) { + if( psEnc->sCmn.API_fs_Hz != psEnc->sCmn.prev_API_fs_Hz && psEnc->sCmn.fs_kHz > 0 ) { + /* Change in API sampling rate in the middle of encoding a packet */ + ret += silk_setup_resamplers( psEnc, psEnc->sCmn.fs_kHz ); + } + return ret; + } + + /* Beyond this point we know that there are no previously coded frames in the payload buffer */ + + /********************************************/ + /* Determine internal sampling rate */ + /********************************************/ + fs_kHz = silk_control_audio_bandwidth( &psEnc->sCmn, encControl ); + if( force_fs_kHz ) { + fs_kHz = force_fs_kHz; + } + /********************************************/ + /* Prepare resampler and buffered data */ + /********************************************/ + ret += silk_setup_resamplers( psEnc, fs_kHz ); + + /********************************************/ + /* Set internal sampling frequency */ + /********************************************/ + ret += silk_setup_fs( psEnc, fs_kHz, encControl->payloadSize_ms ); + + /********************************************/ + /* Set encoding complexity */ + /********************************************/ + ret += silk_setup_complexity( &psEnc->sCmn, encControl->complexity ); + + /********************************************/ + /* Set packet loss rate measured by farend */ + /********************************************/ + psEnc->sCmn.PacketLoss_perc = encControl->packetLossPercentage; + + /********************************************/ + /* Set LBRR usage */ + /********************************************/ + ret += silk_setup_LBRR( &psEnc->sCmn, TargetRate_bps ); + + psEnc->sCmn.controlled_since_last_payload = 1; + + return ret; +} + +static opus_int silk_setup_resamplers( + silk_encoder_state_Fxx *psEnc, /* I/O */ + opus_int fs_kHz /* I */ +) +{ + opus_int ret = SILK_NO_ERROR; + SAVE_STACK; + + if( psEnc->sCmn.fs_kHz != fs_kHz || psEnc->sCmn.prev_API_fs_Hz != psEnc->sCmn.API_fs_Hz ) + { + if( psEnc->sCmn.fs_kHz == 0 ) { + /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ + ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000, 1 ); + } else { + VARDECL( opus_int16, x_buf_API_fs_Hz ); + VARDECL( silk_resampler_state_struct, temp_resampler_state ); +#ifdef FIXED_POINT + opus_int16 *x_bufFIX = psEnc->x_buf; +#else + VARDECL( opus_int16, x_bufFIX ); + opus_int32 new_buf_samples; +#endif + opus_int32 api_buf_samples; + opus_int32 old_buf_samples; + opus_int32 buf_length_ms; + + buf_length_ms = silk_LSHIFT( psEnc->sCmn.nb_subfr * 5, 1 ) + LA_SHAPE_MS; + old_buf_samples = buf_length_ms * psEnc->sCmn.fs_kHz; + +#ifndef FIXED_POINT + new_buf_samples = buf_length_ms * fs_kHz; + ALLOC( x_bufFIX, silk_max( old_buf_samples, new_buf_samples ), + opus_int16 ); + silk_float2short_array( x_bufFIX, psEnc->x_buf, old_buf_samples ); +#endif + + /* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */ + ALLOC( temp_resampler_state, 1, silk_resampler_state_struct ); + ret += silk_resampler_init( temp_resampler_state, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz, 0 ); + + /* Calculate number of samples to temporarily upsample */ + api_buf_samples = buf_length_ms * silk_DIV32_16( psEnc->sCmn.API_fs_Hz, 1000 ); + + /* Temporary resampling of x_buf data to API_fs_Hz */ + ALLOC( x_buf_API_fs_Hz, api_buf_samples, opus_int16 ); + ret += silk_resampler( temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, old_buf_samples ); + + /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ + ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, silk_SMULBB( fs_kHz, 1000 ), 1 ); + + /* Correct resampler state by resampling buffered data from API_fs_Hz to fs_kHz */ + ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, api_buf_samples ); + +#ifndef FIXED_POINT + silk_short2float_array( psEnc->x_buf, x_bufFIX, new_buf_samples); +#endif + } + } + + psEnc->sCmn.prev_API_fs_Hz = psEnc->sCmn.API_fs_Hz; + + RESTORE_STACK; + return ret; +} + +static opus_int silk_setup_fs( + silk_encoder_state_Fxx *psEnc, /* I/O */ + opus_int fs_kHz, /* I */ + opus_int PacketSize_ms /* I */ +) +{ + opus_int ret = SILK_NO_ERROR; + + /* Set packet size */ + if( PacketSize_ms != psEnc->sCmn.PacketSize_ms ) { + if( ( PacketSize_ms != 10 ) && + ( PacketSize_ms != 20 ) && + ( PacketSize_ms != 40 ) && + ( PacketSize_ms != 60 ) ) { + ret = SILK_ENC_PACKET_SIZE_NOT_SUPPORTED; + } + if( PacketSize_ms <= 10 ) { + psEnc->sCmn.nFramesPerPacket = 1; + psEnc->sCmn.nb_subfr = PacketSize_ms == 10 ? 2 : 1; + psEnc->sCmn.frame_length = silk_SMULBB( PacketSize_ms, fs_kHz ); + psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz ); + if( psEnc->sCmn.fs_kHz == 8 ) { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; + } else { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; + } + } else { + psEnc->sCmn.nFramesPerPacket = silk_DIV32_16( PacketSize_ms, MAX_FRAME_LENGTH_MS ); + psEnc->sCmn.nb_subfr = MAX_NB_SUBFR; + psEnc->sCmn.frame_length = silk_SMULBB( 20, fs_kHz ); + psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz ); + if( psEnc->sCmn.fs_kHz == 8 ) { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; + } else { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF; + } + } + psEnc->sCmn.PacketSize_ms = PacketSize_ms; + psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */ + } + + /* Set internal sampling frequency */ + silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 ); + silk_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 ); + if( psEnc->sCmn.fs_kHz != fs_kHz ) { + /* reset part of the state */ + silk_memset( &psEnc->sShape, 0, sizeof( psEnc->sShape ) ); + silk_memset( &psEnc->sPrefilt, 0, sizeof( psEnc->sPrefilt ) ); + silk_memset( &psEnc->sCmn.sNSQ, 0, sizeof( psEnc->sCmn.sNSQ ) ); + silk_memset( psEnc->sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) ); + silk_memset( &psEnc->sCmn.sLP.In_LP_State, 0, sizeof( psEnc->sCmn.sLP.In_LP_State ) ); + psEnc->sCmn.inputBufIx = 0; + psEnc->sCmn.nFramesEncoded = 0; + psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */ + + /* Initialize non-zero parameters */ + psEnc->sCmn.prevLag = 100; + psEnc->sCmn.first_frame_after_reset = 1; + psEnc->sPrefilt.lagPrev = 100; + psEnc->sShape.LastGainIndex = 10; + psEnc->sCmn.sNSQ.lagPrev = 100; + psEnc->sCmn.sNSQ.prev_gain_Q16 = 65536; + psEnc->sCmn.prevSignalType = TYPE_NO_VOICE_ACTIVITY; + + psEnc->sCmn.fs_kHz = fs_kHz; + if( psEnc->sCmn.fs_kHz == 8 ) { + if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; + } else { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; + } + } else { + if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF; + } else { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; + } + } + if( psEnc->sCmn.fs_kHz == 8 || psEnc->sCmn.fs_kHz == 12 ) { + psEnc->sCmn.predictLPCOrder = MIN_LPC_ORDER; + psEnc->sCmn.psNLSF_CB = &silk_NLSF_CB_NB_MB; + } else { + psEnc->sCmn.predictLPCOrder = MAX_LPC_ORDER; + psEnc->sCmn.psNLSF_CB = &silk_NLSF_CB_WB; + } + psEnc->sCmn.subfr_length = SUB_FRAME_LENGTH_MS * fs_kHz; + psEnc->sCmn.frame_length = silk_SMULBB( psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr ); + psEnc->sCmn.ltp_mem_length = silk_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz ); + psEnc->sCmn.la_pitch = silk_SMULBB( LA_PITCH_MS, fs_kHz ); + psEnc->sCmn.max_pitch_lag = silk_SMULBB( 18, fs_kHz ); + if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { + psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz ); + } else { + psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz ); + } + if( psEnc->sCmn.fs_kHz == 16 ) { + psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_WB, 9 ); + psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform8_iCDF; + } else if( psEnc->sCmn.fs_kHz == 12 ) { + psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_MB, 9 ); + psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform6_iCDF; + } else { + psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_NB, 9 ); + psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform4_iCDF; + } + } + + /* Check that settings are valid */ + silk_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length ); + + return ret; +} + +static opus_int silk_setup_complexity( + silk_encoder_state *psEncC, /* I/O */ + opus_int Complexity /* I */ +) +{ + opus_int ret = 0; + + /* Set encoding complexity */ + silk_assert( Complexity >= 0 && Complexity <= 10 ); + if( Complexity < 2 ) { + psEncC->pitchEstimationComplexity = SILK_PE_MIN_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.8, 16 ); + psEncC->pitchEstimationLPCOrder = 6; + psEncC->shapingLPCOrder = 8; + psEncC->la_shape = 3 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = 1; + psEncC->useInterpolatedNLSFs = 0; + psEncC->LTPQuantLowComplexity = 1; + psEncC->NLSF_MSVQ_Survivors = 2; + psEncC->warping_Q16 = 0; + } else if( Complexity < 4 ) { + psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.76, 16 ); + psEncC->pitchEstimationLPCOrder = 8; + psEncC->shapingLPCOrder = 10; + psEncC->la_shape = 5 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = 1; + psEncC->useInterpolatedNLSFs = 0; + psEncC->LTPQuantLowComplexity = 0; + psEncC->NLSF_MSVQ_Survivors = 4; + psEncC->warping_Q16 = 0; + } else if( Complexity < 6 ) { + psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.74, 16 ); + psEncC->pitchEstimationLPCOrder = 10; + psEncC->shapingLPCOrder = 12; + psEncC->la_shape = 5 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = 2; + psEncC->useInterpolatedNLSFs = 1; + psEncC->LTPQuantLowComplexity = 0; + psEncC->NLSF_MSVQ_Survivors = 8; + psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); + } else if( Complexity < 8 ) { + psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.72, 16 ); + psEncC->pitchEstimationLPCOrder = 12; + psEncC->shapingLPCOrder = 14; + psEncC->la_shape = 5 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = 3; + psEncC->useInterpolatedNLSFs = 1; + psEncC->LTPQuantLowComplexity = 0; + psEncC->NLSF_MSVQ_Survivors = 16; + psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); + } else { + psEncC->pitchEstimationComplexity = SILK_PE_MAX_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.7, 16 ); + psEncC->pitchEstimationLPCOrder = 16; + psEncC->shapingLPCOrder = 16; + psEncC->la_shape = 5 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = MAX_DEL_DEC_STATES; + psEncC->useInterpolatedNLSFs = 1; + psEncC->LTPQuantLowComplexity = 0; + psEncC->NLSF_MSVQ_Survivors = 32; + psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); + } + + /* Do not allow higher pitch estimation LPC order than predict LPC order */ + psEncC->pitchEstimationLPCOrder = silk_min_int( psEncC->pitchEstimationLPCOrder, psEncC->predictLPCOrder ); + psEncC->shapeWinLength = SUB_FRAME_LENGTH_MS * psEncC->fs_kHz + 2 * psEncC->la_shape; + psEncC->Complexity = Complexity; + + silk_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER ); + silk_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER ); + silk_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES ); + silk_assert( psEncC->warping_Q16 <= 32767 ); + silk_assert( psEncC->la_shape <= LA_SHAPE_MAX ); + silk_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX ); + silk_assert( psEncC->NLSF_MSVQ_Survivors <= NLSF_VQ_MAX_SURVIVORS ); + + return ret; +} + +static OPUS_INLINE opus_int silk_setup_LBRR( + silk_encoder_state *psEncC, /* I/O */ + const opus_int32 TargetRate_bps /* I */ +) +{ + opus_int LBRR_in_previous_packet, ret = SILK_NO_ERROR; + opus_int32 LBRR_rate_thres_bps; + + LBRR_in_previous_packet = psEncC->LBRR_enabled; + psEncC->LBRR_enabled = 0; + if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) { + if( psEncC->fs_kHz == 8 ) { + LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS; + } else if( psEncC->fs_kHz == 12 ) { + LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS; + } else { + LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS; + } + LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps, 125 - silk_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) ); + + if( TargetRate_bps > LBRR_rate_thres_bps ) { + /* Set gain increase for coding LBRR excitation */ + if( LBRR_in_previous_packet == 0 ) { + /* Previous packet did not have LBRR, and was therefore coded at a higher bitrate */ + psEncC->LBRR_GainIncreases = 7; + } else { + psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 ); + } + psEncC->LBRR_enabled = 1; + } + } + + return ret; +} diff --git a/thirdparty/opus/silk/debug.c b/thirdparty/opus/silk/debug.c new file mode 100644 index 0000000000..9253faf71b --- /dev/null +++ b/thirdparty/opus/silk/debug.c @@ -0,0 +1,170 @@ +/*********************************************************************** +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 "debug.h" +#include "SigProc_FIX.h" + +#if SILK_TIC_TOC + +#ifdef _WIN32 + +#if (defined(_WIN32) || defined(_WINCE)) +#include <windows.h> /* timer */ +#else /* Linux or Mac*/ +#include <sys/time.h> +#endif + +unsigned long silk_GetHighResolutionTime(void) /* O time in usec*/ +{ + /* Returns a time counter in microsec */ + /* the resolution is platform dependent */ + /* but is typically 1.62 us resolution */ + LARGE_INTEGER lpPerformanceCount; + LARGE_INTEGER lpFrequency; + QueryPerformanceCounter(&lpPerformanceCount); + QueryPerformanceFrequency(&lpFrequency); + return (unsigned long)((1000000*(lpPerformanceCount.QuadPart)) / lpFrequency.QuadPart); +} +#else /* Linux or Mac*/ +unsigned long GetHighResolutionTime(void) /* O time in usec*/ +{ + struct timeval tv; + gettimeofday(&tv, 0); + return((tv.tv_sec*1000000)+(tv.tv_usec)); +} +#endif + +int silk_Timer_nTimers = 0; +int silk_Timer_depth_ctr = 0; +char silk_Timer_tags[silk_NUM_TIMERS_MAX][silk_NUM_TIMERS_MAX_TAG_LEN]; +#ifdef WIN32 +LARGE_INTEGER silk_Timer_start[silk_NUM_TIMERS_MAX]; +#else +unsigned long silk_Timer_start[silk_NUM_TIMERS_MAX]; +#endif +unsigned int silk_Timer_cnt[silk_NUM_TIMERS_MAX]; +opus_int64 silk_Timer_min[silk_NUM_TIMERS_MAX]; +opus_int64 silk_Timer_sum[silk_NUM_TIMERS_MAX]; +opus_int64 silk_Timer_max[silk_NUM_TIMERS_MAX]; +opus_int64 silk_Timer_depth[silk_NUM_TIMERS_MAX]; + +#ifdef WIN32 +void silk_TimerSave(char *file_name) +{ + if( silk_Timer_nTimers > 0 ) + { + int k; + FILE *fp; + LARGE_INTEGER lpFrequency; + LARGE_INTEGER lpPerformanceCount1, lpPerformanceCount2; + int del = 0x7FFFFFFF; + double avg, sum_avg; + /* estimate overhead of calling performance counters */ + for( k = 0; k < 1000; k++ ) { + QueryPerformanceCounter(&lpPerformanceCount1); + QueryPerformanceCounter(&lpPerformanceCount2); + lpPerformanceCount2.QuadPart -= lpPerformanceCount1.QuadPart; + if( (int)lpPerformanceCount2.LowPart < del ) + del = lpPerformanceCount2.LowPart; + } + QueryPerformanceFrequency(&lpFrequency); + /* print results to file */ + sum_avg = 0.0f; + for( k = 0; k < silk_Timer_nTimers; k++ ) { + if (silk_Timer_depth[k] == 0) { + sum_avg += (1e6 * silk_Timer_sum[k] / silk_Timer_cnt[k] - del) / lpFrequency.QuadPart * silk_Timer_cnt[k]; + } + } + fp = fopen(file_name, "w"); + fprintf(fp, " min avg %% max count\n"); + for( k = 0; k < silk_Timer_nTimers; k++ ) { + if (silk_Timer_depth[k] == 0) { + fprintf(fp, "%-28s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 1) { + fprintf(fp, " %-27s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 2) { + fprintf(fp, " %-26s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 3) { + fprintf(fp, " %-25s", silk_Timer_tags[k]); + } else { + fprintf(fp, " %-24s", silk_Timer_tags[k]); + } + avg = (1e6 * silk_Timer_sum[k] / silk_Timer_cnt[k] - del) / lpFrequency.QuadPart; + fprintf(fp, "%8.2f", (1e6 * (silk_max_64(silk_Timer_min[k] - del, 0))) / lpFrequency.QuadPart); + fprintf(fp, "%12.2f %6.2f", avg, 100.0 * avg / sum_avg * silk_Timer_cnt[k]); + fprintf(fp, "%12.2f", (1e6 * (silk_max_64(silk_Timer_max[k] - del, 0))) / lpFrequency.QuadPart); + fprintf(fp, "%10d\n", silk_Timer_cnt[k]); + } + fprintf(fp, " microseconds\n"); + fclose(fp); + } +} +#else +void silk_TimerSave(char *file_name) +{ + if( silk_Timer_nTimers > 0 ) + { + int k; + FILE *fp; + /* print results to file */ + fp = fopen(file_name, "w"); + fprintf(fp, " min avg max count\n"); + for( k = 0; k < silk_Timer_nTimers; k++ ) + { + if (silk_Timer_depth[k] == 0) { + fprintf(fp, "%-28s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 1) { + fprintf(fp, " %-27s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 2) { + fprintf(fp, " %-26s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 3) { + fprintf(fp, " %-25s", silk_Timer_tags[k]); + } else { + fprintf(fp, " %-24s", silk_Timer_tags[k]); + } + fprintf(fp, "%d ", silk_Timer_min[k]); + fprintf(fp, "%f ", (double)silk_Timer_sum[k] / (double)silk_Timer_cnt[k]); + fprintf(fp, "%d ", silk_Timer_max[k]); + fprintf(fp, "%10d\n", silk_Timer_cnt[k]); + } + fprintf(fp, " microseconds\n"); + fclose(fp); + } +} +#endif + +#endif /* SILK_TIC_TOC */ + +#if SILK_DEBUG +FILE *silk_debug_store_fp[ silk_NUM_STORES_MAX ]; +int silk_debug_store_count = 0; +#endif /* SILK_DEBUG */ + diff --git a/thirdparty/opus/silk/debug.h b/thirdparty/opus/silk/debug.h new file mode 100644 index 0000000000..efb6d3e99e --- /dev/null +++ b/thirdparty/opus/silk/debug.h @@ -0,0 +1,279 @@ +/*********************************************************************** +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 + +#include "typedef.h" +#include <stdio.h> /* file writing */ +#include <string.h> /* strcpy, strcmp */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +unsigned long GetHighResolutionTime(void); /* O time in usec*/ + +/* make SILK_DEBUG dependent on compiler's _DEBUG */ +#if defined _WIN32 + #ifdef _DEBUG + #define SILK_DEBUG 1 + #else + #define SILK_DEBUG 0 + #endif + + /* overrule the above */ + #if 0 + /* #define NO_ASSERTS*/ + #undef SILK_DEBUG + #define SILK_DEBUG 1 + #endif +#else + #define SILK_DEBUG 0 +#endif + +/* Flag for using timers */ +#define SILK_TIC_TOC 0 + + +#if SILK_TIC_TOC + +#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 */ + +#ifdef __cplusplus +} +#endif + +#endif /* SILK_DEBUG_H */ diff --git a/thirdparty/opus/silk/dec_API.c b/thirdparty/opus/silk/dec_API.c new file mode 100644 index 0000000000..b7d8ed48d8 --- /dev/null +++ b/thirdparty/opus/silk/dec_API.c @@ -0,0 +1,419 @@ +/*********************************************************************** +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" + +/************************/ +/* 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; +} silk_decoder; + +/*********************/ +/* Decoder functions */ +/*********************/ + +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_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; + + 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_int16 *samplesOut, /* O Decoded output speech vector */ + opus_int32 *nSamplesOut, /* O Number of samples decoded */ + 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, samplesOut1_tmp_storage2 ); + 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; + int delay_stack_alloc; + SAVE_STACK; + + silk_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 { + silk_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 ) { + silk_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. */ + delay_stack_alloc = decControl->internalSampleRate*decControl->nChannelsInternal + < decControl->API_sampleRate*decControl->nChannelsAPI; + ALLOC( samplesOut1_tmp_storage1, delay_stack_alloc ? ALLOC_NONE + : decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2 ), + opus_int16 ); + if ( delay_stack_alloc ) + { + samplesOut1_tmp[ 0 ] = samplesOut; + samplesOut1_tmp[ 1 ] = samplesOut + channel_state[ 0 ].frame_length + 2; + } else { + 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 ); + } + /* 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; + } + ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag, condCoding, 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, + decControl->nChannelsAPI == 2 ? *nSamplesOut : ALLOC_NONE, opus_int16 ); + if( decControl->nChannelsAPI == 2 ) { + resample_out_ptr = samplesOut2_tmp; + } else { + resample_out_ptr = samplesOut; + } + + ALLOC( samplesOut1_tmp_storage2, delay_stack_alloc + ? decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2 ) + : ALLOC_NONE, + opus_int16 ); + if ( delay_stack_alloc ) { + OPUS_COPY(samplesOut1_tmp_storage2, samplesOut, decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2)); + samplesOut1_tmp[ 0 ] = samplesOut1_tmp_storage2; + samplesOut1_tmp[ 1 ] = samplesOut1_tmp_storage2 + channel_state[ 0 ].frame_length + 2; + } + for( n = 0; n < silk_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) { + + /* Resample decoded signal to API_sampleRate */ + ret += silk_resampler( &channel_state[ n ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec ); + + /* Interleave if stereo output and stereo stream */ + if( decControl->nChannelsAPI == 2 ) { + for( i = 0; i < *nSamplesOut; i++ ) { + samplesOut[ n + 2 * i ] = resample_out_ptr[ i ]; + } + } + } + + /* 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 ] = 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/thirdparty/opus/silk/decode_core.c b/thirdparty/opus/silk/decode_core.c new file mode 100644 index 0000000000..b88991e349 --- /dev/null +++ b/thirdparty/opus/silk/decode_core.c @@ -0,0 +1,239 @@ +/*********************************************************************** +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 ); + ALLOC( sLPC_Q14, psDec->subfr_length + MAX_LPC_ORDER, opus_int32 ); + + 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 coeficients 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; + silk_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 */ + silk_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_LSHIFT32( pres_Q14[ i ], 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 ) ); + } + + /* DEBUG_STORE_DATA( dec.pcm, pxq, psDec->subfr_length * sizeof( opus_int16 ) ) */ + + /* 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/thirdparty/opus/silk/decode_frame.c b/thirdparty/opus/silk/decode_frame.c new file mode 100644 index 0000000000..a605d95ac6 --- /dev/null +++ b/thirdparty/opus/silk/decode_frame.c @@ -0,0 +1,129 @@ +/*********************************************************************** +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" + +/****************/ +/* 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 */ + 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 */ + silk_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 ); + 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 PLC state */ + /********************************************************/ + silk_PLC( psDec, psDecCtrl, pOut, 0, arch ); + + psDec->lossCnt = 0; + psDec->prevSignalType = psDec->indices.signalType; + silk_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, arch ); + } + + /*************************/ + /* Update output buffer. */ + /*************************/ + silk_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/thirdparty/opus/silk/decode_indices.c b/thirdparty/opus/silk/decode_indices.c new file mode 100644 index 0000000000..7afe5c26c1 --- /dev/null +++ b/thirdparty/opus/silk/decode_indices.c @@ -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 ] ); + silk_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 countour 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/thirdparty/opus/silk/decode_parameters.c b/thirdparty/opus/silk/decode_parameters.c new file mode 100644 index 0000000000..e345b1dcef --- /dev/null +++ b/thirdparty/opus/silk/decode_parameters.c @@ -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 ); + + /* 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 ); + } 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/thirdparty/opus/silk/decode_pitch.c b/thirdparty/opus/silk/decode_pitch.c new file mode 100644 index 0000000000..fedbc6a525 --- /dev/null +++ b/thirdparty/opus/silk/decode_pitch.c @@ -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 { + silk_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 { + silk_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/thirdparty/opus/silk/decode_pulses.c b/thirdparty/opus/silk/decode_pulses.c new file mode 100644 index 0000000000..d6bbec9225 --- /dev/null +++ b/thirdparty/opus/silk/decode_pulses.c @@ -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 ) { + silk_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/thirdparty/opus/silk/decoder_set_fs.c b/thirdparty/opus/silk/decoder_set_fs.c new file mode 100644 index 0000000000..eef0fd25e1 --- /dev/null +++ b/thirdparty/opus/silk/decoder_set_fs.c @@ -0,0 +1,108 @@ +/*********************************************************************** +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; + + silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 ); + silk_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 */ + silk_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 */ + silk_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH ); + + return ret; +} + diff --git a/thirdparty/opus/silk/define.h b/thirdparty/opus/silk/define.h new file mode 100644 index 0000000000..19c9b00e25 --- /dev/null +++ b/thirdparty/opus/silk/define.h @@ -0,0 +1,235 @@ +/*********************************************************************** +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" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* 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 +#define TARGET_RATE_TAB_SZ 8 + +/* 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 */ + +/* Maximum sampling frequency */ +#define MAX_FS_KHZ 16 +#define MAX_API_FS_KHZ 48 + +/* 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 16 + +#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 32 +#define DECISION_DELAY_MASK ( DECISION_DELAY - 1 ) + +/* 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 */ + +#if( MAX_LPC_ORDER > DECISION_DELAY ) +# define NSQ_LPC_BUF_LENGTH MAX_LPC_ORDER +#else +# define NSQ_LPC_BUF_LENGTH DECISION_DELAY +#endif + +/***************************/ +/* 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_VQ_MAX_SURVIVORS 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_NLSF_SMTH_Q16 16348 /* 0.25 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/opus/silk/enc_API.c b/thirdparty/opus/silk/enc_API.c new file mode 100644 index 0000000000..f8060286db --- /dev/null +++ b/thirdparty/opus/silk/enc_API.c @@ -0,0 +1,563 @@ +/*********************************************************************** +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 "API.h" +#include "control.h" +#include "typedef.h" +#include "stack_alloc.h" +#include "structs.h" +#include "tuning_parameters.h" +#ifdef FIXED_POINT +#include "main_FIX.h" +#else +#include "main_FLP.h" +#endif + +/***************************************/ +/* Read control structure from encoder */ +/***************************************/ +static opus_int silk_QueryEncoder( /* O Returns error code */ + const void *encState, /* I State */ + silk_EncControlStruct *encStatus /* O Encoder Status */ +); + +/****************************************/ +/* Encoder functions */ +/****************************************/ + +opus_int silk_Get_Encoder_Size( /* O Returns error code */ + opus_int *encSizeBytes /* O Number of bytes in SILK encoder state */ +) +{ + opus_int ret = SILK_NO_ERROR; + + *encSizeBytes = sizeof( silk_encoder ); + + return ret; +} + +/*************************/ +/* Init or Reset encoder */ +/*************************/ +opus_int silk_InitEncoder( /* O Returns error code */ + void *encState, /* I/O State */ + int arch, /* I Run-time architecture */ + silk_EncControlStruct *encStatus /* O Encoder Status */ +) +{ + silk_encoder *psEnc; + opus_int n, ret = SILK_NO_ERROR; + + psEnc = (silk_encoder *)encState; + + /* Reset encoder */ + silk_memset( psEnc, 0, sizeof( silk_encoder ) ); + for( n = 0; n < ENCODER_NUM_CHANNELS; n++ ) { + if( ret += silk_init_encoder( &psEnc->state_Fxx[ n ], arch ) ) { + silk_assert( 0 ); + } + } + + psEnc->nChannelsAPI = 1; + psEnc->nChannelsInternal = 1; + + /* Read control structure */ + if( ret += silk_QueryEncoder( encState, encStatus ) ) { + silk_assert( 0 ); + } + + return ret; +} + +/***************************************/ +/* Read control structure from encoder */ +/***************************************/ +static opus_int silk_QueryEncoder( /* O Returns error code */ + const void *encState, /* I State */ + silk_EncControlStruct *encStatus /* O Encoder Status */ +) +{ + opus_int ret = SILK_NO_ERROR; + silk_encoder_state_Fxx *state_Fxx; + silk_encoder *psEnc = (silk_encoder *)encState; + + state_Fxx = psEnc->state_Fxx; + + encStatus->nChannelsAPI = psEnc->nChannelsAPI; + encStatus->nChannelsInternal = psEnc->nChannelsInternal; + encStatus->API_sampleRate = state_Fxx[ 0 ].sCmn.API_fs_Hz; + encStatus->maxInternalSampleRate = state_Fxx[ 0 ].sCmn.maxInternal_fs_Hz; + encStatus->minInternalSampleRate = state_Fxx[ 0 ].sCmn.minInternal_fs_Hz; + encStatus->desiredInternalSampleRate = state_Fxx[ 0 ].sCmn.desiredInternal_fs_Hz; + encStatus->payloadSize_ms = state_Fxx[ 0 ].sCmn.PacketSize_ms; + encStatus->bitRate = state_Fxx[ 0 ].sCmn.TargetRate_bps; + encStatus->packetLossPercentage = state_Fxx[ 0 ].sCmn.PacketLoss_perc; + encStatus->complexity = state_Fxx[ 0 ].sCmn.Complexity; + encStatus->useInBandFEC = state_Fxx[ 0 ].sCmn.useInBandFEC; + encStatus->useDTX = state_Fxx[ 0 ].sCmn.useDTX; + encStatus->useCBR = state_Fxx[ 0 ].sCmn.useCBR; + encStatus->internalSampleRate = silk_SMULBB( state_Fxx[ 0 ].sCmn.fs_kHz, 1000 ); + encStatus->allowBandwidthSwitch = state_Fxx[ 0 ].sCmn.allow_bandwidth_switch; + encStatus->inWBmodeWithoutVariableLP = state_Fxx[ 0 ].sCmn.fs_kHz == 16 && state_Fxx[ 0 ].sCmn.sLP.mode == 0; + + return ret; +} + + +/**************************/ +/* 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_int16 *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 */ +) +{ + opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0; + opus_int nSamplesToBuffer, nSamplesToBufferMax, nBlocksOf10ms; + opus_int nSamplesFromInput = 0, nSamplesFromInputMax; + opus_int speech_act_thr_for_switch_Q8; + opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol, sum; + silk_encoder *psEnc = ( silk_encoder * )encState; + VARDECL( opus_int16, buf ); + opus_int transition, curr_block, tot_blocks; + SAVE_STACK; + + if (encControl->reducedDependency) + { + psEnc->state_Fxx[0].sCmn.first_frame_after_reset = 1; + psEnc->state_Fxx[1].sCmn.first_frame_after_reset = 1; + } + psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded = psEnc->state_Fxx[ 1 ].sCmn.nFramesEncoded = 0; + + /* Check values in encoder control structure */ + if( ( ret = check_control_input( encControl ) ) != 0 ) { + silk_assert( 0 ); + RESTORE_STACK; + return ret; + } + + encControl->switchReady = 0; + + if( encControl->nChannelsInternal > psEnc->nChannelsInternal ) { + /* Mono -> Stereo transition: init state of second channel and stereo state */ + ret += silk_init_encoder( &psEnc->state_Fxx[ 1 ], psEnc->state_Fxx[ 0 ].sCmn.arch ); + silk_memset( psEnc->sStereo.pred_prev_Q13, 0, sizeof( psEnc->sStereo.pred_prev_Q13 ) ); + silk_memset( psEnc->sStereo.sSide, 0, sizeof( psEnc->sStereo.sSide ) ); + psEnc->sStereo.mid_side_amp_Q0[ 0 ] = 0; + psEnc->sStereo.mid_side_amp_Q0[ 1 ] = 1; + psEnc->sStereo.mid_side_amp_Q0[ 2 ] = 0; + psEnc->sStereo.mid_side_amp_Q0[ 3 ] = 1; + psEnc->sStereo.width_prev_Q14 = 0; + psEnc->sStereo.smth_width_Q14 = SILK_FIX_CONST( 1, 14 ); + if( psEnc->nChannelsAPI == 2 ) { + silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof( silk_resampler_state_struct ) ); + silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.In_HP_State, &psEnc->state_Fxx[ 0 ].sCmn.In_HP_State, sizeof( psEnc->state_Fxx[ 1 ].sCmn.In_HP_State ) ); + } + } + + transition = (encControl->payloadSize_ms != psEnc->state_Fxx[ 0 ].sCmn.PacketSize_ms) || (psEnc->nChannelsInternal != encControl->nChannelsInternal); + + psEnc->nChannelsAPI = encControl->nChannelsAPI; + psEnc->nChannelsInternal = encControl->nChannelsInternal; + + nBlocksOf10ms = silk_DIV32( 100 * nSamplesIn, encControl->API_sampleRate ); + tot_blocks = ( nBlocksOf10ms > 1 ) ? nBlocksOf10ms >> 1 : 1; + curr_block = 0; + if( prefillFlag ) { + /* Only accept input length of 10 ms */ + if( nBlocksOf10ms != 1 ) { + silk_assert( 0 ); + RESTORE_STACK; + return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; + } + /* Reset Encoder */ + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + ret = silk_init_encoder( &psEnc->state_Fxx[ n ], psEnc->state_Fxx[ n ].sCmn.arch ); + silk_assert( !ret ); + } + tmp_payloadSize_ms = encControl->payloadSize_ms; + encControl->payloadSize_ms = 10; + tmp_complexity = encControl->complexity; + encControl->complexity = 0; + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; + psEnc->state_Fxx[ n ].sCmn.prefillFlag = 1; + } + } else { + /* Only accept input lengths that are a multiple of 10 ms */ + if( nBlocksOf10ms * encControl->API_sampleRate != 100 * nSamplesIn || nSamplesIn < 0 ) { + silk_assert( 0 ); + RESTORE_STACK; + return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; + } + /* Make sure no more than one packet can be produced */ + if( 1000 * (opus_int32)nSamplesIn > encControl->payloadSize_ms * encControl->API_sampleRate ) { + silk_assert( 0 ); + RESTORE_STACK; + return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; + } + } + + TargetRate_bps = silk_RSHIFT32( encControl->bitRate, encControl->nChannelsInternal - 1 ); + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + /* Force the side channel to the same rate as the mid */ + opus_int force_fs_kHz = (n==1) ? psEnc->state_Fxx[0].sCmn.fs_kHz : 0; + if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) { + silk_assert( 0 ); + RESTORE_STACK; + return ret; + } + if( psEnc->state_Fxx[n].sCmn.first_frame_after_reset || transition ) { + for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) { + psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] = 0; + } + } + psEnc->state_Fxx[ n ].sCmn.inDTX = psEnc->state_Fxx[ n ].sCmn.useDTX; + } + silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); + + /* Input buffering/resampling and encoding */ + nSamplesToBufferMax = + 10 * nBlocksOf10ms * psEnc->state_Fxx[ 0 ].sCmn.fs_kHz; + nSamplesFromInputMax = + silk_DIV32_16( nSamplesToBufferMax * + psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz, + psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 ); + ALLOC( buf, nSamplesFromInputMax, opus_int16 ); + while( 1 ) { + nSamplesToBuffer = psEnc->state_Fxx[ 0 ].sCmn.frame_length - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx; + nSamplesToBuffer = silk_min( nSamplesToBuffer, nSamplesToBufferMax ); + nSamplesFromInput = silk_DIV32_16( nSamplesToBuffer * psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz, psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 ); + /* Resample and write to buffer */ + if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) { + opus_int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded; + for( n = 0; n < nSamplesFromInput; n++ ) { + buf[ n ] = samplesIn[ 2 * n ]; + } + /* Making sure to start both resamplers from the same state when switching from mono to stereo */ + if( psEnc->nPrevChannelsInternal == 1 && id==0 ) { + silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof(psEnc->state_Fxx[ 1 ].sCmn.resampler_state)); + } + + ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, + &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); + psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; + + nSamplesToBuffer = psEnc->state_Fxx[ 1 ].sCmn.frame_length - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx; + nSamplesToBuffer = silk_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); + for( n = 0; n < nSamplesFromInput; n++ ) { + buf[ n ] = samplesIn[ 2 * n + 1 ]; + } + ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, + &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); + + psEnc->state_Fxx[ 1 ].sCmn.inputBufIx += nSamplesToBuffer; + } else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) { + /* Combine left and right channels before resampling */ + for( n = 0; n < nSamplesFromInput; n++ ) { + sum = samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ]; + buf[ n ] = (opus_int16)silk_RSHIFT_ROUND( sum, 1 ); + } + ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, + &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); + /* On the first mono frame, average the results for the two resampler states */ + if( psEnc->nPrevChannelsInternal == 2 && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 ) { + ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, + &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); + for( n = 0; n < psEnc->state_Fxx[ 0 ].sCmn.frame_length; n++ ) { + psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx+n+2 ] = + silk_RSHIFT(psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx+n+2 ] + + psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx+n+2 ], 1); + } + } + psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; + } else { + silk_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 ); + silk_memcpy(buf, samplesIn, nSamplesFromInput*sizeof(opus_int16)); + ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, + &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); + psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; + } + + samplesIn += nSamplesFromInput * encControl->nChannelsAPI; + nSamplesIn -= nSamplesFromInput; + + /* Default */ + psEnc->allowBandwidthSwitch = 0; + + /* Silk encoder */ + if( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx >= psEnc->state_Fxx[ 0 ].sCmn.frame_length ) { + /* Enough data in input buffer, so encode */ + silk_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length ); + silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length ); + + /* Deal with LBRR data */ + if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 && !prefillFlag ) { + /* Create space at start of payload for VAD and FEC flags */ + opus_uint8 iCDF[ 2 ] = { 0, 0 }; + iCDF[ 0 ] = 256 - silk_RSHIFT( 256, ( psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket + 1 ) * encControl->nChannelsInternal ); + ec_enc_icdf( psRangeEnc, 0, iCDF, 8 ); + + /* Encode any LBRR data from previous packet */ + /* Encode LBRR flags */ + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + LBRR_symbol = 0; + for( i = 0; i < psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket; i++ ) { + LBRR_symbol |= silk_LSHIFT( psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ], i ); + } + psEnc->state_Fxx[ n ].sCmn.LBRR_flag = LBRR_symbol > 0 ? 1 : 0; + if( LBRR_symbol && psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket > 1 ) { + ec_enc_icdf( psRangeEnc, LBRR_symbol - 1, silk_LBRR_flags_iCDF_ptr[ psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket - 2 ], 8 ); + } + } + + /* Code LBRR indices and excitation signals */ + for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) { + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + if( psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] ) { + opus_int condCoding; + + if( encControl->nChannelsInternal == 2 && n == 0 ) { + silk_stereo_encode_pred( psRangeEnc, psEnc->sStereo.predIx[ i ] ); + /* For LBRR data there's no need to code the mid-only flag if the side-channel LBRR flag is set */ + if( psEnc->state_Fxx[ 1 ].sCmn.LBRR_flags[ i ] == 0 ) { + silk_stereo_encode_mid_only( psRangeEnc, psEnc->sStereo.mid_only_flags[ i ] ); + } + } + /* Use conditional coding if previous frame available */ + if( i > 0 && psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i - 1 ] ) { + condCoding = CODE_CONDITIONALLY; + } else { + condCoding = CODE_INDEPENDENTLY; + } + silk_encode_indices( &psEnc->state_Fxx[ n ].sCmn, psRangeEnc, i, 1, condCoding ); + silk_encode_pulses( psRangeEnc, psEnc->state_Fxx[ n ].sCmn.indices_LBRR[i].signalType, psEnc->state_Fxx[ n ].sCmn.indices_LBRR[i].quantOffsetType, + psEnc->state_Fxx[ n ].sCmn.pulses_LBRR[ i ], psEnc->state_Fxx[ n ].sCmn.frame_length ); + } + } + } + + /* Reset LBRR flags */ + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + silk_memset( psEnc->state_Fxx[ n ].sCmn.LBRR_flags, 0, sizeof( psEnc->state_Fxx[ n ].sCmn.LBRR_flags ) ); + } + + psEnc->nBitsUsedLBRR = ec_tell( psRangeEnc ); + } + + silk_HP_variable_cutoff( psEnc->state_Fxx ); + + /* Total target bits for packet */ + nBits = silk_DIV32_16( silk_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 ); + /* Subtract bits used for LBRR */ + if( !prefillFlag ) { + nBits -= psEnc->nBitsUsedLBRR; + } + /* Divide by number of uncoded frames left in packet */ + nBits = silk_DIV32_16( nBits, psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket ); + /* Convert to bits/second */ + if( encControl->payloadSize_ms == 10 ) { + TargetRate_bps = silk_SMULBB( nBits, 100 ); + } else { + TargetRate_bps = silk_SMULBB( nBits, 50 ); + } + /* Subtract fraction of bits in excess of target in previous frames and packets */ + TargetRate_bps -= silk_DIV32_16( silk_MUL( psEnc->nBitsExceeded, 1000 ), BITRESERVOIR_DECAY_TIME_MS ); + if( !prefillFlag && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded > 0 ) { + /* Compare actual vs target bits so far in this packet */ + opus_int32 bitsBalance = ec_tell( psRangeEnc ) - psEnc->nBitsUsedLBRR - nBits * psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded; + TargetRate_bps -= silk_DIV32_16( silk_MUL( bitsBalance, 1000 ), BITRESERVOIR_DECAY_TIME_MS ); + } + /* Never exceed input bitrate */ + TargetRate_bps = silk_LIMIT( TargetRate_bps, encControl->bitRate, 5000 ); + + /* Convert Left/Right to Mid/Side */ + if( encControl->nChannelsInternal == 2 ) { + silk_stereo_LR_to_MS( &psEnc->sStereo, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ 2 ], &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ 2 ], + psEnc->sStereo.predIx[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ], &psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ], + MStargetRates_bps, TargetRate_bps, psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8, encControl->toMono, + psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, psEnc->state_Fxx[ 0 ].sCmn.frame_length ); + if( psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] == 0 ) { + /* Reset side channel encoder memory for first frame with side coding */ + if( psEnc->prev_decode_only_middle == 1 ) { + silk_memset( &psEnc->state_Fxx[ 1 ].sShape, 0, sizeof( psEnc->state_Fxx[ 1 ].sShape ) ); + silk_memset( &psEnc->state_Fxx[ 1 ].sPrefilt, 0, sizeof( psEnc->state_Fxx[ 1 ].sPrefilt ) ); + silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sNSQ, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sNSQ ) ); + silk_memset( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15 ) ); + silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State ) ); + psEnc->state_Fxx[ 1 ].sCmn.prevLag = 100; + psEnc->state_Fxx[ 1 ].sCmn.sNSQ.lagPrev = 100; + psEnc->state_Fxx[ 1 ].sShape.LastGainIndex = 10; + psEnc->state_Fxx[ 1 ].sCmn.prevSignalType = TYPE_NO_VOICE_ACTIVITY; + psEnc->state_Fxx[ 1 ].sCmn.sNSQ.prev_gain_Q16 = 65536; + psEnc->state_Fxx[ 1 ].sCmn.first_frame_after_reset = 1; + } + silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 1 ] ); + } else { + psEnc->state_Fxx[ 1 ].sCmn.VAD_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] = 0; + } + if( !prefillFlag ) { + silk_stereo_encode_pred( psRangeEnc, psEnc->sStereo.predIx[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] ); + if( psEnc->state_Fxx[ 1 ].sCmn.VAD_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] == 0 ) { + silk_stereo_encode_mid_only( psRangeEnc, psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] ); + } + } + } else { + /* Buffering */ + silk_memcpy( psEnc->state_Fxx[ 0 ].sCmn.inputBuf, psEnc->sStereo.sMid, 2 * sizeof( opus_int16 ) ); + silk_memcpy( psEnc->sStereo.sMid, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.frame_length ], 2 * sizeof( opus_int16 ) ); + } + silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 0 ] ); + + /* Encode */ + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + opus_int maxBits, useCBR; + + /* Handling rate constraints */ + maxBits = encControl->maxBits; + if( tot_blocks == 2 && curr_block == 0 ) { + maxBits = maxBits * 3 / 5; + } else if( tot_blocks == 3 ) { + if( curr_block == 0 ) { + maxBits = maxBits * 2 / 5; + } else if( curr_block == 1 ) { + maxBits = maxBits * 3 / 4; + } + } + useCBR = encControl->useCBR && curr_block == tot_blocks - 1; + + if( encControl->nChannelsInternal == 1 ) { + channelRate_bps = TargetRate_bps; + } else { + channelRate_bps = MStargetRates_bps[ n ]; + if( n == 0 && MStargetRates_bps[ 1 ] > 0 ) { + useCBR = 0; + /* Give mid up to 1/2 of the max bits for that frame */ + maxBits -= encControl->maxBits / ( tot_blocks * 2 ); + } + } + + if( channelRate_bps > 0 ) { + opus_int condCoding; + + silk_control_SNR( &psEnc->state_Fxx[ n ].sCmn, channelRate_bps ); + + /* Use independent coding if no previous frame available */ + if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded - n <= 0 ) { + condCoding = CODE_INDEPENDENTLY; + } else if( n > 0 && psEnc->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; + } + if( ( ret = silk_encode_frame_Fxx( &psEnc->state_Fxx[ n ], nBytesOut, psRangeEnc, condCoding, maxBits, useCBR ) ) != 0 ) { + silk_assert( 0 ); + } + } + psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; + psEnc->state_Fxx[ n ].sCmn.inputBufIx = 0; + psEnc->state_Fxx[ n ].sCmn.nFramesEncoded++; + } + psEnc->prev_decode_only_middle = psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded - 1 ]; + + /* Insert VAD and FEC flags at beginning of bitstream */ + if( *nBytesOut > 0 && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket) { + flags = 0; + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + for( i = 0; i < psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket; i++ ) { + flags = silk_LSHIFT( flags, 1 ); + flags |= psEnc->state_Fxx[ n ].sCmn.VAD_flags[ i ]; + } + flags = silk_LSHIFT( flags, 1 ); + flags |= psEnc->state_Fxx[ n ].sCmn.LBRR_flag; + } + if( !prefillFlag ) { + ec_enc_patch_initial_bits( psRangeEnc, flags, ( psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket + 1 ) * encControl->nChannelsInternal ); + } + + /* Return zero bytes if all channels DTXed */ + if( psEnc->state_Fxx[ 0 ].sCmn.inDTX && ( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inDTX ) ) { + *nBytesOut = 0; + } + + psEnc->nBitsExceeded += *nBytesOut * 8; + psEnc->nBitsExceeded -= silk_DIV32_16( silk_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 ); + psEnc->nBitsExceeded = silk_LIMIT( psEnc->nBitsExceeded, 0, 10000 ); + + /* Update flag indicating if bandwidth switching is allowed */ + speech_act_thr_for_switch_Q8 = silk_SMLAWB( SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ), + SILK_FIX_CONST( ( 1 - SPEECH_ACTIVITY_DTX_THRES ) / MAX_BANDWIDTH_SWITCH_DELAY_MS, 16 + 8 ), psEnc->timeSinceSwitchAllowed_ms ); + if( psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8 < speech_act_thr_for_switch_Q8 ) { + psEnc->allowBandwidthSwitch = 1; + psEnc->timeSinceSwitchAllowed_ms = 0; + } else { + psEnc->allowBandwidthSwitch = 0; + psEnc->timeSinceSwitchAllowed_ms += encControl->payloadSize_ms; + } + } + + if( nSamplesIn == 0 ) { + break; + } + } else { + break; + } + curr_block++; + } + + psEnc->nPrevChannelsInternal = encControl->nChannelsInternal; + + encControl->allowBandwidthSwitch = psEnc->allowBandwidthSwitch; + encControl->inWBmodeWithoutVariableLP = psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == 16 && psEnc->state_Fxx[ 0 ].sCmn.sLP.mode == 0; + encControl->internalSampleRate = silk_SMULBB( psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, 1000 ); + encControl->stereoWidth_Q14 = encControl->toMono ? 0 : psEnc->sStereo.smth_width_Q14; + if( prefillFlag ) { + encControl->payloadSize_ms = tmp_payloadSize_ms; + encControl->complexity = tmp_complexity; + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; + psEnc->state_Fxx[ n ].sCmn.prefillFlag = 0; + } + } + + RESTORE_STACK; + return ret; +} + diff --git a/thirdparty/opus/silk/encode_indices.c b/thirdparty/opus/silk/encode_indices.c new file mode 100644 index 0000000000..666c8c0b13 --- /dev/null +++ b/thirdparty/opus/silk/encode_indices.c @@ -0,0 +1,181 @@ +/*********************************************************************** +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" + +/* Encode side-information parameters to payload */ +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 */ +) +{ + opus_int i, k, typeOffset; + opus_int encode_absolute_lagIndex, delta_lagIndex; + opus_int16 ec_ix[ MAX_LPC_ORDER ]; + opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; + const SideInfoIndices *psIndices; + + if( encode_LBRR ) { + psIndices = &psEncC->indices_LBRR[ FrameIndex ]; + } else { + psIndices = &psEncC->indices; + } + + /*******************************************/ + /* Encode signal type and quantizer offset */ + /*******************************************/ + typeOffset = 2 * psIndices->signalType + psIndices->quantOffsetType; + silk_assert( typeOffset >= 0 && typeOffset < 6 ); + silk_assert( encode_LBRR == 0 || typeOffset >= 2 ); + if( encode_LBRR || typeOffset >= 2 ) { + ec_enc_icdf( psRangeEnc, typeOffset - 2, silk_type_offset_VAD_iCDF, 8 ); + } else { + ec_enc_icdf( psRangeEnc, typeOffset, silk_type_offset_no_VAD_iCDF, 8 ); + } + + /****************/ + /* Encode gains */ + /****************/ + /* first subframe */ + if( condCoding == CODE_CONDITIONALLY ) { + /* conditional coding */ + silk_assert( psIndices->GainsIndices[ 0 ] >= 0 && psIndices->GainsIndices[ 0 ] < MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ); + ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ 0 ], silk_delta_gain_iCDF, 8 ); + } else { + /* independent coding, in two stages: MSB bits followed by 3 LSBs */ + silk_assert( psIndices->GainsIndices[ 0 ] >= 0 && psIndices->GainsIndices[ 0 ] < N_LEVELS_QGAIN ); + ec_enc_icdf( psRangeEnc, silk_RSHIFT( psIndices->GainsIndices[ 0 ], 3 ), silk_gain_iCDF[ psIndices->signalType ], 8 ); + ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ 0 ] & 7, silk_uniform8_iCDF, 8 ); + } + + /* remaining subframes */ + for( i = 1; i < psEncC->nb_subfr; i++ ) { + silk_assert( psIndices->GainsIndices[ i ] >= 0 && psIndices->GainsIndices[ i ] < MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ); + ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ i ], silk_delta_gain_iCDF, 8 ); + } + + /****************/ + /* Encode NLSFs */ + /****************/ + ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ 0 ], &psEncC->psNLSF_CB->CB1_iCDF[ ( psIndices->signalType >> 1 ) * psEncC->psNLSF_CB->nVectors ], 8 ); + silk_NLSF_unpack( ec_ix, pred_Q8, psEncC->psNLSF_CB, psIndices->NLSFIndices[ 0 ] ); + silk_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder ); + for( i = 0; i < psEncC->psNLSF_CB->order; i++ ) { + if( psIndices->NLSFIndices[ i+1 ] >= NLSF_QUANT_MAX_AMPLITUDE ) { + ec_enc_icdf( psRangeEnc, 2 * NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); + ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ i+1 ] - NLSF_QUANT_MAX_AMPLITUDE, silk_NLSF_EXT_iCDF, 8 ); + } else if( psIndices->NLSFIndices[ i+1 ] <= -NLSF_QUANT_MAX_AMPLITUDE ) { + ec_enc_icdf( psRangeEnc, 0, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); + ec_enc_icdf( psRangeEnc, -psIndices->NLSFIndices[ i+1 ] - NLSF_QUANT_MAX_AMPLITUDE, silk_NLSF_EXT_iCDF, 8 ); + } else { + ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ i+1 ] + NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); + } + } + + /* Encode NLSF interpolation factor */ + if( psEncC->nb_subfr == MAX_NB_SUBFR ) { + silk_assert( psIndices->NLSFInterpCoef_Q2 >= 0 && psIndices->NLSFInterpCoef_Q2 < 5 ); + ec_enc_icdf( psRangeEnc, psIndices->NLSFInterpCoef_Q2, silk_NLSF_interpolation_factor_iCDF, 8 ); + } + + if( psIndices->signalType == TYPE_VOICED ) + { + /*********************/ + /* Encode pitch lags */ + /*********************/ + /* lag index */ + encode_absolute_lagIndex = 1; + if( condCoding == CODE_CONDITIONALLY && psEncC->ec_prevSignalType == TYPE_VOICED ) { + /* Delta Encoding */ + delta_lagIndex = psIndices->lagIndex - psEncC->ec_prevLagIndex; + if( delta_lagIndex < -8 || delta_lagIndex > 11 ) { + delta_lagIndex = 0; + } else { + delta_lagIndex = delta_lagIndex + 9; + encode_absolute_lagIndex = 0; /* Only use delta */ + } + silk_assert( delta_lagIndex >= 0 && delta_lagIndex < 21 ); + ec_enc_icdf( psRangeEnc, delta_lagIndex, silk_pitch_delta_iCDF, 8 ); + } + if( encode_absolute_lagIndex ) { + /* Absolute encoding */ + opus_int32 pitch_high_bits, pitch_low_bits; + pitch_high_bits = silk_DIV32_16( psIndices->lagIndex, silk_RSHIFT( psEncC->fs_kHz, 1 ) ); + pitch_low_bits = psIndices->lagIndex - silk_SMULBB( pitch_high_bits, silk_RSHIFT( psEncC->fs_kHz, 1 ) ); + silk_assert( pitch_low_bits < psEncC->fs_kHz / 2 ); + silk_assert( pitch_high_bits < 32 ); + ec_enc_icdf( psRangeEnc, pitch_high_bits, silk_pitch_lag_iCDF, 8 ); + ec_enc_icdf( psRangeEnc, pitch_low_bits, psEncC->pitch_lag_low_bits_iCDF, 8 ); + } + psEncC->ec_prevLagIndex = psIndices->lagIndex; + + /* Countour index */ + silk_assert( psIndices->contourIndex >= 0 ); + silk_assert( ( psIndices->contourIndex < 34 && psEncC->fs_kHz > 8 && psEncC->nb_subfr == 4 ) || + ( psIndices->contourIndex < 11 && psEncC->fs_kHz == 8 && psEncC->nb_subfr == 4 ) || + ( psIndices->contourIndex < 12 && psEncC->fs_kHz > 8 && psEncC->nb_subfr == 2 ) || + ( psIndices->contourIndex < 3 && psEncC->fs_kHz == 8 && psEncC->nb_subfr == 2 ) ); + ec_enc_icdf( psRangeEnc, psIndices->contourIndex, psEncC->pitch_contour_iCDF, 8 ); + + /********************/ + /* Encode LTP gains */ + /********************/ + /* PERIndex value */ + silk_assert( psIndices->PERIndex >= 0 && psIndices->PERIndex < 3 ); + ec_enc_icdf( psRangeEnc, psIndices->PERIndex, silk_LTP_per_index_iCDF, 8 ); + + /* Codebook Indices */ + for( k = 0; k < psEncC->nb_subfr; k++ ) { + silk_assert( psIndices->LTPIndex[ k ] >= 0 && psIndices->LTPIndex[ k ] < ( 8 << psIndices->PERIndex ) ); + ec_enc_icdf( psRangeEnc, psIndices->LTPIndex[ k ], silk_LTP_gain_iCDF_ptrs[ psIndices->PERIndex ], 8 ); + } + + /**********************/ + /* Encode LTP scaling */ + /**********************/ + if( condCoding == CODE_INDEPENDENTLY ) { + silk_assert( psIndices->LTP_scaleIndex >= 0 && psIndices->LTP_scaleIndex < 3 ); + ec_enc_icdf( psRangeEnc, psIndices->LTP_scaleIndex, silk_LTPscale_iCDF, 8 ); + } + silk_assert( !condCoding || psIndices->LTP_scaleIndex == 0 ); + } + + psEncC->ec_prevSignalType = psIndices->signalType; + + /***************/ + /* Encode seed */ + /***************/ + silk_assert( psIndices->Seed >= 0 && psIndices->Seed < 4 ); + ec_enc_icdf( psRangeEnc, psIndices->Seed, silk_uniform4_iCDF, 8 ); +} diff --git a/thirdparty/opus/silk/encode_pulses.c b/thirdparty/opus/silk/encode_pulses.c new file mode 100644 index 0000000000..ab00264f99 --- /dev/null +++ b/thirdparty/opus/silk/encode_pulses.c @@ -0,0 +1,206 @@ +/*********************************************************************** +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" + +/*********************************************/ +/* Encode quantization indices of excitation */ +/*********************************************/ + +static OPUS_INLINE opus_int combine_and_check( /* return ok */ + opus_int *pulses_comb, /* O */ + const opus_int *pulses_in, /* I */ + opus_int max_pulses, /* I max value for sum of pulses */ + opus_int len /* I number of output values */ +) +{ + opus_int k, sum; + + for( k = 0; k < len; k++ ) { + sum = pulses_in[ 2 * k ] + pulses_in[ 2 * k + 1 ]; + if( sum > max_pulses ) { + return 1; + } + pulses_comb[ k ] = sum; + } + + return 0; +} + +/* 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 */ +) +{ + opus_int i, k, j, iter, bit, nLS, scale_down, RateLevelIndex = 0; + opus_int32 abs_q, minSumBits_Q5, sumBits_Q5; + VARDECL( opus_int, abs_pulses ); + VARDECL( opus_int, sum_pulses ); + VARDECL( opus_int, nRshifts ); + opus_int pulses_comb[ 8 ]; + opus_int *abs_pulses_ptr; + const opus_int8 *pulses_ptr; + const opus_uint8 *cdf_ptr; + const opus_uint8 *nBits_ptr; + SAVE_STACK; + + silk_memset( pulses_comb, 0, 8 * sizeof( opus_int ) ); /* Fixing Valgrind reported problem*/ + + /****************************/ + /* Prepare for shell coding */ + /****************************/ + /* 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 ) { + silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */ + iter++; + silk_memset( &pulses[ frame_length ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof(opus_int8)); + } + + /* Take the absolute value of the pulses */ + ALLOC( abs_pulses, iter * SHELL_CODEC_FRAME_LENGTH, opus_int ); + silk_assert( !( SHELL_CODEC_FRAME_LENGTH & 3 ) ); + for( i = 0; i < iter * SHELL_CODEC_FRAME_LENGTH; i+=4 ) { + abs_pulses[i+0] = ( opus_int )silk_abs( pulses[ i + 0 ] ); + abs_pulses[i+1] = ( opus_int )silk_abs( pulses[ i + 1 ] ); + abs_pulses[i+2] = ( opus_int )silk_abs( pulses[ i + 2 ] ); + abs_pulses[i+3] = ( opus_int )silk_abs( pulses[ i + 3 ] ); + } + + /* Calc sum pulses per shell code frame */ + ALLOC( sum_pulses, iter, opus_int ); + ALLOC( nRshifts, iter, opus_int ); + abs_pulses_ptr = abs_pulses; + for( i = 0; i < iter; i++ ) { + nRshifts[ i ] = 0; + + while( 1 ) { + /* 1+1 -> 2 */ + scale_down = combine_and_check( pulses_comb, abs_pulses_ptr, silk_max_pulses_table[ 0 ], 8 ); + /* 2+2 -> 4 */ + scale_down += combine_and_check( pulses_comb, pulses_comb, silk_max_pulses_table[ 1 ], 4 ); + /* 4+4 -> 8 */ + scale_down += combine_and_check( pulses_comb, pulses_comb, silk_max_pulses_table[ 2 ], 2 ); + /* 8+8 -> 16 */ + scale_down += combine_and_check( &sum_pulses[ i ], pulses_comb, silk_max_pulses_table[ 3 ], 1 ); + + if( scale_down ) { + /* We need to downscale the quantization signal */ + nRshifts[ i ]++; + for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { + abs_pulses_ptr[ k ] = silk_RSHIFT( abs_pulses_ptr[ k ], 1 ); + } + } else { + /* Jump out of while(1) loop and go to next shell coding frame */ + break; + } + } + abs_pulses_ptr += SHELL_CODEC_FRAME_LENGTH; + } + + /**************/ + /* Rate level */ + /**************/ + /* find rate level that leads to fewest bits for coding of pulses per block info */ + minSumBits_Q5 = silk_int32_MAX; + for( k = 0; k < N_RATE_LEVELS - 1; k++ ) { + nBits_ptr = silk_pulses_per_block_BITS_Q5[ k ]; + sumBits_Q5 = silk_rate_levels_BITS_Q5[ signalType >> 1 ][ k ]; + for( i = 0; i < iter; i++ ) { + if( nRshifts[ i ] > 0 ) { + sumBits_Q5 += nBits_ptr[ SILK_MAX_PULSES + 1 ]; + } else { + sumBits_Q5 += nBits_ptr[ sum_pulses[ i ] ]; + } + } + if( sumBits_Q5 < minSumBits_Q5 ) { + minSumBits_Q5 = sumBits_Q5; + RateLevelIndex = k; + } + } + ec_enc_icdf( psRangeEnc, RateLevelIndex, silk_rate_levels_iCDF[ signalType >> 1 ], 8 ); + + /***************************************************/ + /* Sum-Weighted-Pulses Encoding */ + /***************************************************/ + cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ]; + for( i = 0; i < iter; i++ ) { + if( nRshifts[ i ] == 0 ) { + ec_enc_icdf( psRangeEnc, sum_pulses[ i ], cdf_ptr, 8 ); + } else { + ec_enc_icdf( psRangeEnc, SILK_MAX_PULSES + 1, cdf_ptr, 8 ); + for( k = 0; k < nRshifts[ i ] - 1; k++ ) { + ec_enc_icdf( psRangeEnc, SILK_MAX_PULSES + 1, silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 ); + } + ec_enc_icdf( psRangeEnc, sum_pulses[ i ], silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 ); + } + } + + /******************/ + /* Shell Encoding */ + /******************/ + for( i = 0; i < iter; i++ ) { + if( sum_pulses[ i ] > 0 ) { + silk_shell_encoder( psRangeEnc, &abs_pulses[ i * SHELL_CODEC_FRAME_LENGTH ] ); + } + } + + /****************/ + /* LSB Encoding */ + /****************/ + for( i = 0; i < iter; i++ ) { + if( nRshifts[ i ] > 0 ) { + pulses_ptr = &pulses[ i * SHELL_CODEC_FRAME_LENGTH ]; + nLS = nRshifts[ i ] - 1; + for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { + abs_q = (opus_int8)silk_abs( pulses_ptr[ k ] ); + for( j = nLS; j > 0; j-- ) { + bit = silk_RSHIFT( abs_q, j ) & 1; + ec_enc_icdf( psRangeEnc, bit, silk_lsb_iCDF, 8 ); + } + bit = abs_q & 1; + ec_enc_icdf( psRangeEnc, bit, silk_lsb_iCDF, 8 ); + } + } + } + + /****************/ + /* Encode signs */ + /****************/ + silk_encode_signs( psRangeEnc, pulses, frame_length, signalType, quantOffsetType, sum_pulses ); + RESTORE_STACK; +} diff --git a/drivers/opus/silk/errors.h b/thirdparty/opus/silk/errors.h index 45070800f2..45070800f2 100644 --- a/drivers/opus/silk/errors.h +++ b/thirdparty/opus/silk/errors.h diff --git a/thirdparty/opus/silk/fixed/LTP_analysis_filter_FIX.c b/thirdparty/opus/silk/fixed/LTP_analysis_filter_FIX.c new file mode 100644 index 0000000000..5574e7069f --- /dev/null +++ b/thirdparty/opus/silk/fixed/LTP_analysis_filter_FIX.c @@ -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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" + +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 */ +) +{ + const opus_int16 *x_ptr, *x_lag_ptr; + opus_int16 Btmp_Q14[ LTP_ORDER ]; + opus_int16 *LTP_res_ptr; + opus_int k, i; + opus_int32 LTP_est; + + x_ptr = x; + LTP_res_ptr = LTP_res; + for( k = 0; k < nb_subfr; k++ ) { + + x_lag_ptr = x_ptr - pitchL[ k ]; + + Btmp_Q14[ 0 ] = LTPCoef_Q14[ k * LTP_ORDER ]; + Btmp_Q14[ 1 ] = LTPCoef_Q14[ k * LTP_ORDER + 1 ]; + Btmp_Q14[ 2 ] = LTPCoef_Q14[ k * LTP_ORDER + 2 ]; + Btmp_Q14[ 3 ] = LTPCoef_Q14[ k * LTP_ORDER + 3 ]; + Btmp_Q14[ 4 ] = LTPCoef_Q14[ k * LTP_ORDER + 4 ]; + + /* LTP analysis FIR filter */ + for( i = 0; i < subfr_length + pre_length; i++ ) { + LTP_res_ptr[ i ] = x_ptr[ i ]; + + /* Long-term prediction */ + LTP_est = silk_SMULBB( x_lag_ptr[ LTP_ORDER / 2 ], Btmp_Q14[ 0 ] ); + LTP_est = silk_SMLABB_ovflw( LTP_est, x_lag_ptr[ 1 ], Btmp_Q14[ 1 ] ); + LTP_est = silk_SMLABB_ovflw( LTP_est, x_lag_ptr[ 0 ], Btmp_Q14[ 2 ] ); + LTP_est = silk_SMLABB_ovflw( LTP_est, x_lag_ptr[ -1 ], Btmp_Q14[ 3 ] ); + LTP_est = silk_SMLABB_ovflw( LTP_est, x_lag_ptr[ -2 ], Btmp_Q14[ 4 ] ); + + LTP_est = silk_RSHIFT_ROUND( LTP_est, 14 ); /* round and -> Q0*/ + + /* Subtract long-term prediction */ + LTP_res_ptr[ i ] = (opus_int16)silk_SAT16( (opus_int32)x_ptr[ i ] - LTP_est ); + + /* Scale residual */ + LTP_res_ptr[ i ] = silk_SMULWB( invGains_Q16[ k ], LTP_res_ptr[ i ] ); + + x_lag_ptr++; + } + + /* Update pointers */ + LTP_res_ptr += subfr_length + pre_length; + x_ptr += subfr_length; + } +} + diff --git a/thirdparty/opus/silk/fixed/LTP_scale_ctrl_FIX.c b/thirdparty/opus/silk/fixed/LTP_scale_ctrl_FIX.c new file mode 100644 index 0000000000..3dcedef891 --- /dev/null +++ b/thirdparty/opus/silk/fixed/LTP_scale_ctrl_FIX.c @@ -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 "main_FIX.h" + +/* 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 */ +) +{ + opus_int round_loss; + + if( condCoding == CODE_INDEPENDENTLY ) { + /* Only scale if first frame in packet */ + round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket; + psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( + silk_SMULWB( silk_SMULBB( round_loss, psEncCtrl->LTPredCodGain_Q7 ), SILK_FIX_CONST( 0.1, 9 ) ), 0, 2 ); + } else { + /* Default is minimum scaling */ + psEnc->sCmn.indices.LTP_scaleIndex = 0; + } + psEncCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ]; +} diff --git a/thirdparty/opus/silk/fixed/apply_sine_window_FIX.c b/thirdparty/opus/silk/fixed/apply_sine_window_FIX.c new file mode 100644 index 0000000000..4502b7130e --- /dev/null +++ b/thirdparty/opus/silk/fixed/apply_sine_window_FIX.c @@ -0,0 +1,101 @@ +/*********************************************************************** +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" + +/* 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 is linearly interpolated, for speed. */ +/* Window length must be between 16 and 120 (incl) and a multiple of 4. */ + +/* Matlab code for table: + for k=16:9*4:16+2*9*4, fprintf(' %7.d,', -round(65536*pi ./ (k:4:k+8*4))); fprintf('\n'); end +*/ +static const opus_int16 freq_table_Q16[ 27 ] = { + 12111, 9804, 8235, 7100, 6239, 5565, 5022, 4575, 4202, + 3885, 3612, 3375, 3167, 2984, 2820, 2674, 2542, 2422, + 2313, 2214, 2123, 2038, 1961, 1889, 1822, 1760, 1702, +}; + +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 */ +) +{ + opus_int k, f_Q16, c_Q16; + opus_int32 S0_Q16, S1_Q16; + + silk_assert( win_type == 1 || win_type == 2 ); + + /* Length must be in a range from 16 to 120 and a multiple of 4 */ + silk_assert( length >= 16 && length <= 120 ); + silk_assert( ( length & 3 ) == 0 ); + + /* Frequency */ + k = ( length >> 2 ) - 4; + silk_assert( k >= 0 && k <= 26 ); + f_Q16 = (opus_int)freq_table_Q16[ k ]; + + /* Factor used for cosine approximation */ + c_Q16 = silk_SMULWB( (opus_int32)f_Q16, -f_Q16 ); + silk_assert( c_Q16 >= -32768 ); + + /* initialize state */ + if( win_type == 1 ) { + /* start from 0 */ + S0_Q16 = 0; + /* approximation of sin(f) */ + S1_Q16 = f_Q16 + silk_RSHIFT( length, 3 ); + } else { + /* start from 1 */ + S0_Q16 = ( (opus_int32)1 << 16 ); + /* approximation of cos(f) */ + S1_Q16 = ( (opus_int32)1 << 16 ) + silk_RSHIFT( c_Q16, 1 ) + silk_RSHIFT( length, 4 ); + } + + /* 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 ] = (opus_int16)silk_SMULWB( silk_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k ] ); + px_win[ k + 1 ] = (opus_int16)silk_SMULWB( S1_Q16, px[ k + 1] ); + S0_Q16 = silk_SMULWB( S1_Q16, c_Q16 ) + silk_LSHIFT( S1_Q16, 1 ) - S0_Q16 + 1; + S0_Q16 = silk_min( S0_Q16, ( (opus_int32)1 << 16 ) ); + + px_win[ k + 2 ] = (opus_int16)silk_SMULWB( silk_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k + 2] ); + px_win[ k + 3 ] = (opus_int16)silk_SMULWB( S0_Q16, px[ k + 3 ] ); + S1_Q16 = silk_SMULWB( S0_Q16, c_Q16 ) + silk_LSHIFT( S0_Q16, 1 ) - S1_Q16; + S1_Q16 = silk_min( S1_Q16, ( (opus_int32)1 << 16 ) ); + } +} diff --git a/thirdparty/opus/silk/fixed/autocorr_FIX.c b/thirdparty/opus/silk/fixed/autocorr_FIX.c new file mode 100644 index 0000000000..de95c98693 --- /dev/null +++ b/thirdparty/opus/silk/fixed/autocorr_FIX.c @@ -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 "SigProc_FIX.h" +#include "celt_lpc.h" + +/* 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 */ +) +{ + opus_int corrCount; + corrCount = silk_min_int( inputDataSize, correlationCount ); + *scale = _celt_autocorr(inputData, results, NULL, 0, corrCount-1, inputDataSize, arch); +} diff --git a/thirdparty/opus/silk/fixed/burg_modified_FIX.c b/thirdparty/opus/silk/fixed/burg_modified_FIX.c new file mode 100644 index 0000000000..4878553b65 --- /dev/null +++ b/thirdparty/opus/silk/fixed/burg_modified_FIX.c @@ -0,0 +1,275 @@ +/*********************************************************************** +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" +#include "tuning_parameters.h" +#include "pitch.h" + +#define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */ + +#define QA 25 +#define N_BITS_HEAD_ROOM 2 +#define MIN_RSHIFTS -16 +#define MAX_RSHIFTS (32 - QA) + +/* 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 */ +) +{ + opus_int k, n, s, lz, rshifts, reached_max_gain; + opus_int32 C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2; + const opus_int16 *x_ptr; + opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ]; + opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ]; + opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ]; + opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ]; + opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ]; + opus_int32 xcorr[ SILK_MAX_ORDER_LPC ]; + opus_int64 C0_64; + + silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); + + /* Compute autocorrelations, added over subframes */ + C0_64 = silk_inner_prod16_aligned_64( x, x, subfr_length*nb_subfr, arch ); + lz = silk_CLZ64(C0_64); + rshifts = 32 + 1 + N_BITS_HEAD_ROOM - lz; + if (rshifts > MAX_RSHIFTS) rshifts = MAX_RSHIFTS; + if (rshifts < MIN_RSHIFTS) rshifts = MIN_RSHIFTS; + + if (rshifts > 0) { + C0 = (opus_int32)silk_RSHIFT64(C0_64, rshifts ); + } else { + C0 = silk_LSHIFT32((opus_int32)C0_64, -rshifts ); + } + + CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ + silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); + if( rshifts > 0 ) { + 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 ] += (opus_int32)silk_RSHIFT64( + silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n, arch ), rshifts ); + } + } + } else { + for( s = 0; s < nb_subfr; s++ ) { + int i; + opus_int32 d; + x_ptr = x + s * subfr_length; + celt_pitch_xcorr(x_ptr, x_ptr + 1, xcorr, subfr_length - D, D, arch ); + for( n = 1; n < D + 1; n++ ) { + for ( i = n + subfr_length - D, d = 0; i < subfr_length; i++ ) + d = MAC16_16( d, x_ptr[ i ], x_ptr[ i - n ] ); + xcorr[ n - 1 ] += d; + } + for( n = 1; n < D + 1; n++ ) { + C_first_row[ n - 1 ] += silk_LSHIFT32( xcorr[ n - 1 ], -rshifts ); + } + } + } + silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); + + /* Initialize */ + CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ + + invGain_Q30 = (opus_int32)1 << 30; + 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) */ + if( rshifts > -2 ) { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], 16 - rshifts ); /* Q(16-rshifts) */ + x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts ); /* Q(16-rshifts) */ + tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], QA - 16 ); /* Q(QA-16) */ + tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); /* Q(QA-16) */ + for( k = 0; k < n; k++ ) { + C_first_row[ k ] = silk_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ + C_last_row[ k ] = silk_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ + Atmp_QA = Af_QA[ k ]; + tmp1 = silk_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); /* Q(QA-16) */ + tmp2 = silk_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] ); /* Q(QA-16) */ + } + tmp1 = silk_LSHIFT32( -tmp1, 32 - QA - rshifts ); /* Q(16-rshifts) */ + tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts ); /* Q(16-rshifts) */ + for( k = 0; k <= n; k++ ) { + CAf[ k ] = silk_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); /* Q( -rshift ) */ + CAb[ k ] = silk_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); /* Q( -rshift ) */ + } + } + } else { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], -rshifts ); /* Q( -rshifts ) */ + x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); /* Q( -rshifts ) */ + tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); /* Q17 */ + tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); /* Q17 */ + for( k = 0; k < n; k++ ) { + C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ + C_last_row[ k ] = silk_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ + Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); /* Q17 */ + tmp1 = silk_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */ + tmp2 = silk_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17 */ + } + tmp1 = -tmp1; /* Q17 */ + tmp2 = -tmp2; /* Q17 */ + for( k = 0; k <= n; k++ ) { + CAf[ k ] = silk_SMLAWW( CAf[ k ], tmp1, + silk_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) ); /* Q( -rshift ) */ + CAb[ k ] = silk_SMLAWW( CAb[ k ], tmp2, + silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) ); /* Q( -rshift ) */ + } + } + } + + /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ + tmp1 = C_first_row[ n ]; /* Q( -rshifts ) */ + tmp2 = C_last_row[ n ]; /* Q( -rshifts ) */ + num = 0; /* Q( -rshifts ) */ + nrg = silk_ADD32( CAb[ 0 ], CAf[ 0 ] ); /* Q( 1-rshifts ) */ + for( k = 0; k < n; k++ ) { + Atmp_QA = Af_QA[ k ]; + lz = silk_CLZ32( silk_abs( Atmp_QA ) ) - 1; + lz = silk_min( 32 - QA, lz ); + Atmp1 = silk_LSHIFT32( Atmp_QA, lz ); /* Q( QA + lz ) */ + + tmp1 = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( C_last_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ + tmp2 = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ + num = silk_ADD_LSHIFT32( num, silk_SMMUL( CAb[ n - k ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ + nrg = silk_ADD_LSHIFT32( nrg, silk_SMMUL( silk_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ), + Atmp1 ), 32 - QA - lz ); /* Q( 1-rshifts ) */ + } + CAf[ n + 1 ] = tmp1; /* Q( -rshifts ) */ + CAb[ n + 1 ] = tmp2; /* Q( -rshifts ) */ + num = silk_ADD32( num, tmp2 ); /* Q( -rshifts ) */ + num = silk_LSHIFT32( -num, 1 ); /* Q( 1-rshifts ) */ + + /* Calculate the next order reflection (parcor) coefficient */ + if( silk_abs( num ) < nrg ) { + rc_Q31 = silk_DIV32_varQ( num, nrg, 31 ); + } else { + rc_Q31 = ( num > 0 ) ? silk_int32_MAX : silk_int32_MIN; + } + + /* Update inverse prediction gain */ + tmp1 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); + tmp1 = silk_LSHIFT( silk_SMMUL( invGain_Q30, tmp1 ), 2 ); + if( tmp1 <= minInvGain_Q30 ) { + /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */ + tmp2 = ( (opus_int32)1 << 30 ) - silk_DIV32_varQ( minInvGain_Q30, invGain_Q30, 30 ); /* Q30 */ + rc_Q31 = silk_SQRT_APPROX( tmp2 ); /* Q15 */ + /* Newton-Raphson iteration */ + rc_Q31 = silk_RSHIFT32( rc_Q31 + silk_DIV32( tmp2, rc_Q31 ), 1 ); /* Q15 */ + rc_Q31 = silk_LSHIFT32( rc_Q31, 16 ); /* Q31 */ + if( num < 0 ) { + /* Ensure adjusted reflection coefficients has the original sign */ + rc_Q31 = -rc_Q31; + } + invGain_Q30 = minInvGain_Q30; + reached_max_gain = 1; + } else { + invGain_Q30 = tmp1; + } + + /* Update the AR coefficients */ + for( k = 0; k < (n + 1) >> 1; k++ ) { + tmp1 = Af_QA[ k ]; /* QA */ + tmp2 = Af_QA[ n - k - 1 ]; /* QA */ + Af_QA[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* QA */ + Af_QA[ n - k - 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* QA */ + } + Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA ); /* QA */ + + if( reached_max_gain ) { + /* Reached max prediction gain; set remaining coefficients to zero and exit loop */ + for( k = n + 1; k < D; k++ ) { + Af_QA[ k ] = 0; + } + break; + } + + /* Update C * Af and C * Ab */ + for( k = 0; k <= n + 1; k++ ) { + tmp1 = CAf[ k ]; /* Q( -rshifts ) */ + tmp2 = CAb[ n - k + 1 ]; /* Q( -rshifts ) */ + CAf[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* Q( -rshifts ) */ + CAb[ n - k + 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* Q( -rshifts ) */ + } + } + + if( reached_max_gain ) { + for( k = 0; k < D; k++ ) { + /* Scale coefficients */ + A_Q16[ k ] = -silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); + } + /* Subtract energy of preceding samples from C0 */ + if( rshifts > 0 ) { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr, D, arch ), rshifts ); + } + } else { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + C0 -= silk_LSHIFT32( silk_inner_prod_aligned( x_ptr, x_ptr, D, arch), -rshifts); + } + } + /* Approximate residual energy */ + *res_nrg = silk_LSHIFT( silk_SMMUL( invGain_Q30, C0 ), 2 ); + *res_nrg_Q = -rshifts; + } else { + /* Return residual energy */ + nrg = CAf[ 0 ]; /* Q( -rshifts ) */ + tmp1 = (opus_int32)1 << 16; /* Q16 */ + for( k = 0; k < D; k++ ) { + Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); /* Q16 */ + nrg = silk_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); /* Q( -rshifts ) */ + tmp1 = silk_SMLAWW( tmp1, Atmp1, Atmp1 ); /* Q16 */ + A_Q16[ k ] = -Atmp1; + } + *res_nrg = silk_SMLAWW( nrg, silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ), -tmp1 );/* Q( -rshifts ) */ + *res_nrg_Q = -rshifts; + } +} diff --git a/thirdparty/opus/silk/fixed/corrMatrix_FIX.c b/thirdparty/opus/silk/fixed/corrMatrix_FIX.c new file mode 100644 index 0000000000..c1d437c785 --- /dev/null +++ b/thirdparty/opus/silk/fixed/corrMatrix_FIX.c @@ -0,0 +1,158 @@ +/*********************************************************************** +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_FIX.h" + +/* 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 */ +) +{ + opus_int lag, i; + const opus_int16 *ptr1, *ptr2; + opus_int32 inner_prod; + + ptr1 = &x[ order - 1 ]; /* Points to first sample of column 0 of X: X[:,0] */ + ptr2 = t; + /* Calculate X'*t */ + if( rshifts > 0 ) { + /* Right shifting used */ + for( lag = 0; lag < order; lag++ ) { + inner_prod = 0; + for( i = 0; i < L; i++ ) { + inner_prod += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts ); + } + Xt[ lag ] = inner_prod; /* X[:,lag]'*t */ + ptr1--; /* Go to next column of X */ + } + } else { + silk_assert( rshifts == 0 ); + for( lag = 0; lag < order; lag++ ) { + Xt[ lag ] = silk_inner_prod_aligned( ptr1, ptr2, L, arch ); /* X[:,lag]'*t */ + ptr1--; /* Go to next column of X */ + } + } +} + +/* 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 */ + const opus_int head_room, /* I Desired headroom */ + opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */ + opus_int *rshifts, /* I/O Right shifts of correlations */ + int arch /* I Run-time architecture */ +) +{ + opus_int i, j, lag, rshifts_local, head_room_rshifts; + opus_int32 energy; + const opus_int16 *ptr1, *ptr2; + + /* Calculate energy to find shift used to fit in 32 bits */ + silk_sum_sqr_shift( &energy, &rshifts_local, x, L + order - 1 ); + /* Add shifts to get the desired head room */ + head_room_rshifts = silk_max( head_room - silk_CLZ32( energy ), 0 ); + + energy = silk_RSHIFT32( energy, head_room_rshifts ); + rshifts_local += head_room_rshifts; + + /* Calculate energy of first column (0) of X: X[:,0]'*X[:,0] */ + /* Remove contribution of first order - 1 samples */ + for( i = 0; i < order - 1; i++ ) { + energy -= silk_RSHIFT32( silk_SMULBB( x[ i ], x[ i ] ), rshifts_local ); + } + if( rshifts_local < *rshifts ) { + /* Adjust energy */ + energy = silk_RSHIFT32( energy, *rshifts - rshifts_local ); + rshifts_local = *rshifts; + } + + /* Calculate energy of remaining columns of X: X[:,j]'*X[:,j] */ + /* Fill out the diagonal of the correlation matrix */ + matrix_ptr( XX, 0, 0, order ) = energy; + ptr1 = &x[ order - 1 ]; /* First sample of column 0 of X */ + for( j = 1; j < order; j++ ) { + energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), rshifts_local ) ); + energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr1[ -j ] ), rshifts_local ) ); + matrix_ptr( XX, j, j, order ) = energy; + } + + ptr2 = &x[ order - 2 ]; /* First sample of column 1 of X */ + /* Calculate the remaining elements of the correlation matrix */ + if( rshifts_local > 0 ) { + /* Right shifting used */ + for( lag = 1; lag < order; lag++ ) { + /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */ + energy = 0; + for( i = 0; i < L; i++ ) { + energy += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts_local ); + } + /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */ + matrix_ptr( XX, lag, 0, order ) = energy; + matrix_ptr( XX, 0, lag, order ) = energy; + for( j = 1; j < ( order - lag ); j++ ) { + energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), rshifts_local ) ); + energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr2[ -j ] ), rshifts_local ) ); + matrix_ptr( XX, lag + j, j, order ) = energy; + matrix_ptr( XX, j, lag + j, order ) = energy; + } + ptr2--; /* Update pointer to first sample of next column (lag) in X */ + } + } else { + for( lag = 1; lag < order; lag++ ) { + /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */ + energy = silk_inner_prod_aligned( ptr1, ptr2, L, arch ); + matrix_ptr( XX, lag, 0, order ) = energy; + matrix_ptr( XX, 0, lag, order ) = energy; + /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */ + for( j = 1; j < ( order - lag ); j++ ) { + energy = silk_SUB32( energy, silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ) ); + energy = silk_SMLABB( energy, ptr1[ -j ], ptr2[ -j ] ); + matrix_ptr( XX, lag + j, j, order ) = energy; + matrix_ptr( XX, j, lag + j, order ) = energy; + } + ptr2--;/* Update pointer to first sample of next column (lag) in X */ + } + } + *rshifts = rshifts_local; +} + diff --git a/thirdparty/opus/silk/fixed/encode_frame_FIX.c b/thirdparty/opus/silk/fixed/encode_frame_FIX.c new file mode 100644 index 0000000000..5ef44b03fc --- /dev/null +++ b/thirdparty/opus/silk/fixed/encode_frame_FIX.c @@ -0,0 +1,387 @@ +/*********************************************************************** +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_FIX.h" +#include "stack_alloc.h" +#include "tuning_parameters.h" + +/* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate */ +static OPUS_INLINE void silk_LBRR_encode_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ + const opus_int32 xfw_Q3[], /* I Input signal */ + opus_int condCoding /* I The type of conditional coding used so far for this frame */ +); + +void silk_encode_do_VAD_FIX( + silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk FIX encoder state */ +) +{ + /****************************/ + /* Voice Activity Detection */ + /****************************/ + silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch ); + + /**************************************************/ + /* Convert speech activity into VAD and DTX flags */ + /**************************************************/ + if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) { + 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_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 */ +) +{ + silk_encoder_control_FIX sEncCtrl; + opus_int i, iter, maxIter, found_upper, found_lower, ret = 0; + opus_int16 *x_frame; + ec_enc sRangeEnc_copy, sRangeEnc_copy2; + silk_nsq_state sNSQ_copy, sNSQ_copy2; + 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; + SAVE_STACK; + + /* 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 */ + /*************************************************************/ + /* start of frame to encode */ + x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; + + /***************************************/ + /* 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_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length * sizeof( opus_int16 ) ); + + if( !psEnc->sCmn.prefillFlag ) { + VARDECL( opus_int32, xfw_Q3 ); + VARDECL( opus_int16, res_pitch ); + VARDECL( opus_uint8, ec_buf_copy ); + opus_int16 *res_pitch_frame; + + ALLOC( res_pitch, + psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + + psEnc->sCmn.ltp_mem_length, opus_int16 ); + /* start of pitch LPC residual frame */ + res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length; + + /*****************************************/ + /* Find pitch lags, initial LPC analysis */ + /*****************************************/ + silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame, psEnc->sCmn.arch ); + + /************************/ + /* Noise shape analysis */ + /************************/ + silk_noise_shape_analysis_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, psEnc->sCmn.arch ); + + /***************************************************/ + /* Find linear prediction coefficients (LPC + LTP) */ + /***************************************************/ + silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch, x_frame, condCoding ); + + /****************************************/ + /* Process gains */ + /****************************************/ + silk_process_gains_FIX( psEnc, &sEncCtrl, condCoding ); + + /*****************************************/ + /* Prefiltering for noise shaper */ + /*****************************************/ + ALLOC( xfw_Q3, psEnc->sCmn.frame_length, opus_int32 ); + silk_prefilter_FIX( psEnc, &sEncCtrl, xfw_Q3, x_frame ); + + /****************************************/ + /* Low Bitrate Redundant Encoding */ + /****************************************/ + silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw_Q3, condCoding ); + + /* Loop over quantizer and entropy 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, &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, 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 */ + /*****************************************/ + if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { + silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses, + sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, + sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14, + psEnc->sCmn.arch ); + } else { + silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses, + sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, + sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14, + psEnc->sCmn.arch); + } + + /****************************************/ + /* 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( 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 ) ); + silk_assert( sRangeEnc_copy2.offs <= 1275 ); + silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs ); + silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, 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_Q10 = silk_ADD_RSHIFT32( sEncCtrl.Lambda_Q10, sEncCtrl.Lambda_Q10, 1 ); + found_upper = 0; + gainsID_upper = -1; + } else { + found_upper = 1; + nBits_upper = nBits; + gainMult_upper = gainMult_Q8; + gainsID_upper = gainsID; + } + } else if( nBits < maxBits - 5 ) { + 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 ) ); + silk_assert( psRangeEnc->offs <= 1275 ); + silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs ); + silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); + LastGainIndex_copy2 = psEnc->sShape.LastGainIndex; + } + } else { + /* Within 5 bits of budget: close enough */ + break; + } + + if( ( found_lower & found_upper ) == 0 ) { + /* Adjust gain according to high-rate rate/distortion curve */ + opus_int32 gain_factor_Q16; + gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) ); + gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) ); + if( nBits > maxBits ) { + gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) ); + } + gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 ); + } else { + /* Adjust gain by interpolating */ + gainMult_Q8 = gainMult_lower + silk_DIV32_16( silk_MUL( gainMult_upper - gainMult_lower, maxBits - nBits_lower ), nBits_upper - nBits_lower ); + /* New gain multplier 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++ ) { + sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 ); + } + + /* Quantize gains */ + psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev; + silk_gains_quant( psEnc->sCmn.indices.GainsIndices, sEncCtrl.Gains_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 ); + } + } + + /* 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( opus_int16 ) ); + + /* 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_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ + const opus_int32 xfw_Q3[], /* I Input signal */ + opus_int condCoding /* I The type of conditional coding used so far for this frame */ +) +{ + opus_int32 TempGains_Q16[ MAX_NB_SUBFR ]; + SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ]; + silk_nsq_state sNSQ_LBRR; + + /*******************************************/ + /* Control use of inband LBRR */ + /*******************************************/ + if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { + psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1; + + /* Copy noise shaping quantizer state and quantization indices from regular encoding */ + silk_memcpy( &sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); + silk_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) ); + + /* Save original gains */ + silk_memcpy( TempGains_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); + + 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 ] = 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 */ + /* Overwrite unquantized gains with quantized gains */ + silk_gains_dequant( psEncCtrl->Gains_Q16, psIndices_LBRR->GainsIndices, + &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); + + /*****************************************/ + /* Noise shaping quantization */ + /*****************************************/ + if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { + silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3, + psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, + psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, + psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch ); + } else { + silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3, + psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, + psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, + psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch ); + } + + /* Restore original gains */ + silk_memcpy( psEncCtrl->Gains_Q16, TempGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); + } +} diff --git a/thirdparty/opus/silk/fixed/find_LPC_FIX.c b/thirdparty/opus/silk/fixed/find_LPC_FIX.c new file mode 100644 index 0000000000..e11cdc86e6 --- /dev/null +++ b/thirdparty/opus/silk/fixed/find_LPC_FIX.c @@ -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_FIX.h" +#include "stack_alloc.h" +#include "tuning_parameters.h" + +/* Finds LPC vector from correlations, and converts to NLSF */ +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 */ +) +{ + opus_int k, subfr_length; + opus_int32 a_Q16[ MAX_LPC_ORDER ]; + opus_int isInterpLower, shift; + opus_int32 res_nrg0, res_nrg1; + opus_int rshift0, rshift1; + + /* Used only for LSF interpolation */ + opus_int32 a_tmp_Q16[ MAX_LPC_ORDER ], res_nrg_interp, res_nrg, res_tmp_nrg; + opus_int res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q; + opus_int16 a_tmp_Q12[ MAX_LPC_ORDER ]; + opus_int16 NLSF0_Q15[ MAX_LPC_ORDER ]; + SAVE_STACK; + + subfr_length = psEncC->subfr_length + psEncC->predictLPCOrder; + + /* Default: no interpolation */ + psEncC->indices.NLSFInterpCoef_Q2 = 4; + + /* Burg AR analysis for the full frame */ + silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, minInvGain_Q30, subfr_length, psEncC->nb_subfr, psEncC->predictLPCOrder, psEncC->arch ); + + if( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) { + VARDECL( opus_int16, LPC_res ); + + /* Optimal solution for last 10 ms */ + silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + 2 * subfr_length, minInvGain_Q30, subfr_length, 2, psEncC->predictLPCOrder, psEncC->arch ); + + /* 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 */ + shift = res_tmp_nrg_Q - res_nrg_Q; + if( shift >= 0 ) { + if( shift < 32 ) { + res_nrg = res_nrg - silk_RSHIFT( res_tmp_nrg, shift ); + } + } else { + silk_assert( shift > -32 ); + res_nrg = silk_RSHIFT( res_nrg, -shift ) - res_tmp_nrg; + res_nrg_Q = res_tmp_nrg_Q; + } + + /* Convert to NLSFs */ + silk_A2NLSF( NLSF_Q15, a_tmp_Q16, psEncC->predictLPCOrder ); + + ALLOC( LPC_res, 2 * subfr_length, opus_int16 ); + + /* Search over interpolation indices to find the one with lowest residual energy */ + 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( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder ); + + /* Calculate residual energy with NLSF interpolation */ + silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, psEncC->predictLPCOrder, psEncC->arch ); + + silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + psEncC->predictLPCOrder, subfr_length - psEncC->predictLPCOrder ); + silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder ); + + /* Add subframe energies from first half frame */ + shift = rshift0 - rshift1; + if( shift >= 0 ) { + res_nrg1 = silk_RSHIFT( res_nrg1, shift ); + res_nrg_interp_Q = -rshift0; + } else { + res_nrg0 = silk_RSHIFT( res_nrg0, -shift ); + res_nrg_interp_Q = -rshift1; + } + res_nrg_interp = silk_ADD32( res_nrg0, res_nrg1 ); + + /* Compare with first half energy without NLSF interpolation, or best interpolated value so far */ + shift = res_nrg_interp_Q - res_nrg_Q; + if( shift >= 0 ) { + if( silk_RSHIFT( res_nrg_interp, shift ) < res_nrg ) { + isInterpLower = silk_TRUE; + } else { + isInterpLower = silk_FALSE; + } + } else { + if( -shift < 32 ) { + if( res_nrg_interp < silk_RSHIFT( res_nrg, -shift ) ) { + isInterpLower = silk_TRUE; + } else { + isInterpLower = silk_FALSE; + } + } else { + isInterpLower = silk_FALSE; + } + } + + /* Determine whether current interpolated NLSFs are best so far */ + if( isInterpLower == silk_TRUE ) { + /* Interpolation has lower residual energy */ + res_nrg = res_nrg_interp; + res_nrg_Q = res_nrg_interp_Q; + psEncC->indices.NLSFInterpCoef_Q2 = (opus_int8)k; + } + } + } + + if( psEncC->indices.NLSFInterpCoef_Q2 == 4 ) { + /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */ + silk_A2NLSF( NLSF_Q15, a_Q16, psEncC->predictLPCOrder ); + } + + silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) ); + RESTORE_STACK; +} diff --git a/thirdparty/opus/silk/fixed/find_LTP_FIX.c b/thirdparty/opus/silk/fixed/find_LTP_FIX.c new file mode 100644 index 0000000000..1314a28137 --- /dev/null +++ b/thirdparty/opus/silk/fixed/find_LTP_FIX.c @@ -0,0 +1,245 @@ +/*********************************************************************** +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_FIX.h" +#include "tuning_parameters.h" + +/* Head room for correlations */ +#define LTP_CORRS_HEAD_ROOM 2 + +void silk_fit_LTP( + opus_int32 LTP_coefs_Q16[ LTP_ORDER ], + opus_int16 LTP_coefs_Q14[ LTP_ORDER ] +); + +void silk_find_LTP_FIX( + opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ + opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ + opus_int *LTPredCodGain_Q7, /* O LTP coding gain */ + const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */ + const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ + const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */ + const opus_int subfr_length, /* I subframe length */ + const opus_int nb_subfr, /* I number of subframes */ + const opus_int mem_offset, /* I number of samples in LTP memory */ + opus_int corr_rshifts[ MAX_NB_SUBFR ], /* O right shifts applied to correlations */ + int arch /* I Run-time architecture */ +) +{ + opus_int i, k, lshift; + const opus_int16 *r_ptr, *lag_ptr; + opus_int16 *b_Q14_ptr; + + opus_int32 regu; + opus_int32 *WLTP_ptr; + opus_int32 b_Q16[ LTP_ORDER ], delta_b_Q14[ LTP_ORDER ], d_Q14[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], g_Q26; + opus_int32 w[ MAX_NB_SUBFR ], WLTP_max, max_abs_d_Q14, max_w_bits; + + opus_int32 temp32, denom32; + opus_int extra_shifts; + opus_int rr_shifts, maxRshifts, maxRshifts_wxtra, LZs; + opus_int32 LPC_res_nrg, LPC_LTP_res_nrg, div_Q16; + opus_int32 Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ]; + opus_int32 wd, m_Q12; + + b_Q14_ptr = b_Q14; + WLTP_ptr = WLTP; + r_ptr = &r_lpc[ mem_offset ]; + for( k = 0; k < nb_subfr; k++ ) { + lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 ); + + silk_sum_sqr_shift( &rr[ k ], &rr_shifts, r_ptr, subfr_length ); /* rr[ k ] in Q( -rr_shifts ) */ + + /* Assure headroom */ + LZs = silk_CLZ32( rr[k] ); + if( LZs < LTP_CORRS_HEAD_ROOM ) { + rr[ k ] = silk_RSHIFT_ROUND( rr[ k ], LTP_CORRS_HEAD_ROOM - LZs ); + rr_shifts += ( LTP_CORRS_HEAD_ROOM - LZs ); + } + corr_rshifts[ k ] = rr_shifts; + silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, LTP_CORRS_HEAD_ROOM, WLTP_ptr, &corr_rshifts[ k ], arch ); /* WLTP_fix_ptr in Q( -corr_rshifts[ k ] ) */ + + /* The correlation vector always has lower max abs value than rr and/or RR so head room is assured */ + silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr, corr_rshifts[ k ], arch ); /* Rr_fix_ptr in Q( -corr_rshifts[ k ] ) */ + if( corr_rshifts[ k ] > rr_shifts ) { + rr[ k ] = silk_RSHIFT( rr[ k ], corr_rshifts[ k ] - rr_shifts ); /* rr[ k ] in Q( -corr_rshifts[ k ] ) */ + } + silk_assert( rr[ k ] >= 0 ); + + regu = 1; + regu = silk_SMLAWB( regu, rr[ k ], SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); + regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); + regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); + silk_regularize_correlations_FIX( WLTP_ptr, &rr[k], regu, LTP_ORDER ); + + silk_solve_LDL_FIX( WLTP_ptr, LTP_ORDER, Rr, b_Q16 ); /* WLTP_fix_ptr and Rr_fix_ptr both in Q(-corr_rshifts[k]) */ + + /* Limit and store in Q14 */ + silk_fit_LTP( b_Q16, b_Q14_ptr ); + + /* Calculate residual energy */ + nrg[ k ] = silk_residual_energy16_covar_FIX( b_Q14_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER, 14 ); /* nrg_fix in Q( -corr_rshifts[ k ] ) */ + + /* temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); */ + extra_shifts = silk_min_int( corr_rshifts[ k ], LTP_CORRS_HEAD_ROOM ); + denom32 = silk_LSHIFT_SAT32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 + extra_shifts ) + /* Q( -corr_rshifts[ k ] + extra_shifts ) */ + silk_RSHIFT( silk_SMULWB( (opus_int32)subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts ); /* Q( -corr_rshifts[ k ] + extra_shifts ) */ + denom32 = silk_max( denom32, 1 ); + silk_assert( ((opus_int64)Wght_Q15[ k ] << 16 ) < silk_int32_MAX ); /* Wght always < 0.5 in Q0 */ + temp32 = silk_DIV32( silk_LSHIFT( (opus_int32)Wght_Q15[ k ], 16 ), denom32 ); /* Q( 15 + 16 + corr_rshifts[k] - extra_shifts ) */ + temp32 = silk_RSHIFT( temp32, 31 + corr_rshifts[ k ] - extra_shifts - 26 ); /* Q26 */ + + /* Limit temp such that the below scaling never wraps around */ + WLTP_max = 0; + for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) { + WLTP_max = silk_max( WLTP_ptr[ i ], WLTP_max ); + } + lshift = silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */ + silk_assert( 26 - 18 + lshift >= 0 ); + if( 26 - 18 + lshift < 31 ) { + temp32 = silk_min_32( temp32, silk_LSHIFT( (opus_int32)1, 26 - 18 + lshift ) ); + } + + silk_scale_vector32_Q26_lshift_18( WLTP_ptr, temp32, LTP_ORDER * LTP_ORDER ); /* WLTP_ptr in Q( 18 - corr_rshifts[ k ] ) */ + + w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER/2, LTP_ORDER/2, LTP_ORDER ); /* w in Q( 18 - corr_rshifts[ k ] ) */ + silk_assert( w[k] >= 0 ); + + r_ptr += subfr_length; + b_Q14_ptr += LTP_ORDER; + WLTP_ptr += LTP_ORDER * LTP_ORDER; + } + + maxRshifts = 0; + for( k = 0; k < nb_subfr; k++ ) { + maxRshifts = silk_max_int( corr_rshifts[ k ], maxRshifts ); + } + + /* Compute LTP coding gain */ + if( LTPredCodGain_Q7 != NULL ) { + LPC_LTP_res_nrg = 0; + LPC_res_nrg = 0; + silk_assert( LTP_CORRS_HEAD_ROOM >= 2 ); /* Check that no overflow will happen when adding */ + for( k = 0; k < nb_subfr; k++ ) { + LPC_res_nrg = silk_ADD32( LPC_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( rr[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */ + LPC_LTP_res_nrg = silk_ADD32( LPC_LTP_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */ + } + LPC_LTP_res_nrg = silk_max( LPC_LTP_res_nrg, 1 ); /* avoid division by zero */ + + div_Q16 = silk_DIV32_varQ( LPC_res_nrg, LPC_LTP_res_nrg, 16 ); + *LTPredCodGain_Q7 = ( opus_int )silk_SMULBB( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ); + + silk_assert( *LTPredCodGain_Q7 == ( opus_int )silk_SAT16( silk_MUL( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ) ) ); + } + + /* smoothing */ + /* d = sum( B, 1 ); */ + b_Q14_ptr = b_Q14; + for( k = 0; k < nb_subfr; k++ ) { + d_Q14[ k ] = 0; + for( i = 0; i < LTP_ORDER; i++ ) { + d_Q14[ k ] += b_Q14_ptr[ i ]; + } + b_Q14_ptr += LTP_ORDER; + } + + /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */ + + /* Find maximum absolute value of d_Q14 and the bits used by w in Q0 */ + max_abs_d_Q14 = 0; + max_w_bits = 0; + for( k = 0; k < nb_subfr; k++ ) { + max_abs_d_Q14 = silk_max_32( max_abs_d_Q14, silk_abs( d_Q14[ k ] ) ); + /* w[ k ] is in Q( 18 - corr_rshifts[ k ] ) */ + /* Find bits needed in Q( 18 - maxRshifts ) */ + max_w_bits = silk_max_32( max_w_bits, 32 - silk_CLZ32( w[ k ] ) + corr_rshifts[ k ] - maxRshifts ); + } + + /* max_abs_d_Q14 = (5 << 15); worst case, i.e. LTP_ORDER * -silk_int16_MIN */ + silk_assert( max_abs_d_Q14 <= ( 5 << 15 ) ); + + /* How many bits is needed for w*d' in Q( 18 - maxRshifts ) in the worst case, of all d_Q14's being equal to max_abs_d_Q14 */ + extra_shifts = max_w_bits + 32 - silk_CLZ32( max_abs_d_Q14 ) - 14; + + /* Subtract what we got available; bits in output var plus maxRshifts */ + extra_shifts -= ( 32 - 1 - 2 + maxRshifts ); /* Keep sign bit free as well as 2 bits for accumulation */ + extra_shifts = silk_max_int( extra_shifts, 0 ); + + maxRshifts_wxtra = maxRshifts + extra_shifts; + + temp32 = silk_RSHIFT( 262, maxRshifts + extra_shifts ) + 1; /* 1e-3f in Q( 18 - (maxRshifts + extra_shifts) ) */ + wd = 0; + for( k = 0; k < nb_subfr; k++ ) { + /* w has at least 2 bits of headroom so no overflow should happen */ + temp32 = silk_ADD32( temp32, silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ) ); /* Q( 18 - maxRshifts_wxtra ) */ + wd = silk_ADD32( wd, silk_LSHIFT( silk_SMULWW( silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ), d_Q14[ k ] ), 2 ) ); /* Q( 18 - maxRshifts_wxtra ) */ + } + m_Q12 = silk_DIV32_varQ( wd, temp32, 12 ); + + b_Q14_ptr = b_Q14; + for( k = 0; k < nb_subfr; k++ ) { + /* w_fix[ k ] from Q( 18 - corr_rshifts[ k ] ) to Q( 16 ) */ + if( 2 - corr_rshifts[k] > 0 ) { + temp32 = silk_RSHIFT( w[ k ], 2 - corr_rshifts[ k ] ); + } else { + temp32 = silk_LSHIFT_SAT32( w[ k ], corr_rshifts[ k ] - 2 ); + } + + g_Q26 = silk_MUL( + silk_DIV32( + SILK_FIX_CONST( LTP_SMOOTHING, 26 ), + silk_RSHIFT( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), 10 ) + temp32 ), /* Q10 */ + silk_LSHIFT_SAT32( silk_SUB_SAT32( (opus_int32)m_Q12, silk_RSHIFT( d_Q14[ k ], 2 ) ), 4 ) ); /* Q16 */ + + temp32 = 0; + for( i = 0; i < LTP_ORDER; i++ ) { + delta_b_Q14[ i ] = silk_max_16( b_Q14_ptr[ i ], 1638 ); /* 1638_Q14 = 0.1_Q0 */ + temp32 += delta_b_Q14[ i ]; /* Q14 */ + } + temp32 = silk_DIV32( g_Q26, temp32 ); /* Q14 -> Q12 */ + for( i = 0; i < LTP_ORDER; i++ ) { + b_Q14_ptr[ i ] = silk_LIMIT_32( (opus_int32)b_Q14_ptr[ i ] + silk_SMULWB( silk_LSHIFT_SAT32( temp32, 4 ), delta_b_Q14[ i ] ), -16000, 28000 ); + } + b_Q14_ptr += LTP_ORDER; + } +} + +void silk_fit_LTP( + opus_int32 LTP_coefs_Q16[ LTP_ORDER ], + opus_int16 LTP_coefs_Q14[ LTP_ORDER ] +) +{ + opus_int i; + + for( i = 0; i < LTP_ORDER; i++ ) { + LTP_coefs_Q14[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( LTP_coefs_Q16[ i ], 2 ) ); + } +} diff --git a/thirdparty/opus/silk/fixed/find_pitch_lags_FIX.c b/thirdparty/opus/silk/fixed/find_pitch_lags_FIX.c new file mode 100644 index 0000000000..b8440a8247 --- /dev/null +++ b/thirdparty/opus/silk/fixed/find_pitch_lags_FIX.c @@ -0,0 +1,145 @@ +/*********************************************************************** +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_FIX.h" +#include "stack_alloc.h" +#include "tuning_parameters.h" + +/* 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 */ +) +{ + opus_int buf_len, i, scale; + opus_int32 thrhld_Q13, res_nrg; + const opus_int16 *x_buf, *x_buf_ptr; + VARDECL( opus_int16, Wsig ); + opus_int16 *Wsig_ptr; + opus_int32 auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ]; + opus_int16 rc_Q15[ MAX_FIND_PITCH_LPC_ORDER ]; + opus_int32 A_Q24[ MAX_FIND_PITCH_LPC_ORDER ]; + opus_int16 A_Q12[ MAX_FIND_PITCH_LPC_ORDER ]; + SAVE_STACK; + + /******************************************/ + /* 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 */ + silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length ); + + x_buf = x - psEnc->sCmn.ltp_mem_length; + + /*************************************/ + /* Estimate LPC AR coefficients */ + /*************************************/ + + /* Calculate windowed signal */ + + ALLOC( Wsig, psEnc->sCmn.pitch_LPC_win_length, opus_int16 ); + + /* First LA_LTP samples */ + x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length; + Wsig_ptr = Wsig; + silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch ); + + /* Middle un - 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 - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) ); + + /* Last LA_LTP samples */ + Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ); + x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ); + silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch ); + + /* Calculate autocorrelation sequence */ + silk_autocorr( auto_corr, &scale, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1, arch ); + + /* Add white noise, as fraction of energy */ + auto_corr[ 0 ] = silk_SMLAWB( auto_corr[ 0 ], auto_corr[ 0 ], SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ) + 1; + + /* Calculate the reflection coefficients using schur */ + res_nrg = silk_schur( rc_Q15, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder ); + + /* Prediction gain */ + psEncCtrl->predGain_Q16 = silk_DIV32_varQ( auto_corr[ 0 ], silk_max_int( res_nrg, 1 ), 16 ); + + /* Convert reflection coefficients to prediction coefficients */ + silk_k2a( A_Q24, rc_Q15, psEnc->sCmn.pitchEstimationLPCOrder ); + + /* Convert From 32 bit Q24 to 16 bit Q12 coefs */ + for( i = 0; i < psEnc->sCmn.pitchEstimationLPCOrder; i++ ) { + A_Q12[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT( A_Q24[ i ], 12 ) ); + } + + /* Do BWE */ + silk_bwexpander( A_Q12, psEnc->sCmn.pitchEstimationLPCOrder, SILK_FIX_CONST( FIND_PITCH_BANDWIDTH_EXPANSION, 16 ) ); + + /*****************************************/ + /* LPC analysis filtering */ + /*****************************************/ + silk_LPC_analysis_filter( res, x_buf, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder, psEnc->sCmn.arch ); + + if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) { + /* Threshold for pitch estimator */ + thrhld_Q13 = SILK_FIX_CONST( 0.6, 13 ); + thrhld_Q13 = silk_SMLABB( thrhld_Q13, SILK_FIX_CONST( -0.004, 13 ), psEnc->sCmn.pitchEstimationLPCOrder ); + thrhld_Q13 = silk_SMLAWB( thrhld_Q13, SILK_FIX_CONST( -0.1, 21 ), psEnc->sCmn.speech_activity_Q8 ); + thrhld_Q13 = silk_SMLABB( thrhld_Q13, SILK_FIX_CONST( -0.15, 13 ), silk_RSHIFT( psEnc->sCmn.prevSignalType, 1 ) ); + thrhld_Q13 = silk_SMLAWB( thrhld_Q13, SILK_FIX_CONST( -0.1, 14 ), psEnc->sCmn.input_tilt_Q15 ); + thrhld_Q13 = silk_SAT16( thrhld_Q13 ); + + /*****************************************/ + /* Call pitch estimator */ + /*****************************************/ + if( silk_pitch_analysis_core( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex, &psEnc->sCmn.indices.contourIndex, + &psEnc->LTPCorr_Q15, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16, + (opus_int)thrhld_Q13, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr, + psEnc->sCmn.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_Q15 = 0; + } + RESTORE_STACK; +} diff --git a/thirdparty/opus/silk/fixed/find_pred_coefs_FIX.c b/thirdparty/opus/silk/fixed/find_pred_coefs_FIX.c new file mode 100644 index 0000000000..d308e9cf5f --- /dev/null +++ b/thirdparty/opus/silk/fixed/find_pred_coefs_FIX.c @@ -0,0 +1,148 @@ +/*********************************************************************** +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_FIX.h" +#include "stack_alloc.h" + +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 */ +) +{ + opus_int i; + opus_int32 invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ], Wght_Q15[ MAX_NB_SUBFR ]; + opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; + const opus_int16 *x_ptr; + opus_int16 *x_pre_ptr; + VARDECL( opus_int16, LPC_in_pre ); + opus_int32 tmp, min_gain_Q16, minInvGain_Q30; + opus_int LTP_corrs_rshift[ MAX_NB_SUBFR ]; + SAVE_STACK; + + /* weighting for weighted least squares */ + min_gain_Q16 = silk_int32_MAX >> 6; + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + min_gain_Q16 = silk_min( min_gain_Q16, psEncCtrl->Gains_Q16[ i ] ); + } + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + /* Divide to Q16 */ + silk_assert( psEncCtrl->Gains_Q16[ i ] > 0 ); + /* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */ + invGains_Q16[ i ] = silk_DIV32_varQ( min_gain_Q16, psEncCtrl->Gains_Q16[ i ], 16 - 2 ); + + /* Ensure Wght_Q15 a minimum value 1 */ + invGains_Q16[ i ] = silk_max( invGains_Q16[ i ], 363 ); + + /* Square the inverted gains */ + silk_assert( invGains_Q16[ i ] == silk_SAT16( invGains_Q16[ i ] ) ); + tmp = silk_SMULWB( invGains_Q16[ i ], invGains_Q16[ i ] ); + Wght_Q15[ i ] = silk_RSHIFT( tmp, 1 ); + + /* Invert the inverted and normalized gains */ + local_gains[ i ] = silk_DIV32( ( (opus_int32)1 << 16 ), invGains_Q16[ i ] ); + } + + ALLOC( LPC_in_pre, + psEnc->sCmn.nb_subfr * psEnc->sCmn.predictLPCOrder + + psEnc->sCmn.frame_length, opus_int16 ); + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + VARDECL( opus_int32, WLTP ); + + /**********/ + /* VOICED */ + /**********/ + silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 ); + + ALLOC( WLTP, psEnc->sCmn.nb_subfr * LTP_ORDER * LTP_ORDER, opus_int32 ); + + /* LTP analysis */ + silk_find_LTP_FIX( psEncCtrl->LTPCoef_Q14, WLTP, &psEncCtrl->LTPredCodGain_Q7, + res_pitch, psEncCtrl->pitchL, Wght_Q15, psEnc->sCmn.subfr_length, + psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length, LTP_corrs_rshift, psEnc->sCmn.arch ); + + /* Quantize LTP gain parameters */ + silk_quant_LTP_gains( psEncCtrl->LTPCoef_Q14, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex, + &psEnc->sCmn.sum_log_gain_Q7, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr, + psEnc->sCmn.arch); + + /* Control LTP scaling */ + silk_LTP_scale_ctrl_FIX( psEnc, psEncCtrl, condCoding ); + + /* Create LTP residual */ + silk_LTP_analysis_filter_FIX( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef_Q14, + psEncCtrl->pitchL, invGains_Q16, 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_vector16( x_pre_ptr, x_ptr, invGains_Q16[ 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_Q14, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( opus_int16 ) ); + psEncCtrl->LTPredCodGain_Q7 = 0; + psEnc->sCmn.sum_log_gain_Q7 = 0; + } + + /* Limit on total predictive coding gain */ + if( psEnc->sCmn.first_frame_after_reset ) { + minInvGain_Q30 = SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN_AFTER_RESET, 30 ); + } else { + minInvGain_Q30 = silk_log2lin( silk_SMLAWB( 16 << 7, (opus_int32)psEncCtrl->LTPredCodGain_Q7, SILK_FIX_CONST( 1.0 / 3, 16 ) ) ); /* Q16 */ + minInvGain_Q30 = silk_DIV32_varQ( minInvGain_Q30, + silk_SMULWW( SILK_FIX_CONST( MAX_PREDICTION_POWER_GAIN, 0 ), + silk_SMLAWB( SILK_FIX_CONST( 0.25, 18 ), SILK_FIX_CONST( 0.75, 18 ), psEncCtrl->coding_quality_Q14 ) ), 14 ); + } + + /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */ + silk_find_LPC_FIX( &psEnc->sCmn, NLSF_Q15, LPC_in_pre, minInvGain_Q30 ); + + /* Quantize LSFs */ + silk_process_NLSFs( &psEnc->sCmn, psEncCtrl->PredCoef_Q12, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 ); + + /* Calculate residual energy using quantized LPC coefficients */ + silk_residual_energy_FIX( psEncCtrl->ResNrg, psEncCtrl->ResNrgQ, LPC_in_pre, psEncCtrl->PredCoef_Q12, local_gains, + psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder, psEnc->sCmn.arch ); + + /* 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 ) ); + RESTORE_STACK; +} diff --git a/thirdparty/opus/silk/fixed/k2a_FIX.c b/thirdparty/opus/silk/fixed/k2a_FIX.c new file mode 100644 index 0000000000..5fee599bcb --- /dev/null +++ b/thirdparty/opus/silk/fixed/k2a_FIX.c @@ -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 "SigProc_FIX.h" + +/* 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 */ +) +{ + opus_int k, n; + opus_int32 Atmp[ SILK_MAX_ORDER_LPC ]; + + for( k = 0; k < order; k++ ) { + for( n = 0; n < k; n++ ) { + Atmp[ n ] = A_Q24[ n ]; + } + for( n = 0; n < k; n++ ) { + A_Q24[ n ] = silk_SMLAWB( A_Q24[ n ], silk_LSHIFT( Atmp[ k - n - 1 ], 1 ), rc_Q15[ k ] ); + } + A_Q24[ k ] = -silk_LSHIFT( (opus_int32)rc_Q15[ k ], 9 ); + } +} diff --git a/thirdparty/opus/silk/fixed/k2a_Q16_FIX.c b/thirdparty/opus/silk/fixed/k2a_Q16_FIX.c new file mode 100644 index 0000000000..3b03987544 --- /dev/null +++ b/thirdparty/opus/silk/fixed/k2a_Q16_FIX.c @@ -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 "SigProc_FIX.h" + +/* 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 */ +) +{ + opus_int k, n; + opus_int32 Atmp[ SILK_MAX_ORDER_LPC ]; + + for( k = 0; k < order; k++ ) { + for( n = 0; n < k; n++ ) { + Atmp[ n ] = A_Q24[ n ]; + } + for( n = 0; n < k; n++ ) { + A_Q24[ n ] = silk_SMLAWW( A_Q24[ n ], Atmp[ k - n - 1 ], rc_Q16[ k ] ); + } + A_Q24[ k ] = -silk_LSHIFT( rc_Q16[ k ], 8 ); + } +} diff --git a/thirdparty/opus/silk/fixed/main_FIX.h b/thirdparty/opus/silk/fixed/main_FIX.h new file mode 100644 index 0000000000..375b5eb32e --- /dev/null +++ b/thirdparty/opus/silk/fixed/main_FIX.h @@ -0,0 +1,272 @@ +/*********************************************************************** +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" + +#ifndef FORCE_CPP_BUILD +#ifdef __cplusplus +extern "C" +{ +#endif +#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 + +/*********************/ +/* 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 */ +); + +/* 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_int32 TargetRate_bps, /* I Target max bitrate (bps) */ + 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 +); + +/****************/ +/* Prefiltering */ +/****************/ +void silk_prefilter_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ + const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */ + opus_int32 xw_Q10[], /* O Weighted signal */ + const opus_int16 x[] /* I Speech signal */ +); + +void silk_warped_LPC_analysis_filter_FIX_c( + opus_int32 state[], /* I/O State [order + 1] */ + opus_int32 res_Q2[], /* O Residual signal [length] */ + const opus_int16 coef_Q13[], /* I Coefficients [order] */ + const opus_int16 input[], /* I Input signal [length] */ + const opus_int16 lambda_Q16, /* I Warping factor */ + const opus_int length, /* I Length of input signal */ + const opus_int order /* I Filter order (even) */ +); + + +/**************************/ +/* 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( + 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) */ +); + +/* 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_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ + opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ + opus_int *LTPredCodGain_Q7, /* O LTP coding gain */ + const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */ + const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ + const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */ + const opus_int subfr_length, /* I subframe length */ + const opus_int nb_subfr, /* I number of subframes */ + const opus_int mem_offset, /* I number of samples in LTP memory */ + opus_int corr_rshifts[ MAX_NB_SUBFR ], /* O right shifts applied to correlations */ + 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 */ + const opus_int head_room, /* I Desired headroom */ + opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */ + opus_int *rshifts, /* I/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 */ +); + +/* Add noise to matrix diagonal */ +void silk_regularize_correlations_FIX( + opus_int32 *XX, /* I/O Correlation matrices */ + opus_int32 *xx, /* I/O Correlation values */ + opus_int32 noise, /* I Noise to add */ + opus_int D /* I Dimension of XX */ +); + +/* Solves Ax = b, assuming A is symmetric */ +void silk_solve_LDL_FIX( + opus_int32 *A, /* I Pointer to symetric square matrix A */ + opus_int M, /* I Size of matrix */ + const opus_int32 *b, /* I Pointer to b vector */ + opus_int32 *x_Q16 /* O Pointer to x solution vector */ +); + +#ifndef FORCE_CPP_BUILD +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* FORCE_CPP_BUILD */ +#endif /* SILK_MAIN_FIX_H */ diff --git a/drivers/opus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h b/thirdparty/opus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h index c30481e437..c30481e437 100644 --- a/drivers/opus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h +++ b/thirdparty/opus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h diff --git a/thirdparty/opus/silk/fixed/mips/prefilter_FIX_mipsr1.h b/thirdparty/opus/silk/fixed/mips/prefilter_FIX_mipsr1.h new file mode 100644 index 0000000000..21b256885f --- /dev/null +++ b/thirdparty/opus/silk/fixed/mips/prefilter_FIX_mipsr1.h @@ -0,0 +1,184 @@ +/*********************************************************************** +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 __PREFILTER_FIX_MIPSR1_H__ +#define __PREFILTER_FIX_MIPSR1_H__ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" +#include "stack_alloc.h" +#include "tuning_parameters.h" + +#define OVERRIDE_silk_warped_LPC_analysis_filter_FIX +void silk_warped_LPC_analysis_filter_FIX( + opus_int32 state[], /* I/O State [order + 1] */ + opus_int32 res_Q2[], /* O Residual signal [length] */ + const opus_int16 coef_Q13[], /* I Coefficients [order] */ + const opus_int16 input[], /* I Input signal [length] */ + const opus_int16 lambda_Q16, /* I Warping factor */ + const opus_int length, /* I Length of input signal */ + const opus_int order, /* I Filter order (even) */ + int arch +) +{ + opus_int n, i; + opus_int32 acc_Q11, acc_Q22, tmp1, tmp2, tmp3, tmp4; + opus_int32 state_cur, state_next; + + (void)arch; + + /* Order must be even */ + /* Length must be even */ + + silk_assert( ( order & 1 ) == 0 ); + silk_assert( ( length & 1 ) == 0 ); + + for( n = 0; n < length; n+=2 ) { + /* Output of lowpass section */ + tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 ); + state_cur = silk_LSHIFT( input[ n ], 14 ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 ); + state_next = tmp2; + acc_Q11 = silk_RSHIFT( order, 1 ); + acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] ); + + + /* Output of lowpass section */ + tmp4 = silk_SMLAWB( state_cur, state_next, lambda_Q16 ); + state[ 0 ] = silk_LSHIFT( input[ n+1 ], 14 ); + /* Output of allpass section */ + tmp3 = silk_SMLAWB( state_next, tmp1 - tmp4, lambda_Q16 ); + state[ 1 ] = tmp4; + acc_Q22 = silk_RSHIFT( order, 1 ); + acc_Q22 = silk_SMLAWB( acc_Q22, tmp4, coef_Q13[ 0 ] ); + + /* Loop over allpass sections */ + for( i = 2; i < order; i += 2 ) { + /* Output of allpass section */ + tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 ); + state_cur = tmp1; + acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 ); + state_next = tmp2; + acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] ); + + + /* Output of allpass section */ + tmp4 = silk_SMLAWB( state_cur, state_next - tmp3, lambda_Q16 ); + state[ i ] = tmp3; + acc_Q22 = silk_SMLAWB( acc_Q22, tmp3, coef_Q13[ i - 1 ] ); + /* Output of allpass section */ + tmp3 = silk_SMLAWB( state_next, tmp1 - tmp4, lambda_Q16 ); + state[ i + 1 ] = tmp4; + acc_Q22 = silk_SMLAWB( acc_Q22, tmp4, coef_Q13[ i ] ); + } + acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); + res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 ); + + state[ order ] = tmp3; + acc_Q22 = silk_SMLAWB( acc_Q22, tmp3, coef_Q13[ order - 1 ] ); + res_Q2[ n+1 ] = silk_LSHIFT( (opus_int32)input[ n+1 ], 2 ) - silk_RSHIFT_ROUND( acc_Q22, 9 ); + } +} + + + +/* Prefilter for finding Quantizer input signal */ +#define OVERRIDE_silk_prefilt_FIX +static inline void silk_prefilt_FIX( + silk_prefilter_state_FIX *P, /* I/O state */ + opus_int32 st_res_Q12[], /* I short term residual signal */ + opus_int32 xw_Q3[], /* O prefiltered signal */ + opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ + opus_int Tilt_Q14, /* I Tilt shaping coeficient */ + opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */ + opus_int lag, /* I Lag for harmonic shaping */ + opus_int length /* I Length of signals */ +) +{ + opus_int i, idx, LTP_shp_buf_idx; + opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10; + opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12; + opus_int16 *LTP_shp_buf; + + /* To speed up use temp variables instead of using the struct */ + LTP_shp_buf = P->sLTP_shp; + LTP_shp_buf_idx = P->sLTP_shp_buf_idx; + sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12; + sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12; + + if( lag > 0 ) { + for( i = 0; i < length; i++ ) { + /* unrolled loop */ + silk_assert( HARM_SHAPE_FIR_TAPS == 3 ); + idx = lag + LTP_shp_buf_idx; + n_LTP_Q12 = silk_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); + n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); + n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); + + n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 ); + n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 ); + + sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) ); + sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) ); + + LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; + LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); + + xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 ); + } + } + else + { + for( i = 0; i < length; i++ ) { + + n_LTP_Q12 = 0; + + n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 ); + n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 ); + + sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) ); + sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) ); + + LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; + LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); + + xw_Q3[i] = silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 9 ); + } + } + + /* Copy temp variable back to state */ + P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12; + P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12; + P->sLTP_shp_buf_idx = LTP_shp_buf_idx; +} + +#endif /* __PREFILTER_FIX_MIPSR1_H__ */ diff --git a/thirdparty/opus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h b/thirdparty/opus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h new file mode 100644 index 0000000000..e803ef0fce --- /dev/null +++ b/thirdparty/opus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h @@ -0,0 +1,165 @@ +/*********************************************************************** +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" + +#undef QC +#define QC 10 + +#undef QS +#define QS 14 + +/* Autocorrelations for a warped frequency axis */ +#define OVERRIDE_silk_warped_autocorrelation_FIX +void silk_warped_autocorrelation_FIX( + 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 ] = __builtin_mips_madd( corr_QC[ i ], tmp1_QS, start_1); + + tmp4_QS = silk_SMLAWB( tmp1_QS, tmp2_QS - tmp3_QS, warping_Q16 ); + corr_QC[ i ] = __builtin_mips_madd( corr_QC[ i ], tmp3_QS, start_2); + + tmp6_QS = silk_SMLAWB( tmp3_QS, tmp4_QS - tmp5_QS, warping_Q16 ); + corr_QC[ i ] = __builtin_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 ] = __builtin_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 ] = __builtin_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 ] = __builtin_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 ] = __builtin_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 ] = __builtin_mips_madd( corr_QC[ i+1 ], tmp8_QS, state_QS[ 0 ]); + + } + state_QS[ order ] = tmp7_QS; + + corr_QC[ order ] = __builtin_mips_madd( corr_QC[ order ], tmp1_QS, start_1); + corr_QC[ order ] = __builtin_mips_madd( corr_QC[ order ], tmp3_QS, start_2); + corr_QC[ order ] = __builtin_mips_madd( corr_QC[ order ], tmp5_QS, start_3); + corr_QC[ order ] = __builtin_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 ] = __builtin_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 ] = __builtin_mips_madd( corr_QC[ i+1 ], tmp2_QS, state_QS[ 0 ]); + } + state_QS[ order ] = tmp1_QS; + corr_QC[ order ] = __builtin_mips_madd( corr_QC[ order ], tmp1_QS, state_QS[ 0 ]); + } + + temp64 = corr_QC[ 0 ]; + temp64 = __builtin_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 = __builtin_mips_shilo(temp64, val); + temp64 = (val >= 0) ? (temp64 >> val) : (temp64 << -val); + corr[ i ] = (opus_int32)silk_CHECK_FIT32( __builtin_mips_shilo( temp64, -lsh ) ); + } + } else { + for( i = 0; i < order + 1; i++ ) { + temp64 = corr_QC[ i ]; + //temp64 = __builtin_mips_shilo(temp64, val); + temp64 = (val >= 0) ? (temp64 >> val) : (temp64 << -val); + corr[ i ] = (opus_int32)silk_CHECK_FIT32( __builtin_mips_shilo( temp64, -lsh ) ); + } + } + + corr_QC[ 0 ] = __builtin_mips_shilo(corr_QC[ 0 ], val); + + silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/ +} +#endif /* __WARPED_AUTOCORRELATION_FIX_MIPSR1_H__ */ diff --git a/thirdparty/opus/silk/fixed/noise_shape_analysis_FIX.c b/thirdparty/opus/silk/fixed/noise_shape_analysis_FIX.c new file mode 100644 index 0000000000..22a89f75ae --- /dev/null +++ b/thirdparty/opus/silk/fixed/noise_shape_analysis_FIX.c @@ -0,0 +1,451 @@ +/*********************************************************************** +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_FIX.h" +#include "stack_alloc.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 opus_int32 warped_gain( /* gain in Q16*/ + const opus_int32 *coefs_Q24, + opus_int lambda_Q16, + opus_int order +) { + opus_int i; + opus_int32 gain_Q24; + + lambda_Q16 = -lambda_Q16; + gain_Q24 = coefs_Q24[ order - 1 ]; + for( i = order - 2; i >= 0; i-- ) { + gain_Q24 = silk_SMLAWB( coefs_Q24[ i ], gain_Q24, lambda_Q16 ); + } + gain_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), gain_Q24, -lambda_Q16 ); + return silk_INVERSE32_varQ( gain_Q24, 40 ); +} + +/* 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 limit_warped_coefs( + opus_int32 *coefs_syn_Q24, + opus_int32 *coefs_ana_Q24, + opus_int lambda_Q16, + opus_int32 limit_Q24, + opus_int order +) { + opus_int i, iter, ind = 0; + opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_syn_Q16, gain_ana_Q16; + opus_int32 nom_Q16, den_Q24; + + /* Convert to monic coefficients */ + lambda_Q16 = -lambda_Q16; + for( i = order - 1; i > 0; i-- ) { + coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); + coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); + } + lambda_Q16 = -lambda_Q16; + nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 ); + den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); + gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); + den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); + gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); + for( i = 0; i < order; i++ ) { + coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); + coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); + } + + for( iter = 0; iter < 10; iter++ ) { + /* Find maximum absolute value */ + maxabs_Q24 = -1; + for( i = 0; i < order; i++ ) { + tmp = silk_max( silk_abs_int32( coefs_syn_Q24[ i ] ), silk_abs_int32( coefs_ana_Q24[ i ] ) ); + if( tmp > maxabs_Q24 ) { + maxabs_Q24 = tmp; + ind = i; + } + } + if( maxabs_Q24 <= limit_Q24 ) { + /* Coefficients are within range - done */ + return; + } + + /* Convert back to true warped coefficients */ + for( i = 1; i < order; i++ ) { + coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); + coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); + } + gain_syn_Q16 = silk_INVERSE32_varQ( gain_syn_Q16, 32 ); + gain_ana_Q16 = silk_INVERSE32_varQ( gain_ana_Q16, 32 ); + for( i = 0; i < order; i++ ) { + coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); + coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); + } + + /* Apply bandwidth expansion */ + chirp_Q16 = SILK_FIX_CONST( 0.99, 16 ) - silk_DIV32_varQ( + silk_SMULWB( maxabs_Q24 - limit_Q24, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ), + silk_MUL( maxabs_Q24, ind + 1 ), 22 ); + silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 ); + silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 ); + + /* Convert to monic warped coefficients */ + lambda_Q16 = -lambda_Q16; + for( i = order - 1; i > 0; i-- ) { + coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); + coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); + } + lambda_Q16 = -lambda_Q16; + nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 ); + den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); + gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); + den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); + gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); + for( i = 0; i < order; i++ ) { + coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); + coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); + } + } + silk_assert( 0 ); +} + +#if defined(MIPSr1_ASM) +#include "mips/noise_shape_analysis_FIX_mipsr1.h" +#endif + +/**************************************************************/ +/* Compute noise shaping coefficients and initial gain values */ +/**************************************************************/ +#ifndef OVERRIDE_silk_noise_shape_analysis_FIX +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 */ +) +{ + silk_shape_state_FIX *psShapeSt = &psEnc->sShape; + opus_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0; + opus_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32; + opus_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7; + opus_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8; + opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; + opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ]; + opus_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ]; + opus_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ]; + VARDECL( opus_int16, x_windowed ); + const opus_int16 *x_ptr, *pitch_res_ptr; + SAVE_STACK; + + /* Point to start of first LPC analysis block */ + x_ptr = x - psEnc->sCmn.la_shape; + + /****************/ + /* GAIN CONTROL */ + /****************/ + SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7; + + /* Input quality is the average of the quality in the lowest two VAD bands */ + psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( (opus_int32)psEnc->sCmn.input_quality_bands_Q15[ 0 ] + + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 ); + + /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ + psEncCtrl->coding_quality_Q14 = silk_RSHIFT( silk_sigm_Q15( silk_RSHIFT_ROUND( SNR_adj_dB_Q7 - + SILK_FIX_CONST( 20.0, 7 ), 4 ) ), 1 ); + + /* Reduce coding SNR during low speech activity */ + if( psEnc->sCmn.useCBR == 0 ) { + b_Q8 = SILK_FIX_CONST( 1.0, 8 ) - psEnc->sCmn.speech_activity_Q8; + b_Q8 = silk_SMULWB( silk_LSHIFT( b_Q8, 8 ), b_Q8 ); + SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, + silk_SMULBB( SILK_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), /* Q11*/ + silk_SMULWB( SILK_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); /* Q12*/ + } + + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /* Reduce gains for periodic signals */ + SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( HARM_SNR_INCR_dB, 8 ), psEnc->LTPCorr_Q15 ); + } else { + /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */ + SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, + silk_SMLAWB( SILK_FIX_CONST( 6.0, 9 ), -SILK_FIX_CONST( 0.4, 18 ), psEnc->sCmn.SNR_dB_Q7 ), + SILK_FIX_CONST( 1.0, 14 ) - psEncCtrl->input_quality_Q14 ); + } + + /*************************/ + /* 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; + psEncCtrl->sparseness_Q8 = 0; + } else { + /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */ + nSamples = silk_LSHIFT( psEnc->sCmn.fs_kHz, 1 ); + energy_variation_Q7 = 0; + log_energy_prev_Q7 = 0; + pitch_res_ptr = pitch_res; + for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) { + silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples ); + nrg += silk_RSHIFT( nSamples, scale ); /* Q(-scale)*/ + + log_energy_Q7 = silk_lin2log( nrg ); + if( k > 0 ) { + energy_variation_Q7 += silk_abs( log_energy_Q7 - log_energy_prev_Q7 ); + } + log_energy_prev_Q7 = log_energy_Q7; + pitch_res_ptr += nSamples; + } + + psEncCtrl->sparseness_Q8 = silk_RSHIFT( silk_sigm_Q15( silk_SMULWB( energy_variation_Q7 - + SILK_FIX_CONST( 5.0, 7 ), SILK_FIX_CONST( 0.1, 16 ) ) ), 7 ); + + /* Set quantization offset depending on sparseness measure */ + if( psEncCtrl->sparseness_Q8 > SILK_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) { + psEnc->sCmn.indices.quantOffsetType = 0; + } else { + psEnc->sCmn.indices.quantOffsetType = 1; + } + + /* Increase coding SNR for sparse signals */ + SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( SPARSE_SNR_INCR_dB, 15 ), psEncCtrl->sparseness_Q8 - SILK_FIX_CONST( 0.5, 8 ) ); + } + + /*******************************/ + /* Control bandwidth expansion */ + /*******************************/ + /* More BWE for signals with high prediction gain */ + strength_Q16 = silk_SMULWB( psEncCtrl->predGain_Q16, SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ); + BWExp1_Q16 = BWExp2_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ), + silk_SMLAWW( SILK_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 ); + delta_Q16 = silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - silk_SMULBB( 3, psEncCtrl->coding_quality_Q14 ), + SILK_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) ); + BWExp1_Q16 = silk_SUB32( BWExp1_Q16, delta_Q16 ); + BWExp2_Q16 = silk_ADD32( BWExp2_Q16, delta_Q16 ); + /* BWExp1 will be applied after BWExp2, so make it relative */ + BWExp1_Q16 = silk_DIV32_16( silk_LSHIFT( BWExp1_Q16, 14 ), silk_RSHIFT( BWExp2_Q16, 2 ) ); + + if( psEnc->sCmn.warping_Q16 > 0 ) { + /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */ + warping_Q16 = silk_SMLAWB( psEnc->sCmn.warping_Q16, (opus_int32)psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( 0.01, 18 ) ); + } else { + warping_Q16 = 0; + } + + /********************************************/ + /* Compute noise shaping AR coefs and gains */ + /********************************************/ + ALLOC( x_windowed, psEnc->sCmn.shapeWinLength, opus_int16 ); + 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 = silk_RSHIFT( psEnc->sCmn.shapeWinLength - flat_part, 1 ); + + silk_apply_sine_window( x_windowed, x_ptr, 1, slope_part ); + shift = slope_part; + silk_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(opus_int16) ); + shift += flat_part; + silk_apply_sine_window( 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_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder ); + } else { + /* Calculate regular auto correlation */ + silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch ); + } + + /* Add white noise, as a fraction of energy */ + auto_corr[0] = silk_ADD32( auto_corr[0], silk_max_32( silk_SMULWB( silk_RSHIFT( auto_corr[ 0 ], 4 ), + SILK_FIX_CONST( SHAPE_WHITE_NOISE_FRACTION, 20 ) ), 1 ) ); + + /* Calculate the reflection coefficients using schur */ + nrg = silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder ); + silk_assert( nrg >= 0 ); + + /* Convert reflection coefficients to prediction coefficients */ + silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder ); + + Qnrg = -scale; /* range: -12...30*/ + silk_assert( Qnrg >= -12 ); + silk_assert( Qnrg <= 30 ); + + /* Make sure that Qnrg is an even number */ + if( Qnrg & 1 ) { + Qnrg -= 1; + nrg >>= 1; + } + + tmp32 = silk_SQRT_APPROX( nrg ); + Qnrg >>= 1; /* range: -6...15*/ + + psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( tmp32, 16 - Qnrg ); + + if( psEnc->sCmn.warping_Q16 > 0 ) { + /* Adjust gain for warping */ + gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder ); + silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); + if ( silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 ) >= ( silk_int32_MAX >> 1 ) ) { + psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX; + } else { + psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); + } + } + + /* Bandwidth expansion for synthesis filter shaping */ + silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 ); + + /* Compute noise shaping filter coefficients */ + silk_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( opus_int32 ) ); + + /* Bandwidth expansion for analysis filter shaping */ + silk_assert( BWExp1_Q16 <= SILK_FIX_CONST( 1.0, 16 ) ); + silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 ); + + /* Ratio of prediction gains, in energy domain */ + pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder ); + nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder ); + + /*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/ + pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 ); + psEncCtrl->GainsPre_Q14[ k ] = ( opus_int ) SILK_FIX_CONST( 0.3, 14 ) + silk_DIV32_varQ( pre_nrg_Q30, nrg, 14 ); + + /* Convert to monic warped prediction coefficients and limit absolute values */ + limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder ); + + /* Convert from Q24 to Q13 and store in int16 */ + for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) { + psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) ); + psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) ); + } + } + + /*****************/ + /* Gain tweaking */ + /*****************/ + /* Increase gains during low speech activity and put lower limit on gains */ + gain_mult_Q16 = silk_log2lin( -silk_SMLAWB( -SILK_FIX_CONST( 16.0, 7 ), SNR_adj_dB_Q7, SILK_FIX_CONST( 0.16, 16 ) ) ); + gain_add_Q16 = silk_log2lin( silk_SMLAWB( SILK_FIX_CONST( 16.0, 7 ), SILK_FIX_CONST( MIN_QGAIN_DB, 7 ), SILK_FIX_CONST( 0.16, 16 ) ) ); + silk_assert( gain_mult_Q16 > 0 ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); + silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); + psEncCtrl->Gains_Q16[ k ] = silk_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 ); + } + + gain_mult_Q16 = SILK_FIX_CONST( 1.0, 16 ) + silk_RSHIFT_ROUND( silk_MLA( SILK_FIX_CONST( INPUT_TILT, 26 ), + psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ), 10 ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->GainsPre_Q14[ k ] = silk_SMULWB( gain_mult_Q16, psEncCtrl->GainsPre_Q14[ k ] ); + } + + /************************************************/ + /* Control low-frequency shaping and noise tilt */ + /************************************************/ + /* Less low frequency shaping for noisy inputs */ + strength_Q16 = silk_MUL( SILK_FIX_CONST( LOW_FREQ_SHAPING, 4 ), silk_SMLAWB( SILK_FIX_CONST( 1.0, 12 ), + SILK_FIX_CONST( LOW_QUALITY_LOW_FREQ_SHAPING_DECR, 13 ), psEnc->sCmn.input_quality_bands_Q15[ 0 ] - SILK_FIX_CONST( 1.0, 15 ) ) ); + strength_Q16 = silk_RSHIFT( silk_MUL( strength_Q16, psEnc->sCmn.speech_activity_Q8 ), 8 ); + 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])*/ + opus_int fs_kHz_inv = silk_DIV32_16( SILK_FIX_CONST( 0.2, 14 ), psEnc->sCmn.fs_kHz ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + b_Q14 = fs_kHz_inv + silk_DIV32_16( SILK_FIX_CONST( 3.0, 14 ), psEncCtrl->pitchL[ k ] ); + /* Pack two coefficients in one int32 */ + psEncCtrl->LF_shp_Q14[ k ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - silk_SMULWB( strength_Q16, b_Q14 ), 16 ); + psEncCtrl->LF_shp_Q14[ k ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); + } + silk_assert( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ) < SILK_FIX_CONST( 0.5, 24 ) ); /* Guarantees that second argument to SMULWB() is within range of an opus_int16*/ + Tilt_Q16 = - SILK_FIX_CONST( HP_NOISE_COEF, 16 ) - + silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - SILK_FIX_CONST( HP_NOISE_COEF, 16 ), + silk_SMULWB( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ), psEnc->sCmn.speech_activity_Q8 ) ); + } else { + b_Q14 = silk_DIV32_16( 21299, psEnc->sCmn.fs_kHz ); /* 1.3_Q0 = 21299_Q14*/ + /* Pack two coefficients in one int32 */ + psEncCtrl->LF_shp_Q14[ 0 ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - + silk_SMULWB( strength_Q16, silk_SMULWB( SILK_FIX_CONST( 0.6, 16 ), b_Q14 ) ), 16 ); + psEncCtrl->LF_shp_Q14[ 0 ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); + for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->LF_shp_Q14[ k ] = psEncCtrl->LF_shp_Q14[ 0 ]; + } + Tilt_Q16 = -SILK_FIX_CONST( HP_NOISE_COEF, 16 ); + } + + /****************************/ + /* HARMONIC SHAPING CONTROL */ + /****************************/ + /* Control boosting of harmonic frequencies */ + HarmBoost_Q16 = silk_SMULWB( silk_SMULWB( SILK_FIX_CONST( 1.0, 17 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 3 ), + psEnc->LTPCorr_Q15 ), SILK_FIX_CONST( LOW_RATE_HARMONIC_BOOST, 16 ) ); + + /* More harmonic boost for noisy input signals */ + HarmBoost_Q16 = silk_SMLAWB( HarmBoost_Q16, + SILK_FIX_CONST( 1.0, 16 ) - silk_LSHIFT( psEncCtrl->input_quality_Q14, 2 ), SILK_FIX_CONST( LOW_INPUT_QUALITY_HARMONIC_BOOST, 16 ) ); + + if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /* More harmonic noise shaping for high bitrates or noisy input */ + HarmShapeGain_Q16 = silk_SMLAWB( SILK_FIX_CONST( HARMONIC_SHAPING, 16 ), + SILK_FIX_CONST( 1.0, 16 ) - silk_SMULWB( SILK_FIX_CONST( 1.0, 18 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 4 ), + psEncCtrl->input_quality_Q14 ), SILK_FIX_CONST( HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING, 16 ) ); + + /* Less harmonic noise shaping for less periodic signals */ + HarmShapeGain_Q16 = silk_SMULWB( silk_LSHIFT( HarmShapeGain_Q16, 1 ), + silk_SQRT_APPROX( silk_LSHIFT( psEnc->LTPCorr_Q15, 15 ) ) ); + } else { + HarmShapeGain_Q16 = 0; + } + + /*************************/ + /* Smooth over subframes */ + /*************************/ + for( k = 0; k < MAX_NB_SUBFR; k++ ) { + psShapeSt->HarmBoost_smth_Q16 = + silk_SMLAWB( psShapeSt->HarmBoost_smth_Q16, HarmBoost_Q16 - psShapeSt->HarmBoost_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); + psShapeSt->HarmShapeGain_smth_Q16 = + silk_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); + psShapeSt->Tilt_smth_Q16 = + silk_SMLAWB( psShapeSt->Tilt_smth_Q16, Tilt_Q16 - psShapeSt->Tilt_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); + + psEncCtrl->HarmBoost_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmBoost_smth_Q16, 2 ); + psEncCtrl->HarmShapeGain_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 ); + psEncCtrl->Tilt_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16, 2 ); + } + RESTORE_STACK; +} +#endif /* OVERRIDE_silk_noise_shape_analysis_FIX */ diff --git a/thirdparty/opus/silk/fixed/pitch_analysis_core_FIX.c b/thirdparty/opus/silk/fixed/pitch_analysis_core_FIX.c new file mode 100644 index 0000000000..01bb9fc0a8 --- /dev/null +++ b/thirdparty/opus/silk/fixed/pitch_analysis_core_FIX.c @@ -0,0 +1,746 @@ +/*********************************************************************** +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" +#include "stack_alloc.h" +#include "debug.h" +#include "pitch.h" + +#define SCRATCH_SIZE 22 +#define SF_LENGTH_4KHZ ( PE_SUBFR_LENGTH_MS * 4 ) +#define SF_LENGTH_8KHZ ( PE_SUBFR_LENGTH_MS * 8 ) +#define MIN_LAG_4KHZ ( PE_MIN_LAG_MS * 4 ) +#define MIN_LAG_8KHZ ( PE_MIN_LAG_MS * 8 ) +#define MAX_LAG_4KHZ ( PE_MAX_LAG_MS * 4 ) +#define MAX_LAG_8KHZ ( PE_MAX_LAG_MS * 8 - 1 ) +#define CSTRIDE_4KHZ ( MAX_LAG_4KHZ + 1 - MIN_LAG_4KHZ ) +#define CSTRIDE_8KHZ ( MAX_LAG_8KHZ + 3 - ( MIN_LAG_8KHZ - 2 ) ) +#define D_COMP_MIN ( MIN_LAG_8KHZ - 3 ) +#define D_COMP_MAX ( MAX_LAG_8KHZ + 4 ) +#define D_COMP_STRIDE ( D_COMP_MAX - D_COMP_MIN ) + +typedef opus_int32 silk_pe_stage3_vals[ PE_NB_STAGE3_LAGS ]; + +/************************************************************/ +/* Internally used functions */ +/************************************************************/ +static void silk_P_Ana_calc_corr_st3( + silk_pe_stage3_vals cross_corr_st3[], /* O 3 DIM correlation array */ + const opus_int16 frame[], /* I vector to correlate */ + opus_int start_lag, /* I lag offset to search around */ + opus_int sf_length, /* I length of a 5 ms subframe */ + 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_pe_stage3_vals energies_st3[], /* O 3 DIM energy array */ + const opus_int16 frame[], /* I vector to calc energy in */ + opus_int start_lag, /* I lag offset to search around */ + opus_int sf_length, /* I length of one 5 ms subframe */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity, /* I Complexity setting */ + int arch /* I Run-time architecture */ +); + +/*************************************************************/ +/* FIXED POINT CORE PITCH ANALYSIS FUNCTION */ +/*************************************************************/ +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 */ +) +{ + VARDECL( opus_int16, frame_8kHz ); + VARDECL( opus_int16, frame_4kHz ); + opus_int32 filt_state[ 6 ]; + const opus_int16 *input_frame_ptr; + opus_int i, k, d, j; + VARDECL( opus_int16, C ); + VARDECL( opus_int32, xcorr32 ); + const opus_int16 *target_ptr, *basis_ptr; + opus_int32 cross_corr, normalizer, energy, shift, energy_basis, energy_target; + opus_int d_srch[ PE_D_SRCH_LENGTH ], Cmax, length_d_srch, length_d_comp; + VARDECL( opus_int16, d_comp ); + opus_int32 sum, threshold, lag_counter; + opus_int CBimax, CBimax_new, CBimax_old, lag, start_lag, end_lag, lag_new; + opus_int32 CC[ PE_NB_CBKS_STAGE2_EXT ], CCmax, CCmax_b, CCmax_new_b, CCmax_new; + VARDECL( silk_pe_stage3_vals, energies_st3 ); + VARDECL( silk_pe_stage3_vals, cross_corr_st3 ); + opus_int frame_length, frame_length_8kHz, frame_length_4kHz; + opus_int sf_length; + opus_int min_lag; + opus_int max_lag; + opus_int32 contour_bias_Q15, diff; + opus_int nb_cbk_search, cbk_size; + opus_int32 delta_lag_log2_sqr_Q7, lag_log2_Q7, prevLag_log2_Q7, prev_lag_bias_Q13; + const opus_int8 *Lag_CB_ptr; + SAVE_STACK; + /* Check for valid sampling frequency */ + silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 ); + + /* Check for valid complexity setting */ + silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); + silk_assert( complexity <= SILK_PE_MAX_COMPLEX ); + + silk_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) ); + silk_assert( search_thres2_Q13 >= 0 && search_thres2_Q13 <= (1<<13) ); + + /* 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; + min_lag = PE_MIN_LAG_MS * Fs_kHz; + max_lag = PE_MAX_LAG_MS * Fs_kHz - 1; + + /* Resample from input sampled at Fs_kHz to 8 kHz */ + ALLOC( frame_8kHz, frame_length_8kHz, opus_int16 ); + if( Fs_kHz == 16 ) { + silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) ); + silk_resampler_down2( filt_state, frame_8kHz, frame, frame_length ); + } else if( Fs_kHz == 12 ) { + silk_memset( filt_state, 0, 6 * sizeof( opus_int32 ) ); + silk_resampler_down2_3( filt_state, frame_8kHz, frame, frame_length ); + } else { + silk_assert( Fs_kHz == 8 ); + silk_memcpy( frame_8kHz, frame, frame_length_8kHz * sizeof(opus_int16) ); + } + + /* Decimate again to 4 kHz */ + silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );/* Set state to zero */ + ALLOC( frame_4kHz, frame_length_4kHz, opus_int16 ); + silk_resampler_down2( filt_state, frame_4kHz, frame_8kHz, frame_length_8kHz ); + + /* 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 ] ); + } + + /******************************************************************************* + ** Scale 4 kHz signal down to prevent correlations measures from overflowing + ** find scaling as max scaling for each 8kHz(?) subframe + *******************************************************************************/ + + /* Inner product is calculated with different lengths, so scale for the worst case */ + silk_sum_sqr_shift( &energy, &shift, frame_4kHz, frame_length_4kHz ); + if( shift > 0 ) { + shift = silk_RSHIFT( shift, 1 ); + for( i = 0; i < frame_length_4kHz; i++ ) { + frame_4kHz[ i ] = silk_RSHIFT( frame_4kHz[ i ], shift ); + } + } + + /****************************************************************************** + * FIRST STAGE, operating in 4 khz + ******************************************************************************/ + ALLOC( C, nb_subfr * CSTRIDE_8KHZ, opus_int16 ); + ALLOC( xcorr32, MAX_LAG_4KHZ-MIN_LAG_4KHZ+1, opus_int32 ); + silk_memset( C, 0, (nb_subfr >> 1) * CSTRIDE_4KHZ * sizeof( opus_int16 ) ); + 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 */ + silk_assert( target_ptr >= frame_4kHz ); + silk_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 */ + silk_assert( basis_ptr >= frame_4kHz ); + silk_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz ); + + celt_pitch_xcorr( target_ptr, target_ptr - MAX_LAG_4KHZ, xcorr32, SF_LENGTH_8KHZ, MAX_LAG_4KHZ - MIN_LAG_4KHZ + 1, arch ); + + /* Calculate first vector products before loop */ + cross_corr = xcorr32[ MAX_LAG_4KHZ - MIN_LAG_4KHZ ]; + normalizer = silk_inner_prod_aligned( target_ptr, target_ptr, SF_LENGTH_8KHZ, arch ); + normalizer = silk_ADD32( normalizer, silk_inner_prod_aligned( basis_ptr, basis_ptr, SF_LENGTH_8KHZ, arch ) ); + normalizer = silk_ADD32( normalizer, silk_SMULBB( SF_LENGTH_8KHZ, 4000 ) ); + + matrix_ptr( C, k, 0, CSTRIDE_4KHZ ) = + (opus_int16)silk_DIV32_varQ( cross_corr, normalizer, 13 + 1 ); /* Q13 */ + + /* 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 = xcorr32[ MAX_LAG_4KHZ - d ]; + + /* Add contribution of new sample and remove contribution from oldest sample */ + normalizer = silk_ADD32( normalizer, + silk_SMULBB( basis_ptr[ 0 ], basis_ptr[ 0 ] ) - + silk_SMULBB( basis_ptr[ SF_LENGTH_8KHZ ], basis_ptr[ SF_LENGTH_8KHZ ] ) ); + + matrix_ptr( C, k, d - MIN_LAG_4KHZ, CSTRIDE_4KHZ) = + (opus_int16)silk_DIV32_varQ( cross_corr, normalizer, 13 + 1 ); /* Q13 */ + } + /* Update target pointer */ + target_ptr += SF_LENGTH_8KHZ; + } + + /* Combine two subframes into single correlation measure and apply short-lag bias */ + if( nb_subfr == PE_MAX_NB_SUBFR ) { + for( i = MAX_LAG_4KHZ; i >= MIN_LAG_4KHZ; i-- ) { + sum = (opus_int32)matrix_ptr( C, 0, i - MIN_LAG_4KHZ, CSTRIDE_4KHZ ) + + (opus_int32)matrix_ptr( C, 1, i - MIN_LAG_4KHZ, CSTRIDE_4KHZ ); /* Q14 */ + sum = silk_SMLAWB( sum, sum, silk_LSHIFT( -i, 4 ) ); /* Q14 */ + C[ i - MIN_LAG_4KHZ ] = (opus_int16)sum; /* Q14 */ + } + } else { + /* Only short-lag bias */ + for( i = MAX_LAG_4KHZ; i >= MIN_LAG_4KHZ; i-- ) { + sum = silk_LSHIFT( (opus_int32)C[ i - MIN_LAG_4KHZ ], 1 ); /* Q14 */ + sum = silk_SMLAWB( sum, sum, silk_LSHIFT( -i, 4 ) ); /* Q14 */ + C[ i - MIN_LAG_4KHZ ] = (opus_int16)sum; /* Q14 */ + } + } + + /* Sort */ + length_d_srch = silk_ADD_LSHIFT32( 4, complexity, 1 ); + silk_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH ); + silk_insertion_sort_decreasing_int16( C, d_srch, CSTRIDE_4KHZ, + length_d_srch ); + + /* Escape if correlation is very low already here */ + Cmax = (opus_int)C[ 0 ]; /* Q14 */ + if( Cmax < SILK_FIX_CONST( 0.2, 14 ) ) { + silk_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) ); + *LTPCorr_Q15 = 0; + *lagIndex = 0; + *contourIndex = 0; + RESTORE_STACK; + return 1; + } + + threshold = silk_SMULWB( search_thres1_Q16, Cmax ); + for( i = 0; i < length_d_srch; i++ ) { + /* Convert to 8 kHz indices for the sorted correlation that exceeds the threshold */ + if( C[ i ] > threshold ) { + d_srch[ i ] = silk_LSHIFT( d_srch[ i ] + MIN_LAG_4KHZ, 1 ); + } else { + length_d_srch = i; + break; + } + } + silk_assert( length_d_srch > 0 ); + + ALLOC( d_comp, D_COMP_STRIDE, opus_int16 ); + for( i = D_COMP_MIN; i < D_COMP_MAX; i++ ) { + d_comp[ i - D_COMP_MIN ] = 0; + } + for( i = 0; i < length_d_srch; i++ ) { + d_comp[ d_srch[ i ] - D_COMP_MIN ] = 1; + } + + /* Convolution */ + for( i = D_COMP_MAX - 1; i >= MIN_LAG_8KHZ; i-- ) { + d_comp[ i - D_COMP_MIN ] += + d_comp[ i - 1 - D_COMP_MIN ] + d_comp[ i - 2 - D_COMP_MIN ]; + } + + length_d_srch = 0; + for( i = MIN_LAG_8KHZ; i < MAX_LAG_8KHZ + 1; i++ ) { + if( d_comp[ i + 1 - D_COMP_MIN ] > 0 ) { + d_srch[ length_d_srch ] = i; + length_d_srch++; + } + } + + /* Convolution */ + for( i = D_COMP_MAX - 1; i >= MIN_LAG_8KHZ; i-- ) { + d_comp[ i - D_COMP_MIN ] += d_comp[ i - 1 - D_COMP_MIN ] + + d_comp[ i - 2 - D_COMP_MIN ] + d_comp[ i - 3 - D_COMP_MIN ]; + } + + length_d_comp = 0; + for( i = MIN_LAG_8KHZ; i < D_COMP_MAX; i++ ) { + if( d_comp[ i - D_COMP_MIN ] > 0 ) { + d_comp[ length_d_comp ] = i - 2; + length_d_comp++; + } + } + + /********************************************************************************** + ** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation + *************************************************************************************/ + + /****************************************************************************** + ** Scale signal down to avoid correlations measures from overflowing + *******************************************************************************/ + /* find scaling as max scaling for each subframe */ + silk_sum_sqr_shift( &energy, &shift, frame_8kHz, frame_length_8kHz ); + if( shift > 0 ) { + shift = silk_RSHIFT( shift, 1 ); + for( i = 0; i < frame_length_8kHz; i++ ) { + frame_8kHz[ i ] = silk_RSHIFT( frame_8kHz[ i ], shift ); + } + } + + /********************************************************************************* + * Find energy of each subframe projected onto its history, for a range of delays + *********************************************************************************/ + silk_memset( C, 0, nb_subfr * CSTRIDE_8KHZ * sizeof( opus_int16 ) ); + + target_ptr = &frame_8kHz[ PE_LTP_MEM_LENGTH_MS * 8 ]; + for( k = 0; k < nb_subfr; k++ ) { + + /* Check that we are within range of the array */ + silk_assert( target_ptr >= frame_8kHz ); + silk_assert( target_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz ); + + energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, SF_LENGTH_8KHZ, arch ), 1 ); + for( j = 0; j < length_d_comp; j++ ) { + d = d_comp[ j ]; + basis_ptr = target_ptr - d; + + /* Check that we are within range of the array */ + silk_assert( basis_ptr >= frame_8kHz ); + silk_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz ); + + cross_corr = silk_inner_prod_aligned( target_ptr, basis_ptr, SF_LENGTH_8KHZ, arch ); + if( cross_corr > 0 ) { + energy_basis = silk_inner_prod_aligned( basis_ptr, basis_ptr, SF_LENGTH_8KHZ, arch ); + matrix_ptr( C, k, d - ( MIN_LAG_8KHZ - 2 ), CSTRIDE_8KHZ ) = + (opus_int16)silk_DIV32_varQ( cross_corr, + silk_ADD32( energy_target, + energy_basis ), + 13 + 1 ); /* Q13 */ + } else { + matrix_ptr( C, k, d - ( MIN_LAG_8KHZ - 2 ), CSTRIDE_8KHZ ) = 0; + } + } + target_ptr += SF_LENGTH_8KHZ; + } + + /* search over lag range and lags codebook */ + /* scale factor for lag codebook, as a function of center lag */ + + CCmax = silk_int32_MIN; + CCmax_b = silk_int32_MIN; + + 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_DIV32_16( silk_LSHIFT( prevLag, 1 ), 3 ); + } else if( Fs_kHz == 16 ) { + prevLag = silk_RSHIFT( prevLag, 1 ); + } + prevLag_log2_Q7 = silk_lin2log( (opus_int32)prevLag ); + } else { + prevLag_log2_Q7 = 0; + } + silk_assert( search_thres2_Q13 == silk_SAT16( search_thres2_Q13 ) ); + /* 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; + for( i = 0; i < nb_subfr; i++ ) { + opus_int d_subfr; + /* Try all codebooks */ + d_subfr = d + matrix_ptr( Lag_CB_ptr, i, j, cbk_size ); + CC[ j ] = CC[ j ] + + (opus_int32)matrix_ptr( C, i, + d_subfr - ( MIN_LAG_8KHZ - 2 ), + CSTRIDE_8KHZ ); + } + } + /* Find best codebook */ + CCmax_new = silk_int32_MIN; + 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_Q7 = silk_lin2log( d ); /* Q7 */ + silk_assert( lag_log2_Q7 == silk_SAT16( lag_log2_Q7 ) ); + silk_assert( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 13 ) == silk_SAT16( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 13 ) ) ); + CCmax_new_b = CCmax_new - silk_RSHIFT( silk_SMULBB( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 13 ), lag_log2_Q7 ), 7 ); /* Q13 */ + + /* Bias towards previous lag */ + silk_assert( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 13 ) == silk_SAT16( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 13 ) ) ); + if( prevLag > 0 ) { + delta_lag_log2_sqr_Q7 = lag_log2_Q7 - prevLag_log2_Q7; + silk_assert( delta_lag_log2_sqr_Q7 == silk_SAT16( delta_lag_log2_sqr_Q7 ) ); + delta_lag_log2_sqr_Q7 = silk_RSHIFT( silk_SMULBB( delta_lag_log2_sqr_Q7, delta_lag_log2_sqr_Q7 ), 7 ); + prev_lag_bias_Q13 = silk_RSHIFT( silk_SMULBB( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 13 ), *LTPCorr_Q15 ), 15 ); /* Q13 */ + prev_lag_bias_Q13 = silk_DIV32( silk_MUL( prev_lag_bias_Q13, delta_lag_log2_sqr_Q7 ), delta_lag_log2_sqr_Q7 + SILK_FIX_CONST( 0.5, 7 ) ); + CCmax_new_b -= prev_lag_bias_Q13; /* Q13 */ + } + + if( CCmax_new_b > CCmax_b && /* Find maximum biased correlation */ + CCmax_new > silk_SMULBB( nb_subfr, search_thres2_Q13 ) && /* Correlation needs to be high enough to be voiced */ + silk_CB_lags_stage2[ 0 ][ CBimax_new ] <= MIN_LAG_8KHZ /* Lag must be in range */ + ) { + 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, nb_subfr * sizeof( opus_int ) ); + *LTPCorr_Q15 = 0; + *lagIndex = 0; + *contourIndex = 0; + RESTORE_STACK; + return 1; + } + + /* Output normalized correlation */ + *LTPCorr_Q15 = (opus_int)silk_LSHIFT( silk_DIV32_16( CCmax, nb_subfr ), 2 ); + silk_assert( *LTPCorr_Q15 >= 0 ); + + if( Fs_kHz > 8 ) { + VARDECL( opus_int16, scratch_mem ); + /***************************************************************************/ + /* Scale input signal down to avoid correlations measures from overflowing */ + /***************************************************************************/ + /* find scaling as max scaling for each subframe */ + silk_sum_sqr_shift( &energy, &shift, frame, frame_length ); + ALLOC( scratch_mem, shift > 0 ? frame_length : ALLOC_NONE, opus_int16 ); + if( shift > 0 ) { + /* Move signal to scratch mem because the input signal should be unchanged */ + shift = silk_RSHIFT( shift, 1 ); + for( i = 0; i < frame_length; i++ ) { + scratch_mem[ i ] = silk_RSHIFT( frame[ i ], shift ); + } + input_frame_ptr = scratch_mem; + } else { + input_frame_ptr = frame; + } + + /* Search in original signal */ + + CBimax_old = CBimax; + /* Compensate for decimation */ + silk_assert( lag == silk_SAT16( lag ) ); + if( Fs_kHz == 12 ) { + lag = silk_RSHIFT( silk_SMULBB( lag, 3 ), 1 ); + } else if( Fs_kHz == 16 ) { + lag = silk_LSHIFT( lag, 1 ); + } else { + lag = silk_SMULBB( lag, 3 ); + } + + 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 = silk_int32_MIN; + /* pitch lags according to second stage */ + for( k = 0; k < nb_subfr; k++ ) { + pitch_out[ k ] = lag + 2 * silk_CB_lags_stage2[ k ][ CBimax_old ]; + } + + /* Set up codebook 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 ]; + } + + /* Calculate the correlations and energies needed in stage 3 */ + ALLOC( energies_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals ); + ALLOC( cross_corr_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals ); + silk_P_Ana_calc_corr_st3( cross_corr_st3, input_frame_ptr, start_lag, sf_length, nb_subfr, complexity, arch ); + silk_P_Ana_calc_energy_st3( energies_st3, input_frame_ptr, start_lag, sf_length, nb_subfr, complexity, arch ); + + lag_counter = 0; + silk_assert( lag == silk_SAT16( lag ) ); + contour_bias_Q15 = silk_DIV32_16( SILK_FIX_CONST( PE_FLATCONTOUR_BIAS, 15 ), lag ); + + target_ptr = &input_frame_ptr[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ]; + energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, nb_subfr * sf_length, arch ), 1 ); + for( d = start_lag; d <= end_lag; d++ ) { + for( j = 0; j < nb_cbk_search; j++ ) { + cross_corr = 0; + energy = energy_target; + for( k = 0; k < nb_subfr; k++ ) { + cross_corr = silk_ADD32( cross_corr, + matrix_ptr( cross_corr_st3, k, j, + nb_cbk_search )[ lag_counter ] ); + energy = silk_ADD32( energy, + matrix_ptr( energies_st3, k, j, + nb_cbk_search )[ lag_counter ] ); + silk_assert( energy >= 0 ); + } + if( cross_corr > 0 ) { + CCmax_new = silk_DIV32_varQ( cross_corr, energy, 13 + 1 ); /* Q13 */ + /* Reduce depending on flatness of contour */ + diff = silk_int16_MAX - silk_MUL( contour_bias_Q15, j ); /* Q15 */ + silk_assert( diff == silk_SAT16( diff ) ); + CCmax_new = silk_SMULWB( CCmax_new, diff ); /* Q14 */ + } else { + CCmax_new = 0; + } + + if( CCmax_new > CCmax && ( d + 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; + } + silk_assert( *lagIndex >= 0 ); + /* return as voiced */ + RESTORE_STACK; + 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_pe_stage3_vals cross_corr_st3[], /* O 3 DIM correlation array */ + const opus_int16 frame[], /* I vector to correlate */ + opus_int start_lag, /* I lag offset to search around */ + opus_int sf_length, /* I length of a 5 ms subframe */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity, /* I Complexity setting */ + int arch /* I Run-time architecture */ +) +{ + const opus_int16 *target_ptr; + opus_int i, j, k, lag_counter, lag_low, lag_high; + opus_int nb_cbk_search, delta, idx, cbk_size; + VARDECL( opus_int32, scratch_mem ); + VARDECL( opus_int32, xcorr32 ); + const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; + SAVE_STACK; + + silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); + silk_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 { + silk_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; + } + ALLOC( scratch_mem, SCRATCH_SIZE, opus_int32 ); + ALLOC( xcorr32, SCRATCH_SIZE, opus_int32 ); + + 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, xcorr32, 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 ] = xcorr32[ 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 ); + matrix_ptr( cross_corr_st3, k, i, nb_cbk_search )[ j ] = + scratch_mem[ idx + j ]; + } + } + target_ptr += sf_length; + } + RESTORE_STACK; +} + +/********************************************************************/ +/* Calculate the energies for first two subframes. The energies are */ +/* calculated recursively. */ +/********************************************************************/ +static void silk_P_Ana_calc_energy_st3( + silk_pe_stage3_vals energies_st3[], /* O 3 DIM energy array */ + const opus_int16 frame[], /* I vector to calc energy in */ + opus_int start_lag, /* I lag offset to search around */ + opus_int sf_length, /* I length of one 5 ms subframe */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity, /* I Complexity setting */ + int arch /* I Run-time architecture */ +) +{ + const opus_int16 *target_ptr, *basis_ptr; + opus_int32 energy; + opus_int k, i, j, lag_counter; + opus_int nb_cbk_search, delta, idx, cbk_size, lag_diff; + VARDECL( opus_int32, scratch_mem ); + const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; + SAVE_STACK; + + silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); + silk_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 { + silk_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; + } + ALLOC( scratch_mem, SCRATCH_SIZE, opus_int32 ); + + 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_inner_prod_aligned( basis_ptr, basis_ptr, sf_length, arch ); + silk_assert( energy >= 0 ); + scratch_mem[ lag_counter ] = 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 -= silk_SMULBB( basis_ptr[ sf_length - i ], basis_ptr[ sf_length - i ] ); + silk_assert( energy >= 0 ); + + /* add part that comes into window */ + energy = silk_ADD_SAT32( energy, silk_SMULBB( basis_ptr[ -i ], basis_ptr[ -i ] ) ); + silk_assert( energy >= 0 ); + silk_assert( lag_counter < SCRATCH_SIZE ); + scratch_mem[ lag_counter ] = 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 ); + matrix_ptr( energies_st3, k, i, nb_cbk_search )[ j ] = + scratch_mem[ idx + j ]; + silk_assert( + matrix_ptr( energies_st3, k, i, nb_cbk_search )[ j ] >= 0 ); + } + } + target_ptr += sf_length; + } + RESTORE_STACK; +} diff --git a/thirdparty/opus/silk/fixed/prefilter_FIX.c b/thirdparty/opus/silk/fixed/prefilter_FIX.c new file mode 100644 index 0000000000..6a8e35152e --- /dev/null +++ b/thirdparty/opus/silk/fixed/prefilter_FIX.c @@ -0,0 +1,221 @@ +/*********************************************************************** +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_FIX.h" +#include "stack_alloc.h" +#include "tuning_parameters.h" + +#if defined(MIPSr1_ASM) +#include "mips/prefilter_FIX_mipsr1.h" +#endif + + +#if !defined(OVERRIDE_silk_warped_LPC_analysis_filter_FIX) +#define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \ + ((void)(arch),silk_warped_LPC_analysis_filter_FIX_c(state, res_Q2, coef_Q13, input, lambda_Q16, length, order)) +#endif + +/* Prefilter for finding Quantizer input signal */ +static OPUS_INLINE void silk_prefilt_FIX( + silk_prefilter_state_FIX *P, /* I/O state */ + opus_int32 st_res_Q12[], /* I short term residual signal */ + opus_int32 xw_Q3[], /* O prefiltered signal */ + opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ + opus_int Tilt_Q14, /* I Tilt shaping coeficient */ + opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */ + opus_int lag, /* I Lag for harmonic shaping */ + opus_int length /* I Length of signals */ +); + +void silk_warped_LPC_analysis_filter_FIX_c( + opus_int32 state[], /* I/O State [order + 1] */ + opus_int32 res_Q2[], /* O Residual signal [length] */ + const opus_int16 coef_Q13[], /* I Coefficients [order] */ + const opus_int16 input[], /* I Input signal [length] */ + const opus_int16 lambda_Q16, /* I Warping factor */ + const opus_int length, /* I Length of input signal */ + const opus_int order /* I Filter order (even) */ +) +{ + opus_int n, i; + opus_int32 acc_Q11, tmp1, tmp2; + + /* Order must be even */ + silk_assert( ( order & 1 ) == 0 ); + + for( n = 0; n < length; n++ ) { + /* Output of lowpass section */ + tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 ); + state[ 0 ] = silk_LSHIFT( input[ n ], 14 ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 ); + state[ 1 ] = tmp2; + acc_Q11 = silk_RSHIFT( order, 1 ); + acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] ); + /* Loop over allpass sections */ + for( i = 2; i < order; i += 2 ) { + /* Output of allpass section */ + tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 ); + state[ i ] = tmp1; + acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 ); + state[ i + 1 ] = tmp2; + acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] ); + } + state[ order ] = tmp1; + acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); + res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 ); + } +} + +void silk_prefilter_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ + const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */ + opus_int32 xw_Q3[], /* O Weighted signal */ + const opus_int16 x[] /* I Speech signal */ +) +{ + silk_prefilter_state_FIX *P = &psEnc->sPrefilt; + opus_int j, k, lag; + opus_int32 tmp_32; + const opus_int16 *AR1_shp_Q13; + const opus_int16 *px; + opus_int32 *pxw_Q3; + opus_int HarmShapeGain_Q12, Tilt_Q14; + opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14; + VARDECL( opus_int32, x_filt_Q12 ); + VARDECL( opus_int32, st_res_Q2 ); + opus_int16 B_Q10[ 2 ]; + SAVE_STACK; + + /* Set up pointers */ + px = x; + pxw_Q3 = xw_Q3; + lag = P->lagPrev; + ALLOC( x_filt_Q12, psEnc->sCmn.subfr_length, opus_int32 ); + ALLOC( st_res_Q2, psEnc->sCmn.subfr_length, opus_int32 ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + /* Update Variables that change per sub frame */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + lag = psEncCtrl->pitchL[ k ]; + } + + /* Noise shape parameters */ + HarmShapeGain_Q12 = silk_SMULWB( (opus_int32)psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] ); + silk_assert( HarmShapeGain_Q12 >= 0 ); + HarmShapeFIRPacked_Q12 = silk_RSHIFT( HarmShapeGain_Q12, 2 ); + HarmShapeFIRPacked_Q12 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q12, 1 ), 16 ); + Tilt_Q14 = psEncCtrl->Tilt_Q14[ k ]; + LF_shp_Q14 = psEncCtrl->LF_shp_Q14[ k ]; + AR1_shp_Q13 = &psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER ]; + + /* Short term FIR filtering*/ + silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res_Q2, AR1_shp_Q13, px, + psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder, psEnc->sCmn.arch ); + + /* Reduce (mainly) low frequencies during harmonic emphasis */ + B_Q10[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 4 ); + tmp_32 = silk_SMLABB( SILK_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */ + tmp_32 = silk_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */ + tmp_32 = silk_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */ + tmp_32 = silk_RSHIFT_ROUND( tmp_32, 14 ); /* Q10 */ + B_Q10[ 1 ]= silk_SAT16( tmp_32 ); + x_filt_Q12[ 0 ] = silk_MLA( silk_MUL( st_res_Q2[ 0 ], B_Q10[ 0 ] ), P->sHarmHP_Q2, B_Q10[ 1 ] ); + for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { + x_filt_Q12[ j ] = silk_MLA( silk_MUL( st_res_Q2[ j ], B_Q10[ 0 ] ), st_res_Q2[ j - 1 ], B_Q10[ 1 ] ); + } + P->sHarmHP_Q2 = st_res_Q2[ psEnc->sCmn.subfr_length - 1 ]; + + silk_prefilt_FIX( P, x_filt_Q12, pxw_Q3, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length ); + + px += psEnc->sCmn.subfr_length; + pxw_Q3 += psEnc->sCmn.subfr_length; + } + + P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ]; + RESTORE_STACK; +} + +#ifndef OVERRIDE_silk_prefilt_FIX +/* Prefilter for finding Quantizer input signal */ +static OPUS_INLINE void silk_prefilt_FIX( + silk_prefilter_state_FIX *P, /* I/O state */ + opus_int32 st_res_Q12[], /* I short term residual signal */ + opus_int32 xw_Q3[], /* O prefiltered signal */ + opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ + opus_int Tilt_Q14, /* I Tilt shaping coeficient */ + opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */ + opus_int lag, /* I Lag for harmonic shaping */ + opus_int length /* I Length of signals */ +) +{ + opus_int i, idx, LTP_shp_buf_idx; + opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10; + opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12; + opus_int16 *LTP_shp_buf; + + /* To speed up use temp variables instead of using the struct */ + LTP_shp_buf = P->sLTP_shp; + LTP_shp_buf_idx = P->sLTP_shp_buf_idx; + sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12; + sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12; + + for( i = 0; i < length; i++ ) { + if( lag > 0 ) { + /* unrolled loop */ + silk_assert( HARM_SHAPE_FIR_TAPS == 3 ); + idx = lag + LTP_shp_buf_idx; + n_LTP_Q12 = silk_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); + n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); + n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); + } else { + n_LTP_Q12 = 0; + } + + n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 ); + n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 ); + + sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) ); + sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) ); + + LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; + LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); + + xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 ); + } + + /* Copy temp variable back to state */ + P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12; + P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12; + P->sLTP_shp_buf_idx = LTP_shp_buf_idx; +} +#endif /* OVERRIDE_silk_prefilt_FIX */ diff --git a/thirdparty/opus/silk/fixed/process_gains_FIX.c b/thirdparty/opus/silk/fixed/process_gains_FIX.c new file mode 100644 index 0000000000..05aba31788 --- /dev/null +++ b/thirdparty/opus/silk/fixed/process_gains_FIX.c @@ -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_FIX.h" +#include "tuning_parameters.h" + +/* 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 */ +) +{ + silk_shape_state_FIX *psShapeSt = &psEnc->sShape; + opus_int k; + opus_int32 s_Q16, InvMaxSqrVal_Q16, gain, gain_squared, ResNrg, ResNrgPart, quant_offset_Q10; + + /* Gain reduction when LTP coding gain is high */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /*s = -0.5f * silk_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) ); */ + s_Q16 = -silk_sigm_Q15( silk_RSHIFT_ROUND( psEncCtrl->LTPredCodGain_Q7 - SILK_FIX_CONST( 12.0, 7 ), 4 ) ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->Gains_Q16[ k ] = silk_SMLAWB( psEncCtrl->Gains_Q16[ k ], psEncCtrl->Gains_Q16[ k ], s_Q16 ); + } + } + + /* Limit the quantized signal */ + /* InvMaxSqrVal = pow( 2.0f, 0.33f * ( 21.0f - SNR_dB ) ) / subfr_length; */ + InvMaxSqrVal_Q16 = silk_DIV32_16( silk_log2lin( + silk_SMULWB( SILK_FIX_CONST( 21 + 16 / 0.33, 7 ) - psEnc->sCmn.SNR_dB_Q7, SILK_FIX_CONST( 0.33, 16 ) ) ), psEnc->sCmn.subfr_length ); + + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + /* Soft limit on ratio residual energy and squared gains */ + ResNrg = psEncCtrl->ResNrg[ k ]; + ResNrgPart = silk_SMULWW( ResNrg, InvMaxSqrVal_Q16 ); + if( psEncCtrl->ResNrgQ[ k ] > 0 ) { + ResNrgPart = silk_RSHIFT_ROUND( ResNrgPart, psEncCtrl->ResNrgQ[ k ] ); + } else { + if( ResNrgPart >= silk_RSHIFT( silk_int32_MAX, -psEncCtrl->ResNrgQ[ k ] ) ) { + ResNrgPart = silk_int32_MAX; + } else { + ResNrgPart = silk_LSHIFT( ResNrgPart, -psEncCtrl->ResNrgQ[ k ] ); + } + } + gain = psEncCtrl->Gains_Q16[ k ]; + gain_squared = silk_ADD_SAT32( ResNrgPart, silk_SMMUL( gain, gain ) ); + if( gain_squared < silk_int16_MAX ) { + /* recalculate with higher precision */ + gain_squared = silk_SMLAWW( silk_LSHIFT( ResNrgPart, 16 ), gain, gain ); + silk_assert( gain_squared > 0 ); + gain = silk_SQRT_APPROX( gain_squared ); /* Q8 */ + gain = silk_min( gain, silk_int32_MAX >> 8 ); + psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( gain, 8 ); /* Q16 */ + } else { + gain = silk_SQRT_APPROX( gain_squared ); /* Q0 */ + gain = silk_min( gain, silk_int32_MAX >> 16 ); + psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( gain, 16 ); /* Q16 */ + } + } + + /* Save unquantized gains and gain Index */ + silk_memcpy( psEncCtrl->GainsUnq_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); + psEncCtrl->lastGainIndexPrev = psShapeSt->LastGainIndex; + + /* Quantize gains */ + silk_gains_quant( psEnc->sCmn.indices.GainsIndices, psEncCtrl->Gains_Q16, + &psShapeSt->LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); + + /* 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_Q7 + silk_RSHIFT( psEnc->sCmn.input_tilt_Q15, 8 ) > SILK_FIX_CONST( 1.0, 7 ) ) { + psEnc->sCmn.indices.quantOffsetType = 0; + } else { + psEnc->sCmn.indices.quantOffsetType = 1; + } + } + + /* Quantizer boundary adjustment */ + quant_offset_Q10 = silk_Quantization_Offsets_Q10[ psEnc->sCmn.indices.signalType >> 1 ][ psEnc->sCmn.indices.quantOffsetType ]; + psEncCtrl->Lambda_Q10 = SILK_FIX_CONST( LAMBDA_OFFSET, 10 ) + + silk_SMULBB( SILK_FIX_CONST( LAMBDA_DELAYED_DECISIONS, 10 ), psEnc->sCmn.nStatesDelayedDecision ) + + silk_SMULWB( SILK_FIX_CONST( LAMBDA_SPEECH_ACT, 18 ), psEnc->sCmn.speech_activity_Q8 ) + + silk_SMULWB( SILK_FIX_CONST( LAMBDA_INPUT_QUALITY, 12 ), psEncCtrl->input_quality_Q14 ) + + silk_SMULWB( SILK_FIX_CONST( LAMBDA_CODING_QUALITY, 12 ), psEncCtrl->coding_quality_Q14 ) + + silk_SMULWB( SILK_FIX_CONST( LAMBDA_QUANT_OFFSET, 16 ), quant_offset_Q10 ); + + silk_assert( psEncCtrl->Lambda_Q10 > 0 ); + silk_assert( psEncCtrl->Lambda_Q10 < SILK_FIX_CONST( 2, 10 ) ); +} diff --git a/thirdparty/opus/silk/fixed/regularize_correlations_FIX.c b/thirdparty/opus/silk/fixed/regularize_correlations_FIX.c new file mode 100644 index 0000000000..a2836b05f4 --- /dev/null +++ b/thirdparty/opus/silk/fixed/regularize_correlations_FIX.c @@ -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 "main_FIX.h" + +/* Add noise to matrix diagonal */ +void silk_regularize_correlations_FIX( + opus_int32 *XX, /* I/O Correlation matrices */ + opus_int32 *xx, /* I/O Correlation values */ + opus_int32 noise, /* I Noise to add */ + opus_int D /* I Dimension of XX */ +) +{ + opus_int i; + for( i = 0; i < D; i++ ) { + matrix_ptr( &XX[ 0 ], i, i, D ) = silk_ADD32( matrix_ptr( &XX[ 0 ], i, i, D ), noise ); + } + xx[ 0 ] += noise; +} diff --git a/thirdparty/opus/silk/fixed/residual_energy16_FIX.c b/thirdparty/opus/silk/fixed/residual_energy16_FIX.c new file mode 100644 index 0000000000..ebffb2a66f --- /dev/null +++ b/thirdparty/opus/silk/fixed/residual_energy16_FIX.c @@ -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_FIX.h" + +/* 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 */ +) +{ + opus_int i, j, lshifts, Qxtra; + opus_int32 c_max, w_max, tmp, tmp2, nrg; + opus_int cn[ MAX_MATRIX_SIZE ]; + const opus_int32 *pRow; + + /* Safety checks */ + silk_assert( D >= 0 ); + silk_assert( D <= 16 ); + silk_assert( cQ > 0 ); + silk_assert( cQ < 16 ); + + lshifts = 16 - cQ; + Qxtra = lshifts; + + c_max = 0; + for( i = 0; i < D; i++ ) { + c_max = silk_max_32( c_max, silk_abs( (opus_int32)c[ i ] ) ); + } + Qxtra = silk_min_int( Qxtra, silk_CLZ32( c_max ) - 17 ); + + w_max = silk_max_32( wXX[ 0 ], wXX[ D * D - 1 ] ); + Qxtra = silk_min_int( Qxtra, silk_CLZ32( silk_MUL( D, silk_RSHIFT( silk_SMULWB( w_max, c_max ), 4 ) ) ) - 5 ); + Qxtra = silk_max_int( Qxtra, 0 ); + for( i = 0; i < D; i++ ) { + cn[ i ] = silk_LSHIFT( ( opus_int )c[ i ], Qxtra ); + silk_assert( silk_abs(cn[i]) <= ( silk_int16_MAX + 1 ) ); /* Check that silk_SMLAWB can be used */ + } + lshifts -= Qxtra; + + /* Compute wxx - 2 * wXx * c */ + tmp = 0; + for( i = 0; i < D; i++ ) { + tmp = silk_SMLAWB( tmp, wXx[ i ], cn[ i ] ); + } + nrg = silk_RSHIFT( wxx, 1 + lshifts ) - tmp; /* Q: -lshifts - 1 */ + + /* Add c' * wXX * c, assuming wXX is symmetric */ + tmp2 = 0; + for( i = 0; i < D; i++ ) { + tmp = 0; + pRow = &wXX[ i * D ]; + for( j = i + 1; j < D; j++ ) { + tmp = silk_SMLAWB( tmp, pRow[ j ], cn[ j ] ); + } + tmp = silk_SMLAWB( tmp, silk_RSHIFT( pRow[ i ], 1 ), cn[ i ] ); + tmp2 = silk_SMLAWB( tmp2, tmp, cn[ i ] ); + } + nrg = silk_ADD_LSHIFT32( nrg, tmp2, lshifts ); /* Q: -lshifts - 1 */ + + /* Keep one bit free always, because we add them for LSF interpolation */ + if( nrg < 1 ) { + nrg = 1; + } else if( nrg > silk_RSHIFT( silk_int32_MAX, lshifts + 2 ) ) { + nrg = silk_int32_MAX >> 1; + } else { + nrg = silk_LSHIFT( nrg, lshifts + 1 ); /* Q0 */ + } + return nrg; + +} diff --git a/thirdparty/opus/silk/fixed/residual_energy_FIX.c b/thirdparty/opus/silk/fixed/residual_energy_FIX.c new file mode 100644 index 0000000000..41f74778e8 --- /dev/null +++ b/thirdparty/opus/silk/fixed/residual_energy_FIX.c @@ -0,0 +1,98 @@ +/*********************************************************************** +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_FIX.h" +#include "stack_alloc.h" + +/* 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 */ +) +{ + opus_int offset, i, j, rshift, lz1, lz2; + opus_int16 *LPC_res_ptr; + VARDECL( opus_int16, LPC_res ); + const opus_int16 *x_ptr; + opus_int32 tmp32; + SAVE_STACK; + + x_ptr = x; + offset = LPC_order + subfr_length; + + /* Filter input to create the LPC residual for each frame half, and measure subframe energies */ + ALLOC( LPC_res, ( MAX_NB_SUBFR >> 1 ) * offset, opus_int16 ); + silk_assert( ( nb_subfr >> 1 ) * ( MAX_NB_SUBFR >> 1 ) == nb_subfr ); + for( i = 0; i < nb_subfr >> 1; i++ ) { + /* Calculate half frame LPC residual signal including preceding samples */ + silk_LPC_analysis_filter( LPC_res, x_ptr, a_Q12[ i ], ( MAX_NB_SUBFR >> 1 ) * offset, LPC_order, arch ); + + /* Point to first subframe of the just calculated LPC residual signal */ + LPC_res_ptr = LPC_res + LPC_order; + for( j = 0; j < ( MAX_NB_SUBFR >> 1 ); j++ ) { + /* Measure subframe energy */ + silk_sum_sqr_shift( &nrgs[ i * ( MAX_NB_SUBFR >> 1 ) + j ], &rshift, LPC_res_ptr, subfr_length ); + + /* Set Q values for the measured energy */ + nrgsQ[ i * ( MAX_NB_SUBFR >> 1 ) + j ] = -rshift; + + /* Move to next subframe */ + LPC_res_ptr += offset; + } + /* Move to next frame half */ + x_ptr += ( MAX_NB_SUBFR >> 1 ) * offset; + } + + /* Apply the squared subframe gains */ + for( i = 0; i < nb_subfr; i++ ) { + /* Fully upscale gains and energies */ + lz1 = silk_CLZ32( nrgs[ i ] ) - 1; + lz2 = silk_CLZ32( gains[ i ] ) - 1; + + tmp32 = silk_LSHIFT32( gains[ i ], lz2 ); + + /* Find squared gains */ + tmp32 = silk_SMMUL( tmp32, tmp32 ); /* Q( 2 * lz2 - 32 )*/ + + /* Scale energies */ + nrgs[ i ] = silk_SMMUL( tmp32, silk_LSHIFT32( nrgs[ i ], lz1 ) ); /* Q( nrgsQ[ i ] + lz1 + 2 * lz2 - 32 - 32 )*/ + nrgsQ[ i ] += lz1 + 2 * lz2 - 32 - 32; + } + RESTORE_STACK; +} diff --git a/thirdparty/opus/silk/fixed/schur64_FIX.c b/thirdparty/opus/silk/fixed/schur64_FIX.c new file mode 100644 index 0000000000..764a10ef3e --- /dev/null +++ b/thirdparty/opus/silk/fixed/schur64_FIX.c @@ -0,0 +1,92 @@ +/*********************************************************************** +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" + +/* 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 */ +) +{ + opus_int k, n; + opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; + opus_int32 Ctmp1_Q30, Ctmp2_Q30, rc_tmp_Q31; + + silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 ); + + /* Check for invalid input */ + if( c[ 0 ] <= 0 ) { + silk_memset( rc_Q16, 0, order * sizeof( opus_int32 ) ); + return 0; + } + + for( k = 0; k < order + 1; k++ ) { + C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; + } + + for( k = 0; k < order; k++ ) { + /* Check that we won't be getting an unstable rc, otherwise stop here. */ + if (silk_abs_int32(C[ k + 1 ][ 0 ]) >= C[ 0 ][ 1 ]) { + if ( C[ k + 1 ][ 0 ] > 0 ) { + rc_Q16[ k ] = -SILK_FIX_CONST( .99f, 16 ); + } else { + rc_Q16[ k ] = SILK_FIX_CONST( .99f, 16 ); + } + k++; + break; + } + + /* Get reflection coefficient: divide two Q30 values and get result in Q31 */ + rc_tmp_Q31 = silk_DIV32_varQ( -C[ k + 1 ][ 0 ], C[ 0 ][ 1 ], 31 ); + + /* Save the output */ + rc_Q16[ k ] = silk_RSHIFT_ROUND( rc_tmp_Q31, 15 ); + + /* Update correlations */ + for( n = 0; n < order - k; n++ ) { + Ctmp1_Q30 = C[ n + k + 1 ][ 0 ]; + Ctmp2_Q30 = C[ n ][ 1 ]; + + /* Multiply and add the highest int32 */ + C[ n + k + 1 ][ 0 ] = Ctmp1_Q30 + silk_SMMUL( silk_LSHIFT( Ctmp2_Q30, 1 ), rc_tmp_Q31 ); + C[ n ][ 1 ] = Ctmp2_Q30 + silk_SMMUL( silk_LSHIFT( Ctmp1_Q30, 1 ), rc_tmp_Q31 ); + } + } + + for(; k < order; k++ ) { + rc_Q16[ k ] = 0; + } + + return silk_max_32( 1, C[ 0 ][ 1 ] ); +} diff --git a/thirdparty/opus/silk/fixed/schur_FIX.c b/thirdparty/opus/silk/fixed/schur_FIX.c new file mode 100644 index 0000000000..c4c0ef23b4 --- /dev/null +++ b/thirdparty/opus/silk/fixed/schur_FIX.c @@ -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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" + +/* 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 */ +) +{ + opus_int k, n, lz; + opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; + opus_int32 Ctmp1, Ctmp2, rc_tmp_Q15; + + silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 ); + + /* Get number of leading zeros */ + lz = silk_CLZ32( c[ 0 ] ); + + /* Copy correlations and adjust level to Q30 */ + if( lz < 2 ) { + /* lz must be 1, so shift one to the right */ + for( k = 0; k < order + 1; k++ ) { + C[ k ][ 0 ] = C[ k ][ 1 ] = silk_RSHIFT( c[ k ], 1 ); + } + } else if( lz > 2 ) { + /* Shift to the left */ + lz -= 2; + for( k = 0; k < order + 1; k++ ) { + C[ k ][ 0 ] = C[ k ][ 1 ] = silk_LSHIFT( c[ k ], lz ); + } + } else { + /* No need to shift */ + for( k = 0; k < order + 1; k++ ) { + C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; + } + } + + for( k = 0; k < order; k++ ) { + /* Check that we won't be getting an unstable rc, otherwise stop here. */ + if (silk_abs_int32(C[ k + 1 ][ 0 ]) >= C[ 0 ][ 1 ]) { + if ( C[ k + 1 ][ 0 ] > 0 ) { + rc_Q15[ k ] = -SILK_FIX_CONST( .99f, 15 ); + } else { + rc_Q15[ k ] = SILK_FIX_CONST( .99f, 15 ); + } + k++; + break; + } + + /* Get reflection coefficient */ + rc_tmp_Q15 = -silk_DIV32_16( C[ k + 1 ][ 0 ], silk_max_32( silk_RSHIFT( C[ 0 ][ 1 ], 15 ), 1 ) ); + + /* Clip (shouldn't happen for properly conditioned inputs) */ + rc_tmp_Q15 = silk_SAT16( rc_tmp_Q15 ); + + /* Store */ + rc_Q15[ k ] = (opus_int16)rc_tmp_Q15; + + /* Update correlations */ + for( n = 0; n < order - k; n++ ) { + Ctmp1 = C[ n + k + 1 ][ 0 ]; + Ctmp2 = C[ n ][ 1 ]; + C[ n + k + 1 ][ 0 ] = silk_SMLAWB( Ctmp1, silk_LSHIFT( Ctmp2, 1 ), rc_tmp_Q15 ); + C[ n ][ 1 ] = silk_SMLAWB( Ctmp2, silk_LSHIFT( Ctmp1, 1 ), rc_tmp_Q15 ); + } + } + + for(; k < order; k++ ) { + rc_Q15[ k ] = 0; + } + + /* return residual energy */ + return silk_max_32( 1, C[ 0 ][ 1 ] ); +} diff --git a/thirdparty/opus/silk/fixed/solve_LS_FIX.c b/thirdparty/opus/silk/fixed/solve_LS_FIX.c new file mode 100644 index 0000000000..51d7d49d02 --- /dev/null +++ b/thirdparty/opus/silk/fixed/solve_LS_FIX.c @@ -0,0 +1,249 @@ +/*********************************************************************** +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_FIX.h" +#include "stack_alloc.h" +#include "tuning_parameters.h" + +/*****************************/ +/* Internal function headers */ +/*****************************/ + +typedef struct { + opus_int32 Q36_part; + opus_int32 Q48_part; +} inv_D_t; + +/* Factorize square matrix A into LDL form */ +static OPUS_INLINE void silk_LDL_factorize_FIX( + opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */ + opus_int M, /* I Size of Matrix */ + opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */ + inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */ +); + +/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */ +static OPUS_INLINE void silk_LS_SolveFirst_FIX( + const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ + opus_int M, /* I Dim of Matrix equation */ + const opus_int32 *b, /* I b Vector */ + opus_int32 *x_Q16 /* O x Vector */ +); + +/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */ +static OPUS_INLINE void silk_LS_SolveLast_FIX( + const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ + const opus_int M, /* I Dim of Matrix equation */ + const opus_int32 *b, /* I b Vector */ + opus_int32 *x_Q16 /* O x Vector */ +); + +static OPUS_INLINE void silk_LS_divide_Q16_FIX( + opus_int32 T[], /* I/O Numenator vector */ + inv_D_t *inv_D, /* I 1 / D vector */ + opus_int M /* I dimension */ +); + +/* Solves Ax = b, assuming A is symmetric */ +void silk_solve_LDL_FIX( + opus_int32 *A, /* I Pointer to symetric square matrix A */ + opus_int M, /* I Size of matrix */ + const opus_int32 *b, /* I Pointer to b vector */ + opus_int32 *x_Q16 /* O Pointer to x solution vector */ +) +{ + VARDECL( opus_int32, L_Q16 ); + opus_int32 Y[ MAX_MATRIX_SIZE ]; + inv_D_t inv_D[ MAX_MATRIX_SIZE ]; + SAVE_STACK; + + silk_assert( M <= MAX_MATRIX_SIZE ); + ALLOC( L_Q16, M * M, opus_int32 ); + + /*************************************************** + Factorize A by LDL such that A = L*D*L', + where L is lower triangular with ones on diagonal + ****************************************************/ + silk_LDL_factorize_FIX( A, M, L_Q16, inv_D ); + + /**************************************************** + * substitute D*L'*x = Y. ie: + L*D*L'*x = b => L*Y = b <=> Y = inv(L)*b + ******************************************************/ + silk_LS_SolveFirst_FIX( L_Q16, M, b, Y ); + + /**************************************************** + D*L'*x = Y <=> L'*x = inv(D)*Y, because D is + diagonal just multiply with 1/d_i + ****************************************************/ + silk_LS_divide_Q16_FIX( Y, inv_D, M ); + + /**************************************************** + x = inv(L') * inv(D) * Y + *****************************************************/ + silk_LS_SolveLast_FIX( L_Q16, M, Y, x_Q16 ); + RESTORE_STACK; +} + +static OPUS_INLINE void silk_LDL_factorize_FIX( + opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */ + opus_int M, /* I Size of Matrix */ + opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */ + inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */ +) +{ + opus_int i, j, k, status, loop_count; + const opus_int32 *ptr1, *ptr2; + opus_int32 diag_min_value, tmp_32, err; + opus_int32 v_Q0[ MAX_MATRIX_SIZE ], D_Q0[ MAX_MATRIX_SIZE ]; + opus_int32 one_div_diag_Q36, one_div_diag_Q40, one_div_diag_Q48; + + silk_assert( M <= MAX_MATRIX_SIZE ); + + status = 1; + diag_min_value = silk_max_32( silk_SMMUL( silk_ADD_SAT32( A[ 0 ], A[ silk_SMULBB( M, M ) - 1 ] ), SILK_FIX_CONST( FIND_LTP_COND_FAC, 31 ) ), 1 << 9 ); + for( loop_count = 0; loop_count < M && status == 1; loop_count++ ) { + status = 0; + for( j = 0; j < M; j++ ) { + ptr1 = matrix_adr( L_Q16, j, 0, M ); + tmp_32 = 0; + for( i = 0; i < j; i++ ) { + v_Q0[ i ] = silk_SMULWW( D_Q0[ i ], ptr1[ i ] ); /* Q0 */ + tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ i ], ptr1[ i ] ); /* Q0 */ + } + tmp_32 = silk_SUB32( matrix_ptr( A, j, j, M ), tmp_32 ); + + if( tmp_32 < diag_min_value ) { + tmp_32 = silk_SUB32( silk_SMULBB( loop_count + 1, diag_min_value ), tmp_32 ); + /* Matrix not positive semi-definite, or ill conditioned */ + for( i = 0; i < M; i++ ) { + matrix_ptr( A, i, i, M ) = silk_ADD32( matrix_ptr( A, i, i, M ), tmp_32 ); + } + status = 1; + break; + } + D_Q0[ j ] = tmp_32; /* always < max(Correlation) */ + + /* two-step division */ + one_div_diag_Q36 = silk_INVERSE32_varQ( tmp_32, 36 ); /* Q36 */ + one_div_diag_Q40 = silk_LSHIFT( one_div_diag_Q36, 4 ); /* Q40 */ + err = silk_SUB32( (opus_int32)1 << 24, silk_SMULWW( tmp_32, one_div_diag_Q40 ) ); /* Q24 */ + one_div_diag_Q48 = silk_SMULWW( err, one_div_diag_Q40 ); /* Q48 */ + + /* Save 1/Ds */ + inv_D[ j ].Q36_part = one_div_diag_Q36; + inv_D[ j ].Q48_part = one_div_diag_Q48; + + matrix_ptr( L_Q16, j, j, M ) = 65536; /* 1.0 in Q16 */ + ptr1 = matrix_adr( A, j, 0, M ); + ptr2 = matrix_adr( L_Q16, j + 1, 0, M ); + for( i = j + 1; i < M; i++ ) { + tmp_32 = 0; + for( k = 0; k < j; k++ ) { + tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ k ], ptr2[ k ] ); /* Q0 */ + } + tmp_32 = silk_SUB32( ptr1[ i ], tmp_32 ); /* always < max(Correlation) */ + + /* tmp_32 / D_Q0[j] : Divide to Q16 */ + matrix_ptr( L_Q16, i, j, M ) = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ), + silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) ); + + /* go to next column */ + ptr2 += M; + } + } + } + + silk_assert( status == 0 ); +} + +static OPUS_INLINE void silk_LS_divide_Q16_FIX( + opus_int32 T[], /* I/O Numenator vector */ + inv_D_t *inv_D, /* I 1 / D vector */ + opus_int M /* I dimension */ +) +{ + opus_int i; + opus_int32 tmp_32; + opus_int32 one_div_diag_Q36, one_div_diag_Q48; + + for( i = 0; i < M; i++ ) { + one_div_diag_Q36 = inv_D[ i ].Q36_part; + one_div_diag_Q48 = inv_D[ i ].Q48_part; + + tmp_32 = T[ i ]; + T[ i ] = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ), silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) ); + } +} + +/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */ +static OPUS_INLINE void silk_LS_SolveFirst_FIX( + const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ + opus_int M, /* I Dim of Matrix equation */ + const opus_int32 *b, /* I b Vector */ + opus_int32 *x_Q16 /* O x Vector */ +) +{ + opus_int i, j; + const opus_int32 *ptr32; + opus_int32 tmp_32; + + for( i = 0; i < M; i++ ) { + ptr32 = matrix_adr( L_Q16, i, 0, M ); + tmp_32 = 0; + for( j = 0; j < i; j++ ) { + tmp_32 = silk_SMLAWW( tmp_32, ptr32[ j ], x_Q16[ j ] ); + } + x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 ); + } +} + +/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */ +static OPUS_INLINE void silk_LS_SolveLast_FIX( + const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ + const opus_int M, /* I Dim of Matrix equation */ + const opus_int32 *b, /* I b Vector */ + opus_int32 *x_Q16 /* O x Vector */ +) +{ + opus_int i, j; + const opus_int32 *ptr32; + opus_int32 tmp_32; + + for( i = M - 1; i >= 0; i-- ) { + ptr32 = matrix_adr( L_Q16, 0, i, M ); + tmp_32 = 0; + for( j = M - 1; j > i; j-- ) { + tmp_32 = silk_SMLAWW( tmp_32, ptr32[ silk_SMULBB( j, M ) ], x_Q16[ j ] ); + } + x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 ); + } +} diff --git a/thirdparty/opus/silk/fixed/structs_FIX.h b/thirdparty/opus/silk/fixed/structs_FIX.h new file mode 100644 index 0000000000..3294b25128 --- /dev/null +++ b/thirdparty/opus/silk/fixed/structs_FIX.h @@ -0,0 +1,134 @@ +/*********************************************************************** +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" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/********************************/ +/* 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; + +/********************************/ +/* Prefilter state */ +/********************************/ +typedef struct { + opus_int16 sLTP_shp[ LTP_BUF_LENGTH ]; + opus_int32 sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ]; + opus_int sLTP_shp_buf_idx; + opus_int32 sLF_AR_shp_Q12; + opus_int32 sLF_MA_shp_Q12; + opus_int32 sHarmHP_Q2; + opus_int32 rand_seed; + opus_int lagPrev; +} silk_prefilter_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 */ + silk_prefilter_state_FIX sPrefilt; /* Prefilter 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 */ +} 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 AR1_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; + silk_DWORD_ALIGN opus_int16 AR2_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 GainsPre_Q14[ MAX_NB_SUBFR ]; + opus_int HarmBoost_Q14[ MAX_NB_SUBFR ]; + 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_int sparseness_Q8; + 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 { + silk_encoder_state_FIX state_Fxx[ ENCODER_NUM_CHANNELS ]; + 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; +} silk_encoder; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/opus/silk/fixed/vector_ops_FIX.c b/thirdparty/opus/silk/fixed/vector_ops_FIX.c new file mode 100644 index 0000000000..d94980014f --- /dev/null +++ b/thirdparty/opus/silk/fixed/vector_ops_FIX.c @@ -0,0 +1,102 @@ +/*********************************************************************** +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 "pitch.h" + +/* 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 */ +) +{ + opus_int i; + opus_int32 tmp32; + + for( i = 0; i < dataSize; i++ ) { + tmp32 = silk_SMULWB( gain_Q16, data_in[ i ] ); + data_out[ i ] = (opus_int16)silk_CHECK_FIT16( tmp32 ); + } +} + +/* Multiply a vector by a constant */ +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 */ +) +{ + opus_int i; + + for( i = 0; i < dataSize; i++ ) { + data1[ i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( silk_SMULL( data1[ i ], gain_Q26 ), 8 ) ); /* OUTPUT: Q18 */ + } +} + +/* sum = for(i=0;i<len;i++)inVec1[i]*inVec2[i]; --- inner product */ +/* Note for ARM asm: */ +/* * inVec1 and inVec2 should be at least 2 byte aligned. */ +/* * len should be positive 16bit integer. */ +/* * only when len>6, memory access can be reduced by half. */ +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 */ +) +{ +#ifdef FIXED_POINT + return celt_inner_prod(inVec1, inVec2, len, arch); +#else + opus_int i; + opus_int32 sum = 0; + for( i = 0; i < len; i++ ) { + sum = silk_SMLABB( sum, inVec1[ i ], inVec2[ i ] ); + } + return sum; +#endif +} + +opus_int64 silk_inner_prod16_aligned_64_c( + const opus_int16 *inVec1, /* I input vector 1 */ + const opus_int16 *inVec2, /* I input vector 2 */ + const opus_int len /* I vector lengths */ +) +{ + opus_int i; + opus_int64 sum = 0; + for( i = 0; i < len; i++ ) { + sum = silk_SMLALBB( sum, inVec1[ i ], inVec2[ i ] ); + } + return sum; +} diff --git a/thirdparty/opus/silk/fixed/warped_autocorrelation_FIX.c b/thirdparty/opus/silk/fixed/warped_autocorrelation_FIX.c new file mode 100644 index 0000000000..6ca6c1184d --- /dev/null +++ b/thirdparty/opus/silk/fixed/warped_autocorrelation_FIX.c @@ -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 + +#include "main_FIX.h" + +#define QC 10 +#define QS 14 + +#if defined(MIPSr1_ASM) +#include "mips/warped_autocorrelation_FIX_mipsr1.h" +#endif + + +#ifndef OVERRIDE_silk_warped_autocorrelation_FIX +/* Autocorrelations for a warped frequency axis */ +void silk_warped_autocorrelation_FIX( + 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, tmp2_QS; + opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; + opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; + + /* Order must be even */ + silk_assert( ( order & 1 ) == 0 ); + silk_assert( 2 * QS - QC >= 0 ); + + /* Loop over samples */ + for( n = 0; 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 ] += silk_RSHIFT64( silk_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); + /* 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 ] += silk_RSHIFT64( silk_SMULL( tmp2_QS, state_QS[ 0 ] ), 2 * QS - QC ); + } + state_QS[ order ] = tmp1_QS; + corr_QC[ order ] += silk_RSHIFT64( silk_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); + } + + lsh = silk_CLZ64( corr_QC[ 0 ] ) - 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++ ) { + corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_LSHIFT64( corr_QC[ i ], lsh ) ); + } + } else { + for( i = 0; i < order + 1; i++ ) { + corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QC[ i ], -lsh ) ); + } + } + silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/ +} +#endif /* OVERRIDE_silk_warped_autocorrelation_FIX */ diff --git a/thirdparty/opus/silk/fixed/x86/burg_modified_FIX_sse.c b/thirdparty/opus/silk/fixed/x86/burg_modified_FIX_sse.c new file mode 100644 index 0000000000..3756095fbe --- /dev/null +++ b/thirdparty/opus/silk/fixed/x86/burg_modified_FIX_sse.c @@ -0,0 +1,375 @@ +/* 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 "SigProc_FIX.h" +#include "define.h" +#include "tuning_parameters.h" +#include "pitch.h" +#include "celt/x86/x86cpu.h" + +#define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */ + +#define QA 25 +#define N_BITS_HEAD_ROOM 2 +#define MIN_RSHIFTS -16 +#define MAX_RSHIFTS (32 - QA) + +/* Compute reflection coefficients from input signal */ +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 */ +) +{ + opus_int k, n, s, lz, rshifts, rshifts_extra, reached_max_gain; + opus_int32 C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2; + const opus_int16 *x_ptr; + opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ]; + opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ]; + opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ]; + opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ]; + opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ]; + opus_int32 xcorr[ SILK_MAX_ORDER_LPC ]; + + __m128i FIRST_3210, LAST_3210, ATMP_3210, TMP1_3210, TMP2_3210, T1_3210, T2_3210, PTR_3210, SUBFR_3210, X1_3210, X2_3210; + __m128i CONST1 = _mm_set1_epi32(1); + + silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); + + /* Compute autocorrelations, added over subframes */ + silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length ); + if( rshifts > MAX_RSHIFTS ) { + C0 = silk_LSHIFT32( C0, rshifts - MAX_RSHIFTS ); + silk_assert( C0 > 0 ); + rshifts = MAX_RSHIFTS; + } else { + lz = silk_CLZ32( C0 ) - 1; + rshifts_extra = N_BITS_HEAD_ROOM - lz; + if( rshifts_extra > 0 ) { + rshifts_extra = silk_min( rshifts_extra, MAX_RSHIFTS - rshifts ); + C0 = silk_RSHIFT32( C0, rshifts_extra ); + } else { + rshifts_extra = silk_max( rshifts_extra, MIN_RSHIFTS - rshifts ); + C0 = silk_LSHIFT32( C0, -rshifts_extra ); + } + rshifts += rshifts_extra; + } + CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ + silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); + if( rshifts > 0 ) { + 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 ] += (opus_int32)silk_RSHIFT64( + silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n, arch ), rshifts ); + } + } + } else { + for( s = 0; s < nb_subfr; s++ ) { + int i; + opus_int32 d; + x_ptr = x + s * subfr_length; + celt_pitch_xcorr(x_ptr, x_ptr + 1, xcorr, subfr_length - D, D, arch ); + for( n = 1; n < D + 1; n++ ) { + for ( i = n + subfr_length - D, d = 0; i < subfr_length; i++ ) + d = MAC16_16( d, x_ptr[ i ], x_ptr[ i - n ] ); + xcorr[ n - 1 ] += d; + } + for( n = 1; n < D + 1; n++ ) { + C_first_row[ n - 1 ] += silk_LSHIFT32( xcorr[ n - 1 ], -rshifts ); + } + } + } + silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); + + /* Initialize */ + CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ + + invGain_Q30 = (opus_int32)1 << 30; + 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) */ + if( rshifts > -2 ) { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], 16 - rshifts ); /* Q(16-rshifts) */ + x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts ); /* Q(16-rshifts) */ + tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], QA - 16 ); /* Q(QA-16) */ + tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); /* Q(QA-16) */ + for( k = 0; k < n; k++ ) { + C_first_row[ k ] = silk_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ + C_last_row[ k ] = silk_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ + Atmp_QA = Af_QA[ k ]; + tmp1 = silk_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); /* Q(QA-16) */ + tmp2 = silk_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] ); /* Q(QA-16) */ + } + tmp1 = silk_LSHIFT32( -tmp1, 32 - QA - rshifts ); /* Q(16-rshifts) */ + tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts ); /* Q(16-rshifts) */ + for( k = 0; k <= n; k++ ) { + CAf[ k ] = silk_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); /* Q( -rshift ) */ + CAb[ k ] = silk_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); /* Q( -rshift ) */ + } + } + } else { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], -rshifts ); /* Q( -rshifts ) */ + x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); /* Q( -rshifts ) */ + tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); /* Q17 */ + tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); /* Q17 */ + + X1_3210 = _mm_set1_epi32( x1 ); + X2_3210 = _mm_set1_epi32( x2 ); + TMP1_3210 = _mm_setzero_si128(); + TMP2_3210 = _mm_setzero_si128(); + for( k = 0; k < n - 3; k += 4 ) { + PTR_3210 = OP_CVTEPI16_EPI32_M64( &x_ptr[ n - k - 1 - 3 ] ); + SUBFR_3210 = OP_CVTEPI16_EPI32_M64( &x_ptr[ subfr_length - n + k ] ); + FIRST_3210 = _mm_loadu_si128( (__m128i *)&C_first_row[ k ] ); + PTR_3210 = _mm_shuffle_epi32( PTR_3210, _MM_SHUFFLE( 0, 1, 2, 3 ) ); + LAST_3210 = _mm_loadu_si128( (__m128i *)&C_last_row[ k ] ); + ATMP_3210 = _mm_loadu_si128( (__m128i *)&Af_QA[ k ] ); + + T1_3210 = _mm_mullo_epi32( PTR_3210, X1_3210 ); + T2_3210 = _mm_mullo_epi32( SUBFR_3210, X2_3210 ); + + ATMP_3210 = _mm_srai_epi32( ATMP_3210, 7 ); + ATMP_3210 = _mm_add_epi32( ATMP_3210, CONST1 ); + ATMP_3210 = _mm_srai_epi32( ATMP_3210, 1 ); + + FIRST_3210 = _mm_add_epi32( FIRST_3210, T1_3210 ); + LAST_3210 = _mm_add_epi32( LAST_3210, T2_3210 ); + + PTR_3210 = _mm_mullo_epi32( ATMP_3210, PTR_3210 ); + SUBFR_3210 = _mm_mullo_epi32( ATMP_3210, SUBFR_3210 ); + + _mm_storeu_si128( (__m128i *)&C_first_row[ k ], FIRST_3210 ); + _mm_storeu_si128( (__m128i *)&C_last_row[ k ], LAST_3210 ); + + TMP1_3210 = _mm_add_epi32( TMP1_3210, PTR_3210 ); + TMP2_3210 = _mm_add_epi32( TMP2_3210, SUBFR_3210 ); + } + + TMP1_3210 = _mm_add_epi32( TMP1_3210, _mm_unpackhi_epi64(TMP1_3210, TMP1_3210 ) ); + TMP2_3210 = _mm_add_epi32( TMP2_3210, _mm_unpackhi_epi64(TMP2_3210, TMP2_3210 ) ); + TMP1_3210 = _mm_add_epi32( TMP1_3210, _mm_shufflelo_epi16(TMP1_3210, 0x0E ) ); + TMP2_3210 = _mm_add_epi32( TMP2_3210, _mm_shufflelo_epi16(TMP2_3210, 0x0E ) ); + + tmp1 += _mm_cvtsi128_si32( TMP1_3210 ); + tmp2 += _mm_cvtsi128_si32( TMP2_3210 ); + + for( ; k < n; k++ ) { + C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ + C_last_row[ k ] = silk_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ + Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); /* Q17 */ + tmp1 = silk_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */ + tmp2 = silk_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17 */ + } + + tmp1 = -tmp1; /* Q17 */ + tmp2 = -tmp2; /* Q17 */ + + { + __m128i xmm_tmp1, xmm_tmp2; + __m128i xmm_x_ptr_n_k_x2x0, xmm_x_ptr_n_k_x3x1; + __m128i xmm_x_ptr_sub_x2x0, xmm_x_ptr_sub_x3x1; + + xmm_tmp1 = _mm_set1_epi32( tmp1 ); + xmm_tmp2 = _mm_set1_epi32( tmp2 ); + + for( k = 0; k <= n - 3; k += 4 ) { + xmm_x_ptr_n_k_x2x0 = OP_CVTEPI16_EPI32_M64( &x_ptr[ n - k - 3 ] ); + xmm_x_ptr_sub_x2x0 = OP_CVTEPI16_EPI32_M64( &x_ptr[ subfr_length - n + k - 1 ] ); + + xmm_x_ptr_n_k_x2x0 = _mm_shuffle_epi32( xmm_x_ptr_n_k_x2x0, _MM_SHUFFLE( 0, 1, 2, 3 ) ); + + xmm_x_ptr_n_k_x2x0 = _mm_slli_epi32( xmm_x_ptr_n_k_x2x0, -rshifts - 1 ); + xmm_x_ptr_sub_x2x0 = _mm_slli_epi32( xmm_x_ptr_sub_x2x0, -rshifts - 1 ); + + /* equal shift right 4 bytes, xmm_x_ptr_n_k_x3x1 = _mm_srli_si128(xmm_x_ptr_n_k_x2x0, 4)*/ + xmm_x_ptr_n_k_x3x1 = _mm_shuffle_epi32( xmm_x_ptr_n_k_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) ); + xmm_x_ptr_sub_x3x1 = _mm_shuffle_epi32( xmm_x_ptr_sub_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) ); + + xmm_x_ptr_n_k_x2x0 = _mm_mul_epi32( xmm_x_ptr_n_k_x2x0, xmm_tmp1 ); + xmm_x_ptr_n_k_x3x1 = _mm_mul_epi32( xmm_x_ptr_n_k_x3x1, xmm_tmp1 ); + xmm_x_ptr_sub_x2x0 = _mm_mul_epi32( xmm_x_ptr_sub_x2x0, xmm_tmp2 ); + xmm_x_ptr_sub_x3x1 = _mm_mul_epi32( xmm_x_ptr_sub_x3x1, xmm_tmp2 ); + + xmm_x_ptr_n_k_x2x0 = _mm_srli_epi64( xmm_x_ptr_n_k_x2x0, 16 ); + xmm_x_ptr_n_k_x3x1 = _mm_slli_epi64( xmm_x_ptr_n_k_x3x1, 16 ); + xmm_x_ptr_sub_x2x0 = _mm_srli_epi64( xmm_x_ptr_sub_x2x0, 16 ); + xmm_x_ptr_sub_x3x1 = _mm_slli_epi64( xmm_x_ptr_sub_x3x1, 16 ); + + xmm_x_ptr_n_k_x2x0 = _mm_blend_epi16( xmm_x_ptr_n_k_x2x0, xmm_x_ptr_n_k_x3x1, 0xCC ); + xmm_x_ptr_sub_x2x0 = _mm_blend_epi16( xmm_x_ptr_sub_x2x0, xmm_x_ptr_sub_x3x1, 0xCC ); + + X1_3210 = _mm_loadu_si128( (__m128i *)&CAf[ k ] ); + PTR_3210 = _mm_loadu_si128( (__m128i *)&CAb[ k ] ); + + X1_3210 = _mm_add_epi32( X1_3210, xmm_x_ptr_n_k_x2x0 ); + PTR_3210 = _mm_add_epi32( PTR_3210, xmm_x_ptr_sub_x2x0 ); + + _mm_storeu_si128( (__m128i *)&CAf[ k ], X1_3210 ); + _mm_storeu_si128( (__m128i *)&CAb[ k ], PTR_3210 ); + } + + for( ; k <= n; k++ ) { + CAf[ k ] = silk_SMLAWW( CAf[ k ], tmp1, + silk_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) ); /* Q( -rshift ) */ + CAb[ k ] = silk_SMLAWW( CAb[ k ], tmp2, + silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) ); /* Q( -rshift ) */ + } + } + } + } + + /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ + tmp1 = C_first_row[ n ]; /* Q( -rshifts ) */ + tmp2 = C_last_row[ n ]; /* Q( -rshifts ) */ + num = 0; /* Q( -rshifts ) */ + nrg = silk_ADD32( CAb[ 0 ], CAf[ 0 ] ); /* Q( 1-rshifts ) */ + for( k = 0; k < n; k++ ) { + Atmp_QA = Af_QA[ k ]; + lz = silk_CLZ32( silk_abs( Atmp_QA ) ) - 1; + lz = silk_min( 32 - QA, lz ); + Atmp1 = silk_LSHIFT32( Atmp_QA, lz ); /* Q( QA + lz ) */ + + tmp1 = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( C_last_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ + tmp2 = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ + num = silk_ADD_LSHIFT32( num, silk_SMMUL( CAb[ n - k ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ + nrg = silk_ADD_LSHIFT32( nrg, silk_SMMUL( silk_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ), + Atmp1 ), 32 - QA - lz ); /* Q( 1-rshifts ) */ + } + CAf[ n + 1 ] = tmp1; /* Q( -rshifts ) */ + CAb[ n + 1 ] = tmp2; /* Q( -rshifts ) */ + num = silk_ADD32( num, tmp2 ); /* Q( -rshifts ) */ + num = silk_LSHIFT32( -num, 1 ); /* Q( 1-rshifts ) */ + + /* Calculate the next order reflection (parcor) coefficient */ + if( silk_abs( num ) < nrg ) { + rc_Q31 = silk_DIV32_varQ( num, nrg, 31 ); + } else { + rc_Q31 = ( num > 0 ) ? silk_int32_MAX : silk_int32_MIN; + } + + /* Update inverse prediction gain */ + tmp1 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); + tmp1 = silk_LSHIFT( silk_SMMUL( invGain_Q30, tmp1 ), 2 ); + if( tmp1 <= minInvGain_Q30 ) { + /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */ + tmp2 = ( (opus_int32)1 << 30 ) - silk_DIV32_varQ( minInvGain_Q30, invGain_Q30, 30 ); /* Q30 */ + rc_Q31 = silk_SQRT_APPROX( tmp2 ); /* Q15 */ + /* Newton-Raphson iteration */ + rc_Q31 = silk_RSHIFT32( rc_Q31 + silk_DIV32( tmp2, rc_Q31 ), 1 ); /* Q15 */ + rc_Q31 = silk_LSHIFT32( rc_Q31, 16 ); /* Q31 */ + if( num < 0 ) { + /* Ensure adjusted reflection coefficients has the original sign */ + rc_Q31 = -rc_Q31; + } + invGain_Q30 = minInvGain_Q30; + reached_max_gain = 1; + } else { + invGain_Q30 = tmp1; + } + + /* Update the AR coefficients */ + for( k = 0; k < (n + 1) >> 1; k++ ) { + tmp1 = Af_QA[ k ]; /* QA */ + tmp2 = Af_QA[ n - k - 1 ]; /* QA */ + Af_QA[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* QA */ + Af_QA[ n - k - 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* QA */ + } + Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA ); /* QA */ + + if( reached_max_gain ) { + /* Reached max prediction gain; set remaining coefficients to zero and exit loop */ + for( k = n + 1; k < D; k++ ) { + Af_QA[ k ] = 0; + } + break; + } + + /* Update C * Af and C * Ab */ + for( k = 0; k <= n + 1; k++ ) { + tmp1 = CAf[ k ]; /* Q( -rshifts ) */ + tmp2 = CAb[ n - k + 1 ]; /* Q( -rshifts ) */ + CAf[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* Q( -rshifts ) */ + CAb[ n - k + 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* Q( -rshifts ) */ + } + } + + if( reached_max_gain ) { + for( k = 0; k < D; k++ ) { + /* Scale coefficients */ + A_Q16[ k ] = -silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); + } + /* Subtract energy of preceding samples from C0 */ + if( rshifts > 0 ) { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr, D, arch ), rshifts ); + } + } else { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + C0 -= silk_LSHIFT32( silk_inner_prod_aligned( x_ptr, x_ptr, D, arch ), -rshifts ); + } + } + /* Approximate residual energy */ + *res_nrg = silk_LSHIFT( silk_SMMUL( invGain_Q30, C0 ), 2 ); + *res_nrg_Q = -rshifts; + } else { + /* Return residual energy */ + nrg = CAf[ 0 ]; /* Q( -rshifts ) */ + tmp1 = (opus_int32)1 << 16; /* Q16 */ + for( k = 0; k < D; k++ ) { + Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); /* Q16 */ + nrg = silk_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); /* Q( -rshifts ) */ + tmp1 = silk_SMLAWW( tmp1, Atmp1, Atmp1 ); /* Q16 */ + A_Q16[ k ] = -Atmp1; + } + *res_nrg = silk_SMLAWW( nrg, silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ), -tmp1 );/* Q( -rshifts ) */ + *res_nrg_Q = -rshifts; + } +} diff --git a/thirdparty/opus/silk/fixed/x86/prefilter_FIX_sse.c b/thirdparty/opus/silk/fixed/x86/prefilter_FIX_sse.c new file mode 100644 index 0000000000..488a603f5d --- /dev/null +++ b/thirdparty/opus/silk/fixed/x86/prefilter_FIX_sse.c @@ -0,0 +1,160 @@ +/* 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 "main.h" +#include "celt/x86/x86cpu.h" + +void silk_warped_LPC_analysis_filter_FIX_sse4_1( + opus_int32 state[], /* I/O State [order + 1] */ + opus_int32 res_Q2[], /* O Residual signal [length] */ + const opus_int16 coef_Q13[], /* I Coefficients [order] */ + const opus_int16 input[], /* I Input signal [length] */ + const opus_int16 lambda_Q16, /* I Warping factor */ + const opus_int length, /* I Length of input signal */ + const opus_int order /* I Filter order (even) */ +) +{ + opus_int n, i; + opus_int32 acc_Q11, tmp1, tmp2; + + /* Order must be even */ + silk_assert( ( order & 1 ) == 0 ); + + if (order == 10) + { + if (0 == lambda_Q16) + { + __m128i coef_Q13_3210, coef_Q13_7654; + __m128i coef_Q13_0123, coef_Q13_4567; + __m128i state_0123, state_4567; + __m128i xmm_product1, xmm_product2; + __m128i xmm_tempa, xmm_tempb; + + register opus_int32 sum; + register opus_int32 state_8, state_9, state_a; + register opus_int64 coef_Q13_8, coef_Q13_9; + + silk_assert( length > 0 ); + + coef_Q13_3210 = OP_CVTEPI16_EPI32_M64( &coef_Q13[ 0 ] ); + coef_Q13_7654 = OP_CVTEPI16_EPI32_M64( &coef_Q13[ 4 ] ); + + coef_Q13_0123 = _mm_shuffle_epi32( coef_Q13_3210, _MM_SHUFFLE( 0, 1, 2, 3 ) ); + coef_Q13_4567 = _mm_shuffle_epi32( coef_Q13_7654, _MM_SHUFFLE( 0, 1, 2, 3 ) ); + + coef_Q13_8 = (opus_int64) coef_Q13[ 8 ]; + coef_Q13_9 = (opus_int64) coef_Q13[ 9 ]; + + state_0123 = _mm_loadu_si128( (__m128i *)(&state[ 0 ] ) ); + state_4567 = _mm_loadu_si128( (__m128i *)(&state[ 4 ] ) ); + + state_0123 = _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) ); + state_4567 = _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) ); + + state_8 = state[ 8 ]; + state_9 = state[ 9 ]; + state_a = 0; + + for( n = 0; n < length; n++ ) + { + xmm_product1 = _mm_mul_epi32( coef_Q13_0123, state_0123 ); /* 64-bit multiply, only 2 pairs */ + xmm_product2 = _mm_mul_epi32( coef_Q13_4567, state_4567 ); + + xmm_tempa = _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) ); + xmm_tempb = _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) ); + + xmm_product1 = _mm_srli_epi64( xmm_product1, 16 ); /* >> 16, zero extending works */ + xmm_product2 = _mm_srli_epi64( xmm_product2, 16 ); + + xmm_tempa = _mm_mul_epi32( coef_Q13_3210, xmm_tempa ); + xmm_tempb = _mm_mul_epi32( coef_Q13_7654, xmm_tempb ); + + xmm_tempa = _mm_srli_epi64( xmm_tempa, 16 ); + xmm_tempb = _mm_srli_epi64( xmm_tempb, 16 ); + + xmm_tempa = _mm_add_epi32( xmm_tempa, xmm_product1 ); + xmm_tempb = _mm_add_epi32( xmm_tempb, xmm_product2 ); + xmm_tempa = _mm_add_epi32( xmm_tempa, xmm_tempb ); + + sum = (coef_Q13_8 * state_8) >> 16; + sum += (coef_Q13_9 * state_9) >> 16; + + xmm_tempa = _mm_add_epi32( xmm_tempa, _mm_shuffle_epi32( xmm_tempa, _MM_SHUFFLE( 0, 0, 0, 2 ) ) ); + sum += _mm_cvtsi128_si32( xmm_tempa); + res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( ( 5 + sum ), 9); + + /* move right */ + state_a = state_9; + state_9 = state_8; + state_8 = _mm_cvtsi128_si32( state_4567 ); + state_4567 = _mm_alignr_epi8( state_0123, state_4567, 4 ); + + state_0123 = _mm_alignr_epi8( _mm_cvtsi32_si128( silk_LSHIFT( input[ n ], 14 ) ), state_0123, 4 ); + } + + _mm_storeu_si128( (__m128i *)( &state[ 0 ] ), _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) ) ); + _mm_storeu_si128( (__m128i *)( &state[ 4 ] ), _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) ) ); + state[ 8 ] = state_8; + state[ 9 ] = state_9; + state[ 10 ] = state_a; + + return; + } + } + + for( n = 0; n < length; n++ ) { + /* Output of lowpass section */ + tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 ); + state[ 0 ] = silk_LSHIFT( input[ n ], 14 ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 ); + state[ 1 ] = tmp2; + acc_Q11 = silk_RSHIFT( order, 1 ); + acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] ); + /* Loop over allpass sections */ + for( i = 2; i < order; i += 2 ) { + /* Output of allpass section */ + tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 ); + state[ i ] = tmp1; + acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 ); + state[ i + 1 ] = tmp2; + acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] ); + } + state[ order ] = tmp1; + acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); + res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 ); + } +} diff --git a/thirdparty/opus/silk/fixed/x86/vector_ops_FIX_sse.c b/thirdparty/opus/silk/fixed/x86/vector_ops_FIX_sse.c new file mode 100644 index 0000000000..c1e90564d0 --- /dev/null +++ b/thirdparty/opus/silk/fixed/x86/vector_ops_FIX_sse.c @@ -0,0 +1,88 @@ +/* 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 "main.h" + +#include "SigProc_FIX.h" +#include "pitch.h" + +opus_int64 silk_inner_prod16_aligned_64_sse4_1( + const opus_int16 *inVec1, /* I input vector 1 */ + const opus_int16 *inVec2, /* I input vector 2 */ + const opus_int len /* I vector lengths */ +) +{ + opus_int i, dataSize8; + opus_int64 sum; + + __m128i xmm_tempa; + __m128i inVec1_76543210, acc1; + __m128i inVec2_76543210, acc2; + + sum = 0; + dataSize8 = len & ~7; + + acc1 = _mm_setzero_si128(); + acc2 = _mm_setzero_si128(); + + for( i = 0; i < dataSize8; i += 8 ) { + inVec1_76543210 = _mm_loadu_si128( (__m128i *)(&inVec1[i + 0] ) ); + inVec2_76543210 = _mm_loadu_si128( (__m128i *)(&inVec2[i + 0] ) ); + + /* only when all 4 operands are -32768 (0x8000), this results in wrap around */ + inVec1_76543210 = _mm_madd_epi16( inVec1_76543210, inVec2_76543210 ); + + xmm_tempa = _mm_cvtepi32_epi64( inVec1_76543210 ); + /* equal shift right 8 bytes */ + inVec1_76543210 = _mm_shuffle_epi32( inVec1_76543210, _MM_SHUFFLE( 0, 0, 3, 2 ) ); + inVec1_76543210 = _mm_cvtepi32_epi64( inVec1_76543210 ); + + acc1 = _mm_add_epi64( acc1, xmm_tempa ); + acc2 = _mm_add_epi64( acc2, inVec1_76543210 ); + } + + acc1 = _mm_add_epi64( acc1, acc2 ); + + /* equal shift right 8 bytes */ + acc2 = _mm_shuffle_epi32( acc1, _MM_SHUFFLE( 0, 0, 3, 2 ) ); + acc1 = _mm_add_epi64( acc1, acc2 ); + + _mm_storel_epi64( (__m128i *)&sum, acc1 ); + + for( ; i < len; i++ ) { + sum = silk_SMLABB( sum, inVec1[ i ], inVec2[ i ] ); + } + + return sum; +} diff --git a/thirdparty/opus/silk/float/LPC_analysis_filter_FLP.c b/thirdparty/opus/silk/float/LPC_analysis_filter_FLP.c new file mode 100644 index 0000000000..cae89a0a18 --- /dev/null +++ b/thirdparty/opus/silk/float/LPC_analysis_filter_FLP.c @@ -0,0 +1,249 @@ +/*********************************************************************** +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 */ +) +{ + silk_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: + silk_assert( 0 ); + break; + } + + /* Set first Order output samples to zero */ + silk_memset( r_LPC, 0, Order * sizeof( silk_float ) ); +} + diff --git a/thirdparty/opus/silk/float/LPC_inv_pred_gain_FLP.c b/thirdparty/opus/silk/float/LPC_inv_pred_gain_FLP.c new file mode 100644 index 0000000000..25178bacdd --- /dev/null +++ b/thirdparty/opus/silk/float/LPC_inv_pred_gain_FLP.c @@ -0,0 +1,76 @@ +/*********************************************************************** +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" + +#define RC_THRESHOLD 0.9999f + +/* 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; + silk_float Atmp[ 2 ][ SILK_MAX_ORDER_LPC ]; + silk_float *Aold, *Anew; + + Anew = Atmp[ order & 1 ]; + silk_memcpy( Anew, A, order * sizeof(silk_float) ); + + invGain = 1.0; + for( k = order - 1; k > 0; k-- ) { + rc = -Anew[ k ]; + if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) { + return 0.0f; + } + rc_mult1 = 1.0f - rc * rc; + rc_mult2 = 1.0f / rc_mult1; + invGain *= rc_mult1; + /* swap pointers */ + Aold = Anew; + Anew = Atmp[ k & 1 ]; + for( n = 0; n < k; n++ ) { + Anew[ n ] = (silk_float)( ( Aold[ n ] - Aold[ k - n - 1 ] * rc ) * rc_mult2 ); + } + } + rc = -Anew[ 0 ]; + if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) { + return 0.0f; + } + rc_mult1 = 1.0f - rc * rc; + invGain *= rc_mult1; + return (silk_float)invGain; +} diff --git a/thirdparty/opus/silk/float/LTP_analysis_filter_FLP.c b/thirdparty/opus/silk/float/LTP_analysis_filter_FLP.c new file mode 100644 index 0000000000..849b7c1c52 --- /dev/null +++ b/thirdparty/opus/silk/float/LTP_analysis_filter_FLP.c @@ -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/thirdparty/opus/silk/float/LTP_scale_ctrl_FLP.c b/thirdparty/opus/silk/float/LTP_scale_ctrl_FLP.c new file mode 100644 index 0000000000..8dbe29d0fa --- /dev/null +++ b/thirdparty/opus/silk/float/LTP_scale_ctrl_FLP.c @@ -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. +***********************************************************************/ + +#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; + psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( round_loss * psEncCtrl->LTPredCodGain * 0.1f, 0.0f, 2.0f ); + } 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/thirdparty/opus/silk/float/SigProc_FLP.h b/thirdparty/opus/silk/float/SigProc_FLP.h new file mode 100644 index 0000000000..f0cb3733be --- /dev/null +++ b/thirdparty/opus/silk/float/SigProc_FLP.h @@ -0,0 +1,204 @@ +/*********************************************************************** +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 <math.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +/********************************************************************/ +/* 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 */ +); + +/* Solve the normal equations using the Levinson-Durbin recursion */ +silk_float silk_levinsondurbin_FLP( /* O prediction error energy */ + silk_float A[], /* O prediction coefficients [order] */ + const silk_float corr[], /* I input auto-correlations [order + 1] */ + const opus_int 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 */ +); + +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 */ +); + +/* 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( + const silk_float *data1, + const silk_float *data2, + opus_int dataSize +); + +/* 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 ) ); +} + +#ifdef __cplusplus +} +#endif + +#endif /* SILK_SIGPROC_FLP_H */ diff --git a/thirdparty/opus/silk/float/apply_sine_window_FLP.c b/thirdparty/opus/silk/float/apply_sine_window_FLP.c new file mode 100644 index 0000000000..6aae57c0ab --- /dev/null +++ b/thirdparty/opus/silk/float/apply_sine_window_FLP.c @@ -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; + + silk_assert( win_type == 1 || win_type == 2 ); + + /* Length must be multiple of 4 */ + silk_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/thirdparty/opus/silk/float/autocorrelation_FLP.c b/thirdparty/opus/silk/float/autocorrelation_FLP.c new file mode 100644 index 0000000000..8b8a9e659a --- /dev/null +++ b/thirdparty/opus/silk/float/autocorrelation_FLP.c @@ -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. +***********************************************************************/ + +#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 */ +) +{ + 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 ); + } +} diff --git a/thirdparty/opus/silk/float/burg_modified_FLP.c b/thirdparty/opus/silk/float/burg_modified_FLP.c new file mode 100644 index 0000000000..ea5dc25a93 --- /dev/null +++ b/thirdparty/opus/silk/float/burg_modified_FLP.c @@ -0,0 +1,186 @@ +/*********************************************************************** +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 */ +) +{ + 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 ]; + + silk_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 ); + } + } + 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/thirdparty/opus/silk/float/bwexpander_FLP.c b/thirdparty/opus/silk/float/bwexpander_FLP.c new file mode 100644 index 0000000000..d55a4d79ab --- /dev/null +++ b/thirdparty/opus/silk/float/bwexpander_FLP.c @@ -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/thirdparty/opus/silk/float/corrMatrix_FLP.c b/thirdparty/opus/silk/float/corrMatrix_FLP.c new file mode 100644 index 0000000000..eae6a1cfca --- /dev/null +++ b/thirdparty/opus/silk/float/corrMatrix_FLP.c @@ -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 + +/********************************************************************** + * 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] */ +) +{ + 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 ); + 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] */ +) +{ + 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 ); + 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/thirdparty/opus/silk/float/encode_frame_FLP.c b/thirdparty/opus/silk/float/encode_frame_FLP.c new file mode 100644 index 0000000000..2092a4d9e2 --- /dev/null +++ b/thirdparty/opus/silk/float/encode_frame_FLP.c @@ -0,0 +1,372 @@ +/*********************************************************************** +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" + +/* 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 */ +) +{ + /****************************/ + /* Voice Activity Detection */ + /****************************/ + silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch ); + + /**************************************************/ + /* Convert speech activity into VAD and DTX flags */ + /**************************************************/ + if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) { + 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 xfw[ MAX_FRAME_LENGTH ]; + silk_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ]; + ec_enc sRangeEnc_copy, sRangeEnc_copy2; + silk_nsq_state sNSQ_copy, sNSQ_copy2; + 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_uint8 ec_buf_copy[ 1275 ]; + + /* 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 ) { + /*****************************************/ + /* 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, x_frame, condCoding ); + + /****************************************/ + /* Process gains */ + /****************************************/ + silk_process_gains_FLP( psEnc, &sEncCtrl, condCoding ); + + /*****************************************/ + /* Prefiltering for noise shaper */ + /*****************************************/ + silk_prefilter_FLP( psEnc, &sEncCtrl, xfw, x_frame ); + + /****************************************/ + /* Low Bitrate Redundant Encoding */ + /****************************************/ + silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, 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, &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; + 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, 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, xfw ); + + /****************************************/ + /* 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( 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 ) ); + silk_assert( sRangeEnc_copy2.offs <= 1275 ); + silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs ); + silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, 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 *= 1.5f; + found_upper = 0; + gainsID_upper = -1; + } else { + found_upper = 1; + nBits_upper = nBits; + gainMult_upper = gainMult_Q8; + gainsID_upper = gainsID; + } + } else if( nBits < maxBits - 5 ) { + 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 ) ); + silk_assert( psRangeEnc->offs <= 1275 ); + silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs ); + silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); + LastGainIndex_copy2 = psEnc->sShape.LastGainIndex; + } + } else { + /* Within 5 bits of budget: close enough */ + break; + } + + if( ( found_lower & found_upper ) == 0 ) { + /* Adjust gain according to high-rate rate/distortion curve */ + opus_int32 gain_factor_Q16; + gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) ); + gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) ); + if( nBits > maxBits ) { + gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) ); + } + gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 ); + } else { + /* Adjust gain by interpolating */ + gainMult_Q8 = gainMult_lower + ( ( gainMult_upper - gainMult_lower ) * ( maxBits - nBits_lower ) ) / ( nBits_upper - nBits_lower ); + /* New gain multplier 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++ ) { + pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 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; + 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 ); + + 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 ]; + silk_nsq_state sNSQ_LBRR; + + /*******************************************/ + /* Control use of inband LBRR */ + /*******************************************/ + if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { + psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1; + + /* Copy noise shaping quantizer state and quantization indices from regular encoding */ + silk_memcpy( &sNSQ_LBRR, &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, + psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], xfw ); + + /* Restore original gains */ + silk_memcpy( psEncCtrl->Gains, TempGains, psEnc->sCmn.nb_subfr * sizeof( silk_float ) ); + } +} diff --git a/thirdparty/opus/silk/float/energy_FLP.c b/thirdparty/opus/silk/float/energy_FLP.c new file mode 100644 index 0000000000..24b8179f9e --- /dev/null +++ b/thirdparty/opus/silk/float/energy_FLP.c @@ -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. +***********************************************************************/ + +#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, dataSize4; + double result; + + /* 4x unrolled loop */ + result = 0.0; + dataSize4 = dataSize & 0xFFFC; + for( i = 0; i < dataSize4; 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/thirdparty/opus/silk/float/find_LPC_FLP.c b/thirdparty/opus/silk/float/find_LPC_FLP.c new file mode 100644 index 0000000000..fcfe1c3681 --- /dev/null +++ b/thirdparty/opus/silk/float/find_LPC_FLP.c @@ -0,0 +1,104 @@ +/*********************************************************************** +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 */ +) +{ + 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 ); + + 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 ); + + /* 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 ); + + /* 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 ); + } + + silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || + ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) ); +} diff --git a/thirdparty/opus/silk/float/find_LTP_FLP.c b/thirdparty/opus/silk/float/find_LTP_FLP.c new file mode 100644 index 0000000000..7229996014 --- /dev/null +++ b/thirdparty/opus/silk/float/find_LTP_FLP.c @@ -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 "main_FLP.h" +#include "tuning_parameters.h" + +void silk_find_LTP_FLP( + silk_float b[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ + silk_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ + silk_float *LTPredCodGain, /* O LTP coding gain */ + const silk_float r_lpc[], /* I LPC residual */ + const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ + const silk_float Wght[ MAX_NB_SUBFR ], /* I Weights */ + const opus_int subfr_length, /* I Subframe length */ + const opus_int nb_subfr, /* I number of subframes */ + const opus_int mem_offset /* I Number of samples in LTP memory */ +) +{ + opus_int i, k; + silk_float *b_ptr, temp, *WLTP_ptr; + silk_float LPC_res_nrg, LPC_LTP_res_nrg; + silk_float d[ MAX_NB_SUBFR ], m, g, delta_b[ LTP_ORDER ]; + silk_float w[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], regu; + silk_float Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ]; + const silk_float *r_ptr, *lag_ptr; + + b_ptr = b; + WLTP_ptr = WLTP; + r_ptr = &r_lpc[ mem_offset ]; + 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, WLTP_ptr ); + silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr ); + + rr[ k ] = ( silk_float )silk_energy_FLP( r_ptr, subfr_length ); + regu = 1.0f + rr[ k ] + + matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ) + + matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ); + regu *= LTP_DAMPING / 3; + silk_regularize_correlations_FLP( WLTP_ptr, &rr[ k ], regu, LTP_ORDER ); + silk_solve_LDL_FLP( WLTP_ptr, LTP_ORDER, Rr, b_ptr ); + + /* Calculate residual energy */ + nrg[ k ] = silk_residual_energy_covar_FLP( b_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER ); + + temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); + silk_scale_vector_FLP( WLTP_ptr, temp, LTP_ORDER * LTP_ORDER ); + w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER / 2, LTP_ORDER / 2, LTP_ORDER ); + + r_ptr += subfr_length; + b_ptr += LTP_ORDER; + WLTP_ptr += LTP_ORDER * LTP_ORDER; + } + + /* Compute LTP coding gain */ + if( LTPredCodGain != NULL ) { + LPC_LTP_res_nrg = 1e-6f; + LPC_res_nrg = 0.0f; + for( k = 0; k < nb_subfr; k++ ) { + LPC_res_nrg += rr[ k ] * Wght[ k ]; + LPC_LTP_res_nrg += nrg[ k ] * Wght[ k ]; + } + + silk_assert( LPC_LTP_res_nrg > 0 ); + *LTPredCodGain = 3.0f * silk_log2( LPC_res_nrg / LPC_LTP_res_nrg ); + } + + /* Smoothing */ + /* d = sum( B, 1 ); */ + b_ptr = b; + for( k = 0; k < nb_subfr; k++ ) { + d[ k ] = 0; + for( i = 0; i < LTP_ORDER; i++ ) { + d[ k ] += b_ptr[ i ]; + } + b_ptr += LTP_ORDER; + } + /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */ + temp = 1e-3f; + for( k = 0; k < nb_subfr; k++ ) { + temp += w[ k ]; + } + m = 0; + for( k = 0; k < nb_subfr; k++ ) { + m += d[ k ] * w[ k ]; + } + m = m / temp; + + b_ptr = b; + for( k = 0; k < nb_subfr; k++ ) { + g = LTP_SMOOTHING / ( LTP_SMOOTHING + w[ k ] ) * ( m - d[ k ] ); + temp = 0; + for( i = 0; i < LTP_ORDER; i++ ) { + delta_b[ i ] = silk_max_float( b_ptr[ i ], 0.1f ); + temp += delta_b[ i ]; + } + temp = g / temp; + for( i = 0; i < LTP_ORDER; i++ ) { + b_ptr[ i ] = b_ptr[ i ] + delta_b[ i ] * temp; + } + b_ptr += LTP_ORDER; + } +} diff --git a/thirdparty/opus/silk/float/find_pitch_lags_FLP.c b/thirdparty/opus/silk/float/find_pitch_lags_FLP.c new file mode 100644 index 0000000000..f3b22d25ce --- /dev/null +++ b/thirdparty/opus/silk/float/find_pitch_lags_FLP.c @@ -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 */ + silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length ); + + x_buf = x - psEnc->sCmn.ltp_mem_length; + + /******************************************/ + /* Estimate LPC AR coeficients */ + /******************************************/ + + /* 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 ); + + /* 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/thirdparty/opus/silk/float/find_pred_coefs_FLP.c b/thirdparty/opus/silk/float/find_pred_coefs_FLP.c new file mode 100644 index 0000000000..1af4fe5f1b --- /dev/null +++ b/thirdparty/opus/silk/float/find_pred_coefs_FLP.c @@ -0,0 +1,118 @@ +/*********************************************************************** +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 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ]; + silk_float invGains[ MAX_NB_SUBFR ], Wght[ MAX_NB_SUBFR ]; + opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; + 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 ]; + Wght[ i ] = invGains[ i ] * invGains[ i ]; + } + + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /**********/ + /* VOICED */ + /**********/ + silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 ); + + /* LTP analysis */ + silk_find_LTP_FLP( psEncCtrl->LTPCoef, WLTP, &psEncCtrl->LTPredCodGain, res_pitch, + psEncCtrl->pitchL, Wght, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length ); + + /* 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, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, 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 ); + + /* 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/thirdparty/opus/silk/float/inner_product_FLP.c b/thirdparty/opus/silk/float/inner_product_FLP.c new file mode 100644 index 0000000000..029c012911 --- /dev/null +++ b/thirdparty/opus/silk/float/inner_product_FLP.c @@ -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. +***********************************************************************/ + +#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( + const silk_float *data1, + const silk_float *data2, + opus_int dataSize +) +{ + opus_int i, dataSize4; + double result; + + /* 4x unrolled loop */ + result = 0.0; + dataSize4 = dataSize & 0xFFFC; + for( i = 0; i < dataSize4; 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/thirdparty/opus/silk/float/k2a_FLP.c b/thirdparty/opus/silk/float/k2a_FLP.c new file mode 100644 index 0000000000..12af4e7669 --- /dev/null +++ b/thirdparty/opus/silk/float/k2a_FLP.c @@ -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 "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 Atmp[ SILK_MAX_ORDER_LPC ]; + + for( k = 0; k < order; k++ ) { + for( n = 0; n < k; n++ ) { + Atmp[ n ] = A[ n ]; + } + for( n = 0; n < k; n++ ) { + A[ n ] += Atmp[ k - n - 1 ] * rc[ k ]; + } + A[ k ] = -rc[ k ]; + } +} diff --git a/thirdparty/opus/silk/float/levinsondurbin_FLP.c b/thirdparty/opus/silk/float/levinsondurbin_FLP.c new file mode 100644 index 0000000000..f0ba606981 --- /dev/null +++ b/thirdparty/opus/silk/float/levinsondurbin_FLP.c @@ -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 "SigProc_FLP.h" + +/* Solve the normal equations using the Levinson-Durbin recursion */ +silk_float silk_levinsondurbin_FLP( /* O prediction error energy */ + silk_float A[], /* O prediction coefficients [order] */ + const silk_float corr[], /* I input auto-correlations [order + 1] */ + const opus_int order /* I prediction order */ +) +{ + opus_int i, mHalf, m; + silk_float min_nrg, nrg, t, km, Atmp1, Atmp2; + + min_nrg = 1e-12f * corr[ 0 ] + 1e-9f; + nrg = corr[ 0 ]; + nrg = silk_max_float(min_nrg, nrg); + A[ 0 ] = corr[ 1 ] / nrg; + nrg -= A[ 0 ] * corr[ 1 ]; + nrg = silk_max_float(min_nrg, nrg); + + for( m = 1; m < order; m++ ) + { + t = corr[ m + 1 ]; + for( i = 0; i < m; i++ ) { + t -= A[ i ] * corr[ m - i ]; + } + + /* reflection coefficient */ + km = t / nrg; + + /* residual energy */ + nrg -= km * t; + nrg = silk_max_float(min_nrg, nrg); + + mHalf = m >> 1; + for( i = 0; i < mHalf; i++ ) { + Atmp1 = A[ i ]; + Atmp2 = A[ m - i - 1 ]; + A[ m - i - 1 ] -= km * Atmp1; + A[ i ] -= km * Atmp2; + } + if( m & 1 ) { + A[ mHalf ] -= km * A[ mHalf ]; + } + A[ m ] = km; + } + + /* return the residual energy */ + return nrg; +} + diff --git a/thirdparty/opus/silk/float/main_FLP.h b/thirdparty/opus/silk/float/main_FLP.h new file mode 100644 index 0000000000..e5a75972e5 --- /dev/null +++ b/thirdparty/opus/silk/float/main_FLP.h @@ -0,0 +1,313 @@ +/*********************************************************************** +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" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#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 */ +); + +/* 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_int32 TargetRate_bps, /* I Target max bitrate (bps) */ + 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 +); + +/****************/ +/* Prefiltering */ +/****************/ +void silk_prefilter_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + const silk_encoder_control_FLP *psEncCtrl, /* I Encoder control FLP */ + silk_float xw[], /* O Weighted signal */ + const silk_float x[] /* I Speech signal */ +); + +/**************************/ +/* 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) */ +); + +/* LTP analysis */ +void silk_find_LTP_FLP( + silk_float b[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ + silk_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ + silk_float *LTPredCodGain, /* O LTP coding gain */ + const silk_float r_lpc[], /* I LPC residual */ + const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ + const silk_float Wght[ MAX_NB_SUBFR ], /* I Weights */ + const opus_int subfr_length, /* I Subframe length */ + const opus_int nb_subfr, /* I number of subframes */ + const opus_int mem_offset /* I Number of samples in LTP memory */ +); + +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 ], /* I/O (Un-)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 */ + const silk_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */ + const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */ + const opus_int lowComplexity, /* I Flag for low complexity */ + 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] */ +); + +/* 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] */ +); + +/* 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 */ +); + +/* Function to solve linear equation Ax = b, where A is an MxM symmetric matrix */ +void silk_solve_LDL_FLP( + silk_float *A, /* I/O Symmetric square matrix, out: reg. */ + const opus_int M, /* I Size of matrix */ + const silk_float *b, /* I Pointer to b vector */ + silk_float *x /* O Pointer to x solution vector */ +); + +/* 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 */ +); + +/* 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 */ +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/opus/silk/float/noise_shape_analysis_FLP.c b/thirdparty/opus/silk/float/noise_shape_analysis_FLP.c new file mode 100644 index 0000000000..65f6ea5870 --- /dev/null +++ b/thirdparty/opus/silk/float/noise_shape_analysis_FLP.c @@ -0,0 +1,365 @@ +/*********************************************************************** +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_syn, + silk_float *coefs_ana, + silk_float lambda, + silk_float limit, + opus_int order +) { + opus_int i, iter, ind = 0; + silk_float tmp, maxabs, chirp, gain_syn, gain_ana; + + /* Convert to monic coefficients */ + for( i = order - 1; i > 0; i-- ) { + coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ]; + coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ]; + } + gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] ); + gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] ); + for( i = 0; i < order; i++ ) { + coefs_syn[ i ] *= gain_syn; + coefs_ana[ i ] *= gain_ana; + } + + /* Limit */ + for( iter = 0; iter < 10; iter++ ) { + /* Find maximum absolute value */ + maxabs = -1.0f; + for( i = 0; i < order; i++ ) { + tmp = silk_max( silk_abs_float( coefs_syn[ i ] ), silk_abs_float( coefs_ana[ 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_syn[ i - 1 ] += lambda * coefs_syn[ i ]; + coefs_ana[ i - 1 ] += lambda * coefs_ana[ i ]; + } + gain_syn = 1.0f / gain_syn; + gain_ana = 1.0f / gain_ana; + for( i = 0; i < order; i++ ) { + coefs_syn[ i ] *= gain_syn; + coefs_ana[ i ] *= gain_ana; + } + + /* Apply bandwidth expansion */ + chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) ); + silk_bwexpander_FLP( coefs_syn, order, chirp ); + silk_bwexpander_FLP( coefs_ana, order, chirp ); + + /* Convert to monic warped coefficients */ + for( i = order - 1; i > 0; i-- ) { + coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ]; + coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ]; + } + gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] ); + gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] ); + for( i = 0; i < order; i++ ) { + coefs_syn[ i ] *= gain_syn; + coefs_ana[ i ] *= gain_ana; + } + } + 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; + silk_float SNR_adj_dB, HarmBoost, HarmShapeGain, Tilt; + silk_float nrg, pre_nrg, log_energy, log_energy_prev, energy_variation; + silk_float delta, BWExp1, BWExp2, gain_mult, gain_add, strength, b, warping; + silk_float x_windowed[ SHAPE_LPC_WIN_MAX ]; + silk_float auto_corr[ 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; + psEncCtrl->sparseness = 0.0f; + } 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; + for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; 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; + } + psEncCtrl->sparseness = silk_sigmoid( 0.4f * ( energy_variation - 5.0f ) ); + + /* Set quantization offset depending on sparseness measure */ + if( psEncCtrl->sparseness > SPARSENESS_THRESHOLD_QNT_OFFSET ) { + psEnc->sCmn.indices.quantOffsetType = 0; + } else { + psEnc->sCmn.indices.quantOffsetType = 1; + } + + /* Increase coding SNR for sparse signals */ + SNR_adj_dB += SPARSE_SNR_INCR_dB * ( psEncCtrl->sparseness - 0.5f ); + } + + /*******************************/ + /* 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 */ + BWExp1 = BWExp2 = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength ); + delta = LOW_RATE_BANDWIDTH_EXPANSION_DELTA * ( 1.0f - 0.75f * psEncCtrl->coding_quality ); + BWExp1 -= delta; + BWExp2 += delta; + /* BWExp1 will be applied after BWExp2, so make it relative */ + BWExp1 /= BWExp2; + + if( psEnc->sCmn.warping_Q16 > 0 ) { + /* 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; + } else { + warping = 0.0f; + } + + /********************************************/ + /* 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 ); + } + + /* Add white noise, as a fraction of energy */ + auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION; + + /* Convert correlations to prediction coefficients, and compute residual energy */ + nrg = silk_levinsondurbin_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], auto_corr, 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->AR2[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder ); + } + + /* Bandwidth expansion for synthesis filter shaping */ + silk_bwexpander_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp2 ); + + /* Compute noise shaping filter coefficients */ + silk_memcpy( + &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], + &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], + psEnc->sCmn.shapingLPCOrder * sizeof( silk_float ) ); + + /* Bandwidth expansion for analysis filter shaping */ + silk_bwexpander_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp1 ); + + /* Ratio of prediction gains, in energy domain */ + pre_nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder ); + nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder ); + psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ); + + /* Convert to monic warped prediction coefficients and limit absolute values */ + warped_true2monic_coefs( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], + warping, 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; + } + + gain_mult = 1.0f + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT; + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->GainsPre[ k ] *= gain_mult; + } + + /************************************************/ + /* 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 */ + /****************************/ + /* Control boosting of harmonic frequencies */ + HarmBoost = LOW_RATE_HARMONIC_BOOST * ( 1.0f - psEncCtrl->coding_quality ) * psEnc->LTPCorr; + + /* More harmonic boost for noisy input signals */ + HarmBoost += LOW_INPUT_QUALITY_HARMONIC_BOOST * ( 1.0f - psEncCtrl->input_quality ); + + 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->HarmBoost_smth += SUBFR_SMTH_COEF * ( HarmBoost - psShapeSt->HarmBoost_smth ); + psEncCtrl->HarmBoost[ k ] = psShapeSt->HarmBoost_smth; + 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/thirdparty/opus/silk/float/pitch_analysis_core_FLP.c b/thirdparty/opus/silk/float/pitch_analysis_core_FLP.c new file mode 100644 index 0000000000..d0e637a29d --- /dev/null +++ b/thirdparty/opus/silk/float/pitch_analysis_core_FLP.c @@ -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 */ + silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 ); + + /* Check for valid complexity setting */ + silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); + silk_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 { + silk_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 ] += 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 */ + silk_assert( target_ptr >= frame_4kHz ); + silk_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 */ + silk_assert( basis_ptr >= frame_4kHz ); + silk_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; + silk_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; + } + } + silk_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 ); + 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; + } + silk_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; + + silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); + silk_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 { + silk_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; + + silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); + silk_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 { + silk_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/thirdparty/opus/silk/float/prefilter_FLP.c b/thirdparty/opus/silk/float/prefilter_FLP.c new file mode 100644 index 0000000000..8bc32fb410 --- /dev/null +++ b/thirdparty/opus/silk/float/prefilter_FLP.c @@ -0,0 +1,206 @@ +/*********************************************************************** +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" + +/* +* Prefilter for finding Quantizer input signal +*/ +static OPUS_INLINE void silk_prefilt_FLP( + silk_prefilter_state_FLP *P, /* I/O state */ + silk_float st_res[], /* I */ + silk_float xw[], /* O */ + silk_float *HarmShapeFIR, /* I */ + silk_float Tilt, /* I */ + silk_float LF_MA_shp, /* I */ + silk_float LF_AR_shp, /* I */ + opus_int lag, /* I */ + opus_int length /* I */ +); + +static void silk_warped_LPC_analysis_filter_FLP( + silk_float state[], /* I/O State [order + 1] */ + silk_float res[], /* O Residual signal [length] */ + const silk_float coef[], /* I Coefficients [order] */ + const silk_float input[], /* I Input signal [length] */ + const silk_float lambda, /* I Warping factor */ + const opus_int length, /* I Length of input signal */ + const opus_int order /* I Filter order (even) */ +) +{ + opus_int n, i; + silk_float acc, tmp1, tmp2; + + /* Order must be even */ + silk_assert( ( order & 1 ) == 0 ); + + for( n = 0; n < length; n++ ) { + /* Output of lowpass section */ + tmp2 = state[ 0 ] + lambda * state[ 1 ]; + state[ 0 ] = input[ n ]; + /* Output of allpass section */ + tmp1 = state[ 1 ] + lambda * ( state[ 2 ] - tmp2 ); + state[ 1 ] = tmp2; + acc = coef[ 0 ] * tmp2; + /* Loop over allpass sections */ + for( i = 2; i < order; i += 2 ) { + /* Output of allpass section */ + tmp2 = state[ i ] + lambda * ( state[ i + 1 ] - tmp1 ); + state[ i ] = tmp1; + acc += coef[ i - 1 ] * tmp1; + /* Output of allpass section */ + tmp1 = state[ i + 1 ] + lambda * ( state[ i + 2 ] - tmp2 ); + state[ i + 1 ] = tmp2; + acc += coef[ i ] * tmp2; + } + state[ order ] = tmp1; + acc += coef[ order - 1 ] * tmp1; + res[ n ] = input[ n ] - acc; + } +} + +/* +* silk_prefilter. Main prefilter function +*/ +void silk_prefilter_FLP( + silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ + const silk_encoder_control_FLP *psEncCtrl, /* I Encoder control FLP */ + silk_float xw[], /* O Weighted signal */ + const silk_float x[] /* I Speech signal */ +) +{ + silk_prefilter_state_FLP *P = &psEnc->sPrefilt; + opus_int j, k, lag; + silk_float HarmShapeGain, Tilt, LF_MA_shp, LF_AR_shp; + silk_float B[ 2 ]; + const silk_float *AR1_shp; + const silk_float *px; + silk_float *pxw; + silk_float HarmShapeFIR[ 3 ]; + silk_float st_res[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ]; + + /* Set up pointers */ + px = x; + pxw = xw; + lag = P->lagPrev; + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + /* Update Variables that change per sub frame */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + lag = psEncCtrl->pitchL[ k ]; + } + + /* Noise shape parameters */ + HarmShapeGain = psEncCtrl->HarmShapeGain[ k ] * ( 1.0f - psEncCtrl->HarmBoost[ k ] ); + HarmShapeFIR[ 0 ] = 0.25f * HarmShapeGain; + HarmShapeFIR[ 1 ] = 32767.0f / 65536.0f * HarmShapeGain; + HarmShapeFIR[ 2 ] = 0.25f * HarmShapeGain; + Tilt = psEncCtrl->Tilt[ k ]; + LF_MA_shp = psEncCtrl->LF_MA_shp[ k ]; + LF_AR_shp = psEncCtrl->LF_AR_shp[ k ]; + AR1_shp = &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ]; + + /* Short term FIR filtering */ + silk_warped_LPC_analysis_filter_FLP( P->sAR_shp, st_res, AR1_shp, px, + (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder ); + + /* Reduce (mainly) low frequencies during harmonic emphasis */ + B[ 0 ] = psEncCtrl->GainsPre[ k ]; + B[ 1 ] = -psEncCtrl->GainsPre[ k ] * + ( psEncCtrl->HarmBoost[ k ] * HarmShapeGain + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT ); + pxw[ 0 ] = B[ 0 ] * st_res[ 0 ] + B[ 1 ] * P->sHarmHP; + for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { + pxw[ j ] = B[ 0 ] * st_res[ j ] + B[ 1 ] * st_res[ j - 1 ]; + } + P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ]; + + silk_prefilt_FLP( P, pxw, pxw, HarmShapeFIR, Tilt, LF_MA_shp, LF_AR_shp, lag, psEnc->sCmn.subfr_length ); + + px += psEnc->sCmn.subfr_length; + pxw += psEnc->sCmn.subfr_length; + } + P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ]; +} + +/* +* Prefilter for finding Quantizer input signal +*/ +static OPUS_INLINE void silk_prefilt_FLP( + silk_prefilter_state_FLP *P, /* I/O state */ + silk_float st_res[], /* I */ + silk_float xw[], /* O */ + silk_float *HarmShapeFIR, /* I */ + silk_float Tilt, /* I */ + silk_float LF_MA_shp, /* I */ + silk_float LF_AR_shp, /* I */ + opus_int lag, /* I */ + opus_int length /* I */ +) +{ + opus_int i; + opus_int idx, LTP_shp_buf_idx; + silk_float n_Tilt, n_LF, n_LTP; + silk_float sLF_AR_shp, sLF_MA_shp; + silk_float *LTP_shp_buf; + + /* To speed up use temp variables instead of using the struct */ + LTP_shp_buf = P->sLTP_shp; + LTP_shp_buf_idx = P->sLTP_shp_buf_idx; + sLF_AR_shp = P->sLF_AR_shp; + sLF_MA_shp = P->sLF_MA_shp; + + for( i = 0; i < length; i++ ) { + if( lag > 0 ) { + silk_assert( HARM_SHAPE_FIR_TAPS == 3 ); + idx = lag + LTP_shp_buf_idx; + n_LTP = LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ] * HarmShapeFIR[ 0 ]; + n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ] * HarmShapeFIR[ 1 ]; + n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ] * HarmShapeFIR[ 2 ]; + } else { + n_LTP = 0; + } + + n_Tilt = sLF_AR_shp * Tilt; + n_LF = sLF_AR_shp * LF_AR_shp + sLF_MA_shp * LF_MA_shp; + + sLF_AR_shp = st_res[ i ] - n_Tilt; + sLF_MA_shp = sLF_AR_shp - n_LF; + + LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; + LTP_shp_buf[ LTP_shp_buf_idx ] = sLF_MA_shp; + + xw[ i ] = sLF_MA_shp - n_LTP; + } + /* Copy temp variable back to state */ + P->sLF_AR_shp = sLF_AR_shp; + P->sLF_MA_shp = sLF_MA_shp; + P->sLTP_shp_buf_idx = LTP_shp_buf_idx; +} diff --git a/thirdparty/opus/silk/float/process_gains_FLP.c b/thirdparty/opus/silk/float/process_gains_FLP.c new file mode 100644 index 0000000000..c0da0dae44 --- /dev/null +++ b/thirdparty/opus/silk/float/process_gains_FLP.c @@ -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/thirdparty/opus/silk/float/regularize_correlations_FLP.c b/thirdparty/opus/silk/float/regularize_correlations_FLP.c new file mode 100644 index 0000000000..df4612604c --- /dev/null +++ b/thirdparty/opus/silk/float/regularize_correlations_FLP.c @@ -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/thirdparty/opus/silk/float/residual_energy_FLP.c b/thirdparty/opus/silk/float/residual_energy_FLP.c new file mode 100644 index 0000000000..b2e03a86a4 --- /dev/null +++ b/thirdparty/opus/silk/float/residual_energy_FLP.c @@ -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 */ + silk_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/thirdparty/opus/silk/float/scale_copy_vector_FLP.c b/thirdparty/opus/silk/float/scale_copy_vector_FLP.c new file mode 100644 index 0000000000..20db32b3b1 --- /dev/null +++ b/thirdparty/opus/silk/float/scale_copy_vector_FLP.c @@ -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/thirdparty/opus/silk/float/scale_vector_FLP.c b/thirdparty/opus/silk/float/scale_vector_FLP.c new file mode 100644 index 0000000000..108fdcbed5 --- /dev/null +++ b/thirdparty/opus/silk/float/scale_vector_FLP.c @@ -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/thirdparty/opus/silk/float/schur_FLP.c b/thirdparty/opus/silk/float/schur_FLP.c new file mode 100644 index 0000000000..ee436f8351 --- /dev/null +++ b/thirdparty/opus/silk/float/schur_FLP.c @@ -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; + silk_float C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; + silk_float Ctmp1, Ctmp2, rc_tmp; + + silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 ); + + /* Copy correlations */ + for( k = 0; k < order+1; k++ ) { + C[ k ][ 0 ] = C[ k ][ 1 ] = auto_corr[ k ]; + } + + 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 ] = 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 C[ 0 ][ 1 ]; +} + diff --git a/thirdparty/opus/silk/float/solve_LS_FLP.c b/thirdparty/opus/silk/float/solve_LS_FLP.c new file mode 100644 index 0000000000..7c90d665a0 --- /dev/null +++ b/thirdparty/opus/silk/float/solve_LS_FLP.c @@ -0,0 +1,207 @@ +/*********************************************************************** +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" + +/********************************************************************** + * LDL Factorisation. Finds the upper triangular matrix L and the diagonal + * Matrix D (only the diagonal elements returned in a vector)such that + * the symmetric matric A is given by A = L*D*L'. + **********************************************************************/ +static OPUS_INLINE void silk_LDL_FLP( + silk_float *A, /* I/O Pointer to Symetric Square Matrix */ + opus_int M, /* I Size of Matrix */ + silk_float *L, /* I/O Pointer to Square Upper triangular Matrix */ + silk_float *Dinv /* I/O Pointer to vector holding the inverse diagonal elements of D */ +); + +/********************************************************************** + * Function to solve linear equation Ax = b, when A is a MxM lower + * triangular matrix, with ones on the diagonal. + **********************************************************************/ +static OPUS_INLINE void silk_SolveWithLowerTriangularWdiagOnes_FLP( + const silk_float *L, /* I Pointer to Lower Triangular Matrix */ + opus_int M, /* I Dim of Matrix equation */ + const silk_float *b, /* I b Vector */ + silk_float *x /* O x Vector */ +); + +/********************************************************************** + * Function to solve linear equation (A^T)x = b, when A is a MxM lower + * triangular, with ones on the diagonal. (ie then A^T is upper triangular) + **********************************************************************/ +static OPUS_INLINE void silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( + const silk_float *L, /* I Pointer to Lower Triangular Matrix */ + opus_int M, /* I Dim of Matrix equation */ + const silk_float *b, /* I b Vector */ + silk_float *x /* O x Vector */ +); + +/********************************************************************** + * Function to solve linear equation Ax = b, when A is a MxM + * symmetric square matrix - using LDL factorisation + **********************************************************************/ +void silk_solve_LDL_FLP( + silk_float *A, /* I/O Symmetric square matrix, out: reg. */ + const opus_int M, /* I Size of matrix */ + const silk_float *b, /* I Pointer to b vector */ + silk_float *x /* O Pointer to x solution vector */ +) +{ + opus_int i; + silk_float L[ MAX_MATRIX_SIZE ][ MAX_MATRIX_SIZE ]; + silk_float T[ MAX_MATRIX_SIZE ]; + silk_float Dinv[ MAX_MATRIX_SIZE ]; /* inverse diagonal elements of D*/ + + silk_assert( M <= MAX_MATRIX_SIZE ); + + /*************************************************** + Factorize A by LDL such that A = L*D*(L^T), + where L is lower triangular with ones on diagonal + ****************************************************/ + silk_LDL_FLP( A, M, &L[ 0 ][ 0 ], Dinv ); + + /**************************************************** + * substitute D*(L^T) = T. ie: + L*D*(L^T)*x = b => L*T = b <=> T = inv(L)*b + ******************************************************/ + silk_SolveWithLowerTriangularWdiagOnes_FLP( &L[ 0 ][ 0 ], M, b, T ); + + /**************************************************** + D*(L^T)*x = T <=> (L^T)*x = inv(D)*T, because D is + diagonal just multiply with 1/d_i + ****************************************************/ + for( i = 0; i < M; i++ ) { + T[ i ] = T[ i ] * Dinv[ i ]; + } + /**************************************************** + x = inv(L') * inv(D) * T + *****************************************************/ + silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( &L[ 0 ][ 0 ], M, T, x ); +} + +static OPUS_INLINE void silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( + const silk_float *L, /* I Pointer to Lower Triangular Matrix */ + opus_int M, /* I Dim of Matrix equation */ + const silk_float *b, /* I b Vector */ + silk_float *x /* O x Vector */ +) +{ + opus_int i, j; + silk_float temp; + const silk_float *ptr1; + + for( i = M - 1; i >= 0; i-- ) { + ptr1 = matrix_adr( L, 0, i, M ); + temp = 0; + for( j = M - 1; j > i ; j-- ) { + temp += ptr1[ j * M ] * x[ j ]; + } + temp = b[ i ] - temp; + x[ i ] = temp; + } +} + +static OPUS_INLINE void silk_SolveWithLowerTriangularWdiagOnes_FLP( + const silk_float *L, /* I Pointer to Lower Triangular Matrix */ + opus_int M, /* I Dim of Matrix equation */ + const silk_float *b, /* I b Vector */ + silk_float *x /* O x Vector */ +) +{ + opus_int i, j; + silk_float temp; + const silk_float *ptr1; + + for( i = 0; i < M; i++ ) { + ptr1 = matrix_adr( L, i, 0, M ); + temp = 0; + for( j = 0; j < i; j++ ) { + temp += ptr1[ j ] * x[ j ]; + } + temp = b[ i ] - temp; + x[ i ] = temp; + } +} + +static OPUS_INLINE void silk_LDL_FLP( + silk_float *A, /* I/O Pointer to Symetric Square Matrix */ + opus_int M, /* I Size of Matrix */ + silk_float *L, /* I/O Pointer to Square Upper triangular Matrix */ + silk_float *Dinv /* I/O Pointer to vector holding the inverse diagonal elements of D */ +) +{ + opus_int i, j, k, loop_count, err = 1; + silk_float *ptr1, *ptr2; + double temp, diag_min_value; + silk_float v[ MAX_MATRIX_SIZE ], D[ MAX_MATRIX_SIZE ]; /* temp arrays*/ + + silk_assert( M <= MAX_MATRIX_SIZE ); + + diag_min_value = FIND_LTP_COND_FAC * 0.5f * ( A[ 0 ] + A[ M * M - 1 ] ); + for( loop_count = 0; loop_count < M && err == 1; loop_count++ ) { + err = 0; + for( j = 0; j < M; j++ ) { + ptr1 = matrix_adr( L, j, 0, M ); + temp = matrix_ptr( A, j, j, M ); /* element in row j column j*/ + for( i = 0; i < j; i++ ) { + v[ i ] = ptr1[ i ] * D[ i ]; + temp -= ptr1[ i ] * v[ i ]; + } + if( temp < diag_min_value ) { + /* Badly conditioned matrix: add white noise and run again */ + temp = ( loop_count + 1 ) * diag_min_value - temp; + for( i = 0; i < M; i++ ) { + matrix_ptr( A, i, i, M ) += ( silk_float )temp; + } + err = 1; + break; + } + D[ j ] = ( silk_float )temp; + Dinv[ j ] = ( silk_float )( 1.0f / temp ); + matrix_ptr( L, j, j, M ) = 1.0f; + + ptr1 = matrix_adr( A, j, 0, M ); + ptr2 = matrix_adr( L, j + 1, 0, M); + for( i = j + 1; i < M; i++ ) { + temp = 0.0; + for( k = 0; k < j; k++ ) { + temp += ptr2[ k ] * v[ k ]; + } + matrix_ptr( L, i, j, M ) = ( silk_float )( ( ptr1[ i ] - temp ) * Dinv[ j ] ); + ptr2 += M; /* go to next column*/ + } + } + } + silk_assert( err == 0 ); +} + diff --git a/thirdparty/opus/silk/float/sort_FLP.c b/thirdparty/opus/silk/float/sort_FLP.c new file mode 100644 index 0000000000..f08d7592c5 --- /dev/null +++ b/thirdparty/opus/silk/float/sort_FLP.c @@ -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 */ + silk_assert( K > 0 ); + silk_assert( L > 0 ); + silk_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/thirdparty/opus/silk/float/structs_FLP.h b/thirdparty/opus/silk/float/structs_FLP.h new file mode 100644 index 0000000000..14d647ced2 --- /dev/null +++ b/thirdparty/opus/silk/float/structs_FLP.h @@ -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. +***********************************************************************/ + +#ifndef SILK_STRUCTS_FLP_H +#define SILK_STRUCTS_FLP_H + +#include "typedef.h" +#include "main.h" +#include "structs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/********************************/ +/* Noise shaping analysis state */ +/********************************/ +typedef struct { + opus_int8 LastGainIndex; + silk_float HarmBoost_smth; + silk_float HarmShapeGain_smth; + silk_float Tilt_smth; +} silk_shape_state_FLP; + +/********************************/ +/* Prefilter state */ +/********************************/ +typedef struct { + silk_float sLTP_shp[ LTP_BUF_LENGTH ]; + silk_float sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ]; + opus_int sLTP_shp_buf_idx; + silk_float sLF_AR_shp; + silk_float sLF_MA_shp; + silk_float sHarmHP; + opus_int32 rand_seed; + opus_int lagPrev; +} silk_prefilter_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 */ + silk_prefilter_state_FLP sPrefilt; /* Prefilter 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 AR1[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; + silk_float AR2[ 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 GainsPre[ MAX_NB_SUBFR ]; + silk_float HarmBoost[ 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 sparseness; + 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 { + silk_encoder_state_FLP state_Fxx[ ENCODER_NUM_CHANNELS ]; + 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; +} silk_encoder; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/opus/silk/float/warped_autocorrelation_FLP.c b/thirdparty/opus/silk/float/warped_autocorrelation_FLP.c new file mode 100644 index 0000000000..542414f48e --- /dev/null +++ b/thirdparty/opus/silk/float/warped_autocorrelation_FLP.c @@ -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_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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; + double C[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; + + /* Order must be even */ + silk_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 */ + tmp2 = state[ i ] + warping * ( state[ i + 1 ] - tmp1 ); + state[ i ] = tmp1; + C[ i ] += state[ 0 ] * tmp1; + /* Output of allpass section */ + tmp1 = state[ i + 1 ] + warping * ( state[ i + 2 ] - 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/thirdparty/opus/silk/float/wrappers_FLP.c b/thirdparty/opus/silk/float/wrappers_FLP.c new file mode 100644 index 0000000000..6666b8efaa --- /dev/null +++ b/thirdparty/opus/silk/float/wrappers_FLP.c @@ -0,0 +1,202 @@ +/*********************************************************************** +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 */ +) +{ + opus_int i; + opus_int16 a_fix_Q12[ MAX_LPC_ORDER ]; + + silk_NLSF2A( a_fix_Q12, NLSF_Q15, LPC_order ); + + 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_int32 x_Q3[ 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 AR2_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++ ) { + AR2_Q13[ i * MAX_SHAPE_LPC_ORDER + j ] = silk_float2int( psEncCtrl->AR2[ 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++ ) { + x_Q3[ i ] = silk_float2int( 8.0f * x[ i ] ); + } + + /* Call NSQ */ + if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { + silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x_Q3, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14, + AR2_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, x_Q3, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14, + AR2_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 ], /* I/O (Un-)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 */ + const silk_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */ + const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */ + const opus_int lowComplexity, /* I Flag for low complexity */ + const opus_int nb_subfr, /* I number of subframes */ + int arch /* I Run-time architecture */ +) +{ + opus_int i; + opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ]; + opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ]; + + for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) { + B_Q14[ i ] = (opus_int16)silk_float2int( B[ i ] * 16384.0f ); + } + for( i = 0; i < nb_subfr * LTP_ORDER * LTP_ORDER; i++ ) { + W_Q18[ i ] = (opus_int32)silk_float2int( W[ i ] * 262144.0f ); + } + + silk_quant_LTP_gains( B_Q14, cbk_index, periodicity_index, sum_log_gain_Q7, W_Q18, mu_Q10, lowComplexity, nb_subfr, arch ); + + for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) { + B[ i ] = (silk_float)B_Q14[ i ] * ( 1.0f / 16384.0f ); + } +} diff --git a/thirdparty/opus/silk/gain_quant.c b/thirdparty/opus/silk/gain_quant.c new file mode 100644 index 0000000000..64ccd0611b --- /dev/null +++ b/thirdparty/opus/silk/gain_quant.c @@ -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 "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; + } 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/thirdparty/opus/silk/init_decoder.c b/thirdparty/opus/silk/init_decoder.c new file mode 100644 index 0000000000..f887c67886 --- /dev/null +++ b/thirdparty/opus/silk/init_decoder.c @@ -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 "main.h" + +/************************/ +/* 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 ) ); + + /* Used to deactivate LSF interpolation */ + psDec->first_frame_after_reset = 1; + psDec->prev_gain_Q16 = 65536; + + /* Reset CNG state */ + silk_CNG_Reset( psDec ); + + /* Reset PLC state */ + silk_PLC_Reset( psDec ); + + return(0); +} + diff --git a/thirdparty/opus/silk/init_encoder.c b/thirdparty/opus/silk/init_encoder.c new file mode 100644 index 0000000000..65995c33fa --- /dev/null +++ b/thirdparty/opus/silk/init_encoder.c @@ -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. +***********************************************************************/ + +#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" +#include "cpu_support.h" + +/*********************************/ +/* Initialize 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 */ +) +{ + opus_int ret = 0; + + /* Clear the entire encoder state */ + silk_memset( psEnc, 0, sizeof( silk_encoder_state_Fxx ) ); + + psEnc->sCmn.arch = arch; + + psEnc->sCmn.variable_HP_smth1_Q15 = silk_LSHIFT( silk_lin2log( SILK_FIX_CONST( VARIABLE_HP_MIN_CUTOFF_HZ, 16 ) ) - ( 16 << 7 ), 8 ); + psEnc->sCmn.variable_HP_smth2_Q15 = psEnc->sCmn.variable_HP_smth1_Q15; + + /* Used to deactivate LSF interpolation, pitch prediction */ + psEnc->sCmn.first_frame_after_reset = 1; + + /* Initialize Silk VAD */ + ret += silk_VAD_Init( &psEnc->sCmn.sVAD ); + + return ret; +} diff --git a/thirdparty/opus/silk/inner_prod_aligned.c b/thirdparty/opus/silk/inner_prod_aligned.c new file mode 100644 index 0000000000..257ae9e04e --- /dev/null +++ b/thirdparty/opus/silk/inner_prod_aligned.c @@ -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/thirdparty/opus/silk/interpolate.c b/thirdparty/opus/silk/interpolate.c new file mode 100644 index 0000000000..1bd8ca4d53 --- /dev/null +++ b/thirdparty/opus/silk/interpolate.c @@ -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; + + silk_assert( ifact_Q2 >= 0 ); + silk_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/thirdparty/opus/silk/lin2log.c b/thirdparty/opus/silk/lin2log.c new file mode 100644 index 0000000000..d4fe515321 --- /dev/null +++ b/thirdparty/opus/silk/lin2log.c @@ -0,0 +1,46 @@ +/*********************************************************************** +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_LSHIFT( 31 - lz, 7 ) + silk_SMLAWB( frac_Q7, silk_MUL( frac_Q7, 128 - frac_Q7 ), 179 ); +} + diff --git a/thirdparty/opus/silk/log2lin.c b/thirdparty/opus/silk/log2lin.c new file mode 100644 index 0000000000..b7c48e4740 --- /dev/null +++ b/thirdparty/opus/silk/log2lin.c @@ -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/thirdparty/opus/silk/macros.h b/thirdparty/opus/silk/macros.h new file mode 100644 index 0000000000..bc30303466 --- /dev/null +++ b/thirdparty/opus/silk/macros.h @@ -0,0 +1,153 @@ +/*********************************************************************** +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" + +#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 + +/* Set this if opus_int64 is a native type of the CPU. */ +#define OPUS_FAST_INT64 (defined(__x86_64__) || defined(__LP64__) || defined(_WIN64)) + +/* 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) (((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) ((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 */ +#define silk_SMULWT(a32, b32) (((a32) >> 16) * ((b32) >> 16) + ((((a32) & 0x0000FFFF) * ((b32) >> 16)) >> 16)) + +/* a32 + (b32 * (c32 >> 16)) >> 16 */ +#if OPUS_FAST_INT64 +#define silk_SMLAWT(a32, b32, c32) ((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_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) ((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(MIPSr1_ASM) +#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 + +#endif /* SILK_MACROS_H */ + diff --git a/thirdparty/opus/silk/main.h b/thirdparty/opus/silk/main.h new file mode 100644 index 0000000000..2f90d68f7d --- /dev/null +++ b/thirdparty/opus/silk/main.h @@ -0,0 +1,471 @@ +/*********************************************************************** +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 + +/* 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 redidual 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 ], /* I/O (un)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 */ + const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */ + opus_int mu_Q9, /* I Mu value (R/D tradeoff) */ + opus_int lowComplexity, /* I Flag for low complexity */ + 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 *rate_dist_Q14, /* O best weighted quant error + mu * rate */ + opus_int *gain_Q7, /* O sum of absolute LTP coefficients */ + const opus_int16 *in_Q14, /* I input vector to be quantized */ + const opus_int32 *W_Q18, /* I weighting matrix */ + 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 mu_Q9, /* I tradeoff betw. weighted error and rate */ + const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ + opus_int L /* I number of vectors in codebook */ +); + +#if !defined(OVERRIDE_silk_VQ_WMat_EC) +#define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \ + mu_Q9, max_gain_Q7, L, arch) \ + ((void)(arch),silk_VQ_WMat_EC_c(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \ + mu_Q9, max_gain_Q7, L)) +#endif + +/************************************/ +/* Noise shaping quantization (NSQ) */ +/************************************/ + +void silk_NSQ_c( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_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, 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_c(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 + +/* Noise shaping using delayed decision */ +void silk_NSQ_del_dec_c( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_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, 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_del_dec_c(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 + +/************/ +/* 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_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_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 */ + 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/thirdparty/opus/silk/mips/NSQ_del_dec_mipsr1.h b/thirdparty/opus/silk/mips/NSQ_del_dec_mipsr1.h new file mode 100644 index 0000000000..f6afd923e8 --- /dev/null +++ b/thirdparty/opus/silk/mips/NSQ_del_dec_mipsr1.h @@ -0,0 +1,405 @@ +/*********************************************************************** +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_DEL_DEC_MIPSR1_H__ +#define __NSQ_DEL_DEC_MIPSR1_H__ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "stack_alloc.h" + +#define OVERRIDE_silk_noise_shape_quantizer_del_dec +static inline void silk_noise_shape_quantizer_del_dec( + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + opus_int signalType, /* I Signal type */ + const opus_int32 x_Q10[], /* I */ + opus_int8 pulses[], /* O */ + opus_int16 xq[], /* O */ + opus_int32 sLTP_Q15[], /* I/O LTP filter state */ + opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */ + 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 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 subfr, /* I Subframe number */ + opus_int shapingLPCOrder, /* I Shaping LPC filter order */ + opus_int predictLPCOrder, /* I Prediction filter order */ + opus_int warping_Q16, /* I */ + opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ + opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ + opus_int decisionDelay /* I */ +) +{ + opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx; + opus_int32 Winner_rand_state; + opus_int32 LTP_pred_Q14, LPC_pred_Q14, n_AR_Q14, n_LTP_Q14; + opus_int32 n_LF_Q14, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10; + opus_int32 q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10; + opus_int32 tmp1, tmp2, sLF_AR_shp_Q14; + opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14; + NSQ_sample_struct psSampleState[ MAX_DEL_DEC_STATES ][ 2 ]; + NSQ_del_dec_struct *psDD; + NSQ_sample_struct *psSS; + opus_int16 b_Q14_0, b_Q14_1, b_Q14_2, b_Q14_3, b_Q14_4; + opus_int16 a_Q12_0, a_Q12_1, a_Q12_2, a_Q12_3, a_Q12_4, a_Q12_5, a_Q12_6; + opus_int16 a_Q12_7, a_Q12_8, a_Q12_9, a_Q12_10, a_Q12_11, a_Q12_12, a_Q12_13; + opus_int16 a_Q12_14, a_Q12_15; + + opus_int32 cur, prev, next; + + //Intialize b_Q14 variables + b_Q14_0 = b_Q14[ 0 ]; + b_Q14_1 = b_Q14[ 1 ]; + b_Q14_2 = b_Q14[ 2 ]; + b_Q14_3 = b_Q14[ 3 ]; + b_Q14_4 = b_Q14[ 4 ]; + + //Intialize a_Q12 variables + a_Q12_0 = a_Q12[0]; + a_Q12_1 = a_Q12[1]; + a_Q12_2 = a_Q12[2]; + a_Q12_3 = a_Q12[3]; + a_Q12_4 = a_Q12[4]; + a_Q12_5 = a_Q12[5]; + a_Q12_6 = a_Q12[6]; + a_Q12_7 = a_Q12[7]; + a_Q12_8 = a_Q12[8]; + a_Q12_9 = a_Q12[9]; + a_Q12_10 = a_Q12[10]; + a_Q12_11 = a_Q12[11]; + a_Q12_12 = a_Q12[12]; + a_Q12_13 = a_Q12[13]; + a_Q12_14 = a_Q12[14]; + a_Q12_15 = a_Q12[15]; + + long long temp64; + + silk_assert( nStatesDelayedDecision > 0 ); + + shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; + pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 ); + + for( i = 0; i < length; i++ ) { + /* Perform common calculations used in all states */ + + /* Long-term prediction */ + if( signalType == TYPE_VOICED ) { + /* Unrolled loop */ + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + temp64 = __builtin_mips_mult(pred_lag_ptr[ 0 ], b_Q14_0 ); + temp64 = __builtin_mips_madd( temp64, pred_lag_ptr[ -1 ], b_Q14_1 ); + temp64 = __builtin_mips_madd( temp64, pred_lag_ptr[ -2 ], b_Q14_2 ); + temp64 = __builtin_mips_madd( temp64, pred_lag_ptr[ -3 ], b_Q14_3 ); + temp64 = __builtin_mips_madd( temp64, pred_lag_ptr[ -4 ], b_Q14_4 ); + temp64 += 32768; + LTP_pred_Q14 = __builtin_mips_extr_w(temp64, 16); + LTP_pred_Q14 = silk_LSHIFT( LTP_pred_Q14, 1 ); /* Q13 -> Q14 */ + pred_lag_ptr++; + } else { + LTP_pred_Q14 = 0; + } + + /* Long-term shaping */ + if( lag > 0 ) { + /* Symmetric, packed FIR coefficients */ + n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); + n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); + n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */ + shp_lag_ptr++; + } else { + n_LTP_Q14 = 0; + } + + for( k = 0; k < nStatesDelayedDecision; k++ ) { + /* Delayed decision state */ + psDD = &psDelDec[ k ]; + + /* Sample state */ + psSS = psSampleState[ k ]; + + /* Generate dither */ + psDD->Seed = silk_RAND( psDD->Seed ); + + /* Pointer used in short term prediction and shaping */ + psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ]; + /* Short-term prediction */ + silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 ); + temp64 = __builtin_mips_mult(psLPC_Q14[ 0 ], a_Q12_0 ); + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -1 ], a_Q12_1 ); + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -2 ], a_Q12_2 ); + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -3 ], a_Q12_3 ); + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -4 ], a_Q12_4 ); + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -5 ], a_Q12_5 ); + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -6 ], a_Q12_6 ); + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -7 ], a_Q12_7 ); + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -8 ], a_Q12_8 ); + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -9 ], a_Q12_9 ); + if( predictLPCOrder == 16 ) { + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -10 ], a_Q12_10 ); + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -11 ], a_Q12_11 ); + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -12 ], a_Q12_12 ); + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -13 ], a_Q12_13 ); + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -14 ], a_Q12_14 ); + temp64 = __builtin_mips_madd( temp64, psLPC_Q14[ -15 ], a_Q12_15 ); + } + temp64 += 32768; + LPC_pred_Q14 = __builtin_mips_extr_w(temp64, 16); + + LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */ + + /* Noise shape feedback */ + silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ + /* Output of lowpass section */ + tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 ); + psDD->sAR2_Q14[ 0 ] = tmp2; + + temp64 = __builtin_mips_mult(tmp2, AR_shp_Q13[ 0 ] ); + + prev = psDD->sAR2_Q14[ 1 ]; + + /* Loop over allpass sections */ + for( j = 2; j < shapingLPCOrder; j += 2 ) { + cur = psDD->sAR2_Q14[ j ]; + next = psDD->sAR2_Q14[ j+1 ]; + /* Output of allpass section */ + tmp2 = silk_SMLAWB( prev, cur - tmp1, warping_Q16 ); + psDD->sAR2_Q14[ j - 1 ] = tmp1; + temp64 = __builtin_mips_madd( temp64, tmp1, AR_shp_Q13[ j - 1 ] ); + temp64 = __builtin_mips_madd( temp64, tmp2, AR_shp_Q13[ j ] ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( cur, next - tmp2, warping_Q16 ); + psDD->sAR2_Q14[ j + 0 ] = tmp2; + prev = next; + } + psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1; + temp64 = __builtin_mips_madd( temp64, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] ); + temp64 += 32768; + n_AR_Q14 = __builtin_mips_extr_w(temp64, 16); + n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 1 ); /* Q11 -> Q12 */ + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, psDD->LF_AR_Q14, Tilt_Q14 ); /* Q12 */ + n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 2 ); /* Q12 -> Q14 */ + + n_LF_Q14 = silk_SMULWB( psDD->Shape_Q14[ *smpl_buf_idx ], LF_shp_Q14 ); /* Q12 */ + n_LF_Q14 = silk_SMLAWT( n_LF_Q14, psDD->LF_AR_Q14, LF_shp_Q14 ); /* Q12 */ + n_LF_Q14 = silk_LSHIFT( n_LF_Q14, 2 ); /* Q12 -> Q14 */ + + /* Input minus prediction plus noise feedback */ + /* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */ + tmp1 = silk_ADD32( n_AR_Q14, n_LF_Q14 ); /* Q14 */ + tmp2 = silk_ADD32( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */ + tmp1 = silk_SUB32( tmp2, tmp1 ); /* Q13 */ + tmp1 = silk_RSHIFT_ROUND( tmp1, 4 ); /* Q10 */ + + r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */ + + /* Flip sign depending on dither */ + if ( psDD->Seed < 0 ) { + r_Q10 = -r_Q10; + } + r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 ); + + /* Find two quantization level candidates and measure their rate-distortion */ + q1_Q10 = silk_SUB32( r_Q10, offset_Q10 ); + q1_Q0 = silk_RSHIFT( q1_Q10, 10 ); + if( q1_Q0 > 0 ) { + q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = silk_ADD32( q1_Q10, 1024 ); + rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q0 == 0 ) { + q1_Q10 = offset_Q10; + q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q0 == -1 ) { + q2_Q10 = offset_Q10; + q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else { /* q1_Q0 < -1 */ + q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = silk_ADD32( q1_Q10, 1024 ); + rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( -q2_Q10, Lambda_Q10 ); + } + rr_Q10 = silk_SUB32( r_Q10, q1_Q10 ); + rd1_Q10 = silk_RSHIFT( silk_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 ); + rr_Q10 = silk_SUB32( r_Q10, q2_Q10 ); + rd2_Q10 = silk_RSHIFT( silk_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 ); + + if( rd1_Q10 < rd2_Q10 ) { + psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 ); + psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 ); + psSS[ 0 ].Q_Q10 = q1_Q10; + psSS[ 1 ].Q_Q10 = q2_Q10; + } else { + psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 ); + psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 ); + psSS[ 0 ].Q_Q10 = q2_Q10; + psSS[ 1 ].Q_Q10 = q1_Q10; + } + + /* Update states for best quantization */ + + /* Quantized excitation */ + exc_Q14 = silk_LSHIFT32( psSS[ 0 ].Q_Q10, 4 ); + if ( psDD->Seed < 0 ) { + exc_Q14 = -exc_Q14; + } + + /* Add predictions */ + LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 ); + xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 ); + + /* Update states */ + sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 ); + psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 ); + psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14; + psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14; + psSS[ 0 ].xq_Q14 = xq_Q14; + + /* Update states for second best quantization */ + + /* Quantized excitation */ + exc_Q14 = silk_LSHIFT32( psSS[ 1 ].Q_Q10, 4 ); + if ( psDD->Seed < 0 ) { + exc_Q14 = -exc_Q14; + } + + + /* Add predictions */ + LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 ); + xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 ); + + /* Update states */ + sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 ); + psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 ); + psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14; + psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14; + psSS[ 1 ].xq_Q14 = xq_Q14; + } + + *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */ + last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */ + + /* Find winner */ + RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; + Winner_ind = 0; + for( k = 1; k < nStatesDelayedDecision; k++ ) { + if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psSampleState[ k ][ 0 ].RD_Q10; + Winner_ind = k; + } + } + + /* Increase RD values of expired states */ + Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ]; + for( k = 0; k < nStatesDelayedDecision; k++ ) { + if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) { + psSampleState[ k ][ 0 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 0 ].RD_Q10, silk_int32_MAX >> 4 ); + psSampleState[ k ][ 1 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 1 ].RD_Q10, silk_int32_MAX >> 4 ); + silk_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 ); + } + } + + /* Find worst in first set and best in second set */ + RDmax_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; + RDmin_Q10 = psSampleState[ 0 ][ 1 ].RD_Q10; + RDmax_ind = 0; + RDmin_ind = 0; + for( k = 1; k < nStatesDelayedDecision; k++ ) { + /* find worst in first set */ + if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) { + RDmax_Q10 = psSampleState[ k ][ 0 ].RD_Q10; + RDmax_ind = k; + } + /* find best in second set */ + if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psSampleState[ k ][ 1 ].RD_Q10; + RDmin_ind = k; + } + } + + /* Replace a state if best from second set outperforms worst in first set */ + if( RDmin_Q10 < RDmax_Q10 ) { + silk_memcpy( ( (opus_int32 *)&psDelDec[ RDmax_ind ] ) + i, + ( (opus_int32 *)&psDelDec[ RDmin_ind ] ) + i, sizeof( NSQ_del_dec_struct ) - i * sizeof( opus_int32) ); + silk_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) ); + } + + /* Write samples from winner to output and long-term filter states */ + psDD = &psDelDec[ Winner_ind ]; + if( subfr > 0 || i >= decisionDelay ) { + pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); + xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( + silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], delayedGain_Q10[ last_smple_idx ] ), 8 ) ); + NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q14[ last_smple_idx ]; + sLTP_Q15[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q15[ last_smple_idx ]; + } + NSQ->sLTP_shp_buf_idx++; + NSQ->sLTP_buf_idx++; + + /* Update states */ + for( k = 0; k < nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + psSS = &psSampleState[ k ][ 0 ]; + psDD->LF_AR_Q14 = psSS->LF_AR_Q14; + psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14; + psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14; + psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10; + psDD->Pred_Q15[ *smpl_buf_idx ] = silk_LSHIFT32( psSS->LPC_exc_Q14, 1 ); + psDD->Shape_Q14[ *smpl_buf_idx ] = psSS->sLTP_shp_Q14; + psDD->Seed = silk_ADD32_ovflw( psDD->Seed, silk_RSHIFT_ROUND( psSS->Q_Q10, 10 ) ); + psDD->RandState[ *smpl_buf_idx ] = psDD->Seed; + psDD->RD_Q10 = psSS->RD_Q10; + } + delayedGain_Q10[ *smpl_buf_idx ] = Gain_Q10; + } + /* Update LPC states */ + for( k = 0; k < nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + silk_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); + } +} + +#endif /* __NSQ_DEL_DEC_MIPSR1_H__ */ diff --git a/drivers/opus/silk/mips/macros_mipsr1.h b/thirdparty/opus/silk/mips/macros_mipsr1.h index 12ed981a6e..12ed981a6e 100644 --- a/drivers/opus/silk/mips/macros_mipsr1.h +++ b/thirdparty/opus/silk/mips/macros_mipsr1.h diff --git a/drivers/opus/silk/mips/sigproc_fix_mipsr1.h b/thirdparty/opus/silk/mips/sigproc_fix_mipsr1.h index 3b0a695365..3b0a695365 100644 --- a/drivers/opus/silk/mips/sigproc_fix_mipsr1.h +++ b/thirdparty/opus/silk/mips/sigproc_fix_mipsr1.h diff --git a/thirdparty/opus/silk/pitch_est_defines.h b/thirdparty/opus/silk/pitch_est_defines.h new file mode 100644 index 0000000000..e1e4b5d768 --- /dev/null +++ b/thirdparty/opus/silk/pitch_est_defines.h @@ -0,0 +1,88 @@ +/*********************************************************************** +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/thirdparty/opus/silk/pitch_est_tables.c b/thirdparty/opus/silk/pitch_est_tables.c new file mode 100644 index 0000000000..81a8bacaca --- /dev/null +++ b/thirdparty/opus/silk/pitch_est_tables.c @@ -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/thirdparty/opus/silk/process_NLSFs.c b/thirdparty/opus/silk/process_NLSFs.c new file mode 100644 index 0000000000..c27cf03046 --- /dev/null +++ b/thirdparty/opus/silk/process_NLSFs.c @@ -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 "main.h" + +/* 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_int i, doInterpolate; + opus_int NLSF_mu_Q20; + opus_int32 i_sqr_Q15; + opus_int16 pNLSF0_temp_Q15[ MAX_LPC_ORDER ]; + opus_int16 pNLSFW_QW[ MAX_LPC_ORDER ]; + opus_int16 pNLSFW0_temp_QW[ MAX_LPC_ORDER ]; + + silk_assert( psEncC->speech_activity_Q8 >= 0 ); + silk_assert( psEncC->speech_activity_Q8 <= SILK_FIX_CONST( 1.0, 8 ) ); + silk_assert( psEncC->useInterpolatedNLSFs == 1 || psEncC->indices.NLSFInterpCoef_Q2 == ( 1 << 2 ) ); + + /***********************/ + /* Calculate mu values */ + /***********************/ + /* NLSF_mu = 0.003 - 0.0015 * psEnc->speech_activity; */ + NLSF_mu_Q20 = silk_SMLAWB( SILK_FIX_CONST( 0.003, 20 ), SILK_FIX_CONST( -0.001, 28 ), psEncC->speech_activity_Q8 ); + if( psEncC->nb_subfr == 2 ) { + /* Multiply by 1.5 for 10 ms packets */ + NLSF_mu_Q20 = silk_ADD_RSHIFT( NLSF_mu_Q20, NLSF_mu_Q20, 1 ); + } + + silk_assert( NLSF_mu_Q20 > 0 ); + silk_assert( NLSF_mu_Q20 <= SILK_FIX_CONST( 0.005, 20 ) ); + + /* Calculate NLSF weights */ + silk_NLSF_VQ_weights_laroia( pNLSFW_QW, pNLSF_Q15, psEncC->predictLPCOrder ); + + /* Update NLSF weights for interpolated NLSFs */ + doInterpolate = ( psEncC->useInterpolatedNLSFs == 1 ) && ( psEncC->indices.NLSFInterpCoef_Q2 < 4 ); + if( doInterpolate ) { + /* Calculate the interpolated NLSF vector for the first half */ + silk_interpolate( pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15, + psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder ); + + /* Calculate first half NLSF weights for the interpolated NLSFs */ + silk_NLSF_VQ_weights_laroia( pNLSFW0_temp_QW, pNLSF0_temp_Q15, psEncC->predictLPCOrder ); + + /* Update NLSF weights with contribution from first half */ + i_sqr_Q15 = silk_LSHIFT( silk_SMULBB( psEncC->indices.NLSFInterpCoef_Q2, psEncC->indices.NLSFInterpCoef_Q2 ), 11 ); + for( i = 0; i < psEncC->predictLPCOrder; i++ ) { + pNLSFW_QW[ i ] = silk_SMLAWB( silk_RSHIFT( pNLSFW_QW[ i ], 1 ), (opus_int32)pNLSFW0_temp_QW[ i ], i_sqr_Q15 ); + silk_assert( pNLSFW_QW[ i ] >= 1 ); + } + } + + silk_NLSF_encode( psEncC->indices.NLSFIndices, pNLSF_Q15, psEncC->psNLSF_CB, pNLSFW_QW, + NLSF_mu_Q20, psEncC->NLSF_MSVQ_Survivors, psEncC->indices.signalType ); + + /* Convert quantized NLSFs back to LPC coefficients */ + silk_NLSF2A( PredCoef_Q12[ 1 ], pNLSF_Q15, psEncC->predictLPCOrder ); + + if( doInterpolate ) { + /* Calculate the interpolated, quantized LSF vector for the first half */ + silk_interpolate( pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15, + psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder ); + + /* Convert back to LPC coefficients */ + silk_NLSF2A( PredCoef_Q12[ 0 ], pNLSF0_temp_Q15, psEncC->predictLPCOrder ); + + } else { + /* Copy LPC coefficients for first half from second half */ + silk_memcpy( PredCoef_Q12[ 0 ], PredCoef_Q12[ 1 ], psEncC->predictLPCOrder * sizeof( opus_int16 ) ); + } +} diff --git a/thirdparty/opus/silk/quant_LTP_gains.c b/thirdparty/opus/silk/quant_LTP_gains.c new file mode 100644 index 0000000000..513a8c4468 --- /dev/null +++ b/thirdparty/opus/silk/quant_LTP_gains.c @@ -0,0 +1,129 @@ +/*********************************************************************** +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 "tuning_parameters.h" + +void silk_quant_LTP_gains( + opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (un)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 */ + const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */ + opus_int mu_Q9, /* I Mu value (R/D tradeoff) */ + opus_int lowComplexity, /* I Flag for low complexity */ + const opus_int nb_subfr, /* I number of subframes */ + int arch /* I Run-time architecture */ +) +{ + opus_int j, k, cbk_size; + opus_int8 temp_idx[ MAX_NB_SUBFR ]; + const opus_uint8 *cl_ptr_Q5; + const opus_int8 *cbk_ptr_Q7; + const opus_uint8 *cbk_gain_ptr_Q7; + const opus_int16 *b_Q14_ptr; + const opus_int32 *W_Q18_ptr; + opus_int32 rate_dist_Q14_subfr, rate_dist_Q14, min_rate_dist_Q14; + opus_int32 sum_log_gain_tmp_Q7, best_sum_log_gain_Q7, max_gain_Q7, gain_Q7; + + /***************************************************/ + /* iterate over different codebooks with different */ + /* rates/distortions, and choose best */ + /***************************************************/ + min_rate_dist_Q14 = silk_int32_MAX; + best_sum_log_gain_Q7 = 0; + for( k = 0; k < 3; k++ ) { + /* Safety margin for pitch gain control, to take into account factors + such as state rescaling/rewhitening. */ + opus_int32 gain_safety = SILK_FIX_CONST( 0.4, 7 ); + + cl_ptr_Q5 = silk_LTP_gain_BITS_Q5_ptrs[ k ]; + cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ k ]; + cbk_gain_ptr_Q7 = silk_LTP_vq_gain_ptrs_Q7[ k ]; + cbk_size = silk_LTP_vq_sizes[ k ]; + + /* Set up pointer to first subframe */ + W_Q18_ptr = W_Q18; + b_Q14_ptr = B_Q14; + + rate_dist_Q14 = 0; + sum_log_gain_tmp_Q7 = *sum_log_gain_Q7; + for( j = 0; j < nb_subfr; j++ ) { + max_gain_Q7 = silk_log2lin( ( SILK_FIX_CONST( MAX_SUM_LOG_GAIN_DB / 6.0, 7 ) - sum_log_gain_tmp_Q7 ) + + SILK_FIX_CONST( 7, 7 ) ) - gain_safety; + + silk_VQ_WMat_EC( + &temp_idx[ j ], /* O index of best codebook vector */ + &rate_dist_Q14_subfr, /* O best weighted quantization error + mu * rate */ + &gain_Q7, /* O sum of absolute LTP coefficients */ + b_Q14_ptr, /* I input vector to be quantized */ + W_Q18_ptr, /* I weighting matrix */ + cbk_ptr_Q7, /* I codebook */ + cbk_gain_ptr_Q7, /* I codebook effective gains */ + cl_ptr_Q5, /* I code length for each codebook vector */ + mu_Q9, /* I tradeoff between weighted error and rate */ + max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ + cbk_size, /* I number of vectors in codebook */ + arch /* I Run-time architecture */ + ); + + rate_dist_Q14 = silk_ADD_POS_SAT32( rate_dist_Q14, rate_dist_Q14_subfr ); + sum_log_gain_tmp_Q7 = silk_max(0, sum_log_gain_tmp_Q7 + + silk_lin2log( gain_safety + gain_Q7 ) - SILK_FIX_CONST( 7, 7 )); + + b_Q14_ptr += LTP_ORDER; + W_Q18_ptr += LTP_ORDER * LTP_ORDER; + } + + /* Avoid never finding a codebook */ + rate_dist_Q14 = silk_min( silk_int32_MAX - 1, rate_dist_Q14 ); + + if( rate_dist_Q14 < min_rate_dist_Q14 ) { + min_rate_dist_Q14 = rate_dist_Q14; + *periodicity_index = (opus_int8)k; + silk_memcpy( cbk_index, temp_idx, nb_subfr * sizeof( opus_int8 ) ); + best_sum_log_gain_Q7 = sum_log_gain_tmp_Q7; + } + + /* Break early in low-complexity mode if rate distortion is below threshold */ + if( lowComplexity && ( rate_dist_Q14 < silk_LTP_gain_middle_avg_RD_Q14 ) ) { + break; + } + } + + cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ *periodicity_index ]; + for( j = 0; j < nb_subfr; j++ ) { + for( k = 0; k < LTP_ORDER; k++ ) { + B_Q14[ j * LTP_ORDER + k ] = silk_LSHIFT( cbk_ptr_Q7[ cbk_index[ j ] * LTP_ORDER + k ], 7 ); + } + } + *sum_log_gain_Q7 = best_sum_log_gain_Q7; +} diff --git a/thirdparty/opus/silk/resampler.c b/thirdparty/opus/silk/resampler.c new file mode 100644 index 0000000000..374fbb3722 --- /dev/null +++ b/thirdparty/opus/silk/resampler.c @@ -0,0 +1,215 @@ +/*********************************************************************** +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[ 5 ][ 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 } +}; + +static const opus_int8 delay_matrix_dec[ 3 ][ 5 ] = { +/* in \ out 8 12 16 24 48 */ +/* 8 */ { 4, 0, 2, 0, 0 }, +/* 12 */ { 0, 9, 4, 7, 4 }, +/* 16 */ { 0, 3, 12, 7, 7 } +}; + +/* Simple way to make [8000, 12000, 16000, 24000, 48000] to [0, 1, 2, 3, 4] */ +#define rateID(R) ( ( ( ((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 ) || + ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 ) ) { + silk_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 ) ) { + silk_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 */ + silk_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 */ + silk_assert( inLen >= S->Fs_in_kHz ); + /* Delay can't exceed the 1 ms of buffering */ + silk_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/thirdparty/opus/silk/resampler_down2.c b/thirdparty/opus/silk/resampler_down2.c new file mode 100644 index 0000000000..cec3634640 --- /dev/null +++ b/thirdparty/opus/silk/resampler_down2.c @@ -0,0 +1,74 @@ +/*********************************************************************** +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; + + silk_assert( silk_resampler_down2_0 > 0 ); + silk_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/thirdparty/opus/silk/resampler_down2_3.c b/thirdparty/opus/silk/resampler_down2_3.c new file mode 100644 index 0000000000..4342614dcc --- /dev/null +++ b/thirdparty/opus/silk/resampler_down2_3.c @@ -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/thirdparty/opus/silk/resampler_private.h b/thirdparty/opus/silk/resampler_private.h new file mode 100644 index 0000000000..422a7d9d95 --- /dev/null +++ b/thirdparty/opus/silk/resampler_private.h @@ -0,0 +1,88 @@ +/*********************************************************************** +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 + +#ifdef __cplusplus +extern "C" { +#endif + +#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 */ +); + +#ifdef __cplusplus +} +#endif +#endif /* SILK_RESAMPLER_PRIVATE_H */ diff --git a/thirdparty/opus/silk/resampler_private_AR2.c b/thirdparty/opus/silk/resampler_private_AR2.c new file mode 100644 index 0000000000..5fff23714f --- /dev/null +++ b/thirdparty/opus/silk/resampler_private_AR2.c @@ -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 "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/thirdparty/opus/silk/resampler_private_IIR_FIR.c b/thirdparty/opus/silk/resampler_private_IIR_FIR.c new file mode 100644 index 0000000000..6b2b3a2e18 --- /dev/null +++ b/thirdparty/opus/silk/resampler_private_IIR_FIR.c @@ -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/thirdparty/opus/silk/resampler_private_down_FIR.c b/thirdparty/opus/silk/resampler_private_down_FIR.c new file mode 100644 index 0000000000..783e42b356 --- /dev/null +++ b/thirdparty/opus/silk/resampler_private_down_FIR.c @@ -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: + silk_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/thirdparty/opus/silk/resampler_private_up2_HQ.c b/thirdparty/opus/silk/resampler_private_up2_HQ.c new file mode 100644 index 0000000000..c7ec8de365 --- /dev/null +++ b/thirdparty/opus/silk/resampler_private_up2_HQ.c @@ -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/thirdparty/opus/silk/resampler_rom.c b/thirdparty/opus/silk/resampler_rom.c new file mode 100644 index 0000000000..5e6b04476a --- /dev/null +++ b/thirdparty/opus/silk/resampler_rom.c @@ -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/thirdparty/opus/silk/resampler_rom.h b/thirdparty/opus/silk/resampler_rom.h new file mode 100644 index 0000000000..490b3388dc --- /dev/null +++ b/thirdparty/opus/silk/resampler_rom.h @@ -0,0 +1,68 @@ +/*********************************************************************** +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 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#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 ]; + +#ifdef __cplusplus +} +#endif + +#endif /* SILK_FIX_RESAMPLER_ROM_H */ diff --git a/drivers/opus/silk/resampler_structs.h b/thirdparty/opus/silk/resampler_structs.h index 9e9457d11c..9e9457d11c 100644 --- a/drivers/opus/silk/resampler_structs.h +++ b/thirdparty/opus/silk/resampler_structs.h diff --git a/thirdparty/opus/silk/shell_coder.c b/thirdparty/opus/silk/shell_coder.c new file mode 100644 index 0000000000..4af341474b --- /dev/null +++ b/thirdparty/opus/silk/shell_coder.c @@ -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/thirdparty/opus/silk/sigm_Q15.c b/thirdparty/opus/silk/sigm_Q15.c new file mode 100644 index 0000000000..3c507d255b --- /dev/null +++ b/thirdparty/opus/silk/sigm_Q15.c @@ -0,0 +1,76 @@ +/*********************************************************************** +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/thirdparty/opus/silk/sort.c b/thirdparty/opus/silk/sort.c new file mode 100644 index 0000000000..8670dbdd02 --- /dev/null +++ b/thirdparty/opus/silk/sort.c @@ -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: http://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 */ + silk_assert( K > 0 ); + silk_assert( L > 0 ); + silk_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 */ + silk_assert( K > 0 ); + silk_assert( L > 0 ); + silk_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 */ + silk_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/thirdparty/opus/silk/stereo_LR_to_MS.c b/thirdparty/opus/silk/stereo_LR_to_MS.c new file mode 100644 index 0000000000..42906e6f67 --- /dev/null +++ b/thirdparty/opus/silk/stereo_LR_to_MS.c @@ -0,0 +1,229 @@ +/*********************************************************************** +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" + +/* 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 */ +) +{ + opus_int n, is10msFrame, denom_Q16, delta0_Q13, delta1_Q13; + opus_int32 sum, diff, smooth_coef_Q16, pred_Q13[ 2 ], pred0_Q13, pred1_Q13; + opus_int32 LP_ratio_Q14, HP_ratio_Q14, frac_Q16, frac_3_Q16, min_mid_rate_bps, width_Q14, w_Q24, deltaw_Q24; + VARDECL( opus_int16, side ); + VARDECL( opus_int16, LP_mid ); + VARDECL( opus_int16, HP_mid ); + VARDECL( opus_int16, LP_side ); + VARDECL( opus_int16, HP_side ); + opus_int16 *mid = &x1[ -2 ]; + SAVE_STACK; + + ALLOC( side, frame_length + 2, opus_int16 ); + /* Convert to basic mid/side signals */ + for( n = 0; n < frame_length + 2; n++ ) { + sum = x1[ n - 2 ] + (opus_int32)x2[ n - 2 ]; + diff = x1[ n - 2 ] - (opus_int32)x2[ n - 2 ]; + mid[ n ] = (opus_int16)silk_RSHIFT_ROUND( sum, 1 ); + side[ n ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( diff, 1 ) ); + } + + /* Buffering */ + silk_memcpy( mid, state->sMid, 2 * sizeof( opus_int16 ) ); + silk_memcpy( side, state->sSide, 2 * sizeof( opus_int16 ) ); + silk_memcpy( state->sMid, &mid[ frame_length ], 2 * sizeof( opus_int16 ) ); + silk_memcpy( state->sSide, &side[ frame_length ], 2 * sizeof( opus_int16 ) ); + + /* LP and HP filter mid signal */ + ALLOC( LP_mid, frame_length, opus_int16 ); + ALLOC( HP_mid, frame_length, opus_int16 ); + for( n = 0; n < frame_length; n++ ) { + sum = silk_RSHIFT_ROUND( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 2 ); + LP_mid[ n ] = sum; + HP_mid[ n ] = mid[ n + 1 ] - sum; + } + + /* LP and HP filter side signal */ + ALLOC( LP_side, frame_length, opus_int16 ); + ALLOC( HP_side, frame_length, opus_int16 ); + for( n = 0; n < frame_length; n++ ) { + sum = silk_RSHIFT_ROUND( silk_ADD_LSHIFT( side[ n ] + side[ n + 2 ], side[ n + 1 ], 1 ), 2 ); + LP_side[ n ] = sum; + HP_side[ n ] = side[ n + 1 ] - sum; + } + + /* Find energies and predictors */ + is10msFrame = frame_length == 10 * fs_kHz; + smooth_coef_Q16 = is10msFrame ? + SILK_FIX_CONST( STEREO_RATIO_SMOOTH_COEF / 2, 16 ) : + SILK_FIX_CONST( STEREO_RATIO_SMOOTH_COEF, 16 ); + smooth_coef_Q16 = silk_SMULWB( silk_SMULBB( prev_speech_act_Q8, prev_speech_act_Q8 ), smooth_coef_Q16 ); + + pred_Q13[ 0 ] = silk_stereo_find_predictor( &LP_ratio_Q14, LP_mid, LP_side, &state->mid_side_amp_Q0[ 0 ], frame_length, smooth_coef_Q16 ); + pred_Q13[ 1 ] = silk_stereo_find_predictor( &HP_ratio_Q14, HP_mid, HP_side, &state->mid_side_amp_Q0[ 2 ], frame_length, smooth_coef_Q16 ); + /* Ratio of the norms of residual and mid signals */ + frac_Q16 = silk_SMLABB( HP_ratio_Q14, LP_ratio_Q14, 3 ); + frac_Q16 = silk_min( frac_Q16, SILK_FIX_CONST( 1, 16 ) ); + + /* Determine bitrate distribution between mid and side, and possibly reduce stereo width */ + total_rate_bps -= is10msFrame ? 1200 : 600; /* Subtract approximate bitrate for coding stereo parameters */ + if( total_rate_bps < 1 ) { + total_rate_bps = 1; + } + min_mid_rate_bps = silk_SMLABB( 2000, fs_kHz, 900 ); + silk_assert( min_mid_rate_bps < 32767 ); + /* Default bitrate distribution: 8 parts for Mid and (5+3*frac) parts for Side. so: mid_rate = ( 8 / ( 13 + 3 * frac ) ) * total_ rate */ + frac_3_Q16 = silk_MUL( 3, frac_Q16 ); + mid_side_rates_bps[ 0 ] = silk_DIV32_varQ( total_rate_bps, SILK_FIX_CONST( 8 + 5, 16 ) + frac_3_Q16, 16+3 ); + /* If Mid bitrate below minimum, reduce stereo width */ + if( mid_side_rates_bps[ 0 ] < min_mid_rate_bps ) { + mid_side_rates_bps[ 0 ] = min_mid_rate_bps; + mid_side_rates_bps[ 1 ] = total_rate_bps - mid_side_rates_bps[ 0 ]; + /* width = 4 * ( 2 * side_rate - min_rate ) / ( ( 1 + 3 * frac ) * min_rate ) */ + width_Q14 = silk_DIV32_varQ( silk_LSHIFT( mid_side_rates_bps[ 1 ], 1 ) - min_mid_rate_bps, + silk_SMULWB( SILK_FIX_CONST( 1, 16 ) + frac_3_Q16, min_mid_rate_bps ), 14+2 ); + width_Q14 = silk_LIMIT( width_Q14, 0, SILK_FIX_CONST( 1, 14 ) ); + } else { + mid_side_rates_bps[ 1 ] = total_rate_bps - mid_side_rates_bps[ 0 ]; + width_Q14 = SILK_FIX_CONST( 1, 14 ); + } + + /* Smoother */ + state->smth_width_Q14 = (opus_int16)silk_SMLAWB( state->smth_width_Q14, width_Q14 - state->smth_width_Q14, smooth_coef_Q16 ); + + /* At very low bitrates or for inputs that are nearly amplitude panned, switch to panned-mono coding */ + *mid_only_flag = 0; + if( toMono ) { + /* Last frame before stereo->mono transition; collapse stereo width */ + width_Q14 = 0; + pred_Q13[ 0 ] = 0; + pred_Q13[ 1 ] = 0; + silk_stereo_quant_pred( pred_Q13, ix ); + } else if( state->width_prev_Q14 == 0 && + ( 8 * total_rate_bps < 13 * min_mid_rate_bps || silk_SMULWB( frac_Q16, state->smth_width_Q14 ) < SILK_FIX_CONST( 0.05, 14 ) ) ) + { + /* Code as panned-mono; previous frame already had zero width */ + /* Scale down and quantize predictors */ + pred_Q13[ 0 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 0 ] ), 14 ); + pred_Q13[ 1 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); + silk_stereo_quant_pred( pred_Q13, ix ); + /* Collapse stereo width */ + width_Q14 = 0; + pred_Q13[ 0 ] = 0; + pred_Q13[ 1 ] = 0; + mid_side_rates_bps[ 0 ] = total_rate_bps; + mid_side_rates_bps[ 1 ] = 0; + *mid_only_flag = 1; + } else if( state->width_prev_Q14 != 0 && + ( 8 * total_rate_bps < 11 * min_mid_rate_bps || silk_SMULWB( frac_Q16, state->smth_width_Q14 ) < SILK_FIX_CONST( 0.02, 14 ) ) ) + { + /* Transition to zero-width stereo */ + /* Scale down and quantize predictors */ + pred_Q13[ 0 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 0 ] ), 14 ); + pred_Q13[ 1 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); + silk_stereo_quant_pred( pred_Q13, ix ); + /* Collapse stereo width */ + width_Q14 = 0; + pred_Q13[ 0 ] = 0; + pred_Q13[ 1 ] = 0; + } else if( state->smth_width_Q14 > SILK_FIX_CONST( 0.95, 14 ) ) { + /* Full-width stereo coding */ + silk_stereo_quant_pred( pred_Q13, ix ); + width_Q14 = SILK_FIX_CONST( 1, 14 ); + } else { + /* Reduced-width stereo coding; scale down and quantize predictors */ + pred_Q13[ 0 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 0 ] ), 14 ); + pred_Q13[ 1 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); + silk_stereo_quant_pred( pred_Q13, ix ); + width_Q14 = state->smth_width_Q14; + } + + /* Make sure to keep on encoding until the tapered output has been transmitted */ + if( *mid_only_flag == 1 ) { + state->silent_side_len += frame_length - STEREO_INTERP_LEN_MS * fs_kHz; + if( state->silent_side_len < LA_SHAPE_MS * fs_kHz ) { + *mid_only_flag = 0; + } else { + /* Limit to avoid wrapping around */ + state->silent_side_len = 10000; + } + } else { + state->silent_side_len = 0; + } + + if( *mid_only_flag == 0 && mid_side_rates_bps[ 1 ] < 1 ) { + mid_side_rates_bps[ 1 ] = 1; + mid_side_rates_bps[ 0 ] = silk_max_int( 1, total_rate_bps - mid_side_rates_bps[ 1 ]); + } + + /* Interpolate predictors and subtract prediction from side channel */ + pred0_Q13 = -state->pred_prev_Q13[ 0 ]; + pred1_Q13 = -state->pred_prev_Q13[ 1 ]; + w_Q24 = silk_LSHIFT( state->width_prev_Q14, 10 ); + 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 ); + deltaw_Q24 = silk_LSHIFT( silk_SMULWB( width_Q14 - state->width_prev_Q14, denom_Q16 ), 10 ); + for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) { + pred0_Q13 += delta0_Q13; + pred1_Q13 += delta1_Q13; + w_Q24 += deltaw_Q24; + sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ + sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ + sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)mid[ 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 ]; + w_Q24 = silk_LSHIFT( width_Q14, 10 ); + for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { + sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ + sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ + sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)mid[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ + x2[ n - 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) ); + } + state->pred_prev_Q13[ 0 ] = (opus_int16)pred_Q13[ 0 ]; + state->pred_prev_Q13[ 1 ] = (opus_int16)pred_Q13[ 1 ]; + state->width_prev_Q14 = (opus_int16)width_Q14; + RESTORE_STACK; +} diff --git a/thirdparty/opus/silk/stereo_MS_to_LR.c b/thirdparty/opus/silk/stereo_MS_to_LR.c new file mode 100644 index 0000000000..62521a4f35 --- /dev/null +++ b/thirdparty/opus/silk/stereo_MS_to_LR.c @@ -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_LSHIFT( x1[ n ] + 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_LSHIFT( x1[ n ] + 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/thirdparty/opus/silk/stereo_decode_pred.c b/thirdparty/opus/silk/stereo_decode_pred.c new file mode 100644 index 0000000000..56ba3925e8 --- /dev/null +++ b/thirdparty/opus/silk/stereo_decode_pred.c @@ -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/thirdparty/opus/silk/stereo_encode_pred.c b/thirdparty/opus/silk/stereo_encode_pred.c new file mode 100644 index 0000000000..e6dd195066 --- /dev/null +++ b/thirdparty/opus/silk/stereo_encode_pred.c @@ -0,0 +1,62 @@ +/*********************************************************************** +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" + +/* 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 */ +) +{ + opus_int n; + + /* Entropy coding */ + n = 5 * ix[ 0 ][ 2 ] + ix[ 1 ][ 2 ]; + silk_assert( n < 25 ); + ec_enc_icdf( psRangeEnc, n, silk_stereo_pred_joint_iCDF, 8 ); + for( n = 0; n < 2; n++ ) { + silk_assert( ix[ n ][ 0 ] < 3 ); + silk_assert( ix[ n ][ 1 ] < STEREO_QUANT_SUB_STEPS ); + ec_enc_icdf( psRangeEnc, ix[ n ][ 0 ], silk_uniform3_iCDF, 8 ); + ec_enc_icdf( psRangeEnc, ix[ n ][ 1 ], silk_uniform5_iCDF, 8 ); + } +} + +/* 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 +) +{ + /* Encode flag that only mid channel is coded */ + ec_enc_icdf( psRangeEnc, mid_only_flag, silk_stereo_only_code_mid_iCDF, 8 ); +} diff --git a/thirdparty/opus/silk/stereo_find_predictor.c b/thirdparty/opus/silk/stereo_find_predictor.c new file mode 100644 index 0000000000..e30e90bddc --- /dev/null +++ b/thirdparty/opus/silk/stereo_find_predictor.c @@ -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/thirdparty/opus/silk/stereo_quant_pred.c b/thirdparty/opus/silk/stereo_quant_pred.c new file mode 100644 index 0000000000..d4ced6c3e8 --- /dev/null +++ b/thirdparty/opus/silk/stereo_quant_pred.c @@ -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" + +/* 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 */ +) +{ + opus_int i, j, n; + opus_int32 low_Q13, step_Q13, lvl_Q13, err_min_Q13, err_Q13, quant_pred_Q13 = 0; + + /* Quantize */ + for( n = 0; n < 2; n++ ) { + /* Brute-force search over quantization levels */ + err_min_Q13 = silk_int32_MAX; + for( i = 0; i < STEREO_QUANT_TAB_SIZE - 1; i++ ) { + low_Q13 = silk_stereo_pred_quant_Q13[ i ]; + step_Q13 = silk_SMULWB( silk_stereo_pred_quant_Q13[ i + 1 ] - low_Q13, + SILK_FIX_CONST( 0.5 / STEREO_QUANT_SUB_STEPS, 16 ) ); + for( j = 0; j < STEREO_QUANT_SUB_STEPS; j++ ) { + lvl_Q13 = silk_SMLABB( low_Q13, step_Q13, 2 * j + 1 ); + err_Q13 = silk_abs( pred_Q13[ n ] - lvl_Q13 ); + if( err_Q13 < err_min_Q13 ) { + err_min_Q13 = err_Q13; + quant_pred_Q13 = lvl_Q13; + ix[ n ][ 0 ] = i; + ix[ n ][ 1 ] = j; + } else { + /* Error increasing, so we're past the optimum */ + goto done; + } + } + } + done: + ix[ n ][ 2 ] = silk_DIV32_16( ix[ n ][ 0 ], 3 ); + ix[ n ][ 0 ] -= ix[ n ][ 2 ] * 3; + pred_Q13[ n ] = quant_pred_Q13; + } + + /* Subtract second from first predictor (helps when actually applying these) */ + pred_Q13[ 0 ] -= pred_Q13[ 1 ]; +} diff --git a/thirdparty/opus/silk/structs.h b/thirdparty/opus/silk/structs.h new file mode 100644 index 0000000000..827829dc6f --- /dev/null +++ b/thirdparty/opus/silk/structs.h @@ -0,0 +1,327 @@ +/*********************************************************************** +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 __cplusplus +extern "C" +{ +#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_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 */ +} 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_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_int LTPQuantLowComplexity; /* Flag for low complexity LTP quantization */ + opus_int mu_LTP_Q9; /* Rate-distortion tradeoff in LTP quantization */ + 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; + + +/* 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 coeficients 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; +} 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 { + 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; + + 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; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/opus/silk/sum_sqr_shift.c b/thirdparty/opus/silk/sum_sqr_shift.c new file mode 100644 index 0000000000..129df191d8 --- /dev/null +++ b/thirdparty/opus/silk/sum_sqr_shift.c @@ -0,0 +1,86 @@ +/*********************************************************************** +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_int32 nrg_tmp, nrg; + + nrg = 0; + shft = 0; + len--; + for( i = 0; i < len; i += 2 ) { + nrg = silk_SMLABB_ovflw( nrg, x[ i ], x[ i ] ); + nrg = silk_SMLABB_ovflw( nrg, x[ i + 1 ], x[ i + 1 ] ); + if( nrg < 0 ) { + /* Scale down */ + nrg = (opus_int32)silk_RSHIFT_uint( (opus_uint32)nrg, 2 ); + shft = 2; + i+=2; + break; + } + } + for( ; i < len; 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, (opus_uint32)nrg_tmp, shft ); + if( nrg < 0 ) { + /* Scale down */ + nrg = (opus_int32)silk_RSHIFT_uint( (opus_uint32)nrg, 2 ); + shft += 2; + } + } + 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 ); + } + + /* Make sure to have at least one extra leading zero (two leading zeros in total) */ + if( nrg & 0xC0000000 ) { + nrg = silk_RSHIFT_uint( (opus_uint32)nrg, 2 ); + shft += 2; + } + + /* Output arguments */ + *shift = shft; + *energy = nrg; +} + diff --git a/thirdparty/opus/silk/table_LSF_cos.c b/thirdparty/opus/silk/table_LSF_cos.c new file mode 100644 index 0000000000..ec9dc63927 --- /dev/null +++ b/thirdparty/opus/silk/table_LSF_cos.c @@ -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/thirdparty/opus/silk/tables.h b/thirdparty/opus/silk/tables.h new file mode 100644 index 0000000000..7fea6fda39 --- /dev/null +++ b/thirdparty/opus/silk/tables.h @@ -0,0 +1,122 @@ +/*********************************************************************** +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" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* 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_int16 silk_LTP_gain_middle_avg_RD_Q14; +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 */ + +/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */ +extern const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ]; /* 32 */ +extern const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ]; /* 32 */ +extern const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ]; /* 32 */ +extern const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ]; /* 32 */ + +/* 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 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/opus/silk/tables_LTP.c b/thirdparty/opus/silk/tables_LTP.c new file mode 100644 index 0000000000..0e6a0254d5 --- /dev/null +++ b/thirdparty/opus/silk/tables_LTP.c @@ -0,0 +1,296 @@ +/*********************************************************************** +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 +}; + +const opus_int16 silk_LTP_gain_middle_avg_RD_Q14 = 12304; + +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/thirdparty/opus/silk/tables_NLSF_CB_NB_MB.c b/thirdparty/opus/silk/tables_NLSF_CB_NB_MB.c new file mode 100644 index 0000000000..8c59d207aa --- /dev/null +++ b/thirdparty/opus/silk/tables_NLSF_CB_NB_MB.c @@ -0,0 +1,159 @@ +/*********************************************************************** +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_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_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/thirdparty/opus/silk/tables_NLSF_CB_WB.c b/thirdparty/opus/silk/tables_NLSF_CB_WB.c new file mode 100644 index 0000000000..50af87eb2e --- /dev/null +++ b/thirdparty/opus/silk/tables_NLSF_CB_WB.c @@ -0,0 +1,198 @@ +/*********************************************************************** +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_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_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/thirdparty/opus/silk/tables_gain.c b/thirdparty/opus/silk/tables_gain.c new file mode 100644 index 0000000000..37e41d890c --- /dev/null +++ b/thirdparty/opus/silk/tables_gain.c @@ -0,0 +1,63 @@ +/*********************************************************************** +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" + +#ifdef __cplusplus +extern "C" +{ +#endif + +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 +}; + +#ifdef __cplusplus +} +#endif diff --git a/thirdparty/opus/silk/tables_other.c b/thirdparty/opus/silk/tables_other.c new file mode 100644 index 0000000000..398686bf26 --- /dev/null +++ b/thirdparty/opus/silk/tables_other.c @@ -0,0 +1,138 @@ +/*********************************************************************** +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" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */ +const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ] = { + 0, 8000, 9400, 11500, 13500, 17500, 25000, MAX_TARGET_RATE_BPS +}; +const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ] = { + 0, 9000, 12000, 14500, 18500, 24500, 35500, MAX_TARGET_RATE_BPS +}; +const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ] = { + 0, 10500, 14000, 17000, 21500, 28500, 42000, MAX_TARGET_RATE_BPS +}; +const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ] = { + 18, 29, 38, 40, 46, 52, 62, 84 +}; + +/* 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 } +}; + +#ifdef __cplusplus +} +#endif + diff --git a/thirdparty/opus/silk/tables_pitch_lag.c b/thirdparty/opus/silk/tables_pitch_lag.c new file mode 100644 index 0000000000..e80cc59a27 --- /dev/null +++ b/thirdparty/opus/silk/tables_pitch_lag.c @@ -0,0 +1,69 @@ +/*********************************************************************** +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/thirdparty/opus/silk/tables_pulses_per_block.c b/thirdparty/opus/silk/tables_pulses_per_block.c new file mode 100644 index 0000000000..c7c01c8893 --- /dev/null +++ b/thirdparty/opus/silk/tables_pulses_per_block.c @@ -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/drivers/opus/silk/tuning_parameters.h b/thirdparty/opus/silk/tuning_parameters.h index 5b8f404235..5b8f404235 100644 --- a/drivers/opus/silk/tuning_parameters.h +++ b/thirdparty/opus/silk/tuning_parameters.h diff --git a/thirdparty/opus/silk/typedef.h b/thirdparty/opus/silk/typedef.h new file mode 100644 index 0000000000..97b7e709be --- /dev/null +++ b/thirdparty/opus/silk/typedef.h @@ -0,0 +1,78 @@ +/*********************************************************************** +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); + abort(); +} +# define silk_assert(COND) {if (!(COND)) {silk_fatal("assertion failed: " #COND);}} +# else +# define silk_assert(COND) +# endif +#endif + +#endif /* SILK_TYPEDEF_H */ diff --git a/thirdparty/opus/silk/x86/NSQ_del_dec_sse.c b/thirdparty/opus/silk/x86/NSQ_del_dec_sse.c new file mode 100644 index 0000000000..21d4a8bc1e --- /dev/null +++ b/thirdparty/opus/silk/x86/NSQ_del_dec_sse.c @@ -0,0 +1,857 @@ +/* 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 "main.h" +#include "celt/x86/x86cpu.h" + +#include "stack_alloc.h" + +typedef struct { + opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ]; + opus_int32 RandState[ DECISION_DELAY ]; + opus_int32 Q_Q10[ DECISION_DELAY ]; + opus_int32 Xq_Q14[ DECISION_DELAY ]; + opus_int32 Pred_Q15[ DECISION_DELAY ]; + opus_int32 Shape_Q14[ DECISION_DELAY ]; + opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ]; + opus_int32 LF_AR_Q14; + opus_int32 Seed; + opus_int32 SeedInit; + opus_int32 RD_Q10; +} NSQ_del_dec_struct; + +typedef struct { + opus_int32 Q_Q10; + opus_int32 RD_Q10; + opus_int32 xq_Q14; + opus_int32 LF_AR_Q14; + opus_int32 sLTP_shp_Q14; + opus_int32 LPC_exc_Q14; +} NSQ_sample_struct; + +typedef NSQ_sample_struct NSQ_sample_pair[ 2 ]; + +static OPUS_INLINE void silk_nsq_del_dec_scale_states_sse4_1( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + const opus_int32 x_Q3[], /* I Input in Q3 */ + opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */ + const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ + opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ + opus_int subfr, /* I Subframe number */ + opus_int nStatesDelayedDecision, /* I Number of del dec states */ + const opus_int LTP_scale_Q14, /* I LTP state scaling */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ + const opus_int signal_type, /* I Signal type */ + const opus_int decisionDelay /* I Decision delay */ +); + +/******************************************/ +/* Noise shape quantizer for one subframe */ +/******************************************/ +static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1( + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + opus_int signalType, /* I Signal type */ + const opus_int32 x_Q10[], /* I */ + opus_int8 pulses[], /* O */ + opus_int16 xq[], /* O */ + opus_int32 sLTP_Q15[], /* I/O LTP filter state */ + opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */ + 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 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 subfr, /* I Subframe number */ + opus_int shapingLPCOrder, /* I Shaping LPC filter order */ + opus_int predictLPCOrder, /* I Prediction filter order */ + opus_int warping_Q16, /* I */ + opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ + opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ + opus_int decisionDelay /* I */ +); + +void silk_NSQ_del_dec_sse4_1( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_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 */ +) +{ + opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr; + opus_int last_smple_idx, smpl_buf_idx, decisionDelay; + const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; + opus_int16 *pxq; + VARDECL( opus_int32, sLTP_Q15 ); + VARDECL( opus_int16, sLTP ); + opus_int32 HarmShapeFIRPacked_Q14; + opus_int offset_Q10; + opus_int32 RDmin_Q10, Gain_Q10; + VARDECL( opus_int32, x_sc_Q10 ); + VARDECL( opus_int32, delayedGain_Q10 ); + VARDECL( NSQ_del_dec_struct, psDelDec ); + NSQ_del_dec_struct *psDD; + SAVE_STACK; + + /* Set unvoiced lag to the previous one, overwrite later for voiced */ + lag = NSQ->lagPrev; + + silk_assert( NSQ->prev_gain_Q16 != 0 ); + + /* Initialize delayed decision states */ + ALLOC( psDelDec, psEncC->nStatesDelayedDecision, NSQ_del_dec_struct ); + silk_memset( psDelDec, 0, psEncC->nStatesDelayedDecision * sizeof( NSQ_del_dec_struct ) ); + for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + psDD->Seed = ( k + psIndices->Seed ) & 3; + psDD->SeedInit = psDD->Seed; + psDD->RD_Q10 = 0; + psDD->LF_AR_Q14 = NSQ->sLF_AR_shp_Q14; + psDD->Shape_Q14[ 0 ] = NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ]; + silk_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); + silk_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) ); + } + + offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; + smpl_buf_idx = 0; /* index of oldest samples */ + + decisionDelay = silk_min_int( DECISION_DELAY, psEncC->subfr_length ); + + /* For voiced frames limit the decision delay to lower than the pitch lag */ + if( psIndices->signalType == TYPE_VOICED ) { + for( k = 0; k < psEncC->nb_subfr; k++ ) { + decisionDelay = silk_min_int( decisionDelay, pitchL[ k ] - LTP_ORDER / 2 - 1 ); + } + } else { + if( lag > 0 ) { + decisionDelay = silk_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 ); + } + } + + if( psIndices->NLSFInterpCoef_Q2 == 4 ) { + LSF_interpolation_flag = 0; + } else { + LSF_interpolation_flag = 1; + } + + ALLOC( sLTP_Q15, + psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 ); + ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 ); + ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 ); + ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 ); + /* Set up pointers to start of sub frame */ + pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; + NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + subfr = 0; + for( k = 0; k < psEncC->nb_subfr; k++ ) { + A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ]; + B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; + AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; + + /* Noise shape parameters */ + silk_assert( HarmShapeGain_Q14[ k ] >= 0 ); + HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); + HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); + + NSQ->rewhite_flag = 0; + if( psIndices->signalType == TYPE_VOICED ) { + /* Voiced */ + lag = pitchL[ k ]; + + /* Re-whitening */ + if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { + if( k == 2 ) { + /* RESET DELAYED DECISIONS */ + /* Find winner */ + RDmin_Q10 = psDelDec[ 0 ].RD_Q10; + Winner_ind = 0; + for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) { + if( psDelDec[ i ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psDelDec[ i ].RD_Q10; + Winner_ind = i; + } + } + for( i = 0; i < psEncC->nStatesDelayedDecision; i++ ) { + if( i != Winner_ind ) { + psDelDec[ i ].RD_Q10 += ( silk_int32_MAX >> 4 ); + silk_assert( psDelDec[ i ].RD_Q10 >= 0 ); + } + } + + /* Copy final part of signals from winner state to output and long-term filter states */ + psDD = &psDelDec[ Winner_ind ]; + last_smple_idx = smpl_buf_idx + decisionDelay; + for( i = 0; i < decisionDelay; i++ ) { + last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; + pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); + pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( + silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) ); + NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ]; + } + + subfr = 0; + } + + /* Rewhiten with new A coefs */ + start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; + silk_assert( start_idx > 0 ); + + silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], + A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch ); + + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + NSQ->rewhite_flag = 1; + } + } + + silk_nsq_del_dec_scale_states_sse4_1( psEncC, NSQ, psDelDec, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, + psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay ); + + silk_noise_shape_quantizer_del_dec_sse4_1( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, + delayedGain_Q10, A_Q12, B_Q14, AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], + Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder, + psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay ); + + x_Q3 += psEncC->subfr_length; + pulses += psEncC->subfr_length; + pxq += psEncC->subfr_length; + } + + /* Find winner */ + RDmin_Q10 = psDelDec[ 0 ].RD_Q10; + Winner_ind = 0; + for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) { + if( psDelDec[ k ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psDelDec[ k ].RD_Q10; + Winner_ind = k; + } + } + + /* Copy final part of signals from winner state to output and long-term filter states */ + psDD = &psDelDec[ Winner_ind ]; + psIndices->Seed = psDD->SeedInit; + last_smple_idx = smpl_buf_idx + decisionDelay; + Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 ); + for( i = 0; i < decisionDelay; i++ ) { + last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; + pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); + pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( + silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) ); + NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ]; + } + silk_memcpy( NSQ->sLPC_Q14, &psDD->sLPC_Q14[ psEncC->subfr_length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); + silk_memcpy( NSQ->sAR2_Q14, psDD->sAR2_Q14, sizeof( psDD->sAR2_Q14 ) ); + + /* Update states */ + NSQ->sLF_AR_shp_Q14 = psDD->LF_AR_Q14; + NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; + + /* Save quantized speech signal */ + /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */ + silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); + silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); + RESTORE_STACK; +} + +/******************************************/ +/* Noise shape quantizer for one subframe */ +/******************************************/ +static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1( + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + opus_int signalType, /* I Signal type */ + const opus_int32 x_Q10[], /* I */ + opus_int8 pulses[], /* O */ + opus_int16 xq[], /* O */ + opus_int32 sLTP_Q15[], /* I/O LTP filter state */ + opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */ + 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 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 subfr, /* I Subframe number */ + opus_int shapingLPCOrder, /* I Shaping LPC filter order */ + opus_int predictLPCOrder, /* I Prediction filter order */ + opus_int warping_Q16, /* I */ + opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ + opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ + opus_int decisionDelay /* I */ +) +{ + opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx; + opus_int32 Winner_rand_state; + opus_int32 LTP_pred_Q14, LPC_pred_Q14, n_AR_Q14, n_LTP_Q14; + opus_int32 n_LF_Q14, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10; + opus_int32 q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10; + opus_int32 tmp1, tmp2, sLF_AR_shp_Q14; + opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14; + VARDECL( NSQ_sample_pair, psSampleState ); + NSQ_del_dec_struct *psDD; + NSQ_sample_struct *psSS; + + __m128i a_Q12_0123, a_Q12_4567, a_Q12_89AB, a_Q12_CDEF; + __m128i b_Q12_0123, b_sr_Q12_0123; + SAVE_STACK; + + silk_assert( nStatesDelayedDecision > 0 ); + ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair ); + + shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; + pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 ); + + a_Q12_0123 = OP_CVTEPI16_EPI32_M64( a_Q12 ); + a_Q12_4567 = OP_CVTEPI16_EPI32_M64( a_Q12 + 4 ); + + if( opus_likely( predictLPCOrder == 16 ) ) { + a_Q12_89AB = OP_CVTEPI16_EPI32_M64( a_Q12 + 8 ); + a_Q12_CDEF = OP_CVTEPI16_EPI32_M64( a_Q12 + 12 ); + } + + if( signalType == TYPE_VOICED ){ + b_Q12_0123 = OP_CVTEPI16_EPI32_M64( b_Q14 ); + b_sr_Q12_0123 = _mm_shuffle_epi32( b_Q12_0123, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ + } + for( i = 0; i < length; i++ ) { + /* Perform common calculations used in all states */ + + /* Long-term prediction */ + if( signalType == TYPE_VOICED ) { + /* Unrolled loop */ + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LTP_pred_Q14 = 2; + { + __m128i tmpa, tmpb, pred_lag_ptr_tmp; + pred_lag_ptr_tmp = _mm_loadu_si128( (__m128i *)(&pred_lag_ptr[ -3 ] ) ); + pred_lag_ptr_tmp = _mm_shuffle_epi32( pred_lag_ptr_tmp, 0x1B ); + tmpa = _mm_mul_epi32( pred_lag_ptr_tmp, b_Q12_0123 ); + tmpa = _mm_srli_si128( tmpa, 2 ); + + pred_lag_ptr_tmp = _mm_shuffle_epi32( pred_lag_ptr_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) );/* equal shift right 4 bytes */ + pred_lag_ptr_tmp = _mm_mul_epi32( pred_lag_ptr_tmp, b_sr_Q12_0123 ); + pred_lag_ptr_tmp = _mm_srli_si128( pred_lag_ptr_tmp, 2 ); + pred_lag_ptr_tmp = _mm_add_epi32( pred_lag_ptr_tmp, tmpa ); + + tmpb = _mm_shuffle_epi32( pred_lag_ptr_tmp, _MM_SHUFFLE( 0, 0, 3, 2 ) );/* equal shift right 8 bytes */ + pred_lag_ptr_tmp = _mm_add_epi32( pred_lag_ptr_tmp, tmpb ); + LTP_pred_Q14 += _mm_cvtsi128_si32( pred_lag_ptr_tmp ); + + LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); + LTP_pred_Q14 = silk_LSHIFT( LTP_pred_Q14, 1 ); /* Q13 -> Q14 */ + pred_lag_ptr++; + } + } else { + LTP_pred_Q14 = 0; + } + + /* Long-term shaping */ + if( lag > 0 ) { + /* Symmetric, packed FIR coefficients */ + n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); + n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); + n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */ + shp_lag_ptr++; + } else { + n_LTP_Q14 = 0; + } + { + __m128i tmpa, tmpb, psLPC_Q14_tmp, a_Q12_tmp; + + for( k = 0; k < nStatesDelayedDecision; k++ ) { + /* Delayed decision state */ + psDD = &psDelDec[ k ]; + + /* Sample state */ + psSS = psSampleState[ k ]; + + /* Generate dither */ + psDD->Seed = silk_RAND( psDD->Seed ); + + /* Pointer used in short term prediction and shaping */ + psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ]; + /* Short-term prediction */ + silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 ); + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LPC_pred_Q14 = silk_RSHIFT( predictLPCOrder, 1 ); + + tmpb = _mm_setzero_si128(); + + /* step 1 */ + psLPC_Q14_tmp = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -3 ] ) ); /* -3, -2 , -1, 0 */ + psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, 0x1B ); /* 0, -1, -2, -3 */ + tmpa = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_0123 ); /* 0, -1, -2, -3 * 0123 -> 0*0, 2*-2 */ + + tmpa = _mm_srli_epi64( tmpa, 16 ); + tmpb = _mm_add_epi32( tmpb, tmpa ); + + psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ + a_Q12_tmp = _mm_shuffle_epi32( a_Q12_0123, _MM_SHUFFLE(0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ + psLPC_Q14_tmp = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_tmp ); /* 1*-1, 3*-3 */ + psLPC_Q14_tmp = _mm_srli_epi64( psLPC_Q14_tmp, 16 ); + tmpb = _mm_add_epi32( tmpb, psLPC_Q14_tmp ); + + /* step 2 */ + psLPC_Q14_tmp = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -7 ] ) ); + psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, 0x1B ); + tmpa = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_4567 ); + tmpa = _mm_srli_epi64( tmpa, 16 ); + tmpb = _mm_add_epi32( tmpb, tmpa ); + + psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ + a_Q12_tmp = _mm_shuffle_epi32( a_Q12_4567, _MM_SHUFFLE(0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ + psLPC_Q14_tmp = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_tmp ); + psLPC_Q14_tmp = _mm_srli_epi64( psLPC_Q14_tmp, 16 ); + tmpb = _mm_add_epi32( tmpb, psLPC_Q14_tmp ); + + if ( opus_likely( predictLPCOrder == 16 ) ) + { + /* step 3 */ + psLPC_Q14_tmp = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -11 ] ) ); + psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, 0x1B ); + tmpa = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_89AB ); + tmpa = _mm_srli_epi64( tmpa, 16 ); + tmpb = _mm_add_epi32( tmpb, tmpa ); + + psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ + a_Q12_tmp = _mm_shuffle_epi32( a_Q12_89AB, _MM_SHUFFLE(0, 3, 2, 1 ) );/* equal shift right 4 bytes */ + psLPC_Q14_tmp = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_tmp ); + psLPC_Q14_tmp = _mm_srli_epi64( psLPC_Q14_tmp, 16 ); + tmpb = _mm_add_epi32( tmpb, psLPC_Q14_tmp ); + + /* setp 4 */ + psLPC_Q14_tmp = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -15 ] ) ); + psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, 0x1B ); + tmpa = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_CDEF ); + tmpa = _mm_srli_epi64( tmpa, 16 ); + tmpb = _mm_add_epi32( tmpb, tmpa ); + + psLPC_Q14_tmp = _mm_shuffle_epi32( psLPC_Q14_tmp, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ + a_Q12_tmp = _mm_shuffle_epi32( a_Q12_CDEF, _MM_SHUFFLE(0, 3, 2, 1 ) ); /* equal shift right 4 bytes */ + psLPC_Q14_tmp = _mm_mul_epi32( psLPC_Q14_tmp, a_Q12_tmp ); + psLPC_Q14_tmp = _mm_srli_epi64( psLPC_Q14_tmp, 16 ); + tmpb = _mm_add_epi32( tmpb, psLPC_Q14_tmp ); + + /* add at last */ + /* equal shift right 8 bytes*/ + tmpa = _mm_shuffle_epi32( tmpb, _MM_SHUFFLE( 0, 0, 3, 2 ) ); + tmpb = _mm_add_epi32( tmpb, tmpa ); + LPC_pred_Q14 += _mm_cvtsi128_si32( tmpb ); + } + else + { + /* add at last */ + tmpa = _mm_shuffle_epi32( tmpb, _MM_SHUFFLE( 0, 0, 3, 2 ) ); /* equal shift right 8 bytes*/ + tmpb = _mm_add_epi32( tmpb, tmpa ); + LPC_pred_Q14 += _mm_cvtsi128_si32( tmpb ); + + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -8 ], a_Q12[ 8 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); + } + + LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */ + + /* Noise shape feedback */ + silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ + /* Output of lowpass section */ + tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 ); + psDD->sAR2_Q14[ 0 ] = tmp2; + n_AR_Q14 = silk_RSHIFT( shapingLPCOrder, 1 ); + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ 0 ] ); + /* Loop over allpass sections */ + for( j = 2; j < shapingLPCOrder; j += 2 ) { + /* Output of allpass section */ + tmp2 = silk_SMLAWB( psDD->sAR2_Q14[ j - 1 ], psDD->sAR2_Q14[ j + 0 ] - tmp1, warping_Q16 ); + psDD->sAR2_Q14[ j - 1 ] = tmp1; + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ j - 1 ] ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ j + 0 ], psDD->sAR2_Q14[ j + 1 ] - tmp2, warping_Q16 ); + psDD->sAR2_Q14[ j + 0 ] = tmp2; + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ j ] ); + } + psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1; + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] ); + + n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 1 ); /* Q11 -> Q12 */ + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, psDD->LF_AR_Q14, Tilt_Q14 ); /* Q12 */ + n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 2 ); /* Q12 -> Q14 */ + + n_LF_Q14 = silk_SMULWB( psDD->Shape_Q14[ *smpl_buf_idx ], LF_shp_Q14 ); /* Q12 */ + n_LF_Q14 = silk_SMLAWT( n_LF_Q14, psDD->LF_AR_Q14, LF_shp_Q14 ); /* Q12 */ + n_LF_Q14 = silk_LSHIFT( n_LF_Q14, 2 ); /* Q12 -> Q14 */ + + /* Input minus prediction plus noise feedback */ + /* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */ + tmp1 = silk_ADD32( n_AR_Q14, n_LF_Q14 ); /* Q14 */ + tmp2 = silk_ADD32( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */ + tmp1 = silk_SUB32( tmp2, tmp1 ); /* Q13 */ + tmp1 = silk_RSHIFT_ROUND( tmp1, 4 ); /* Q10 */ + + r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */ + + /* Flip sign depending on dither */ + if ( psDD->Seed < 0 ) { + r_Q10 = -r_Q10; + } + r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 ); + + /* Find two quantization level candidates and measure their rate-distortion */ + q1_Q10 = silk_SUB32( r_Q10, offset_Q10 ); + q1_Q0 = silk_RSHIFT( q1_Q10, 10 ); + if( q1_Q0 > 0 ) { + q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = silk_ADD32( q1_Q10, 1024 ); + rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q0 == 0 ) { + q1_Q10 = offset_Q10; + q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q0 == -1 ) { + q2_Q10 = offset_Q10; + q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else { /* q1_Q0 < -1 */ + q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = silk_ADD32( q1_Q10, 1024 ); + rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( -q2_Q10, Lambda_Q10 ); + } + rr_Q10 = silk_SUB32( r_Q10, q1_Q10 ); + rd1_Q10 = silk_RSHIFT( silk_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 ); + rr_Q10 = silk_SUB32( r_Q10, q2_Q10 ); + rd2_Q10 = silk_RSHIFT( silk_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 ); + + if( rd1_Q10 < rd2_Q10 ) { + psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 ); + psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 ); + psSS[ 0 ].Q_Q10 = q1_Q10; + psSS[ 1 ].Q_Q10 = q2_Q10; + } else { + psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 ); + psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 ); + psSS[ 0 ].Q_Q10 = q2_Q10; + psSS[ 1 ].Q_Q10 = q1_Q10; + } + + /* Update states for best quantization */ + + /* Quantized excitation */ + exc_Q14 = silk_LSHIFT32( psSS[ 0 ].Q_Q10, 4 ); + if ( psDD->Seed < 0 ) { + exc_Q14 = -exc_Q14; + } + + /* Add predictions */ + LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 ); + xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 ); + + /* Update states */ + sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 ); + psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 ); + psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14; + psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14; + psSS[ 0 ].xq_Q14 = xq_Q14; + + /* Update states for second best quantization */ + + /* Quantized excitation */ + exc_Q14 = silk_LSHIFT32( psSS[ 1 ].Q_Q10, 4 ); + if ( psDD->Seed < 0 ) { + exc_Q14 = -exc_Q14; + } + + + /* Add predictions */ + LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 ); + xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 ); + + /* Update states */ + sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 ); + psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 ); + psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14; + psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14; + psSS[ 1 ].xq_Q14 = xq_Q14; + } + } + *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */ + last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */ + + /* Find winner */ + RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; + Winner_ind = 0; + for( k = 1; k < nStatesDelayedDecision; k++ ) { + if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psSampleState[ k ][ 0 ].RD_Q10; + Winner_ind = k; + } + } + + /* Increase RD values of expired states */ + Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ]; + for( k = 0; k < nStatesDelayedDecision; k++ ) { + if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) { + psSampleState[ k ][ 0 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 0 ].RD_Q10, silk_int32_MAX >> 4 ); + psSampleState[ k ][ 1 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 1 ].RD_Q10, silk_int32_MAX >> 4 ); + silk_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 ); + } + } + + /* Find worst in first set and best in second set */ + RDmax_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; + RDmin_Q10 = psSampleState[ 0 ][ 1 ].RD_Q10; + RDmax_ind = 0; + RDmin_ind = 0; + for( k = 1; k < nStatesDelayedDecision; k++ ) { + /* find worst in first set */ + if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) { + RDmax_Q10 = psSampleState[ k ][ 0 ].RD_Q10; + RDmax_ind = k; + } + /* find best in second set */ + if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psSampleState[ k ][ 1 ].RD_Q10; + RDmin_ind = k; + } + } + + /* Replace a state if best from second set outperforms worst in first set */ + if( RDmin_Q10 < RDmax_Q10 ) { + silk_memcpy( ( (opus_int32 *)&psDelDec[ RDmax_ind ] ) + i, + ( (opus_int32 *)&psDelDec[ RDmin_ind ] ) + i, sizeof( NSQ_del_dec_struct ) - i * sizeof( opus_int32) ); + silk_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) ); + } + + /* Write samples from winner to output and long-term filter states */ + psDD = &psDelDec[ Winner_ind ]; + if( subfr > 0 || i >= decisionDelay ) { + pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); + xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( + silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], delayedGain_Q10[ last_smple_idx ] ), 8 ) ); + NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q14[ last_smple_idx ]; + sLTP_Q15[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q15[ last_smple_idx ]; + } + NSQ->sLTP_shp_buf_idx++; + NSQ->sLTP_buf_idx++; + + /* Update states */ + for( k = 0; k < nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + psSS = &psSampleState[ k ][ 0 ]; + psDD->LF_AR_Q14 = psSS->LF_AR_Q14; + psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14; + psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14; + psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10; + psDD->Pred_Q15[ *smpl_buf_idx ] = silk_LSHIFT32( psSS->LPC_exc_Q14, 1 ); + psDD->Shape_Q14[ *smpl_buf_idx ] = psSS->sLTP_shp_Q14; + psDD->Seed = silk_ADD32_ovflw( psDD->Seed, silk_RSHIFT_ROUND( psSS->Q_Q10, 10 ) ); + psDD->RandState[ *smpl_buf_idx ] = psDD->Seed; + psDD->RD_Q10 = psSS->RD_Q10; + } + delayedGain_Q10[ *smpl_buf_idx ] = Gain_Q10; + } + /* Update LPC states */ + for( k = 0; k < nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + silk_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); + } + RESTORE_STACK; +} + +static OPUS_INLINE void silk_nsq_del_dec_scale_states_sse4_1( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + const opus_int32 x_Q3[], /* I Input in Q3 */ + opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */ + const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ + opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ + opus_int subfr, /* I Subframe number */ + opus_int nStatesDelayedDecision, /* I Number of del dec states */ + const opus_int LTP_scale_Q14, /* I LTP state scaling */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ + const opus_int signal_type, /* I Signal type */ + const opus_int decisionDelay /* I Decision delay */ +) +{ + opus_int i, k, lag; + opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23; + NSQ_del_dec_struct *psDD; + __m128i xmm_inv_gain_Q23, xmm_x_Q3_x2x0, xmm_x_Q3_x3x1; + + lag = pitchL[ subfr ]; + inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 ); + + silk_assert( inv_gain_Q31 != 0 ); + + /* Calculate gain adjustment factor */ + if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) { + gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 ); + } else { + gain_adj_Q16 = (opus_int32)1 << 16; + } + + /* Scale input */ + inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 ); + + /* prepare inv_gain_Q23 in packed 4 32-bits */ + xmm_inv_gain_Q23 = _mm_set1_epi32(inv_gain_Q23); + + for( i = 0; i < psEncC->subfr_length - 3; i += 4 ) { + xmm_x_Q3_x2x0 = _mm_loadu_si128( (__m128i *)(&(x_Q3[ i ] ) ) ); + /* equal shift right 4 bytes*/ + xmm_x_Q3_x3x1 = _mm_shuffle_epi32( xmm_x_Q3_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) ); + + xmm_x_Q3_x2x0 = _mm_mul_epi32( xmm_x_Q3_x2x0, xmm_inv_gain_Q23 ); + xmm_x_Q3_x3x1 = _mm_mul_epi32( xmm_x_Q3_x3x1, xmm_inv_gain_Q23 ); + + xmm_x_Q3_x2x0 = _mm_srli_epi64( xmm_x_Q3_x2x0, 16 ); + xmm_x_Q3_x3x1 = _mm_slli_epi64( xmm_x_Q3_x3x1, 16 ); + + xmm_x_Q3_x2x0 = _mm_blend_epi16( xmm_x_Q3_x2x0, xmm_x_Q3_x3x1, 0xCC ); + + _mm_storeu_si128( (__m128i *)(&(x_sc_Q10[ i ])), xmm_x_Q3_x2x0 ); + } + + for( ; i < psEncC->subfr_length; i++ ) { + x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 ); + } + + /* Save inverse gain */ + NSQ->prev_gain_Q16 = Gains_Q16[ subfr ]; + + /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ + if( NSQ->rewhite_flag ) { + if( subfr == 0 ) { + /* Do LTP downscaling */ + inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 ); + } + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { + silk_assert( i < MAX_FRAME_LENGTH ); + sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] ); + } + } + + /* Adjust for changing gain */ + if( gain_adj_Q16 != (opus_int32)1 << 16 ) { + /* Scale long-term shaping state */ + { + __m128i xmm_gain_adj_Q16, xmm_sLTP_shp_Q14_x2x0, xmm_sLTP_shp_Q14_x3x1; + + /* prepare gain_adj_Q16 in packed 4 32-bits */ + xmm_gain_adj_Q16 = _mm_set1_epi32( gain_adj_Q16 ); + + for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx - 3; i += 4 ) + { + xmm_sLTP_shp_Q14_x2x0 = _mm_loadu_si128( (__m128i *)(&(NSQ->sLTP_shp_Q14[ i ] ) ) ); + /* equal shift right 4 bytes*/ + xmm_sLTP_shp_Q14_x3x1 = _mm_shuffle_epi32( xmm_sLTP_shp_Q14_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) ); + + xmm_sLTP_shp_Q14_x2x0 = _mm_mul_epi32( xmm_sLTP_shp_Q14_x2x0, xmm_gain_adj_Q16 ); + xmm_sLTP_shp_Q14_x3x1 = _mm_mul_epi32( xmm_sLTP_shp_Q14_x3x1, xmm_gain_adj_Q16 ); + + xmm_sLTP_shp_Q14_x2x0 = _mm_srli_epi64( xmm_sLTP_shp_Q14_x2x0, 16 ); + xmm_sLTP_shp_Q14_x3x1 = _mm_slli_epi64( xmm_sLTP_shp_Q14_x3x1, 16 ); + + xmm_sLTP_shp_Q14_x2x0 = _mm_blend_epi16( xmm_sLTP_shp_Q14_x2x0, xmm_sLTP_shp_Q14_x3x1, 0xCC ); + + _mm_storeu_si128( (__m128i *)(&(NSQ->sLTP_shp_Q14[ i ] ) ), xmm_sLTP_shp_Q14_x2x0 ); + } + + for( ; i < NSQ->sLTP_shp_buf_idx; i++ ) { + NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] ); + } + + /* Scale long-term prediction state */ + if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) { + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) { + sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] ); + } + } + + for( k = 0; k < nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + + /* Scale scalar states */ + psDD->LF_AR_Q14 = silk_SMULWW( gain_adj_Q16, psDD->LF_AR_Q14 ); + + /* Scale short-term prediction and shaping states */ + for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { + psDD->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sLPC_Q14[ i ] ); + } + for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { + psDD->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sAR2_Q14[ i ] ); + } + for( i = 0; i < DECISION_DELAY; i++ ) { + psDD->Pred_Q15[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Pred_Q15[ i ] ); + psDD->Shape_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Shape_Q14[ i ] ); + } + } + } + } +} diff --git a/thirdparty/opus/silk/x86/NSQ_sse.c b/thirdparty/opus/silk/x86/NSQ_sse.c new file mode 100644 index 0000000000..72f34fd6fc --- /dev/null +++ b/thirdparty/opus/silk/x86/NSQ_sse.c @@ -0,0 +1,720 @@ +/* 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 "main.h" +#include "celt/x86/x86cpu.h" +#include "stack_alloc.h" + +static OPUS_INLINE void silk_nsq_scale_states_sse4_1( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + const opus_int32 x_Q3[], /* I input in Q3 */ + opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */ + const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */ + opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ + opus_int subfr, /* I subframe number */ + const opus_int LTP_scale_Q14, /* I */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ + const opus_int signal_type /* I Signal type */ +); + +static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1( + 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 offset_Q10, /* I */ + opus_int length, /* I Input length */ + opus_int32 table[][4] /* I */ +); + +void silk_NSQ_sse4_1( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_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 */ +) +{ + opus_int k, lag, start_idx, LSF_interpolation_flag; + const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; + opus_int16 *pxq; + VARDECL( opus_int32, sLTP_Q15 ); + VARDECL( opus_int16, sLTP ); + opus_int32 HarmShapeFIRPacked_Q14; + opus_int offset_Q10; + VARDECL( opus_int32, x_sc_Q10 ); + + opus_int32 table[ 64 ][ 4 ]; + opus_int32 tmp1; + opus_int32 q1_Q10, q2_Q10, rd1_Q20, rd2_Q20; + + SAVE_STACK; + + NSQ->rand_seed = psIndices->Seed; + + /* Set unvoiced lag to the previous one, overwrite later for voiced */ + lag = NSQ->lagPrev; + + silk_assert( NSQ->prev_gain_Q16 != 0 ); + + offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; + + /* 0 */ + q1_Q10 = offset_Q10; + q2_Q10 = offset_Q10 + ( 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q20 = q1_Q10 * Lambda_Q10; + rd2_Q20 = q2_Q10 * Lambda_Q10; + + table[ 32 ][ 0 ] = q1_Q10; + table[ 32 ][ 1 ] = q2_Q10; + table[ 32 ][ 2 ] = 2 * (q1_Q10 - q2_Q10); + table[ 32 ][ 3 ] = (rd1_Q20 - rd2_Q20) + (q1_Q10 * q1_Q10 - q2_Q10 * q2_Q10); + + /* -1 */ + q1_Q10 = offset_Q10 - ( 1024 - QUANT_LEVEL_ADJUST_Q10 ); + q2_Q10 = offset_Q10; + rd1_Q20 = - q1_Q10 * Lambda_Q10; + rd2_Q20 = q2_Q10 * Lambda_Q10; + + table[ 31 ][ 0 ] = q1_Q10; + table[ 31 ][ 1 ] = q2_Q10; + table[ 31 ][ 2 ] = 2 * (q1_Q10 - q2_Q10); + table[ 31 ][ 3 ] = (rd1_Q20 - rd2_Q20) + (q1_Q10 * q1_Q10 - q2_Q10 * q2_Q10); + + /* > 0 */ + for (k = 1; k <= 31; k++) + { + tmp1 = offset_Q10 + silk_LSHIFT( k, 10 ); + + q1_Q10 = tmp1 - QUANT_LEVEL_ADJUST_Q10; + q2_Q10 = tmp1 - QUANT_LEVEL_ADJUST_Q10 + 1024; + rd1_Q20 = q1_Q10 * Lambda_Q10; + rd2_Q20 = q2_Q10 * Lambda_Q10; + + table[ 32 + k ][ 0 ] = q1_Q10; + table[ 32 + k ][ 1 ] = q2_Q10; + table[ 32 + k ][ 2 ] = 2 * (q1_Q10 - q2_Q10); + table[ 32 + k ][ 3 ] = (rd1_Q20 - rd2_Q20) + (q1_Q10 * q1_Q10 - q2_Q10 * q2_Q10); + } + + /* < -1 */ + for (k = -32; k <= -2; k++) + { + tmp1 = offset_Q10 + silk_LSHIFT( k, 10 ); + + q1_Q10 = tmp1 + QUANT_LEVEL_ADJUST_Q10; + q2_Q10 = tmp1 + QUANT_LEVEL_ADJUST_Q10 + 1024; + rd1_Q20 = - q1_Q10 * Lambda_Q10; + rd2_Q20 = - q2_Q10 * Lambda_Q10; + + table[ 32 + k ][ 0 ] = q1_Q10; + table[ 32 + k ][ 1 ] = q2_Q10; + table[ 32 + k ][ 2 ] = 2 * (q1_Q10 - q2_Q10); + table[ 32 + k ][ 3 ] = (rd1_Q20 - rd2_Q20) + (q1_Q10 * q1_Q10 - q2_Q10 * q2_Q10); + } + + if( psIndices->NLSFInterpCoef_Q2 == 4 ) { + LSF_interpolation_flag = 0; + } else { + LSF_interpolation_flag = 1; + } + + ALLOC( sLTP_Q15, + psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 ); + ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 ); + ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 ); + /* Set up pointers to start of sub frame */ + NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; + for( k = 0; k < psEncC->nb_subfr; k++ ) { + A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ]; + B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; + AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; + + /* Noise shape parameters */ + silk_assert( HarmShapeGain_Q14[ k ] >= 0 ); + HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); + HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); + + NSQ->rewhite_flag = 0; + if( psIndices->signalType == TYPE_VOICED ) { + /* Voiced */ + lag = pitchL[ k ]; + + /* Re-whitening */ + if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { + /* Rewhiten with new A coefs */ + start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; + silk_assert( start_idx > 0 ); + + silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], + A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch ); + + NSQ->rewhite_flag = 1; + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + } + } + + silk_nsq_scale_states_sse4_1( psEncC, NSQ, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType ); + + if ( opus_likely( ( 10 == psEncC->shapingLPCOrder ) && ( 16 == psEncC->predictLPCOrder) ) ) + { + silk_noise_shape_quantizer_10_16_sse4_1( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14, + AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], + offset_Q10, psEncC->subfr_length, &(table[32]) ); + } + else + { + silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14, + AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10, + offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder ); + } + + x_Q3 += psEncC->subfr_length; + pulses += psEncC->subfr_length; + pxq += psEncC->subfr_length; + } + + /* Update lagPrev for next frame */ + NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; + + /* Save quantized speech and noise shaping signals */ + /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */ + silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); + silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); + RESTORE_STACK; +} + +/***********************************/ +/* silk_noise_shape_quantizer_10_16 */ +/***********************************/ +static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1( + 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 offset_Q10, /* I */ + opus_int length, /* I Input length */ + opus_int32 table[][4] /* I */ +) +{ + opus_int i; + opus_int32 LTP_pred_Q13, LPC_pred_Q10, n_AR_Q12, n_LTP_Q13; + opus_int32 n_LF_Q12, r_Q10, q1_Q0, q1_Q10, q2_Q10; + opus_int32 exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10; + opus_int32 tmp1, tmp2, sLF_AR_shp_Q14; + opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr; + + __m128i xmm_tempa, xmm_tempb; + + __m128i xmm_one; + + __m128i psLPC_Q14_hi_01234567, psLPC_Q14_hi_89ABCDEF; + __m128i psLPC_Q14_lo_01234567, psLPC_Q14_lo_89ABCDEF; + __m128i a_Q12_01234567, a_Q12_89ABCDEF; + + __m128i sAR2_Q14_hi_76543210, sAR2_Q14_lo_76543210; + __m128i AR_shp_Q13_76543210; + + shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; + pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 ); + + /* Set up short term AR state */ + psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ]; + + sLF_AR_shp_Q14 = NSQ->sLF_AR_shp_Q14; + xq_Q14 = psLPC_Q14[ 0 ]; + LTP_pred_Q13 = 0; + + /* load a_Q12 */ + xmm_one = _mm_set_epi8( 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 ); + + /* load a_Q12[0] - a_Q12[7] */ + a_Q12_01234567 = _mm_loadu_si128( (__m128i *)(&a_Q12[ 0 ] ) ); + /* load a_Q12[ 8 ] - a_Q12[ 15 ] */ + a_Q12_89ABCDEF = _mm_loadu_si128( (__m128i *)(&a_Q12[ 8 ] ) ); + + a_Q12_01234567 = _mm_shuffle_epi8( a_Q12_01234567, xmm_one ); + a_Q12_89ABCDEF = _mm_shuffle_epi8( a_Q12_89ABCDEF, xmm_one ); + + /* load AR_shp_Q13 */ + AR_shp_Q13_76543210 = _mm_loadu_si128( (__m128i *)(&AR_shp_Q13[0] ) ); + + /* load psLPC_Q14 */ + xmm_one = _mm_set_epi8(15, 14, 11, 10, 7, 6, 3, 2, 13, 12, 9, 8, 5, 4, 1, 0 ); + + xmm_tempa = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[-16]) ); + xmm_tempb = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[-12]) ); + + xmm_tempa = _mm_shuffle_epi8( xmm_tempa, xmm_one ); + xmm_tempb = _mm_shuffle_epi8( xmm_tempb, xmm_one ); + + psLPC_Q14_hi_89ABCDEF = _mm_unpackhi_epi64( xmm_tempa, xmm_tempb ); + psLPC_Q14_lo_89ABCDEF = _mm_unpacklo_epi64( xmm_tempa, xmm_tempb ); + + xmm_tempa = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -8 ]) ); + xmm_tempb = _mm_loadu_si128( (__m128i *)(&psLPC_Q14[ -4 ]) ); + + xmm_tempa = _mm_shuffle_epi8( xmm_tempa, xmm_one ); + xmm_tempb = _mm_shuffle_epi8( xmm_tempb, xmm_one ); + + psLPC_Q14_hi_01234567 = _mm_unpackhi_epi64( xmm_tempa, xmm_tempb ); + psLPC_Q14_lo_01234567 = _mm_unpacklo_epi64( xmm_tempa, xmm_tempb ); + + /* load sAR2_Q14 */ + xmm_tempa = _mm_loadu_si128( (__m128i *)(&(NSQ->sAR2_Q14[ 0 ]) ) ); + xmm_tempb = _mm_loadu_si128( (__m128i *)(&(NSQ->sAR2_Q14[ 4 ]) ) ); + + xmm_tempa = _mm_shuffle_epi8( xmm_tempa, xmm_one ); + xmm_tempb = _mm_shuffle_epi8( xmm_tempb, xmm_one ); + + sAR2_Q14_hi_76543210 = _mm_unpackhi_epi64( xmm_tempa, xmm_tempb ); + sAR2_Q14_lo_76543210 = _mm_unpacklo_epi64( xmm_tempa, xmm_tempb ); + + /* prepare 1 in 8 * 16bit */ + xmm_one = _mm_set1_epi16(1); + + for( i = 0; i < length; i++ ) + { + /* Short-term prediction */ + __m128i xmm_hi_07, xmm_hi_8F, xmm_lo_07, xmm_lo_8F; + + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LPC_pred_Q10 = 8; /* silk_RSHIFT( predictLPCOrder, 1 ); */ + + /* shift psLPC_Q14 */ + psLPC_Q14_hi_89ABCDEF = _mm_alignr_epi8( psLPC_Q14_hi_01234567, psLPC_Q14_hi_89ABCDEF, 2 ); + psLPC_Q14_lo_89ABCDEF = _mm_alignr_epi8( psLPC_Q14_lo_01234567, psLPC_Q14_lo_89ABCDEF, 2 ); + + psLPC_Q14_hi_01234567 = _mm_srli_si128( psLPC_Q14_hi_01234567, 2 ); + psLPC_Q14_lo_01234567 = _mm_srli_si128( psLPC_Q14_lo_01234567, 2 ); + + psLPC_Q14_hi_01234567 = _mm_insert_epi16( psLPC_Q14_hi_01234567, (xq_Q14 >> 16), 7 ); + psLPC_Q14_lo_01234567 = _mm_insert_epi16( psLPC_Q14_lo_01234567, (xq_Q14), 7 ); + + /* high part, use pmaddwd, results in 4 32-bit */ + xmm_hi_07 = _mm_madd_epi16( psLPC_Q14_hi_01234567, a_Q12_01234567 ); + xmm_hi_8F = _mm_madd_epi16( psLPC_Q14_hi_89ABCDEF, a_Q12_89ABCDEF ); + + /* low part, use pmulhw, results in 8 16-bit, note we need simulate unsigned * signed, _mm_srai_epi16(psLPC_Q14_lo_01234567, 15) */ + xmm_tempa = _mm_cmpgt_epi16( _mm_setzero_si128(), psLPC_Q14_lo_01234567 ); + xmm_tempb = _mm_cmpgt_epi16( _mm_setzero_si128(), psLPC_Q14_lo_89ABCDEF ); + + xmm_tempa = _mm_and_si128( xmm_tempa, a_Q12_01234567 ); + xmm_tempb = _mm_and_si128( xmm_tempb, a_Q12_89ABCDEF ); + + xmm_lo_07 = _mm_mulhi_epi16( psLPC_Q14_lo_01234567, a_Q12_01234567 ); + xmm_lo_8F = _mm_mulhi_epi16( psLPC_Q14_lo_89ABCDEF, a_Q12_89ABCDEF ); + + xmm_lo_07 = _mm_add_epi16( xmm_lo_07, xmm_tempa ); + xmm_lo_8F = _mm_add_epi16( xmm_lo_8F, xmm_tempb ); + + xmm_lo_07 = _mm_madd_epi16( xmm_lo_07, xmm_one ); + xmm_lo_8F = _mm_madd_epi16( xmm_lo_8F, xmm_one ); + + /* accumulate */ + xmm_hi_07 = _mm_add_epi32( xmm_hi_07, xmm_hi_8F ); + xmm_lo_07 = _mm_add_epi32( xmm_lo_07, xmm_lo_8F ); + + xmm_hi_07 = _mm_add_epi32( xmm_hi_07, xmm_lo_07 ); + + xmm_hi_07 = _mm_add_epi32( xmm_hi_07, _mm_unpackhi_epi64(xmm_hi_07, xmm_hi_07 ) ); + xmm_hi_07 = _mm_add_epi32( xmm_hi_07, _mm_shufflelo_epi16(xmm_hi_07, 0x0E ) ); + + LPC_pred_Q10 += _mm_cvtsi128_si32( xmm_hi_07 ); + + /* Long-term prediction */ + if ( opus_likely( signalType == TYPE_VOICED ) ) { + /* Unrolled loop */ + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LTP_pred_Q13 = 2; + { + __m128i b_Q14_3210, b_Q14_0123, pred_lag_ptr_0123; + + b_Q14_3210 = OP_CVTEPI16_EPI32_M64( b_Q14 ); + b_Q14_0123 = _mm_shuffle_epi32( b_Q14_3210, 0x1B ); + + /* loaded: [0] [-1] [-2] [-3] */ + pred_lag_ptr_0123 = _mm_loadu_si128( (__m128i *)(&pred_lag_ptr[ -3 ] ) ); + /* shuffle to [-3] [-2] [-1] [0] and to new xmm */ + xmm_tempa = _mm_shuffle_epi32( pred_lag_ptr_0123, 0x1B ); + /*64-bit multiply, a[2] * b[-2], a[0] * b[0] */ + xmm_tempa = _mm_mul_epi32( xmm_tempa, b_Q14_3210 ); + /* right shift 2 bytes (16 bits), zero extended */ + xmm_tempa = _mm_srli_si128( xmm_tempa, 2 ); + + /* a[1] * b[-1], a[3] * b[-3] */ + pred_lag_ptr_0123 = _mm_mul_epi32( pred_lag_ptr_0123, b_Q14_0123 ); + pred_lag_ptr_0123 = _mm_srli_si128( pred_lag_ptr_0123, 2 ); + + pred_lag_ptr_0123 = _mm_add_epi32( pred_lag_ptr_0123, xmm_tempa ); + /* equal shift right 8 bytes*/ + xmm_tempa = _mm_shuffle_epi32( pred_lag_ptr_0123, _MM_SHUFFLE( 0, 0, 3, 2 ) ); + xmm_tempa = _mm_add_epi32( xmm_tempa, pred_lag_ptr_0123 ); + + LTP_pred_Q13 += _mm_cvtsi128_si32( xmm_tempa ); + + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); + pred_lag_ptr++; + } + } + + /* Noise shape feedback */ + NSQ->sAR2_Q14[ 9 ] = NSQ->sAR2_Q14[ 8 ]; + NSQ->sAR2_Q14[ 8 ] = _mm_cvtsi128_si32( _mm_srli_si128(_mm_unpackhi_epi16( sAR2_Q14_lo_76543210, sAR2_Q14_hi_76543210 ), 12 ) ); + + sAR2_Q14_hi_76543210 = _mm_slli_si128( sAR2_Q14_hi_76543210, 2 ); + sAR2_Q14_lo_76543210 = _mm_slli_si128( sAR2_Q14_lo_76543210, 2 ); + + sAR2_Q14_hi_76543210 = _mm_insert_epi16( sAR2_Q14_hi_76543210, (xq_Q14 >> 16), 0 ); + sAR2_Q14_lo_76543210 = _mm_insert_epi16( sAR2_Q14_lo_76543210, (xq_Q14), 0 ); + + /* high part, use pmaddwd, results in 4 32-bit */ + xmm_hi_07 = _mm_madd_epi16( sAR2_Q14_hi_76543210, AR_shp_Q13_76543210 ); + + /* low part, use pmulhw, results in 8 16-bit, note we need simulate unsigned * signed,_mm_srai_epi16(sAR2_Q14_lo_76543210, 15) */ + xmm_tempa = _mm_cmpgt_epi16( _mm_setzero_si128(), sAR2_Q14_lo_76543210 ); + xmm_tempa = _mm_and_si128( xmm_tempa, AR_shp_Q13_76543210 ); + + xmm_lo_07 = _mm_mulhi_epi16( sAR2_Q14_lo_76543210, AR_shp_Q13_76543210 ); + xmm_lo_07 = _mm_add_epi16( xmm_lo_07, xmm_tempa ); + + xmm_lo_07 = _mm_madd_epi16( xmm_lo_07, xmm_one ); + + /* accumulate */ + xmm_hi_07 = _mm_add_epi32( xmm_hi_07, xmm_lo_07 ); + + xmm_hi_07 = _mm_add_epi32( xmm_hi_07, _mm_unpackhi_epi64(xmm_hi_07, xmm_hi_07 ) ); + xmm_hi_07 = _mm_add_epi32( xmm_hi_07, _mm_shufflelo_epi16(xmm_hi_07, 0x0E ) ); + + n_AR_Q12 = 5 + _mm_cvtsi128_si32( xmm_hi_07 ); + + n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sAR2_Q14[ 8 ], AR_shp_Q13[ 8 ] ); + n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sAR2_Q14[ 9 ], AR_shp_Q13[ 9 ] ); + + n_AR_Q12 = silk_LSHIFT32( n_AR_Q12, 1 ); /* Q11 -> Q12 */ + n_AR_Q12 = silk_SMLAWB( n_AR_Q12, sLF_AR_shp_Q14, Tilt_Q14 ); + + n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 ); + n_LF_Q12 = silk_SMLAWT( n_LF_Q12, sLF_AR_shp_Q14, LF_shp_Q14 ); + + silk_assert( lag > 0 || signalType != TYPE_VOICED ); + + /* Combine prediction and noise shaping signals */ + tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */ + tmp1 = silk_SUB32( tmp1, n_LF_Q12 ); /* Q12 */ + if( lag > 0 ) { + /* Symmetric, packed FIR coefficients */ + n_LTP_Q13 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); + n_LTP_Q13 = silk_SMLAWT( n_LTP_Q13, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); + n_LTP_Q13 = silk_LSHIFT( n_LTP_Q13, 1 ); + shp_lag_ptr++; + + tmp2 = silk_SUB32( LTP_pred_Q13, n_LTP_Q13 ); /* Q13 */ + tmp1 = silk_ADD_LSHIFT32( tmp2, tmp1, 1 ); /* Q13 */ + tmp1 = silk_RSHIFT_ROUND( tmp1, 3 ); /* Q10 */ + } else { + tmp1 = silk_RSHIFT_ROUND( tmp1, 2 ); /* Q10 */ + } + + r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */ + + /* Generate dither */ + NSQ->rand_seed = silk_RAND( NSQ->rand_seed ); + + /* Flip sign depending on dither */ + tmp2 = -r_Q10; + if ( NSQ->rand_seed < 0 ) r_Q10 = tmp2; + + r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 ); + + /* Find two quantization level candidates and measure their rate-distortion */ + q1_Q10 = silk_SUB32( r_Q10, offset_Q10 ); + q1_Q0 = silk_RSHIFT( q1_Q10, 10 ); + + q1_Q10 = table[q1_Q0][0]; + q2_Q10 = table[q1_Q0][1]; + + if (r_Q10 * table[q1_Q0][2] - table[q1_Q0][3] < 0) + { + q1_Q10 = q2_Q10; + } + + pulses[ i ] = (opus_int8)silk_RSHIFT_ROUND( q1_Q10, 10 ); + + /* Excitation */ + exc_Q14 = silk_LSHIFT( q1_Q10, 4 ); + + tmp2 = -exc_Q14; + if ( NSQ->rand_seed < 0 ) exc_Q14 = tmp2; + + /* Add predictions */ + LPC_exc_Q14 = silk_ADD_LSHIFT32( exc_Q14, LTP_pred_Q13, 1 ); + xq_Q14 = silk_ADD_LSHIFT32( LPC_exc_Q14, LPC_pred_Q10, 4 ); + + /* Update states */ + psLPC_Q14++; + *psLPC_Q14 = xq_Q14; + sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, n_AR_Q12, 2 ); + + NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 ); + sLTP_Q15[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q14, 1 ); + NSQ->sLTP_shp_buf_idx++; + NSQ->sLTP_buf_idx++; + + /* Make dither dependent on quantized signal */ + NSQ->rand_seed = silk_ADD32_ovflw( NSQ->rand_seed, pulses[ i ] ); + } + + NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14; + + /* Scale XQ back to normal level before saving */ + psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH ]; + + /* write back sAR2_Q14 */ + xmm_tempa = _mm_unpackhi_epi16( sAR2_Q14_lo_76543210, sAR2_Q14_hi_76543210 ); + xmm_tempb = _mm_unpacklo_epi16( sAR2_Q14_lo_76543210, sAR2_Q14_hi_76543210 ); + _mm_storeu_si128( (__m128i *)(&NSQ->sAR2_Q14[ 4 ]), xmm_tempa ); + _mm_storeu_si128( (__m128i *)(&NSQ->sAR2_Q14[ 0 ]), xmm_tempb ); + + /* xq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( psLPC_Q14[ i ], Gain_Q10 ), 8 ) ); */ + { + __m128i xmm_Gain_Q10; + __m128i xmm_xq_Q14_3210, xmm_xq_Q14_x3x1, xmm_xq_Q14_7654, xmm_xq_Q14_x7x5; + + /* prepare (1 << 7) in packed 4 32-bits */ + xmm_tempa = _mm_set1_epi32( (1 << 7) ); + + /* prepare Gain_Q10 in packed 4 32-bits */ + xmm_Gain_Q10 = _mm_set1_epi32( Gain_Q10 ); + + /* process xq */ + for (i = 0; i < length - 7; i += 8) + { + xmm_xq_Q14_3210 = _mm_loadu_si128( (__m128i *)(&(psLPC_Q14[ i + 0 ] ) ) ); + xmm_xq_Q14_7654 = _mm_loadu_si128( (__m128i *)(&(psLPC_Q14[ i + 4 ] ) ) ); + + /* equal shift right 4 bytes*/ + xmm_xq_Q14_x3x1 = _mm_shuffle_epi32( xmm_xq_Q14_3210, _MM_SHUFFLE( 0, 3, 2, 1 ) ); + /* equal shift right 4 bytes*/ + xmm_xq_Q14_x7x5 = _mm_shuffle_epi32( xmm_xq_Q14_7654, _MM_SHUFFLE( 0, 3, 2, 1 ) ); + + xmm_xq_Q14_3210 = _mm_mul_epi32( xmm_xq_Q14_3210, xmm_Gain_Q10 ); + xmm_xq_Q14_x3x1 = _mm_mul_epi32( xmm_xq_Q14_x3x1, xmm_Gain_Q10 ); + xmm_xq_Q14_7654 = _mm_mul_epi32( xmm_xq_Q14_7654, xmm_Gain_Q10 ); + xmm_xq_Q14_x7x5 = _mm_mul_epi32( xmm_xq_Q14_x7x5, xmm_Gain_Q10 ); + + xmm_xq_Q14_3210 = _mm_srli_epi64( xmm_xq_Q14_3210, 16 ); + xmm_xq_Q14_x3x1 = _mm_slli_epi64( xmm_xq_Q14_x3x1, 16 ); + xmm_xq_Q14_7654 = _mm_srli_epi64( xmm_xq_Q14_7654, 16 ); + xmm_xq_Q14_x7x5 = _mm_slli_epi64( xmm_xq_Q14_x7x5, 16 ); + + xmm_xq_Q14_3210 = _mm_blend_epi16( xmm_xq_Q14_3210, xmm_xq_Q14_x3x1, 0xCC ); + xmm_xq_Q14_7654 = _mm_blend_epi16( xmm_xq_Q14_7654, xmm_xq_Q14_x7x5, 0xCC ); + + /* silk_RSHIFT_ROUND(xq, 8) */ + xmm_xq_Q14_3210 = _mm_add_epi32( xmm_xq_Q14_3210, xmm_tempa ); + xmm_xq_Q14_7654 = _mm_add_epi32( xmm_xq_Q14_7654, xmm_tempa ); + + xmm_xq_Q14_3210 = _mm_srai_epi32( xmm_xq_Q14_3210, 8 ); + xmm_xq_Q14_7654 = _mm_srai_epi32( xmm_xq_Q14_7654, 8 ); + + /* silk_SAT16 */ + xmm_xq_Q14_3210 = _mm_packs_epi32( xmm_xq_Q14_3210, xmm_xq_Q14_7654 ); + + /* save to xq */ + _mm_storeu_si128( (__m128i *)(&xq[ i ] ), xmm_xq_Q14_3210 ); + } + } + for ( ; i < length; i++) + { + xq[i] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( psLPC_Q14[ i ], Gain_Q10 ), 8 ) ); + } + + /* Update LPC synth buffer */ + silk_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); +} + +static OPUS_INLINE void silk_nsq_scale_states_sse4_1( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + const opus_int32 x_Q3[], /* I input in Q3 */ + opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */ + const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */ + opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ + opus_int subfr, /* I subframe number */ + const opus_int LTP_scale_Q14, /* I */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ + const opus_int signal_type /* I Signal type */ +) +{ + opus_int i, lag; + opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23; + __m128i xmm_inv_gain_Q23, xmm_x_Q3_x2x0, xmm_x_Q3_x3x1; + + lag = pitchL[ subfr ]; + inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 ); + silk_assert( inv_gain_Q31 != 0 ); + + /* Calculate gain adjustment factor */ + if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) { + gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 ); + } else { + gain_adj_Q16 = (opus_int32)1 << 16; + } + + /* Scale input */ + inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 ); + + /* prepare inv_gain_Q23 in packed 4 32-bits */ + xmm_inv_gain_Q23 = _mm_set1_epi32(inv_gain_Q23); + + for( i = 0; i < psEncC->subfr_length - 3; i += 4 ) { + xmm_x_Q3_x2x0 = _mm_loadu_si128( (__m128i *)(&(x_Q3[ i ] ) ) ); + + /* equal shift right 4 bytes*/ + xmm_x_Q3_x3x1 = _mm_shuffle_epi32( xmm_x_Q3_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) ); + + xmm_x_Q3_x2x0 = _mm_mul_epi32( xmm_x_Q3_x2x0, xmm_inv_gain_Q23 ); + xmm_x_Q3_x3x1 = _mm_mul_epi32( xmm_x_Q3_x3x1, xmm_inv_gain_Q23 ); + + xmm_x_Q3_x2x0 = _mm_srli_epi64( xmm_x_Q3_x2x0, 16 ); + xmm_x_Q3_x3x1 = _mm_slli_epi64( xmm_x_Q3_x3x1, 16 ); + + xmm_x_Q3_x2x0 = _mm_blend_epi16( xmm_x_Q3_x2x0, xmm_x_Q3_x3x1, 0xCC ); + + _mm_storeu_si128( (__m128i *)(&(x_sc_Q10[ i ] ) ), xmm_x_Q3_x2x0 ); + } + + for( ; i < psEncC->subfr_length; i++ ) { + x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 ); + } + + /* Save inverse gain */ + NSQ->prev_gain_Q16 = Gains_Q16[ subfr ]; + + /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ + if( NSQ->rewhite_flag ) { + if( subfr == 0 ) { + /* Do LTP downscaling */ + inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 ); + } + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { + silk_assert( i < MAX_FRAME_LENGTH ); + sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] ); + } + } + + /* Adjust for changing gain */ + if( gain_adj_Q16 != (opus_int32)1 << 16 ) { + /* Scale long-term shaping state */ + __m128i xmm_gain_adj_Q16, xmm_sLTP_shp_Q14_x2x0, xmm_sLTP_shp_Q14_x3x1; + + /* prepare gain_adj_Q16 in packed 4 32-bits */ + xmm_gain_adj_Q16 = _mm_set1_epi32(gain_adj_Q16); + + for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx - 3; i += 4 ) + { + xmm_sLTP_shp_Q14_x2x0 = _mm_loadu_si128( (__m128i *)(&(NSQ->sLTP_shp_Q14[ i ] ) ) ); + /* equal shift right 4 bytes*/ + xmm_sLTP_shp_Q14_x3x1 = _mm_shuffle_epi32( xmm_sLTP_shp_Q14_x2x0, _MM_SHUFFLE( 0, 3, 2, 1 ) ); + + xmm_sLTP_shp_Q14_x2x0 = _mm_mul_epi32( xmm_sLTP_shp_Q14_x2x0, xmm_gain_adj_Q16 ); + xmm_sLTP_shp_Q14_x3x1 = _mm_mul_epi32( xmm_sLTP_shp_Q14_x3x1, xmm_gain_adj_Q16 ); + + xmm_sLTP_shp_Q14_x2x0 = _mm_srli_epi64( xmm_sLTP_shp_Q14_x2x0, 16 ); + xmm_sLTP_shp_Q14_x3x1 = _mm_slli_epi64( xmm_sLTP_shp_Q14_x3x1, 16 ); + + xmm_sLTP_shp_Q14_x2x0 = _mm_blend_epi16( xmm_sLTP_shp_Q14_x2x0, xmm_sLTP_shp_Q14_x3x1, 0xCC ); + + _mm_storeu_si128( (__m128i *)(&(NSQ->sLTP_shp_Q14[ i ] ) ), xmm_sLTP_shp_Q14_x2x0 ); + } + + for( ; i < NSQ->sLTP_shp_buf_idx; i++ ) { + NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] ); + } + + /* Scale long-term prediction state */ + if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) { + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { + sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] ); + } + } + + NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 ); + + /* Scale short-term prediction and shaping states */ + for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { + NSQ->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] ); + } + for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { + NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] ); + } + } +} diff --git a/thirdparty/opus/silk/x86/SigProc_FIX_sse.h b/thirdparty/opus/silk/x86/SigProc_FIX_sse.h new file mode 100644 index 0000000000..61efa8da41 --- /dev/null +++ b/thirdparty/opus/silk/x86/SigProc_FIX_sse.h @@ -0,0 +1,94 @@ +/* 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 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)) + +#else + +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 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_aligned_64_sse4_1( + const opus_int16 *inVec1, + const opus_int16 *inVec2, + const opus_int len +); + + +#if defined(OPUS_X86_PRESUME_SSE4_1) + +#define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \ + ((void)(arch),silk_inner_prod16_aligned_64_sse4_1(inVec1, inVec2, len)) + +#else + +extern opus_int64 (*const SILK_INNER_PROD16_ALIGNED_64_IMPL[OPUS_ARCHMASK + 1])( + const opus_int16 *inVec1, + const opus_int16 *inVec2, + const opus_int len); + +# define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \ + ((*SILK_INNER_PROD16_ALIGNED_64_IMPL[(arch) & OPUS_ARCHMASK])(inVec1, inVec2, len)) + +#endif +#endif +#endif diff --git a/thirdparty/opus/silk/x86/VAD_sse.c b/thirdparty/opus/silk/x86/VAD_sse.c new file mode 100644 index 0000000000..4e90f4410d --- /dev/null +++ b/thirdparty/opus/silk/x86/VAD_sse.c @@ -0,0 +1,277 @@ +/* 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 "main.h" +#include "stack_alloc.h" + +/* Weighting factors for tilt measure */ +static const opus_int32 tiltWeights[ VAD_N_BANDS ] = { 30000, 6000, -12000, -12000 }; + +/***************************************/ +/* Get the speech activity level in Q8 */ +/***************************************/ +opus_int silk_VAD_GetSA_Q8_sse4_1( /* O Return value, 0 if success */ + silk_encoder_state *psEncC, /* I/O Encoder state */ + const opus_int16 pIn[] /* I PCM input */ +) +{ + opus_int SA_Q15, pSNR_dB_Q7, input_tilt; + opus_int decimated_framelength1, decimated_framelength2; + opus_int decimated_framelength; + opus_int dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s; + opus_int32 sumSquared, smooth_coef_Q16; + opus_int16 HPstateTmp; + VARDECL( opus_int16, X ); + opus_int32 Xnrg[ VAD_N_BANDS ]; + opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ]; + opus_int32 speech_nrg, x_tmp; + opus_int X_offset[ VAD_N_BANDS ]; + opus_int ret = 0; + silk_VAD_state *psSilk_VAD = &psEncC->sVAD; + + SAVE_STACK; + + /* Safety checks */ + silk_assert( VAD_N_BANDS == 4 ); + silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length ); + silk_assert( psEncC->frame_length <= 512 ); + silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) ); + + /***********************/ + /* Filter and Decimate */ + /***********************/ + decimated_framelength1 = silk_RSHIFT( psEncC->frame_length, 1 ); + decimated_framelength2 = silk_RSHIFT( psEncC->frame_length, 2 ); + decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 ); + /* Decimate into 4 bands: + 0 L 3L L 3L 5L + - -- - -- -- + 8 8 2 4 4 + + [0-1 kHz| temp. |1-2 kHz| 2-4 kHz | 4-8 kHz | + + They're arranged to allow the minimal ( frame_length / 4 ) extra + scratch space during the downsampling process */ + X_offset[ 0 ] = 0; + X_offset[ 1 ] = decimated_framelength + decimated_framelength2; + X_offset[ 2 ] = X_offset[ 1 ] + decimated_framelength; + X_offset[ 3 ] = X_offset[ 2 ] + decimated_framelength2; + ALLOC( X, X_offset[ 3 ] + decimated_framelength1, opus_int16 ); + + /* 0-8 kHz to 0-4 kHz and 4-8 kHz */ + silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ], + X, &X[ X_offset[ 3 ] ], psEncC->frame_length ); + + /* 0-4 kHz to 0-2 kHz and 2-4 kHz */ + silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState1[ 0 ], + X, &X[ X_offset[ 2 ] ], decimated_framelength1 ); + + /* 0-2 kHz to 0-1 kHz and 1-2 kHz */ + silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState2[ 0 ], + X, &X[ X_offset[ 1 ] ], decimated_framelength2 ); + + /*********************************************/ + /* HP filter on lowest band (differentiator) */ + /*********************************************/ + X[ decimated_framelength - 1 ] = silk_RSHIFT( X[ decimated_framelength - 1 ], 1 ); + HPstateTmp = X[ decimated_framelength - 1 ]; + for( i = decimated_framelength - 1; i > 0; i-- ) { + X[ i - 1 ] = silk_RSHIFT( X[ i - 1 ], 1 ); + X[ i ] -= X[ i - 1 ]; + } + X[ 0 ] -= psSilk_VAD->HPstate; + psSilk_VAD->HPstate = HPstateTmp; + + /*************************************/ + /* Calculate the energy in each band */ + /*************************************/ + for( b = 0; b < VAD_N_BANDS; b++ ) { + /* Find the decimated framelength in the non-uniformly divided bands */ + decimated_framelength = silk_RSHIFT( psEncC->frame_length, silk_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) ); + + /* Split length into subframe lengths */ + dec_subframe_length = silk_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 ); + dec_subframe_offset = 0; + + /* Compute energy per sub-frame */ + /* initialize with summed energy of last subframe */ + Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ]; + for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) { + __m128i xmm_X, xmm_acc; + sumSquared = 0; + + xmm_acc = _mm_setzero_si128(); + + for( i = 0; i < dec_subframe_length - 7; i += 8 ) + { + xmm_X = _mm_loadu_si128( (__m128i *)&(X[ X_offset[ b ] + i + dec_subframe_offset ] ) ); + xmm_X = _mm_srai_epi16( xmm_X, 3 ); + xmm_X = _mm_madd_epi16( xmm_X, xmm_X ); + xmm_acc = _mm_add_epi32( xmm_acc, xmm_X ); + } + + xmm_acc = _mm_add_epi32( xmm_acc, _mm_unpackhi_epi64( xmm_acc, xmm_acc ) ); + xmm_acc = _mm_add_epi32( xmm_acc, _mm_shufflelo_epi16( xmm_acc, 0x0E ) ); + + sumSquared += _mm_cvtsi128_si32( xmm_acc ); + + for( ; i < dec_subframe_length; i++ ) { + /* The energy will be less than dec_subframe_length * ( silk_int16_MIN / 8 ) ^ 2. */ + /* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */ + x_tmp = silk_RSHIFT( + X[ X_offset[ b ] + i + dec_subframe_offset ], 3 ); + sumSquared = silk_SMLABB( sumSquared, x_tmp, x_tmp ); + + /* Safety check */ + silk_assert( sumSquared >= 0 ); + } + + /* Add/saturate summed energy of current subframe */ + if( s < VAD_INTERNAL_SUBFRAMES - 1 ) { + Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], sumSquared ); + } else { + /* Look-ahead subframe */ + Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], silk_RSHIFT( sumSquared, 1 ) ); + } + + dec_subframe_offset += dec_subframe_length; + } + psSilk_VAD->XnrgSubfr[ b ] = sumSquared; + } + + /********************/ + /* Noise estimation */ + /********************/ + silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD ); + + /***********************************************/ + /* Signal-plus-noise to noise ratio estimation */ + /***********************************************/ + sumSquared = 0; + input_tilt = 0; + for( b = 0; b < VAD_N_BANDS; b++ ) { + speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ]; + if( speech_nrg > 0 ) { + /* Divide, with sufficient resolution */ + if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) { + NrgToNoiseRatio_Q8[ b ] = silk_DIV32( silk_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 ); + } else { + NrgToNoiseRatio_Q8[ b ] = silk_DIV32( Xnrg[ b ], silk_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 ); + } + + /* Convert to log domain */ + SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128; + + /* Sum-of-squares */ + sumSquared = silk_SMLABB( sumSquared, SNR_Q7, SNR_Q7 ); /* Q14 */ + + /* Tilt measure */ + if( speech_nrg < ( (opus_int32)1 << 20 ) ) { + /* Scale down SNR value for small subband speech energies */ + SNR_Q7 = silk_SMULWB( silk_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 ); + } + input_tilt = silk_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 ); + } else { + NrgToNoiseRatio_Q8[ b ] = 256; + } + } + + /* Mean-of-squares */ + sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */ + + /* Root-mean-square approximation, scale to dBs, and write to output pointer */ + pSNR_dB_Q7 = (opus_int16)( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */ + + /*********************************/ + /* Speech Probability Estimation */ + /*********************************/ + SA_Q15 = silk_sigm_Q15( silk_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 ); + + /**************************/ + /* Frequency Tilt Measure */ + /**************************/ + psEncC->input_tilt_Q15 = silk_LSHIFT( silk_sigm_Q15( input_tilt ) - 16384, 1 ); + + /**************************************************/ + /* Scale the sigmoid output based on power levels */ + /**************************************************/ + speech_nrg = 0; + for( b = 0; b < VAD_N_BANDS; b++ ) { + /* Accumulate signal-without-noise energies, higher frequency bands have more weight */ + speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 ); + } + + /* Power scaling */ + if( speech_nrg <= 0 ) { + SA_Q15 = silk_RSHIFT( SA_Q15, 1 ); + } else if( speech_nrg < 32768 ) { + if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { + speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 16 ); + } else { + speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 15 ); + } + + /* square-root */ + speech_nrg = silk_SQRT_APPROX( speech_nrg ); + SA_Q15 = silk_SMULWB( 32768 + speech_nrg, SA_Q15 ); + } + + /* Copy the resulting speech activity in Q8 */ + psEncC->speech_activity_Q8 = silk_min_int( silk_RSHIFT( SA_Q15, 7 ), silk_uint8_MAX ); + + /***********************************/ + /* Energy Level and SNR estimation */ + /***********************************/ + /* Smoothing coefficient */ + smooth_coef_Q16 = silk_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, silk_SMULWB( (opus_int32)SA_Q15, SA_Q15 ) ); + + if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { + smooth_coef_Q16 >>= 1; + } + + for( b = 0; b < VAD_N_BANDS; b++ ) { + /* compute smoothed energy-to-noise ratio per band */ + psSilk_VAD->NrgRatioSmth_Q8[ b ] = silk_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ], + NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 ); + + /* signal to noise ratio in dB per band */ + SNR_Q7 = 3 * ( silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 ); + /* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */ + psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( silk_RSHIFT( SNR_Q7 - 16 * 128, 4 ) ); + } + + RESTORE_STACK; + return( ret ); +} diff --git a/thirdparty/opus/silk/x86/VQ_WMat_EC_sse.c b/thirdparty/opus/silk/x86/VQ_WMat_EC_sse.c new file mode 100644 index 0000000000..74d6c6d0ec --- /dev/null +++ b/thirdparty/opus/silk/x86/VQ_WMat_EC_sse.c @@ -0,0 +1,142 @@ +/* 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 "main.h" +#include "celt/x86/x86cpu.h" + +/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */ +void silk_VQ_WMat_EC_sse4_1( + opus_int8 *ind, /* O index of best codebook vector */ + opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */ + opus_int *gain_Q7, /* O sum of absolute LTP coefficients */ + const opus_int16 *in_Q14, /* I input vector to be quantized */ + const opus_int32 *W_Q18, /* I weighting matrix */ + 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 mu_Q9, /* I tradeoff betw. weighted error and rate */ + const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ + opus_int L /* I number of vectors in codebook */ +) +{ + opus_int k, gain_tmp_Q7; + const opus_int8 *cb_row_Q7; + opus_int16 diff_Q14[ 5 ]; + opus_int32 sum1_Q14, sum2_Q16; + + __m128i C_tmp1, C_tmp2, C_tmp3, C_tmp4, C_tmp5; + /* Loop over codebook */ + *rate_dist_Q14 = silk_int32_MAX; + cb_row_Q7 = cb_Q7; + for( k = 0; k < L; k++ ) { + gain_tmp_Q7 = cb_gain_Q7[k]; + + diff_Q14[ 0 ] = in_Q14[ 0 ] - silk_LSHIFT( cb_row_Q7[ 0 ], 7 ); + + C_tmp1 = OP_CVTEPI16_EPI32_M64( &in_Q14[ 1 ] ); + C_tmp2 = OP_CVTEPI8_EPI32_M32( &cb_row_Q7[ 1 ] ); + C_tmp2 = _mm_slli_epi32( C_tmp2, 7 ); + C_tmp1 = _mm_sub_epi32( C_tmp1, C_tmp2 ); + + diff_Q14[ 1 ] = _mm_extract_epi16( C_tmp1, 0 ); + diff_Q14[ 2 ] = _mm_extract_epi16( C_tmp1, 2 ); + diff_Q14[ 3 ] = _mm_extract_epi16( C_tmp1, 4 ); + diff_Q14[ 4 ] = _mm_extract_epi16( C_tmp1, 6 ); + + /* Weighted rate */ + sum1_Q14 = silk_SMULBB( mu_Q9, cl_Q5[ k ] ); + + /* Penalty for too large gain */ + sum1_Q14 = silk_ADD_LSHIFT32( sum1_Q14, silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 10 ); + + silk_assert( sum1_Q14 >= 0 ); + + /* first row of W_Q18 */ + C_tmp3 = _mm_loadu_si128( (__m128i *)(&W_Q18[ 1 ] ) ); + C_tmp4 = _mm_mul_epi32( C_tmp3, C_tmp1 ); + C_tmp4 = _mm_srli_si128( C_tmp4, 2 ); + + C_tmp1 = _mm_shuffle_epi32( C_tmp1, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* shift right 4 bytes */ + C_tmp3 = _mm_shuffle_epi32( C_tmp3, _MM_SHUFFLE( 0, 3, 2, 1 ) ); /* shift right 4 bytes */ + + C_tmp5 = _mm_mul_epi32( C_tmp3, C_tmp1 ); + C_tmp5 = _mm_srli_si128( C_tmp5, 2 ); + + C_tmp5 = _mm_add_epi32( C_tmp4, C_tmp5 ); + C_tmp5 = _mm_slli_epi32( C_tmp5, 1 ); + + C_tmp5 = _mm_add_epi32( C_tmp5, _mm_shuffle_epi32( C_tmp5, _MM_SHUFFLE( 0, 0, 0, 2 ) ) ); + sum2_Q16 = _mm_cvtsi128_si32( C_tmp5 ); + + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] ); + + /* second row of W_Q18 */ + sum2_Q16 = silk_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] ); + sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] ); + + /* third row of W_Q18 */ + sum2_Q16 = silk_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] ); + sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] ); + + /* fourth row of W_Q18 */ + sum2_Q16 = silk_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] ); + sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] ); + + /* last row of W_Q18 */ + sum2_Q16 = silk_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] ); + + silk_assert( sum1_Q14 >= 0 ); + + /* find best */ + if( sum1_Q14 < *rate_dist_Q14 ) { + *rate_dist_Q14 = sum1_Q14; + *ind = (opus_int8)k; + *gain_Q7 = gain_tmp_Q7; + } + + /* Go to next cbk vector */ + cb_row_Q7 += LTP_ORDER; + } +} diff --git a/thirdparty/opus/silk/x86/main_sse.h b/thirdparty/opus/silk/x86/main_sse.h new file mode 100644 index 0000000000..afd5ec26e1 --- /dev/null +++ b/thirdparty/opus/silk/x86/main_sse.h @@ -0,0 +1,276 @@ +/* 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) + +# define OVERRIDE_silk_VQ_WMat_EC + +void silk_VQ_WMat_EC_sse4_1( + opus_int8 *ind, /* O index of best codebook vector */ + opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */ + opus_int *gain_Q7, /* O sum of absolute LTP coefficients */ + const opus_int16 *in_Q14, /* I input vector to be quantized */ + const opus_int32 *W_Q18, /* I weighting matrix */ + 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 mu_Q9, /* I tradeoff betw. weighted error and rate */ + const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ + opus_int L /* I number of vectors in codebook */ +); + +#if defined OPUS_X86_PRESUME_SSE4_1 + +#define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \ + mu_Q9, max_gain_Q7, L, arch) \ + ((void)(arch),silk_VQ_WMat_EC_sse4_1(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \ + mu_Q9, max_gain_Q7, L)) + +#else + +extern void (*const SILK_VQ_WMAT_EC_IMPL[OPUS_ARCHMASK + 1])( + opus_int8 *ind, /* O index of best codebook vector */ + opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */ + opus_int *gain_Q7, /* O sum of absolute LTP coefficients */ + const opus_int16 *in_Q14, /* I input vector to be quantized */ + const opus_int32 *W_Q18, /* I weighting matrix */ + 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 mu_Q9, /* I tradeoff betw. weighted error and rate */ + const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ + opus_int L /* I number of vectors in codebook */ +); + +# define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \ + mu_Q9, max_gain_Q7, L, arch) \ + ((*SILK_VQ_WMAT_EC_IMPL[(arch) & OPUS_ARCHMASK])(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \ + mu_Q9, max_gain_Q7, L)) + +#endif + +# define OVERRIDE_silk_NSQ + +void silk_NSQ_sse4_1( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_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 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)) + +#else + +extern void (*const SILK_NSQ_IMPL[OPUS_ARCHMASK + 1])( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_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 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 + +# define OVERRIDE_silk_NSQ_del_dec + +void silk_NSQ_del_dec_sse4_1( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_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 silk_NSQ_del_dec(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_del_dec_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)) + +#else + +extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_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 silk_NSQ_del_dec(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_DEL_DEC_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_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 */ +); + +/**************************/ +/* 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 */ +); + +# define OVERRIDE_silk_VAD_GetSA_Q8 + +opus_int silk_VAD_GetSA_Q8_sse4_1( + silk_encoder_state *psEnC, + const opus_int16 pIn[] +); + +#if defined(OPUS_X86_PRESUME_SSE4_1) +#define silk_VAD_GetSA_Q8(psEnC, pIn, arch) ((void)(arch),silk_VAD_GetSA_Q8_sse4_1(psEnC, pIn)) + +#else + +# define silk_VAD_GetSA_Q8(psEnC, pIn, arch) \ + ((*SILK_VAD_GETSA_Q8_IMPL[(arch) & OPUS_ARCHMASK])(psEnC, pIn)) + +extern opus_int (*const SILK_VAD_GETSA_Q8_IMPL[OPUS_ARCHMASK + 1])( + silk_encoder_state *psEnC, + const opus_int16 pIn[]); + +# define OVERRIDE_silk_warped_LPC_analysis_filter_FIX + +#endif + +void silk_warped_LPC_analysis_filter_FIX_sse4_1( + opus_int32 state[], /* I/O State [order + 1] */ + opus_int32 res_Q2[], /* O Residual signal [length] */ + const opus_int16 coef_Q13[], /* I Coefficients [order] */ + const opus_int16 input[], /* I Input signal [length] */ + const opus_int16 lambda_Q16, /* I Warping factor */ + const opus_int length, /* I Length of input signal */ + const opus_int order /* I Filter order (even) */ +); + +#if defined(OPUS_X86_PRESUME_SSE4_1) +#define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \ + ((void)(arch),silk_warped_LPC_analysis_filter_FIX_c(state, res_Q2, coef_Q13, input, lambda_Q16, length, order)) + +#else + +extern void (*const SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[OPUS_ARCHMASK + 1])( + opus_int32 state[], /* I/O State [order + 1] */ + opus_int32 res_Q2[], /* O Residual signal [length] */ + const opus_int16 coef_Q13[], /* I Coefficients [order] */ + const opus_int16 input[], /* I Input signal [length] */ + const opus_int16 lambda_Q16, /* I Warping factor */ + const opus_int length, /* I Length of input signal */ + const opus_int order /* I Filter order (even) */ +); + +# define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \ + ((*SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[(arch) & OPUS_ARCHMASK])(state, res_Q2, coef_Q13, input, lambda_Q16, length, order)) + +#endif + +# endif +#endif diff --git a/thirdparty/opus/silk/x86/x86_silk_map.c b/thirdparty/opus/silk/x86/x86_silk_map.c new file mode 100644 index 0000000000..818841f2c1 --- /dev/null +++ b/thirdparty/opus/silk/x86/x86_silk_map.c @@ -0,0 +1,174 @@ +/* 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" +#include "pitch.h" +#include "main.h" + +#if !defined(OPUS_X86_PRESUME_SSE4_1) + +#if defined(FIXED_POINT) + +#include "fixed/main_FIX.h" + +opus_int64 (*const SILK_INNER_PROD16_ALIGNED_64_IMPL[ OPUS_ARCHMASK + 1 ] )( + const opus_int16 *inVec1, + const opus_int16 *inVec2, + const opus_int len +) = { + silk_inner_prod16_aligned_64_c, /* non-sse */ + silk_inner_prod16_aligned_64_c, + silk_inner_prod16_aligned_64_c, + MAY_HAVE_SSE4_1( silk_inner_prod16_aligned_64 ), /* sse4.1 */ + MAY_HAVE_SSE4_1( silk_inner_prod16_aligned_64 ) /* 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/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_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 *rate_dist_Q14, /* O best weighted quant error + mu * rate */ + opus_int *gain_Q7, /* O sum of absolute LTP coefficients */ + const opus_int16 *in_Q14, /* I input vector to be quantized */ + const opus_int32 *W_Q18, /* I weighting matrix */ + 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 mu_Q9, /* I tradeoff betw. weighted error and rate */ + const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ + 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/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_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_SSE4_1( silk_NSQ_del_dec ) /* avx */ +}; + +#if defined(FIXED_POINT) + +void (*const SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[ OPUS_ARCHMASK + 1 ] )( + opus_int32 state[], /* I/O State [order + 1] */ + opus_int32 res_Q2[], /* O Residual signal [length] */ + const opus_int16 coef_Q13[], /* I Coefficients [order] */ + const opus_int16 input[], /* I Input signal [length] */ + const opus_int16 lambda_Q16, /* I Warping factor */ + const opus_int length, /* I Length of input signal */ + const opus_int order /* I Filter order (even) */ +) = { + silk_warped_LPC_analysis_filter_FIX_c, /* non-sse */ + silk_warped_LPC_analysis_filter_FIX_c, + silk_warped_LPC_analysis_filter_FIX_c, + MAY_HAVE_SSE4_1( silk_warped_LPC_analysis_filter_FIX ), /* sse4.1 */ + MAY_HAVE_SSE4_1( silk_warped_LPC_analysis_filter_FIX ) /* avx */ +}; + +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 +#endif diff --git a/thirdparty/opus/stream.c b/thirdparty/opus/stream.c new file mode 100644 index 0000000000..0238a6b31b --- /dev/null +++ b/thirdparty/opus/stream.c @@ -0,0 +1,366 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: stdio-based convenience library for opening/seeking/decoding + last mod: $Id: vorbisfile.c 17573 2010-10-27 14:53:59Z xiphmont $ + + ********************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "internal.h" +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#if defined(_WIN32) +# include <io.h> +#endif + +typedef struct OpusMemStream OpusMemStream; + +#define OP_MEM_SIZE_MAX (~(size_t)0>>1) +#define OP_MEM_DIFF_MAX ((ptrdiff_t)OP_MEM_SIZE_MAX) + +/*The context information needed to read from a block of memory as if it were a + file.*/ +struct OpusMemStream{ + /*The block of memory to read from.*/ + const unsigned char *data; + /*The total size of the block. + This must be at most OP_MEM_SIZE_MAX to prevent signed overflow while + seeking.*/ + ptrdiff_t size; + /*The current file position. + This is allowed to be set arbitrarily greater than size (i.e., past the end + of the block, though we will not read data past the end of the block), but + is not allowed to be negative (i.e., before the beginning of the block).*/ + ptrdiff_t pos; +}; + +static int op_fread(void *_stream,unsigned char *_ptr,int _buf_size){ + FILE *stream; + size_t ret; + /*Check for empty read.*/ + if(_buf_size<=0)return 0; + stream=(FILE *)_stream; + ret=fread(_ptr,1,_buf_size,stream); + OP_ASSERT(ret<=(size_t)_buf_size); + /*If ret==0 and !feof(stream), there was a read error.*/ + return ret>0||feof(stream)?(int)ret:OP_EREAD; +} + +static int op_fseek(void *_stream,opus_int64 _offset,int _whence){ +#if defined(_WIN32) + /*_fseeki64() is not exposed until MSCVCRT80. + This is the default starting with MSVC 2005 (_MSC_VER>=1400), but we want + to allow linking against older MSVCRT versions for compatibility back to + XP without installing extra runtime libraries. + i686-pc-mingw32 does not have fseeko() and requires + __MSVCRT_VERSION__>=0x800 for _fseeki64(), which screws up linking with + other libraries (that don't use MSVCRT80 from MSVC 2005 by default). + i686-w64-mingw32 does have fseeko() and respects _FILE_OFFSET_BITS, but I + don't know how to detect that at compile time. + We could just use fseeko64() (which is available in both), but its + implemented using fgetpos()/fsetpos() just like this code, except without + the overflow checking, so we prefer our version.*/ + opus_int64 pos; + /*We don't use fpos_t directly because it might be a struct if __STDC__ is + non-zero or _INTEGRAL_MAX_BITS < 64. + I'm not certain when the latter is true, but someone could in theory set + the former. + Either way, it should be binary compatible with a normal 64-bit int (this + assumption is not portable, but I believe it is true for MSVCRT).*/ + OP_ASSERT(sizeof(pos)==sizeof(fpos_t)); + /*Translate the seek to an absolute one.*/ + if(_whence==SEEK_CUR){ + int ret; + ret=fgetpos((FILE *)_stream,(fpos_t *)&pos); + if(ret)return ret; + } + else if(_whence==SEEK_END)pos=_filelengthi64(_fileno((FILE *)_stream)); + else if(_whence==SEEK_SET)pos=0; + else return -1; + /*Check for errors or overflow.*/ + if(pos<0||_offset<-pos||_offset>OP_INT64_MAX-pos)return -1; + pos+=_offset; + return fsetpos((FILE *)_stream,(fpos_t *)&pos); +#else + /*This function actually conforms to the SUSv2 and POSIX.1-2001, so we prefer + it except on Windows.*/ + return fseeko((FILE *)_stream,(off_t)_offset,_whence); +#endif +} + +static opus_int64 op_ftell(void *_stream){ +#if defined(_WIN32) + /*_ftelli64() is not exposed until MSCVCRT80, and ftello()/ftello64() have + the same problems as fseeko()/fseeko64() in MingW. + See above for a more detailed explanation.*/ + opus_int64 pos; + OP_ASSERT(sizeof(pos)==sizeof(fpos_t)); + return fgetpos((FILE *)_stream,(fpos_t *)&pos)?-1:pos; +#else + /*This function actually conforms to the SUSv2 and POSIX.1-2001, so we prefer + it except on Windows.*/ + return ftello((FILE *)_stream); +#endif +} + +static const OpusFileCallbacks OP_FILE_CALLBACKS={ + op_fread, + op_fseek, + op_ftell, + (op_close_func)fclose +}; + +#if defined(_WIN32) +# include <stddef.h> +# include <errno.h> + +/*Windows doesn't accept UTF-8 by default, and we don't have a wchar_t API, + so if we just pass the path to fopen(), then there'd be no way for a user + of our API to open a Unicode filename. + Instead, we translate from UTF-8 to UTF-16 and use Windows' wchar_t API. + This makes this API more consistent with platforms where the character set + used by fopen is the same as used on disk, which is generally UTF-8, and + with our metadata API, which always uses UTF-8.*/ +static wchar_t *op_utf8_to_utf16(const char *_src){ + wchar_t *dst; + size_t len; + len=strlen(_src); + /*Worst-case output is 1 wide character per 1 input character.*/ + dst=(wchar_t *)_ogg_malloc(sizeof(*dst)*(len+1)); + if(dst!=NULL){ + size_t si; + size_t di; + for(di=si=0;si<len;si++){ + int c0; + c0=(unsigned char)_src[si]; + if(!(c0&0x80)){ + /*Start byte says this is a 1-byte sequence.*/ + dst[di++]=(wchar_t)c0; + continue; + } + else{ + int c1; + /*This is safe, because c0 was not 0 and _src is NUL-terminated.*/ + c1=(unsigned char)_src[si+1]; + if((c1&0xC0)==0x80){ + /*Found at least one continuation byte.*/ + if((c0&0xE0)==0xC0){ + wchar_t w; + /*Start byte says this is a 2-byte sequence.*/ + w=(c0&0x1F)<<6|c1&0x3F; + if(w>=0x80U){ + /*This is a 2-byte sequence that is not overlong.*/ + dst[di++]=w; + si++; + continue; + } + } + else{ + int c2; + /*This is safe, because c1 was not 0 and _src is NUL-terminated.*/ + c2=(unsigned char)_src[si+2]; + if((c2&0xC0)==0x80){ + /*Found at least two continuation bytes.*/ + if((c0&0xF0)==0xE0){ + wchar_t w; + /*Start byte says this is a 3-byte sequence.*/ + w=(c0&0xF)<<12|(c1&0x3F)<<6|c2&0x3F; + if(w>=0x800U&&(w<0xD800||w>=0xE000)&&w<0xFFFE){ + /*This is a 3-byte sequence that is not overlong, not a + UTF-16 surrogate pair value, and not a 'not a character' + value.*/ + dst[di++]=w; + si+=2; + continue; + } + } + else{ + int c3; + /*This is safe, because c2 was not 0 and _src is + NUL-terminated.*/ + c3=(unsigned char)_src[si+3]; + if((c3&0xC0)==0x80){ + /*Found at least three continuation bytes.*/ + if((c0&0xF8)==0xF0){ + opus_uint32 w; + /*Start byte says this is a 4-byte sequence.*/ + w=(c0&7)<<18|(c1&0x3F)<<12|(c2&0x3F)<<6&(c3&0x3F); + if(w>=0x10000U&&w<0x110000U){ + /*This is a 4-byte sequence that is not overlong and not + greater than the largest valid Unicode code point. + Convert it to a surrogate pair.*/ + w-=0x10000; + dst[di++]=(wchar_t)(0xD800+(w>>10)); + dst[di++]=(wchar_t)(0xDC00+(w&0x3FF)); + si+=3; + continue; + } + } + } + } + } + } + } + } + /*If we got here, we encountered an illegal UTF-8 sequence.*/ + _ogg_free(dst); + return NULL; + } + OP_ASSERT(di<=len); + dst[di]='\0'; + } + return dst; +} + +#endif + +void *op_fopen(OpusFileCallbacks *_cb,const char *_path,const char *_mode){ + FILE *fp; +#if !defined(_WIN32) + fp=fopen(_path,_mode); +#else + fp=NULL; + if(_path==NULL||_mode==NULL)errno=EINVAL; + else{ + wchar_t *wpath; + wchar_t *wmode; + wpath=op_utf8_to_utf16(_path); + wmode=op_utf8_to_utf16(_mode); + if(wmode==NULL)errno=EINVAL; + else if(wpath==NULL)errno=ENOENT; + else fp=_wfopen(wpath,wmode); + _ogg_free(wmode); + _ogg_free(wpath); + } +#endif + if(fp!=NULL)*_cb=*&OP_FILE_CALLBACKS; + return fp; +} + +void *op_fdopen(OpusFileCallbacks *_cb,int _fd,const char *_mode){ + FILE *fp; + fp=fdopen(_fd,_mode); + if(fp!=NULL)*_cb=*&OP_FILE_CALLBACKS; + return fp; +} + +void *op_freopen(OpusFileCallbacks *_cb,const char *_path,const char *_mode, + void *_stream){ + FILE *fp; +#if !defined(_WIN32) + fp=freopen(_path,_mode,(FILE *)_stream); +#else + fp=NULL; + if(_path==NULL||_mode==NULL)errno=EINVAL; + else{ + wchar_t *wpath; + wchar_t *wmode; + wpath=op_utf8_to_utf16(_path); + wmode=op_utf8_to_utf16(_mode); + if(wmode==NULL)errno=EINVAL; + else if(wpath==NULL)errno=ENOENT; + else fp=_wfreopen(wpath,wmode,(FILE *)_stream); + _ogg_free(wmode); + _ogg_free(wpath); + } +#endif + if(fp!=NULL)*_cb=*&OP_FILE_CALLBACKS; + return fp; +} + +static int op_mem_read(void *_stream,unsigned char *_ptr,int _buf_size){ + OpusMemStream *stream; + ptrdiff_t size; + ptrdiff_t pos; + stream=(OpusMemStream *)_stream; + /*Check for empty read.*/ + if(_buf_size<=0)return 0; + size=stream->size; + pos=stream->pos; + /*Check for EOF.*/ + if(pos>=size)return 0; + /*Check for a short read.*/ + _buf_size=(int)OP_MIN(size-pos,_buf_size); + memcpy(_ptr,stream->data+pos,_buf_size); + pos+=_buf_size; + stream->pos=pos; + return _buf_size; +} + +static int op_mem_seek(void *_stream,opus_int64 _offset,int _whence){ + OpusMemStream *stream; + ptrdiff_t pos; + stream=(OpusMemStream *)_stream; + pos=stream->pos; + OP_ASSERT(pos>=0); + switch(_whence){ + case SEEK_SET:{ + /*Check for overflow:*/ + if(_offset<0||_offset>OP_MEM_DIFF_MAX)return -1; + pos=(ptrdiff_t)_offset; + }break; + case SEEK_CUR:{ + /*Check for overflow:*/ + if(_offset<-pos||_offset>OP_MEM_DIFF_MAX-pos)return -1; + pos=(ptrdiff_t)(pos+_offset); + }break; + case SEEK_END:{ + ptrdiff_t size; + size=stream->size; + OP_ASSERT(size>=0); + /*Check for overflow:*/ + if(_offset>size||_offset<size-OP_MEM_DIFF_MAX)return -1; + pos=(ptrdiff_t)(size-_offset); + }break; + default:return -1; + } + stream->pos=pos; + return 0; +} + +static opus_int64 op_mem_tell(void *_stream){ + OpusMemStream *stream; + stream=(OpusMemStream *)_stream; + return (ogg_int64_t)stream->pos; +} + +static int op_mem_close(void *_stream){ + _ogg_free(_stream); + return 0; +} + +static const OpusFileCallbacks OP_MEM_CALLBACKS={ + op_mem_read, + op_mem_seek, + op_mem_tell, + op_mem_close +}; + +void *op_mem_stream_create(OpusFileCallbacks *_cb, + const unsigned char *_data,size_t _size){ + OpusMemStream *stream; + if(_size>OP_MEM_SIZE_MAX)return NULL; + stream=(OpusMemStream *)_ogg_malloc(sizeof(*stream)); + if(stream!=NULL){ + *_cb=*&OP_MEM_CALLBACKS; + stream->data=_data; + stream->size=_size; + stream->pos=0; + } + return stream; +} diff --git a/drivers/opus/tansig_table.h b/thirdparty/opus/tansig_table.h index c76f844a72..c76f844a72 100644 --- a/drivers/opus/tansig_table.h +++ b/thirdparty/opus/tansig_table.h diff --git a/thirdparty/opus/wincerts.c b/thirdparty/opus/wincerts.c new file mode 100644 index 0000000000..b0e35aa352 --- /dev/null +++ b/thirdparty/opus/wincerts.c @@ -0,0 +1,171 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2013 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ********************************************************************/ + +/*This should really be part of OpenSSL, but there's been a patch [1] sitting + in their bugtracker for over two years that implements this, without any + action, so I'm giving up and re-implementing it locally. + + [1] <http://rt.openssl.org/Ticket/Display.html?id=2158>*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "internal.h" +#if defined(OP_ENABLE_HTTP)&&defined(_WIN32) +/*You must include windows.h before wincrypt.h and x509.h.*/ +# define WIN32_LEAN_AND_MEAN +# define WIN32_EXTRA_LEAN +# include <windows.h> +/*You must include wincrypt.h before x509.h, too, or X509_NAME doesn't get + defined properly.*/ +# include <wincrypt.h> +# include <openssl/ssl.h> +# include <openssl/err.h> +# include <openssl/x509.h> + +static int op_capi_new(X509_LOOKUP *_lu){ + HCERTSTORE h_store; + h_store=CertOpenStore(CERT_STORE_PROV_SYSTEM_A,0,0, + CERT_STORE_OPEN_EXISTING_FLAG|CERT_STORE_READONLY_FLAG| + CERT_SYSTEM_STORE_CURRENT_USER|CERT_STORE_SHARE_CONTEXT_FLAG,"ROOT"); + if(h_store!=NULL){ + _lu->method_data=(char *)h_store; + return 1; + } + return 0; +} + +static void op_capi_free(X509_LOOKUP *_lu){ + HCERTSTORE h_store; + h_store=(HCERTSTORE)_lu->method_data; +# if defined(OP_ENABLE_ASSERTIONS) + OP_ALWAYS_TRUE(CertCloseStore(h_store,CERT_CLOSE_STORE_CHECK_FLAG)); +# else + CertCloseStore(h_store,0); +# endif +} + +static int op_capi_retrieve_by_subject(X509_LOOKUP *_lu,int _type, + X509_NAME *_name,X509_OBJECT *_ret){ + X509_OBJECT *obj; + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + obj=X509_OBJECT_retrieve_by_subject(_lu->store_ctx->objs,_type,_name); + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + if(obj!=NULL){ + _ret->type=obj->type; + memcpy(&_ret->data,&obj->data,sizeof(_ret->data)); + return 1; + } + return 0; +} + +static int op_capi_get_by_subject(X509_LOOKUP *_lu,int _type,X509_NAME *_name, + X509_OBJECT *_ret){ + HCERTSTORE h_store; + if(_name==NULL)return 0; + if(_name->bytes==NULL||_name->bytes->length<=0||_name->modified){ + if(i2d_X509_NAME(_name,NULL)<0)return 0; + OP_ASSERT(_name->bytes->length>0); + } + h_store=(HCERTSTORE)_lu->method_data; + switch(_type){ + case X509_LU_X509:{ + CERT_NAME_BLOB find_para; + PCCERT_CONTEXT cert; + X509 *x; + int ret; + /*Although X509_NAME contains a canon_enc field, that "canonical" [1] + encoding was just made up by OpenSSL. + It doesn't correspond to any actual standard, and since it drops the + initial sequence header, won't be recognized by the Crypto API. + The assumption here is that CertFindCertificateInStore() will allow any + appropriate variations in the encoding when it does its comparison. + This is, however, emphatically not true under Wine, which just compares + the encodings with memcmp(). + Most of the time things work anyway, though, and there isn't really + anything we can do to make the situation better. + + [1] A "canonical form" is defined as the one where, if you locked 10 + mathematicians in a room and asked them to come up with a + representation for something, it's the answer that 9 of them would + give you back. + I don't think OpenSSL's encoding qualifies.*/ + find_para.cbData=_name->bytes->length; + find_para.pbData=(unsigned char *)_name->bytes->data; + cert=CertFindCertificateInStore(h_store,X509_ASN_ENCODING,0, + CERT_FIND_SUBJECT_NAME,&find_para,NULL); + if(cert==NULL)return 0; + x=d2i_X509(NULL,(const unsigned char **)&cert->pbCertEncoded, + cert->cbCertEncoded); + CertFreeCertificateContext(cert); + if(x==NULL)return 0; + ret=X509_STORE_add_cert(_lu->store_ctx,x); + X509_free(x); + if(ret)return op_capi_retrieve_by_subject(_lu,_type,_name,_ret); + }break; + case X509_LU_CRL:{ + CERT_INFO cert_info; + CERT_CONTEXT find_para; + PCCRL_CONTEXT crl; + X509_CRL *x; + int ret; + ret=op_capi_retrieve_by_subject(_lu,_type,_name,_ret); + if(ret>0)return ret; + memset(&cert_info,0,sizeof(cert_info)); + cert_info.Issuer.cbData=_name->bytes->length; + cert_info.Issuer.pbData=(unsigned char *)_name->bytes->data; + memset(&find_para,0,sizeof(find_para)); + find_para.pCertInfo=&cert_info; + crl=CertFindCRLInStore(h_store,0,0,CRL_FIND_ISSUED_BY,&find_para,NULL); + if(crl==NULL)return 0; + x=d2i_X509_CRL(NULL,(const unsigned char **)&crl->pbCrlEncoded, + crl->cbCrlEncoded); + CertFreeCRLContext(crl); + if(x==NULL)return 0; + ret=X509_STORE_add_crl(_lu->store_ctx,x); + X509_CRL_free(x); + if(ret)return op_capi_retrieve_by_subject(_lu,_type,_name,_ret); + }break; + } + return 0; +} + +/*This is not const because OpenSSL doesn't allow it, even though it won't + write to it.*/ +static X509_LOOKUP_METHOD X509_LOOKUP_CAPI={ + "Load Crypto API store into cache", + op_capi_new, + op_capi_free, + NULL, + NULL, + NULL, + op_capi_get_by_subject, + NULL, + NULL, + NULL +}; + +int SSL_CTX_set_default_verify_paths_win32(SSL_CTX *_ssl_ctx){ + X509_STORE *store; + X509_LOOKUP *lu; + /*We intentionally do not add the normal default paths, as they are usually + wrong, and are just asking to be used as an exploit vector.*/ + store=SSL_CTX_get_cert_store(_ssl_ctx); + OP_ASSERT(store!=NULL); + lu=X509_STORE_add_lookup(store,&X509_LOOKUP_CAPI); + if(lu==NULL)return 0; + ERR_clear_error(); + return 1; +} + +#endif diff --git a/drivers/opus/winerrno.h b/thirdparty/opus/winerrno.h index 32a90b4ee1..32a90b4ee1 100644 --- a/drivers/opus/winerrno.h +++ b/thirdparty/opus/winerrno.h diff --git a/drivers/pvr/AlphaBitmap.h b/thirdparty/pvrtccompressor/AlphaBitmap.h index 57c6b026ea..57c6b026ea 100644 --- a/drivers/pvr/AlphaBitmap.h +++ b/thirdparty/pvrtccompressor/AlphaBitmap.h diff --git a/drivers/pvr/BitScale.cpp b/thirdparty/pvrtccompressor/BitScale.cpp index 97b3f0aa25..97b3f0aa25 100644 --- a/drivers/pvr/BitScale.cpp +++ b/thirdparty/pvrtccompressor/BitScale.cpp diff --git a/drivers/pvr/BitScale.h b/thirdparty/pvrtccompressor/BitScale.h index 36613aeeee..36613aeeee 100644 --- a/drivers/pvr/BitScale.h +++ b/thirdparty/pvrtccompressor/BitScale.h diff --git a/drivers/pvr/BitUtility.h b/thirdparty/pvrtccompressor/BitUtility.h index 588ff3e892..588ff3e892 100644 --- a/drivers/pvr/BitUtility.h +++ b/thirdparty/pvrtccompressor/BitUtility.h diff --git a/drivers/pvr/Bitmap.h b/thirdparty/pvrtccompressor/Bitmap.h index 508ed8cb75..508ed8cb75 100644 --- a/drivers/pvr/Bitmap.h +++ b/thirdparty/pvrtccompressor/Bitmap.h diff --git a/drivers/pvr/ColorRgba.h b/thirdparty/pvrtccompressor/ColorRgba.h index 0701420566..0701420566 100644 --- a/drivers/pvr/ColorRgba.h +++ b/thirdparty/pvrtccompressor/ColorRgba.h diff --git a/drivers/pvr/Interval.h b/thirdparty/pvrtccompressor/Interval.h index a7252e8375..a7252e8375 100644 --- a/drivers/pvr/Interval.h +++ b/thirdparty/pvrtccompressor/Interval.h diff --git a/thirdparty/pvrtccompressor/LICENSE.TXT b/thirdparty/pvrtccompressor/LICENSE.TXT new file mode 100644 index 0000000000..974fc09e25 --- /dev/null +++ b/thirdparty/pvrtccompressor/LICENSE.TXT @@ -0,0 +1,25 @@ +Copyright © 2014, Jeffrey Lim. All Rights Reserved. + +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. + +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "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. diff --git a/drivers/pvr/MortonTable.cpp b/thirdparty/pvrtccompressor/MortonTable.cpp index 29a5af67f6..29a5af67f6 100644 --- a/drivers/pvr/MortonTable.cpp +++ b/thirdparty/pvrtccompressor/MortonTable.cpp diff --git a/drivers/pvr/MortonTable.h b/thirdparty/pvrtccompressor/MortonTable.h index 7a27e59544..7a27e59544 100644 --- a/drivers/pvr/MortonTable.h +++ b/thirdparty/pvrtccompressor/MortonTable.h diff --git a/drivers/pvr/Point2.h b/thirdparty/pvrtccompressor/Point2.h index 89fa4b6322..89fa4b6322 100644 --- a/drivers/pvr/Point2.h +++ b/thirdparty/pvrtccompressor/Point2.h diff --git a/drivers/pvr/PvrTcDecoder.cpp b/thirdparty/pvrtccompressor/PvrTcDecoder.cpp index d8a36b342c..d8a36b342c 100644 --- a/drivers/pvr/PvrTcDecoder.cpp +++ b/thirdparty/pvrtccompressor/PvrTcDecoder.cpp diff --git a/drivers/pvr/PvrTcDecoder.h b/thirdparty/pvrtccompressor/PvrTcDecoder.h index 1b6fcf964c..1b6fcf964c 100644 --- a/drivers/pvr/PvrTcDecoder.h +++ b/thirdparty/pvrtccompressor/PvrTcDecoder.h diff --git a/drivers/pvr/PvrTcEncoder.cpp b/thirdparty/pvrtccompressor/PvrTcEncoder.cpp index 587b1320f1..587b1320f1 100644 --- a/drivers/pvr/PvrTcEncoder.cpp +++ b/thirdparty/pvrtccompressor/PvrTcEncoder.cpp diff --git a/drivers/pvr/PvrTcEncoder.h b/thirdparty/pvrtccompressor/PvrTcEncoder.h index b9344367d9..b9344367d9 100644 --- a/drivers/pvr/PvrTcEncoder.h +++ b/thirdparty/pvrtccompressor/PvrTcEncoder.h diff --git a/drivers/pvr/PvrTcPacket.cpp b/thirdparty/pvrtccompressor/PvrTcPacket.cpp index 2e40d371e8..2e40d371e8 100644 --- a/drivers/pvr/PvrTcPacket.cpp +++ b/thirdparty/pvrtccompressor/PvrTcPacket.cpp diff --git a/drivers/pvr/PvrTcPacket.h b/thirdparty/pvrtccompressor/PvrTcPacket.h index ac3b6a4dd1..ac3b6a4dd1 100644 --- a/drivers/pvr/PvrTcPacket.h +++ b/thirdparty/pvrtccompressor/PvrTcPacket.h diff --git a/drivers/pvr/RgbBitmap.h b/thirdparty/pvrtccompressor/RgbBitmap.h index cf1d78667d..cf1d78667d 100644 --- a/drivers/pvr/RgbBitmap.h +++ b/thirdparty/pvrtccompressor/RgbBitmap.h diff --git a/drivers/pvr/RgbaBitmap.h b/thirdparty/pvrtccompressor/RgbaBitmap.h index 66b5542c1a..66b5542c1a 100644 --- a/drivers/pvr/RgbaBitmap.h +++ b/thirdparty/pvrtccompressor/RgbaBitmap.h diff --git a/drivers/etc1/rg_etc1.cpp b/thirdparty/rg-etc1/rg_etc1.cpp index 8e28b53f9d..8e28b53f9d 100644 --- a/drivers/etc1/rg_etc1.cpp +++ b/thirdparty/rg-etc1/rg_etc1.cpp diff --git a/drivers/etc1/rg_etc1.h b/thirdparty/rg-etc1/rg_etc1.h index 9ce89a6cc6..9ce89a6cc6 100644 --- a/drivers/etc1/rg_etc1.h +++ b/thirdparty/rg-etc1/rg_etc1.h diff --git a/drivers/rtaudio/RtAudio.cpp b/thirdparty/rtaudio/RtAudio.cpp index 04159776f7..04159776f7 100644 --- a/drivers/rtaudio/RtAudio.cpp +++ b/thirdparty/rtaudio/RtAudio.cpp diff --git a/drivers/rtaudio/RtAudio.h b/thirdparty/rtaudio/RtAudio.h index 4392e95f32..4392e95f32 100644 --- a/drivers/rtaudio/RtAudio.h +++ b/thirdparty/rtaudio/RtAudio.h diff --git a/thirdparty/squish/alpha.cpp b/thirdparty/squish/alpha.cpp new file mode 100644 index 0000000000..7039c1a3b8 --- /dev/null +++ b/thirdparty/squish/alpha.cpp @@ -0,0 +1,350 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#include "alpha.h" + +#include <climits> +#include <algorithm> + +namespace squish { + +static int FloatToInt( float a, int limit ) +{ + // use ANSI round-to-zero behaviour to get round-to-nearest + int i = ( int )( a + 0.5f ); + + // clamp to the limit + if( i < 0 ) + i = 0; + else if( i > limit ) + i = limit; + + // done + return i; +} + +void CompressAlphaDxt3( u8 const* rgba, int mask, void* block ) +{ + u8* bytes = reinterpret_cast< u8* >( block ); + + // quantise and pack the alpha values pairwise + for( int i = 0; i < 8; ++i ) + { + // quantise down to 4 bits + float alpha1 = ( float )rgba[8*i + 3] * ( 15.0f/255.0f ); + float alpha2 = ( float )rgba[8*i + 7] * ( 15.0f/255.0f ); + int quant1 = FloatToInt( alpha1, 15 ); + int quant2 = FloatToInt( alpha2, 15 ); + + // set alpha to zero where masked + int bit1 = 1 << ( 2*i ); + int bit2 = 1 << ( 2*i + 1 ); + if( ( mask & bit1 ) == 0 ) + quant1 = 0; + if( ( mask & bit2 ) == 0 ) + quant2 = 0; + + // pack into the byte + bytes[i] = ( u8 )( quant1 | ( quant2 << 4 ) ); + } +} + +void DecompressAlphaDxt3( u8* rgba, void const* block ) +{ + u8 const* bytes = reinterpret_cast< u8 const* >( block ); + + // unpack the alpha values pairwise + for( int i = 0; i < 8; ++i ) + { + // quantise down to 4 bits + u8 quant = bytes[i]; + + // unpack the values + u8 lo = quant & 0x0f; + u8 hi = quant & 0xf0; + + // convert back up to bytes + rgba[8*i + 3] = lo | ( lo << 4 ); + rgba[8*i + 7] = hi | ( hi >> 4 ); + } +} + +static void FixRange( int& min, int& max, int steps ) +{ + if( max - min < steps ) + max = std::min( min + steps, 255 ); + if( max - min < steps ) + min = std::max( 0, max - steps ); +} + +static int FitCodes( u8 const* rgba, int mask, u8 const* codes, u8* indices ) +{ + // fit each alpha value to the codebook + int err = 0; + for( int i = 0; i < 16; ++i ) + { + // check this pixel is valid + int bit = 1 << i; + if( ( mask & bit ) == 0 ) + { + // use the first code + indices[i] = 0; + continue; + } + + // find the least error and corresponding index + int value = rgba[4*i + 3]; + int least = INT_MAX; + int index = 0; + for( int j = 0; j < 8; ++j ) + { + // get the squared error from this code + int dist = ( int )value - ( int )codes[j]; + dist *= dist; + + // compare with the best so far + if( dist < least ) + { + least = dist; + index = j; + } + } + + // save this index and accumulate the error + indices[i] = ( u8 )index; + err += least; + } + + // return the total error + return err; +} + +static void WriteAlphaBlock( int alpha0, int alpha1, u8 const* indices, void* block ) +{ + u8* bytes = reinterpret_cast< u8* >( block ); + + // write the first two bytes + bytes[0] = ( u8 )alpha0; + bytes[1] = ( u8 )alpha1; + + // pack the indices with 3 bits each + u8* dest = bytes + 2; + u8 const* src = indices; + for( int i = 0; i < 2; ++i ) + { + // pack 8 3-bit values + int value = 0; + for( int j = 0; j < 8; ++j ) + { + int index = *src++; + value |= ( index << 3*j ); + } + + // store in 3 bytes + for( int j = 0; j < 3; ++j ) + { + int byte = ( value >> 8*j ) & 0xff; + *dest++ = ( u8 )byte; + } + } +} + +static void WriteAlphaBlock5( int alpha0, int alpha1, u8 const* indices, void* block ) +{ + // check the relative values of the endpoints + if( alpha0 > alpha1 ) + { + // swap the indices + u8 swapped[16]; + for( int i = 0; i < 16; ++i ) + { + u8 index = indices[i]; + if( index == 0 ) + swapped[i] = 1; + else if( index == 1 ) + swapped[i] = 0; + else if( index <= 5 ) + swapped[i] = 7 - index; + else + swapped[i] = index; + } + + // write the block + WriteAlphaBlock( alpha1, alpha0, swapped, block ); + } + else + { + // write the block + WriteAlphaBlock( alpha0, alpha1, indices, block ); + } +} + +static void WriteAlphaBlock7( int alpha0, int alpha1, u8 const* indices, void* block ) +{ + // check the relative values of the endpoints + if( alpha0 < alpha1 ) + { + // swap the indices + u8 swapped[16]; + for( int i = 0; i < 16; ++i ) + { + u8 index = indices[i]; + if( index == 0 ) + swapped[i] = 1; + else if( index == 1 ) + swapped[i] = 0; + else + swapped[i] = 9 - index; + } + + // write the block + WriteAlphaBlock( alpha1, alpha0, swapped, block ); + } + else + { + // write the block + WriteAlphaBlock( alpha0, alpha1, indices, block ); + } +} + +void CompressAlphaDxt5( u8 const* rgba, int mask, void* block ) +{ + // get the range for 5-alpha and 7-alpha interpolation + int min5 = 255; + int max5 = 0; + int min7 = 255; + int max7 = 0; + for( int i = 0; i < 16; ++i ) + { + // check this pixel is valid + int bit = 1 << i; + if( ( mask & bit ) == 0 ) + continue; + + // incorporate into the min/max + int value = rgba[4*i + 3]; + if( value < min7 ) + min7 = value; + if( value > max7 ) + max7 = value; + if( value != 0 && value < min5 ) + min5 = value; + if( value != 255 && value > max5 ) + max5 = value; + } + + // handle the case that no valid range was found + if( min5 > max5 ) + min5 = max5; + if( min7 > max7 ) + min7 = max7; + + // fix the range to be the minimum in each case + FixRange( min5, max5, 5 ); + FixRange( min7, max7, 7 ); + + // set up the 5-alpha code book + u8 codes5[8]; + codes5[0] = ( u8 )min5; + codes5[1] = ( u8 )max5; + for( int i = 1; i < 5; ++i ) + codes5[1 + i] = ( u8 )( ( ( 5 - i )*min5 + i*max5 )/5 ); + codes5[6] = 0; + codes5[7] = 255; + + // set up the 7-alpha code book + u8 codes7[8]; + codes7[0] = ( u8 )min7; + codes7[1] = ( u8 )max7; + for( int i = 1; i < 7; ++i ) + codes7[1 + i] = ( u8 )( ( ( 7 - i )*min7 + i*max7 )/7 ); + + // fit the data to both code books + u8 indices5[16]; + u8 indices7[16]; + int err5 = FitCodes( rgba, mask, codes5, indices5 ); + int err7 = FitCodes( rgba, mask, codes7, indices7 ); + + // save the block with least error + if( err5 <= err7 ) + WriteAlphaBlock5( min5, max5, indices5, block ); + else + WriteAlphaBlock7( min7, max7, indices7, block ); +} + +void DecompressAlphaDxt5( u8* rgba, void const* block ) +{ + // get the two alpha values + u8 const* bytes = reinterpret_cast< u8 const* >( block ); + int alpha0 = bytes[0]; + int alpha1 = bytes[1]; + + // compare the values to build the codebook + u8 codes[8]; + codes[0] = ( u8 )alpha0; + codes[1] = ( u8 )alpha1; + if( alpha0 <= alpha1 ) + { + // use 5-alpha codebook + for( int i = 1; i < 5; ++i ) + codes[1 + i] = ( u8 )( ( ( 5 - i )*alpha0 + i*alpha1 )/5 ); + codes[6] = 0; + codes[7] = 255; + } + else + { + // use 7-alpha codebook + for( int i = 1; i < 7; ++i ) + codes[1 + i] = ( u8 )( ( ( 7 - i )*alpha0 + i*alpha1 )/7 ); + } + + // decode the indices + u8 indices[16]; + u8 const* src = bytes + 2; + u8* dest = indices; + for( int i = 0; i < 2; ++i ) + { + // grab 3 bytes + int value = 0; + for( int j = 0; j < 3; ++j ) + { + int byte = *src++; + value |= ( byte << 8*j ); + } + + // unpack 8 3-bit values from it + for( int j = 0; j < 8; ++j ) + { + int index = ( value >> 3*j ) & 0x7; + *dest++ = ( u8 )index; + } + } + + // write out the indexed codebook values + for( int i = 0; i < 16; ++i ) + rgba[4*i + 3] = codes[indices[i]]; +} + +} // namespace squish diff --git a/thirdparty/squish/alpha.h b/thirdparty/squish/alpha.h new file mode 100644 index 0000000000..a1fffd4049 --- /dev/null +++ b/thirdparty/squish/alpha.h @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#ifndef SQUISH_ALPHA_H +#define SQUISH_ALPHA_H + +#include "squish.h" + +namespace squish { + +void CompressAlphaDxt3( u8 const* rgba, int mask, void* block ); +void CompressAlphaDxt5( u8 const* rgba, int mask, void* block ); + +void DecompressAlphaDxt3( u8* rgba, void const* block ); +void DecompressAlphaDxt5( u8* rgba, void const* block ); + +} // namespace squish + +#endif // ndef SQUISH_ALPHA_H diff --git a/thirdparty/squish/clusterfit.cpp b/thirdparty/squish/clusterfit.cpp new file mode 100644 index 0000000000..1610ecb5d8 --- /dev/null +++ b/thirdparty/squish/clusterfit.cpp @@ -0,0 +1,392 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + Copyright (c) 2007 Ignacio Castano icastano@nvidia.com + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#include "clusterfit.h" +#include "colourset.h" +#include "colourblock.h" +#include <cfloat> + +namespace squish { + +ClusterFit::ClusterFit( ColourSet const* colours, int flags, float* metric ) + : ColourFit( colours, flags ) +{ + // set the iteration count + m_iterationCount = ( m_flags & kColourIterativeClusterFit ) ? kMaxIterations : 1; + + // initialise the metric (old perceptual = 0.2126f, 0.7152f, 0.0722f) + if( metric ) + m_metric = Vec4( metric[0], metric[1], metric[2], 1.0f ); + else + m_metric = VEC4_CONST( 1.0f ); + + // initialise the best error + m_besterror = VEC4_CONST( FLT_MAX ); + + // cache some values + int const count = m_colours->GetCount(); + Vec3 const* values = m_colours->GetPoints(); + + // get the covariance matrix + Sym3x3 covariance = ComputeWeightedCovariance( count, values, m_colours->GetWeights() ); + + // compute the principle component + m_principle = ComputePrincipleComponent( covariance ); +} + +bool ClusterFit::ConstructOrdering( Vec3 const& axis, int iteration ) +{ + // cache some values + int const count = m_colours->GetCount(); + Vec3 const* values = m_colours->GetPoints(); + + // build the list of dot products + float dps[16]; + u8* order = ( u8* )m_order + 16*iteration; + for( int i = 0; i < count; ++i ) + { + dps[i] = Dot( values[i], axis ); + order[i] = ( u8 )i; + } + + // stable sort using them + for( int i = 0; i < count; ++i ) + { + for( int j = i; j > 0 && dps[j] < dps[j - 1]; --j ) + { + std::swap( dps[j], dps[j - 1] ); + std::swap( order[j], order[j - 1] ); + } + } + + // check this ordering is unique + for( int it = 0; it < iteration; ++it ) + { + u8 const* prev = ( u8* )m_order + 16*it; + bool same = true; + for( int i = 0; i < count; ++i ) + { + if( order[i] != prev[i] ) + { + same = false; + break; + } + } + if( same ) + return false; + } + + // copy the ordering and weight all the points + Vec3 const* unweighted = m_colours->GetPoints(); + float const* weights = m_colours->GetWeights(); + m_xsum_wsum = VEC4_CONST( 0.0f ); + for( int i = 0; i < count; ++i ) + { + int j = order[i]; + Vec4 p( unweighted[j].X(), unweighted[j].Y(), unweighted[j].Z(), 1.0f ); + Vec4 w( weights[j] ); + Vec4 x = p*w; + m_points_weights[i] = x; + m_xsum_wsum += x; + } + return true; +} + +void ClusterFit::Compress3( void* block ) +{ + // declare variables + int const count = m_colours->GetCount(); + Vec4 const two = VEC4_CONST( 2.0 ); + Vec4 const one = VEC4_CONST( 1.0f ); + Vec4 const half_half2( 0.5f, 0.5f, 0.5f, 0.25f ); + Vec4 const zero = VEC4_CONST( 0.0f ); + Vec4 const half = VEC4_CONST( 0.5f ); + Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f ); + Vec4 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f, 0.0f ); + + // prepare an ordering using the principle axis + ConstructOrdering( m_principle, 0 ); + + // check all possible clusters and iterate on the total order + Vec4 beststart = VEC4_CONST( 0.0f ); + Vec4 bestend = VEC4_CONST( 0.0f ); + Vec4 besterror = m_besterror; + u8 bestindices[16]; + int bestiteration = 0; + int besti = 0, bestj = 0; + + // loop over iterations (we avoid the case that all points in first or last cluster) + for( int iterationIndex = 0;; ) + { + // first cluster [0,i) is at the start + Vec4 part0 = VEC4_CONST( 0.0f ); + for( int i = 0; i < count; ++i ) + { + // second cluster [i,j) is half along + Vec4 part1 = ( i == 0 ) ? m_points_weights[0] : VEC4_CONST( 0.0f ); + int jmin = ( i == 0 ) ? 1 : i; + for( int j = jmin;; ) + { + // last cluster [j,count) is at the end + Vec4 part2 = m_xsum_wsum - part1 - part0; + + // compute least squares terms directly + Vec4 alphax_sum = MultiplyAdd( part1, half_half2, part0 ); + Vec4 alpha2_sum = alphax_sum.SplatW(); + + Vec4 betax_sum = MultiplyAdd( part1, half_half2, part2 ); + Vec4 beta2_sum = betax_sum.SplatW(); + + Vec4 alphabeta_sum = ( part1*half_half2 ).SplatW(); + + // compute the least-squares optimal points + Vec4 factor = Reciprocal( NegativeMultiplySubtract( alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum ) ); + Vec4 a = NegativeMultiplySubtract( betax_sum, alphabeta_sum, alphax_sum*beta2_sum )*factor; + Vec4 b = NegativeMultiplySubtract( alphax_sum, alphabeta_sum, betax_sum*alpha2_sum )*factor; + + // clamp to the grid + a = Min( one, Max( zero, a ) ); + b = Min( one, Max( zero, b ) ); + a = Truncate( MultiplyAdd( grid, a, half ) )*gridrcp; + b = Truncate( MultiplyAdd( grid, b, half ) )*gridrcp; + + // compute the error (we skip the constant xxsum) + Vec4 e1 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum ); + Vec4 e2 = NegativeMultiplySubtract( a, alphax_sum, a*b*alphabeta_sum ); + Vec4 e3 = NegativeMultiplySubtract( b, betax_sum, e2 ); + Vec4 e4 = MultiplyAdd( two, e3, e1 ); + + // apply the metric to the error term + Vec4 e5 = e4*m_metric; + Vec4 error = e5.SplatX() + e5.SplatY() + e5.SplatZ(); + + // keep the solution if it wins + if( CompareAnyLessThan( error, besterror ) ) + { + beststart = a; + bestend = b; + besti = i; + bestj = j; + besterror = error; + bestiteration = iterationIndex; + } + + // advance + if( j == count ) + break; + part1 += m_points_weights[j]; + ++j; + } + + // advance + part0 += m_points_weights[i]; + } + + // stop if we didn't improve in this iteration + if( bestiteration != iterationIndex ) + break; + + // advance if possible + ++iterationIndex; + if( iterationIndex == m_iterationCount ) + break; + + // stop if a new iteration is an ordering that has already been tried + Vec3 axis = ( bestend - beststart ).GetVec3(); + if( !ConstructOrdering( axis, iterationIndex ) ) + break; + } + + // save the block if necessary + if( CompareAnyLessThan( besterror, m_besterror ) ) + { + // remap the indices + u8 const* order = ( u8* )m_order + 16*bestiteration; + + u8 unordered[16]; + for( int m = 0; m < besti; ++m ) + unordered[order[m]] = 0; + for( int m = besti; m < bestj; ++m ) + unordered[order[m]] = 2; + for( int m = bestj; m < count; ++m ) + unordered[order[m]] = 1; + + m_colours->RemapIndices( unordered, bestindices ); + + // save the block + WriteColourBlock3( beststart.GetVec3(), bestend.GetVec3(), bestindices, block ); + + // save the error + m_besterror = besterror; + } +} + +void ClusterFit::Compress4( void* block ) +{ + // declare variables + int const count = m_colours->GetCount(); + Vec4 const two = VEC4_CONST( 2.0f ); + Vec4 const one = VEC4_CONST( 1.0f ); + Vec4 const onethird_onethird2( 1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f, 1.0f/9.0f ); + Vec4 const twothirds_twothirds2( 2.0f/3.0f, 2.0f/3.0f, 2.0f/3.0f, 4.0f/9.0f ); + Vec4 const twonineths = VEC4_CONST( 2.0f/9.0f ); + Vec4 const zero = VEC4_CONST( 0.0f ); + Vec4 const half = VEC4_CONST( 0.5f ); + Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f ); + Vec4 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f, 0.0f ); + + // prepare an ordering using the principle axis + ConstructOrdering( m_principle, 0 ); + + // check all possible clusters and iterate on the total order + Vec4 beststart = VEC4_CONST( 0.0f ); + Vec4 bestend = VEC4_CONST( 0.0f ); + Vec4 besterror = m_besterror; + u8 bestindices[16]; + int bestiteration = 0; + int besti = 0, bestj = 0, bestk = 0; + + // loop over iterations (we avoid the case that all points in first or last cluster) + for( int iterationIndex = 0;; ) + { + // first cluster [0,i) is at the start + Vec4 part0 = VEC4_CONST( 0.0f ); + for( int i = 0; i < count; ++i ) + { + // second cluster [i,j) is one third along + Vec4 part1 = VEC4_CONST( 0.0f ); + for( int j = i;; ) + { + // third cluster [j,k) is two thirds along + Vec4 part2 = ( j == 0 ) ? m_points_weights[0] : VEC4_CONST( 0.0f ); + int kmin = ( j == 0 ) ? 1 : j; + for( int k = kmin;; ) + { + // last cluster [k,count) is at the end + Vec4 part3 = m_xsum_wsum - part2 - part1 - part0; + + // compute least squares terms directly + Vec4 const alphax_sum = MultiplyAdd( part2, onethird_onethird2, MultiplyAdd( part1, twothirds_twothirds2, part0 ) ); + Vec4 const alpha2_sum = alphax_sum.SplatW(); + + Vec4 const betax_sum = MultiplyAdd( part1, onethird_onethird2, MultiplyAdd( part2, twothirds_twothirds2, part3 ) ); + Vec4 const beta2_sum = betax_sum.SplatW(); + + Vec4 const alphabeta_sum = twonineths*( part1 + part2 ).SplatW(); + + // compute the least-squares optimal points + Vec4 factor = Reciprocal( NegativeMultiplySubtract( alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum ) ); + Vec4 a = NegativeMultiplySubtract( betax_sum, alphabeta_sum, alphax_sum*beta2_sum )*factor; + Vec4 b = NegativeMultiplySubtract( alphax_sum, alphabeta_sum, betax_sum*alpha2_sum )*factor; + + // clamp to the grid + a = Min( one, Max( zero, a ) ); + b = Min( one, Max( zero, b ) ); + a = Truncate( MultiplyAdd( grid, a, half ) )*gridrcp; + b = Truncate( MultiplyAdd( grid, b, half ) )*gridrcp; + + // compute the error (we skip the constant xxsum) + Vec4 e1 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum ); + Vec4 e2 = NegativeMultiplySubtract( a, alphax_sum, a*b*alphabeta_sum ); + Vec4 e3 = NegativeMultiplySubtract( b, betax_sum, e2 ); + Vec4 e4 = MultiplyAdd( two, e3, e1 ); + + // apply the metric to the error term + Vec4 e5 = e4*m_metric; + Vec4 error = e5.SplatX() + e5.SplatY() + e5.SplatZ(); + + // keep the solution if it wins + if( CompareAnyLessThan( error, besterror ) ) + { + beststart = a; + bestend = b; + besterror = error; + besti = i; + bestj = j; + bestk = k; + bestiteration = iterationIndex; + } + + // advance + if( k == count ) + break; + part2 += m_points_weights[k]; + ++k; + } + + // advance + if( j == count ) + break; + part1 += m_points_weights[j]; + ++j; + } + + // advance + part0 += m_points_weights[i]; + } + + // stop if we didn't improve in this iteration + if( bestiteration != iterationIndex ) + break; + + // advance if possible + ++iterationIndex; + if( iterationIndex == m_iterationCount ) + break; + + // stop if a new iteration is an ordering that has already been tried + Vec3 axis = ( bestend - beststart ).GetVec3(); + if( !ConstructOrdering( axis, iterationIndex ) ) + break; + } + + // save the block if necessary + if( CompareAnyLessThan( besterror, m_besterror ) ) + { + // remap the indices + u8 const* order = ( u8* )m_order + 16*bestiteration; + + u8 unordered[16]; + for( int m = 0; m < besti; ++m ) + unordered[order[m]] = 0; + for( int m = besti; m < bestj; ++m ) + unordered[order[m]] = 2; + for( int m = bestj; m < bestk; ++m ) + unordered[order[m]] = 3; + for( int m = bestk; m < count; ++m ) + unordered[order[m]] = 1; + + m_colours->RemapIndices( unordered, bestindices ); + + // save the block + WriteColourBlock4( beststart.GetVec3(), bestend.GetVec3(), bestindices, block ); + + // save the error + m_besterror = besterror; + } +} + +} // namespace squish diff --git a/thirdparty/squish/clusterfit.h b/thirdparty/squish/clusterfit.h new file mode 100644 index 0000000000..999396b262 --- /dev/null +++ b/thirdparty/squish/clusterfit.h @@ -0,0 +1,61 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + Copyright (c) 2007 Ignacio Castano icastano@nvidia.com + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#ifndef SQUISH_CLUSTERFIT_H +#define SQUISH_CLUSTERFIT_H + +#include "squish.h" +#include "maths.h" +#include "simd.h" +#include "colourfit.h" + +namespace squish { + +class ClusterFit : public ColourFit +{ +public: + ClusterFit( ColourSet const* colours, int flags, float* metric ); + +private: + bool ConstructOrdering( Vec3 const& axis, int iteration ); + + virtual void Compress3( void* block ); + virtual void Compress4( void* block ); + + enum { kMaxIterations = 8 }; + + int m_iterationCount; + Vec3 m_principle; + u8 m_order[16*kMaxIterations]; + Vec4 m_points_weights[16]; + Vec4 m_xsum_wsum; + Vec4 m_metric; + Vec4 m_besterror; +}; + +} // namespace squish + +#endif // ndef SQUISH_CLUSTERFIT_H diff --git a/thirdparty/squish/colourblock.cpp b/thirdparty/squish/colourblock.cpp new file mode 100644 index 0000000000..af8b980365 --- /dev/null +++ b/thirdparty/squish/colourblock.cpp @@ -0,0 +1,214 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#include "colourblock.h" + +namespace squish { + +static int FloatToInt( float a, int limit ) +{ + // use ANSI round-to-zero behaviour to get round-to-nearest + int i = ( int )( a + 0.5f ); + + // clamp to the limit + if( i < 0 ) + i = 0; + else if( i > limit ) + i = limit; + + // done + return i; +} + +static int FloatTo565( Vec3::Arg colour ) +{ + // get the components in the correct range + int r = FloatToInt( 31.0f*colour.X(), 31 ); + int g = FloatToInt( 63.0f*colour.Y(), 63 ); + int b = FloatToInt( 31.0f*colour.Z(), 31 ); + + // pack into a single value + return ( r << 11 ) | ( g << 5 ) | b; +} + +static void WriteColourBlock( int a, int b, u8* indices, void* block ) +{ + // get the block as bytes + u8* bytes = ( u8* )block; + + // write the endpoints + bytes[0] = ( u8 )( a & 0xff ); + bytes[1] = ( u8 )( a >> 8 ); + bytes[2] = ( u8 )( b & 0xff ); + bytes[3] = ( u8 )( b >> 8 ); + + // write the indices + for( int i = 0; i < 4; ++i ) + { + u8 const* ind = indices + 4*i; + bytes[4 + i] = ind[0] | ( ind[1] << 2 ) | ( ind[2] << 4 ) | ( ind[3] << 6 ); + } +} + +void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ) +{ + // get the packed values + int a = FloatTo565( start ); + int b = FloatTo565( end ); + + // remap the indices + u8 remapped[16]; + if( a <= b ) + { + // use the indices directly + for( int i = 0; i < 16; ++i ) + remapped[i] = indices[i]; + } + else + { + // swap a and b + std::swap( a, b ); + for( int i = 0; i < 16; ++i ) + { + if( indices[i] == 0 ) + remapped[i] = 1; + else if( indices[i] == 1 ) + remapped[i] = 0; + else + remapped[i] = indices[i]; + } + } + + // write the block + WriteColourBlock( a, b, remapped, block ); +} + +void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ) +{ + // get the packed values + int a = FloatTo565( start ); + int b = FloatTo565( end ); + + // remap the indices + u8 remapped[16]; + if( a < b ) + { + // swap a and b + std::swap( a, b ); + for( int i = 0; i < 16; ++i ) + remapped[i] = ( indices[i] ^ 0x1 ) & 0x3; + } + else if( a == b ) + { + // use index 0 + for( int i = 0; i < 16; ++i ) + remapped[i] = 0; + } + else + { + // use the indices directly + for( int i = 0; i < 16; ++i ) + remapped[i] = indices[i]; + } + + // write the block + WriteColourBlock( a, b, remapped, block ); +} + +static int Unpack565( u8 const* packed, u8* colour ) +{ + // build the packed value + int value = ( int )packed[0] | ( ( int )packed[1] << 8 ); + + // get the components in the stored range + u8 red = ( u8 )( ( value >> 11 ) & 0x1f ); + u8 green = ( u8 )( ( value >> 5 ) & 0x3f ); + u8 blue = ( u8 )( value & 0x1f ); + + // scale up to 8 bits + colour[0] = ( red << 3 ) | ( red >> 2 ); + colour[1] = ( green << 2 ) | ( green >> 4 ); + colour[2] = ( blue << 3 ) | ( blue >> 2 ); + colour[3] = 255; + + // return the value + return value; +} + +void DecompressColour( u8* rgba, void const* block, bool isDxt1 ) +{ + // get the block bytes + u8 const* bytes = reinterpret_cast< u8 const* >( block ); + + // unpack the endpoints + u8 codes[16]; + int a = Unpack565( bytes, codes ); + int b = Unpack565( bytes + 2, codes + 4 ); + + // generate the midpoints + for( int i = 0; i < 3; ++i ) + { + int c = codes[i]; + int d = codes[4 + i]; + + if( isDxt1 && a <= b ) + { + codes[8 + i] = ( u8 )( ( c + d )/2 ); + codes[12 + i] = 0; + } + else + { + codes[8 + i] = ( u8 )( ( 2*c + d )/3 ); + codes[12 + i] = ( u8 )( ( c + 2*d )/3 ); + } + } + + // fill in alpha for the intermediate values + codes[8 + 3] = 255; + codes[12 + 3] = ( isDxt1 && a <= b ) ? 0 : 255; + + // unpack the indices + u8 indices[16]; + for( int i = 0; i < 4; ++i ) + { + u8* ind = indices + 4*i; + u8 packed = bytes[4 + i]; + + ind[0] = packed & 0x3; + ind[1] = ( packed >> 2 ) & 0x3; + ind[2] = ( packed >> 4 ) & 0x3; + ind[3] = ( packed >> 6 ) & 0x3; + } + + // store out the colours + for( int i = 0; i < 16; ++i ) + { + u8 offset = 4*indices[i]; + for( int j = 0; j < 4; ++j ) + rgba[4*i + j] = codes[offset + j]; + } +} + +} // namespace squish diff --git a/thirdparty/squish/colourblock.h b/thirdparty/squish/colourblock.h new file mode 100644 index 0000000000..fee2cd7c5d --- /dev/null +++ b/thirdparty/squish/colourblock.h @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#ifndef SQUISH_COLOURBLOCK_H +#define SQUISH_COLOURBLOCK_H + +#include "squish.h" +#include "maths.h" + +namespace squish { + +void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ); +void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ); + +void DecompressColour( u8* rgba, void const* block, bool isDxt1 ); + +} // namespace squish + +#endif // ndef SQUISH_COLOURBLOCK_H diff --git a/thirdparty/squish/colourfit.cpp b/thirdparty/squish/colourfit.cpp new file mode 100644 index 0000000000..e45b656557 --- /dev/null +++ b/thirdparty/squish/colourfit.cpp @@ -0,0 +1,54 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#include "colourfit.h" +#include "colourset.h" + +namespace squish { + +ColourFit::ColourFit( ColourSet const* colours, int flags ) + : m_colours( colours ), + m_flags( flags ) +{ +} + +ColourFit::~ColourFit() +{ +} + +void ColourFit::Compress( void* block ) +{ + bool isDxt1 = ( ( m_flags & kDxt1 ) != 0 ); + if( isDxt1 ) + { + Compress3( block ); + if( !m_colours->IsTransparent() ) + Compress4( block ); + } + else + Compress4( block ); +} + +} // namespace squish diff --git a/thirdparty/squish/colourfit.h b/thirdparty/squish/colourfit.h new file mode 100644 index 0000000000..e73dceb2eb --- /dev/null +++ b/thirdparty/squish/colourfit.h @@ -0,0 +1,56 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#ifndef SQUISH_COLOURFIT_H +#define SQUISH_COLOURFIT_H + +#include "squish.h" +#include "maths.h" + +#include <climits> + +namespace squish { + +class ColourSet; + +class ColourFit +{ +public: + ColourFit( ColourSet const* colours, int flags ); + virtual ~ColourFit(); + + void Compress( void* block ); + +protected: + virtual void Compress3( void* block ) = 0; + virtual void Compress4( void* block ) = 0; + + ColourSet const* m_colours; + int m_flags; +}; + +} // namespace squish + +#endif // ndef SQUISH_COLOURFIT_H diff --git a/thirdparty/squish/colourset.cpp b/thirdparty/squish/colourset.cpp new file mode 100644 index 0000000000..e900556471 --- /dev/null +++ b/thirdparty/squish/colourset.cpp @@ -0,0 +1,121 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#include "colourset.h" + +namespace squish { + +ColourSet::ColourSet( u8 const* rgba, int mask, int flags ) + : m_count( 0 ), + m_transparent( false ) +{ + // check the compression mode for dxt1 + bool isDxt1 = ( ( flags & kDxt1 ) != 0 ); + bool weightByAlpha = ( ( flags & kWeightColourByAlpha ) != 0 ); + + // create the minimal set + for( int i = 0; i < 16; ++i ) + { + // check this pixel is enabled + int bit = 1 << i; + if( ( mask & bit ) == 0 ) + { + m_remap[i] = -1; + continue; + } + + // check for transparent pixels when using dxt1 + if( isDxt1 && rgba[4*i + 3] < 128 ) + { + m_remap[i] = -1; + m_transparent = true; + continue; + } + + // loop over previous points for a match + for( int j = 0;; ++j ) + { + // allocate a new point + if( j == i ) + { + // normalise coordinates to [0,1] + float x = ( float )rgba[4*i] / 255.0f; + float y = ( float )rgba[4*i + 1] / 255.0f; + float z = ( float )rgba[4*i + 2] / 255.0f; + + // ensure there is always non-zero weight even for zero alpha + float w = ( float )( rgba[4*i + 3] + 1 ) / 256.0f; + + // add the point + m_points[m_count] = Vec3( x, y, z ); + m_weights[m_count] = ( weightByAlpha ? w : 1.0f ); + m_remap[i] = m_count; + + // advance + ++m_count; + break; + } + + // check for a match + int oldbit = 1 << j; + bool match = ( ( mask & oldbit ) != 0 ) + && ( rgba[4*i] == rgba[4*j] ) + && ( rgba[4*i + 1] == rgba[4*j + 1] ) + && ( rgba[4*i + 2] == rgba[4*j + 2] ) + && ( rgba[4*j + 3] >= 128 || !isDxt1 ); + if( match ) + { + // get the index of the match + int index = m_remap[j]; + + // ensure there is always non-zero weight even for zero alpha + float w = ( float )( rgba[4*i + 3] + 1 ) / 256.0f; + + // map to this point and increase the weight + m_weights[index] += ( weightByAlpha ? w : 1.0f ); + m_remap[i] = index; + break; + } + } + } + + // square root the weights + for( int i = 0; i < m_count; ++i ) + m_weights[i] = std::sqrt( m_weights[i] ); +} + +void ColourSet::RemapIndices( u8 const* source, u8* target ) const +{ + for( int i = 0; i < 16; ++i ) + { + int j = m_remap[i]; + if( j == -1 ) + target[i] = 3; + else + target[i] = source[j]; + } +} + +} // namespace squish diff --git a/thirdparty/squish/colourset.h b/thirdparty/squish/colourset.h new file mode 100644 index 0000000000..e13bb6fc35 --- /dev/null +++ b/thirdparty/squish/colourset.h @@ -0,0 +1,58 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#ifndef SQUISH_COLOURSET_H +#define SQUISH_COLOURSET_H + +#include "squish.h" +#include "maths.h" + +namespace squish { + +/*! @brief Represents a set of block colours +*/ +class ColourSet +{ +public: + ColourSet( u8 const* rgba, int mask, int flags ); + + int GetCount() const { return m_count; } + Vec3 const* GetPoints() const { return m_points; } + float const* GetWeights() const { return m_weights; } + bool IsTransparent() const { return m_transparent; } + + void RemapIndices( u8 const* source, u8* target ) const; + +private: + int m_count; + Vec3 m_points[16]; + float m_weights[16]; + int m_remap[16]; + bool m_transparent; +}; + +} // namespace sqish + +#endif // ndef SQUISH_COLOURSET_H diff --git a/thirdparty/squish/config.h b/thirdparty/squish/config.h new file mode 100644 index 0000000000..92edefe966 --- /dev/null +++ b/thirdparty/squish/config.h @@ -0,0 +1,49 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#ifndef SQUISH_CONFIG_H +#define SQUISH_CONFIG_H + +// Set to 1 when building squish to use Altivec instructions. +#ifndef SQUISH_USE_ALTIVEC +#define SQUISH_USE_ALTIVEC 0 +#endif + +// Set to 1 or 2 when building squish to use SSE or SSE2 instructions. +#ifndef SQUISH_USE_SSE +#define SQUISH_USE_SSE 0 +#endif + +// Internally set SQUISH_USE_SIMD when either Altivec or SSE is available. +#if SQUISH_USE_ALTIVEC && SQUISH_USE_SSE +#error "Cannot enable both Altivec and SSE!" +#endif +#if SQUISH_USE_ALTIVEC || SQUISH_USE_SSE +#define SQUISH_USE_SIMD 1 +#else +#define SQUISH_USE_SIMD 0 +#endif + +#endif // ndef SQUISH_CONFIG_H diff --git a/thirdparty/squish/maths.cpp b/thirdparty/squish/maths.cpp new file mode 100644 index 0000000000..4fa0bcfb35 --- /dev/null +++ b/thirdparty/squish/maths.cpp @@ -0,0 +1,259 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +/*! @file + + The symmetric eigensystem solver algorithm is from + http://www.geometrictools.com/Documentation/EigenSymmetric3x3.pdf +*/ + +#include "maths.h" +#include "simd.h" +#include <cfloat> + +namespace squish { + +Sym3x3 ComputeWeightedCovariance( int n, Vec3 const* points, float const* weights ) +{ + // compute the centroid + float total = 0.0f; + Vec3 centroid( 0.0f ); + for( int i = 0; i < n; ++i ) + { + total += weights[i]; + centroid += weights[i]*points[i]; + } + if( total > FLT_EPSILON ) + centroid /= total; + + // accumulate the covariance matrix + Sym3x3 covariance( 0.0f ); + for( int i = 0; i < n; ++i ) + { + Vec3 a = points[i] - centroid; + Vec3 b = weights[i]*a; + + covariance[0] += a.X()*b.X(); + covariance[1] += a.X()*b.Y(); + covariance[2] += a.X()*b.Z(); + covariance[3] += a.Y()*b.Y(); + covariance[4] += a.Y()*b.Z(); + covariance[5] += a.Z()*b.Z(); + } + + // return it + return covariance; +} + +#if 0 + +static Vec3 GetMultiplicity1Evector( Sym3x3 const& matrix, float evalue ) +{ + // compute M + Sym3x3 m; + m[0] = matrix[0] - evalue; + m[1] = matrix[1]; + m[2] = matrix[2]; + m[3] = matrix[3] - evalue; + m[4] = matrix[4]; + m[5] = matrix[5] - evalue; + + // compute U + Sym3x3 u; + u[0] = m[3]*m[5] - m[4]*m[4]; + u[1] = m[2]*m[4] - m[1]*m[5]; + u[2] = m[1]*m[4] - m[2]*m[3]; + u[3] = m[0]*m[5] - m[2]*m[2]; + u[4] = m[1]*m[2] - m[4]*m[0]; + u[5] = m[0]*m[3] - m[1]*m[1]; + + // find the largest component + float mc = std::fabs( u[0] ); + int mi = 0; + for( int i = 1; i < 6; ++i ) + { + float c = std::fabs( u[i] ); + if( c > mc ) + { + mc = c; + mi = i; + } + } + + // pick the column with this component + switch( mi ) + { + case 0: + return Vec3( u[0], u[1], u[2] ); + + case 1: + case 3: + return Vec3( u[1], u[3], u[4] ); + + default: + return Vec3( u[2], u[4], u[5] ); + } +} + +static Vec3 GetMultiplicity2Evector( Sym3x3 const& matrix, float evalue ) +{ + // compute M + Sym3x3 m; + m[0] = matrix[0] - evalue; + m[1] = matrix[1]; + m[2] = matrix[2]; + m[3] = matrix[3] - evalue; + m[4] = matrix[4]; + m[5] = matrix[5] - evalue; + + // find the largest component + float mc = std::fabs( m[0] ); + int mi = 0; + for( int i = 1; i < 6; ++i ) + { + float c = std::fabs( m[i] ); + if( c > mc ) + { + mc = c; + mi = i; + } + } + + // pick the first eigenvector based on this index + switch( mi ) + { + case 0: + case 1: + return Vec3( -m[1], m[0], 0.0f ); + + case 2: + return Vec3( m[2], 0.0f, -m[0] ); + + case 3: + case 4: + return Vec3( 0.0f, -m[4], m[3] ); + + default: + return Vec3( 0.0f, -m[5], m[4] ); + } +} + +Vec3 ComputePrincipleComponent( Sym3x3 const& matrix ) +{ + // compute the cubic coefficients + float c0 = matrix[0]*matrix[3]*matrix[5] + + 2.0f*matrix[1]*matrix[2]*matrix[4] + - matrix[0]*matrix[4]*matrix[4] + - matrix[3]*matrix[2]*matrix[2] + - matrix[5]*matrix[1]*matrix[1]; + float c1 = matrix[0]*matrix[3] + matrix[0]*matrix[5] + matrix[3]*matrix[5] + - matrix[1]*matrix[1] - matrix[2]*matrix[2] - matrix[4]*matrix[4]; + float c2 = matrix[0] + matrix[3] + matrix[5]; + + // compute the quadratic coefficients + float a = c1 - ( 1.0f/3.0f )*c2*c2; + float b = ( -2.0f/27.0f )*c2*c2*c2 + ( 1.0f/3.0f )*c1*c2 - c0; + + // compute the root count check + float Q = 0.25f*b*b + ( 1.0f/27.0f )*a*a*a; + + // test the multiplicity + if( FLT_EPSILON < Q ) + { + // only one root, which implies we have a multiple of the identity + return Vec3( 1.0f ); + } + else if( Q < -FLT_EPSILON ) + { + // three distinct roots + float theta = std::atan2( std::sqrt( -Q ), -0.5f*b ); + float rho = std::sqrt( 0.25f*b*b - Q ); + + float rt = std::pow( rho, 1.0f/3.0f ); + float ct = std::cos( theta/3.0f ); + float st = std::sin( theta/3.0f ); + + float l1 = ( 1.0f/3.0f )*c2 + 2.0f*rt*ct; + float l2 = ( 1.0f/3.0f )*c2 - rt*( ct + ( float )sqrt( 3.0f )*st ); + float l3 = ( 1.0f/3.0f )*c2 - rt*( ct - ( float )sqrt( 3.0f )*st ); + + // pick the larger + if( std::fabs( l2 ) > std::fabs( l1 ) ) + l1 = l2; + if( std::fabs( l3 ) > std::fabs( l1 ) ) + l1 = l3; + + // get the eigenvector + return GetMultiplicity1Evector( matrix, l1 ); + } + else // if( -FLT_EPSILON <= Q && Q <= FLT_EPSILON ) + { + // two roots + float rt; + if( b < 0.0f ) + rt = -std::pow( -0.5f*b, 1.0f/3.0f ); + else + rt = std::pow( 0.5f*b, 1.0f/3.0f ); + + float l1 = ( 1.0f/3.0f )*c2 + rt; // repeated + float l2 = ( 1.0f/3.0f )*c2 - 2.0f*rt; + + // get the eigenvector + if( std::fabs( l1 ) > std::fabs( l2 ) ) + return GetMultiplicity2Evector( matrix, l1 ); + else + return GetMultiplicity1Evector( matrix, l2 ); + } +} + +#else + +#define POWER_ITERATION_COUNT 8 + +Vec3 ComputePrincipleComponent( Sym3x3 const& matrix ) +{ + Vec4 const row0( matrix[0], matrix[1], matrix[2], 0.0f ); + Vec4 const row1( matrix[1], matrix[3], matrix[4], 0.0f ); + Vec4 const row2( matrix[2], matrix[4], matrix[5], 0.0f ); + Vec4 v = VEC4_CONST( 1.0f ); + for( int i = 0; i < POWER_ITERATION_COUNT; ++i ) + { + // matrix multiply + Vec4 w = row0*v.SplatX(); + w = MultiplyAdd(row1, v.SplatY(), w); + w = MultiplyAdd(row2, v.SplatZ(), w); + + // get max component from xyz in all channels + Vec4 a = Max(w.SplatX(), Max(w.SplatY(), w.SplatZ())); + + // divide through and advance + v = w*Reciprocal(a); + } + return v.GetVec3(); +} + +#endif + +} // namespace squish diff --git a/thirdparty/squish/maths.h b/thirdparty/squish/maths.h new file mode 100644 index 0000000000..59c32196b1 --- /dev/null +++ b/thirdparty/squish/maths.h @@ -0,0 +1,233 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#ifndef SQUISH_MATHS_H +#define SQUISH_MATHS_H + +#include <cmath> +#include <algorithm> +#include "config.h" + +namespace squish { + +class Vec3 +{ +public: + typedef Vec3 const& Arg; + + Vec3() + { + } + + explicit Vec3( float s ) + { + m_x = s; + m_y = s; + m_z = s; + } + + Vec3( float x, float y, float z ) + { + m_x = x; + m_y = y; + m_z = z; + } + + float X() const { return m_x; } + float Y() const { return m_y; } + float Z() const { return m_z; } + + Vec3 operator-() const + { + return Vec3( -m_x, -m_y, -m_z ); + } + + Vec3& operator+=( Arg v ) + { + m_x += v.m_x; + m_y += v.m_y; + m_z += v.m_z; + return *this; + } + + Vec3& operator-=( Arg v ) + { + m_x -= v.m_x; + m_y -= v.m_y; + m_z -= v.m_z; + return *this; + } + + Vec3& operator*=( Arg v ) + { + m_x *= v.m_x; + m_y *= v.m_y; + m_z *= v.m_z; + return *this; + } + + Vec3& operator*=( float s ) + { + m_x *= s; + m_y *= s; + m_z *= s; + return *this; + } + + Vec3& operator/=( Arg v ) + { + m_x /= v.m_x; + m_y /= v.m_y; + m_z /= v.m_z; + return *this; + } + + Vec3& operator/=( float s ) + { + float t = 1.0f/s; + m_x *= t; + m_y *= t; + m_z *= t; + return *this; + } + + friend Vec3 operator+( Arg left, Arg right ) + { + Vec3 copy( left ); + return copy += right; + } + + friend Vec3 operator-( Arg left, Arg right ) + { + Vec3 copy( left ); + return copy -= right; + } + + friend Vec3 operator*( Arg left, Arg right ) + { + Vec3 copy( left ); + return copy *= right; + } + + friend Vec3 operator*( Arg left, float right ) + { + Vec3 copy( left ); + return copy *= right; + } + + friend Vec3 operator*( float left, Arg right ) + { + Vec3 copy( right ); + return copy *= left; + } + + friend Vec3 operator/( Arg left, Arg right ) + { + Vec3 copy( left ); + return copy /= right; + } + + friend Vec3 operator/( Arg left, float right ) + { + Vec3 copy( left ); + return copy /= right; + } + + friend float Dot( Arg left, Arg right ) + { + return left.m_x*right.m_x + left.m_y*right.m_y + left.m_z*right.m_z; + } + + friend Vec3 Min( Arg left, Arg right ) + { + return Vec3( + std::min( left.m_x, right.m_x ), + std::min( left.m_y, right.m_y ), + std::min( left.m_z, right.m_z ) + ); + } + + friend Vec3 Max( Arg left, Arg right ) + { + return Vec3( + std::max( left.m_x, right.m_x ), + std::max( left.m_y, right.m_y ), + std::max( left.m_z, right.m_z ) + ); + } + + friend Vec3 Truncate( Arg v ) + { + return Vec3( + v.m_x > 0.0f ? std::floor( v.m_x ) : std::ceil( v.m_x ), + v.m_y > 0.0f ? std::floor( v.m_y ) : std::ceil( v.m_y ), + v.m_z > 0.0f ? std::floor( v.m_z ) : std::ceil( v.m_z ) + ); + } + +private: + float m_x; + float m_y; + float m_z; +}; + +inline float LengthSquared( Vec3::Arg v ) +{ + return Dot( v, v ); +} + +class Sym3x3 +{ +public: + Sym3x3() + { + } + + Sym3x3( float s ) + { + for( int i = 0; i < 6; ++i ) + m_x[i] = s; + } + + float operator[]( int index ) const + { + return m_x[index]; + } + + float& operator[]( int index ) + { + return m_x[index]; + } + +private: + float m_x[6]; +}; + +Sym3x3 ComputeWeightedCovariance( int n, Vec3 const* points, float const* weights ); +Vec3 ComputePrincipleComponent( Sym3x3 const& matrix ); + +} // namespace squish + +#endif // ndef SQUISH_MATHS_H diff --git a/thirdparty/squish/rangefit.cpp b/thirdparty/squish/rangefit.cpp new file mode 100644 index 0000000000..adc07ed7d2 --- /dev/null +++ b/thirdparty/squish/rangefit.cpp @@ -0,0 +1,201 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#include "rangefit.h" +#include "colourset.h" +#include "colourblock.h" +#include <cfloat> + +namespace squish { + +RangeFit::RangeFit( ColourSet const* colours, int flags, float* metric ) + : ColourFit( colours, flags ) +{ + // initialise the metric (old perceptual = 0.2126f, 0.7152f, 0.0722f) + if( metric ) + m_metric = Vec3( metric[0], metric[1], metric[2] ); + else + m_metric = Vec3( 1.0f ); + + // initialise the best error + m_besterror = FLT_MAX; + + // cache some values + int const count = m_colours->GetCount(); + Vec3 const* values = m_colours->GetPoints(); + float const* weights = m_colours->GetWeights(); + + // get the covariance matrix + Sym3x3 covariance = ComputeWeightedCovariance( count, values, weights ); + + // compute the principle component + Vec3 principle = ComputePrincipleComponent( covariance ); + + // get the min and max range as the codebook endpoints + Vec3 start( 0.0f ); + Vec3 end( 0.0f ); + if( count > 0 ) + { + float min, max; + + // compute the range + start = end = values[0]; + min = max = Dot( values[0], principle ); + for( int i = 1; i < count; ++i ) + { + float val = Dot( values[i], principle ); + if( val < min ) + { + start = values[i]; + min = val; + } + else if( val > max ) + { + end = values[i]; + max = val; + } + } + } + + // clamp the output to [0, 1] + Vec3 const one( 1.0f ); + Vec3 const zero( 0.0f ); + start = Min( one, Max( zero, start ) ); + end = Min( one, Max( zero, end ) ); + + // clamp to the grid and save + Vec3 const grid( 31.0f, 63.0f, 31.0f ); + Vec3 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f ); + Vec3 const half( 0.5f ); + m_start = Truncate( grid*start + half )*gridrcp; + m_end = Truncate( grid*end + half )*gridrcp; +} + +void RangeFit::Compress3( void* block ) +{ + // cache some values + int const count = m_colours->GetCount(); + Vec3 const* values = m_colours->GetPoints(); + + // create a codebook + Vec3 codes[3]; + codes[0] = m_start; + codes[1] = m_end; + codes[2] = 0.5f*m_start + 0.5f*m_end; + + // match each point to the closest code + u8 closest[16]; + float error = 0.0f; + for( int i = 0; i < count; ++i ) + { + // find the closest code + float dist = FLT_MAX; + int idx = 0; + for( int j = 0; j < 3; ++j ) + { + float d = LengthSquared( m_metric*( values[i] - codes[j] ) ); + if( d < dist ) + { + dist = d; + idx = j; + } + } + + // save the index + closest[i] = ( u8 )idx; + + // accumulate the error + error += dist; + } + + // save this scheme if it wins + if( error < m_besterror ) + { + // remap the indices + u8 indices[16]; + m_colours->RemapIndices( closest, indices ); + + // save the block + WriteColourBlock3( m_start, m_end, indices, block ); + + // save the error + m_besterror = error; + } +} + +void RangeFit::Compress4( void* block ) +{ + // cache some values + int const count = m_colours->GetCount(); + Vec3 const* values = m_colours->GetPoints(); + + // create a codebook + Vec3 codes[4]; + codes[0] = m_start; + codes[1] = m_end; + codes[2] = ( 2.0f/3.0f )*m_start + ( 1.0f/3.0f )*m_end; + codes[3] = ( 1.0f/3.0f )*m_start + ( 2.0f/3.0f )*m_end; + + // match each point to the closest code + u8 closest[16]; + float error = 0.0f; + for( int i = 0; i < count; ++i ) + { + // find the closest code + float dist = FLT_MAX; + int idx = 0; + for( int j = 0; j < 4; ++j ) + { + float d = LengthSquared( m_metric*( values[i] - codes[j] ) ); + if( d < dist ) + { + dist = d; + idx = j; + } + } + + // save the index + closest[i] = ( u8 )idx; + + // accumulate the error + error += dist; + } + + // save this scheme if it wins + if( error < m_besterror ) + { + // remap the indices + u8 indices[16]; + m_colours->RemapIndices( closest, indices ); + + // save the block + WriteColourBlock4( m_start, m_end, indices, block ); + + // save the error + m_besterror = error; + } +} + +} // namespace squish diff --git a/thirdparty/squish/rangefit.h b/thirdparty/squish/rangefit.h new file mode 100644 index 0000000000..bdb21a9007 --- /dev/null +++ b/thirdparty/squish/rangefit.h @@ -0,0 +1,54 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#ifndef SQUISH_RANGEFIT_H +#define SQUISH_RANGEFIT_H + +#include "squish.h" +#include "colourfit.h" +#include "maths.h" + +namespace squish { + +class ColourSet; + +class RangeFit : public ColourFit +{ +public: + RangeFit( ColourSet const* colours, int flags, float* metric ); + +private: + virtual void Compress3( void* block ); + virtual void Compress4( void* block ); + + Vec3 m_metric; + Vec3 m_start; + Vec3 m_end; + float m_besterror; +}; + +} // squish + +#endif // ndef SQUISH_RANGEFIT_H diff --git a/thirdparty/squish/simd.h b/thirdparty/squish/simd.h new file mode 100644 index 0000000000..1e02fa160e --- /dev/null +++ b/thirdparty/squish/simd.h @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#ifndef SQUISH_SIMD_H +#define SQUISH_SIMD_H + +#include "maths.h" + +#if SQUISH_USE_ALTIVEC +#include "simd_ve.h" +#elif SQUISH_USE_SSE +#include "simd_sse.h" +#else +#include "simd_float.h" +#endif + + +#endif // ndef SQUISH_SIMD_H diff --git a/thirdparty/squish/simd_float.h b/thirdparty/squish/simd_float.h new file mode 100644 index 0000000000..030ea70950 --- /dev/null +++ b/thirdparty/squish/simd_float.h @@ -0,0 +1,183 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#ifndef SQUISH_SIMD_FLOAT_H +#define SQUISH_SIMD_FLOAT_H + +#include <algorithm> + +namespace squish { + +#define VEC4_CONST( X ) Vec4( X ) + +class Vec4 +{ +public: + typedef Vec4 const& Arg; + + Vec4() {} + + explicit Vec4( float s ) + : m_x( s ), + m_y( s ), + m_z( s ), + m_w( s ) + { + } + + Vec4( float x, float y, float z, float w ) + : m_x( x ), + m_y( y ), + m_z( z ), + m_w( w ) + { + } + + Vec3 GetVec3() const + { + return Vec3( m_x, m_y, m_z ); + } + + Vec4 SplatX() const { return Vec4( m_x ); } + Vec4 SplatY() const { return Vec4( m_y ); } + Vec4 SplatZ() const { return Vec4( m_z ); } + Vec4 SplatW() const { return Vec4( m_w ); } + + Vec4& operator+=( Arg v ) + { + m_x += v.m_x; + m_y += v.m_y; + m_z += v.m_z; + m_w += v.m_w; + return *this; + } + + Vec4& operator-=( Arg v ) + { + m_x -= v.m_x; + m_y -= v.m_y; + m_z -= v.m_z; + m_w -= v.m_w; + return *this; + } + + Vec4& operator*=( Arg v ) + { + m_x *= v.m_x; + m_y *= v.m_y; + m_z *= v.m_z; + m_w *= v.m_w; + return *this; + } + + friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right ) + { + Vec4 copy( left ); + return copy += right; + } + + friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right ) + { + Vec4 copy( left ); + return copy -= right; + } + + friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right ) + { + Vec4 copy( left ); + return copy *= right; + } + + //! Returns a*b + c + friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) + { + return a*b + c; + } + + //! Returns -( a*b - c ) + friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) + { + return c - a*b; + } + + friend Vec4 Reciprocal( Vec4::Arg v ) + { + return Vec4( + 1.0f/v.m_x, + 1.0f/v.m_y, + 1.0f/v.m_z, + 1.0f/v.m_w + ); + } + + friend Vec4 Min( Vec4::Arg left, Vec4::Arg right ) + { + return Vec4( + std::min( left.m_x, right.m_x ), + std::min( left.m_y, right.m_y ), + std::min( left.m_z, right.m_z ), + std::min( left.m_w, right.m_w ) + ); + } + + friend Vec4 Max( Vec4::Arg left, Vec4::Arg right ) + { + return Vec4( + std::max( left.m_x, right.m_x ), + std::max( left.m_y, right.m_y ), + std::max( left.m_z, right.m_z ), + std::max( left.m_w, right.m_w ) + ); + } + + friend Vec4 Truncate( Vec4::Arg v ) + { + return Vec4( + v.m_x > 0.0f ? std::floor( v.m_x ) : std::ceil( v.m_x ), + v.m_y > 0.0f ? std::floor( v.m_y ) : std::ceil( v.m_y ), + v.m_z > 0.0f ? std::floor( v.m_z ) : std::ceil( v.m_z ), + v.m_w > 0.0f ? std::floor( v.m_w ) : std::ceil( v.m_w ) + ); + } + + friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right ) + { + return left.m_x < right.m_x + || left.m_y < right.m_y + || left.m_z < right.m_z + || left.m_w < right.m_w; + } + +private: + float m_x; + float m_y; + float m_z; + float m_w; +}; + +} // namespace squish + +#endif // ndef SQUISH_SIMD_FLOAT_H + diff --git a/thirdparty/squish/simd_sse.h b/thirdparty/squish/simd_sse.h new file mode 100644 index 0000000000..2e8be4ca7b --- /dev/null +++ b/thirdparty/squish/simd_sse.h @@ -0,0 +1,180 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#ifndef SQUISH_SIMD_SSE_H +#define SQUISH_SIMD_SSE_H + +#include <xmmintrin.h> +#if ( SQUISH_USE_SSE > 1 ) +#include <emmintrin.h> +#endif + +#define SQUISH_SSE_SPLAT( a ) \ + ( ( a ) | ( ( a ) << 2 ) | ( ( a ) << 4 ) | ( ( a ) << 6 ) ) + +#define SQUISH_SSE_SHUF( x, y, z, w ) \ + ( ( x ) | ( ( y ) << 2 ) | ( ( z ) << 4 ) | ( ( w ) << 6 ) ) + +namespace squish { + +#define VEC4_CONST( X ) Vec4( X ) + +class Vec4 +{ +public: + typedef Vec4 const& Arg; + + Vec4() {} + + explicit Vec4( __m128 v ) : m_v( v ) {} + + Vec4( Vec4 const& arg ) : m_v( arg.m_v ) {} + + Vec4& operator=( Vec4 const& arg ) + { + m_v = arg.m_v; + return *this; + } + + explicit Vec4( float s ) : m_v( _mm_set1_ps( s ) ) {} + + Vec4( float x, float y, float z, float w ) : m_v( _mm_setr_ps( x, y, z, w ) ) {} + + Vec3 GetVec3() const + { +#ifdef __GNUC__ + __attribute__ ((__aligned__ (16))) float c[4]; +#else + __declspec(align(16)) float c[4]; +#endif + _mm_store_ps( c, m_v ); + return Vec3( c[0], c[1], c[2] ); + } + + Vec4 SplatX() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 0 ) ) ); } + Vec4 SplatY() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 1 ) ) ); } + Vec4 SplatZ() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 2 ) ) ); } + Vec4 SplatW() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 3 ) ) ); } + + Vec4& operator+=( Arg v ) + { + m_v = _mm_add_ps( m_v, v.m_v ); + return *this; + } + + Vec4& operator-=( Arg v ) + { + m_v = _mm_sub_ps( m_v, v.m_v ); + return *this; + } + + Vec4& operator*=( Arg v ) + { + m_v = _mm_mul_ps( m_v, v.m_v ); + return *this; + } + + friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right ) + { + return Vec4( _mm_add_ps( left.m_v, right.m_v ) ); + } + + friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right ) + { + return Vec4( _mm_sub_ps( left.m_v, right.m_v ) ); + } + + friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right ) + { + return Vec4( _mm_mul_ps( left.m_v, right.m_v ) ); + } + + //! Returns a*b + c + friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) + { + return Vec4( _mm_add_ps( _mm_mul_ps( a.m_v, b.m_v ), c.m_v ) ); + } + + //! Returns -( a*b - c ) + friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) + { + return Vec4( _mm_sub_ps( c.m_v, _mm_mul_ps( a.m_v, b.m_v ) ) ); + } + + friend Vec4 Reciprocal( Vec4::Arg v ) + { + // get the reciprocal estimate + __m128 estimate = _mm_rcp_ps( v.m_v ); + + // one round of Newton-Rhaphson refinement + __m128 diff = _mm_sub_ps( _mm_set1_ps( 1.0f ), _mm_mul_ps( estimate, v.m_v ) ); + return Vec4( _mm_add_ps( _mm_mul_ps( diff, estimate ), estimate ) ); + } + + friend Vec4 Min( Vec4::Arg left, Vec4::Arg right ) + { + return Vec4( _mm_min_ps( left.m_v, right.m_v ) ); + } + + friend Vec4 Max( Vec4::Arg left, Vec4::Arg right ) + { + return Vec4( _mm_max_ps( left.m_v, right.m_v ) ); + } + + friend Vec4 Truncate( Vec4::Arg v ) + { +#if ( SQUISH_USE_SSE == 1 ) + // convert to ints + __m128 input = v.m_v; + __m64 lo = _mm_cvttps_pi32( input ); + __m64 hi = _mm_cvttps_pi32( _mm_movehl_ps( input, input ) ); + + // convert to floats + __m128 part = _mm_movelh_ps( input, _mm_cvtpi32_ps( input, hi ) ); + __m128 truncated = _mm_cvtpi32_ps( part, lo ); + + // clear out the MMX multimedia state to allow FP calls later + _mm_empty(); + return Vec4( truncated ); +#else + // use SSE2 instructions + return Vec4( _mm_cvtepi32_ps( _mm_cvttps_epi32( v.m_v ) ) ); +#endif + } + + friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right ) + { + __m128 bits = _mm_cmplt_ps( left.m_v, right.m_v ); + int value = _mm_movemask_ps( bits ); + return value != 0; + } + +private: + __m128 m_v; +}; + +} // namespace squish + +#endif // ndef SQUISH_SIMD_SSE_H diff --git a/thirdparty/squish/simd_ve.h b/thirdparty/squish/simd_ve.h new file mode 100644 index 0000000000..08a1537503 --- /dev/null +++ b/thirdparty/squish/simd_ve.h @@ -0,0 +1,166 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#ifndef SQUISH_SIMD_VE_H +#define SQUISH_SIMD_VE_H + +#include <altivec.h> +#undef bool + +namespace squish { + +#define VEC4_CONST( X ) Vec4( ( vector float ){ X } ) + +class Vec4 +{ +public: + typedef Vec4 Arg; + + Vec4() {} + + explicit Vec4( vector float v ) : m_v( v ) {} + + Vec4( Vec4 const& arg ) : m_v( arg.m_v ) {} + + Vec4& operator=( Vec4 const& arg ) + { + m_v = arg.m_v; + return *this; + } + + explicit Vec4( float s ) + { + union { vector float v; float c[4]; } u; + u.c[0] = s; + u.c[1] = s; + u.c[2] = s; + u.c[3] = s; + m_v = u.v; + } + + Vec4( float x, float y, float z, float w ) + { + union { vector float v; float c[4]; } u; + u.c[0] = x; + u.c[1] = y; + u.c[2] = z; + u.c[3] = w; + m_v = u.v; + } + + Vec3 GetVec3() const + { + union { vector float v; float c[4]; } u; + u.v = m_v; + return Vec3( u.c[0], u.c[1], u.c[2] ); + } + + Vec4 SplatX() const { return Vec4( vec_splat( m_v, 0 ) ); } + Vec4 SplatY() const { return Vec4( vec_splat( m_v, 1 ) ); } + Vec4 SplatZ() const { return Vec4( vec_splat( m_v, 2 ) ); } + Vec4 SplatW() const { return Vec4( vec_splat( m_v, 3 ) ); } + + Vec4& operator+=( Arg v ) + { + m_v = vec_add( m_v, v.m_v ); + return *this; + } + + Vec4& operator-=( Arg v ) + { + m_v = vec_sub( m_v, v.m_v ); + return *this; + } + + Vec4& operator*=( Arg v ) + { + m_v = vec_madd( m_v, v.m_v, ( vector float ){ -0.0f } ); + return *this; + } + + friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right ) + { + return Vec4( vec_add( left.m_v, right.m_v ) ); + } + + friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right ) + { + return Vec4( vec_sub( left.m_v, right.m_v ) ); + } + + friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right ) + { + return Vec4( vec_madd( left.m_v, right.m_v, ( vector float ){ -0.0f } ) ); + } + + //! Returns a*b + c + friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) + { + return Vec4( vec_madd( a.m_v, b.m_v, c.m_v ) ); + } + + //! Returns -( a*b - c ) + friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) + { + return Vec4( vec_nmsub( a.m_v, b.m_v, c.m_v ) ); + } + + friend Vec4 Reciprocal( Vec4::Arg v ) + { + // get the reciprocal estimate + vector float estimate = vec_re( v.m_v ); + + // one round of Newton-Rhaphson refinement + vector float diff = vec_nmsub( estimate, v.m_v, ( vector float ){ 1.0f } ); + return Vec4( vec_madd( diff, estimate, estimate ) ); + } + + friend Vec4 Min( Vec4::Arg left, Vec4::Arg right ) + { + return Vec4( vec_min( left.m_v, right.m_v ) ); + } + + friend Vec4 Max( Vec4::Arg left, Vec4::Arg right ) + { + return Vec4( vec_max( left.m_v, right.m_v ) ); + } + + friend Vec4 Truncate( Vec4::Arg v ) + { + return Vec4( vec_trunc( v.m_v ) ); + } + + friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right ) + { + return vec_any_lt( left.m_v, right.m_v ) != 0; + } + +private: + vector float m_v; +}; + +} // namespace squish + +#endif // ndef SQUISH_SIMD_VE_H diff --git a/thirdparty/squish/singlecolourfit.cpp b/thirdparty/squish/singlecolourfit.cpp new file mode 100644 index 0000000000..cef0ebc410 --- /dev/null +++ b/thirdparty/squish/singlecolourfit.cpp @@ -0,0 +1,172 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#include "singlecolourfit.h" +#include "colourset.h" +#include "colourblock.h" + +namespace squish { + +struct SourceBlock +{ + u8 start; + u8 end; + u8 error; +}; + +struct SingleColourLookup +{ + SourceBlock sources[2]; +}; + +#include "singlecolourlookup.inl" + +static int FloatToInt( float a, int limit ) +{ + // use ANSI round-to-zero behaviour to get round-to-nearest + int i = ( int )( a + 0.5f ); + + // clamp to the limit + if( i < 0 ) + i = 0; + else if( i > limit ) + i = limit; + + // done + return i; +} + +SingleColourFit::SingleColourFit( ColourSet const* colours, int flags ) + : ColourFit( colours, flags ) +{ + // grab the single colour + Vec3 const* values = m_colours->GetPoints(); + m_colour[0] = ( u8 )FloatToInt( 255.0f*values->X(), 255 ); + m_colour[1] = ( u8 )FloatToInt( 255.0f*values->Y(), 255 ); + m_colour[2] = ( u8 )FloatToInt( 255.0f*values->Z(), 255 ); + + // initialise the best error + m_besterror = INT_MAX; +} + +void SingleColourFit::Compress3( void* block ) +{ + // build the table of lookups + SingleColourLookup const* const lookups[] = + { + lookup_5_3, + lookup_6_3, + lookup_5_3 + }; + + // find the best end-points and index + ComputeEndPoints( lookups ); + + // build the block if we win + if( m_error < m_besterror ) + { + // remap the indices + u8 indices[16]; + m_colours->RemapIndices( &m_index, indices ); + + // save the block + WriteColourBlock3( m_start, m_end, indices, block ); + + // save the error + m_besterror = m_error; + } +} + +void SingleColourFit::Compress4( void* block ) +{ + // build the table of lookups + SingleColourLookup const* const lookups[] = + { + lookup_5_4, + lookup_6_4, + lookup_5_4 + }; + + // find the best end-points and index + ComputeEndPoints( lookups ); + + // build the block if we win + if( m_error < m_besterror ) + { + // remap the indices + u8 indices[16]; + m_colours->RemapIndices( &m_index, indices ); + + // save the block + WriteColourBlock4( m_start, m_end, indices, block ); + + // save the error + m_besterror = m_error; + } +} + +void SingleColourFit::ComputeEndPoints( SingleColourLookup const* const* lookups ) +{ + // check each index combination (endpoint or intermediate) + m_error = INT_MAX; + for( int index = 0; index < 2; ++index ) + { + // check the error for this codebook index + SourceBlock const* sources[3]; + int error = 0; + for( int channel = 0; channel < 3; ++channel ) + { + // grab the lookup table and index for this channel + SingleColourLookup const* lookup = lookups[channel]; + int target = m_colour[channel]; + + // store a pointer to the source for this channel + sources[channel] = lookup[target].sources + index; + + // accumulate the error + int diff = sources[channel]->error; + error += diff*diff; + } + + // keep it if the error is lower + if( error < m_error ) + { + m_start = Vec3( + ( float )sources[0]->start/31.0f, + ( float )sources[1]->start/63.0f, + ( float )sources[2]->start/31.0f + ); + m_end = Vec3( + ( float )sources[0]->end/31.0f, + ( float )sources[1]->end/63.0f, + ( float )sources[2]->end/31.0f + ); + m_index = ( u8 )( 2*index ); + m_error = error; + } + } +} + +} // namespace squish diff --git a/thirdparty/squish/singlecolourfit.h b/thirdparty/squish/singlecolourfit.h new file mode 100644 index 0000000000..974ce77256 --- /dev/null +++ b/thirdparty/squish/singlecolourfit.h @@ -0,0 +1,58 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#ifndef SQUISH_SINGLECOLOURFIT_H +#define SQUISH_SINGLECOLOURFIT_H + +#include "squish.h" +#include "colourfit.h" + +namespace squish { + +class ColourSet; +struct SingleColourLookup; + +class SingleColourFit : public ColourFit +{ +public: + SingleColourFit( ColourSet const* colours, int flags ); + +private: + virtual void Compress3( void* block ); + virtual void Compress4( void* block ); + + void ComputeEndPoints( SingleColourLookup const* const* lookups ); + + u8 m_colour[3]; + Vec3 m_start; + Vec3 m_end; + u8 m_index; + int m_error; + int m_besterror; +}; + +} // namespace squish + +#endif // ndef SQUISH_SINGLECOLOURFIT_H diff --git a/thirdparty/squish/singlecolourlookup.inl b/thirdparty/squish/singlecolourlookup.inl new file mode 100644 index 0000000000..5b44a1e5e6 --- /dev/null +++ b/thirdparty/squish/singlecolourlookup.inl @@ -0,0 +1,1064 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +static SingleColourLookup const lookup_5_3[] = +{ + { { { 0, 0, 0 }, { 0, 0, 0 } } }, + { { { 0, 0, 1 }, { 0, 0, 1 } } }, + { { { 0, 0, 2 }, { 0, 0, 2 } } }, + { { { 0, 0, 3 }, { 0, 1, 1 } } }, + { { { 0, 0, 4 }, { 0, 1, 0 } } }, + { { { 1, 0, 3 }, { 0, 1, 1 } } }, + { { { 1, 0, 2 }, { 0, 1, 2 } } }, + { { { 1, 0, 1 }, { 0, 2, 1 } } }, + { { { 1, 0, 0 }, { 0, 2, 0 } } }, + { { { 1, 0, 1 }, { 0, 2, 1 } } }, + { { { 1, 0, 2 }, { 0, 2, 2 } } }, + { { { 1, 0, 3 }, { 0, 3, 1 } } }, + { { { 1, 0, 4 }, { 0, 3, 0 } } }, + { { { 2, 0, 3 }, { 0, 3, 1 } } }, + { { { 2, 0, 2 }, { 0, 3, 2 } } }, + { { { 2, 0, 1 }, { 0, 4, 1 } } }, + { { { 2, 0, 0 }, { 0, 4, 0 } } }, + { { { 2, 0, 1 }, { 0, 4, 1 } } }, + { { { 2, 0, 2 }, { 0, 4, 2 } } }, + { { { 2, 0, 3 }, { 0, 5, 1 } } }, + { { { 2, 0, 4 }, { 0, 5, 0 } } }, + { { { 3, 0, 3 }, { 0, 5, 1 } } }, + { { { 3, 0, 2 }, { 0, 5, 2 } } }, + { { { 3, 0, 1 }, { 0, 6, 1 } } }, + { { { 3, 0, 0 }, { 0, 6, 0 } } }, + { { { 3, 0, 1 }, { 0, 6, 1 } } }, + { { { 3, 0, 2 }, { 0, 6, 2 } } }, + { { { 3, 0, 3 }, { 0, 7, 1 } } }, + { { { 3, 0, 4 }, { 0, 7, 0 } } }, + { { { 4, 0, 4 }, { 0, 7, 1 } } }, + { { { 4, 0, 3 }, { 0, 7, 2 } } }, + { { { 4, 0, 2 }, { 1, 7, 1 } } }, + { { { 4, 0, 1 }, { 1, 7, 0 } } }, + { { { 4, 0, 0 }, { 0, 8, 0 } } }, + { { { 4, 0, 1 }, { 0, 8, 1 } } }, + { { { 4, 0, 2 }, { 2, 7, 1 } } }, + { { { 4, 0, 3 }, { 2, 7, 0 } } }, + { { { 4, 0, 4 }, { 0, 9, 0 } } }, + { { { 5, 0, 3 }, { 0, 9, 1 } } }, + { { { 5, 0, 2 }, { 3, 7, 1 } } }, + { { { 5, 0, 1 }, { 3, 7, 0 } } }, + { { { 5, 0, 0 }, { 0, 10, 0 } } }, + { { { 5, 0, 1 }, { 0, 10, 1 } } }, + { { { 5, 0, 2 }, { 0, 10, 2 } } }, + { { { 5, 0, 3 }, { 0, 11, 1 } } }, + { { { 5, 0, 4 }, { 0, 11, 0 } } }, + { { { 6, 0, 3 }, { 0, 11, 1 } } }, + { { { 6, 0, 2 }, { 0, 11, 2 } } }, + { { { 6, 0, 1 }, { 0, 12, 1 } } }, + { { { 6, 0, 0 }, { 0, 12, 0 } } }, + { { { 6, 0, 1 }, { 0, 12, 1 } } }, + { { { 6, 0, 2 }, { 0, 12, 2 } } }, + { { { 6, 0, 3 }, { 0, 13, 1 } } }, + { { { 6, 0, 4 }, { 0, 13, 0 } } }, + { { { 7, 0, 3 }, { 0, 13, 1 } } }, + { { { 7, 0, 2 }, { 0, 13, 2 } } }, + { { { 7, 0, 1 }, { 0, 14, 1 } } }, + { { { 7, 0, 0 }, { 0, 14, 0 } } }, + { { { 7, 0, 1 }, { 0, 14, 1 } } }, + { { { 7, 0, 2 }, { 0, 14, 2 } } }, + { { { 7, 0, 3 }, { 0, 15, 1 } } }, + { { { 7, 0, 4 }, { 0, 15, 0 } } }, + { { { 8, 0, 4 }, { 0, 15, 1 } } }, + { { { 8, 0, 3 }, { 0, 15, 2 } } }, + { { { 8, 0, 2 }, { 1, 15, 1 } } }, + { { { 8, 0, 1 }, { 1, 15, 0 } } }, + { { { 8, 0, 0 }, { 0, 16, 0 } } }, + { { { 8, 0, 1 }, { 0, 16, 1 } } }, + { { { 8, 0, 2 }, { 2, 15, 1 } } }, + { { { 8, 0, 3 }, { 2, 15, 0 } } }, + { { { 8, 0, 4 }, { 0, 17, 0 } } }, + { { { 9, 0, 3 }, { 0, 17, 1 } } }, + { { { 9, 0, 2 }, { 3, 15, 1 } } }, + { { { 9, 0, 1 }, { 3, 15, 0 } } }, + { { { 9, 0, 0 }, { 0, 18, 0 } } }, + { { { 9, 0, 1 }, { 0, 18, 1 } } }, + { { { 9, 0, 2 }, { 0, 18, 2 } } }, + { { { 9, 0, 3 }, { 0, 19, 1 } } }, + { { { 9, 0, 4 }, { 0, 19, 0 } } }, + { { { 10, 0, 3 }, { 0, 19, 1 } } }, + { { { 10, 0, 2 }, { 0, 19, 2 } } }, + { { { 10, 0, 1 }, { 0, 20, 1 } } }, + { { { 10, 0, 0 }, { 0, 20, 0 } } }, + { { { 10, 0, 1 }, { 0, 20, 1 } } }, + { { { 10, 0, 2 }, { 0, 20, 2 } } }, + { { { 10, 0, 3 }, { 0, 21, 1 } } }, + { { { 10, 0, 4 }, { 0, 21, 0 } } }, + { { { 11, 0, 3 }, { 0, 21, 1 } } }, + { { { 11, 0, 2 }, { 0, 21, 2 } } }, + { { { 11, 0, 1 }, { 0, 22, 1 } } }, + { { { 11, 0, 0 }, { 0, 22, 0 } } }, + { { { 11, 0, 1 }, { 0, 22, 1 } } }, + { { { 11, 0, 2 }, { 0, 22, 2 } } }, + { { { 11, 0, 3 }, { 0, 23, 1 } } }, + { { { 11, 0, 4 }, { 0, 23, 0 } } }, + { { { 12, 0, 4 }, { 0, 23, 1 } } }, + { { { 12, 0, 3 }, { 0, 23, 2 } } }, + { { { 12, 0, 2 }, { 1, 23, 1 } } }, + { { { 12, 0, 1 }, { 1, 23, 0 } } }, + { { { 12, 0, 0 }, { 0, 24, 0 } } }, + { { { 12, 0, 1 }, { 0, 24, 1 } } }, + { { { 12, 0, 2 }, { 2, 23, 1 } } }, + { { { 12, 0, 3 }, { 2, 23, 0 } } }, + { { { 12, 0, 4 }, { 0, 25, 0 } } }, + { { { 13, 0, 3 }, { 0, 25, 1 } } }, + { { { 13, 0, 2 }, { 3, 23, 1 } } }, + { { { 13, 0, 1 }, { 3, 23, 0 } } }, + { { { 13, 0, 0 }, { 0, 26, 0 } } }, + { { { 13, 0, 1 }, { 0, 26, 1 } } }, + { { { 13, 0, 2 }, { 0, 26, 2 } } }, + { { { 13, 0, 3 }, { 0, 27, 1 } } }, + { { { 13, 0, 4 }, { 0, 27, 0 } } }, + { { { 14, 0, 3 }, { 0, 27, 1 } } }, + { { { 14, 0, 2 }, { 0, 27, 2 } } }, + { { { 14, 0, 1 }, { 0, 28, 1 } } }, + { { { 14, 0, 0 }, { 0, 28, 0 } } }, + { { { 14, 0, 1 }, { 0, 28, 1 } } }, + { { { 14, 0, 2 }, { 0, 28, 2 } } }, + { { { 14, 0, 3 }, { 0, 29, 1 } } }, + { { { 14, 0, 4 }, { 0, 29, 0 } } }, + { { { 15, 0, 3 }, { 0, 29, 1 } } }, + { { { 15, 0, 2 }, { 0, 29, 2 } } }, + { { { 15, 0, 1 }, { 0, 30, 1 } } }, + { { { 15, 0, 0 }, { 0, 30, 0 } } }, + { { { 15, 0, 1 }, { 0, 30, 1 } } }, + { { { 15, 0, 2 }, { 0, 30, 2 } } }, + { { { 15, 0, 3 }, { 0, 31, 1 } } }, + { { { 15, 0, 4 }, { 0, 31, 0 } } }, + { { { 16, 0, 4 }, { 0, 31, 1 } } }, + { { { 16, 0, 3 }, { 0, 31, 2 } } }, + { { { 16, 0, 2 }, { 1, 31, 1 } } }, + { { { 16, 0, 1 }, { 1, 31, 0 } } }, + { { { 16, 0, 0 }, { 4, 28, 0 } } }, + { { { 16, 0, 1 }, { 4, 28, 1 } } }, + { { { 16, 0, 2 }, { 2, 31, 1 } } }, + { { { 16, 0, 3 }, { 2, 31, 0 } } }, + { { { 16, 0, 4 }, { 4, 29, 0 } } }, + { { { 17, 0, 3 }, { 4, 29, 1 } } }, + { { { 17, 0, 2 }, { 3, 31, 1 } } }, + { { { 17, 0, 1 }, { 3, 31, 0 } } }, + { { { 17, 0, 0 }, { 4, 30, 0 } } }, + { { { 17, 0, 1 }, { 4, 30, 1 } } }, + { { { 17, 0, 2 }, { 4, 30, 2 } } }, + { { { 17, 0, 3 }, { 4, 31, 1 } } }, + { { { 17, 0, 4 }, { 4, 31, 0 } } }, + { { { 18, 0, 3 }, { 4, 31, 1 } } }, + { { { 18, 0, 2 }, { 4, 31, 2 } } }, + { { { 18, 0, 1 }, { 5, 31, 1 } } }, + { { { 18, 0, 0 }, { 5, 31, 0 } } }, + { { { 18, 0, 1 }, { 5, 31, 1 } } }, + { { { 18, 0, 2 }, { 5, 31, 2 } } }, + { { { 18, 0, 3 }, { 6, 31, 1 } } }, + { { { 18, 0, 4 }, { 6, 31, 0 } } }, + { { { 19, 0, 3 }, { 6, 31, 1 } } }, + { { { 19, 0, 2 }, { 6, 31, 2 } } }, + { { { 19, 0, 1 }, { 7, 31, 1 } } }, + { { { 19, 0, 0 }, { 7, 31, 0 } } }, + { { { 19, 0, 1 }, { 7, 31, 1 } } }, + { { { 19, 0, 2 }, { 7, 31, 2 } } }, + { { { 19, 0, 3 }, { 8, 31, 1 } } }, + { { { 19, 0, 4 }, { 8, 31, 0 } } }, + { { { 20, 0, 4 }, { 8, 31, 1 } } }, + { { { 20, 0, 3 }, { 8, 31, 2 } } }, + { { { 20, 0, 2 }, { 9, 31, 1 } } }, + { { { 20, 0, 1 }, { 9, 31, 0 } } }, + { { { 20, 0, 0 }, { 12, 28, 0 } } }, + { { { 20, 0, 1 }, { 12, 28, 1 } } }, + { { { 20, 0, 2 }, { 10, 31, 1 } } }, + { { { 20, 0, 3 }, { 10, 31, 0 } } }, + { { { 20, 0, 4 }, { 12, 29, 0 } } }, + { { { 21, 0, 3 }, { 12, 29, 1 } } }, + { { { 21, 0, 2 }, { 11, 31, 1 } } }, + { { { 21, 0, 1 }, { 11, 31, 0 } } }, + { { { 21, 0, 0 }, { 12, 30, 0 } } }, + { { { 21, 0, 1 }, { 12, 30, 1 } } }, + { { { 21, 0, 2 }, { 12, 30, 2 } } }, + { { { 21, 0, 3 }, { 12, 31, 1 } } }, + { { { 21, 0, 4 }, { 12, 31, 0 } } }, + { { { 22, 0, 3 }, { 12, 31, 1 } } }, + { { { 22, 0, 2 }, { 12, 31, 2 } } }, + { { { 22, 0, 1 }, { 13, 31, 1 } } }, + { { { 22, 0, 0 }, { 13, 31, 0 } } }, + { { { 22, 0, 1 }, { 13, 31, 1 } } }, + { { { 22, 0, 2 }, { 13, 31, 2 } } }, + { { { 22, 0, 3 }, { 14, 31, 1 } } }, + { { { 22, 0, 4 }, { 14, 31, 0 } } }, + { { { 23, 0, 3 }, { 14, 31, 1 } } }, + { { { 23, 0, 2 }, { 14, 31, 2 } } }, + { { { 23, 0, 1 }, { 15, 31, 1 } } }, + { { { 23, 0, 0 }, { 15, 31, 0 } } }, + { { { 23, 0, 1 }, { 15, 31, 1 } } }, + { { { 23, 0, 2 }, { 15, 31, 2 } } }, + { { { 23, 0, 3 }, { 16, 31, 1 } } }, + { { { 23, 0, 4 }, { 16, 31, 0 } } }, + { { { 24, 0, 4 }, { 16, 31, 1 } } }, + { { { 24, 0, 3 }, { 16, 31, 2 } } }, + { { { 24, 0, 2 }, { 17, 31, 1 } } }, + { { { 24, 0, 1 }, { 17, 31, 0 } } }, + { { { 24, 0, 0 }, { 20, 28, 0 } } }, + { { { 24, 0, 1 }, { 20, 28, 1 } } }, + { { { 24, 0, 2 }, { 18, 31, 1 } } }, + { { { 24, 0, 3 }, { 18, 31, 0 } } }, + { { { 24, 0, 4 }, { 20, 29, 0 } } }, + { { { 25, 0, 3 }, { 20, 29, 1 } } }, + { { { 25, 0, 2 }, { 19, 31, 1 } } }, + { { { 25, 0, 1 }, { 19, 31, 0 } } }, + { { { 25, 0, 0 }, { 20, 30, 0 } } }, + { { { 25, 0, 1 }, { 20, 30, 1 } } }, + { { { 25, 0, 2 }, { 20, 30, 2 } } }, + { { { 25, 0, 3 }, { 20, 31, 1 } } }, + { { { 25, 0, 4 }, { 20, 31, 0 } } }, + { { { 26, 0, 3 }, { 20, 31, 1 } } }, + { { { 26, 0, 2 }, { 20, 31, 2 } } }, + { { { 26, 0, 1 }, { 21, 31, 1 } } }, + { { { 26, 0, 0 }, { 21, 31, 0 } } }, + { { { 26, 0, 1 }, { 21, 31, 1 } } }, + { { { 26, 0, 2 }, { 21, 31, 2 } } }, + { { { 26, 0, 3 }, { 22, 31, 1 } } }, + { { { 26, 0, 4 }, { 22, 31, 0 } } }, + { { { 27, 0, 3 }, { 22, 31, 1 } } }, + { { { 27, 0, 2 }, { 22, 31, 2 } } }, + { { { 27, 0, 1 }, { 23, 31, 1 } } }, + { { { 27, 0, 0 }, { 23, 31, 0 } } }, + { { { 27, 0, 1 }, { 23, 31, 1 } } }, + { { { 27, 0, 2 }, { 23, 31, 2 } } }, + { { { 27, 0, 3 }, { 24, 31, 1 } } }, + { { { 27, 0, 4 }, { 24, 31, 0 } } }, + { { { 28, 0, 4 }, { 24, 31, 1 } } }, + { { { 28, 0, 3 }, { 24, 31, 2 } } }, + { { { 28, 0, 2 }, { 25, 31, 1 } } }, + { { { 28, 0, 1 }, { 25, 31, 0 } } }, + { { { 28, 0, 0 }, { 28, 28, 0 } } }, + { { { 28, 0, 1 }, { 28, 28, 1 } } }, + { { { 28, 0, 2 }, { 26, 31, 1 } } }, + { { { 28, 0, 3 }, { 26, 31, 0 } } }, + { { { 28, 0, 4 }, { 28, 29, 0 } } }, + { { { 29, 0, 3 }, { 28, 29, 1 } } }, + { { { 29, 0, 2 }, { 27, 31, 1 } } }, + { { { 29, 0, 1 }, { 27, 31, 0 } } }, + { { { 29, 0, 0 }, { 28, 30, 0 } } }, + { { { 29, 0, 1 }, { 28, 30, 1 } } }, + { { { 29, 0, 2 }, { 28, 30, 2 } } }, + { { { 29, 0, 3 }, { 28, 31, 1 } } }, + { { { 29, 0, 4 }, { 28, 31, 0 } } }, + { { { 30, 0, 3 }, { 28, 31, 1 } } }, + { { { 30, 0, 2 }, { 28, 31, 2 } } }, + { { { 30, 0, 1 }, { 29, 31, 1 } } }, + { { { 30, 0, 0 }, { 29, 31, 0 } } }, + { { { 30, 0, 1 }, { 29, 31, 1 } } }, + { { { 30, 0, 2 }, { 29, 31, 2 } } }, + { { { 30, 0, 3 }, { 30, 31, 1 } } }, + { { { 30, 0, 4 }, { 30, 31, 0 } } }, + { { { 31, 0, 3 }, { 30, 31, 1 } } }, + { { { 31, 0, 2 }, { 30, 31, 2 } } }, + { { { 31, 0, 1 }, { 31, 31, 1 } } }, + { { { 31, 0, 0 }, { 31, 31, 0 } } } +}; + +static SingleColourLookup const lookup_6_3[] = +{ + { { { 0, 0, 0 }, { 0, 0, 0 } } }, + { { { 0, 0, 1 }, { 0, 1, 1 } } }, + { { { 0, 0, 2 }, { 0, 1, 0 } } }, + { { { 1, 0, 1 }, { 0, 2, 1 } } }, + { { { 1, 0, 0 }, { 0, 2, 0 } } }, + { { { 1, 0, 1 }, { 0, 3, 1 } } }, + { { { 1, 0, 2 }, { 0, 3, 0 } } }, + { { { 2, 0, 1 }, { 0, 4, 1 } } }, + { { { 2, 0, 0 }, { 0, 4, 0 } } }, + { { { 2, 0, 1 }, { 0, 5, 1 } } }, + { { { 2, 0, 2 }, { 0, 5, 0 } } }, + { { { 3, 0, 1 }, { 0, 6, 1 } } }, + { { { 3, 0, 0 }, { 0, 6, 0 } } }, + { { { 3, 0, 1 }, { 0, 7, 1 } } }, + { { { 3, 0, 2 }, { 0, 7, 0 } } }, + { { { 4, 0, 1 }, { 0, 8, 1 } } }, + { { { 4, 0, 0 }, { 0, 8, 0 } } }, + { { { 4, 0, 1 }, { 0, 9, 1 } } }, + { { { 4, 0, 2 }, { 0, 9, 0 } } }, + { { { 5, 0, 1 }, { 0, 10, 1 } } }, + { { { 5, 0, 0 }, { 0, 10, 0 } } }, + { { { 5, 0, 1 }, { 0, 11, 1 } } }, + { { { 5, 0, 2 }, { 0, 11, 0 } } }, + { { { 6, 0, 1 }, { 0, 12, 1 } } }, + { { { 6, 0, 0 }, { 0, 12, 0 } } }, + { { { 6, 0, 1 }, { 0, 13, 1 } } }, + { { { 6, 0, 2 }, { 0, 13, 0 } } }, + { { { 7, 0, 1 }, { 0, 14, 1 } } }, + { { { 7, 0, 0 }, { 0, 14, 0 } } }, + { { { 7, 0, 1 }, { 0, 15, 1 } } }, + { { { 7, 0, 2 }, { 0, 15, 0 } } }, + { { { 8, 0, 1 }, { 0, 16, 1 } } }, + { { { 8, 0, 0 }, { 0, 16, 0 } } }, + { { { 8, 0, 1 }, { 0, 17, 1 } } }, + { { { 8, 0, 2 }, { 0, 17, 0 } } }, + { { { 9, 0, 1 }, { 0, 18, 1 } } }, + { { { 9, 0, 0 }, { 0, 18, 0 } } }, + { { { 9, 0, 1 }, { 0, 19, 1 } } }, + { { { 9, 0, 2 }, { 0, 19, 0 } } }, + { { { 10, 0, 1 }, { 0, 20, 1 } } }, + { { { 10, 0, 0 }, { 0, 20, 0 } } }, + { { { 10, 0, 1 }, { 0, 21, 1 } } }, + { { { 10, 0, 2 }, { 0, 21, 0 } } }, + { { { 11, 0, 1 }, { 0, 22, 1 } } }, + { { { 11, 0, 0 }, { 0, 22, 0 } } }, + { { { 11, 0, 1 }, { 0, 23, 1 } } }, + { { { 11, 0, 2 }, { 0, 23, 0 } } }, + { { { 12, 0, 1 }, { 0, 24, 1 } } }, + { { { 12, 0, 0 }, { 0, 24, 0 } } }, + { { { 12, 0, 1 }, { 0, 25, 1 } } }, + { { { 12, 0, 2 }, { 0, 25, 0 } } }, + { { { 13, 0, 1 }, { 0, 26, 1 } } }, + { { { 13, 0, 0 }, { 0, 26, 0 } } }, + { { { 13, 0, 1 }, { 0, 27, 1 } } }, + { { { 13, 0, 2 }, { 0, 27, 0 } } }, + { { { 14, 0, 1 }, { 0, 28, 1 } } }, + { { { 14, 0, 0 }, { 0, 28, 0 } } }, + { { { 14, 0, 1 }, { 0, 29, 1 } } }, + { { { 14, 0, 2 }, { 0, 29, 0 } } }, + { { { 15, 0, 1 }, { 0, 30, 1 } } }, + { { { 15, 0, 0 }, { 0, 30, 0 } } }, + { { { 15, 0, 1 }, { 0, 31, 1 } } }, + { { { 15, 0, 2 }, { 0, 31, 0 } } }, + { { { 16, 0, 2 }, { 1, 31, 1 } } }, + { { { 16, 0, 1 }, { 1, 31, 0 } } }, + { { { 16, 0, 0 }, { 0, 32, 0 } } }, + { { { 16, 0, 1 }, { 2, 31, 0 } } }, + { { { 16, 0, 2 }, { 0, 33, 0 } } }, + { { { 17, 0, 1 }, { 3, 31, 0 } } }, + { { { 17, 0, 0 }, { 0, 34, 0 } } }, + { { { 17, 0, 1 }, { 4, 31, 0 } } }, + { { { 17, 0, 2 }, { 0, 35, 0 } } }, + { { { 18, 0, 1 }, { 5, 31, 0 } } }, + { { { 18, 0, 0 }, { 0, 36, 0 } } }, + { { { 18, 0, 1 }, { 6, 31, 0 } } }, + { { { 18, 0, 2 }, { 0, 37, 0 } } }, + { { { 19, 0, 1 }, { 7, 31, 0 } } }, + { { { 19, 0, 0 }, { 0, 38, 0 } } }, + { { { 19, 0, 1 }, { 8, 31, 0 } } }, + { { { 19, 0, 2 }, { 0, 39, 0 } } }, + { { { 20, 0, 1 }, { 9, 31, 0 } } }, + { { { 20, 0, 0 }, { 0, 40, 0 } } }, + { { { 20, 0, 1 }, { 10, 31, 0 } } }, + { { { 20, 0, 2 }, { 0, 41, 0 } } }, + { { { 21, 0, 1 }, { 11, 31, 0 } } }, + { { { 21, 0, 0 }, { 0, 42, 0 } } }, + { { { 21, 0, 1 }, { 12, 31, 0 } } }, + { { { 21, 0, 2 }, { 0, 43, 0 } } }, + { { { 22, 0, 1 }, { 13, 31, 0 } } }, + { { { 22, 0, 0 }, { 0, 44, 0 } } }, + { { { 22, 0, 1 }, { 14, 31, 0 } } }, + { { { 22, 0, 2 }, { 0, 45, 0 } } }, + { { { 23, 0, 1 }, { 15, 31, 0 } } }, + { { { 23, 0, 0 }, { 0, 46, 0 } } }, + { { { 23, 0, 1 }, { 0, 47, 1 } } }, + { { { 23, 0, 2 }, { 0, 47, 0 } } }, + { { { 24, 0, 1 }, { 0, 48, 1 } } }, + { { { 24, 0, 0 }, { 0, 48, 0 } } }, + { { { 24, 0, 1 }, { 0, 49, 1 } } }, + { { { 24, 0, 2 }, { 0, 49, 0 } } }, + { { { 25, 0, 1 }, { 0, 50, 1 } } }, + { { { 25, 0, 0 }, { 0, 50, 0 } } }, + { { { 25, 0, 1 }, { 0, 51, 1 } } }, + { { { 25, 0, 2 }, { 0, 51, 0 } } }, + { { { 26, 0, 1 }, { 0, 52, 1 } } }, + { { { 26, 0, 0 }, { 0, 52, 0 } } }, + { { { 26, 0, 1 }, { 0, 53, 1 } } }, + { { { 26, 0, 2 }, { 0, 53, 0 } } }, + { { { 27, 0, 1 }, { 0, 54, 1 } } }, + { { { 27, 0, 0 }, { 0, 54, 0 } } }, + { { { 27, 0, 1 }, { 0, 55, 1 } } }, + { { { 27, 0, 2 }, { 0, 55, 0 } } }, + { { { 28, 0, 1 }, { 0, 56, 1 } } }, + { { { 28, 0, 0 }, { 0, 56, 0 } } }, + { { { 28, 0, 1 }, { 0, 57, 1 } } }, + { { { 28, 0, 2 }, { 0, 57, 0 } } }, + { { { 29, 0, 1 }, { 0, 58, 1 } } }, + { { { 29, 0, 0 }, { 0, 58, 0 } } }, + { { { 29, 0, 1 }, { 0, 59, 1 } } }, + { { { 29, 0, 2 }, { 0, 59, 0 } } }, + { { { 30, 0, 1 }, { 0, 60, 1 } } }, + { { { 30, 0, 0 }, { 0, 60, 0 } } }, + { { { 30, 0, 1 }, { 0, 61, 1 } } }, + { { { 30, 0, 2 }, { 0, 61, 0 } } }, + { { { 31, 0, 1 }, { 0, 62, 1 } } }, + { { { 31, 0, 0 }, { 0, 62, 0 } } }, + { { { 31, 0, 1 }, { 0, 63, 1 } } }, + { { { 31, 0, 2 }, { 0, 63, 0 } } }, + { { { 32, 0, 2 }, { 1, 63, 1 } } }, + { { { 32, 0, 1 }, { 1, 63, 0 } } }, + { { { 32, 0, 0 }, { 16, 48, 0 } } }, + { { { 32, 0, 1 }, { 2, 63, 0 } } }, + { { { 32, 0, 2 }, { 16, 49, 0 } } }, + { { { 33, 0, 1 }, { 3, 63, 0 } } }, + { { { 33, 0, 0 }, { 16, 50, 0 } } }, + { { { 33, 0, 1 }, { 4, 63, 0 } } }, + { { { 33, 0, 2 }, { 16, 51, 0 } } }, + { { { 34, 0, 1 }, { 5, 63, 0 } } }, + { { { 34, 0, 0 }, { 16, 52, 0 } } }, + { { { 34, 0, 1 }, { 6, 63, 0 } } }, + { { { 34, 0, 2 }, { 16, 53, 0 } } }, + { { { 35, 0, 1 }, { 7, 63, 0 } } }, + { { { 35, 0, 0 }, { 16, 54, 0 } } }, + { { { 35, 0, 1 }, { 8, 63, 0 } } }, + { { { 35, 0, 2 }, { 16, 55, 0 } } }, + { { { 36, 0, 1 }, { 9, 63, 0 } } }, + { { { 36, 0, 0 }, { 16, 56, 0 } } }, + { { { 36, 0, 1 }, { 10, 63, 0 } } }, + { { { 36, 0, 2 }, { 16, 57, 0 } } }, + { { { 37, 0, 1 }, { 11, 63, 0 } } }, + { { { 37, 0, 0 }, { 16, 58, 0 } } }, + { { { 37, 0, 1 }, { 12, 63, 0 } } }, + { { { 37, 0, 2 }, { 16, 59, 0 } } }, + { { { 38, 0, 1 }, { 13, 63, 0 } } }, + { { { 38, 0, 0 }, { 16, 60, 0 } } }, + { { { 38, 0, 1 }, { 14, 63, 0 } } }, + { { { 38, 0, 2 }, { 16, 61, 0 } } }, + { { { 39, 0, 1 }, { 15, 63, 0 } } }, + { { { 39, 0, 0 }, { 16, 62, 0 } } }, + { { { 39, 0, 1 }, { 16, 63, 1 } } }, + { { { 39, 0, 2 }, { 16, 63, 0 } } }, + { { { 40, 0, 1 }, { 17, 63, 1 } } }, + { { { 40, 0, 0 }, { 17, 63, 0 } } }, + { { { 40, 0, 1 }, { 18, 63, 1 } } }, + { { { 40, 0, 2 }, { 18, 63, 0 } } }, + { { { 41, 0, 1 }, { 19, 63, 1 } } }, + { { { 41, 0, 0 }, { 19, 63, 0 } } }, + { { { 41, 0, 1 }, { 20, 63, 1 } } }, + { { { 41, 0, 2 }, { 20, 63, 0 } } }, + { { { 42, 0, 1 }, { 21, 63, 1 } } }, + { { { 42, 0, 0 }, { 21, 63, 0 } } }, + { { { 42, 0, 1 }, { 22, 63, 1 } } }, + { { { 42, 0, 2 }, { 22, 63, 0 } } }, + { { { 43, 0, 1 }, { 23, 63, 1 } } }, + { { { 43, 0, 0 }, { 23, 63, 0 } } }, + { { { 43, 0, 1 }, { 24, 63, 1 } } }, + { { { 43, 0, 2 }, { 24, 63, 0 } } }, + { { { 44, 0, 1 }, { 25, 63, 1 } } }, + { { { 44, 0, 0 }, { 25, 63, 0 } } }, + { { { 44, 0, 1 }, { 26, 63, 1 } } }, + { { { 44, 0, 2 }, { 26, 63, 0 } } }, + { { { 45, 0, 1 }, { 27, 63, 1 } } }, + { { { 45, 0, 0 }, { 27, 63, 0 } } }, + { { { 45, 0, 1 }, { 28, 63, 1 } } }, + { { { 45, 0, 2 }, { 28, 63, 0 } } }, + { { { 46, 0, 1 }, { 29, 63, 1 } } }, + { { { 46, 0, 0 }, { 29, 63, 0 } } }, + { { { 46, 0, 1 }, { 30, 63, 1 } } }, + { { { 46, 0, 2 }, { 30, 63, 0 } } }, + { { { 47, 0, 1 }, { 31, 63, 1 } } }, + { { { 47, 0, 0 }, { 31, 63, 0 } } }, + { { { 47, 0, 1 }, { 32, 63, 1 } } }, + { { { 47, 0, 2 }, { 32, 63, 0 } } }, + { { { 48, 0, 2 }, { 33, 63, 1 } } }, + { { { 48, 0, 1 }, { 33, 63, 0 } } }, + { { { 48, 0, 0 }, { 48, 48, 0 } } }, + { { { 48, 0, 1 }, { 34, 63, 0 } } }, + { { { 48, 0, 2 }, { 48, 49, 0 } } }, + { { { 49, 0, 1 }, { 35, 63, 0 } } }, + { { { 49, 0, 0 }, { 48, 50, 0 } } }, + { { { 49, 0, 1 }, { 36, 63, 0 } } }, + { { { 49, 0, 2 }, { 48, 51, 0 } } }, + { { { 50, 0, 1 }, { 37, 63, 0 } } }, + { { { 50, 0, 0 }, { 48, 52, 0 } } }, + { { { 50, 0, 1 }, { 38, 63, 0 } } }, + { { { 50, 0, 2 }, { 48, 53, 0 } } }, + { { { 51, 0, 1 }, { 39, 63, 0 } } }, + { { { 51, 0, 0 }, { 48, 54, 0 } } }, + { { { 51, 0, 1 }, { 40, 63, 0 } } }, + { { { 51, 0, 2 }, { 48, 55, 0 } } }, + { { { 52, 0, 1 }, { 41, 63, 0 } } }, + { { { 52, 0, 0 }, { 48, 56, 0 } } }, + { { { 52, 0, 1 }, { 42, 63, 0 } } }, + { { { 52, 0, 2 }, { 48, 57, 0 } } }, + { { { 53, 0, 1 }, { 43, 63, 0 } } }, + { { { 53, 0, 0 }, { 48, 58, 0 } } }, + { { { 53, 0, 1 }, { 44, 63, 0 } } }, + { { { 53, 0, 2 }, { 48, 59, 0 } } }, + { { { 54, 0, 1 }, { 45, 63, 0 } } }, + { { { 54, 0, 0 }, { 48, 60, 0 } } }, + { { { 54, 0, 1 }, { 46, 63, 0 } } }, + { { { 54, 0, 2 }, { 48, 61, 0 } } }, + { { { 55, 0, 1 }, { 47, 63, 0 } } }, + { { { 55, 0, 0 }, { 48, 62, 0 } } }, + { { { 55, 0, 1 }, { 48, 63, 1 } } }, + { { { 55, 0, 2 }, { 48, 63, 0 } } }, + { { { 56, 0, 1 }, { 49, 63, 1 } } }, + { { { 56, 0, 0 }, { 49, 63, 0 } } }, + { { { 56, 0, 1 }, { 50, 63, 1 } } }, + { { { 56, 0, 2 }, { 50, 63, 0 } } }, + { { { 57, 0, 1 }, { 51, 63, 1 } } }, + { { { 57, 0, 0 }, { 51, 63, 0 } } }, + { { { 57, 0, 1 }, { 52, 63, 1 } } }, + { { { 57, 0, 2 }, { 52, 63, 0 } } }, + { { { 58, 0, 1 }, { 53, 63, 1 } } }, + { { { 58, 0, 0 }, { 53, 63, 0 } } }, + { { { 58, 0, 1 }, { 54, 63, 1 } } }, + { { { 58, 0, 2 }, { 54, 63, 0 } } }, + { { { 59, 0, 1 }, { 55, 63, 1 } } }, + { { { 59, 0, 0 }, { 55, 63, 0 } } }, + { { { 59, 0, 1 }, { 56, 63, 1 } } }, + { { { 59, 0, 2 }, { 56, 63, 0 } } }, + { { { 60, 0, 1 }, { 57, 63, 1 } } }, + { { { 60, 0, 0 }, { 57, 63, 0 } } }, + { { { 60, 0, 1 }, { 58, 63, 1 } } }, + { { { 60, 0, 2 }, { 58, 63, 0 } } }, + { { { 61, 0, 1 }, { 59, 63, 1 } } }, + { { { 61, 0, 0 }, { 59, 63, 0 } } }, + { { { 61, 0, 1 }, { 60, 63, 1 } } }, + { { { 61, 0, 2 }, { 60, 63, 0 } } }, + { { { 62, 0, 1 }, { 61, 63, 1 } } }, + { { { 62, 0, 0 }, { 61, 63, 0 } } }, + { { { 62, 0, 1 }, { 62, 63, 1 } } }, + { { { 62, 0, 2 }, { 62, 63, 0 } } }, + { { { 63, 0, 1 }, { 63, 63, 1 } } }, + { { { 63, 0, 0 }, { 63, 63, 0 } } } +}; + +static SingleColourLookup const lookup_5_4[] = +{ + { { { 0, 0, 0 }, { 0, 0, 0 } } }, + { { { 0, 0, 1 }, { 0, 1, 1 } } }, + { { { 0, 0, 2 }, { 0, 1, 0 } } }, + { { { 0, 0, 3 }, { 0, 1, 1 } } }, + { { { 0, 0, 4 }, { 0, 2, 1 } } }, + { { { 1, 0, 3 }, { 0, 2, 0 } } }, + { { { 1, 0, 2 }, { 0, 2, 1 } } }, + { { { 1, 0, 1 }, { 0, 3, 1 } } }, + { { { 1, 0, 0 }, { 0, 3, 0 } } }, + { { { 1, 0, 1 }, { 1, 2, 1 } } }, + { { { 1, 0, 2 }, { 1, 2, 0 } } }, + { { { 1, 0, 3 }, { 0, 4, 0 } } }, + { { { 1, 0, 4 }, { 0, 5, 1 } } }, + { { { 2, 0, 3 }, { 0, 5, 0 } } }, + { { { 2, 0, 2 }, { 0, 5, 1 } } }, + { { { 2, 0, 1 }, { 0, 6, 1 } } }, + { { { 2, 0, 0 }, { 0, 6, 0 } } }, + { { { 2, 0, 1 }, { 2, 3, 1 } } }, + { { { 2, 0, 2 }, { 2, 3, 0 } } }, + { { { 2, 0, 3 }, { 0, 7, 0 } } }, + { { { 2, 0, 4 }, { 1, 6, 1 } } }, + { { { 3, 0, 3 }, { 1, 6, 0 } } }, + { { { 3, 0, 2 }, { 0, 8, 0 } } }, + { { { 3, 0, 1 }, { 0, 9, 1 } } }, + { { { 3, 0, 0 }, { 0, 9, 0 } } }, + { { { 3, 0, 1 }, { 0, 9, 1 } } }, + { { { 3, 0, 2 }, { 0, 10, 1 } } }, + { { { 3, 0, 3 }, { 0, 10, 0 } } }, + { { { 3, 0, 4 }, { 2, 7, 1 } } }, + { { { 4, 0, 4 }, { 2, 7, 0 } } }, + { { { 4, 0, 3 }, { 0, 11, 0 } } }, + { { { 4, 0, 2 }, { 1, 10, 1 } } }, + { { { 4, 0, 1 }, { 1, 10, 0 } } }, + { { { 4, 0, 0 }, { 0, 12, 0 } } }, + { { { 4, 0, 1 }, { 0, 13, 1 } } }, + { { { 4, 0, 2 }, { 0, 13, 0 } } }, + { { { 4, 0, 3 }, { 0, 13, 1 } } }, + { { { 4, 0, 4 }, { 0, 14, 1 } } }, + { { { 5, 0, 3 }, { 0, 14, 0 } } }, + { { { 5, 0, 2 }, { 2, 11, 1 } } }, + { { { 5, 0, 1 }, { 2, 11, 0 } } }, + { { { 5, 0, 0 }, { 0, 15, 0 } } }, + { { { 5, 0, 1 }, { 1, 14, 1 } } }, + { { { 5, 0, 2 }, { 1, 14, 0 } } }, + { { { 5, 0, 3 }, { 0, 16, 0 } } }, + { { { 5, 0, 4 }, { 0, 17, 1 } } }, + { { { 6, 0, 3 }, { 0, 17, 0 } } }, + { { { 6, 0, 2 }, { 0, 17, 1 } } }, + { { { 6, 0, 1 }, { 0, 18, 1 } } }, + { { { 6, 0, 0 }, { 0, 18, 0 } } }, + { { { 6, 0, 1 }, { 2, 15, 1 } } }, + { { { 6, 0, 2 }, { 2, 15, 0 } } }, + { { { 6, 0, 3 }, { 0, 19, 0 } } }, + { { { 6, 0, 4 }, { 1, 18, 1 } } }, + { { { 7, 0, 3 }, { 1, 18, 0 } } }, + { { { 7, 0, 2 }, { 0, 20, 0 } } }, + { { { 7, 0, 1 }, { 0, 21, 1 } } }, + { { { 7, 0, 0 }, { 0, 21, 0 } } }, + { { { 7, 0, 1 }, { 0, 21, 1 } } }, + { { { 7, 0, 2 }, { 0, 22, 1 } } }, + { { { 7, 0, 3 }, { 0, 22, 0 } } }, + { { { 7, 0, 4 }, { 2, 19, 1 } } }, + { { { 8, 0, 4 }, { 2, 19, 0 } } }, + { { { 8, 0, 3 }, { 0, 23, 0 } } }, + { { { 8, 0, 2 }, { 1, 22, 1 } } }, + { { { 8, 0, 1 }, { 1, 22, 0 } } }, + { { { 8, 0, 0 }, { 0, 24, 0 } } }, + { { { 8, 0, 1 }, { 0, 25, 1 } } }, + { { { 8, 0, 2 }, { 0, 25, 0 } } }, + { { { 8, 0, 3 }, { 0, 25, 1 } } }, + { { { 8, 0, 4 }, { 0, 26, 1 } } }, + { { { 9, 0, 3 }, { 0, 26, 0 } } }, + { { { 9, 0, 2 }, { 2, 23, 1 } } }, + { { { 9, 0, 1 }, { 2, 23, 0 } } }, + { { { 9, 0, 0 }, { 0, 27, 0 } } }, + { { { 9, 0, 1 }, { 1, 26, 1 } } }, + { { { 9, 0, 2 }, { 1, 26, 0 } } }, + { { { 9, 0, 3 }, { 0, 28, 0 } } }, + { { { 9, 0, 4 }, { 0, 29, 1 } } }, + { { { 10, 0, 3 }, { 0, 29, 0 } } }, + { { { 10, 0, 2 }, { 0, 29, 1 } } }, + { { { 10, 0, 1 }, { 0, 30, 1 } } }, + { { { 10, 0, 0 }, { 0, 30, 0 } } }, + { { { 10, 0, 1 }, { 2, 27, 1 } } }, + { { { 10, 0, 2 }, { 2, 27, 0 } } }, + { { { 10, 0, 3 }, { 0, 31, 0 } } }, + { { { 10, 0, 4 }, { 1, 30, 1 } } }, + { { { 11, 0, 3 }, { 1, 30, 0 } } }, + { { { 11, 0, 2 }, { 4, 24, 0 } } }, + { { { 11, 0, 1 }, { 1, 31, 1 } } }, + { { { 11, 0, 0 }, { 1, 31, 0 } } }, + { { { 11, 0, 1 }, { 1, 31, 1 } } }, + { { { 11, 0, 2 }, { 2, 30, 1 } } }, + { { { 11, 0, 3 }, { 2, 30, 0 } } }, + { { { 11, 0, 4 }, { 2, 31, 1 } } }, + { { { 12, 0, 4 }, { 2, 31, 0 } } }, + { { { 12, 0, 3 }, { 4, 27, 0 } } }, + { { { 12, 0, 2 }, { 3, 30, 1 } } }, + { { { 12, 0, 1 }, { 3, 30, 0 } } }, + { { { 12, 0, 0 }, { 4, 28, 0 } } }, + { { { 12, 0, 1 }, { 3, 31, 1 } } }, + { { { 12, 0, 2 }, { 3, 31, 0 } } }, + { { { 12, 0, 3 }, { 3, 31, 1 } } }, + { { { 12, 0, 4 }, { 4, 30, 1 } } }, + { { { 13, 0, 3 }, { 4, 30, 0 } } }, + { { { 13, 0, 2 }, { 6, 27, 1 } } }, + { { { 13, 0, 1 }, { 6, 27, 0 } } }, + { { { 13, 0, 0 }, { 4, 31, 0 } } }, + { { { 13, 0, 1 }, { 5, 30, 1 } } }, + { { { 13, 0, 2 }, { 5, 30, 0 } } }, + { { { 13, 0, 3 }, { 8, 24, 0 } } }, + { { { 13, 0, 4 }, { 5, 31, 1 } } }, + { { { 14, 0, 3 }, { 5, 31, 0 } } }, + { { { 14, 0, 2 }, { 5, 31, 1 } } }, + { { { 14, 0, 1 }, { 6, 30, 1 } } }, + { { { 14, 0, 0 }, { 6, 30, 0 } } }, + { { { 14, 0, 1 }, { 6, 31, 1 } } }, + { { { 14, 0, 2 }, { 6, 31, 0 } } }, + { { { 14, 0, 3 }, { 8, 27, 0 } } }, + { { { 14, 0, 4 }, { 7, 30, 1 } } }, + { { { 15, 0, 3 }, { 7, 30, 0 } } }, + { { { 15, 0, 2 }, { 8, 28, 0 } } }, + { { { 15, 0, 1 }, { 7, 31, 1 } } }, + { { { 15, 0, 0 }, { 7, 31, 0 } } }, + { { { 15, 0, 1 }, { 7, 31, 1 } } }, + { { { 15, 0, 2 }, { 8, 30, 1 } } }, + { { { 15, 0, 3 }, { 8, 30, 0 } } }, + { { { 15, 0, 4 }, { 10, 27, 1 } } }, + { { { 16, 0, 4 }, { 10, 27, 0 } } }, + { { { 16, 0, 3 }, { 8, 31, 0 } } }, + { { { 16, 0, 2 }, { 9, 30, 1 } } }, + { { { 16, 0, 1 }, { 9, 30, 0 } } }, + { { { 16, 0, 0 }, { 12, 24, 0 } } }, + { { { 16, 0, 1 }, { 9, 31, 1 } } }, + { { { 16, 0, 2 }, { 9, 31, 0 } } }, + { { { 16, 0, 3 }, { 9, 31, 1 } } }, + { { { 16, 0, 4 }, { 10, 30, 1 } } }, + { { { 17, 0, 3 }, { 10, 30, 0 } } }, + { { { 17, 0, 2 }, { 10, 31, 1 } } }, + { { { 17, 0, 1 }, { 10, 31, 0 } } }, + { { { 17, 0, 0 }, { 12, 27, 0 } } }, + { { { 17, 0, 1 }, { 11, 30, 1 } } }, + { { { 17, 0, 2 }, { 11, 30, 0 } } }, + { { { 17, 0, 3 }, { 12, 28, 0 } } }, + { { { 17, 0, 4 }, { 11, 31, 1 } } }, + { { { 18, 0, 3 }, { 11, 31, 0 } } }, + { { { 18, 0, 2 }, { 11, 31, 1 } } }, + { { { 18, 0, 1 }, { 12, 30, 1 } } }, + { { { 18, 0, 0 }, { 12, 30, 0 } } }, + { { { 18, 0, 1 }, { 14, 27, 1 } } }, + { { { 18, 0, 2 }, { 14, 27, 0 } } }, + { { { 18, 0, 3 }, { 12, 31, 0 } } }, + { { { 18, 0, 4 }, { 13, 30, 1 } } }, + { { { 19, 0, 3 }, { 13, 30, 0 } } }, + { { { 19, 0, 2 }, { 16, 24, 0 } } }, + { { { 19, 0, 1 }, { 13, 31, 1 } } }, + { { { 19, 0, 0 }, { 13, 31, 0 } } }, + { { { 19, 0, 1 }, { 13, 31, 1 } } }, + { { { 19, 0, 2 }, { 14, 30, 1 } } }, + { { { 19, 0, 3 }, { 14, 30, 0 } } }, + { { { 19, 0, 4 }, { 14, 31, 1 } } }, + { { { 20, 0, 4 }, { 14, 31, 0 } } }, + { { { 20, 0, 3 }, { 16, 27, 0 } } }, + { { { 20, 0, 2 }, { 15, 30, 1 } } }, + { { { 20, 0, 1 }, { 15, 30, 0 } } }, + { { { 20, 0, 0 }, { 16, 28, 0 } } }, + { { { 20, 0, 1 }, { 15, 31, 1 } } }, + { { { 20, 0, 2 }, { 15, 31, 0 } } }, + { { { 20, 0, 3 }, { 15, 31, 1 } } }, + { { { 20, 0, 4 }, { 16, 30, 1 } } }, + { { { 21, 0, 3 }, { 16, 30, 0 } } }, + { { { 21, 0, 2 }, { 18, 27, 1 } } }, + { { { 21, 0, 1 }, { 18, 27, 0 } } }, + { { { 21, 0, 0 }, { 16, 31, 0 } } }, + { { { 21, 0, 1 }, { 17, 30, 1 } } }, + { { { 21, 0, 2 }, { 17, 30, 0 } } }, + { { { 21, 0, 3 }, { 20, 24, 0 } } }, + { { { 21, 0, 4 }, { 17, 31, 1 } } }, + { { { 22, 0, 3 }, { 17, 31, 0 } } }, + { { { 22, 0, 2 }, { 17, 31, 1 } } }, + { { { 22, 0, 1 }, { 18, 30, 1 } } }, + { { { 22, 0, 0 }, { 18, 30, 0 } } }, + { { { 22, 0, 1 }, { 18, 31, 1 } } }, + { { { 22, 0, 2 }, { 18, 31, 0 } } }, + { { { 22, 0, 3 }, { 20, 27, 0 } } }, + { { { 22, 0, 4 }, { 19, 30, 1 } } }, + { { { 23, 0, 3 }, { 19, 30, 0 } } }, + { { { 23, 0, 2 }, { 20, 28, 0 } } }, + { { { 23, 0, 1 }, { 19, 31, 1 } } }, + { { { 23, 0, 0 }, { 19, 31, 0 } } }, + { { { 23, 0, 1 }, { 19, 31, 1 } } }, + { { { 23, 0, 2 }, { 20, 30, 1 } } }, + { { { 23, 0, 3 }, { 20, 30, 0 } } }, + { { { 23, 0, 4 }, { 22, 27, 1 } } }, + { { { 24, 0, 4 }, { 22, 27, 0 } } }, + { { { 24, 0, 3 }, { 20, 31, 0 } } }, + { { { 24, 0, 2 }, { 21, 30, 1 } } }, + { { { 24, 0, 1 }, { 21, 30, 0 } } }, + { { { 24, 0, 0 }, { 24, 24, 0 } } }, + { { { 24, 0, 1 }, { 21, 31, 1 } } }, + { { { 24, 0, 2 }, { 21, 31, 0 } } }, + { { { 24, 0, 3 }, { 21, 31, 1 } } }, + { { { 24, 0, 4 }, { 22, 30, 1 } } }, + { { { 25, 0, 3 }, { 22, 30, 0 } } }, + { { { 25, 0, 2 }, { 22, 31, 1 } } }, + { { { 25, 0, 1 }, { 22, 31, 0 } } }, + { { { 25, 0, 0 }, { 24, 27, 0 } } }, + { { { 25, 0, 1 }, { 23, 30, 1 } } }, + { { { 25, 0, 2 }, { 23, 30, 0 } } }, + { { { 25, 0, 3 }, { 24, 28, 0 } } }, + { { { 25, 0, 4 }, { 23, 31, 1 } } }, + { { { 26, 0, 3 }, { 23, 31, 0 } } }, + { { { 26, 0, 2 }, { 23, 31, 1 } } }, + { { { 26, 0, 1 }, { 24, 30, 1 } } }, + { { { 26, 0, 0 }, { 24, 30, 0 } } }, + { { { 26, 0, 1 }, { 26, 27, 1 } } }, + { { { 26, 0, 2 }, { 26, 27, 0 } } }, + { { { 26, 0, 3 }, { 24, 31, 0 } } }, + { { { 26, 0, 4 }, { 25, 30, 1 } } }, + { { { 27, 0, 3 }, { 25, 30, 0 } } }, + { { { 27, 0, 2 }, { 28, 24, 0 } } }, + { { { 27, 0, 1 }, { 25, 31, 1 } } }, + { { { 27, 0, 0 }, { 25, 31, 0 } } }, + { { { 27, 0, 1 }, { 25, 31, 1 } } }, + { { { 27, 0, 2 }, { 26, 30, 1 } } }, + { { { 27, 0, 3 }, { 26, 30, 0 } } }, + { { { 27, 0, 4 }, { 26, 31, 1 } } }, + { { { 28, 0, 4 }, { 26, 31, 0 } } }, + { { { 28, 0, 3 }, { 28, 27, 0 } } }, + { { { 28, 0, 2 }, { 27, 30, 1 } } }, + { { { 28, 0, 1 }, { 27, 30, 0 } } }, + { { { 28, 0, 0 }, { 28, 28, 0 } } }, + { { { 28, 0, 1 }, { 27, 31, 1 } } }, + { { { 28, 0, 2 }, { 27, 31, 0 } } }, + { { { 28, 0, 3 }, { 27, 31, 1 } } }, + { { { 28, 0, 4 }, { 28, 30, 1 } } }, + { { { 29, 0, 3 }, { 28, 30, 0 } } }, + { { { 29, 0, 2 }, { 30, 27, 1 } } }, + { { { 29, 0, 1 }, { 30, 27, 0 } } }, + { { { 29, 0, 0 }, { 28, 31, 0 } } }, + { { { 29, 0, 1 }, { 29, 30, 1 } } }, + { { { 29, 0, 2 }, { 29, 30, 0 } } }, + { { { 29, 0, 3 }, { 29, 30, 1 } } }, + { { { 29, 0, 4 }, { 29, 31, 1 } } }, + { { { 30, 0, 3 }, { 29, 31, 0 } } }, + { { { 30, 0, 2 }, { 29, 31, 1 } } }, + { { { 30, 0, 1 }, { 30, 30, 1 } } }, + { { { 30, 0, 0 }, { 30, 30, 0 } } }, + { { { 30, 0, 1 }, { 30, 31, 1 } } }, + { { { 30, 0, 2 }, { 30, 31, 0 } } }, + { { { 30, 0, 3 }, { 30, 31, 1 } } }, + { { { 30, 0, 4 }, { 31, 30, 1 } } }, + { { { 31, 0, 3 }, { 31, 30, 0 } } }, + { { { 31, 0, 2 }, { 31, 30, 1 } } }, + { { { 31, 0, 1 }, { 31, 31, 1 } } }, + { { { 31, 0, 0 }, { 31, 31, 0 } } } +}; + +static SingleColourLookup const lookup_6_4[] = +{ + { { { 0, 0, 0 }, { 0, 0, 0 } } }, + { { { 0, 0, 1 }, { 0, 1, 0 } } }, + { { { 0, 0, 2 }, { 0, 2, 0 } } }, + { { { 1, 0, 1 }, { 0, 3, 1 } } }, + { { { 1, 0, 0 }, { 0, 3, 0 } } }, + { { { 1, 0, 1 }, { 0, 4, 0 } } }, + { { { 1, 0, 2 }, { 0, 5, 0 } } }, + { { { 2, 0, 1 }, { 0, 6, 1 } } }, + { { { 2, 0, 0 }, { 0, 6, 0 } } }, + { { { 2, 0, 1 }, { 0, 7, 0 } } }, + { { { 2, 0, 2 }, { 0, 8, 0 } } }, + { { { 3, 0, 1 }, { 0, 9, 1 } } }, + { { { 3, 0, 0 }, { 0, 9, 0 } } }, + { { { 3, 0, 1 }, { 0, 10, 0 } } }, + { { { 3, 0, 2 }, { 0, 11, 0 } } }, + { { { 4, 0, 1 }, { 0, 12, 1 } } }, + { { { 4, 0, 0 }, { 0, 12, 0 } } }, + { { { 4, 0, 1 }, { 0, 13, 0 } } }, + { { { 4, 0, 2 }, { 0, 14, 0 } } }, + { { { 5, 0, 1 }, { 0, 15, 1 } } }, + { { { 5, 0, 0 }, { 0, 15, 0 } } }, + { { { 5, 0, 1 }, { 0, 16, 0 } } }, + { { { 5, 0, 2 }, { 1, 15, 0 } } }, + { { { 6, 0, 1 }, { 0, 17, 0 } } }, + { { { 6, 0, 0 }, { 0, 18, 0 } } }, + { { { 6, 0, 1 }, { 0, 19, 0 } } }, + { { { 6, 0, 2 }, { 3, 14, 0 } } }, + { { { 7, 0, 1 }, { 0, 20, 0 } } }, + { { { 7, 0, 0 }, { 0, 21, 0 } } }, + { { { 7, 0, 1 }, { 0, 22, 0 } } }, + { { { 7, 0, 2 }, { 4, 15, 0 } } }, + { { { 8, 0, 1 }, { 0, 23, 0 } } }, + { { { 8, 0, 0 }, { 0, 24, 0 } } }, + { { { 8, 0, 1 }, { 0, 25, 0 } } }, + { { { 8, 0, 2 }, { 6, 14, 0 } } }, + { { { 9, 0, 1 }, { 0, 26, 0 } } }, + { { { 9, 0, 0 }, { 0, 27, 0 } } }, + { { { 9, 0, 1 }, { 0, 28, 0 } } }, + { { { 9, 0, 2 }, { 7, 15, 0 } } }, + { { { 10, 0, 1 }, { 0, 29, 0 } } }, + { { { 10, 0, 0 }, { 0, 30, 0 } } }, + { { { 10, 0, 1 }, { 0, 31, 0 } } }, + { { { 10, 0, 2 }, { 9, 14, 0 } } }, + { { { 11, 0, 1 }, { 0, 32, 0 } } }, + { { { 11, 0, 0 }, { 0, 33, 0 } } }, + { { { 11, 0, 1 }, { 2, 30, 0 } } }, + { { { 11, 0, 2 }, { 0, 34, 0 } } }, + { { { 12, 0, 1 }, { 0, 35, 0 } } }, + { { { 12, 0, 0 }, { 0, 36, 0 } } }, + { { { 12, 0, 1 }, { 3, 31, 0 } } }, + { { { 12, 0, 2 }, { 0, 37, 0 } } }, + { { { 13, 0, 1 }, { 0, 38, 0 } } }, + { { { 13, 0, 0 }, { 0, 39, 0 } } }, + { { { 13, 0, 1 }, { 5, 30, 0 } } }, + { { { 13, 0, 2 }, { 0, 40, 0 } } }, + { { { 14, 0, 1 }, { 0, 41, 0 } } }, + { { { 14, 0, 0 }, { 0, 42, 0 } } }, + { { { 14, 0, 1 }, { 6, 31, 0 } } }, + { { { 14, 0, 2 }, { 0, 43, 0 } } }, + { { { 15, 0, 1 }, { 0, 44, 0 } } }, + { { { 15, 0, 0 }, { 0, 45, 0 } } }, + { { { 15, 0, 1 }, { 8, 30, 0 } } }, + { { { 15, 0, 2 }, { 0, 46, 0 } } }, + { { { 16, 0, 2 }, { 0, 47, 0 } } }, + { { { 16, 0, 1 }, { 1, 46, 0 } } }, + { { { 16, 0, 0 }, { 0, 48, 0 } } }, + { { { 16, 0, 1 }, { 0, 49, 0 } } }, + { { { 16, 0, 2 }, { 0, 50, 0 } } }, + { { { 17, 0, 1 }, { 2, 47, 0 } } }, + { { { 17, 0, 0 }, { 0, 51, 0 } } }, + { { { 17, 0, 1 }, { 0, 52, 0 } } }, + { { { 17, 0, 2 }, { 0, 53, 0 } } }, + { { { 18, 0, 1 }, { 4, 46, 0 } } }, + { { { 18, 0, 0 }, { 0, 54, 0 } } }, + { { { 18, 0, 1 }, { 0, 55, 0 } } }, + { { { 18, 0, 2 }, { 0, 56, 0 } } }, + { { { 19, 0, 1 }, { 5, 47, 0 } } }, + { { { 19, 0, 0 }, { 0, 57, 0 } } }, + { { { 19, 0, 1 }, { 0, 58, 0 } } }, + { { { 19, 0, 2 }, { 0, 59, 0 } } }, + { { { 20, 0, 1 }, { 7, 46, 0 } } }, + { { { 20, 0, 0 }, { 0, 60, 0 } } }, + { { { 20, 0, 1 }, { 0, 61, 0 } } }, + { { { 20, 0, 2 }, { 0, 62, 0 } } }, + { { { 21, 0, 1 }, { 8, 47, 0 } } }, + { { { 21, 0, 0 }, { 0, 63, 0 } } }, + { { { 21, 0, 1 }, { 1, 62, 0 } } }, + { { { 21, 0, 2 }, { 1, 63, 0 } } }, + { { { 22, 0, 1 }, { 10, 46, 0 } } }, + { { { 22, 0, 0 }, { 2, 62, 0 } } }, + { { { 22, 0, 1 }, { 2, 63, 0 } } }, + { { { 22, 0, 2 }, { 3, 62, 0 } } }, + { { { 23, 0, 1 }, { 11, 47, 0 } } }, + { { { 23, 0, 0 }, { 3, 63, 0 } } }, + { { { 23, 0, 1 }, { 4, 62, 0 } } }, + { { { 23, 0, 2 }, { 4, 63, 0 } } }, + { { { 24, 0, 1 }, { 13, 46, 0 } } }, + { { { 24, 0, 0 }, { 5, 62, 0 } } }, + { { { 24, 0, 1 }, { 5, 63, 0 } } }, + { { { 24, 0, 2 }, { 6, 62, 0 } } }, + { { { 25, 0, 1 }, { 14, 47, 0 } } }, + { { { 25, 0, 0 }, { 6, 63, 0 } } }, + { { { 25, 0, 1 }, { 7, 62, 0 } } }, + { { { 25, 0, 2 }, { 7, 63, 0 } } }, + { { { 26, 0, 1 }, { 16, 45, 0 } } }, + { { { 26, 0, 0 }, { 8, 62, 0 } } }, + { { { 26, 0, 1 }, { 8, 63, 0 } } }, + { { { 26, 0, 2 }, { 9, 62, 0 } } }, + { { { 27, 0, 1 }, { 16, 48, 0 } } }, + { { { 27, 0, 0 }, { 9, 63, 0 } } }, + { { { 27, 0, 1 }, { 10, 62, 0 } } }, + { { { 27, 0, 2 }, { 10, 63, 0 } } }, + { { { 28, 0, 1 }, { 16, 51, 0 } } }, + { { { 28, 0, 0 }, { 11, 62, 0 } } }, + { { { 28, 0, 1 }, { 11, 63, 0 } } }, + { { { 28, 0, 2 }, { 12, 62, 0 } } }, + { { { 29, 0, 1 }, { 16, 54, 0 } } }, + { { { 29, 0, 0 }, { 12, 63, 0 } } }, + { { { 29, 0, 1 }, { 13, 62, 0 } } }, + { { { 29, 0, 2 }, { 13, 63, 0 } } }, + { { { 30, 0, 1 }, { 16, 57, 0 } } }, + { { { 30, 0, 0 }, { 14, 62, 0 } } }, + { { { 30, 0, 1 }, { 14, 63, 0 } } }, + { { { 30, 0, 2 }, { 15, 62, 0 } } }, + { { { 31, 0, 1 }, { 16, 60, 0 } } }, + { { { 31, 0, 0 }, { 15, 63, 0 } } }, + { { { 31, 0, 1 }, { 24, 46, 0 } } }, + { { { 31, 0, 2 }, { 16, 62, 0 } } }, + { { { 32, 0, 2 }, { 16, 63, 0 } } }, + { { { 32, 0, 1 }, { 17, 62, 0 } } }, + { { { 32, 0, 0 }, { 25, 47, 0 } } }, + { { { 32, 0, 1 }, { 17, 63, 0 } } }, + { { { 32, 0, 2 }, { 18, 62, 0 } } }, + { { { 33, 0, 1 }, { 18, 63, 0 } } }, + { { { 33, 0, 0 }, { 27, 46, 0 } } }, + { { { 33, 0, 1 }, { 19, 62, 0 } } }, + { { { 33, 0, 2 }, { 19, 63, 0 } } }, + { { { 34, 0, 1 }, { 20, 62, 0 } } }, + { { { 34, 0, 0 }, { 28, 47, 0 } } }, + { { { 34, 0, 1 }, { 20, 63, 0 } } }, + { { { 34, 0, 2 }, { 21, 62, 0 } } }, + { { { 35, 0, 1 }, { 21, 63, 0 } } }, + { { { 35, 0, 0 }, { 30, 46, 0 } } }, + { { { 35, 0, 1 }, { 22, 62, 0 } } }, + { { { 35, 0, 2 }, { 22, 63, 0 } } }, + { { { 36, 0, 1 }, { 23, 62, 0 } } }, + { { { 36, 0, 0 }, { 31, 47, 0 } } }, + { { { 36, 0, 1 }, { 23, 63, 0 } } }, + { { { 36, 0, 2 }, { 24, 62, 0 } } }, + { { { 37, 0, 1 }, { 24, 63, 0 } } }, + { { { 37, 0, 0 }, { 32, 47, 0 } } }, + { { { 37, 0, 1 }, { 25, 62, 0 } } }, + { { { 37, 0, 2 }, { 25, 63, 0 } } }, + { { { 38, 0, 1 }, { 26, 62, 0 } } }, + { { { 38, 0, 0 }, { 32, 50, 0 } } }, + { { { 38, 0, 1 }, { 26, 63, 0 } } }, + { { { 38, 0, 2 }, { 27, 62, 0 } } }, + { { { 39, 0, 1 }, { 27, 63, 0 } } }, + { { { 39, 0, 0 }, { 32, 53, 0 } } }, + { { { 39, 0, 1 }, { 28, 62, 0 } } }, + { { { 39, 0, 2 }, { 28, 63, 0 } } }, + { { { 40, 0, 1 }, { 29, 62, 0 } } }, + { { { 40, 0, 0 }, { 32, 56, 0 } } }, + { { { 40, 0, 1 }, { 29, 63, 0 } } }, + { { { 40, 0, 2 }, { 30, 62, 0 } } }, + { { { 41, 0, 1 }, { 30, 63, 0 } } }, + { { { 41, 0, 0 }, { 32, 59, 0 } } }, + { { { 41, 0, 1 }, { 31, 62, 0 } } }, + { { { 41, 0, 2 }, { 31, 63, 0 } } }, + { { { 42, 0, 1 }, { 32, 61, 0 } } }, + { { { 42, 0, 0 }, { 32, 62, 0 } } }, + { { { 42, 0, 1 }, { 32, 63, 0 } } }, + { { { 42, 0, 2 }, { 41, 46, 0 } } }, + { { { 43, 0, 1 }, { 33, 62, 0 } } }, + { { { 43, 0, 0 }, { 33, 63, 0 } } }, + { { { 43, 0, 1 }, { 34, 62, 0 } } }, + { { { 43, 0, 2 }, { 42, 47, 0 } } }, + { { { 44, 0, 1 }, { 34, 63, 0 } } }, + { { { 44, 0, 0 }, { 35, 62, 0 } } }, + { { { 44, 0, 1 }, { 35, 63, 0 } } }, + { { { 44, 0, 2 }, { 44, 46, 0 } } }, + { { { 45, 0, 1 }, { 36, 62, 0 } } }, + { { { 45, 0, 0 }, { 36, 63, 0 } } }, + { { { 45, 0, 1 }, { 37, 62, 0 } } }, + { { { 45, 0, 2 }, { 45, 47, 0 } } }, + { { { 46, 0, 1 }, { 37, 63, 0 } } }, + { { { 46, 0, 0 }, { 38, 62, 0 } } }, + { { { 46, 0, 1 }, { 38, 63, 0 } } }, + { { { 46, 0, 2 }, { 47, 46, 0 } } }, + { { { 47, 0, 1 }, { 39, 62, 0 } } }, + { { { 47, 0, 0 }, { 39, 63, 0 } } }, + { { { 47, 0, 1 }, { 40, 62, 0 } } }, + { { { 47, 0, 2 }, { 48, 46, 0 } } }, + { { { 48, 0, 2 }, { 40, 63, 0 } } }, + { { { 48, 0, 1 }, { 41, 62, 0 } } }, + { { { 48, 0, 0 }, { 41, 63, 0 } } }, + { { { 48, 0, 1 }, { 48, 49, 0 } } }, + { { { 48, 0, 2 }, { 42, 62, 0 } } }, + { { { 49, 0, 1 }, { 42, 63, 0 } } }, + { { { 49, 0, 0 }, { 43, 62, 0 } } }, + { { { 49, 0, 1 }, { 48, 52, 0 } } }, + { { { 49, 0, 2 }, { 43, 63, 0 } } }, + { { { 50, 0, 1 }, { 44, 62, 0 } } }, + { { { 50, 0, 0 }, { 44, 63, 0 } } }, + { { { 50, 0, 1 }, { 48, 55, 0 } } }, + { { { 50, 0, 2 }, { 45, 62, 0 } } }, + { { { 51, 0, 1 }, { 45, 63, 0 } } }, + { { { 51, 0, 0 }, { 46, 62, 0 } } }, + { { { 51, 0, 1 }, { 48, 58, 0 } } }, + { { { 51, 0, 2 }, { 46, 63, 0 } } }, + { { { 52, 0, 1 }, { 47, 62, 0 } } }, + { { { 52, 0, 0 }, { 47, 63, 0 } } }, + { { { 52, 0, 1 }, { 48, 61, 0 } } }, + { { { 52, 0, 2 }, { 48, 62, 0 } } }, + { { { 53, 0, 1 }, { 56, 47, 0 } } }, + { { { 53, 0, 0 }, { 48, 63, 0 } } }, + { { { 53, 0, 1 }, { 49, 62, 0 } } }, + { { { 53, 0, 2 }, { 49, 63, 0 } } }, + { { { 54, 0, 1 }, { 58, 46, 0 } } }, + { { { 54, 0, 0 }, { 50, 62, 0 } } }, + { { { 54, 0, 1 }, { 50, 63, 0 } } }, + { { { 54, 0, 2 }, { 51, 62, 0 } } }, + { { { 55, 0, 1 }, { 59, 47, 0 } } }, + { { { 55, 0, 0 }, { 51, 63, 0 } } }, + { { { 55, 0, 1 }, { 52, 62, 0 } } }, + { { { 55, 0, 2 }, { 52, 63, 0 } } }, + { { { 56, 0, 1 }, { 61, 46, 0 } } }, + { { { 56, 0, 0 }, { 53, 62, 0 } } }, + { { { 56, 0, 1 }, { 53, 63, 0 } } }, + { { { 56, 0, 2 }, { 54, 62, 0 } } }, + { { { 57, 0, 1 }, { 62, 47, 0 } } }, + { { { 57, 0, 0 }, { 54, 63, 0 } } }, + { { { 57, 0, 1 }, { 55, 62, 0 } } }, + { { { 57, 0, 2 }, { 55, 63, 0 } } }, + { { { 58, 0, 1 }, { 56, 62, 1 } } }, + { { { 58, 0, 0 }, { 56, 62, 0 } } }, + { { { 58, 0, 1 }, { 56, 63, 0 } } }, + { { { 58, 0, 2 }, { 57, 62, 0 } } }, + { { { 59, 0, 1 }, { 57, 63, 1 } } }, + { { { 59, 0, 0 }, { 57, 63, 0 } } }, + { { { 59, 0, 1 }, { 58, 62, 0 } } }, + { { { 59, 0, 2 }, { 58, 63, 0 } } }, + { { { 60, 0, 1 }, { 59, 62, 1 } } }, + { { { 60, 0, 0 }, { 59, 62, 0 } } }, + { { { 60, 0, 1 }, { 59, 63, 0 } } }, + { { { 60, 0, 2 }, { 60, 62, 0 } } }, + { { { 61, 0, 1 }, { 60, 63, 1 } } }, + { { { 61, 0, 0 }, { 60, 63, 0 } } }, + { { { 61, 0, 1 }, { 61, 62, 0 } } }, + { { { 61, 0, 2 }, { 61, 63, 0 } } }, + { { { 62, 0, 1 }, { 62, 62, 1 } } }, + { { { 62, 0, 0 }, { 62, 62, 0 } } }, + { { { 62, 0, 1 }, { 62, 63, 0 } } }, + { { { 62, 0, 2 }, { 63, 62, 0 } } }, + { { { 63, 0, 1 }, { 63, 63, 1 } } }, + { { { 63, 0, 0 }, { 63, 63, 0 } } } +}; diff --git a/thirdparty/squish/squish.cpp b/thirdparty/squish/squish.cpp new file mode 100644 index 0000000000..d3cbabbafd --- /dev/null +++ b/thirdparty/squish/squish.cpp @@ -0,0 +1,395 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#include <string.h> +#include "squish.h" +#include "colourset.h" +#include "maths.h" +#include "rangefit.h" +#include "clusterfit.h" +#include "colourblock.h" +#include "alpha.h" +#include "singlecolourfit.h" + +namespace squish { + +static int FixFlags( int flags ) +{ + // grab the flag bits + int method = flags & ( kDxt1 | kDxt3 | kDxt5 | kBc4 | kBc5 ); + int fit = flags & ( kColourIterativeClusterFit | kColourClusterFit | kColourRangeFit ); + int extra = flags & kWeightColourByAlpha; + + // set defaults + if ( method != kDxt3 + && method != kDxt5 + && method != kBc4 + && method != kBc5 ) + { + method = kDxt1; + } + if( fit != kColourRangeFit && fit != kColourIterativeClusterFit ) + fit = kColourClusterFit; + + // done + return method | fit | extra; +} + +void CompressMasked( u8 const* rgba, int mask, void* block, int flags, float* metric ) +{ + // fix any bad flags + flags = FixFlags( flags ); + + if ( ( flags & ( kBc4 | kBc5 ) ) != 0 ) + { + u8 alpha[16*4]; + for( int i = 0; i < 16; ++i ) + { + alpha[i*4 + 3] = rgba[i*4 + 0]; // copy R to A + } + + u8* rBlock = reinterpret_cast< u8* >( block ); + CompressAlphaDxt5( alpha, mask, rBlock ); + + if ( ( flags & ( kBc5 ) ) != 0 ) + { + for( int i = 0; i < 16; ++i ) + { + alpha[i*4 + 3] = rgba[i*4 + 1]; // copy G to A + } + + u8* gBlock = reinterpret_cast< u8* >( block ) + 8; + CompressAlphaDxt5( alpha, mask, gBlock ); + } + + return; + } + + // get the block locations + void* colourBlock = block; + void* alphaBlock = block; + if( ( flags & ( kDxt3 | kDxt5 ) ) != 0 ) + colourBlock = reinterpret_cast< u8* >( block ) + 8; + + // create the minimal point set + ColourSet colours( rgba, mask, flags ); + + // check the compression type and compress colour + if( colours.GetCount() == 1 ) + { + // always do a single colour fit + SingleColourFit fit( &colours, flags ); + fit.Compress( colourBlock ); + } + else if( ( flags & kColourRangeFit ) != 0 || colours.GetCount() == 0 ) + { + // do a range fit + RangeFit fit( &colours, flags, metric ); + fit.Compress( colourBlock ); + } + else + { + // default to a cluster fit (could be iterative or not) + ClusterFit fit( &colours, flags, metric ); + fit.Compress( colourBlock ); + } + + // compress alpha separately if necessary + if( ( flags & kDxt3 ) != 0 ) + CompressAlphaDxt3( rgba, mask, alphaBlock ); + else if( ( flags & kDxt5 ) != 0 ) + CompressAlphaDxt5( rgba, mask, alphaBlock ); +} + +void Decompress( u8* rgba, void const* block, int flags ) +{ + // fix any bad flags + flags = FixFlags( flags ); + + // get the block locations + void const* colourBlock = block; + void const* alphaBlock = block; + if( ( flags & ( kDxt3 | kDxt5 ) ) != 0 ) + colourBlock = reinterpret_cast< u8 const* >( block ) + 8; + + // decompress colour + DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); + + // decompress alpha separately if necessary + if( ( flags & kDxt3 ) != 0 ) + DecompressAlphaDxt3( rgba, alphaBlock ); + else if( ( flags & kDxt5 ) != 0 ) + DecompressAlphaDxt5( rgba, alphaBlock ); +} + +int GetStorageRequirements( int width, int height, int flags ) +{ + // fix any bad flags + flags = FixFlags( flags ); + + // compute the storage requirements + int blockcount = ( ( width + 3 )/4 ) * ( ( height + 3 )/4 ); + int blocksize = ( ( flags & ( kDxt1 | kBc4 ) ) != 0 ) ? 8 : 16; + return blockcount*blocksize; +} + +void CopyRGBA( u8 const* source, u8* dest, int flags ) +{ + if (flags & kSourceBGRA) + { + // convert from bgra to rgba + dest[0] = source[2]; + dest[1] = source[1]; + dest[2] = source[0]; + dest[3] = source[3]; + } + else + { + for( int i = 0; i < 4; ++i ) + *dest++ = *source++; + } +} + +void CompressImage( u8 const* rgba, int width, int height, int pitch, void* blocks, int flags, float* metric ) +{ + // fix any bad flags + flags = FixFlags( flags ); + + // initialise the block output + u8* targetBlock = reinterpret_cast< u8* >( blocks ); + int bytesPerBlock = ( ( flags & ( kDxt1 | kBc4 ) ) != 0 ) ? 8 : 16; + + // loop over blocks + for( int y = 0; y < height; y += 4 ) + { + for( int x = 0; x < width; x += 4 ) + { + // build the 4x4 block of pixels + u8 sourceRgba[16*4]; + u8* targetPixel = sourceRgba; + int mask = 0; + for( int py = 0; py < 4; ++py ) + { + for( int px = 0; px < 4; ++px ) + { + // get the source pixel in the image + int sx = x + px; + int sy = y + py; + + // enable if we're in the image + if( sx < width && sy < height ) + { + // copy the rgba value + u8 const* sourcePixel = rgba + pitch*sy + 4*sx; + CopyRGBA(sourcePixel, targetPixel, flags); + // enable this pixel + mask |= ( 1 << ( 4*py + px ) ); + } + + // advance to the next pixel + targetPixel += 4; + } + } + + // compress it into the output + CompressMasked( sourceRgba, mask, targetBlock, flags, metric ); + + // advance + targetBlock += bytesPerBlock; + } + } +} + +void CompressImage( u8 const* rgba, int width, int height, void* blocks, int flags, float* metric ) +{ + CompressImage(rgba, width, height, width*4, blocks, flags, metric); +} + +void DecompressImage( u8* rgba, int width, int height, int pitch, void const* blocks, int flags ) +{ + // fix any bad flags + flags = FixFlags( flags ); + + // initialise the block input + u8 const* sourceBlock = reinterpret_cast< u8 const* >( blocks ); + int bytesPerBlock = ( ( flags & ( kDxt1 | kBc4 ) ) != 0 ) ? 8 : 16; + + // loop over blocks + for( int y = 0; y < height; y += 4 ) + { + for( int x = 0; x < width; x += 4 ) + { + // decompress the block + u8 targetRgba[4*16]; + Decompress( targetRgba, sourceBlock, flags ); + + // write the decompressed pixels to the correct image locations + u8 const* sourcePixel = targetRgba; + for( int py = 0; py < 4; ++py ) + { + for( int px = 0; px < 4; ++px ) + { + // get the target location + int sx = x + px; + int sy = y + py; + + // write if we're in the image + if( sx < width && sy < height ) + { + // copy the rgba value + u8* targetPixel = rgba + pitch*sy + 4*sx; + CopyRGBA(sourcePixel, targetPixel, flags); + } + + // advance to the next pixel + sourcePixel += 4; + } + } + + // advance + sourceBlock += bytesPerBlock; + } + } +} + +void DecompressImage( u8* rgba, int width, int height, void const* blocks, int flags ) +{ + DecompressImage( rgba, width, height, width*4, blocks, flags ); +} + +static double ErrorSq(double x, double y) +{ + return (x - y) * (x - y); +} + +static void ComputeBlockWMSE(u8 const *original, u8 const *compressed, unsigned int w, unsigned int h, double &cmse, double &amse) +{ + // Computes the MSE for the block and weights it by the variance of the original block. + // If the variance of the original block is less than 4 (i.e. a standard deviation of 1 per channel) + // then the block is close to being a single colour. Quantisation errors in single colour blocks + // are easier to see than similar errors in blocks that contain more colours, particularly when there + // are many such blocks in a large area (eg a blue sky background) as they cause banding. Given that + // banding is easier to see than small errors in "complex" blocks, we weight the errors by a factor + // of 5. This implies that images with large, single colour areas will have a higher potential WMSE + // than images with lots of detail. + + cmse = amse = 0; + unsigned int sum_p[4]; // per channel sum of pixels + unsigned int sum_p2[4]; // per channel sum of pixels squared + memset(sum_p, 0, sizeof(sum_p)); + memset(sum_p2, 0, sizeof(sum_p2)); + for( unsigned int py = 0; py < 4; ++py ) + { + for( unsigned int px = 0; px < 4; ++px ) + { + if( px < w && py < h ) + { + double pixelCMSE = 0; + for( int i = 0; i < 3; ++i ) + { + pixelCMSE += ErrorSq(original[i], compressed[i]); + sum_p[i] += original[i]; + sum_p2[i] += (unsigned int)original[i]*original[i]; + } + if( original[3] == 0 && compressed[3] == 0 ) + pixelCMSE = 0; // transparent in both, so colour is inconsequential + amse += ErrorSq(original[3], compressed[3]); + cmse += pixelCMSE; + sum_p[3] += original[3]; + sum_p2[3] += (unsigned int)original[3]*original[3]; + } + original += 4; + compressed += 4; + } + } + unsigned int variance = 0; + for( int i = 0; i < 4; ++i ) + variance += w*h*sum_p2[i] - sum_p[i]*sum_p[i]; + if( variance < 4 * w * w * h * h ) + { + amse *= 5; + cmse *= 5; + } +} + +void ComputeMSE( u8 const *rgba, int width, int height, int pitch, u8 const *dxt, int flags, double &colourMSE, double &alphaMSE ) +{ + // fix any bad flags + flags = FixFlags( flags ); + colourMSE = alphaMSE = 0; + + // initialise the block input + squish::u8 const* sourceBlock = dxt; + int bytesPerBlock = ( ( flags & squish::kDxt1 ) != 0 ) ? 8 : 16; + + // loop over blocks + for( int y = 0; y < height; y += 4 ) + { + for( int x = 0; x < width; x += 4 ) + { + // decompress the block + u8 targetRgba[4*16]; + Decompress( targetRgba, sourceBlock, flags ); + u8 const* sourcePixel = targetRgba; + + // copy across to a similar pixel block + u8 originalRgba[4*16]; + u8* originalPixel = originalRgba; + + for( int py = 0; py < 4; ++py ) + { + for( int px = 0; px < 4; ++px ) + { + int sx = x + px; + int sy = y + py; + if( sx < width && sy < height ) + { + u8 const* targetPixel = rgba + pitch*sy + 4*sx; + CopyRGBA(targetPixel, originalPixel, flags); + } + sourcePixel += 4; + originalPixel += 4; + } + } + + // compute the weighted MSE of the block + double blockCMSE, blockAMSE; + ComputeBlockWMSE(originalRgba, targetRgba, std::min(4, width - x), std::min(4, height - y), blockCMSE, blockAMSE); + colourMSE += blockCMSE; + alphaMSE += blockAMSE; + // advance + sourceBlock += bytesPerBlock; + } + } + colourMSE /= (width * height * 3); + alphaMSE /= (width * height); +} + +void ComputeMSE( u8 const *rgba, int width, int height, u8 const *dxt, int flags, double &colourMSE, double &alphaMSE ) +{ + ComputeMSE(rgba, width, height, width*4, dxt, flags, colourMSE, alphaMSE); +} + +} // namespace squish diff --git a/thirdparty/squish/squish.h b/thirdparty/squish/squish.h new file mode 100644 index 0000000000..7c46e37ff1 --- /dev/null +++ b/thirdparty/squish/squish.h @@ -0,0 +1,300 @@ +/* ----------------------------------------------------------------------------- + + Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + -------------------------------------------------------------------------- */ + +#ifndef SQUISH_H +#define SQUISH_H + +//! All squish API functions live in this namespace. +namespace squish { + +// ----------------------------------------------------------------------------- + +//! Typedef a quantity that is a single unsigned byte. +typedef unsigned char u8; + +// ----------------------------------------------------------------------------- + +enum +{ + //! Use DXT1 compression. + kDxt1 = ( 1 << 0 ), + + //! Use DXT3 compression. + kDxt3 = ( 1 << 1 ), + + //! Use DXT5 compression. + kDxt5 = ( 1 << 2 ), + + //! Use BC4 compression. + kBc4 = ( 1 << 3 ), + + //! Use BC5 compression. + kBc5 = ( 1 << 4 ), + + //! Use a slow but high quality colour compressor (the default). + kColourClusterFit = ( 1 << 5 ), + + //! Use a fast but low quality colour compressor. + kColourRangeFit = ( 1 << 6 ), + + //! Weight the colour by alpha during cluster fit (disabled by default). + kWeightColourByAlpha = ( 1 << 7 ), + + //! Use a very slow but very high quality colour compressor. + kColourIterativeClusterFit = ( 1 << 8 ), + + //! Source is BGRA rather than RGBA + kSourceBGRA = ( 1 << 9 ) +}; + +// ----------------------------------------------------------------------------- + +/*! @brief Compresses a 4x4 block of pixels. + + @param rgba The rgba values of the 16 source pixels. + @param mask The valid pixel mask. + @param block Storage for the compressed DXT block. + @param flags Compression flags. + @param metric An optional perceptual metric. + + The source pixels should be presented as a contiguous array of 16 rgba + values, with each component as 1 byte each. In memory this should be: + + { r1, g1, b1, a1, .... , r16, g16, b16, a16 } + + The mask parameter enables only certain pixels within the block. The lowest + bit enables the first pixel and so on up to the 16th bit. Bits beyond the + 16th bit are ignored. Pixels that are not enabled are allowed to take + arbitrary colours in the output block. An example of how this can be used + is in the CompressImage function to disable pixels outside the bounds of + the image when the width or height is not divisible by 4. + + The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression, + however, DXT1 will be used by default if none is specified. When using DXT1 + compression, 8 bytes of storage are required for the compressed DXT block. + DXT3 and DXT5 compression require 16 bytes of storage per block. + + The flags parameter can also specify a preferred colour compressor to use + when fitting the RGB components of the data. Possible colour compressors + are: kColourClusterFit (the default), kColourRangeFit (very fast, low + quality) or kColourIterativeClusterFit (slowest, best quality). + + When using kColourClusterFit or kColourIterativeClusterFit, an additional + flag can be specified to weight the importance of each pixel by its alpha + value. For images that are rendered using alpha blending, this can + significantly increase the perceived quality. + + The metric parameter can be used to weight the relative importance of each + colour channel, or pass NULL to use the default uniform weight of + { 1.0f, 1.0f, 1.0f }. This replaces the previous flag-based control that + allowed either uniform or "perceptual" weights with the fixed values + { 0.2126f, 0.7152f, 0.0722f }. If non-NULL, the metric should point to a + contiguous array of 3 floats. +*/ +void CompressMasked( u8 const* rgba, int mask, void* block, int flags, float* metric = 0 ); + +// ----------------------------------------------------------------------------- + +/*! @brief Compresses a 4x4 block of pixels. + + @param rgba The rgba values of the 16 source pixels. + @param block Storage for the compressed DXT block. + @param flags Compression flags. + @param metric An optional perceptual metric. + + The source pixels should be presented as a contiguous array of 16 rgba + values, with each component as 1 byte each. In memory this should be: + + { r1, g1, b1, a1, .... , r16, g16, b16, a16 } + + The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression, + however, DXT1 will be used by default if none is specified. When using DXT1 + compression, 8 bytes of storage are required for the compressed DXT block. + DXT3 and DXT5 compression require 16 bytes of storage per block. + + The flags parameter can also specify a preferred colour compressor to use + when fitting the RGB components of the data. Possible colour compressors + are: kColourClusterFit (the default), kColourRangeFit (very fast, low + quality) or kColourIterativeClusterFit (slowest, best quality). + + When using kColourClusterFit or kColourIterativeClusterFit, an additional + flag can be specified to weight the importance of each pixel by its alpha + value. For images that are rendered using alpha blending, this can + significantly increase the perceived quality. + + The metric parameter can be used to weight the relative importance of each + colour channel, or pass NULL to use the default uniform weight of + { 1.0f, 1.0f, 1.0f }. This replaces the previous flag-based control that + allowed either uniform or "perceptual" weights with the fixed values + { 0.2126f, 0.7152f, 0.0722f }. If non-NULL, the metric should point to a + contiguous array of 3 floats. + + This method is an inline that calls CompressMasked with a mask of 0xffff, + provided for compatibility with older versions of squish. +*/ +inline void Compress( u8 const* rgba, void* block, int flags, float* metric = 0 ) +{ + CompressMasked( rgba, 0xffff, block, flags, metric ); +} + +// ----------------------------------------------------------------------------- + +/*! @brief Decompresses a 4x4 block of pixels. + + @param rgba Storage for the 16 decompressed pixels. + @param block The compressed DXT block. + @param flags Compression flags. + + The decompressed pixels will be written as a contiguous array of 16 rgba + values, with each component as 1 byte each. In memory this is: + + { r1, g1, b1, a1, .... , r16, g16, b16, a16 } + + The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression, + however, DXT1 will be used by default if none is specified. All other flags + are ignored. +*/ +void Decompress( u8* rgba, void const* block, int flags ); + +// ----------------------------------------------------------------------------- + +/*! @brief Computes the amount of compressed storage required. + + @param width The width of the image. + @param height The height of the image. + @param flags Compression flags. + + The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression, + however, DXT1 will be used by default if none is specified. All other flags + are ignored. + + Most DXT images will be a multiple of 4 in each dimension, but this + function supports arbitrary size images by allowing the outer blocks to + be only partially used. +*/ +int GetStorageRequirements( int width, int height, int flags ); + +// ----------------------------------------------------------------------------- + +/*! @brief Compresses an image in memory. + + @param rgba The pixels of the source. + @param width The width of the source image. + @param height The height of the source image. + @param pitch The pitch of the source image. + @param blocks Storage for the compressed output. + @param flags Compression flags. + @param metric An optional perceptual metric. + + The source pixels should be presented as a contiguous array of width*height + rgba values, with each component as 1 byte each. In memory this should be: + + { r1, g1, b1, a1, .... , rn, gn, bn, an } for n = width*height + + The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression, + however, DXT1 will be used by default if none is specified. When using DXT1 + compression, 8 bytes of storage are required for each compressed DXT block. + DXT3 and DXT5 compression require 16 bytes of storage per block. + + The flags parameter can also specify a preferred colour compressor to use + when fitting the RGB components of the data. Possible colour compressors + are: kColourClusterFit (the default), kColourRangeFit (very fast, low + quality) or kColourIterativeClusterFit (slowest, best quality). + + When using kColourClusterFit or kColourIterativeClusterFit, an additional + flag can be specified to weight the importance of each pixel by its alpha + value. For images that are rendered using alpha blending, this can + significantly increase the perceived quality. + + The metric parameter can be used to weight the relative importance of each + colour channel, or pass NULL to use the default uniform weight of + { 1.0f, 1.0f, 1.0f }. This replaces the previous flag-based control that + allowed either uniform or "perceptual" weights with the fixed values + { 0.2126f, 0.7152f, 0.0722f }. If non-NULL, the metric should point to a + contiguous array of 3 floats. + + Internally this function calls squish::CompressMasked for each block, which + allows for pixels outside the image to take arbitrary values. The function + squish::GetStorageRequirements can be called to compute the amount of memory + to allocate for the compressed output. +*/ +void CompressImage( u8 const* rgba, int width, int height, int pitch, void* blocks, int flags, float* metric = 0 ); +void CompressImage( u8 const* rgba, int width, int height, void* blocks, int flags, float* metric = 0 ); + +// ----------------------------------------------------------------------------- + +/*! @brief Decompresses an image in memory. + + @param rgba Storage for the decompressed pixels. + @param width The width of the source image. + @param height The height of the source image. + @param pitch The pitch of the decompressed pixels. + @param blocks The compressed DXT blocks. + @param flags Compression flags. + + The decompressed pixels will be written as a contiguous array of width*height + 16 rgba values, with each component as 1 byte each. In memory this is: + + { r1, g1, b1, a1, .... , rn, gn, bn, an } for n = width*height + + The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression, + however, DXT1 will be used by default if none is specified. All other flags + are ignored. + + Internally this function calls squish::Decompress for each block. +*/ +void DecompressImage( u8* rgba, int width, int height, int pitch, void const* blocks, int flags ); +void DecompressImage( u8* rgba, int width, int height, void const* blocks, int flags ); + +// ----------------------------------------------------------------------------- + +/*! @brief Computes MSE of an compressed image in memory. + + @param rgba The original image pixels. + @param width The width of the source image. + @param height The height of the source image. + @param pitch The pitch of the source image. + @param dxt The compressed dxt blocks + @param flags Compression flags. + @param colourMSE The MSE of the colour values. + @param alphaMSE The MSE of the alpha values. + + The colour MSE and alpha MSE are computed across all pixels. The colour MSE is + averaged across all rgb values (i.e. colourMSE = sum sum_k ||dxt.k - rgba.k||/3) + + The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression, + however, DXT1 will be used by default if none is specified. All other flags + are ignored. + + Internally this function calls squish::Decompress for each block. +*/ +void ComputeMSE(u8 const *rgba, int width, int height, int pitch, u8 const *dxt, int flags, double &colourMSE, double &alphaMSE); +void ComputeMSE(u8 const *rgba, int width, int height, u8 const *dxt, int flags, double &colourMSE, double &alphaMSE); + +// ----------------------------------------------------------------------------- + +} // namespace squish + +#endif // ndef SQUISH_H diff --git a/drivers/builtin_zlib/zlib/adler32.c b/thirdparty/zlib/adler32.c index a868f073d8..a868f073d8 100644 --- a/drivers/builtin_zlib/zlib/adler32.c +++ b/thirdparty/zlib/adler32.c diff --git a/drivers/builtin_zlib/zlib/compress.c b/thirdparty/zlib/compress.c index 6e9762676a..6e9762676a 100644 --- a/drivers/builtin_zlib/zlib/compress.c +++ b/thirdparty/zlib/compress.c diff --git a/drivers/builtin_zlib/zlib/crc32.c b/thirdparty/zlib/crc32.c index 979a7190a3..979a7190a3 100644 --- a/drivers/builtin_zlib/zlib/crc32.c +++ b/thirdparty/zlib/crc32.c diff --git a/drivers/builtin_zlib/zlib/crc32.h b/thirdparty/zlib/crc32.h index 9e0c778102..9e0c778102 100644 --- a/drivers/builtin_zlib/zlib/crc32.h +++ b/thirdparty/zlib/crc32.h diff --git a/drivers/builtin_zlib/zlib/deflate.c b/thirdparty/zlib/deflate.c index 696957705b..696957705b 100644 --- a/drivers/builtin_zlib/zlib/deflate.c +++ b/thirdparty/zlib/deflate.c diff --git a/drivers/builtin_zlib/zlib/deflate.h b/thirdparty/zlib/deflate.h index ce0299edd1..ce0299edd1 100644 --- a/drivers/builtin_zlib/zlib/deflate.h +++ b/thirdparty/zlib/deflate.h diff --git a/drivers/builtin_zlib/zlib/infback.c b/thirdparty/zlib/infback.c index f3833c2e43..f3833c2e43 100644 --- a/drivers/builtin_zlib/zlib/infback.c +++ b/thirdparty/zlib/infback.c diff --git a/drivers/builtin_zlib/zlib/inffast.c b/thirdparty/zlib/inffast.c index bda59ceb6a..bda59ceb6a 100644 --- a/drivers/builtin_zlib/zlib/inffast.c +++ b/thirdparty/zlib/inffast.c diff --git a/drivers/builtin_zlib/zlib/inffast.h b/thirdparty/zlib/inffast.h index e5c1aa4ca8..e5c1aa4ca8 100644 --- a/drivers/builtin_zlib/zlib/inffast.h +++ b/thirdparty/zlib/inffast.h diff --git a/drivers/builtin_zlib/zlib/inffixed.h b/thirdparty/zlib/inffixed.h index d628327769..d628327769 100644 --- a/drivers/builtin_zlib/zlib/inffixed.h +++ b/thirdparty/zlib/inffixed.h diff --git a/drivers/builtin_zlib/zlib/inflate.c b/thirdparty/zlib/inflate.c index 870f89bb4d..870f89bb4d 100644 --- a/drivers/builtin_zlib/zlib/inflate.c +++ b/thirdparty/zlib/inflate.c diff --git a/drivers/builtin_zlib/zlib/inflate.h b/thirdparty/zlib/inflate.h index 95f4986d40..95f4986d40 100644 --- a/drivers/builtin_zlib/zlib/inflate.h +++ b/thirdparty/zlib/inflate.h diff --git a/drivers/builtin_zlib/zlib/inftrees.c b/thirdparty/zlib/inftrees.c index 44d89cf24e..44d89cf24e 100644 --- a/drivers/builtin_zlib/zlib/inftrees.c +++ b/thirdparty/zlib/inftrees.c diff --git a/drivers/builtin_zlib/zlib/inftrees.h b/thirdparty/zlib/inftrees.h index baa53a0b1a..baa53a0b1a 100644 --- a/drivers/builtin_zlib/zlib/inftrees.h +++ b/thirdparty/zlib/inftrees.h diff --git a/drivers/builtin_zlib/zlib/trees.c b/thirdparty/zlib/trees.c index 1fd7759ef0..1fd7759ef0 100644 --- a/drivers/builtin_zlib/zlib/trees.c +++ b/thirdparty/zlib/trees.c diff --git a/drivers/builtin_zlib/zlib/trees.h b/thirdparty/zlib/trees.h index d35639d82a..d35639d82a 100644 --- a/drivers/builtin_zlib/zlib/trees.h +++ b/thirdparty/zlib/trees.h diff --git a/drivers/builtin_zlib/zlib/uncompr.c b/thirdparty/zlib/uncompr.c index 242e9493df..242e9493df 100644 --- a/drivers/builtin_zlib/zlib/uncompr.c +++ b/thirdparty/zlib/uncompr.c diff --git a/drivers/builtin_zlib/zlib/zconf.h b/thirdparty/zlib/zconf.h index f44af82fc2..f44af82fc2 100644 --- a/drivers/builtin_zlib/zlib/zconf.h +++ b/thirdparty/zlib/zconf.h diff --git a/drivers/builtin_zlib/zlib/zlib.h b/thirdparty/zlib/zlib.h index 3e0c7672ac..3e0c7672ac 100644 --- a/drivers/builtin_zlib/zlib/zlib.h +++ b/thirdparty/zlib/zlib.h diff --git a/drivers/builtin_zlib/zlib/zutil.c b/thirdparty/zlib/zutil.c index 23d2ebef00..23d2ebef00 100644 --- a/drivers/builtin_zlib/zlib/zutil.c +++ b/thirdparty/zlib/zutil.c diff --git a/drivers/builtin_zlib/zlib/zutil.h b/thirdparty/zlib/zutil.h index 24ab06b1cf..24ab06b1cf 100644 --- a/drivers/builtin_zlib/zlib/zutil.h +++ b/thirdparty/zlib/zutil.h diff --git a/tools/SCsub b/tools/SCsub index f6c14a13fb..b0b33d4f01 100644 --- a/tools/SCsub +++ b/tools/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.tool_sources=[] @@ -115,12 +117,8 @@ if (env["tools"]!="no"): env.Command('#tools/editor/builtin_fonts.h',flist,make_fonts_header) SConscript('editor/SCsub'); - #SConscript('scintilla/SCsub'); SConscript('collada/SCsub'); - SConscript('docdump/SCsub'); - #SConscript('freetype/SCsub'); SConscript('doc/SCsub') - SConscript('pck/SCsub') lib = env.Library("tool",env.tool_sources) diff --git a/tools/addheader/files b/tools/addheader/files deleted file mode 100644 index 7b0968236c..0000000000 --- a/tools/addheader/files +++ /dev/null @@ -1,158 +0,0 @@ -./scene/*.h -./scene/*.cpp -./scene/io/*.h -./scene/io/*.cpp -./scene/main/*.h -./scene/main/*.cpp -./scene/resources/*.h -./scene/resources/*.cpp -./scene/gui/*.h -./scene/gui/*.cpp -./scene/audio/*.h -./scene/audio/*.cpp -./scene/3d/*.h -./scene/3d/*.cpp -./scene/2d/*.h -./scene/2d/*.cpp -./scene/animation/*.h -./scene/animation/*.cpp -./bin/tests/*.h -./bin/tests/*.cpp -./main/*.h -./main/*.cpp -./modules/gridmap/*.h -./modules/gridmap/*.cpp -./servers/*.h -./servers/*.cpp -./servers/physics_2d/*.h -./servers/physics_2d/*.cpp -./servers/physics/*.h -./servers/physics/*.cpp -./servers/visual/*.h -./servers/visual/*.cpp -./servers/spatial_sound_2d/*.h -./servers/spatial_sound_2d/*.cpp -./servers/audio/*.h -./servers/audio/*.cpp -./tools/doc/doc_data.h -./tools/doc/doc_data.cpp -./tools/collada/collada.h -./tools/collada/collada.cpp -./tools/editor/*.h -./tools/editor/*.cpp -./tools/editor/plugins/*.h -./tools/editor/plugins/*.cpp -./tools/editor/io_plugins/*.h -./tools/editor/io_plugins/*.cpp -./tools/docdump/doc_dump.h -./tools/docdump/doc_dump.cpp -./core/*.h -./core/*.cpp -./core/io/object_format_binary.h -./core/io/file_access_buffered_fa.h -./core/io/file_access_buffered.h -./core/io/resource_saver.h -./core/io/file_access_compressed.cpp -./core/io/object_format_xml.cpp -./core/io/http_client.h -./core/io/object_format_xml.h -./core/io/compression.h -./core/io/ip_address.h -./core/io/file_access_pack.h -./core/io/ip.h -./core/io/tcp_server.h -./core/io/tcp_server.cpp -./core/io/packet_peer.cpp -./core/io/marshalls.h -./core/io/stream_peer.cpp -./core/io/resource_loader.cpp -./core/io/stream_peer_tcp.h -./core/io/stream_peer_tcp.cpp -./core/io/translation_loader_po.h -./core/io/zip_io.h -./core/io/ip_address.cpp -./core/io/object_saver_base.cpp -./core/io/object_loader.cpp -./core/io/xml_parser.h -./core/io/file_access_network.cpp -./core/io/resource_loader.h -./core/io/packet_peer.h -./core/io/stream_peer.h -./core/io/marshalls.cpp -./core/io/config_file.h -./core/io/ip.cpp -./core/io/file_access_zip.cpp -./core/io/resource_format_binary.h -./core/io/image_loader.h -./core/io/file_access_zip.h -./core/io/http_client.cpp -./core/io/file_access_memory.h -./core/io/xml_parser.cpp -./core/io/object_saver_base.h -./core/io/object_saver.cpp -./core/io/compression.cpp -./core/io/resource_format_xml.cpp -./core/io/object_format_binary.cpp -./core/io/file_access_compressed.h -./core/io/json.h -./core/io/file_access_pack.cpp -./core/io/resource_format_binary.cpp -./core/io/object_loader.h -./core/io/object_saver.h -./core/io/json.cpp -./core/io/file_access_network.h -./core/io/resource_saver.cpp -./core/io/file_access_memory.cpp -./core/io/image_loader.cpp -./core/io/resource_format_xml.h -./core/io/file_access_buffered.cpp -./core/io/config_file.cpp -./core/io/translation_loader_po.cpp -./core/os/*.h -./core/os/*.cpp -./core/math/*.h -./core/math/*.cpp -./script/gdscript/*.h -./script/gdscript/*.cpp -./script/multiscript/multi_script.cpp -./script/multiscript/multi_script.h -./script/register_script_types.h -./platform/android/*.h -./platform/android/*.cpp -./platform/android/java/src/com/android/godot/*.java -./platform/server/*.h -./platform/server/*.cpp -./platform/bb10/*.h -./platform/bb10/*.cpp -./platform/javascript/*.h -./platform/javascript/*.cpp -./platform/javascript/export/export.h -./platform/javascript/export/export.cpp -./platform/iphone/*.h -./platform/iphone/*.cpp -./platform/iphone/*.mm -./platform/windows/*.h -./platform/windows/*.cpp -./platform/osx/*.h -./platform/osx/*.cpp -./platform/osx/*.mm -./platform/x11/*.h -./platform/x11/*.cpp -./drivers/unix/*.h -./drivers/unix/*.cpp -./drivers/gles2/*.h -./drivers/gles2/*.cpp -./drivers/chibi/*.h -./drivers/chibi/*.cpp -./drivers/png/resource_saver_png.cpp -./drivers/png/image_loader_png.cpp -./drivers/png/image_loader_png.h -./drivers/vorbis/audio_stream_ogg_vorbis.h -./drivers/vorbis/audio_stream_ogg_vorbis.cpp -./drivers/gl_context/context_gl.h -./drivers/gles1/*.h -./drivers/gles1/*.cpp -./drivers/windows/*.h -./drivers/windows/*.cpp -./drivers/alsa/audio_driver_alsa.h -./drivers/alsa/audio_driver_alsa.cpp diff --git a/tools/addheader/header.txt b/tools/addheader/header.txt deleted file mode 100644 index e4efb2dcfc..0000000000 --- a/tools/addheader/header.txt +++ /dev/null @@ -1,12 +0,0 @@ -/*************************************************/ -/* $filename */ -/*************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/*************************************************/ -/* Source code within this file is: */ -/* (c) 2007-2016 Juan Linietsky, Ariel Manzur */ -/* All Rights Reserved. */ -/*************************************************/ - - diff --git a/tools/buildstuff/zlib_freetype231_jpeg_libpng-bin-win32-vs81.zip b/tools/buildstuff/zlib_freetype231_jpeg_libpng-bin-win32-vs81.zip Binary files differdeleted file mode 100644 index 4adf30ea29..0000000000 --- a/tools/buildstuff/zlib_freetype231_jpeg_libpng-bin-win32-vs81.zip +++ /dev/null diff --git a/tools/collada/SCsub b/tools/collada/SCsub index 34524f10ef..473474201a 100644 --- a/tools/collada/SCsub +++ b/tools/collada/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.tool_sources,"*.cpp") diff --git a/tools/docker/Dockerfile b/tools/dist/docker/Dockerfile index 428de9d1a7..428de9d1a7 100644 --- a/tools/docker/Dockerfile +++ b/tools/dist/docker/Dockerfile diff --git a/tools/docker/README.md b/tools/dist/docker/README.md index 7f10b46ad8..7f10b46ad8 100644 --- a/tools/docker/README.md +++ b/tools/dist/docker/README.md diff --git a/tools/docker/scripts/install-android-tools b/tools/dist/docker/scripts/install-android-tools index 8a617d9942..8a617d9942 100644 --- a/tools/docker/scripts/install-android-tools +++ b/tools/dist/docker/scripts/install-android-tools diff --git a/tools/html_fs/godot.html b/tools/dist/html_fs/godot.html index c354826e1f..c354826e1f 100644 --- a/tools/html_fs/godot.html +++ b/tools/dist/html_fs/godot.html diff --git a/tools/html_fs/godotfs.js b/tools/dist/html_fs/godotfs.js index 2c59344cf5..2c59344cf5 100644 --- a/tools/html_fs/godotfs.js +++ b/tools/dist/html_fs/godotfs.js diff --git a/platform/iphone/xcode/godot_xcode/data.pck b/tools/dist/ios_xcode/godot_xcode/data.pck index e69de29bb2..e69de29bb2 100644 --- a/platform/iphone/xcode/godot_xcode/data.pck +++ b/tools/dist/ios_xcode/godot_xcode/data.pck diff --git a/platform/iphone/xcode/godot_xcode/godot_debug.iphone b/tools/dist/ios_xcode/godot_xcode/godot_debug.iphone index e69de29bb2..e69de29bb2 100755 --- a/platform/iphone/xcode/godot_xcode/godot_debug.iphone +++ b/tools/dist/ios_xcode/godot_xcode/godot_debug.iphone diff --git a/platform/iphone/xcode/godot_xcode/godot_ios.xcodeproj/project.pbxproj b/tools/dist/ios_xcode/godot_xcode/godot_ios.xcodeproj/project.pbxproj index bdba8488c8..bdba8488c8 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios.xcodeproj/project.pbxproj +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios.xcodeproj/project.pbxproj diff --git a/platform/iphone/xcode/godot_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/tools/dist/ios_xcode/godot_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 3c9ba38bbe..3c9ba38bbe 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-568h@2x~iphone.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-568h@2x~iphone.png Binary files differindex 1d5e472665..1d5e472665 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Default-568h@2x~iphone.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-568h@2x~iphone.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-667h.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-667h.png Binary files differindex b13a399c83..b13a399c83 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Default-667h.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-667h.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-667h@2x.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-667h@2x.png Binary files differindex b51598fed0..b51598fed0 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Default-667h@2x.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-667h@2x.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-736h.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-736h.png Binary files differindex 8c44edbccd..8c44edbccd 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Default-736h.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-736h.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-736h@3x.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-736h@3x.png Binary files differindex 33847ac136..33847ac136 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Default-736h@3x.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-736h@3x.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape-736h.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Landscape-736h.png Binary files differindex 2a025b745b..2a025b745b 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape-736h.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Landscape-736h.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape@2x~ipad.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Landscape@2x~ipad.png Binary files differindex 7099f3e18d..7099f3e18d 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape@2x~ipad.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Landscape@2x~ipad.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape~ipad.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Landscape~ipad.png Binary files differindex 4a761c339a..4a761c339a 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape~ipad.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Landscape~ipad.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Portrait@2x~ipad.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Portrait@2x~ipad.png Binary files differindex b09cf21186..b09cf21186 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Portrait@2x~ipad.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Portrait@2x~ipad.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Portrait~ipad.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Portrait~ipad.png Binary files differindex fa698eb70c..fa698eb70c 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Portrait~ipad.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default-Portrait~ipad.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default@2x~iphone.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default@2x~iphone.png Binary files differindex ddf2861f4d..ddf2861f4d 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Default@2x~iphone.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default@2x~iphone.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default~iphone.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default~iphone.png Binary files differindex c485a33b03..c485a33b03 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Default~iphone.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Default~iphone.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Contents.json b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Contents.json index a458b67873..a458b67873 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Contents.json diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-100.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-100.png Binary files differindex 165f4423b3..165f4423b3 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-100.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-100.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-114.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-114.png Binary files differindex 2e205e920c..2e205e920c 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-114.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-114.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-120.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-120.png Binary files differindex 6245f83f48..6245f83f48 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-120.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-120.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-144.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-144.png Binary files differindex 7b24e01bc6..7b24e01bc6 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-144.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-144.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-152.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-152.png Binary files differindex 344b470fa3..344b470fa3 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-152.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-152.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-180.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-180.png Binary files differindex 0dcebbc3f2..0dcebbc3f2 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-180.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-180.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-29.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-29.png Binary files differindex 9ae94e9aaf..9ae94e9aaf 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-29.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-29.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-40.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-40.png Binary files differindex 569f24df91..569f24df91 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-40.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-40.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-50.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-50.png Binary files differindex 9e69ed3121..9e69ed3121 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-50.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-50.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-57.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-57.png Binary files differindex b970fa3067..b970fa3067 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-57.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-57.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-58.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-58.png Binary files differindex 6097a6c73b..6097a6c73b 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-58.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-58.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-60.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-60.png Binary files differindex 21b9622eb6..21b9622eb6 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-60.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-60.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-72.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-72.png Binary files differindex 34dea8e6ad..34dea8e6ad 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-72.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-72.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-76.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-76.png Binary files differindex f72eb0b345..f72eb0b345 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-76.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-76.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-80.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-80.png Binary files differindex 793c9b1f5f..793c9b1f5f 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-80.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-80.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-167.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-167.png Binary files differindex 7cd0e054ab..7cd0e054ab 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-167.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-167.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-87.png b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-87.png Binary files differindex e9b2429754..e9b2429754 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-87.png +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-87.png diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/sizes b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/sizes index e328a62cb6..e328a62cb6 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/sizes +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/sizes diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/en.lproj/InfoPlist.strings b/tools/dist/ios_xcode/godot_xcode/godot_ios/en.lproj/InfoPlist.strings index 477b28ff8f..477b28ff8f 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/en.lproj/InfoPlist.strings +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/en.lproj/InfoPlist.strings diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/godot_ios-Info.plist b/tools/dist/ios_xcode/godot_xcode/godot_ios/godot_ios-Info.plist index f97b0fca36..f97b0fca36 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/godot_ios-Info.plist +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/godot_ios-Info.plist diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/main.m b/tools/dist/ios_xcode/godot_xcode/godot_ios/main.m index 3e4ea5e129..3e4ea5e129 100644 --- a/platform/iphone/xcode/godot_xcode/godot_ios/main.m +++ b/tools/dist/ios_xcode/godot_xcode/godot_ios/main.m diff --git a/platform/iphone/xcode/godot_xcode/godot_opt.iphone b/tools/dist/ios_xcode/godot_xcode/godot_opt.iphone index e69de29bb2..e69de29bb2 100755 --- a/platform/iphone/xcode/godot_xcode/godot_opt.iphone +++ b/tools/dist/ios_xcode/godot_xcode/godot_opt.iphone diff --git a/tools/osx_template.app/Contents/Info.plist b/tools/dist/osx_template.app/Contents/Info.plist index 5146c875bc..5146c875bc 100755 --- a/tools/osx_template.app/Contents/Info.plist +++ b/tools/dist/osx_template.app/Contents/Info.plist diff --git a/tools/Godot.app/Contents/PkgInfo b/tools/dist/osx_template.app/Contents/PkgInfo index 6f749b0f37..6f749b0f37 100644 --- a/tools/Godot.app/Contents/PkgInfo +++ b/tools/dist/osx_template.app/Contents/PkgInfo diff --git a/tools/osx_template.app/Contents/Resources/icon.icns b/tools/dist/osx_template.app/Contents/Resources/icon.icns Binary files differindex 375f61437d..375f61437d 100644 --- a/tools/osx_template.app/Contents/Resources/icon.icns +++ b/tools/dist/osx_template.app/Contents/Resources/icon.icns diff --git a/tools/Godot.app/Contents/Info.plist b/tools/dist/osx_tools.app/Contents/Info.plist index 2a3e727133..2a3e727133 100755 --- a/tools/Godot.app/Contents/Info.plist +++ b/tools/dist/osx_tools.app/Contents/Info.plist diff --git a/tools/osx_template.app/Contents/PkgInfo b/tools/dist/osx_tools.app/Contents/PkgInfo index 6f749b0f37..6f749b0f37 100644 --- a/tools/osx_template.app/Contents/PkgInfo +++ b/tools/dist/osx_tools.app/Contents/PkgInfo diff --git a/tools/Godot.app/Contents/Resources/Godot.icns b/tools/dist/osx_tools.app/Contents/Resources/Godot.icns Binary files differindex 375f61437d..375f61437d 100644 --- a/tools/Godot.app/Contents/Resources/Godot.icns +++ b/tools/dist/osx_tools.app/Contents/Resources/Godot.icns diff --git a/tools/dist/uwp_template/AppxManifest.xml b/tools/dist/uwp_template/AppxManifest.xml new file mode 100644 index 0000000000..48a2ba7eb3 --- /dev/null +++ b/tools/dist/uwp_template/AppxManifest.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp build" xmlns:build="http://schemas.microsoft.com/developer/appx/2015/build">
+ <Identity Name="$identity_name$" Publisher="$publisher$" Version="$version_string$" ProcessorArchitecture="$architecture$" />
+ <mp:PhoneIdentity PhoneProductId="$product_guid$" PhonePublisherId="$publisher_guid$" />
+ <Properties>
+ <DisplayName>$display_name$</DisplayName>
+ <PublisherDisplayName>$publisher_display_name$</PublisherDisplayName>
+ <Logo>Assets\StoreLogo.png</Logo>
+ </Properties>
+ <Dependencies>
+ <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.10240.0" MaxVersionTested="10.0.14393.0" />
+ <PackageDependency Name="Microsoft.VCLibs.140.00" MinVersion="14.0.24123.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
+ </Dependencies>
+ <Resources>
+ <Resource Language="EN-US" />
+ </Resources>
+ <Applications>
+ <Application Id="App" Executable="godot.winrt.exe" EntryPoint="GodotWinRT.App">
+ <uap:VisualElements DisplayName="$display_name$" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="$app_description$" BackgroundColor="$bg_color$">
+ <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" Square310x310Logo="Assets\Square310x310Logo.png" Square71x71Logo="Assets\Square71x71Logo.png" ShortName="$short_name$">
+ $name_on_tiles$
+ </uap:DefaultTile>
+ <uap:SplashScreen Image="Assets\SplashScreen.png" />
+ $rotation_preference$
+ </uap:VisualElements>
+ </Application>
+ </Applications>
+ $capabilities_place$
+ <build:Metadata>
+ <build:Item Name="GodotEngine" Version="$godot_version$" />
+ </build:Metadata>
+</Package>
\ No newline at end of file diff --git a/tools/dist/uwp_template/Assets/SplashScreen.scale-100.png b/tools/dist/uwp_template/Assets/SplashScreen.scale-100.png Binary files differnew file mode 100644 index 0000000000..540bfb1c01 --- /dev/null +++ b/tools/dist/uwp_template/Assets/SplashScreen.scale-100.png diff --git a/tools/dist/uwp_template/Assets/Square150x150Logo.scale-100.png b/tools/dist/uwp_template/Assets/Square150x150Logo.scale-100.png Binary files differnew file mode 100644 index 0000000000..6cff663eb5 --- /dev/null +++ b/tools/dist/uwp_template/Assets/Square150x150Logo.scale-100.png diff --git a/tools/dist/uwp_template/Assets/Square310x310Logo.scale-100.png b/tools/dist/uwp_template/Assets/Square310x310Logo.scale-100.png Binary files differnew file mode 100644 index 0000000000..12ec232c87 --- /dev/null +++ b/tools/dist/uwp_template/Assets/Square310x310Logo.scale-100.png diff --git a/tools/dist/uwp_template/Assets/Square44x44Logo.scale-100.png b/tools/dist/uwp_template/Assets/Square44x44Logo.scale-100.png Binary files differnew file mode 100644 index 0000000000..ad059994ed --- /dev/null +++ b/tools/dist/uwp_template/Assets/Square44x44Logo.scale-100.png diff --git a/tools/dist/uwp_template/Assets/Square71x71Logo.scale-100.png b/tools/dist/uwp_template/Assets/Square71x71Logo.scale-100.png Binary files differnew file mode 100644 index 0000000000..b1bf331365 --- /dev/null +++ b/tools/dist/uwp_template/Assets/Square71x71Logo.scale-100.png diff --git a/tools/dist/uwp_template/Assets/StoreLogo.scale-100.png b/tools/dist/uwp_template/Assets/StoreLogo.scale-100.png Binary files differnew file mode 100644 index 0000000000..8d7a625c82 --- /dev/null +++ b/tools/dist/uwp_template/Assets/StoreLogo.scale-100.png diff --git a/tools/dist/uwp_template/Assets/Wide310x150Logo.scale-100.png b/tools/dist/uwp_template/Assets/Wide310x150Logo.scale-100.png Binary files differnew file mode 100644 index 0000000000..b06f1ad50f --- /dev/null +++ b/tools/dist/uwp_template/Assets/Wide310x150Logo.scale-100.png diff --git a/tools/doc/SCsub b/tools/doc/SCsub index 34524f10ef..473474201a 100644 --- a/tools/doc/SCsub +++ b/tools/doc/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') env.add_source_files(env.tool_sources,"*.cpp") diff --git a/tools/doc/doc_data.cpp b/tools/doc/doc_data.cpp index 479b99a03d..4a8fdfb215 100644 --- a/tools/doc/doc_data.cpp +++ b/tools/doc/doc_data.cpp @@ -198,6 +198,11 @@ void DocData::generate(bool p_basic_types) { if (method.qualifiers!="") method.qualifiers+=" "; method.qualifiers+="const"; + + } else if (E->get().flags&METHOD_FLAG_VARARG) { + if (method.qualifiers!="") + method.qualifiers+=" "; + method.qualifiers+="vararg"; } for(int i=-1;i<E->get().arguments.size();i++) { diff --git a/tools/docdump/doc_dump.cpp b/tools/doc/doc_dump.cpp index fbf13f9e8f..fbf13f9e8f 100644 --- a/tools/docdump/doc_dump.cpp +++ b/tools/doc/doc_dump.cpp diff --git a/tools/docdump/doc_dump.h b/tools/doc/doc_dump.h index 372f5e0969..372f5e0969 100644 --- a/tools/docdump/doc_dump.h +++ b/tools/doc/doc_dump.h diff --git a/tools/docdump/SCsub b/tools/docdump/SCsub deleted file mode 100644 index 34524f10ef..0000000000 --- a/tools/docdump/SCsub +++ /dev/null @@ -1,5 +0,0 @@ -Import('env') - -env.add_source_files(env.tool_sources,"*.cpp") - -Export('env') diff --git a/tools/editor/SCsub b/tools/editor/SCsub index 34651b36f2..f6cb16dc24 100644 --- a/tools/editor/SCsub +++ b/tools/editor/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp index 2f67df1fc3..a556031e5e 100644 --- a/tools/editor/animation_editor.cpp +++ b/tools/editor/animation_editor.cpp @@ -1933,12 +1933,20 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { if (mb.button_index==BUTTON_WHEEL_UP && mb.pressed) { - v_scroll->set_val( v_scroll->get_val() - v_scroll->get_page() / 8 ); + if (mb.mod.command) { + zoom->set_val(zoom->get_val() + zoom->get_step()); + } else { + v_scroll->set_val( v_scroll->get_val() - v_scroll->get_page() / 8 ); + } } if (mb.button_index==BUTTON_WHEEL_DOWN && mb.pressed) { - v_scroll->set_val( v_scroll->get_val() + v_scroll->get_page() / 8 ); + if (mb.mod.command) { + zoom->set_val(zoom->get_val() - zoom->get_step()); + } else { + v_scroll->set_val( v_scroll->get_val() + v_scroll->get_page() / 8 ); + } } if (mb.button_index==BUTTON_RIGHT && mb.pressed) { diff --git a/tools/editor/code_editor.cpp b/tools/editor/code_editor.cpp index 2779275ea8..626f86d33d 100644 --- a/tools/editor/code_editor.cpp +++ b/tools/editor/code_editor.cpp @@ -356,7 +356,7 @@ void FindReplaceBar::_show_search() { show(); search_text->grab_focus(); - if (text_edit->is_selection_active()) { + if (text_edit->is_selection_active() && !selection_only->is_pressed()) { search_text->set_text(text_edit->get_selection_text()); } @@ -376,12 +376,16 @@ void FindReplaceBar::popup_search() { void FindReplaceBar::popup_replace() { + if (!replace_hbc->is_visible() || !replace_options_hbc->is_visible()) { replace_text->clear(); replace_hbc->show(); replace_options_hbc->show(); + } + selection_only->set_pressed( (text_edit->is_selection_active() && text_edit->get_selection_from_line() < text_edit->get_selection_to_line()) ); + _show_search(); } @@ -409,6 +413,14 @@ void FindReplaceBar::_search_text_entered(const String& p_text) { search_next(); } +void FindReplaceBar::_replace_text_entered(const String& p_text) { + + if (selection_only->is_pressed() && text_edit->is_selection_active()) { + _replace_all(); + _hide_bar(); + } +} + String FindReplaceBar::get_search_text() const { return search_text->get_text(); @@ -452,6 +464,7 @@ void FindReplaceBar::_bind_methods() { ObjectTypeDB::bind_method("_editor_text_changed",&FindReplaceBar::_editor_text_changed); ObjectTypeDB::bind_method("_search_text_changed",&FindReplaceBar::_search_text_changed); ObjectTypeDB::bind_method("_search_text_entered",&FindReplaceBar::_search_text_entered); + ObjectTypeDB::bind_method("_replace_text_entered",&FindReplaceBar::_replace_text_entered); ObjectTypeDB::bind_method("_search_current",&FindReplaceBar::search_current); ObjectTypeDB::bind_method("_search_next",&FindReplaceBar::search_next); ObjectTypeDB::bind_method("_search_prev",&FindReplaceBar::search_prev); @@ -497,18 +510,19 @@ FindReplaceBar::FindReplaceBar() { replace_text = memnew(LineEdit); replace_hbc->add_child(replace_text); replace_text->set_custom_minimum_size(Size2(200, 0)); - replace_text->connect("text_entered",this,"_search_text_entered"); + replace_text->connect("text_entered",this,"_replace_text_entered"); + - replace = memnew(ToolButton); + replace = memnew(Button); replace_hbc->add_child(replace); replace->set_text(TTR("Replace")); - replace->set_focus_mode(FOCUS_NONE); + //replace->set_focus_mode(FOCUS_NONE); replace->connect("pressed",this,"_replace_pressed"); - replace_all = memnew(ToolButton); + replace_all = memnew(Button); replace_hbc->add_child(replace_all); replace_all->set_text(TTR("Replace All")); - replace_all->set_focus_mode(FOCUS_NONE); + //replace_all->set_focus_mode(FOCUS_NONE); replace_all->connect("pressed",this,"_replace_all_pressed"); Control *spacer_split = memnew( Control ); @@ -581,8 +595,10 @@ void FindReplaceDialog::popup_search() { void FindReplaceDialog::popup_replace() { + set_title(TTR("Replace")); bool do_selection=(text_edit->is_selection_active() && text_edit->get_selection_from_line() < text_edit->get_selection_to_line()); + set_replace_selection_only(do_selection); if (!do_selection && text_edit->is_selection_active()) { @@ -1035,7 +1051,7 @@ void CodeTextEditor::_reset_zoom() { void CodeTextEditor::_line_col_changed() { line_nb->set_text(itos(text_editor->cursor_get_line() + 1)); - col_nb->set_text(itos(text_editor->cursor_get_column())); + col_nb->set_text(itos(text_editor->cursor_get_column() + 1)); } void CodeTextEditor::_text_changed() { @@ -1089,6 +1105,24 @@ void CodeTextEditor::_font_resize_timeout() { } } +void CodeTextEditor::update_editor_settings() { + + text_editor->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/auto_brace_complete")); + text_editor->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/scroll_past_end_of_file")); + text_editor->set_tab_size(EditorSettings::get_singleton()->get("text_editor/tab_size")); + text_editor->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/draw_tabs")); + text_editor->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/show_line_numbers")); + text_editor->set_line_numbers_zero_padded(EditorSettings::get_singleton()->get("text_editor/line_numbers_zero_padded")); + text_editor->set_show_line_length_guideline(EditorSettings::get_singleton()->get("text_editor/show_line_length_guideline")); + text_editor->set_line_length_guideline_column(EditorSettings::get_singleton()->get("text_editor/line_length_guideline_column")); + text_editor->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/syntax_highlighting")); + text_editor->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlight_all_occurrences")); + text_editor->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/caret_blink")); + text_editor->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/caret_blink_speed")); + text_editor->set_draw_breakpoint_gutter(EditorSettings::get_singleton()->get("text_editor/show_breakpoint_gutter")); + text_editor->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/block_caret")); +} + void CodeTextEditor::set_error(const String& p_error) { if (p_error!="") { @@ -1112,8 +1146,10 @@ void CodeTextEditor::_update_font() { font_overridden = true; } } - if(!font_overridden) + if(!font_overridden) { + text_editor->add_font_override("font",get_font("source","EditorFonts")); + } } void CodeTextEditor::_on_settings_change() { @@ -1152,7 +1188,7 @@ void CodeTextEditor::_notification(int p_what) { _load_theme_settings(); emit_signal("load_theme_settings"); } - if (p_what==NOTIFICATION_ENTER_TREE) { + if (p_what==NOTIFICATION_THEME_CHANGED) { _update_font(); } } diff --git a/tools/editor/code_editor.h b/tools/editor/code_editor.h index 2affa31482..ce3b5bee26 100644 --- a/tools/editor/code_editor.h +++ b/tools/editor/code_editor.h @@ -73,8 +73,8 @@ class FindReplaceBar : public HBoxContainer { TextureButton *hide_button; LineEdit *replace_text; - ToolButton *replace; - ToolButton *replace_all; + Button *replace; + Button *replace_all; CheckBox *selection_only; VBoxContainer *text_vbc; @@ -98,6 +98,7 @@ class FindReplaceBar : public HBoxContainer { void _search_options_changed(bool p_pressed); void _search_text_changed(const String& p_text); void _search_text_entered(const String& p_text); + void _replace_text_entered(const String& p_text); protected: void _notification(int p_what); @@ -241,6 +242,7 @@ protected: public: + void update_editor_settings(); void set_error(const String& p_error); void update_line_and_column() { _line_col_changed(); } TextEdit *get_text_edit() { return text_editor; } diff --git a/tools/editor/connections_dialog.cpp b/tools/editor/connections_dialog.cpp index c4f2435675..1baad2c6b3 100644 --- a/tools/editor/connections_dialog.cpp +++ b/tools/editor/connections_dialog.cpp @@ -181,6 +181,14 @@ void ConnectDialog::ok_pressed() { error->popup_centered_minsize(); return; } + Node* target = tree->get_selected(); + if (target->get_script().is_null()) { + if (!target->has_method(dst_method->get_text())) { + error->set_text(TTR("Target method not found! Specify a valid method or attach a script to target Node.")); + error->popup_centered_minsize(); + return; + } + } emit_signal("connected"); hide(); diff --git a/tools/editor/create_dialog.cpp b/tools/editor/create_dialog.cpp index 5aac8bff09..320939cb97 100644 --- a/tools/editor/create_dialog.cpp +++ b/tools/editor/create_dialog.cpp @@ -42,11 +42,84 @@ void CreateDialog::popup(bool p_dontclear) { + recent->clear(); + + FileAccess *f = FileAccess::open( EditorSettings::get_singleton()->get_project_settings_path().plus_file("create_recent."+base_type), FileAccess::READ ); + + if (f) { + + TreeItem *root = recent->create_item(); + + while(!f->eof_reached()) { + String l = f->get_line().strip_edges(); + + if (l!=String()) { + + TreeItem *ti = recent->create_item(root); + ti->set_text(0,l); + if (has_icon(l,"EditorIcons")) { + + ti->set_icon(0,get_icon(l,"EditorIcons")); + } else { + ti->set_icon(0,get_icon("Object","EditorIcons")); + } + } + } + + memdelete(f); + } + + favorites->clear(); + + f = FileAccess::open( EditorSettings::get_singleton()->get_project_settings_path().plus_file("favorites."+base_type), FileAccess::READ ); + + favorite_list.clear(); + + if (f) { + + + while(!f->eof_reached()) { + String l = f->get_line().strip_edges(); + + if (l!=String()) { + favorite_list.push_back(l); + } + } + + memdelete(f); + } else { +#if 0 +// I think this was way too confusing + if (base_type=="Node") { + //harcode some favorites :D + favorite_list.push_back("Panel"); + favorite_list.push_back("Button"); + favorite_list.push_back("Label"); + favorite_list.push_back("LineEdit"); + favorite_list.push_back("Node2D"); + favorite_list.push_back("Sprite"); + favorite_list.push_back("Camera2D"); + favorite_list.push_back("Area2D"); + favorite_list.push_back("CollisionShape2D"); + favorite_list.push_back("Spatial"); + favorite_list.push_back("Camera"); + favorite_list.push_back("Area"); + favorite_list.push_back("CollisionShape"); + favorite_list.push_back("TestCube"); + favorite_list.push_back("AnimationPlayer"); + + } +#endif + } + + _update_favorite_list(); + popup_centered_ratio(); if (p_dontclear) search_box->select_all(); - else + else { search_box->clear(); + } search_box->grab_focus(); _update_search(); @@ -104,7 +177,7 @@ void CreateDialog::add_type(const String& p_type,HashMap<String,TreeItem*>& p_ty item->set_selectable(0,false); } else { - if (!*to_select && (search_box->get_text().is_subsequence_ofi(p_type))) { + if ((!*to_select && (search_box->get_text().is_subsequence_ofi(p_type))) || search_box->get_text()==p_type) { *to_select=item; } @@ -140,6 +213,8 @@ void CreateDialog::_update_search() { search_options->clear(); + favorite->set_disabled(true); + help_bit->set_text(""); /* TreeItem *root = search_options->create_item(); @@ -225,7 +300,7 @@ void CreateDialog::_update_search() { } - if (!to_select) { + if (!to_select || ct[i].name==search_box->get_text()) { to_select=item; } @@ -234,8 +309,11 @@ void CreateDialog::_update_search() { } } - if (to_select) + if (to_select) { to_select->select(0); + favorite->set_disabled(false); + favorite->set_pressed(favorite_list.find(to_select->get_text(0))!=-1); + } get_ok()->set_disabled(root->get_children()==NULL); @@ -246,6 +324,32 @@ void CreateDialog::_confirmed() { TreeItem *ti = search_options->get_selected(); if (!ti) return; + + FileAccess *f = FileAccess::open( EditorSettings::get_singleton()->get_project_settings_path().plus_file("create_recent."+base_type), FileAccess::WRITE ); + + if (f) { + f->store_line(get_selected_type()); + TreeItem *t = recent->get_root(); + if (t) + t=t->get_children(); + int count=0; + while(t) { + if (t->get_text(0)!=get_selected_type()) { + + f->store_line(t->get_text(0)); + } + + if (count>32) { + //limit it to 32 entries.. + break; + } + t=t->get_next(); + count++; + } + + memdelete(f); + } + emit_signal("create"); hide(); } @@ -255,6 +359,7 @@ void CreateDialog::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { connect("confirmed",this,"_confirmed"); + favorite->set_icon(get_icon("Favorites","EditorIcons")); } if (p_what==NOTIFICATION_EXIT_TREE) { @@ -344,6 +449,9 @@ void CreateDialog::_item_selected() { String name = item->get_text(0); + favorite->set_disabled(false); + favorite->set_pressed(favorite_list.find(name)!=-1); + if (!EditorHelp::get_doc_data()->class_list.has(name)) return; @@ -351,12 +459,182 @@ void CreateDialog::_item_selected() { } + +void CreateDialog::_favorite_toggled() { + + TreeItem *item = search_options->get_selected(); + if (!item) + return; + + String name = item->get_text(0); + + if (favorite_list.find(name)==-1) { + favorite_list.push_back(name); + favorite->set_pressed(true); + } else { + favorite_list.erase(name); + favorite->set_pressed(false); + } + + _save_favorite_list(); + _update_favorite_list(); +} + +void CreateDialog::_save_favorite_list() { + + FileAccess *f = FileAccess::open( EditorSettings::get_singleton()->get_project_settings_path().plus_file("favorites."+base_type), FileAccess::WRITE ); + + if (f) { + + for(int i=0;i<favorite_list.size();i++) { + + f->store_line(favorite_list[i]); + } + memdelete(f); + } +} + +void CreateDialog::_update_favorite_list() { + + favorites->clear(); + TreeItem *root = favorites->create_item(); + for(int i=0;i<favorite_list.size();i++) { + TreeItem *ti = favorites->create_item(root); + String l = favorite_list[i]; + ti->set_text(0,l); + + if (has_icon(l,"EditorIcons")) { + + ti->set_icon(0,get_icon(l,"EditorIcons")); + } else { + ti->set_icon(0,get_icon("Object","EditorIcons")); + } + } +} + + +void CreateDialog::_history_selected() { + + TreeItem *item = recent->get_selected(); + if (!item) + return; + + search_box->set_text(item->get_text(0)); + _update_search(); + +} + +void CreateDialog::_favorite_selected(){ + + TreeItem *item = favorites->get_selected(); + if (!item) + return; + + search_box->set_text(item->get_text(0)); + _update_search(); + +} + +void CreateDialog::_history_activated() { + + _confirmed(); +} + +void CreateDialog::_favorite_activated(){ + + _confirmed(); +} + +Variant CreateDialog::get_drag_data_fw(const Point2& p_point,Control* p_from) { + + TreeItem *ti = favorites->get_item_at_pos(p_point); + if (ti) { + Dictionary d; + d["type"]="create_favorite_drag"; + d["class"]=ti->get_text(0); + + ToolButton *tb = memnew( ToolButton ); + tb->set_icon(ti->get_icon(0)); + tb->set_text(ti->get_text(0)); + set_drag_preview(tb); + + return d; + } + + return Variant(); +} + +bool CreateDialog::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{ + + Dictionary d = p_data; + if (d.has("type") && String(d["type"])=="create_favorite_drag") { + favorites->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN); + return true; + } + + return false; +} +void CreateDialog::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){ + + Dictionary d = p_data; + + TreeItem *ti = favorites->get_item_at_pos(p_point); + if (!ti) + return; + + String drop_at = ti->get_text(0); + int ds = favorites->get_drop_section_at_pos(p_point); + + int drop_idx = favorite_list.find(drop_at); + if (drop_idx<0) + return; + + String type = d["class"]; + + int from_idx = favorite_list.find(type); + if (from_idx<0) + return; + + if (drop_idx==from_idx) { + ds=-1; //cause it will be gone + } else if (drop_idx>from_idx) { + drop_idx--; + } + + favorite_list.remove(from_idx); + + if (ds<0) { + favorite_list.insert(drop_idx,type); + } else { + if (drop_idx>=favorite_list.size()-1) { + favorite_list.push_back(type); + } else { + favorite_list.insert(drop_idx+1,type); + } + } + + _save_favorite_list(); + _update_favorite_list(); + + +} + void CreateDialog::_bind_methods() { ObjectTypeDB::bind_method(_MD("_text_changed"),&CreateDialog::_text_changed); ObjectTypeDB::bind_method(_MD("_confirmed"),&CreateDialog::_confirmed); ObjectTypeDB::bind_method(_MD("_sbox_input"),&CreateDialog::_sbox_input); ObjectTypeDB::bind_method(_MD("_item_selected"),&CreateDialog::_item_selected); + ObjectTypeDB::bind_method(_MD("_favorite_toggled"),&CreateDialog::_favorite_toggled); + ObjectTypeDB::bind_method(_MD("_history_selected"),&CreateDialog::_history_selected); + ObjectTypeDB::bind_method(_MD("_favorite_selected"),&CreateDialog::_favorite_selected); + ObjectTypeDB::bind_method(_MD("_history_activated"),&CreateDialog::_history_activated); + ObjectTypeDB::bind_method(_MD("_favorite_activated"),&CreateDialog::_favorite_activated); + + + ObjectTypeDB::bind_method("get_drag_data_fw",&CreateDialog::get_drag_data_fw); + ObjectTypeDB::bind_method("can_drop_data_fw",&CreateDialog::can_drop_data_fw); + ObjectTypeDB::bind_method("drop_data_fw",&CreateDialog::drop_data_fw); ADD_SIGNAL(MethodInfo("create")); @@ -365,12 +643,44 @@ void CreateDialog::_bind_methods() { CreateDialog::CreateDialog() { + HSplitContainer *hbc = memnew( HSplitContainer ); + + add_child(hbc); + set_child_rect(hbc); + + VBoxContainer *lvbc = memnew( VBoxContainer); + hbc->add_child(lvbc); + lvbc->set_custom_minimum_size(Size2(150,0)*EDSCALE); + + favorites = memnew (Tree ); + lvbc->add_margin_child(TTR("Favorites:"),favorites,true); + favorites->set_hide_root(true); + favorites->set_hide_folding(true); + favorites->connect("cell_selected",this,"_favorite_selected"); + favorites->connect("item_activated",this,"_favorite_activated"); + favorites->set_drag_forwarding(this); + + + recent = memnew (Tree ); + lvbc->add_margin_child(TTR("Recent:"),recent,true); + recent->set_hide_root(true); + recent->set_hide_folding(true); + recent->connect("cell_selected",this,"_history_selected"); + recent->connect("item_activated",this,"_history_activated"); + VBoxContainer *vbc = memnew( VBoxContainer ); - add_child(vbc); - set_child_rect(vbc); + hbc->add_child(vbc); + vbc->set_h_size_flags(SIZE_EXPAND_FILL); + HBoxContainer *search_hb = memnew( HBoxContainer ); search_box = memnew( LineEdit ); - vbc->add_margin_child(TTR("Search:"),search_box); + search_box->set_h_size_flags(SIZE_EXPAND_FILL); + search_hb->add_child(search_box); + favorite = memnew( Button ); + favorite->set_toggle_mode(true); + search_hb->add_child(favorite); + favorite->connect("pressed",this,"_favorite_toggled"); + vbc->add_margin_child(TTR("Search:"),search_hb); search_box->connect("text_changed",this,"_text_changed"); search_box->connect("input_event",this,"_sbox_input"); search_options = memnew( Tree ); diff --git a/tools/editor/create_dialog.h b/tools/editor/create_dialog.h index 41156b538a..706a06ae16 100644 --- a/tools/editor/create_dialog.h +++ b/tools/editor/create_dialog.h @@ -32,6 +32,7 @@ #include "scene/gui/dialogs.h" #include "scene/gui/button.h" #include "scene/gui/tree.h" +#include "scene/gui/item_list.h" #include "scene/gui/line_edit.h" #include "scene/gui/label.h" #include "editor_help.h" @@ -46,6 +47,12 @@ class CreateDialog : public ConfirmationDialog { OBJ_TYPE(CreateDialog,ConfirmationDialog ) + + Vector<String> favorite_list; + Tree *favorites; + Tree *recent; + + Button *favorite; LineEdit *search_box; Tree *search_options; String base_type; @@ -55,6 +62,15 @@ class CreateDialog : public ConfirmationDialog { void _item_selected(); void _update_search(); + void _update_favorite_list(); + void _save_favorite_list(); + void _favorite_toggled(); + + void _history_selected(); + void _favorite_selected(); + + void _history_activated(); + void _favorite_activated(); void _sbox_input(const InputEvent& p_ie); @@ -63,6 +79,9 @@ class CreateDialog : public ConfirmationDialog { void add_type(const String& p_type,HashMap<String,TreeItem*>& p_types,TreeItem *p_root,TreeItem **to_select); + Variant get_drag_data_fw(const Point2& p_point,Control* p_from); + bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const; + void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from); protected: diff --git a/tools/editor/editor_data.cpp b/tools/editor/editor_data.cpp index 35ec1ebfcc..8fc18b5b39 100644 --- a/tools/editor/editor_data.cpp +++ b/tools/editor/editor_data.cpp @@ -877,8 +877,7 @@ bool EditorSelection::is_selected(Node * p_node) const { return selection.has(p_node); } - -Array EditorSelection::_get_selected_nodes() { +Array EditorSelection::_get_transformable_selected_nodes() { Array ret; @@ -890,6 +889,18 @@ Array EditorSelection::_get_selected_nodes() { return ret; } +Array EditorSelection::_get_selected_nodes() { + + Array ret; + + for (Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) { + + ret.push_back(E->key()); + } + + return ret; +} + void EditorSelection::_bind_methods() { ObjectTypeDB::bind_method(_MD("_node_removed"),&EditorSelection::_node_removed); @@ -897,6 +908,7 @@ void EditorSelection::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_node","node:Node"),&EditorSelection::add_node); ObjectTypeDB::bind_method(_MD("remove_node","node:Node"),&EditorSelection::remove_node); ObjectTypeDB::bind_method(_MD("get_selected_nodes"),&EditorSelection::_get_selected_nodes); + ObjectTypeDB::bind_method(_MD("get_transformable_selected_nodes"),&EditorSelection::_get_transformable_selected_nodes); ADD_SIGNAL( MethodInfo("selection_changed") ); } diff --git a/tools/editor/editor_data.h b/tools/editor/editor_data.h index a0b716f560..59f9d4e4f3 100644 --- a/tools/editor/editor_data.h +++ b/tools/editor/editor_data.h @@ -233,6 +233,8 @@ public: void _update_nl(); Array _get_selected_nodes(); + Array _get_transformable_selected_nodes(); + protected: static void _bind_methods(); diff --git a/tools/editor/editor_dir_dialog.cpp b/tools/editor/editor_dir_dialog.cpp index f6ce7bf3f8..cf0732501e 100644 --- a/tools/editor/editor_dir_dialog.cpp +++ b/tools/editor/editor_dir_dialog.cpp @@ -143,7 +143,7 @@ void EditorDirDialog::set_current_path(const String& p_path) { reload(); String p = p_path; if (p.begins_with("res://")) - p.replace_first("res://",""); + p = p.replace_first("res://",""); Vector<String> dirs = p.split("/"); @@ -162,13 +162,13 @@ void EditorDirDialog::set_current_path(const String& p_path) { ERR_FAIL_COND(!p); String pp = p->get_metadata(0); if (pp=="") { + p->set_metadata(0,String(r->get_metadata(0)).plus_file(d)); _update_dir(p); - updating=true; - p->set_collapsed(false); - updating=false; - _item_collapsed(p); - } + updating=true; + p->set_collapsed(false); + updating=false; + _item_collapsed(p); r=p; } @@ -216,7 +216,7 @@ void EditorDirDialog::_make_dir_confirm() { if (err!=OK) { mkdirerr->popup_centered_minsize(Size2(250,80)); } else { - reload(); + set_current_path(dir.plus_file(makedirname->get_text())); } makedirname->set_text(""); // reset label } diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp index 582b9e2490..be1af16576 100644 --- a/tools/editor/editor_file_system.cpp +++ b/tools/editor/editor_file_system.cpp @@ -208,10 +208,14 @@ void EditorFileSystemDirectory::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_file_count"),&EditorFileSystemDirectory::get_file_count); ObjectTypeDB::bind_method(_MD("get_file","idx"),&EditorFileSystemDirectory::get_file); ObjectTypeDB::bind_method(_MD("get_file_path","idx"),&EditorFileSystemDirectory::get_file_path); - ObjectTypeDB::bind_method(_MD("get_file_types","idx"),&EditorFileSystemDirectory::get_file_type); + ObjectTypeDB::bind_method(_MD("get_file_type","idx"),&EditorFileSystemDirectory::get_file_type); ObjectTypeDB::bind_method(_MD("is_missing_sources","idx"),&EditorFileSystemDirectory::is_missing_sources); ObjectTypeDB::bind_method(_MD("get_name"),&EditorFileSystemDirectory::get_name); - ObjectTypeDB::bind_method(_MD("get_parent"),&EditorFileSystemDirectory::get_parent); + ObjectTypeDB::bind_method(_MD("get_path"),&EditorFileSystemDirectory::get_path); + ObjectTypeDB::bind_method(_MD("get_parent:EditorFileSystemDirectory"),&EditorFileSystemDirectory::get_parent); + ObjectTypeDB::bind_method(_MD("find_file_index","name"),&EditorFileSystemDirectory::find_file_index); + ObjectTypeDB::bind_method(_MD("find_dir_index","name"),&EditorFileSystemDirectory::find_dir_index); + } @@ -1341,6 +1345,16 @@ void EditorFileSystem::update_file(const String& p_file) { void EditorFileSystem::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("get_filesystem:EditorFileSystemDirectory"),&EditorFileSystem::get_filesystem); + ObjectTypeDB::bind_method(_MD("is_scanning"),&EditorFileSystem::is_scanning); + ObjectTypeDB::bind_method(_MD("get_scanning_progress"),&EditorFileSystem::get_scanning_progress); + ObjectTypeDB::bind_method(_MD("scan"),&EditorFileSystem::scan); + ObjectTypeDB::bind_method(_MD("scan_sources"),&EditorFileSystem::scan_sources); + ObjectTypeDB::bind_method(_MD("update_file","path"),&EditorFileSystem::update_file); + ObjectTypeDB::bind_method(_MD("get_path:EditorFileSystemDirectory","path"),&EditorFileSystem::get_path); + ObjectTypeDB::bind_method(_MD("get_file_type","path"),&EditorFileSystem::get_file_type); + ADD_SIGNAL( MethodInfo("filesystem_changed") ); ADD_SIGNAL( MethodInfo("sources_changed",PropertyInfo(Variant::BOOL,"exist")) ); diff --git a/tools/editor/editor_fonts.cpp b/tools/editor/editor_fonts.cpp index 47891eef6c..bcf41cbac8 100644 --- a/tools/editor/editor_fonts.cpp +++ b/tools/editor/editor_fonts.cpp @@ -158,17 +158,10 @@ void editor_register_fonts(Ref<Theme> p_theme) { p_theme->set_font("doc_source","EditorFonts",df_doc_code); - if (editor_is_hidpi()) { - //replace default theme - Ref<Texture> di; - Ref<StyleBox> ds; - fill_default_theme(p_theme,df,df_doc,di,ds,true); + //replace default theme + Ref<Texture> di; + Ref<StyleBox> ds; + fill_default_theme(p_theme,df,df_doc,di,ds,EDSCALE); - } else { - Ref<Texture> di; - Ref<StyleBox> ds; - fill_default_theme(p_theme,df,df_doc,di,ds,false); - - } } diff --git a/tools/editor/editor_help.cpp b/tools/editor/editor_help.cpp index 8f486ba0c2..4f83dc2f66 100644 --- a/tools/editor/editor_help.cpp +++ b/tools/editor/editor_help.cpp @@ -882,6 +882,15 @@ Error EditorHelp::_goto_desc(const String& p_class,int p_vscr) { class_desc->pop(); } + if (cd.methods[i].qualifiers.find("vararg")!=-1) { + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/text_color")); + class_desc->add_text(","); + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/symbol_color")); + class_desc->add_text(" ... "); + class_desc->pop(); + class_desc->pop(); + } + class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/symbol_color")); class_desc->add_text(cd.methods[i].arguments.size()?" )":")"); class_desc->pop(); diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp index 357d139c04..d90a175811 100644 --- a/tools/editor/editor_import_export.cpp +++ b/tools/editor/editor_import_export.cpp @@ -1441,7 +1441,7 @@ bool EditorExportPlatformPC::can_export(String *r_error) const { String err; bool valid=true; - if (use64 && (!exists_export_template(debug_binary64)) || !exists_export_template(release_binary64)) { + if (use64 && (!exists_export_template(debug_binary64) || !exists_export_template(release_binary64))) { valid=false; err="No 64 bits export templates found.\nDownload and install export templates.\n"; } diff --git a/tools/editor/editor_log.cpp b/tools/editor/editor_log.cpp index 20613467d3..02af9712a8 100644 --- a/tools/editor/editor_log.cpp +++ b/tools/editor/editor_log.cpp @@ -161,7 +161,7 @@ void EditorLog::_undo_redo_cbk(void *p_self,const String& p_name) { void EditorLog::_bind_methods() { ObjectTypeDB::bind_method(_MD("_clear_request"),&EditorLog::_clear_request ); - + ObjectTypeDB::bind_method("_override_logger_styles",&EditorLog::_override_logger_styles ); //ObjectTypeDB::bind_method(_MD("_dragged"),&EditorLog::_dragged ); ADD_SIGNAL( MethodInfo("clear_request")); } @@ -193,11 +193,10 @@ EditorLog::EditorLog() { ec->set_custom_minimum_size(Size2(0,180)); ec->set_v_size_flags(SIZE_EXPAND_FILL); - - PanelContainer *pc = memnew( PanelContainer ); - pc->add_style_override("panel",get_stylebox("normal","TextEdit")); + pc = memnew( PanelContainer ); ec->add_child(pc); pc->set_area_as_parent_rect(); + pc->connect("enter_tree", this, "_override_logger_styles"); log = memnew( RichTextLabel ); log->set_scroll_follow(true); @@ -224,6 +223,11 @@ void EditorLog::deinit() { } +void EditorLog::_override_logger_styles() { + + pc->add_style_override("panel",get_stylebox("normal","TextEdit")); + +} EditorLog::~EditorLog() { diff --git a/tools/editor/editor_log.h b/tools/editor/editor_log.h index 699be710d8..bbf35b63cb 100644 --- a/tools/editor/editor_log.h +++ b/tools/editor/editor_log.h @@ -50,6 +50,7 @@ class EditorLog : public VBoxContainer { HBoxContainer *title_hb; // PaneDrag *pd; Control *ec; + PanelContainer *pc; static void _error_handler(void *p_self, const char*p_func, const char*p_file,int p_line, const char*p_error,const char*p_errorexp,ErrorHandlerType p_type); @@ -64,6 +65,7 @@ protected: static void _bind_methods(); void _notification(int p_what); + void _override_logger_styles(); public: void add_message(const String& p_msg, bool p_error=false); diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index f4b67f6e2b..c17cf05ea7 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -176,17 +176,6 @@ void EditorNode::_unhandled_input(const InputEvent& p_event) { if (p_event.type==InputEvent::KEY && p_event.key.pressed && !p_event.key.echo && !gui_base->get_viewport()->gui_has_modal_stack()) { - if (ED_IS_SHORTCUT("editor/fullscreen_mode", p_event)) { - if (distraction_free_mode) { - distraction_free_mode = false; - _update_top_menu_visibility(); - } else { - set_docks_visible(!get_docks_visible()); - } - } - if (ED_IS_SHORTCUT("editor/distraction_free_mode", p_event)) { - set_distraction_free_mode(!get_distraction_free_mode()); - } if (ED_IS_SHORTCUT("editor/next_tab", p_event)) { int next_tab = editor_data.get_edited_scene() + 1; next_tab %= editor_data.get_edited_scene_count(); @@ -277,10 +266,12 @@ void EditorNode::_notification(int p_what) { circle_step=0; circle_step_msec=tick; - circle_step_frame=frame+1; - - update_menu->set_icon(gui_base->get_icon("Progress"+itos(circle_step+1),"EditorIcons")); + circle_step_frame=frame+1; + // update the circle itself only when its enabled + if (!update_menu->get_popup()->is_item_checked(3)){ + update_menu->set_icon(gui_base->get_icon("Progress"+itos(circle_step+1),"EditorIcons")); + } } scene_root->set_size_override(true,Size2(Globals::get_singleton()->get("display/width"),Globals::get_singleton()->get("display/height"))); @@ -785,7 +776,7 @@ bool EditorNode::_find_and_save_resource(RES res,Map<RES,bool>& processed,int32_ if (changed || subchanged) { //save print_line("Also saving modified external resource: "+res->get_path()); - Error err = ResourceSaver::save(res->get_path(),res,flags); + ResourceSaver::save(res->get_path(),res,flags); } processed[res]=false; //because it's a file @@ -1228,7 +1219,8 @@ void EditorNode::_dialog_action(String p_file) { //_save_scene(p_file); _save_scene_with_preview(p_file); - _run(false); + _call_build(); + _run(true); } } break; @@ -1374,6 +1366,7 @@ void EditorNode::_dialog_action(String p_file) { unzClose(pkg); } break; + case RESOURCE_SAVE: case RESOURCE_SAVE_AS: { @@ -2646,6 +2639,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { } break; case RUN_PLAY: { _menu_option_confirm(RUN_STOP,true); + _call_build(); _run(false); } break; @@ -2681,17 +2675,19 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { } break; case RUN_PLAY_SCENE: { _menu_option_confirm(RUN_STOP,true); + _call_build(); _run(true); } break; case RUN_PLAY_NATIVE: { - + bool autosave = EDITOR_DEF("run/auto_save_before_running",true); if (autosave) { _menu_option_confirm(FILE_SAVE_ALL_SCENES, false); } if (run_native->is_deploy_debug_remote_enabled()){ _menu_option_confirm(RUN_STOP,true); + _call_build(); emit_signal("play_pressed"); editor_run.run_native_notify(); } @@ -2803,6 +2799,10 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { update_menu->get_popup()->set_item_checked(1,true); OS::get_singleton()->set_low_processor_usage_mode(true); } break; + case SETTINGS_UPDATE_SPINNER_HIDE: { + update_menu->set_icon(gui_base->get_icon("Collapse","EditorIcons")); + update_menu->get_popup()->toggle_item_checked(3); + } break; case SETTINGS_PREFERENCES: { settings_config_dialog->popup_edit_settings(); @@ -2817,6 +2817,12 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { file_templates->popup_centered_ratio(); } break; + case SETTINGS_TOGGLE_FULLSCREN: { + + OS::get_singleton()->set_window_fullscreen( !OS::get_singleton()->is_window_fullscreen() ); + + + } break; case SETTINGS_PICK_MAIN_SCENE: { @@ -3002,6 +3008,8 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor) { singleton->main_editor_buttons.push_back(tb); singleton->main_editor_button_vb->add_child(tb); singleton->editor_table.push_back(p_editor); + + singleton->distraction_free->raise(); } singleton->editor_data.add_editor_plugin( p_editor ); singleton->add_child(p_editor); @@ -3014,7 +3022,11 @@ void EditorNode::remove_editor_plugin(EditorPlugin *p_editor) { for(int i=0;i<singleton->main_editor_buttons.size();i++) { - if (p_editor->get_name()==singleton->main_editor_buttons[i]->get_name()) { + if (p_editor->get_name()==singleton->main_editor_buttons[i]->get_text()) { + + if (singleton->main_editor_buttons[i]->is_pressed()) { + singleton->_editor_select(EDITOR_SCRIPT); + } memdelete( singleton->main_editor_buttons[i] ); singleton->main_editor_buttons.remove(i); @@ -4044,6 +4056,7 @@ void EditorNode::_quick_opened() { void EditorNode::_quick_run() { + _call_build(); _run(false,quick_run->get_selected()); } @@ -4139,6 +4152,11 @@ void EditorNode::register_editor_types() { //ObjectTypeDB::register_type<EditorImportExport>(); ObjectTypeDB::register_type<EditorSettings>(); ObjectTypeDB::register_type<EditorSpatialGizmo>(); + ObjectTypeDB::register_type<EditorResourcePreview>(); + ObjectTypeDB::register_type<EditorResourcePreviewGenerator>(); + ObjectTypeDB::register_type<EditorFileSystem>(); + ObjectTypeDB::register_type<EditorFileSystemDirectory>(); + //ObjectTypeDB::register_type<EditorImporter>(); @@ -4602,7 +4620,10 @@ void EditorNode::_update_dock_slots_visibility() { } void EditorNode::_update_top_menu_visibility() { - if (distraction_free_mode) { + + return; // I think removing top menu is too much + /* + if (distraction_free->is_pressed()) { play_cc->hide(); menu_hb->hide(); scene_tabs->hide(); @@ -4610,7 +4631,7 @@ void EditorNode::_update_top_menu_visibility() { play_cc->show(); menu_hb->show(); scene_tabs->show(); - } + }*/ } void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String& p_section) { @@ -4986,8 +5007,14 @@ bool EditorNode::get_docks_visible() const { return docks_visible; } +void EditorNode::_toggle_distraction_free_mode() { + + set_distraction_free_mode( distraction_free->is_pressed() ); +} + void EditorNode::set_distraction_free_mode(bool p_enter) { - distraction_free_mode = p_enter; + + distraction_free->set_pressed(p_enter); if (p_enter) { if (docks_visible) { @@ -5000,7 +5027,7 @@ void EditorNode::set_distraction_free_mode(bool p_enter) { } bool EditorNode::get_distraction_free_mode() const { - return distraction_free_mode; + return distraction_free->is_pressed(); } void EditorNode::add_control_to_dock(DockSlot p_slot,Control* p_control) { @@ -5232,6 +5259,24 @@ void EditorNode::add_plugin_init_callback(EditorPluginInitializeCallback p_callb EditorPluginInitializeCallback EditorNode::plugin_init_callbacks[EditorNode::MAX_INIT_CALLBACKS]; +int EditorNode::build_callback_count=0; + +void EditorNode::add_build_callback(EditorBuildCallback p_callback) { + + ERR_FAIL_COND(build_callback_count==MAX_INIT_CALLBACKS); + + build_callbacks[build_callback_count++]=p_callback; +} + +EditorPluginInitializeCallback EditorNode::build_callbacks[EditorNode::MAX_BUILD_CALLBACKS]; + +void EditorNode::_call_build() { + + for(int i=0;i<build_callback_count;i++) { + build_callbacks[i](); + } +} + void EditorNode::_bind_methods() { @@ -5300,6 +5345,7 @@ void EditorNode::_bind_methods() { ObjectTypeDB::bind_method("_clear_search_box",&EditorNode::_clear_search_box); ObjectTypeDB::bind_method("_clear_undo_history",&EditorNode::_clear_undo_history); ObjectTypeDB::bind_method("_dropped_files",&EditorNode::_dropped_files); + ObjectTypeDB::bind_method("_toggle_distraction_free_mode",&EditorNode::_toggle_distraction_free_mode); @@ -5344,7 +5390,7 @@ EditorNode::EditorNode() { changing_scene=false; _initializing_addons=false; docks_visible = true; - distraction_free_mode=false; + FileAccess::set_backup_save(true); @@ -5353,19 +5399,27 @@ EditorNode::EditorNode() { // load settings if (!EditorSettings::get_singleton()) EditorSettings::create(); + + bool use_single_dock_column = false; { int dpi_mode = EditorSettings::get_singleton()->get("global/hidpi_mode"); if (dpi_mode==0) { - editor_set_hidpi( OS::get_singleton()->get_screen_dpi(0) > 150 ); + editor_set_scale( OS::get_singleton()->get_screen_dpi(0) > 150 && OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x>2000 ? 2.0 : 1.0 ); + + use_single_dock_column = OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x<1200; + + } else if (dpi_mode==1) { + editor_set_scale(0.75); } else if (dpi_mode==2) { - editor_set_hidpi(true); - } else { - editor_set_hidpi(false); + editor_set_scale(1.0); + } else if (dpi_mode==3) { + editor_set_scale(1.5); + } else if (dpi_mode==4) { + editor_set_scale(2.0); } } - ResourceLoader::set_abort_on_missing_resources(false); FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files")); EditorFileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files")); @@ -5414,9 +5468,9 @@ EditorNode::EditorNode() { theme_base->add_child(gui_base); gui_base->set_area_as_parent_rect(); - theme_base->set_theme( create_default_theme() ); - theme = create_editor_theme(); - gui_base->set_theme(theme); + Ref<Theme> theme = create_editor_theme(); + theme_base->set_theme( theme ); + gui_base->set_theme(create_custom_theme()); resource_preview = memnew( EditorResourcePreview ); add_child(resource_preview); @@ -5672,8 +5726,6 @@ EditorNode::EditorNode() { prev_scene->set_pos(Point2(3,24)); prev_scene->hide(); - ED_SHORTCUT("editor/fullscreen_mode",TTR("Fullscreen Mode"),KEY_MASK_SHIFT|KEY_F11); - ED_SHORTCUT("editor/distraction_free_mode",TTR("Distraction Free Mode"),KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_F11); ED_SHORTCUT("editor/next_tab", TTR("Next tab"), KEY_MASK_CMD+KEY_TAB); @@ -5744,6 +5796,13 @@ EditorNode::EditorNode() { editor_region->add_child(main_editor_button_vb); menu_hb->add_child(editor_region); + distraction_free = memnew( ToolButton ); + main_editor_button_vb->add_child(distraction_free); + distraction_free->set_shortcut( ED_SHORTCUT("editor/distraction_free_mode",TTR("Distraction Free Mode"),KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_F11) ); + distraction_free->connect("pressed",this,"_toggle_distraction_free_mode"); + distraction_free->set_icon(gui_base->get_icon("DistractionFree","EditorIcons")); + distraction_free->set_toggle_mode(true); + //menu_hb->add_spacer(); #if 0 node_menu = memnew( MenuButton ); @@ -5984,6 +6043,9 @@ EditorNode::EditorNode() { p->add_child(editor_layouts); editor_layouts->connect("item_pressed",this,"_layout_menu_option"); p->add_submenu_item(TTR("Editor Layout"), "Layouts"); + + p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode",TTR("Toggle Fullscreen"),KEY_MASK_SHIFT|KEY_F11),SETTINGS_TOGGLE_FULLSCREN); + p->add_separator(); p->add_item(TTR("Install Export Templates"),SETTINGS_LOAD_EXPORT_TEMPLATES); p->add_separator(); @@ -6008,6 +6070,8 @@ EditorNode::EditorNode() { p=update_menu->get_popup(); p->add_check_item(TTR("Update Always"),SETTINGS_UPDATE_ALWAYS); p->add_check_item(TTR("Update Changes"),SETTINGS_UPDATE_CHANGES); + p->add_separator(); + p->add_check_item(TTR("Disable Update Spinner"),SETTINGS_UPDATE_SPINNER_HIDE); p->set_item_checked(1,true); //sources_button->connect(); @@ -6176,12 +6240,24 @@ EditorNode::EditorNode() { node_dock = memnew( NodeDock ); //node_dock->set_undoredo(&editor_data.get_undo_redo()); - dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(node_dock); + if (use_single_dock_column) { + dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(node_dock); + } else { + dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(node_dock); + } scenes_dock = memnew( FileSystemDock(this) ); scenes_dock->set_name(TTR("FileSystem")); scenes_dock->set_display_mode(int(EditorSettings::get_singleton()->get("filesystem_dock/display_mode"))); - dock_slot[DOCK_SLOT_LEFT_UR]->add_child(scenes_dock); + + if (use_single_dock_column) { + dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(scenes_dock); + left_r_vsplit->hide(); + dock_slot[DOCK_SLOT_LEFT_UR]->hide(); + dock_slot[DOCK_SLOT_LEFT_BR]->hide(); + } else { + dock_slot[DOCK_SLOT_LEFT_UR]->add_child(scenes_dock); + } //prop_pallete->add_child(scenes_dock); scenes_dock->connect("open",this,"open_request"); scenes_dock->connect("instance",this,"_instance_request"); @@ -6190,9 +6266,9 @@ EditorNode::EditorNode() { overridden_default_layout=-1; default_layout.instance(); - default_layout->set_value(docks_section, "dock_3", TTR("Scene")); - default_layout->set_value(docks_section, "dock_4", TTR("FileSystem")); - default_layout->set_value(docks_section, "dock_5", TTR("Inspector")); + default_layout->set_value(docks_section, "dock_3", TTR("FileSystem")); + default_layout->set_value(docks_section, "dock_5", TTR("Scene")); + default_layout->set_value(docks_section, "dock_6", TTR("Inspector")+","+TTR("Node")); for(int i=0;i<DOCK_SLOT_MAX/2;i++) default_layout->set_value(docks_section, "dock_hsplit_"+itos(i+1), 0); @@ -6543,11 +6619,6 @@ EditorNode::EditorNode() { Globals::get_singleton()->set("debug/indicators_enabled",true); Globals::get_singleton()->set("render/room_cull_enabled",false); - theme->set_color("prop_category","Editor",Color::hex(0x3f3a44ff)); - theme->set_color("prop_section","Editor",Color::hex(0x35313aff)); - theme->set_color("prop_subsection","Editor",Color::hex(0x312e37ff)); - theme->set_color("fg_selected","Editor",Color::html("ffbd8e8e")); - theme->set_color("fg_error","Editor",Color::html("ffbd8e8e")); reference_resource_mem=true; save_external_resources_mem=true; @@ -6684,45 +6755,54 @@ EditorNode::~EditorNode() { void EditorPluginList::make_visible(bool p_visible) { - if (!plugins_list.empty()) { - for (int i = 0; i < plugins_list.size(); i++) { - plugins_list[i]->make_visible(p_visible); - } + + for (int i = 0; i < plugins_list.size(); i++) { + plugins_list[i]->make_visible(p_visible); } + } void EditorPluginList::edit(Object* p_object) { - if (!plugins_list.empty()) { - for (int i = 0; i < plugins_list.size(); i++) { - plugins_list[i]->edit(p_object); - } + + for (int i = 0; i < plugins_list.size(); i++) { + plugins_list[i]->edit(p_object); } + } -bool EditorPluginList::forward_input_event(const InputEvent& p_event) { +bool EditorPluginList::forward_input_event(const Matrix32& p_canvas_xform,const InputEvent& p_event) { + bool discard = false; - if (!plugins_list.empty()) { - for (int i = 0; i < plugins_list.size(); i++) { - if (plugins_list[i]->forward_input_event(p_event)) { - discard = true; - } + + for (int i = 0; i < plugins_list.size(); i++) { + if (plugins_list[i]->forward_canvas_input_event(p_canvas_xform,p_event)) { + discard = true; } } + return discard; } bool EditorPluginList::forward_spatial_input_event(Camera* p_camera, const InputEvent& p_event) { bool discard = false; - if (!plugins_list.empty()) { - for (int i = 0; i < plugins_list.size(); i++) { - if (plugins_list[i]->forward_spatial_input_event(p_camera, p_event)) { - discard = true; - } + + for (int i = 0; i < plugins_list.size(); i++) { + if (plugins_list[i]->forward_spatial_input_event(p_camera, p_event)) { + discard = true; } } + return discard; } +void EditorPluginList::forward_draw_over_canvas(const Matrix32& p_canvas_xform,Control* p_canvas) { + + for (int i = 0; i < plugins_list.size(); i++) { + plugins_list[i]->forward_draw_over_canvas(p_canvas_xform,p_canvas); + } + +} + bool EditorPluginList::empty() { return plugins_list.empty(); } diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index e6119cf577..6392b96f8f 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -95,6 +95,7 @@ typedef void (*EditorNodeInitCallback)(); typedef void (*EditorPluginInitializeCallback)(); +typedef void (*EditorBuildCallback)(); class EditorPluginList; @@ -178,6 +179,7 @@ private: RUN_RELOAD_SCRIPTS, SETTINGS_UPDATE_ALWAYS, SETTINGS_UPDATE_CHANGES, + SETTINGS_UPDATE_SPINNER_HIDE, SETTINGS_EXPORT_PREFERENCES, SETTINGS_PREFERENCES, SETTINGS_OPTIMIZED_PRESETS, @@ -186,6 +188,7 @@ private: SETTINGS_LAYOUT_DEFAULT, SETTINGS_LOAD_EXPORT_TEMPLATES, SETTINGS_PICK_MAIN_SCENE, + SETTINGS_TOGGLE_FULLSCREN, SETTINGS_HELP, SETTINGS_ABOUT, SOURCES_REIMPORT, @@ -356,7 +359,7 @@ private: int dock_popup_selected; Timer *dock_drag_timer; bool docks_visible; - bool distraction_free_mode; + ToolButton *distraction_free; String _tmp_import_path; @@ -576,13 +579,21 @@ private: static void _file_access_close_error_notify(const String& p_str); + void _toggle_distraction_free_mode(); enum { - MAX_INIT_CALLBACKS=128 + MAX_INIT_CALLBACKS=128, + MAX_BUILD_CALLBACKS=128 }; + + static int plugin_init_callback_count; static EditorPluginInitializeCallback plugin_init_callbacks[MAX_INIT_CALLBACKS]; + + void _call_build(); + static int build_callback_count; + static EditorBuildCallback build_callbacks[MAX_BUILD_CALLBACKS]; protected: void _notification(int p_what); static void _bind_methods(); @@ -690,6 +701,7 @@ public: void notify_child_process_exited(); + OS::ProcessID get_child_process_id() const { return editor_run.get_pid(); } void stop_child_process(); Ref<Theme> get_editor_theme() const { return theme; } @@ -750,6 +762,7 @@ public: void get_singleton(const char* arg1, bool arg2); static void add_init_callback(EditorNodeInitCallback p_callback) { _init_callbacks.push_back(p_callback); } + static void add_build_callback(EditorBuildCallback p_callback); @@ -780,8 +793,9 @@ public: void make_visible(bool p_visible); void edit(Object *p_object); - bool forward_input_event(const InputEvent& p_event); + bool forward_input_event(const Matrix32& p_canvas_xform,const InputEvent& p_event); bool forward_spatial_input_event(Camera* p_camera, const InputEvent& p_event); + void forward_draw_over_canvas(const Matrix32& p_canvas_xform,Control* p_canvas); void clear(); bool empty(); diff --git a/tools/editor/editor_plugin.cpp b/tools/editor/editor_plugin.cpp index 5e671549ef..4b82d5e59c 100644 --- a/tools/editor/editor_plugin.cpp +++ b/tools/editor/editor_plugin.cpp @@ -32,6 +32,7 @@ #include "plugins/spatial_editor_plugin.h" #include "tools/editor/editor_node.h" #include "tools/editor/editor_settings.h" +#include "editor_resource_preview.h" void EditorPlugin::add_custom_type(const String& p_type, const String& p_base,const Ref<Script>& p_script, const Ref<Texture>& p_icon) { @@ -70,6 +71,11 @@ void EditorPlugin::remove_control_from_bottom_panel(Control *p_control) { } +Control * EditorPlugin::get_editor_viewport() { + + return EditorNode::get_singleton()->get_viewport(); +} + void EditorPlugin::add_control_to_container(CustomControlContainer p_location,Control *p_control) { switch(p_location) { @@ -130,13 +136,25 @@ Ref<SpatialEditorGizmo> EditorPlugin::create_spatial_gizmo(Spatial* p_spatial) { return Ref<SpatialEditorGizmo>(); } -bool EditorPlugin::forward_input_event(const InputEvent& p_event) { +bool EditorPlugin::forward_canvas_input_event(const Matrix32& p_canvas_xform,const InputEvent& p_event) { - if (get_script_instance() && get_script_instance()->has_method("forward_input_event")) { - return get_script_instance()->call("forward_input_event",p_event); + if (get_script_instance() && get_script_instance()->has_method("forward_canvas_input_event")) { + return get_script_instance()->call("forward_canvas_input_event",p_canvas_xform,p_event); } return false; } + +void EditorPlugin::forward_draw_over_canvas(const Matrix32& p_canvas_xform,Control *p_canvas) { + + if (get_script_instance() && get_script_instance()->has_method("forward_draw_over_canvas")) { + get_script_instance()->call("forward_draw_over_canvas",p_canvas_xform,p_canvas); + } +} + +void EditorPlugin::update_canvas() { + CanvasItemEditor::get_singleton()->get_viewport_control()->update(); +} + bool EditorPlugin::forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event) { if (get_script_instance() && get_script_instance()->has_method("forward_spatial_input_event")) { @@ -272,6 +290,10 @@ EditorSettings *EditorPlugin::get_editor_settings() { return EditorSettings::get_singleton(); } +EditorResourcePreview *EditorPlugin::get_resource_previewer() { + return EditorResourcePreview::get_singleton(); +} + void EditorPlugin::add_import_plugin(const Ref<EditorImportPlugin>& p_editor_import) { EditorNode::get_singleton()->add_editor_import_plugin(p_editor_import); @@ -298,6 +320,24 @@ Control *EditorPlugin::get_base_control() { return EditorNode::get_singleton()->get_gui_base(); } +void EditorPlugin::make_bottom_panel_item_visible(Control * p_item) { + + EditorNode::get_singleton()->make_bottom_panel_item_visible(p_item); +} + +void EditorPlugin::hide_bottom_panel() { + + EditorNode::get_singleton()->hide_bottom_panel(); +} + +void EditorPlugin::inspect_object(Object *p_obj,const String& p_for_property) { + + EditorNode::get_singleton()->push_item(p_obj,p_for_property); +} + +EditorFileSystem *EditorPlugin::get_resource_file_system() { + return EditorFileSystem::get_singleton(); +} void EditorPlugin::_bind_methods() { @@ -308,6 +348,7 @@ void EditorPlugin::_bind_methods() { ObjectTypeDB::bind_method(_MD("remove_control_from_bottom_panel","control:Control"),&EditorPlugin::remove_control_from_bottom_panel); ObjectTypeDB::bind_method(_MD("add_custom_type","type","base","script:Script","icon:Texture"),&EditorPlugin::add_custom_type); ObjectTypeDB::bind_method(_MD("remove_custom_type","type"),&EditorPlugin::remove_custom_type); + ObjectTypeDB::bind_method(_MD("get_editor_viewport:Control"), &EditorPlugin::get_editor_viewport); ObjectTypeDB::bind_method(_MD("add_import_plugin","plugin:EditorImportPlugin"),&EditorPlugin::add_import_plugin); ObjectTypeDB::bind_method(_MD("remove_import_plugin","plugin:EditorImportPlugin"),&EditorPlugin::remove_import_plugin); @@ -315,6 +356,14 @@ void EditorPlugin::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_export_plugin","plugin:EditorExportPlugin"),&EditorPlugin::add_export_plugin); ObjectTypeDB::bind_method(_MD("remove_export_plugin","plugin:EditorExportPlugin"),&EditorPlugin::remove_export_plugin); + ObjectTypeDB::bind_method(_MD("get_resource_previewer:EditorResourcePreview"),&EditorPlugin::get_resource_previewer); + ObjectTypeDB::bind_method(_MD("get_resource_filesystem:EditorFileSystem"),&EditorPlugin::get_resource_file_system); + + ObjectTypeDB::bind_method(_MD("inspect_object","object","for_property"),&EditorPlugin::inspect_object,DEFVAL(String())); + ObjectTypeDB::bind_method(_MD("update_canvas"),&EditorPlugin::update_canvas); + + ObjectTypeDB::bind_method(_MD("make_bottom_panel_item_visible","item:Control"), &EditorPlugin::make_bottom_panel_item_visible); + ObjectTypeDB::bind_method(_MD("hide_bottom_panel"), &EditorPlugin::hide_bottom_panel); ObjectTypeDB::bind_method(_MD("get_base_control:Control"),&EditorPlugin::get_base_control); ObjectTypeDB::bind_method(_MD("get_undo_redo:UndoRedo"),&EditorPlugin::_get_undo_redo); @@ -322,7 +371,8 @@ void EditorPlugin::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_editor_settings:EditorSettings"),&EditorPlugin::get_editor_settings); ObjectTypeDB::bind_method(_MD("queue_save_layout"),&EditorPlugin::queue_save_layout); - ObjectTypeDB::add_virtual_method(get_type_static(),MethodInfo(Variant::BOOL,"forward_input_event",PropertyInfo(Variant::INPUT_EVENT,"event"))); + ObjectTypeDB::add_virtual_method(get_type_static(),MethodInfo(Variant::BOOL,"forward_canvas_input_event",PropertyInfo(Variant::MATRIX32,"canvas_xform"),PropertyInfo(Variant::INPUT_EVENT,"event"))); + ObjectTypeDB::add_virtual_method(get_type_static(),MethodInfo("forward_draw_over_canvas",PropertyInfo(Variant::MATRIX32,"canvas_xform"),PropertyInfo(Variant::OBJECT,"canvas:Control"))); ObjectTypeDB::add_virtual_method(get_type_static(),MethodInfo(Variant::BOOL,"forward_spatial_input_event",PropertyInfo(Variant::OBJECT,"camera",PROPERTY_HINT_RESOURCE_TYPE,"Camera"),PropertyInfo(Variant::INPUT_EVENT,"event"))); MethodInfo gizmo = MethodInfo(Variant::OBJECT,"create_spatial_gizmo",PropertyInfo(Variant::OBJECT,"for_spatial:Spatial")); gizmo.return_val.hint=PROPERTY_HINT_RESOURCE_TYPE; diff --git a/tools/editor/editor_plugin.h b/tools/editor/editor_plugin.h index 9a9c32357d..2700c49a6c 100644 --- a/tools/editor/editor_plugin.h +++ b/tools/editor/editor_plugin.h @@ -34,6 +34,7 @@ #include "scene/resources/texture.h" #include "undo_redo.h" #include "io/config_file.h" + /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -47,6 +48,8 @@ class EditorSettings; class SpatialEditorGizmo; class EditorImportPlugin; class EditorExportPlugin; +class EditorResourcePreview; +class EditorFileSystem; class EditorPlugin : public Node { @@ -97,9 +100,11 @@ public: void add_control_to_dock(DockSlot p_slot,Control *p_control); void remove_control_from_docks(Control *p_control); void remove_control_from_bottom_panel(Control *p_control); + Control* get_editor_viewport(); virtual Ref<SpatialEditorGizmo> create_spatial_gizmo(Spatial* p_spatial); - virtual bool forward_input_event(const InputEvent& p_event); + virtual bool forward_canvas_input_event(const Matrix32& p_canvas_xform, const InputEvent& p_event); + virtual void forward_draw_over_canvas(const Matrix32& p_canvas_xform,Control *p_canvas); virtual bool forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event); virtual String get_name() const; virtual bool has_main_screen() const; @@ -116,12 +121,19 @@ public: virtual bool get_remove_list(List<Node*> *p_list); virtual void set_window_layout(Ref<ConfigFile> p_layout); virtual void get_window_layout(Ref<ConfigFile> p_layout); - virtual void edited_scene_changed(){}; // if changes are pending in editor, apply them + virtual void edited_scene_changed(){} // if changes are pending in editor, apply them + + void update_canvas(); + + virtual void inspect_object(Object *p_obj,const String& p_for_property=String()); void queue_save_layout() const; Control *get_base_control(); + void make_bottom_panel_item_visible(Control *p_item); + void hide_bottom_panel(); + void add_import_plugin(const Ref<EditorImportPlugin>& p_editor_import); void remove_import_plugin(const Ref<EditorImportPlugin>& p_editor_import); @@ -131,6 +143,8 @@ public: EditorSelection* get_selection(); //EditorImportExport *get_import_export(); EditorSettings *get_editor_settings(); + EditorResourcePreview *get_resource_previewer(); + EditorFileSystem *get_resource_file_system(); virtual void restore_global_state(); virtual void save_global_state(); diff --git a/tools/editor/editor_resource_preview.cpp b/tools/editor/editor_resource_preview.cpp index a02fe2a531..6afc3e2a34 100644 --- a/tools/editor/editor_resource_preview.cpp +++ b/tools/editor/editor_resource_preview.cpp @@ -35,14 +35,46 @@ #include "editor_scale.h" #include "message_queue.h" +bool EditorResourcePreviewGenerator::handles(const String& p_type) const { + + if (get_script_instance() && get_script_instance()->has_method("handles")) { + return get_script_instance()->call("handles",p_type); + } + ERR_EXPLAIN("EditorResourcePreviewGenerator::handles needs to be overriden"); + ERR_FAIL_V(false); +} +Ref<Texture> EditorResourcePreviewGenerator::generate(const RES& p_from){ + + if (get_script_instance() && get_script_instance()->has_method("generate")) { + return get_script_instance()->call("generate",p_from); + } + ERR_EXPLAIN("EditorResourcePreviewGenerator::generate needs to be overriden"); + ERR_FAIL_V(Ref<Texture>()); + +} + + Ref<Texture> EditorResourcePreviewGenerator::generate_from_path(const String& p_path) { + if (get_script_instance() && get_script_instance()->has_method("generate_from_path")) { + return get_script_instance()->call("generate_from_path",p_path); + } + RES res = ResourceLoader::load(p_path); if (!res.is_valid()) return res; return generate(res); } + +void EditorResourcePreviewGenerator::_bind_methods() { + + ObjectTypeDB::add_virtual_method(get_type_static(),MethodInfo(Variant::BOOL,"handles",PropertyInfo(Variant::STRING,"type"))); + ObjectTypeDB::add_virtual_method(get_type_static(),MethodInfo(Variant::OBJECT,"generate:Texture",PropertyInfo(Variant::OBJECT,"from",PROPERTY_HINT_RESOURCE_TYPE,"Resource"))); + ObjectTypeDB::add_virtual_method(get_type_static(),MethodInfo(Variant::OBJECT,"generate_from_path:Texture",PropertyInfo(Variant::STRING,"path",PROPERTY_HINT_FILE))); + +} + EditorResourcePreviewGenerator::EditorResourcePreviewGenerator() { @@ -330,6 +362,11 @@ void EditorResourcePreview::add_preview_generator(const Ref<EditorResourcePrevie preview_generators.push_back(p_generator); } +void EditorResourcePreview::remove_preview_generator(const Ref<EditorResourcePreviewGenerator>& p_generator) { + + preview_generators.erase(p_generator); +} + EditorResourcePreview* EditorResourcePreview::get_singleton() { return singleton; @@ -338,6 +375,11 @@ EditorResourcePreview* EditorResourcePreview::get_singleton() { void EditorResourcePreview::_bind_methods() { ObjectTypeDB::bind_method("_preview_ready",&EditorResourcePreview::_preview_ready); + + ObjectTypeDB::bind_method(_MD("queue_resource_preview","path","receiver","receiver_func","userdata:Variant"),&EditorResourcePreview::queue_resource_preview); + ObjectTypeDB::bind_method(_MD("queue_edited_resource_preview","resource:Resource","receiver","receiver_func","userdata:Variant"),&EditorResourcePreview::queue_edited_resource_preview); + ObjectTypeDB::bind_method(_MD("add_preview_generator","generator:EditorResourcePreviewGenerator"),&EditorResourcePreview::add_preview_generator); + ObjectTypeDB::bind_method(_MD("remove_preview_generator","generator:EditorResourcePreviewGenerator"),&EditorResourcePreview::remove_preview_generator); ObjectTypeDB::bind_method(_MD("check_for_invalidation","path"),&EditorResourcePreview::check_for_invalidation); diff --git a/tools/editor/editor_resource_preview.h b/tools/editor/editor_resource_preview.h index 51a00965eb..2756360130 100644 --- a/tools/editor/editor_resource_preview.h +++ b/tools/editor/editor_resource_preview.h @@ -57,10 +57,13 @@ class EditorResourcePreviewGenerator : public Reference { OBJ_TYPE(EditorResourcePreviewGenerator,Reference ); +protected: + + static void _bind_methods(); public: - virtual bool handles(const String& p_type) const=0; - virtual Ref<Texture> generate(const RES& p_from)=0; + virtual bool handles(const String& p_type) const; + virtual Ref<Texture> generate(const RES& p_from); virtual Ref<Texture> generate_from_path(const String& p_path); EditorResourcePreviewGenerator(); @@ -121,6 +124,7 @@ public: void queue_edited_resource_preview(const Ref<Resource>& p_path, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata); void add_preview_generator(const Ref<EditorResourcePreviewGenerator>& p_generator); + void remove_preview_generator(const Ref<EditorResourcePreviewGenerator>& p_generator); void check_for_invalidation(const String& p_path); EditorResourcePreview(); diff --git a/tools/editor/editor_run.cpp b/tools/editor/editor_run.cpp index fb0f24c084..5fbb4ae2a0 100644 --- a/tools/editor/editor_run.cpp +++ b/tools/editor/editor_run.cpp @@ -52,6 +52,9 @@ Error EditorRun::run(const String& p_scene,const String p_custom_args,const List args.push_back("localhost:"+String::num(GLOBAL_DEF("debug/debug_port", 6007))); } + args.push_back("-epid"); + args.push_back(String::num(OS::get_singleton()->get_process_ID())); + if (p_custom_args!="") { Vector<String> cargs=p_custom_args.split(" ",false); @@ -132,6 +135,7 @@ Error EditorRun::run(const String& p_scene,const String p_custom_args,const List } + if (p_breakpoints.size()) { args.push_back("-bp"); diff --git a/tools/editor/editor_run.h b/tools/editor/editor_run.h index 0b96a2c91c..5aa2adf801 100644 --- a/tools/editor/editor_run.h +++ b/tools/editor/editor_run.h @@ -53,6 +53,8 @@ public: void run_native_notify() { status=STATUS_PLAY; } void stop(); + OS::ProcessID get_pid() const { return pid; } + void set_debug_collisions(bool p_debug); bool get_debug_collisions() const; diff --git a/tools/editor/editor_scale.cpp b/tools/editor/editor_scale.cpp index c332acc0ca..8575e1c30a 100644 --- a/tools/editor/editor_scale.cpp +++ b/tools/editor/editor_scale.cpp @@ -1,14 +1,13 @@ #include "editor_scale.h" #include "os/os.h" -static bool editor_hidpi=false; +static float scale = 1.0; -void editor_set_hidpi(bool p_hidpi) { +void editor_set_scale(float p_scale) { - editor_hidpi=p_hidpi; + scale=p_scale; } +float editor_get_scale() { -bool editor_is_hidpi() { - - return editor_hidpi; + return scale; } diff --git a/tools/editor/editor_scale.h b/tools/editor/editor_scale.h index a60cf00f0a..90e575f771 100644 --- a/tools/editor/editor_scale.h +++ b/tools/editor/editor_scale.h @@ -1,8 +1,8 @@ #ifndef EDITOR_SCALE_H #define EDITOR_SCALE_H -void editor_set_hidpi(bool p_hidpi); -bool editor_is_hidpi(); +void editor_set_scale(float p_scale); +float editor_get_scale(); -#define EDSCALE (editor_is_hidpi() ? 2 : 1) +#define EDSCALE (editor_get_scale()) #endif // EDITOR_SCALE_H diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp index 99c80fdc36..f5741c4a9e 100644 --- a/tools/editor/editor_settings.cpp +++ b/tools/editor/editor_settings.cpp @@ -511,7 +511,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { } set("global/hidpi_mode",0); - hints["global/hidpi_mode"]=PropertyInfo(Variant::INT,"global/hidpi_mode",PROPERTY_HINT_ENUM,"Auto,LoDPI,HiDPI",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED); + hints["global/hidpi_mode"]=PropertyInfo(Variant::INT,"global/hidpi_mode",PROPERTY_HINT_ENUM,"Auto,VeryLoDPI,LoDPI,MidDPI,HiDPI",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED); set("global/show_script_in_scene_tabs",false); set("global/font_size",14); hints["global/font_size"]=PropertyInfo(Variant::INT,"global/font_size",PROPERTY_HINT_RANGE,"10,40,1",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED); @@ -546,9 +546,15 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { hints["text_editor/tab_size"]=PropertyInfo(Variant::INT,"text_editor/tab_size",PROPERTY_HINT_RANGE,"1, 64, 1"); // size of 0 crashes. set("text_editor/draw_tabs", true); + set("text_editor/line_numbers_zero_padded", false); + set("text_editor/show_line_numbers", true); set("text_editor/show_breakpoint_gutter", true); + set("text_editor/show_line_length_guideline", false); + set("text_editor/line_length_guideline_column", 80); + hints["text_editor/line_length_guideline_column"]=PropertyInfo(Variant::INT,"text_editor/line_length_guideline_column",PROPERTY_HINT_RANGE,"20, 160, 10"); + set("text_editor/trim_trailing_whitespace_on_save", false); set("text_editor/idle_parse_delay",2); set("text_editor/create_signal_callbacks",true); @@ -565,8 +571,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { set("text_editor/restore_scripts_on_load",true); - set("scenetree_editor/duplicate_node_name_num_separator",0); - hints["scenetree_editor/duplicate_node_name_num_separator"]=PropertyInfo(Variant::INT,"scenetree_editor/duplicate_node_name_num_separator",PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash"); //set("scenetree_editor/display_old_action_buttons",false); set("scenetree_editor/start_create_dialog_fully_expanded",false); set("scenetree_editor/draw_relationship_lines",false); @@ -574,6 +578,9 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { set("grid_map/pick_distance", 5000.0); + set("3d_editor/grid_color",Color(0,1,0,0.2)); + hints["3d_editor/grid_color"]=PropertyInfo(Variant::COLOR,"3d_editor/grid_color", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED); + set("3d_editor/default_fov",45.0); set("3d_editor/default_z_near",0.1); set("3d_editor/default_z_far",500.0); @@ -1019,6 +1026,34 @@ void EditorSettings::set_optimize_save(bool p_optimize) { optimize_save=p_optimize; } +String EditorSettings::get_last_selected_language() +{ + Ref<ConfigFile> cf = memnew( ConfigFile ); + String path = get_project_settings_path().plus_file("project_metadata.cfg"); + Error err = cf->load(path); + if (err != OK) { + WARN_PRINTS("Can't load config file: " + path); + return ""; + } + Variant last_selected_language = cf->get_value("script_setup", "last_selected_language"); + if (last_selected_language.get_type() != Variant::STRING) + return ""; + return static_cast<String>(last_selected_language); +} + +void EditorSettings::set_last_selected_language(String p_language) +{ + Ref<ConfigFile> cf = memnew( ConfigFile ); + String path = get_project_settings_path().plus_file("project_metadata.cfg"); + Error err = cf->load(path); + if (err != OK) { + WARN_PRINTS("Can't load config file: " + path); + return; + } + cf->set_value("script_setup", "last_selected_language", p_language); + cf->save(path); +} + void EditorSettings::_bind_methods() { ObjectTypeDB::bind_method(_MD("erase","property"),&EditorSettings::erase); diff --git a/tools/editor/editor_settings.h b/tools/editor/editor_settings.h index 2a7d3bb4f0..a976602304 100644 --- a/tools/editor/editor_settings.h +++ b/tools/editor/editor_settings.h @@ -160,6 +160,9 @@ public: void set_optimize_save(bool p_optimize); + String get_last_selected_language(); + void set_last_selected_language(String p_language); + EditorSettings(); ~EditorSettings(); diff --git a/tools/editor/editor_themes.cpp b/tools/editor/editor_themes.cpp index 44e21aee85..08f14ec167 100644 --- a/tools/editor/editor_themes.cpp +++ b/tools/editor/editor_themes.cpp @@ -32,8 +32,9 @@ #include "editor_fonts.h" #include "editor_settings.h" #include "core/io/resource_loader.h" +#include "editor_scale.h" -Ref<Theme> create_default_theme() +Ref<Theme> create_editor_theme() { Ref<Theme> theme = Ref<Theme>( memnew( Theme ) ); @@ -43,32 +44,36 @@ Ref<Theme> create_default_theme() Ref<StyleBoxTexture> focus_sbt=memnew( StyleBoxTexture ); focus_sbt->set_texture(theme->get_icon("EditorFocus","EditorIcons")); for(int i=0;i<4;i++) { - focus_sbt->set_margin_size(Margin(i),16); - focus_sbt->set_default_margin(Margin(i),16); + focus_sbt->set_margin_size(Margin(i),16*EDSCALE); + focus_sbt->set_default_margin(Margin(i),16*EDSCALE); } focus_sbt->set_draw_center(false); theme->set_stylebox("EditorFocus","EditorStyles",focus_sbt); + theme->set_color("prop_category","Editor",Color::hex(0x3f3a44ff)); + theme->set_color("prop_section","Editor",Color::hex(0x35313aff)); + theme->set_color("prop_subsection","Editor",Color::hex(0x312e37ff)); + theme->set_color("fg_selected","Editor",Color::html("ffbd8e8e")); + theme->set_color("fg_error","Editor",Color::html("ffbd8e8e")); return theme; } -Ref<Theme> create_editor_theme() +Ref<Theme> create_custom_theme() { - Ref<Theme> theme = NULL; + Ref<Theme> theme; String custom_theme = EditorSettings::get_singleton()->get("global/custom_theme"); if (custom_theme!="") { theme = ResourceLoader::load(custom_theme); } - if (theme.is_null() || !theme.is_valid()) { - theme = create_default_theme(); - } - String global_font = EditorSettings::get_singleton()->get("global/custom_font"); if (global_font!="") { Ref<Font> fnt = ResourceLoader::load(global_font); if (fnt.is_valid()) { + if (!theme.is_valid()) { + theme.instance(); + } theme->set_default_theme_font(fnt); } } diff --git a/tools/editor/editor_themes.h b/tools/editor/editor_themes.h index dbff8b3079..db49801600 100644 --- a/tools/editor/editor_themes.h +++ b/tools/editor/editor_themes.h @@ -31,8 +31,8 @@ #include "scene/resources/theme.h" -Ref<Theme> create_default_theme(); - Ref<Theme> create_editor_theme(); +Ref<Theme> create_custom_theme(); + #endif diff --git a/tools/editor/fileserver/SCsub b/tools/editor/fileserver/SCsub index 363a2ce4c0..6299fd416c 100644 --- a/tools/editor/fileserver/SCsub +++ b/tools/editor/fileserver/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') Export('env') env.add_source_files(env.tool_sources,"*.cpp") diff --git a/tools/editor/filesystem_dock.cpp b/tools/editor/filesystem_dock.cpp index 8a94c6e340..5b1e80fc3b 100644 --- a/tools/editor/filesystem_dock.cpp +++ b/tools/editor/filesystem_dock.cpp @@ -234,13 +234,6 @@ void FileSystemDock::_dir_selected() { button_favorite->set_pressed(found); - if (ti->get_parent() && ti->get_parent()->get_parent()==tree->get_root() && !ti->get_parent()->get_prev()) { - - //a favorite!!! - } else { - - - } if (!split_mode) { _open_pressed(); //go directly to dir diff --git a/tools/editor/icons/2x/icon_distraction_free.png b/tools/editor/icons/2x/icon_distraction_free.png Binary files differnew file mode 100644 index 0000000000..034239a4e7 --- /dev/null +++ b/tools/editor/icons/2x/icon_distraction_free.png diff --git a/tools/editor/icons/2x/icon_load.png b/tools/editor/icons/2x/icon_load.png Binary files differindex 2e797c448b..729eedd2dd 100644 --- a/tools/editor/icons/2x/icon_load.png +++ b/tools/editor/icons/2x/icon_load.png diff --git a/tools/editor/icons/2x/icon_mini_aabb.png b/tools/editor/icons/2x/icon_mini_aabb.png Binary files differindex f0fd5620e9..25603eec49 100644 --- a/tools/editor/icons/2x/icon_mini_aabb.png +++ b/tools/editor/icons/2x/icon_mini_aabb.png diff --git a/tools/editor/icons/2x/icon_mini_transform.png b/tools/editor/icons/2x/icon_mini_transform.png Binary files differindex cb106ba5fa..5144871c5c 100644 --- a/tools/editor/icons/2x/icon_mini_transform.png +++ b/tools/editor/icons/2x/icon_mini_transform.png diff --git a/tools/editor/icons/2x/icon_open.png b/tools/editor/icons/2x/icon_open.png Binary files differdeleted file mode 100644 index 2e797c448b..0000000000 --- a/tools/editor/icons/2x/icon_open.png +++ /dev/null diff --git a/tools/editor/icons/2x/icon_remote_transform.png b/tools/editor/icons/2x/icon_remote_transform.png Binary files differnew file mode 100644 index 0000000000..dad528615a --- /dev/null +++ b/tools/editor/icons/2x/icon_remote_transform.png diff --git a/tools/editor/icons/SCsub b/tools/editor/icons/SCsub index bc104294cb..9e05d8f391 100644 --- a/tools/editor/icons/SCsub +++ b/tools/editor/icons/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') def make_editor_icons_action(target, source, env): @@ -61,8 +63,10 @@ def make_editor_icons_action(target, source, env): s.write("static Ref<ImageTexture> make_icon(const uint8_t* p_png,const uint8_t* p_hidpi_png) {\n") s.write("\tRef<ImageTexture> texture( memnew( ImageTexture ) );\n") - s.write("\tImage img((editor_is_hidpi()&&p_hidpi_png)?p_hidpi_png:p_png);\n") - s.write("\tif (editor_is_hidpi() && !p_hidpi_png) { img.convert(Image::FORMAT_RGBA); img.expand_x2_hq2x(); }\n") + s.write("\tbool use_hidpi_image=(editor_get_scale()>1.0&&p_hidpi_png);\n") + s.write("\tImage img(use_hidpi_image?p_hidpi_png:p_png);\n") + s.write("\tif (editor_get_scale()>1.0 && !p_hidpi_png) { img.convert(Image::FORMAT_RGBA); img.expand_x2_hq2x(); use_hidpi_image=true;}\n") + s.write("\timg.resize(img.get_width()*EDSCALE/(use_hidpi_image?2:1),img.get_height()*EDSCALE/(use_hidpi_image?2:1));\n") s.write("\ttexture->create_from_image( img,ImageTexture::FLAG_FILTER );\n") s.write("\treturn texture;\n") s.write("}\n\n") diff --git a/tools/editor/icons/icon_color_frame.png b/tools/editor/icons/icon_color_frame.png Binary files differnew file mode 100644 index 0000000000..a82eefc10a --- /dev/null +++ b/tools/editor/icons/icon_color_frame.png diff --git a/tools/editor/icons/icon_distraction_free.png b/tools/editor/icons/icon_distraction_free.png Binary files differnew file mode 100644 index 0000000000..c6f8a08874 --- /dev/null +++ b/tools/editor/icons/icon_distraction_free.png diff --git a/tools/editor/icons/icon_load.png b/tools/editor/icons/icon_load.png Binary files differindex cc05e98ebb..98da8135f2 100644 --- a/tools/editor/icons/icon_load.png +++ b/tools/editor/icons/icon_load.png diff --git a/tools/editor/icons/icon_mini_aabb.png b/tools/editor/icons/icon_mini_aabb.png Binary files differindex 3a6be5605a..eebc4633e4 100644 --- a/tools/editor/icons/icon_mini_aabb.png +++ b/tools/editor/icons/icon_mini_aabb.png diff --git a/tools/editor/icons/icon_mini_transform.png b/tools/editor/icons/icon_mini_transform.png Binary files differindex 0107107a96..068ea0506c 100644 --- a/tools/editor/icons/icon_mini_transform.png +++ b/tools/editor/icons/icon_mini_transform.png diff --git a/tools/editor/icons/icon_open.png b/tools/editor/icons/icon_open.png Binary files differdeleted file mode 100644 index cc05e98ebb..0000000000 --- a/tools/editor/icons/icon_open.png +++ /dev/null diff --git a/tools/editor/icons/icon_remote_transform.png b/tools/editor/icons/icon_remote_transform.png Binary files differnew file mode 100644 index 0000000000..2a8b5f4d0e --- /dev/null +++ b/tools/editor/icons/icon_remote_transform.png diff --git a/tools/editor/icons/source/icon_distraction_free.svg b/tools/editor/icons/source/icon_distraction_free.svg new file mode 100644 index 0000000000..4ae48b2fb6 --- /dev/null +++ b/tools/editor/icons/source/icon_distraction_free.svg @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + viewBox="0 0 16 16" + id="svg2" + version="1.1" + inkscape:version="0.91 r13725" + inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_add_track.png" + inkscape:export-xdpi="45" + inkscape:export-ydpi="45" + sodipodi:docname="icon_distraction_free.svg"> + <defs + id="defs4" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="32.000001" + inkscape:cx="10.344519" + inkscape:cy="8.9631686" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + units="px" + inkscape:snap-bbox="true" + inkscape:bbox-paths="true" + inkscape:bbox-nodes="true" + inkscape:snap-bbox-edge-midpoints="true" + inkscape:snap-bbox-midpoints="false" + inkscape:snap-object-midpoints="true" + inkscape:snap-center="true" + inkscape:window-width="1920" + inkscape:window-height="1016" + inkscape:window-x="0" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:snap-midpoints="true" + inkscape:snap-smooth-nodes="true" + inkscape:object-nodes="true"> + <inkscape:grid + type="xygrid" + id="grid3336" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-1036.3622)"> + <path + style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 3.7578125 2.34375 L 2.34375 3.7578125 L 5.2929688 6.7070312 L 6.7070312 5.2929688 L 3.7578125 2.34375 z M 12.242188 2.34375 L 9.2929688 5.2929688 L 10.707031 6.7070312 L 13.65625 3.7578125 L 12.242188 2.34375 z M 5.2929688 9.2929688 L 2.34375 12.242188 L 3.7578125 13.65625 L 6.7070312 10.707031 L 5.2929688 9.2929688 z M 10.707031 9.2929688 L 9.2929688 10.707031 L 12.242188 13.65625 L 13.65625 12.242188 L 10.707031 9.2929688 z " + transform="translate(0,1036.3622)" + id="rect4137" /> + <path + style="fill:#e0e0e0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 1,1051.3622 0,-5 5,5 z" + id="path4155" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <path + sodipodi:nodetypes="cccc" + inkscape:connector-curvature="0" + id="path4158" + d="m 15,1051.3622 0,-5 -5,5 z" + style="fill:#e0e0e0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:#e0e0e0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 15,1037.3622 0,5 -5,-5 z" + id="path4160" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <path + sodipodi:nodetypes="cccc" + inkscape:connector-curvature="0" + id="path4162" + d="m 1,1037.3622 0,5 5,-5 z" + style="fill:#e0e0e0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> +</svg> diff --git a/tools/editor/icons/source/icon_load.svg b/tools/editor/icons/source/icon_load.svg new file mode 100644 index 0000000000..f8e78fb4ea --- /dev/null +++ b/tools/editor/icons/source/icon_load.svg @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + viewBox="0 0 16 16" + id="svg2" + version="1.1" + inkscape:version="0.91 r13725" + inkscape:export-filename="/home/godotengine/godot/tools/editor/icons/2x/icon_load.png" + inkscape:export-xdpi="180" + inkscape:export-ydpi="180" + sodipodi:docname="icon_load.svg"> + <defs + id="defs4" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="22.627417" + inkscape:cx="12.685427" + inkscape:cy="1.6294402" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + units="px" + inkscape:snap-bbox="true" + inkscape:bbox-paths="true" + inkscape:bbox-nodes="true" + inkscape:snap-bbox-edge-midpoints="true" + inkscape:snap-bbox-midpoints="false" + inkscape:snap-object-midpoints="true" + inkscape:snap-center="true" + inkscape:window-width="1920" + inkscape:window-height="1119" + inkscape:window-x="0" + inkscape:window-y="26" + inkscape:window-maximized="1" + inkscape:snap-smooth-nodes="true" + inkscape:object-nodes="true" + showguides="false"> + <inkscape:grid + type="xygrid" + id="grid3336" + spacingx="0.5" + spacingy="0.5" + empspacing="2" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-1036.3622)"> + <path + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#e0e0e0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" + d="M 1.5000703,2 C 1.0834036,2 0.7251221,2.1928844 0.4590547,2.4589844 0.1929873,2.7250844 7.03e-5,3.0834 7.03e-5,3.5 l 0.5,8.5 c 0.041565,0.581917 0.1536332,1.110716 0.5214844,1.478516 C 1.3894058,13.846416 1.916737,14 2.5000703,14 l 0.5,0 0.5,0 9.9997657,0 c 0.231666,-10e-5 0.432919,-0.159266 0.486328,-0.384766 l 2,-7.4999996 C 16.060474,5.8013344 15.822456,5.5002 15.499836,5.5 L 4.7559297,5.5 C 4.5236856,5.5003 4.3126587,5.6584963 4.2696015,5.8867188 L 3.0383769,12.412759 C 2.9838992,12.701515 2.7130529,12.963778 2.2988984,12.972656 1.7175274,12.985119 1.5058274,12.46121 1.5000703,12 l -0.5,-8.5 c 0,-0.083 0.057083,-0.2249844 0.1660156,-0.3339844 C 1.2750185,3.0571156 1.416737,3 1.5000703,3 L 12.499836,3 c 0.08333,0 0.225052,0.057016 0.333984,0.1660156 0.108933,0.109 0.224913,0.2750776 0.166016,0.3339844 l 0,1 1,0 0,-1 c 0,-0.4166 -0.192917,-0.7749156 -0.458984,-1.0410156 C 13.274784,2.1928844 12.916503,2 12.499836,2 Z" + transform="translate(0,1036.3622)" + id="path8167" + inkscape:connector-curvature="0" + sodipodi:nodetypes="sscccscccccccssscccssssccssss" /> + </g> +</svg> diff --git a/tools/editor/icons/source/icon_mini_aabb.svg b/tools/editor/icons/source/icon_mini_aabb.svg index f6cc3feda1..ebfd505bea 100644 --- a/tools/editor/icons/source/icon_mini_aabb.svg +++ b/tools/editor/icons/source/icon_mini_aabb.svg @@ -29,8 +29,8 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="45.254835" - inkscape:cx="3.148993" - inkscape:cy="6.4579802" + inkscape:cx="5.0272453" + inkscape:cy="5.132155" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" @@ -76,7 +76,7 @@ id="path4893" inkscape:connector-curvature="0" /> <path - style="fill:#f5acbb;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + style="fill:#f39bad;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="m 3,1046.3622 a 3,3 0 0 0 -3,3 3,3 0 0 0 3,3 l 2,0 0,-6 -2,0 z m 0,2 0,2 a 1.0000174,1.0000174 0 0 1 -1,-1 1.0000174,1.0000174 0 0 1 1,-1 z" id="path4234" inkscape:connector-curvature="0" /> @@ -99,7 +99,7 @@ id="rect4149" style="fill:#ee7991;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> <path - style="fill:#f5acbb;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + style="fill:#f39bad;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="m 8,1044.3622 0,8 2,0 a 3,3 0 0 0 3,-3 3,3 0 0 0 -3,-3 l 0,-2 -2,0 z m 2,4 a 1.0000174,1.0000174 0 0 1 1,1 1.0000174,1.0000174 0 0 1 -1,1 l 0,-2 z" id="path4151" inkscape:connector-curvature="0" /> diff --git a/tools/editor/icons/source/icon_mini_transform.svg b/tools/editor/icons/source/icon_mini_transform.svg index a844171dd4..6da4eb806d 100644 --- a/tools/editor/icons/source/icon_mini_transform.svg +++ b/tools/editor/icons/source/icon_mini_transform.svg @@ -29,8 +29,8 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="32" - inkscape:cx="5.8969613" - inkscape:cy="6.372864" + inkscape:cx="8.2643591" + inkscape:cy="7.6152896" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" @@ -71,26 +71,20 @@ id="layer1" transform="translate(0,-1040.3622)"> <path - style="fill:#f3e49c;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 3,1042.3622 a 3,3 0 0 0 -3,3 l 0,5 2,0 0,-2 1,0 0,-2 -1,0 0,-1 a 1.0000174,1.0000174 0 0 1 1,-1 l 0,-2 z" - id="rect4455" - inkscape:connector-curvature="0" /> + style="fill:#f6a86e;fill-opacity:1;stroke:none;stroke-width:20;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 4,1042.3622 3.0917969,1044.5438 2,1042.3622 l -2,0 2,4 -2,4 2,0 0.9082031,-2.1816 L 4,1050.3622 l 2,0 -2,-4 2,-4 z" + id="rect4214" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccccccccc" /> <path - style="fill:#ecd669;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 8,1044.3622 0,6 2,0 0,-4 a 1.0000174,1.0000174 0 0 1 1,1 l 0,3 2,0 0,-3 0,-1 a 1.0000174,1.0000174 0 0 1 1,1 l 0,3 2,0 0,-3 a 3,3 0 0 0 -3,-3 l -2,0 0,0.1758 a 3,3 0 0 0 -1,-0.1758 l -2,0 z" - id="path4771" + style="fill:#f8bf95;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 9,1042.3622 a 3,3 0 0 0 -3,3 l 0,5 2,0 0,-2 1,0 0,-2 -1,0 0,-1 a 1.0000174,1.0000174 0 0 1 1,-1 l 1,0 0,-2 -1,0 z" + id="rect4455" inkscape:connector-curvature="0" /> <path - style="fill:#ecd669;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 7,1044.3622 a 3,3 0 0 0 -3,3 l 0,3 2,0 0,-3 a 1.0000174,1.0000174 0 0 1 1,-1 l 0,-2 z" - id="rect4601" - inkscape:connector-curvature="0" /> - <rect - style="fill:#f3e49c;fill-opacity:1;stroke:none" - id="rect4139" - width="1" - height="2" - x="3" - y="1042.3622" /> + style="fill:#f6a86e;fill-opacity:1;stroke:none;stroke-width:20;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 10 4 L 10 6 L 10 8 L 10 10 L 12 10 L 12 8 L 13 9 L 14 8 L 14 10 L 16 10 L 16 8 L 16 6 L 16 4 L 14 4 L 13 6 L 12 4 L 10 4 z " + transform="translate(0,1040.3622)" + id="rect4231" /> </g> </svg> diff --git a/tools/editor/icons/source/icon_remote_transform.svg b/tools/editor/icons/source/icon_remote_transform.svg new file mode 100644 index 0000000000..fbbfacf629 --- /dev/null +++ b/tools/editor/icons/source/icon_remote_transform.svg @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + viewBox="0 0 16 16" + id="svg2" + version="1.1" + inkscape:version="0.91 r13725" + inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_node_2d.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + sodipodi:docname="icon_remote_transform.svg"> + <defs + id="defs4" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="16" + inkscape:cx="7.0691739" + inkscape:cy="9.3738931" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + units="px" + inkscape:snap-bbox="true" + inkscape:bbox-paths="true" + inkscape:bbox-nodes="true" + inkscape:snap-bbox-edge-midpoints="true" + inkscape:snap-bbox-midpoints="true" + inkscape:snap-object-midpoints="true" + inkscape:snap-center="true" + inkscape:window-width="1680" + inkscape:window-height="1050" + inkscape:window-x="1366" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:object-paths="true" + inkscape:snap-intersection-paths="true" + inkscape:object-nodes="true" + inkscape:snap-smooth-nodes="true"> + <inkscape:grid + type="xygrid" + id="grid3336" + empspacing="4" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-1036.3622)"> + <path + style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="path4155" + sodipodi:type="arc" + sodipodi:cx="744.13245" + sodipodi:cy="734.23291" + sodipodi:rx="4" + sodipodi:ry="4" + sodipodi:start="0" + sodipodi:end="3.1415927" + d="m 748.13245,734.23291 a 4,4 0 0 1 -2,3.4641 4,4 0 0 1 -4,0 4,4 0 0 1 -2,-3.4641 l 4,0 z" + inkscape:transform-center-y="0.58575321" + transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" + inkscape:transform-center-x="0.58575732" /> + <circle + style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="path4159" + cx="7" + cy="1045.3622" + r="1" /> + <path + style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + d="m 13.242641,1039.1196 a 6.0000172,6.0000172 0 0 0 -8.4852817,0 l 0.7071068,0.7071 a 5.0000172,5.0000172 0 0 1 7.0710679,0 5.0000172,5.0000172 0 0 1 0,7.071 l 0.707107,0.7071 a 6.0000172,6.0000172 0 0 0 0,-8.4852 z" + id="circle4163" + inkscape:connector-curvature="0" + inkscape:transform-center-y="-0.87867618" + inkscape:transform-center-x="-0.8786559" /> + <path + style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + d="m 11.828427,1040.5338 a 4.0000172,4.0000172 0 0 0 -5.6568541,0 l 0.7071068,0.7071 a 3.0000174,3.0000174 0 0 1 4.2426403,0 3.0000174,3.0000174 0 0 1 0,4.2426 l 0.707107,0.7071 a 4.0000172,4.0000172 0 0 0 0,-5.6568 z" + id="circle4168" + inkscape:connector-curvature="0" + inkscape:transform-center-y="-0.58578284" + inkscape:transform-center-x="-0.58576926" /> + <path + style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + d="m 10.414214,1041.948 a 2,2 0 0 0 -2.8284276,0 l 0.7071068,0.7071 a 1.0000174,1.0000174 0 0 1 1.4142136,0 1.0000174,1.0000174 0 0 1 0,1.4142 l 0.7071072,0.7071 a 2,2 0 0 0 0,-2.8284 z" + id="circle4172" + inkscape:connector-curvature="0" + inkscape:transform-center-y="-0.29289334" + inkscape:transform-center-x="-0.29288664" /> + <path + style="fill:#fc9c9c;fill-opacity:0.99607843;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 1,1051.3622 4,-5 1,0 0,5 z" + id="path4181" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccc" /> + </g> +</svg> diff --git a/tools/editor/io_plugins/SCsub b/tools/editor/io_plugins/SCsub index 363a2ce4c0..6299fd416c 100644 --- a/tools/editor/io_plugins/SCsub +++ b/tools/editor/io_plugins/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') Export('env') env.add_source_files(env.tool_sources,"*.cpp") diff --git a/tools/editor/io_plugins/editor_bitmask_import_plugin.cpp b/tools/editor/io_plugins/editor_bitmask_import_plugin.cpp index dca7d011ff..757d2ed5d4 100644 --- a/tools/editor/io_plugins/editor_bitmask_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_bitmask_import_plugin.cpp @@ -147,7 +147,7 @@ public: dst = dst.plus_file(bitmasks[i].get_file().basename() + ".pbm"); - Error err = plugin->import(dst, imd); + plugin->import(dst, imd); } hide(); diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.cpp b/tools/editor/io_plugins/editor_sample_import_plugin.cpp index ac0795f522..7dc74e58dd 100644 --- a/tools/editor/io_plugins/editor_sample_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_sample_import_plugin.cpp @@ -298,7 +298,7 @@ public: dst = dst.plus_file(samples[i].get_file().basename()+".smp"); - Error err = plugin->import(dst,imd); + plugin->import(dst,imd); } hide(); diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.cpp b/tools/editor/io_plugins/editor_scene_import_plugin.cpp index fa62283e37..56af35c6db 100644 --- a/tools/editor/io_plugins/editor_scene_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_scene_import_plugin.cpp @@ -175,6 +175,7 @@ class EditorSceneImportDialog : public ConfirmationDialog { EditorDirDialog *save_select; OptionButton *texture_action; CreateDialog *root_type_choose; + LineEdit *root_node_name; ConfirmationDialog *confirm_open; @@ -639,6 +640,7 @@ void EditorSceneImportDialog::_choose_file(const String& p_path) { } else { #endif save_path->set_text(""); + root_node_name->set_text(""); //save_path->set_text(p_path.get_file().basename()+".scn"); #if 0 } @@ -656,6 +658,9 @@ void EditorSceneImportDialog::_choose_file(const String& p_path) { import_path->set_text(p_path); + if (root_node_name->get_text().size()==0){ + root_node_name->set_text(import_path->get_text().get_file().basename()); + } } void EditorSceneImportDialog::_choose_save_file(const String& p_path) { @@ -788,6 +793,10 @@ void EditorSceneImportDialog::_import(bool p_and_open) { if (!root_default->is_pressed()) { rim->set_option("root_type",root_type->get_text()); } + if (root_node_name->get_text().size()==0) { + root_node_name->set_text(import_path->get_text().get_file().basename()); + } + rim->set_option("root_name",root_node_name->get_text()); List<String> missing; Error err = plugin->import1(rim,&scene,&missing); @@ -946,7 +955,11 @@ void EditorSceneImportDialog::popup_import(const String &p_from) { root_default->set_pressed(true); root_type->set_disabled(true); } - + if (rimd->has_option("root_name")) { + root_node_name->set_text(rimd->get_option("root_name")); + } else { + root_node_name->set_text(root_type->get_text()); // backward compatibility for 2.1 or before + } script_path->set_text(rimd->get_option("post_import_script")); save_path->set_text(p_from.get_base_dir()); @@ -1241,7 +1254,9 @@ EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSce root_default->connect("pressed",this,"_root_default_pressed"); custom_root_hb->add_child(root_default); - + root_node_name = memnew( LineEdit ); + root_node_name->set_h_size_flags(SIZE_EXPAND_FILL); + vbc->add_margin_child(TTR("Root Node Name:"),root_node_name); /* this_import = memnew( OptionButton ); this_import->add_item("Overwrite Existing Scene"); @@ -1447,6 +1462,7 @@ void EditorSceneImportPlugin::_find_resources(const Variant& p_var, Map<Ref<Imag } } break; + default: {} } @@ -2184,6 +2200,7 @@ Error EditorSceneImportPlugin::import1(const Ref<ResourceImportMetadata>& p_from } } + scene->set_name(from->get_option("root_name")); _tag_import_paths(scene,scene); *r_node=scene; @@ -2325,7 +2342,7 @@ void EditorSceneImportPlugin::_filter_tracks(Node *scene, const String& p_text) if (!scene->has_node(String("AnimationPlayer"))) return; - Node* n = scene->get_node(String("AnimationPlayer")); + Node* n = scene->get_node(String("AnimationPlayer")); ERR_FAIL_COND(!n); AnimationPlayer *anim = n->cast_to<AnimationPlayer>(); ERR_FAIL_COND(!anim); @@ -2443,7 +2460,7 @@ void EditorSceneImportPlugin::_optimize_animations(Node *scene, float p_max_lin_ if (!scene->has_node(String("AnimationPlayer"))) return; - Node* n = scene->get_node(String("AnimationPlayer")); + Node* n = scene->get_node(String("AnimationPlayer")); ERR_FAIL_COND(!n); AnimationPlayer *anim = n->cast_to<AnimationPlayer>(); ERR_FAIL_COND(!anim); @@ -2842,7 +2859,7 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c } } - Error err = EditorTextureImportPlugin::get_singleton()->import(target_path,imd); + EditorTextureImportPlugin::get_singleton()->import(target_path,imd); } } diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp index 60642999f2..2935ea8fe2 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp @@ -38,6 +38,7 @@ #include "scene/gui/check_button.h" #include "scene/gui/button_group.h" #include "scene/gui/margin_container.h" +#include "scene/io/resource_format_image.h" static const char *flag_names[]={ ("Streaming Format"), @@ -1589,16 +1590,9 @@ Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, c } break; //use default } + String validated_path=EditorImportPlugin::validate_source_path(p_path); - int flags=0; - - if (Globals::get_singleton()->get("image_loader/filter")) - flags|=IMAGE_FLAG_FILTER; - if (!Globals::get_singleton()->get("image_loader/gen_mipmaps")) - flags|=IMAGE_FLAG_NO_MIPMAPS; - if (!Globals::get_singleton()->get("image_loader/repeat")) - flags|=IMAGE_FLAG_REPEAT; - + int flags=texture_flags_to_export_flags(ResourceFormatLoaderImage::load_image_flags(validated_path)); flags|=IMAGE_FLAG_FIX_BORDER_ALPHA; print_line("group format"+itos(group_format)); @@ -1607,7 +1601,7 @@ Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, c rimd->set_option("quality",group_lossy_quality); rimd->set_option("atlas",false); rimd->set_option("shrink",group_shrink); - rimd->add_source(EditorImportPlugin::validate_source_path(p_path),FileAccess::get_md5(p_path)); + rimd->add_source(validated_path,FileAccess::get_md5(p_path)); } else if (EditorImportExport::get_singleton()->get_image_formats().has(p_path.extension().to_lower()) && EditorImportExport::get_singleton()->get_export_image_action()!=EditorImportExport::IMAGE_ACTION_NONE) { //handled by general image export settings @@ -1619,22 +1613,16 @@ Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, c case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: rimd->set_option("format",IMAGE_FORMAT_COMPRESS_RAM); break; } - int flags=0; - - if (Globals::get_singleton()->get("image_loader/filter")) - flags|=IMAGE_FLAG_FILTER; - if (!Globals::get_singleton()->get("image_loader/gen_mipmaps")) - flags|=IMAGE_FLAG_NO_MIPMAPS; - if (!Globals::get_singleton()->get("image_loader/repeat")) - flags|=IMAGE_FLAG_REPEAT; + String validated_path=EditorImportPlugin::validate_source_path(p_path); + int flags=texture_flags_to_export_flags(ResourceFormatLoaderImage::load_image_flags(validated_path)); flags|=IMAGE_FLAG_FIX_BORDER_ALPHA; rimd->set_option("shrink",EditorImportExport::get_singleton()->get_export_image_shrink()); rimd->set_option("flags",flags); rimd->set_option("quality",EditorImportExport::get_singleton()->get_export_image_quality()); rimd->set_option("atlas",false); - rimd->add_source(EditorImportPlugin::validate_source_path(p_path),FileAccess::get_md5(p_path)); + rimd->add_source(validated_path,FileAccess::get_md5(p_path)); } else { return Vector<uint8_t>(); @@ -1726,6 +1714,33 @@ Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, c return ret; } +uint32_t EditorTextureImportPlugin::texture_flags_to_export_flags(uint32_t p_tex_flags) const { + + uint32_t flags=0; + + if (!(p_tex_flags&Texture::FLAG_MIPMAPS)) { + flags|=IMAGE_FLAG_NO_MIPMAPS; + } + if (p_tex_flags&Texture::FLAG_REPEAT) { + flags|=IMAGE_FLAG_REPEAT; + } + if (p_tex_flags&Texture::FLAG_FILTER) { + flags|=IMAGE_FLAG_FILTER; + } + if (p_tex_flags&Texture::FLAG_ANISOTROPIC_FILTER) { + flags|=IMAGE_FLAG_USE_ANISOTROPY; + } + if (p_tex_flags&Texture::FLAG_CONVERT_TO_LINEAR) { + flags|=IMAGE_FLAG_CONVERT_TO_LINEAR; + } + /* // no correspondence yet + if (p_tex_flags&Texture::TEXTURE_FLAG_MIRRORED_REPEAT) { + flags|=; + }*/ + + return flags; +} + void EditorTextureImportPlugin::import_from_drop(const Vector<String>& p_drop,const String& p_dest_path) { Vector<String> valid; diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.h b/tools/editor/io_plugins/editor_texture_import_plugin.h index 5c8abd10a4..22c10a1a3a 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.h +++ b/tools/editor/io_plugins/editor_texture_import_plugin.h @@ -72,6 +72,8 @@ private: Error _process_texture_data(Ref<ImageTexture> &texture, int format, float quality, int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,float shrink); void compress_image(EditorExportPlatform::ImageCompression p_mode,Image& image,bool p_smaller); + + uint32_t texture_flags_to_export_flags(uint32_t p_tex_flags) const; public: diff --git a/tools/editor/multi_node_edit.cpp b/tools/editor/multi_node_edit.cpp index 4d27b8e349..e4ceaf4a8b 100644 --- a/tools/editor/multi_node_edit.cpp +++ b/tools/editor/multi_node_edit.cpp @@ -53,7 +53,14 @@ bool MultiNodeEdit::_set(const StringName& p_name, const Variant& p_value){ if (!n) continue; - ur->add_do_property(n,name,p_value); + if (p_value.get_type() == Variant::NODE_PATH) { + Node *tonode = n->get_node(p_value); + NodePath p_path = n->get_path_to(tonode); + ur->add_do_property(n,name,p_path); + } else { + ur->add_do_property(n,name,p_value); + } + ur->add_undo_property(n,name,n->get(name)); diff --git a/tools/editor/plugins/SCsub b/tools/editor/plugins/SCsub index 363a2ce4c0..6299fd416c 100644 --- a/tools/editor/plugins/SCsub +++ b/tools/editor/plugins/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') Export('env') env.add_source_files(env.tool_sources,"*.cpp") diff --git a/tools/editor/plugins/animation_player_editor_plugin.cpp b/tools/editor/plugins/animation_player_editor_plugin.cpp index b4d54c6b1e..d6d452dd72 100644 --- a/tools/editor/plugins/animation_player_editor_plugin.cpp +++ b/tools/editor/plugins/animation_player_editor_plugin.cpp @@ -666,7 +666,7 @@ void AnimationPlayerEditor::set_state(const Dictionary& p_state) { return; Node *n = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["player"]); - if (n && n->cast_to<AnimationPlayer>()) { + if (n && n->cast_to<AnimationPlayer>() && EditorNode::get_singleton()->get_editor_selection()->is_selected(n)) { player=n->cast_to<AnimationPlayer>(); _update_player(); show(); diff --git a/tools/editor/plugins/baked_light_baker.cpp b/tools/editor/plugins/baked_light_baker.cpp index a2e94e8855..f43bec1cd3 100644 --- a/tools/editor/plugins/baked_light_baker.cpp +++ b/tools/editor/plugins/baked_light_baker.cpp @@ -1177,8 +1177,6 @@ float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,c diffuse_at_point.g=res_light.g*diffuse_at_point.g; diffuse_at_point.b=res_light.b*diffuse_at_point.b; - float ret=1e6; - if (p_bounces>0) { @@ -1220,7 +1218,7 @@ float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,c #endif - ret=_throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); + _throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); } if (use_specular && (specular_at_point.r>CMP_EPSILON || specular_at_point.g>CMP_EPSILON || specular_at_point.b>CMP_EPSILON)) { diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index 57707ffa72..b0e002ba44 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -290,6 +290,7 @@ Dictionary CanvasItemEditor::get_state() const { state["snap_rotation"]=snap_rotation; state["snap_relative"]=snap_relative; state["snap_pixel"]=snap_pixel; + state["skeleton_show_bones"]=skeleton_show_bones; return state; } void CanvasItemEditor::set_state(const Dictionary& p_state){ @@ -351,6 +352,12 @@ void CanvasItemEditor::set_state(const Dictionary& p_state){ int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); edit_menu->get_popup()->set_item_checked(idx,snap_pixel); } + + if (state.has("skeleton_show_bones")) { + skeleton_show_bones=state["skeleton_show_bones"]; + int idx = skeleton_menu->get_item_index(SKELETON_SHOW_BONES); + skeleton_menu->set_item_checked(idx,skeleton_show_bones); + } } @@ -1051,7 +1058,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { EditorPluginList *over_plugin_list = en->get_editor_plugins_over(); if (!over_plugin_list->empty()) { - bool discard = over_plugin_list->forward_input_event(p_event); + bool discard = over_plugin_list->forward_input_event(transform,p_event); if (discard) { accept_event(); return; @@ -2083,76 +2090,90 @@ void CanvasItemEditor::_viewport_draw() { } - int bone_width = EditorSettings::get_singleton()->get("2d_editor/bone_width"); - Color bone_color1 = EditorSettings::get_singleton()->get("2d_editor/bone_color1"); - Color bone_color2 = EditorSettings::get_singleton()->get("2d_editor/bone_color2"); - Color bone_ik_color = EditorSettings::get_singleton()->get("2d_editor/bone_ik_color"); - Color bone_selected_color = EditorSettings::get_singleton()->get("2d_editor/bone_selected_color"); + { - for(Map<ObjectID,BoneList>::Element*E=bone_list.front();E;E=E->next()) { + EditorNode *en = editor; + EditorPluginList *over_plugin_list = en->get_editor_plugins_over(); - E->get().from=Vector2(); - E->get().to=Vector2(); + if (!over_plugin_list->empty()) { - Object *obj = ObjectDB::get_instance(E->get().bone); - if (!obj) - continue; + over_plugin_list->forward_draw_over_canvas(transform,viewport); - Node2D* n2d = obj->cast_to<Node2D>(); - if (!n2d) - continue; + } + } - if (!n2d->get_parent()) - continue; + if (skeleton_show_bones) { + int bone_width = EditorSettings::get_singleton()->get("2d_editor/bone_width"); + Color bone_color1 = EditorSettings::get_singleton()->get("2d_editor/bone_color1"); + Color bone_color2 = EditorSettings::get_singleton()->get("2d_editor/bone_color2"); + Color bone_ik_color = EditorSettings::get_singleton()->get("2d_editor/bone_ik_color"); + Color bone_selected_color = EditorSettings::get_singleton()->get("2d_editor/bone_selected_color"); - CanvasItem *pi = n2d->get_parent_item(); + for(Map<ObjectID,BoneList>::Element*E=bone_list.front();E;E=E->next()) { + E->get().from=Vector2(); + E->get().to=Vector2(); - Node2D* pn2d=n2d->get_parent()->cast_to<Node2D>(); + Object *obj = ObjectDB::get_instance(E->get().bone); + if (!obj) + continue; - if (!pn2d) - continue; + Node2D* n2d = obj->cast_to<Node2D>(); + if (!n2d) + continue; - Vector2 from = transform.xform(pn2d->get_global_pos()); - Vector2 to = transform.xform(n2d->get_global_pos()); + if (!n2d->get_parent()) + continue; - E->get().from=from; - E->get().to=to; + CanvasItem *pi = n2d->get_parent_item(); - Vector2 rel = to-from; - Vector2 relt = rel.tangent().normalized()*bone_width; + Node2D* pn2d=n2d->get_parent()->cast_to<Node2D>(); + if (!pn2d) + continue; - Vector<Vector2> bone_shape; - bone_shape.push_back(from); - bone_shape.push_back(from+rel*0.2+relt); - bone_shape.push_back(to); - bone_shape.push_back(from+rel*0.2-relt); - Vector<Color> colors; - if (pi->has_meta("_edit_ik_")) { + Vector2 from = transform.xform(pn2d->get_global_pos()); + Vector2 to = transform.xform(n2d->get_global_pos()); - colors.push_back(bone_ik_color); - colors.push_back(bone_ik_color); - colors.push_back(bone_ik_color); - colors.push_back(bone_ik_color); - } else { - colors.push_back(bone_color1); - colors.push_back(bone_color2); - colors.push_back(bone_color1); - colors.push_back(bone_color2); - } + E->get().from=from; + E->get().to=to; + Vector2 rel = to-from; + Vector2 relt = rel.tangent().normalized()*bone_width; - VisualServer::get_singleton()->canvas_item_add_primitive(ci,bone_shape,colors,Vector<Vector2>(),RID()); - if (editor_selection->is_selected(pi)) { - for(int i=0;i<bone_shape.size();i++) { - VisualServer::get_singleton()->canvas_item_add_line(ci,bone_shape[i],bone_shape[(i+1)%bone_shape.size()],bone_selected_color,2); + Vector<Vector2> bone_shape; + bone_shape.push_back(from); + bone_shape.push_back(from+rel*0.2+relt); + bone_shape.push_back(to); + bone_shape.push_back(from+rel*0.2-relt); + Vector<Color> colors; + if (pi->has_meta("_edit_ik_")) { + + colors.push_back(bone_ik_color); + colors.push_back(bone_ik_color); + colors.push_back(bone_ik_color); + colors.push_back(bone_ik_color); + } else { + colors.push_back(bone_color1); + colors.push_back(bone_color2); + colors.push_back(bone_color1); + colors.push_back(bone_color2); } - } + + VisualServer::get_singleton()->canvas_item_add_primitive(ci,bone_shape,colors,Vector<Vector2>(),RID()); + + if (editor_selection->is_selected(pi)) { + for(int i=0;i<bone_shape.size();i++) { + + VisualServer::get_singleton()->canvas_item_add_line(ci,bone_shape[i],bone_shape[(i+1)%bone_shape.size()],bone_selected_color,2); + } + } + + } } } @@ -2536,6 +2557,12 @@ void CanvasItemEditor::_popup_callback(int p_op) { ((SnapDialog *)snap_dialog)->set_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step); snap_dialog->popup_centered(Size2(220,160)); } break; + case SKELETON_SHOW_BONES: { + skeleton_show_bones = !skeleton_show_bones; + int idx = skeleton_menu->get_item_index(SKELETON_SHOW_BONES); + skeleton_menu->set_item_checked(idx,skeleton_show_bones); + viewport->update(); + } break; case ZOOM_IN: { if (zoom>MAX_ZOOM) return; @@ -2999,6 +3026,8 @@ void CanvasItemEditor::_popup_callback(int p_op) { continue; n2d->set_meta("_edit_bone_",true); + if (!skeleton_show_bones) + skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES)); } viewport->update(); @@ -3017,6 +3046,8 @@ void CanvasItemEditor::_popup_callback(int p_op) { continue; n2d->set_meta("_edit_bone_",Variant()); + if (!skeleton_show_bones) + skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES)); } viewport->update(); @@ -3036,6 +3067,8 @@ void CanvasItemEditor::_popup_callback(int p_op) { continue; canvas_item->set_meta("_edit_ik_",true); + if (!skeleton_show_bones) + skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES)); } @@ -3055,6 +3088,8 @@ void CanvasItemEditor::_popup_callback(int p_op) { continue; n2d->set_meta("_edit_ik_",Variant()); + if (!skeleton_show_bones) + skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES)); } viewport->update(); @@ -3401,15 +3436,17 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_shortcut(ED_SHORTCUT("canvas_item_editor/expand_to_parent", TTR("Expand to Parent"), KEY_MASK_CMD | KEY_P), EXPAND_TO_PARENT); p->add_separator(); p->add_submenu_item(TTR("Skeleton.."),"skeleton"); - PopupMenu *p2 = memnew(PopupMenu); - p->add_child(p2); - p2->set_name("skeleton"); - p2->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bones"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B ),SKELETON_MAKE_BONES); - p2->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Bones")), SKELETON_CLEAR_BONES); - p2->add_separator(); - p2->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN); - p2->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN); - p2->connect("item_pressed", this,"_popup_callback"); + skeleton_menu = memnew(PopupMenu); + p->add_child(skeleton_menu); + skeleton_menu->set_name("skeleton"); + skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bones"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B ),SKELETON_MAKE_BONES); + skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Bones")), SKELETON_CLEAR_BONES); + skeleton_menu->add_separator(); + skeleton_menu->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES); + skeleton_menu->add_separator(); + skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN); + skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN); + skeleton_menu->connect("item_pressed", this,"_popup_callback"); /* @@ -3535,6 +3572,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { snap_show_grid=false; snap_rotation=false; snap_pixel=false; + skeleton_show_bones=true; + skeleton_menu->set_item_checked(skeleton_menu->get_item_index(SKELETON_SHOW_BONES),true); updating_value_dialog=false; box_selecting=false; //zoom=0.5; diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h index ea582f6fa7..9f4bc46eb4 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.h +++ b/tools/editor/plugins/canvas_item_editor_plugin.h @@ -124,6 +124,7 @@ class CanvasItemEditor : public VBoxContainer { VIEW_FRAME_TO_SELECTION, SKELETON_MAKE_BONES, SKELETON_CLEAR_BONES, + SKELETON_SHOW_BONES, SKELETON_SET_IK_CHAIN, SKELETON_CLEAR_IK_CHAIN @@ -175,6 +176,7 @@ class CanvasItemEditor : public VBoxContainer { bool snap_rotation; bool snap_relative; bool snap_pixel; + bool skeleton_show_bones; bool box_selecting; Point2 box_selecting_to; bool key_pos; @@ -256,6 +258,7 @@ class CanvasItemEditor : public VBoxContainer { ToolButton *ungroup_button; MenuButton *edit_menu; + PopupMenu *skeleton_menu; MenuButton *view_menu; HBoxContainer *animation_hb; MenuButton *animation_menu; diff --git a/tools/editor/plugins/collision_polygon_2d_editor_plugin.h b/tools/editor/plugins/collision_polygon_2d_editor_plugin.h index 982ba35fe8..431d3651c1 100644 --- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.h +++ b/tools/editor/plugins/collision_polygon_2d_editor_plugin.h @@ -95,7 +95,7 @@ class CollisionPolygon2DEditorPlugin : public EditorPlugin { public: - virtual bool forward_input_event(const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); } + virtual bool forward_canvas_input_event(const Matrix32& p_canvas_xform,const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); } virtual String get_name() const { return "CollisionPolygon2D"; } bool has_main_screen() const { return false; } diff --git a/tools/editor/plugins/collision_shape_2d_editor_plugin.h b/tools/editor/plugins/collision_shape_2d_editor_plugin.h index 1ee81eda43..a8930dc0f2 100644 --- a/tools/editor/plugins/collision_shape_2d_editor_plugin.h +++ b/tools/editor/plugins/collision_shape_2d_editor_plugin.h @@ -86,7 +86,7 @@ class CollisionShape2DEditorPlugin : public EditorPlugin { EditorNode* editor; public: - virtual bool forward_input_event(const InputEvent& p_event) { return collision_shape_2d_editor->forward_input_event(p_event); } + virtual bool forward_canvas_input_event(const Matrix32& p_canvas_xform,const InputEvent& p_event) { return collision_shape_2d_editor->forward_input_event(p_event); } virtual String get_name() const { return "CollisionShape2D"; } bool has_main_screen() const { return false; } diff --git a/tools/editor/plugins/light_occluder_2d_editor_plugin.h b/tools/editor/plugins/light_occluder_2d_editor_plugin.h index b570fff506..0176eb87dd 100644 --- a/tools/editor/plugins/light_occluder_2d_editor_plugin.h +++ b/tools/editor/plugins/light_occluder_2d_editor_plugin.h @@ -99,7 +99,7 @@ class LightOccluder2DEditorPlugin : public EditorPlugin { public: - virtual bool forward_input_event(const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); } + virtual bool forward_canvas_input_event(const Matrix32& p_canvas_xform,const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); } virtual String get_name() const { return "LightOccluder2D"; } bool has_main_screen() const { return false; } diff --git a/tools/editor/plugins/navigation_polygon_editor_plugin.h b/tools/editor/plugins/navigation_polygon_editor_plugin.h index 503b4c2662..defdebbec2 100644 --- a/tools/editor/plugins/navigation_polygon_editor_plugin.h +++ b/tools/editor/plugins/navigation_polygon_editor_plugin.h @@ -101,7 +101,7 @@ class NavigationPolygonEditorPlugin : public EditorPlugin { public: - virtual bool forward_input_event(const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); } + virtual bool forward_canvas_input_event(const Matrix32& p_canvas_xform,const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); } virtual String get_name() const { return "NavigationPolygonInstance"; } bool has_main_screen() const { return false; } diff --git a/tools/editor/plugins/path_2d_editor_plugin.h b/tools/editor/plugins/path_2d_editor_plugin.h index 973c17464e..acbc481e09 100644 --- a/tools/editor/plugins/path_2d_editor_plugin.h +++ b/tools/editor/plugins/path_2d_editor_plugin.h @@ -108,7 +108,7 @@ class Path2DEditorPlugin : public EditorPlugin { public: - virtual bool forward_input_event(const InputEvent& p_event) { return path2d_editor->forward_input_event(p_event); } + virtual bool forward_canvas_input_event(const Matrix32& p_canvas_xform,const InputEvent& p_event) { return path2d_editor->forward_input_event(p_event); } virtual String get_name() const { return "Path2D"; } bool has_main_screen() const { return false; } diff --git a/tools/editor/plugins/polygon_2d_editor_plugin.h b/tools/editor/plugins/polygon_2d_editor_plugin.h index d8b951ec44..33bae94340 100644 --- a/tools/editor/plugins/polygon_2d_editor_plugin.h +++ b/tools/editor/plugins/polygon_2d_editor_plugin.h @@ -151,7 +151,7 @@ class Polygon2DEditorPlugin : public EditorPlugin { public: - virtual bool forward_input_event(const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); } + virtual bool forward_canvas_input_event(const Matrix32& p_canvas_xform,const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); } virtual String get_name() const { return "Polygon2D"; } bool has_main_screen() const { return false; } diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp index fdb7856b83..99c50efd2f 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -43,6 +43,17 @@ /*** SCRIPT EDITOR ****/ + +void ScriptEditorBase::_bind_methods() { + + ADD_SIGNAL(MethodInfo("name_changed")); + ADD_SIGNAL(MethodInfo("request_help_search",PropertyInfo(Variant::STRING,"topic"))); + ADD_SIGNAL(MethodInfo("request_open_script_at_line",PropertyInfo(Variant::OBJECT,"script"),PropertyInfo(Variant::INT,"line"))); + ADD_SIGNAL(MethodInfo("request_save_history")); + ADD_SIGNAL(MethodInfo("go_to_help",PropertyInfo(Variant::STRING,"what"))); + +} + static bool _can_open_in_editor(Script* p_script) { String path = p_script->get_path(); @@ -346,6 +357,34 @@ void ScriptEditor::_update_history_arrows() { script_forward->set_disabled( history_pos>=history.size()-1 ); } +void ScriptEditor::_save_history() { + + + if (history_pos>=0 && history_pos<history.size() && history[history_pos].control==tab_container->get_current_tab_control()) { + + Node *n = tab_container->get_current_tab_control(); + + if (n->cast_to<ScriptEditorBase>()) { + + history[history_pos].state=n->cast_to<ScriptEditorBase>()->get_edit_state(); + } + if (n->cast_to<EditorHelp>()) { + + history[history_pos].state=n->cast_to<EditorHelp>()->get_scroll(); + } + } + + history.resize(history_pos+1); + ScriptHistory sh; + sh.control=tab_container->get_current_tab_control(); + sh.state=Variant(); + + history.push_back(sh); + history_pos++; + + _update_history_arrows(); +} + void ScriptEditor::_go_to_tab(int p_idx) { @@ -480,6 +519,33 @@ void ScriptEditor::_close_docs_tab() { } +void ScriptEditor::_close_all_tabs() { + + int child_count = tab_container->get_child_count(); + for (int i = child_count-1; i>=0; i--) { + + tab_container->set_current_tab(i); + ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>(); + + if (se) { + + // Maybe there are unsaved changes + if (se->is_unsaved()) { + _ask_close_current_unsaved_tab(se); + continue; + } + + } + + _close_current_tab(); + } + +} + +void ScriptEditor::_ask_close_current_unsaved_tab(ScriptEditorBase *current) { + erase_tab_confirm->set_text("Close and save changes?\n\""+current->get_name()+"\""); + erase_tab_confirm->popup_centered_minsize(); +} void ScriptEditor::_resave_scripts(const String& p_str) { @@ -689,29 +755,10 @@ void ScriptEditor::_menu_option(int p_option) { } break; case FILE_SAVE_ALL: { - if (!_test_script_times_on_disk()) + if (_test_script_times_on_disk()) return; save_all_scripts(); - -#if 0 - for(int i=0;i<tab_container->get_child_count();i++) { - - ScriptTextEditor *se = tab_container->get_child(i)->cast_to<ScriptTextEditor>(); - if (!se) - continue; - - - Ref<Script> script = se->get_edited_script(); - - if (script->get_path()=="" || script->get_path().find("local://")!=-1 || script->get_path().find("::")!=-1) - continue; //internal script, who cares - - - editor->save_resource( script ); - } - -#endif } break; case FILE_IMPORT_THEME: { file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); @@ -831,8 +878,7 @@ void ScriptEditor::_menu_option(int p_option) { case FILE_CLOSE: { if (current->is_unsaved()) { - erase_tab_confirm->set_text("Close and save changes?\n\""+current->get_name()+"\""); - erase_tab_confirm->popup_centered_minsize(); + _ask_close_current_unsaved_tab(current); } else { _close_current_tab(); } @@ -840,6 +886,9 @@ void ScriptEditor::_menu_option(int p_option) { case CLOSE_DOCS: { _close_docs_tab(); } break; + case CLOSE_ALL: { + _close_all_tabs(); + } break; case DEBUG_NEXT: { if (debugger) @@ -913,6 +962,9 @@ void ScriptEditor::_menu_option(int p_option) { case CLOSE_DOCS: { _close_docs_tab(); } break; + case CLOSE_ALL: { + _close_all_tabs(); + } break; } @@ -1291,9 +1343,8 @@ struct _ScriptEditorItemData { void ScriptEditor::_update_script_colors() { - bool enabled = EditorSettings::get_singleton()->get("text_editor/script_temperature_enabled"); - if (!enabled) - return; + bool script_temperature_enabled = EditorSettings::get_singleton()->get("text_editor/script_temperature_enabled"); + bool highlight_current = EditorSettings::get_singleton()->get("text_editor/highlight_current_script"); int hist_size = EditorSettings::get_singleton()->get("text_editor/script_temperature_history_size"); Color hot_color=EditorSettings::get_singleton()->get("text_editor/script_temperature_hot_color"); @@ -1307,20 +1358,27 @@ void ScriptEditor::_update_script_colors() { continue; script_list->set_item_custom_bg_color(i,Color(0,0,0,0)); - if (!n->has_meta("__editor_pass")) { - continue; - } - int pass=n->get_meta("__editor_pass"); - int h = edit_pass - pass; - if (h>hist_size) { - continue; - } - int non_zero_hist_size = ( hist_size == 0 ) ? 1 : hist_size; - float v = Math::ease((edit_pass-pass)/float(non_zero_hist_size),0.4); + bool current = tab_container->get_current_tab() == c; + if (current && highlight_current) { + script_list->set_item_custom_bg_color(i, EditorSettings::get_singleton()->get("text_editor/current_script_background_color")); + + } else if (script_temperature_enabled) { + + if (!n->has_meta("__editor_pass")) { + continue; + } + int pass=n->get_meta("__editor_pass"); + int h = edit_pass - pass; + if (h>hist_size) { + continue; + } + int non_zero_hist_size = ( hist_size == 0 ) ? 1 : hist_size; + float v = Math::ease((edit_pass-pass)/float(non_zero_hist_size),0.4); - script_list->set_item_custom_bg_color(i,hot_color.linear_interpolate(cold_color,v)); + script_list->set_item_custom_bg_color(i,hot_color.linear_interpolate(cold_color,v)); + } } } @@ -1476,6 +1534,7 @@ void ScriptEditor::edit(const Ref<Script>& p_script, bool p_grab_focus) { } ERR_FAIL_COND(!se); tab_container->add_child(se); + se->set_edited_script(p_script); se->set_tooltip_request_func("_get_debug_tooltip",this); if (se->get_edit_menu()) { @@ -1497,6 +1556,11 @@ void ScriptEditor::edit(const Ref<Script>& p_script, bool p_grab_focus) { _save_layout(); se->connect("name_changed",this,"_update_script_names"); se->connect("request_help_search",this,"_help_search"); + se->connect("request_open_script_at_line",this,"_goto_script_line"); + se->connect("go_to_help",this,"_help_class_goto"); + se->connect("request_save_history",this,"_save_history"); + + //test for modification, maybe the script was not edited but was loaded @@ -1556,6 +1620,7 @@ void ScriptEditor::apply_scripts() const { void ScriptEditor::_editor_play() { debugger->start(); + debug_menu->get_popup()->grab_focus(); debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_NEXT), true ); debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_STEP), true ); debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_BREAK), false ); @@ -1653,6 +1718,7 @@ void ScriptEditor::_editor_settings_changed() { se->update_settings(); } + _update_script_colors(); ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/auto_reload_and_parse_scripts_on_save",true)); @@ -1802,7 +1868,6 @@ void ScriptEditor::_help_class_open(const String& p_class) { void ScriptEditor::_help_class_goto(const String& p_desc) { - String cname=p_desc.get_slice(":",1); for(int i=0;i<tab_container->get_child_count();i++) { @@ -1972,6 +2037,7 @@ void ScriptEditor::_bind_methods() { ObjectTypeDB::bind_method("_menu_option",&ScriptEditor::_menu_option); ObjectTypeDB::bind_method("_close_current_tab",&ScriptEditor::_close_current_tab); ObjectTypeDB::bind_method("_close_docs_tab", &ScriptEditor::_close_docs_tab); + ObjectTypeDB::bind_method("_close_all_tabs", &ScriptEditor::_close_all_tabs); ObjectTypeDB::bind_method("_editor_play",&ScriptEditor::_editor_play); ObjectTypeDB::bind_method("_editor_pause",&ScriptEditor::_editor_pause); ObjectTypeDB::bind_method("_editor_stop",&ScriptEditor::_editor_stop); @@ -1982,6 +2048,8 @@ void ScriptEditor::_bind_methods() { ObjectTypeDB::bind_method("_goto_script_line",&ScriptEditor::_goto_script_line); ObjectTypeDB::bind_method("_goto_script_line2",&ScriptEditor::_goto_script_line2); ObjectTypeDB::bind_method("_help_search",&ScriptEditor::_help_search); + ObjectTypeDB::bind_method("_save_history",&ScriptEditor::_save_history); + ObjectTypeDB::bind_method("_breaked",&ScriptEditor::_breaked); @@ -2052,8 +2120,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Script"), KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_R), FILE_TOOL_RELOAD_SOFT); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_previous", TTR("History Prev"), KEY_MASK_CTRL|KEY_MASK_ALT|KEY_LEFT), WINDOW_PREV); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_next", TTR("History Next"), KEY_MASK_CTRL|KEY_MASK_ALT|KEY_RIGHT), WINDOW_NEXT); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_previous", TTR("History Prev"), KEY_MASK_ALT|KEY_LEFT), WINDOW_PREV); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_next", TTR("History Next"), KEY_MASK_ALT|KEY_RIGHT), WINDOW_NEXT); file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/import_theme", TTR("Import Theme")), FILE_IMPORT_THEME); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_theme", TTR("Reload Theme")), FILE_RELOAD_THEME); @@ -2062,6 +2130,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_docs", TTR("Close Docs")), CLOSE_DOCS); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_file", TTR("Close"), KEY_MASK_CMD | KEY_W), FILE_CLOSE); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_all", TTR("Close All")), CLOSE_ALL); file_menu->get_popup()->connect("item_pressed", this,"_menu_option"); @@ -2356,9 +2425,11 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) { EDITOR_DEF("external_editor/use_external_editor",false); EDITOR_DEF("external_editor/exec_path",""); EDITOR_DEF("text_editor/script_temperature_enabled",true); + EDITOR_DEF("text_editor/highlight_current_script", true); EDITOR_DEF("text_editor/script_temperature_history_size",15); EDITOR_DEF("text_editor/script_temperature_hot_color",Color(1,0,0,0.3)); EDITOR_DEF("text_editor/script_temperature_cold_color",Color(0,0,1,0.3)); + EDITOR_DEF("text_editor/current_script_background_color",Color(0.81,0.81,0.14,0.63)); EDITOR_DEF("text_editor/group_help_pages",true); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"external_editor/exec_path",PROPERTY_HINT_GLOBAL_FILE)); EDITOR_DEF("external_editor/exec_flags",""); diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h index 1a23ffed72..10f3bce14e 100644 --- a/tools/editor/plugins/script_editor_plugin.h +++ b/tools/editor/plugins/script_editor_plugin.h @@ -78,7 +78,8 @@ class ScriptEditorDebugger; class ScriptEditorBase : public Control { OBJ_TYPE( ScriptEditorBase, Control ); - +protected: + static void _bind_methods(); public: virtual void apply_code()=0; @@ -133,6 +134,7 @@ class ScriptEditor : public VBoxContainer { FILE_SAVE_THEME_AS, FILE_CLOSE, CLOSE_DOCS, + CLOSE_ALL, FILE_TOOL_RELOAD, FILE_TOOL_RELOAD_SOFT, DEBUG_NEXT, @@ -221,6 +223,9 @@ class ScriptEditor : public VBoxContainer { void _close_current_tab(); void _close_docs_tab(); + void _close_all_tabs(); + + void _ask_close_current_unsaved_tab(ScriptEditorBase *current); bool grab_focus_block; @@ -278,6 +283,7 @@ class ScriptEditor : public VBoxContainer { void _help_class_open(const String& p_class); void _help_class_goto(const String& p_desc); void _update_history_arrows(); + void _save_history(); void _go_to_tab(int p_idx); void _update_history_pos(int p_new_pos); void _update_script_colors(); diff --git a/tools/editor/plugins/script_text_editor.cpp b/tools/editor/plugins/script_text_editor.cpp index 57cf8cbea3..40fc3a7bda 100644 --- a/tools/editor/plugins/script_text_editor.cpp +++ b/tools/editor/plugins/script_text_editor.cpp @@ -30,6 +30,7 @@ #include "tools/editor/editor_settings.h" #include "os/keyboard.h" #include "tools/editor/script_editor_debugger.h" +#include "tools/editor/editor_node.h" Vector<String> ScriptTextEditor::get_functions() { @@ -248,17 +249,7 @@ void ScriptTextEditor::add_callback(const String& p_function,StringArray p_args) void ScriptTextEditor::update_settings() { - code_editor->get_text_edit()->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/auto_brace_complete")); - code_editor->get_text_edit()->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/scroll_past_end_of_file")); - code_editor->get_text_edit()->set_tab_size(EditorSettings::get_singleton()->get("text_editor/tab_size")); - code_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/draw_tabs")); - code_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/show_line_numbers")); - code_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/syntax_highlighting")); - code_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlight_all_occurrences")); - code_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/caret_blink")); - code_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/caret_blink_speed")); - code_editor->get_text_edit()->set_draw_breakpoint_gutter(EditorSettings::get_singleton()->get("text_editor/show_breakpoint_gutter")); - code_editor->get_text_edit()->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/block_caret")); + code_editor->update_editor_settings(); } bool ScriptTextEditor::is_unsaved() { @@ -497,6 +488,7 @@ void ScriptTextEditor::_code_complete_scripts(void* p_ud,const String& p_code, L void ScriptTextEditor::_code_complete_script(const String& p_code, List<String>* r_options) { + if (color_panel->is_visible()) return; Node *base = get_tree()->get_edited_scene_root(); if (base) { base = _find_node_for_script(base,base,script); @@ -525,6 +517,74 @@ static void swap_lines(TextEdit *tx, int line1, int line2) tx->cursor_set_line(line2); } +void ScriptTextEditor::_lookup_symbol(const String& p_symbol,int p_row, int p_column) { + + Node *base = get_tree()->get_edited_scene_root(); + if (base) { + base = _find_node_for_script(base,base,script); + } + + + ScriptLanguage::LookupResult result; + if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(),p_symbol,script->get_path().get_base_dir(),base,result)==OK) { + + _goto_line(p_row); + + switch(result.type) { + case ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION: { + + if (result.script.is_valid()) { + emit_signal("request_open_script_at_line",result.script,result.location-1); + } else { + emit_signal("request_save_history"); + _goto_line(result.location-1); + } + } break; + case ScriptLanguage::LookupResult::RESULT_CLASS: { + emit_signal("go_to_help","class_name:"+result.class_name); + } break; + case ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT: { + + StringName cname = result.class_name; + bool success; + while(true) { + ObjectTypeDB::get_integer_constant(cname,result.class_member,&success); + if (success) { + result.class_name=cname; + cname=ObjectTypeDB::type_inherits_from(cname); + } else { + break; + } + } + + + emit_signal("go_to_help","class_constant:"+result.class_name+":"+result.class_member); + + } break; + case ScriptLanguage::LookupResult::RESULT_CLASS_PROPERTY: { + emit_signal("go_to_help","class_property:"+result.class_name+":"+result.class_member); + + } break; + case ScriptLanguage::LookupResult::RESULT_CLASS_METHOD: { + + StringName cname = result.class_name; + + while(true) { + if (ObjectTypeDB::has_method(cname,result.class_member)) { + result.class_name=cname; + cname=ObjectTypeDB::type_inherits_from(cname); + } else { + break; + } + } + + emit_signal("go_to_help","class_method:"+result.class_name+":"+result.class_member); + + } break; + } + + } +} void ScriptTextEditor::_edit_option(int p_op) { @@ -813,6 +873,9 @@ void ScriptTextEditor::_edit_option(int p_op) { case EDIT_TRIM_TRAILING_WHITESAPCE: { trim_trailing_whitespace(); } break; + case EDIT_PICK_COLOR: { + color_panel->popup(); + } break; case SEARCH_FIND: { @@ -919,9 +982,15 @@ void ScriptTextEditor::_bind_methods() { ObjectTypeDB::bind_method("_breakpoint_toggled",&ScriptTextEditor::_breakpoint_toggled); ObjectTypeDB::bind_method("_edit_option",&ScriptTextEditor::_edit_option); ObjectTypeDB::bind_method("_goto_line",&ScriptTextEditor::_goto_line); + ObjectTypeDB::bind_method("_lookup_symbol",&ScriptTextEditor::_lookup_symbol); + ObjectTypeDB::bind_method("_text_edit_input_event", &ScriptTextEditor::_text_edit_input_event); + ObjectTypeDB::bind_method("_color_changed", &ScriptTextEditor::_color_changed); + + + ObjectTypeDB::bind_method("get_drag_data_fw",&ScriptTextEditor::get_drag_data_fw); + ObjectTypeDB::bind_method("can_drop_data_fw",&ScriptTextEditor::can_drop_data_fw); + ObjectTypeDB::bind_method("drop_data_fw",&ScriptTextEditor::drop_data_fw); - ADD_SIGNAL(MethodInfo("name_changed")); - ADD_SIGNAL(MethodInfo("request_help_search",PropertyInfo(Variant::STRING,"topic"))); } Control *ScriptTextEditor::get_edit_menu() { @@ -957,6 +1026,234 @@ void ScriptTextEditor::set_debugger_active(bool p_active) { } + +Variant ScriptTextEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) { + + return Variant(); +} + +bool ScriptTextEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{ + + Dictionary d = p_data; + if (d.has("type") && + ( + + String(d["type"])=="resource" || + String(d["type"])=="files" || + String(d["type"])=="nodes" + ) ) { + + + return true; + } + + + return false; + +} + +#ifdef TOOLS_ENABLED + +static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const Ref<Script> &script) { + + if (p_edited_scene!=p_current_node && p_current_node->get_owner()!=p_edited_scene) + return NULL; + + Ref<Script> scr = p_current_node->get_script(); + + if (scr.is_valid() && scr==script) + return p_current_node; + + for(int i=0;i<p_current_node->get_child_count();i++) { + Node *n = _find_script_node(p_edited_scene,p_current_node->get_child(i),script); + if (n) + return n; + } + + return NULL; +} + +#else + +static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const Ref<Script> &script) { + + return NULL; +} +#endif + + + + +void ScriptTextEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){ + + Dictionary d = p_data; + + if (d.has("type") && String(d["type"])=="resource") { + + Ref<Resource> res = d["resource"]; + if (!res.is_valid()) { + return; + } + + if (res->get_path().is_resource_file()) { + EditorNode::get_singleton()->show_warning("Only resources from filesystem can be dropped."); + return; + } + + code_editor->get_text_edit()->insert_text_at_cursor(res->get_path()); + + } + + if (d.has("type") && String(d["type"])=="files") { + + + Array files = d["files"]; + + String text_to_drop; + for(int i=0;i<files.size();i++) { + + if (i>0) + text_to_drop+=","; + text_to_drop+="\""+String(files[i]).c_escape()+"\""; + + } + + code_editor->get_text_edit()->insert_text_at_cursor(text_to_drop); + + } + + if (d.has("type") && String(d["type"])=="nodes") { + + Node* sn = _find_script_node(get_tree()->get_edited_scene_root(),get_tree()->get_edited_scene_root(),script); + + + if (!sn) { + EditorNode::get_singleton()->show_warning("Can't drop nodes because script '"+get_name()+"' is not used in this scene."); + return; + } + + + Array nodes = d["nodes"]; + String text_to_drop; + for(int i=0;i<nodes.size();i++) { + + if (i>0) + text_to_drop+=","; + + NodePath np = nodes[i]; + Node *node = get_node(np); + if (!node) { + continue; + } + + + + String path = sn->get_path_to(node); + text_to_drop+="\""+path.c_escape()+"\""; + + + } + + code_editor->get_text_edit()->insert_text_at_cursor(text_to_drop); + + + } + + + +} + +void ScriptTextEditor::_text_edit_input_event(const InputEvent& ev) { + if (ev.type == InputEvent::MOUSE_BUTTON) { + InputEventMouseButton mb = ev.mouse_button; + if (mb.button_index == BUTTON_RIGHT && !mb.pressed) { + + int col, row; + TextEdit* tx = code_editor->get_text_edit(); + tx->_get_mouse_pos(Point2i(mb.global_x, mb.global_y)-tx->get_global_pos(), row, col); + Vector2 mpos = Vector2(mb.global_x, mb.global_y)-tx->get_global_pos(); + bool have_selection = (tx->get_selection_text().length() > 0); + bool have_color = (tx->get_word_at_pos(mpos) == "Color"); + if (have_color) { + + String line = tx->get_line(row); + color_line = row; + int begin = 0; + int end = 0; + bool valid = false; + for (int i = col; i < line.length(); i++) { + if (line[i] == '(') { + begin = i; + continue; + } + else if (line[i] == ')') { + end = i+1; + valid = true; + break; + } + } + if (valid) { + color_args = line.substr(begin, end-begin); + String stripped = color_args.replace(" ", "").replace("(", "").replace(")", ""); + Vector<float> color = stripped.split_floats(","); + if (color.size() > 2) { + float alpha = color.size() > 3 ? color[3] : 1.0f; + color_picker->set_color(Color(color[0], color[1], color[2], alpha)); + } + color_panel->set_pos(get_global_transform().xform(get_local_mouse_pos())); + Size2 ms = Size2(300, color_picker->get_combined_minimum_size().height+10); + color_panel->set_size(ms); + } else { + have_color = false; + } + } + _make_context_menu(have_selection, have_color); + } + } +} + +void ScriptTextEditor::_color_changed(const Color& p_color) { + String new_args; + if (p_color.a == 1.0f) { + new_args = String("("+rtos(p_color.r)+", "+rtos(p_color.g)+", "+rtos(p_color.b)+")"); + } else { + new_args = String("("+rtos(p_color.r)+", "+rtos(p_color.g)+", "+rtos(p_color.b)+", "+rtos(p_color.a)+")"); + } + + String line = code_editor->get_text_edit()->get_line(color_line); + String new_line = line.replace(color_args, new_args); + color_args = new_args; + code_editor->get_text_edit()->set_line(color_line, new_line); +} + +void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color) { + + context_menu->clear(); + if (p_selection) { + context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut")); + context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy")); + } + + context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste")); + context_menu->add_separator(); + context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all")); + context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo")); + + if (p_selection) { + context_menu->add_separator(); + context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_left")); + context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right")); + context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment")); + } + if (p_color) { + context_menu->add_separator(); + context_menu->add_item(TTR("Pick Color"), EDIT_PICK_COLOR); + } + context_menu->set_pos(get_global_transform().xform(get_local_mouse_pos())); + context_menu->set_size(Vector2(1, 1)); + context_menu->popup(); +} + ScriptTextEditor::ScriptTextEditor() { code_editor = memnew( CodeTextEditor ); @@ -966,22 +1263,29 @@ ScriptTextEditor::ScriptTextEditor() { code_editor->connect("load_theme_settings",this,"_load_theme_settings"); code_editor->set_code_complete_func(_code_complete_scripts,this); code_editor->get_text_edit()->connect("breakpoint_toggled", this, "_breakpoint_toggled"); + code_editor->get_text_edit()->connect("symbol_lookup", this, "_lookup_symbol"); + + update_settings(); - code_editor->get_text_edit()->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/scroll_past_end_of_file")); - code_editor->get_text_edit()->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/auto_brace_complete")); - code_editor->get_text_edit()->set_tab_size(EditorSettings::get_singleton()->get("text_editor/tab_size")); - code_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/draw_tabs")); - code_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/show_line_numbers")); - code_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/syntax_highlighting")); - code_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlight_all_occurrences")); - code_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/caret_blink")); - code_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/caret_blink_speed")); - code_editor->get_text_edit()->set_draw_breakpoint_gutter(EditorSettings::get_singleton()->get("text_editor/show_breakpoint_gutter")); - code_editor->get_text_edit()->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/block_caret")); code_editor->get_text_edit()->set_callhint_settings( EditorSettings::get_singleton()->get("text_editor/put_callhint_tooltip_below_current_line"), EditorSettings::get_singleton()->get("text_editor/callhint_tooltip_offset")); + code_editor->get_text_edit()->set_select_identifiers_on_hover(true); + code_editor->get_text_edit()->set_context_menu_enabled(false); + code_editor->get_text_edit()->connect("input_event", this, "_text_edit_input_event"); + + context_menu = memnew(PopupMenu); + add_child(context_menu); + context_menu->connect("item_pressed", this, "_edit_option"); + + color_panel = memnew(PopupPanel); + add_child(color_panel); + color_picker = memnew(ColorPicker); + color_panel->add_child(color_picker); + color_panel->set_child_rect(color_picker); + color_picker->connect("color_changed", this, "_color_changed"); + edit_hb = memnew (HBoxContainer); edit_menu = memnew( MenuButton ); @@ -1039,6 +1343,9 @@ ScriptTextEditor::ScriptTextEditor() { goto_line_dialog = memnew(GotoLineDialog); add_child(goto_line_dialog); + + + code_editor->get_text_edit()->set_drag_forwarding(this); } static ScriptEditorBase * create_editor(const Ref<Script>& p_script) { diff --git a/tools/editor/plugins/script_text_editor.h b/tools/editor/plugins/script_text_editor.h index 247fd97e81..ceef50f0bc 100644 --- a/tools/editor/plugins/script_text_editor.h +++ b/tools/editor/plugins/script_text_editor.h @@ -30,6 +30,7 @@ #define SCRIPT_TEXT_EDITOR_H #include "script_editor_plugin.h" +#include "scene/gui/color_picker.h" class ScriptTextEditor : public ScriptEditorBase { @@ -47,10 +48,16 @@ class ScriptTextEditor : public ScriptEditorBase { MenuButton *edit_menu; MenuButton *search_menu; + PopupMenu *context_menu; GotoLineDialog *goto_line_dialog; ScriptEditorQuickOpen *quick_open; + PopupPanel *color_panel; + ColorPicker *color_picker; + int color_line; + String color_args; + enum { EDIT_UNDO, EDIT_REDO, @@ -67,6 +74,7 @@ class ScriptTextEditor : public ScriptEditorBase { EDIT_INDENT_RIGHT, EDIT_INDENT_LEFT, EDIT_CLONE_DOWN, + EDIT_PICK_COLOR, SEARCH_FIND, SEARCH_FIND_NEXT, SEARCH_FIND_PREV, @@ -96,8 +104,17 @@ protected: static void _bind_methods(); void _edit_option(int p_op); + void _make_context_menu(bool p_selection, bool p_color); + void _text_edit_input_event(const InputEvent& ev); + void _color_changed(const Color& p_color); void _goto_line(int p_line) { goto_line(p_line); } + void _lookup_symbol(const String& p_symbol,int p_row, int p_column); + + Variant get_drag_data_fw(const Point2& p_point,Control* p_from); + bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const; + void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from); + public: virtual void apply_code(); diff --git a/tools/editor/plugins/shader_editor_plugin.cpp b/tools/editor/plugins/shader_editor_plugin.cpp index b3317e8313..861f5678f6 100644 --- a/tools/editor/plugins/shader_editor_plugin.cpp +++ b/tools/editor/plugins/shader_editor_plugin.cpp @@ -155,7 +155,7 @@ void ShaderTextEditor::_validate_script() { Error err = ShaderLanguage::compile(code,type,NULL,NULL,&errortxt,&line,&col); if (err!=OK) { - String error_text="error("+itos(line+1)+","+itos(col)+"): "+errortxt; + String error_text="error("+itos(line+1)+","+itos(col+1)+"): "+errortxt; set_error(error_text); get_text_edit()->set_line_as_marked(line,true); @@ -372,41 +372,9 @@ void ShaderEditor::_params_changed() { void ShaderEditor::_editor_settings_changed() { - vertex_editor->get_text_edit()->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/auto_brace_complete")); - vertex_editor->get_text_edit()->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/scroll_past_end_of_file")); - vertex_editor->get_text_edit()->set_tab_size(EditorSettings::get_singleton()->get("text_editor/tab_size")); - vertex_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/draw_tabs")); - vertex_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/show_line_numbers")); - vertex_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/syntax_highlighting")); - vertex_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlight_all_occurrences")); - vertex_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/caret_blink")); - vertex_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/caret_blink_speed")); - vertex_editor->get_text_edit()->add_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/line_spacing")); - vertex_editor->get_text_edit()->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/block_caret")); - - fragment_editor->get_text_edit()->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/auto_brace_complete")); - fragment_editor->get_text_edit()->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/scroll_past_end_of_file")); - fragment_editor->get_text_edit()->set_tab_size(EditorSettings::get_singleton()->get("text_editor/tab_size")); - fragment_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/draw_tabs")); - fragment_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/show_line_numbers")); - fragment_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/syntax_highlighting")); - fragment_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlight_all_occurrences")); - fragment_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/caret_blink")); - fragment_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/caret_blink_speed")); - fragment_editor->get_text_edit()->add_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/line_spacing")); - fragment_editor->get_text_edit()->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/block_caret")); - - light_editor->get_text_edit()->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/auto_brace_complete")); - light_editor->get_text_edit()->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/scroll_past_end_of_file")); - light_editor->get_text_edit()->set_tab_size(EditorSettings::get_singleton()->get("text_editor/tab_size")); - light_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/draw_tabs")); - light_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/show_line_numbers")); - light_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/syntax_highlighting")); - light_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlight_all_occurrences")); - light_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/caret_blink")); - light_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/caret_blink_speed")); - light_editor->get_text_edit()->add_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/line_spacing")); - light_editor->get_text_edit()->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/block_caret")); + vertex_editor->update_editor_settings(); + fragment_editor->update_editor_settings(); + light_editor->update_editor_settings(); } void ShaderEditor::_bind_methods() { diff --git a/tools/editor/plugins/shader_graph_editor_plugin.cpp b/tools/editor/plugins/shader_graph_editor_plugin.cpp index 815da48e96..3ab906f84e 100644 --- a/tools/editor/plugins/shader_graph_editor_plugin.cpp +++ b/tools/editor/plugins/shader_graph_editor_plugin.cpp @@ -901,6 +901,7 @@ void ShaderGraphView::_variant_edited() { case Variant::COLOR: v2=Color(); break; + default: {} } UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Default Value")); @@ -1321,6 +1322,7 @@ void ShaderGraphView::_default_changed(int p_id, Node *p_button, int p_param, in h=PROPERTY_HINT_COLOR_NO_ALPHA; v=Color(); break; + default: {} } ped_popup->edit(NULL,"",vt,v,h,p_hint); @@ -1347,6 +1349,8 @@ ToolButton *ShaderGraphView::make_label(String text, Variant::Type v_type) { break; case Variant::COLOR: l->set_icon(ped_popup->get_icon("Color", "EditorIcons")); + break; + default: {} } return l; } @@ -1372,7 +1376,7 @@ ToolButton *ShaderGraphView::make_editor(String text,GraphNode* gn,int p_id,int case Variant::TRANSFORM: edit->set_icon(ped_popup->get_icon("Matrix", "EditorIcons")); break; - case Variant::COLOR: + case Variant::COLOR: { Image icon_color = Image(15,15,false,Image::FORMAT_RGB); Color c = graph->default_get_value(type,p_id,param); for (int x=1;x<14;x++) @@ -1382,7 +1386,8 @@ ToolButton *ShaderGraphView::make_editor(String text,GraphNode* gn,int p_id,int t.instance(); t->create_from_image(icon_color); edit->set_icon(t); - break; + } break; + default: {} } return edit; } @@ -2417,6 +2422,7 @@ void ShaderGraphView::_create_node(int p_id) { colors.push_back("Color"); colors.push_back("LightColor"); colors.push_back("Light"); + colors.push_back("ShadowColor"); colors.push_back("Diffuse"); colors.push_back("Specular"); colors.push_back("Emmision"); @@ -2429,6 +2435,7 @@ void ShaderGraphView::_create_node(int p_id) { reals.push_back("ShadeParam"); reals.push_back("SpecularExp"); reals.push_back("LightAlpha"); + reals.push_back("ShadowAlpha"); reals.push_back("PointSize"); reals.push_back("Discard"); diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp index 95106d2c81..6dcc71422a 100644 --- a/tools/editor/plugins/spatial_editor_plugin.cpp +++ b/tools/editor/plugins/spatial_editor_plugin.cpp @@ -1978,6 +1978,11 @@ void SpatialEditorViewport::_menu_option(int p_option) { _update_name(); } break; + case VIEW_CENTER_TO_ORIGIN: { + + cursor.pos = Vector3(0,0,0); + + } break; case VIEW_CENTER_TO_SELECTION: { focus_selection(); @@ -2391,6 +2396,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_GIZMOS),true); view_menu->get_popup()->add_separator(); + view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/focus_origin"), VIEW_CENTER_TO_ORIGIN); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/focus_selection"), VIEW_CENTER_TO_SELECTION); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/align_selection_with_view"), VIEW_ALIGN_SELECTION_WITH_VIEW); view_menu->get_popup()->connect("item_pressed",this,"_menu_option"); @@ -3151,6 +3157,8 @@ void SpatialEditor::_init_indicators() { Vector<Color> origin_colors; Vector<Vector3> origin_points; + Color grid_color = EditorSettings::get_singleton()->get("3d_editor/grid_color"); + for(int i=0;i<3;i++) { Vector3 axis; axis[i]=1; @@ -3168,10 +3176,10 @@ void SpatialEditor::_init_indicators() { for(int j=-ORIGIN_GRID_SIZE;j<=ORIGIN_GRID_SIZE;j++) { - grid_colors[i].push_back(Color(axis.x,axis.y,axis.z,0.2)); - grid_colors[i].push_back(Color(axis.x,axis.y,axis.z,0.2)); - grid_colors[i].push_back(Color(axis.x,axis.y,axis.z,0.2)); - grid_colors[i].push_back(Color(axis.x,axis.y,axis.z,0.2)); + grid_colors[i].push_back(grid_color); + grid_colors[i].push_back(grid_color); + grid_colors[i].push_back(grid_color); + grid_colors[i].push_back(grid_color); grid_points[i].push_back(axis_n1*ORIGIN_GRID_SIZE+axis_n2*j); grid_points[i].push_back(-axis_n1*ORIGIN_GRID_SIZE+axis_n2*j); grid_points[i].push_back(axis_n2*ORIGIN_GRID_SIZE+axis_n1*j); @@ -3467,6 +3475,8 @@ void SpatialEditor::_unhandled_key_input(InputEvent p_event) { if (!is_visible() || get_viewport()->gui_has_modal_stack()) return; +#if 0 +//i don't remember this being used, why was it here? { EditorNode *en = editor; @@ -3478,6 +3488,7 @@ void SpatialEditor::_unhandled_key_input(InputEvent p_event) { } } +#endif switch(p_event.type) { @@ -3853,6 +3864,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { ED_SHORTCUT("spatial_editor/switch_perspective_orthogonal", TTR("Switch Perspective/Orthogonal view"), KEY_KP_5); ED_SHORTCUT("spatial_editor/snap", TTR("Snap"), KEY_S); ED_SHORTCUT("spatial_editor/insert_anim_key", TTR("Insert Animation Key"), KEY_K); + ED_SHORTCUT("spatial_editor/focus_origin", TTR("Focus Origin"), KEY_O); ED_SHORTCUT("spatial_editor/focus_selection", TTR("Focus Selection"), KEY_F); ED_SHORTCUT("spatial_editor/align_selection_with_view", TTR("Align Selection With View"), KEY_MASK_ALT+KEY_MASK_CMD+KEY_F); diff --git a/tools/editor/plugins/spatial_editor_plugin.h b/tools/editor/plugins/spatial_editor_plugin.h index 975092a01d..89587526ee 100644 --- a/tools/editor/plugins/spatial_editor_plugin.h +++ b/tools/editor/plugins/spatial_editor_plugin.h @@ -76,6 +76,7 @@ friend class SpatialEditor; VIEW_RIGHT, VIEW_FRONT, VIEW_REAR, + VIEW_CENTER_TO_ORIGIN, VIEW_CENTER_TO_SELECTION, VIEW_ALIGN_SELECTION_WITH_VIEW, VIEW_PERSPECTIVE, diff --git a/tools/editor/plugins/texture_region_editor_plugin.cpp b/tools/editor/plugins/texture_region_editor_plugin.cpp index 43086fb208..6b918e6e8f 100644 --- a/tools/editor/plugins/texture_region_editor_plugin.cpp +++ b/tools/editor/plugins/texture_region_editor_plugin.cpp @@ -653,6 +653,7 @@ void TextureRegionEditor::edit(Object *p_obj) } else { p_obj->connect("texture_changed",this,"_edit_region"); } + p_obj->add_change_receptor(this); p_obj->connect("exit_tree",this,"_node_removed",varray(p_obj),CONNECT_ONESHOT); _edit_region(); } else { @@ -673,6 +674,12 @@ void TextureRegionEditor::edit(Object *p_obj) edit_draw->update(); } +void TextureRegionEditor::_changed_callback(Object *p_changed, const char *p_prop) { + if ((String)p_prop == "region_rect") { + _edit_region(); + } +} + void TextureRegionEditor::_edit_region() { Ref<Texture> texture = NULL; diff --git a/tools/editor/plugins/texture_region_editor_plugin.h b/tools/editor/plugins/texture_region_editor_plugin.h index 3658a38f11..f0bb7c9bc2 100644 --- a/tools/editor/plugins/texture_region_editor_plugin.h +++ b/tools/editor/plugins/texture_region_editor_plugin.h @@ -116,6 +116,8 @@ protected: Vector2 snap_point(Vector2 p_target) const; + virtual void _changed_callback(Object *p_changed, const char *p_prop); + public: void _edit_region(); diff --git a/tools/editor/plugins/theme_editor_plugin.cpp b/tools/editor/plugins/theme_editor_plugin.cpp index 5db331ba45..84568aa8c0 100644 --- a/tools/editor/plugins/theme_editor_plugin.cpp +++ b/tools/editor/plugins/theme_editor_plugin.cpp @@ -668,7 +668,7 @@ ThemeEditor::ThemeEditor() { theme_menu = memnew( MenuButton ); - theme_menu->set_text("Theme"); + theme_menu->set_text(TTR("Theme")); theme_menu->get_popup()->add_item(TTR("Add Item"),POPUP_ADD); theme_menu->get_popup()->add_item(TTR("Add Class Items"),POPUP_CLASS_ADD); theme_menu->get_popup()->add_item(TTR("Remove Item"),POPUP_REMOVE); diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp index 822d9e6c87..43fe7d7ea9 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.cpp +++ b/tools/editor/plugins/tile_map_editor_plugin.cpp @@ -289,15 +289,16 @@ void TileMapEditor::_pick_tile(const Point2& p_pos) { canvas_item_editor->update(); } -DVector<Vector2> TileMapEditor::_bucket_fill(const Point2i& p_start) { +DVector<Vector2> TileMapEditor::_bucket_fill(const Point2i& p_start, bool erase) { - if (node->get_cell(p_start.x, p_start.y) != TileMap::INVALID_CELL) - return DVector<Vector2>(); + int prev_id = node->get_cell(p_start.x, p_start.y); + int id = TileMap::INVALID_CELL; + if (!erase) { + id = get_selected_tile(); - int id = get_selected_tile(); - - if (id == TileMap::INVALID_CELL) - return DVector<Vector2>(); + if (id == TileMap::INVALID_CELL) + return DVector<Vector2>(); + } Rect2 r = node->get_item_rect(); r.pos = r.pos/node->get_cell_size(); @@ -316,7 +317,7 @@ DVector<Vector2> TileMapEditor::_bucket_fill(const Point2i& p_start) { if (!r.has_point(n)) continue; - if (node->get_cell(n.x, n.y) == TileMap::INVALID_CELL) { + if (node->get_cell(n.x, n.y) == prev_id) { node->set_cellv(n, id, flip_h, flip_v, transpose); @@ -685,6 +686,12 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { } else if (tool==TOOL_BUCKET) { + Dictionary pop; + pop["id"] = node->get_cell(over_tile.x, over_tile.y); + pop["flip_h"] = node->is_cell_x_flipped(over_tile.x, over_tile.y); + pop["flip_v"] = node->is_cell_y_flipped(over_tile.x, over_tile.y); + pop["transpose"] = node->is_cell_transposed(over_tile.x, over_tile.y); + DVector<Vector2> points = _bucket_fill(over_tile); if (points.size() == 0) @@ -699,7 +706,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { undo_redo->create_action("Bucket Fill"); undo_redo->add_do_method(this, "_fill_points", points, op); - undo_redo->add_undo_method(this, "_erase_points", points); + undo_redo->add_undo_method(this, "_fill_points", points, pop); undo_redo->commit_action(); } @@ -782,6 +789,26 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { tool=TOOL_NONE; return true; + + } else if (tool==TOOL_BUCKET) { + + Dictionary pop; + pop["id"] = node->get_cell(over_tile.x, over_tile.y); + pop["flip_h"] = node->is_cell_x_flipped(over_tile.x, over_tile.y); + pop["flip_v"] = node->is_cell_y_flipped(over_tile.x, over_tile.y); + pop["transpose"] = node->is_cell_transposed(over_tile.x, over_tile.y); + + DVector<Vector2> points = _bucket_fill(over_tile, true); + + if (points.size() == 0) + return false; + + undo_redo->create_action("Bucket Fill"); + + undo_redo->add_do_method(this, "_erase_points", points); + undo_redo->add_undo_method(this, "_fill_points", points, pop); + + undo_redo->commit_action(); } } } @@ -798,7 +825,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { canvas_item_editor->update(); } - int tile_under = node->get_cell(over_tile.x, over_tile.y); + int tile_under = node->get_cell(over_tile.x, over_tile.y); String tile_name = "none"; if (node->get_tileset()->has_tile(tile_under)) diff --git a/tools/editor/plugins/tile_map_editor_plugin.h b/tools/editor/plugins/tile_map_editor_plugin.h index 666290489b..2f24002770 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.h +++ b/tools/editor/plugins/tile_map_editor_plugin.h @@ -129,7 +129,7 @@ class TileMapEditor : public VBoxContainer { void _pick_tile(const Point2& p_pos); - DVector<Vector2> _bucket_fill(const Point2i& p_start); + DVector<Vector2> _bucket_fill(const Point2i& p_start, bool erase=false); void _fill_points(const DVector<Vector2> p_points, const Dictionary& p_op); void _erase_points(const DVector<Vector2> p_points); @@ -181,7 +181,7 @@ class TileMapEditorPlugin : public EditorPlugin { public: - virtual bool forward_input_event(const InputEvent& p_event) { return tile_map_editor->forward_input_event(p_event); } + virtual bool forward_canvas_input_event(const Matrix32& p_canvas_xform,const InputEvent& p_event) { return tile_map_editor->forward_input_event(p_event); } virtual String get_name() const { return "TileMap"; } bool has_main_screen() const { return false; } diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp index dc1d6ec0f9..1c99982155 100644 --- a/tools/editor/project_manager.cpp +++ b/tools/editor/project_manager.cpp @@ -142,6 +142,7 @@ private: String sp = p.simplify_path(); project_path->set_text(sp); _path_text_changed(p); + get_ok()->call_deferred("grab_focus"); } void _path_selected(const String& p_path) { @@ -150,7 +151,7 @@ private: String sp = p.simplify_path(); project_path->set_text(sp); _path_text_changed(p); - + get_ok()->call_deferred("grab_focus"); } void _browse_path() { @@ -506,7 +507,7 @@ void ProjectManager::_panel_draw(Node *p_hb) { hb->draw_line(Point2(0,hb->get_size().y+1),Point2(hb->get_size().x-10,hb->get_size().y+1),get_color("guide_color","Tree")); if (selected_list.has(hb->get_meta("name"))) { - hb->draw_style_box(get_stylebox("selected","Tree"),Rect2(Point2(),hb->get_size()-Size2(10,0))); + hb->draw_style_box( gui_base->get_stylebox("selected","Tree"),Rect2(Point2(),hb->get_size()-Size2(10,0))); } } @@ -753,7 +754,7 @@ void ProjectManager::_load_recent_projects() { List<PropertyInfo> properties; EditorSettings::get_singleton()->get_property_list(&properties); - Color font_color = get_color("font_color","Tree"); + Color font_color = gui_base->get_color("font_color","Tree"); List<ProjectItem> projects; List<ProjectItem> favorite_projects; @@ -864,6 +865,7 @@ void ProjectManager::_load_recent_projects() { hb->set_meta("favorite",is_favorite); hb->connect("draw",this,"_panel_draw",varray(hb)); hb->connect("input_event",this,"_panel_input",varray(hb)); + hb->add_constant_override("separation",10*EDSCALE); VBoxContainer *favorite_box = memnew( VBoxContainer ); TextureButton *favorite = memnew( TextureButton ); @@ -885,7 +887,7 @@ void ProjectManager::_load_recent_projects() { ec->set_custom_minimum_size(Size2(0,1)); vb->add_child(ec); Label *title = memnew( Label(project_name) ); - title->add_font_override("font",get_font("large","Fonts")); + title->add_font_override("font", gui_base->get_font("large","Fonts")); title->add_color_override("font_color",font_color); vb->add_child(title); Label *fpath = memnew( Label(path) ); @@ -1185,25 +1187,27 @@ ProjectManager::ProjectManager() { { int dpi_mode = EditorSettings::get_singleton()->get("global/hidpi_mode"); if (dpi_mode==0) { - editor_set_hidpi( OS::get_singleton()->get_screen_dpi(0) > 150 ); + editor_set_scale( OS::get_singleton()->get_screen_dpi(0) > 150 && OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x>2000 ? 2.0 : 1.0 ); + } else if (dpi_mode==1) { + editor_set_scale(0.75); } else if (dpi_mode==2) { - editor_set_hidpi(true); - } else { - editor_set_hidpi(false); + editor_set_scale(1.0); + } else if (dpi_mode==3) { + editor_set_scale(1.5); + } else if (dpi_mode==4) { + editor_set_scale(2.0); } } FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files")); set_area_as_parent_rect(); + set_theme(create_editor_theme()); gui_base = memnew( Control ); add_child(gui_base); gui_base->set_area_as_parent_rect(); - - set_theme(create_default_theme()); - Ref<Theme> theme = create_editor_theme(); - gui_base->set_theme(theme); + gui_base->set_theme(create_custom_theme()); Panel *panel = memnew( Panel ); gui_base->add_child(panel); @@ -1226,7 +1230,7 @@ ProjectManager::ProjectManager() { CenterContainer *ccl = memnew( CenterContainer ); Label *l = memnew( Label ); l->set_text(_MKSTR(VERSION_NAME)+String(" - ")+TTR("Project Manager")); - l->add_font_override("font",get_font("doc","EditorFonts")); + l->add_font_override("font", gui_base->get_font("doc","EditorFonts")); ccl->add_child(l); top_hb->add_child(ccl); top_hb->add_spacer(); @@ -1262,7 +1266,7 @@ ProjectManager::ProjectManager() { search_tree_vb->add_child(search_box); PanelContainer *pc = memnew( PanelContainer); - pc->add_style_override("panel",get_stylebox("bg","Tree")); + pc->add_style_override("panel", gui_base->get_stylebox("bg","Tree")); search_tree_vb->add_child(pc); pc->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 2ea28e26ad..ef6b1aa47c 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -214,6 +214,12 @@ void CustomPropertyEditor::_menu_option(int p_which) { } } } break; + case OBJ_MENU_NEW_SCRIPT: { + + if (owner->cast_to<Node>()) + EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(owner->cast_to<Node>()); + + } break; default: { @@ -322,26 +328,26 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty if (c>=2) { if (!hint_text.get_slice(",",1).empty()) - max=hint_text.get_slice(",",1).to_double(); + max=hint_text.get_slice(",",1).to_double(); } - if (type==Variant::REAL && c>=3) { + if (c>=3) { if (!hint_text.get_slice(",",2).empty()) - step= hint_text.get_slice(",",2).to_double(); + step= hint_text.get_slice(",",2).to_double(); } if (c>=4 && hint_text.get_slice(",",3)=="slider") { slider->set_min(min); slider->set_max(max); - slider->set_step((type==Variant::REAL) ? step : 1); + slider->set_step(step); slider->set_val(v); slider->show(); set_size(Size2(110,30)*EDSCALE); } else { spinbox->set_min(min); spinbox->set_max(max); - spinbox->set_step((type==Variant::REAL) ? step : 1); + spinbox->set_step(step); spinbox->set_val(v); spinbox->show(); set_size(Size2(70,35)*EDSCALE); @@ -850,8 +856,10 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty menu->clear(); menu->set_size(Size2(1,1)); - - if (hint_text!="") { + if (p_name=="script/script" && hint_text=="Script" && owner->cast_to<Node>()) { + menu->add_icon_item(get_icon("Script","EditorIcons"),TTR("New Script"),OBJ_MENU_NEW_SCRIPT); + menu->add_separator(); + } else if (hint_text!="") { int idx=0; for(int i=0;i<hint_text.get_slice_count(",");i++) { @@ -3041,7 +3049,7 @@ void PropertyEditor::update_tree() { if (E) { descr=E->get().brief_description; } - class_descr_cache[type]=descr.world_wrap(80); + class_descr_cache[type]=descr.word_wrap(80); } @@ -3134,7 +3142,7 @@ void PropertyEditor::update_tree() { if (E) { for(int i=0;i<E->get().methods.size();i++) { if (E->get().methods[i].name==setter.operator String()) { - descr=E->get().methods[i].description.strip_edges().world_wrap(80); + descr=E->get().methods[i].description.strip_edges().word_wrap(80); } } } @@ -3174,6 +3182,7 @@ void PropertyEditor::update_tree() { item->set_cell_mode( 1, TreeItem::CELL_MODE_CHECK ); item->set_text(1,TTR("On")); + item->set_tooltip(1, obj->get(p.name) ? "True" : "False"); item->set_checked( 1, obj->get( p.name ) ); if (show_type_icons) item->set_icon( 0, get_icon("Bool","EditorIcons") ); @@ -3249,7 +3258,7 @@ void PropertyEditor::update_tree() { max=p.hint_string.get_slice(",",1).to_double(); } - if (p.type==Variant::REAL && c>=3) { + if (p.type!=PROPERTY_HINT_SPRITE_FRAME && c>=3) { step= p.hint_string.get_slice(",",2).to_double(); } @@ -3604,9 +3613,10 @@ void PropertyEditor::update_tree() { } break; case Variant::NODE_PATH: { - item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM ); + item->set_cell_mode(1, TreeItem::CELL_MODE_STRING); item->set_editable( 1, !read_only ); item->set_text(1,obj->get(p.name)); + item->add_button(1, get_icon("Collapse", "EditorIcons")); } break; case Variant::OBJECT: { @@ -3820,6 +3830,7 @@ void PropertyEditor::_item_edited() { case Variant::BOOL: { _edit_set(name,item->is_checked(1)); + item->set_tooltip(1, item->is_checked(1) ? "True" : "False"); } break; case Variant::INT: case Variant::REAL: { @@ -3882,6 +3893,7 @@ void PropertyEditor::_item_edited() { } break; case Variant::NODE_PATH: { + _edit_set(name, NodePath(item->get_text(1))); } break; @@ -4057,7 +4069,17 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) { String n = d["name"]; String ht = d["hint_text"]; - if (t==Variant::STRING) { + if(t == Variant::NODE_PATH) { + + Variant v = obj->get(n); + custom_editor->edit(obj, n, (Variant::Type)t, v, h, ht); + Rect2 where = tree->get_item_rect(ti, 1); + where.pos -= tree->get_scroll(); + where.pos += tree->get_global_pos(); + custom_editor->set_pos(where.pos); + custom_editor->popup(); + + } else if (t==Variant::STRING) { Variant v = obj->get(n); @@ -4557,7 +4579,7 @@ void SectionedPropertyEditor::update_category_list() { else if ( !(pi.usage&PROPERTY_USAGE_EDITOR) ) continue; - if (pi.name.find(":")!=-1 || pi.name=="script/script") + if (pi.name.find(":")!=-1 || pi.name=="script/script" || pi.name.begins_with("resource/")) continue; int sp = pi.name.find("/"); if (sp!=-1) { diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h index 6c6c309d32..3fe332bf87 100644 --- a/tools/editor/property_editor.h +++ b/tools/editor/property_editor.h @@ -65,6 +65,7 @@ class CustomPropertyEditor : public Popup { OBJ_MENU_COPY=4, OBJ_MENU_PASTE=5, OBJ_MENU_REIMPORT=6, + OBJ_MENU_NEW_SCRIPT=7, TYPE_BASE_ID=100 }; diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp index 506dfd3889..56f10ff7f8 100644 --- a/tools/editor/scene_tree_dock.cpp +++ b/tools/editor/scene_tree_dock.cpp @@ -227,7 +227,7 @@ void SceneTreeDock::_perform_instance_scenes(const Vector<String>& p_files,Node* editor_data->get_undo_redo().add_do_reference(instanced_scene); editor_data->get_undo_redo().add_undo_method(parent,"remove_child",instanced_scene); - String new_name = parent->validate_child_name(instanced_scene->get_name()); + String new_name = parent->validate_child_name(instanced_scene); ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); editor_data->get_undo_redo().add_do_method(sed,"live_debug_instance_node",edited_scene->get_path_to(parent),p_files[i],new_name); editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+new_name)); @@ -238,6 +238,34 @@ void SceneTreeDock::_perform_instance_scenes(const Vector<String>& p_files,Node* } +void SceneTreeDock::_replace_with_branch_scene(const String& p_file,Node* base) { + Ref<PackedScene> sdata = ResourceLoader::load(p_file); + if (!sdata.is_valid()) { + accept->get_ok()->set_text(TTR("Ugh")); + accept->set_text(vformat(TTR("Error loading scene from %s"),p_file)); + accept->popup_centered_minsize(); + return; + } + + Node *instanced_scene=sdata->instance(true); + if (!instanced_scene) { + accept->get_ok()->set_text(TTR("Ugh")); + accept->set_text(vformat(TTR("Error instancing scene from %s"),p_file)); + accept->popup_centered_minsize(); + return; + } + + Node *parent = base->get_parent(); + int pos = base->get_index(); + memdelete(base); + parent->add_child(instanced_scene); + parent->move_child(instanced_scene, pos); + instanced_scene->set_owner(edited_scene); + editor_selection->clear(); + editor_selection->add_node(instanced_scene); + scene_tree->set_selected(instanced_scene); +} + bool SceneTreeDock::_cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node) { int childCount = p_desired_node->get_child_count(); @@ -257,17 +285,6 @@ bool SceneTreeDock::_cyclical_dependency_exists(const String& p_target_scene_pat } -static String _get_name_num_separator() { - switch(EditorSettings::get_singleton()->get("scenetree_editor/duplicate_node_name_num_separator").operator int()) { - case 0: return ""; - case 1: return " "; - case 2: return "_"; - case 3: return "-"; - } - return " "; -} - - void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { current_option=p_tool; @@ -474,37 +491,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (selection.size()==1) dupsingle=dup; - String name = node->get_name(); - - String nums; - for(int i=name.length()-1;i>=0;i--) { - CharType n=name[i]; - if (n>='0' && n<='9') { - nums=String::chr(name[i])+nums; - } else { - break; - } - } - - int num=nums.to_int(); - if (num<1) - num=1; - else - num++; - - String nnsep = _get_name_num_separator(); - name = name.substr(0,name.length()-nums.length()).strip_edges(); - if ( name.substr(name.length()-nnsep.length(),nnsep.length()) == nnsep) { - name = name.substr(0,name.length()-nnsep.length()); - } - String attempt = (name + nnsep + itos(num)).strip_edges(); - - while(parent->has_node(attempt)) { - num++; - attempt = (name + nnsep + itos(num)).strip_edges(); - } - - dup->set_name(attempt); + dup->set_name(parent->validate_child_name(dup)); editor_data->get_undo_redo().add_do_method(parent,"_add_child_below_node",node, dup); for (List<Node*>::Element *F=owned.front();F;F=F->next()) { @@ -522,8 +509,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); - editor_data->get_undo_redo().add_do_method(sed,"live_debug_duplicate_node",edited_scene->get_path_to(node),attempt); - editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+attempt)); + editor_data->get_undo_redo().add_do_method(sed,"live_debug_duplicate_node",edited_scene->get_path_to(node),dup->get_name()); + editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+dup->get_name())); //parent->add_child(dup); //reselect.push_back(dup); @@ -1109,6 +1096,7 @@ void SceneTreeDock::_do_reparent(Node* p_new_parent,int p_position_in_parent,Vec editor_data->get_undo_redo().create_action(TTR("Reparent Node")); List<Pair<NodePath,NodePath> > path_renames; + Vector<StringName> former_names; int inc=0; @@ -1118,6 +1106,7 @@ void SceneTreeDock::_do_reparent(Node* p_new_parent,int p_position_in_parent,Vec Node *node = p_nodes[ni]; fill_path_renames(node,new_parent,&path_renames); + former_names.push_back(node->get_name()); List<Node*> owned; node->get_owned_by(node->get_owner(),&owned); @@ -1140,7 +1129,7 @@ void SceneTreeDock::_do_reparent(Node* p_new_parent,int p_position_in_parent,Vec editor_data->get_undo_redo().add_do_method(new_parent,"move_child",node,p_position_in_parent+inc); ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); - String new_name = new_parent->validate_child_name(node->get_name()); + String new_name = new_parent->validate_child_name(node); editor_data->get_undo_redo().add_do_method(sed,"live_debug_reparent_node",edited_scene->get_path_to(node),edited_scene->get_path_to(new_parent),new_name,-1); editor_data->get_undo_redo().add_undo_method(sed,"live_debug_reparent_node",NodePath(String(edited_scene->get_path_to(new_parent))+"/"+new_name),edited_scene->get_path_to(node->get_parent()),node->get_name(),node->get_index()); @@ -1159,6 +1148,7 @@ void SceneTreeDock::_do_reparent(Node* p_new_parent,int p_position_in_parent,Vec editor_data->get_undo_redo().add_do_method(AnimationPlayerEditor::singleton->get_key_editor(),"set_root",node); editor_data->get_undo_redo().add_undo_method(new_parent,"remove_child",node); + editor_data->get_undo_redo().add_undo_method(node,"set_name",former_names[ni]); inc++; @@ -1360,7 +1350,7 @@ void SceneTreeDock::_create() { editor_data->get_undo_redo().add_undo_method(parent,"remove_child",child); - String new_name = parent->validate_child_name(child->get_type()); + String new_name = parent->validate_child_name(child); ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); editor_data->get_undo_redo().add_do_method(sed,"live_debug_create_node",edited_scene->get_path_to(parent),child->get_type(),new_name); editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+new_name)); @@ -1551,7 +1541,7 @@ void SceneTreeDock::_new_scene_from(String p_file) { accept->popup_centered_minsize(); return; } - + _replace_with_branch_scene(p_file, base); } else { accept->get_ok()->set_text(TTR("I see..")); accept->set_text(TTR("Error duplicating scene to save it.")); @@ -1841,6 +1831,12 @@ void SceneTreeDock::_focus_node() { } } +void SceneTreeDock::open_script_dialog(Node* p_for_node) { + + scene_tree->set_selected(p_for_node,false); + _tool_selected(TOOL_SCRIPT); +} + void SceneTreeDock::_bind_methods() { ObjectTypeDB::bind_method(_MD("_tool_selected"),&SceneTreeDock::_tool_selected,DEFVAL(false)); diff --git a/tools/editor/scene_tree_dock.h b/tools/editor/scene_tree_dock.h index d92f12c34b..8933a03883 100644 --- a/tools/editor/scene_tree_dock.h +++ b/tools/editor/scene_tree_dock.h @@ -153,6 +153,7 @@ class SceneTreeDock : public VBoxContainer { void _filter_changed(const String& p_filter); void _perform_instance_scenes(const Vector<String>& p_files,Node* parent,int p_pos); + void _replace_with_branch_scene(const String& p_file,Node* base); protected: @@ -175,6 +176,7 @@ public: SceneTreeEditor *get_tree_editor() { return scene_tree; } + void open_script_dialog(Node* p_for_node); SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelection *p_editor_selection,EditorData &p_editor_data); }; diff --git a/tools/editor/scene_tree_editor.cpp b/tools/editor/scene_tree_editor.cpp index e5a97fa26e..53bfe8cc57 100644 --- a/tools/editor/scene_tree_editor.cpp +++ b/tools/editor/scene_tree_editor.cpp @@ -254,7 +254,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item,int p_column,int p_id) String config_err = n->get_configuration_warning(); if (config_err==String()) return; - config_err=config_err.world_wrap(80); + config_err=config_err.word_wrap(80); warning->set_text(config_err); warning->popup_centered_minsize(); diff --git a/tools/editor/script_create_dialog.cpp b/tools/editor/script_create_dialog.cpp index 749198314a..62d5c7cd84 100644 --- a/tools/editor/script_create_dialog.cpp +++ b/tools/editor/script_create_dialog.cpp @@ -121,6 +121,8 @@ void ScriptCreateDialog::ok_pressed() { Ref<Script> scr = ScriptServer::get_language( language_menu->get_selected() )->get_template(cname,parent_name->get_text()); //scr->set_source_code(text); + String selected_language = language_menu->get_item_text(language_menu->get_selected()); + editor_settings->set_last_selected_language(selected_language); if (cname!="") scr->set_name(cname); @@ -330,7 +332,17 @@ ScriptCreateDialog::ScriptCreateDialog() { language_menu->add_item(ScriptServer::get_language(i)->get_name()); } - language_menu->select(0); + editor_settings = EditorSettings::get_singleton(); + String last_selected_language = editor_settings->get_last_selected_language(); + if (last_selected_language != "") + for (int i = 0; i < language_menu->get_item_count(); i++) + if (language_menu->get_item_text(i) == last_selected_language) + { + language_menu->select(i); + break; + } + else language_menu->select(0); + language_menu->connect("item_selected",this,"_lang_changed"); //parent_name->set_text(); diff --git a/tools/editor/script_create_dialog.h b/tools/editor/script_create_dialog.h index 181989402e..c71ea16d39 100644 --- a/tools/editor/script_create_dialog.h +++ b/tools/editor/script_create_dialog.h @@ -33,6 +33,7 @@ #include "scene/gui/line_edit.h" #include "scene/gui/option_button.h" #include "tools/editor/editor_file_dialog.h" +#include "tools/editor/editor_settings.h" #include "scene/gui/check_button.h" class ScriptCreateDialog : public ConfirmationDialog { @@ -50,6 +51,7 @@ class ScriptCreateDialog : public ConfirmationDialog { AcceptDialog *alert; bool path_valid; String initial_bp; + EditorSettings *editor_settings; void _path_changed(const String& p_path=String()); diff --git a/tools/editor/script_editor_debugger.cpp b/tools/editor/script_editor_debugger.cpp index da42f54095..c8170ca9a3 100644 --- a/tools/editor/script_editor_debugger.cpp +++ b/tools/editor/script_editor_debugger.cpp @@ -216,6 +216,8 @@ void ScriptEditorDebugger::debug_continue() { ERR_FAIL_COND(connection.is_null()); ERR_FAIL_COND(!connection->is_connected()); + OS::get_singleton()->enable_for_stealing_focus(EditorNode::get_singleton()->get_child_process_id()); + Array msg; msg.push_back("continue"); ppeer->put_var(msg); @@ -1087,6 +1089,9 @@ void ScriptEditorDebugger::start() { stop(); + if (!EditorNode::get_log()->is_visible()) { + EditorNode::get_singleton()->make_bottom_panel_item_visible(EditorNode::get_log()); + } uint16_t port = GLOBAL_DEF("debug/remote_port",6007); perf_history.clear(); diff --git a/tools/editor/spatial_editor_gizmos.cpp b/tools/editor/spatial_editor_gizmos.cpp index 480d33fd0a..84803eb6db 100644 --- a/tools/editor/spatial_editor_gizmos.cpp +++ b/tools/editor/spatial_editor_gizmos.cpp @@ -422,8 +422,6 @@ bool EditorSpatialGizmo::intersect_ray(const Camera *p_camera,const Point2& p_po if (billboard_handle) { t.set_look_at(t.origin,t.origin+p_camera->get_transform().basis.get_axis(2),p_camera->get_transform().basis.get_axis(1)); } - Transform ti=t.affine_inverse(); - float min_d=1e20; int idx=-1; diff --git a/tools/glwrapper/makewrapper.py b/tools/glwrapper/makewrapper.py deleted file mode 100644 index 2e5f06be12..0000000000 --- a/tools/glwrapper/makewrapper.py +++ /dev/null @@ -1,183 +0,0 @@ -#! /usr/bin/python -import sys - -if (len(sys.argv)<2): - print("usage: makewrapper.py <headers>") - sys.exit(255) - - -functions=[] -types=[] -constants=[] - -READ_FUNCTIONS=0 -READ_TYPES=1 -READ_CONSTANTS=2 - -read_what=READ_TYPES - -for x in (range(len(sys.argv)-1)): - f=open(sys.argv[x+1],"r") - - while(True): - - line=f.readline() - if (line==""): - break - - line=line.replace("\n","").strip() - """ - if (line.find("[types]")!=-1): - read_what=READ_TYPES - continue - elif (line.find("[constants]")!=-1): - read=READ_TYPES - continue - elif (line.find("[functions]")!=-1): - read_what=READ_FUNCTIONS - continue - """ - - if (line.find("#define")!=-1): - if (line.find("0x")==-1 and line.find("GL_VERSION")==-1): - continue - constants.append(line) - elif (line.find("typedef")!=-1): - if (line.find("(")!=-1 or line.find(")")!=-1 or line.find("ARB")!=-1 or line.find("EXT")!=-1 or line.find("GL")==-1): - continue - types.append(line) - elif (line.find("APIENTRY")!=-1 and line.find("GLAPI")!=-1): - - if (line.find("ARB")!=-1 or line.find("EXT")!=-1 or line.find("NV")!=-1): - continue - - line=line.replace("APIENTRY","") - line=line.replace("GLAPI","") - - glpos=line.find(" gl") - if (glpos==-1): - - glpos=line.find("\tgl") - if (glpos==-1): - continue - - ret=line[:glpos].strip(); - - line=line[glpos:].strip() - namepos=line.find("(") - - if (namepos==-1): - continue - - name=line[:namepos].strip() - line=line[namepos:] - - argpos=line.rfind(")") - if (argpos==-1): - continue - - args=line[1:argpos] - - funcdata={} - funcdata["ret"]=ret - funcdata["name"]=name - funcdata["args"]=args - - functions.append(funcdata) - print(funcdata) - - - -#print(types) -#print(constants) -#print(functions) - - -f=open("glwrapper.h","w") - -f.write("#ifndef GL_WRAPPER\n") -f.write("#define GL_WRAPPER\n\n\n") - -header_code="""\ -#if defined(__gl_h_) || defined(__GL_H__) -#error gl.h included before glwrapper.h -#endif -#if defined(__glext_h_) || defined(__GLEXT_H_) -#error glext.h included before glwrapper.h -#endif -#if defined(__gl_ATI_h_) -#error glATI.h included before glwrapper.h -#endif - -#define __gl_h_ -#define __GL_H__ -#define __glext_h_ -#define __GLEXT_H_ -#define __gl_ATI_h_ - -#define GL_TRUE 1 -#define GL_FALSE 0 - -#define GL_ZERO 0 -#define GL_ONE 1 -#define GL_NONE 0 -#define GL_NO_ERROR 0 - -\n\n -""" - -f.write("#include <stddef.h>\n\n\n") - -f.write(header_code); - -f.write("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n") -f.write("#if defined(_WIN32) && !defined(__CYGWIN__)\n") -f.write("#define GLWRP_APIENTRY __stdcall\n") -f.write("#else\n"); -f.write("#define GLWRP_APIENTRY \n") -f.write("#endif\n\n"); -for x in types: - f.write(x+"\n") - -f.write("\n\n") - -for x in constants: - f.write(x+"\n") - -f.write("\n\n") - -for x in functions: - f.write("extern "+x["ret"]+" GLWRP_APIENTRY (*__wrapper_"+x["name"]+")("+x["args"]+");\n") - f.write("#define "+x["name"]+" __wrapper_"+x["name"]+"\n") - -f.write("\n\n") -f.write("typedef void (*GLWrapperFuncPtr)(void);\n\n"); -f.write("void glWrapperInit( GLWrapperFuncPtr (*wrapperFunc)(const char*) );\n") - -f.write("#ifdef __cplusplus\n}\n#endif\n") - -f.write("#endif\n\n") - -f=open("glwrapper.c","w") - -f.write("\n\n") -f.write("#include \"glwrapper.h\"\n") -f.write("\n\n") - -for x in functions: - f.write(x["ret"]+" GLWRP_APIENTRY (*__wrapper_"+x["name"]+")("+x["args"]+")=NULL;\n") - -f.write("\n\n") -f.write("void glWrapperInit( GLWrapperFuncPtr (*wrapperFunc)(const char*) ) {\n") -f.write("\n") - -for x in functions: - f.write("\t__wrapper_"+x["name"]+"=("+x["ret"]+" GLWRP_APIENTRY (*)("+x["args"]+"))wrapperFunc(\""+x["name"]+"\");\n") - -f.write("\n\n") -f.write("}\n") -f.write("\n\n") - - - - diff --git a/tools/ios_xcode_template/data.pck b/tools/ios_xcode_template/data.pck deleted file mode 100644 index e69de29bb2..0000000000 --- a/tools/ios_xcode_template/data.pck +++ /dev/null diff --git a/tools/ios_xcode_template/godot_ios.xcodeproj/project.pbxproj b/tools/ios_xcode_template/godot_ios.xcodeproj/project.pbxproj deleted file mode 100644 index 4ae1ec8a53..0000000000 --- a/tools/ios_xcode_template/godot_ios.xcodeproj/project.pbxproj +++ /dev/null @@ -1,469 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - D0BCFE3818AEBDA2004A7AAE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */; }; - D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */; }; - D0BCFE3C18AEBDA2004A7AAE /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */; }; - D0BCFE3E18AEBDA2004A7AAE /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */; }; - D0BCFE4018AEBDA2004A7AAE /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */; }; - D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */; }; - D0BCFE6218AEBDA3004A7AAE /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE6118AEBDA3004A7AAE /* XCTest.framework */; }; - D0BCFE6318AEBDA3004A7AAE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */; }; - D0BCFE6418AEBDA3004A7AAE /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */; }; - D0BCFE6C18AEBDA3004A7AAE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE6A18AEBDA3004A7AAE /* InfoPlist.strings */; }; - D0BCFE6E18AEBDA3004A7AAE /* godot_iosTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D0BCFE6D18AEBDA3004A7AAE /* godot_iosTests.m */; }; - D0BCFE7818AEBFEB004A7AAE /* data.pck in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7718AEBFEB004A7AAE /* data.pck */; }; - D0BCFE7A18AEC06A004A7AAE /* godot_opt.iphone in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7918AEC06A004A7AAE /* godot_opt.iphone */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - D0BCFE6518AEBDA3004A7AAE /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D0BCFE2C18AEBDA2004A7AAE /* Project object */; - proxyType = 1; - remoteGlobalIDString = D0BCFE3318AEBDA2004A7AAE; - remoteInfo = godot_ios; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - D0BCFE3418AEBDA2004A7AAE /* godot_ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = godot_ios.app; sourceTree = BUILT_PRODUCTS_DIR; }; - D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; }; - D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; - D0BCFE4318AEBDA2004A7AAE /* godot_ios-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "godot_ios-Info.plist"; sourceTree = "<group>"; }; - D0BCFE4518AEBDA2004A7AAE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; }; - D0BCFE4918AEBDA2004A7AAE /* godot_ios-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "godot_ios-Prefix.pch"; sourceTree = "<group>"; }; - D0BCFE6018AEBDA3004A7AAE /* godot_iosTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = godot_iosTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - D0BCFE6118AEBDA3004A7AAE /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; - D0BCFE6918AEBDA3004A7AAE /* godot_iosTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "godot_iosTests-Info.plist"; sourceTree = "<group>"; }; - D0BCFE6B18AEBDA3004A7AAE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; }; - D0BCFE6D18AEBDA3004A7AAE /* godot_iosTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = godot_iosTests.m; sourceTree = "<group>"; }; - D0BCFE7718AEBFEB004A7AAE /* data.pck */ = {isa = PBXFileReference; lastKnownFileType = file; path = data.pck; sourceTree = "<group>"; }; - D0BCFE7918AEC06A004A7AAE /* godot_opt.iphone */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = godot_opt.iphone; sourceTree = "<group>"; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - D0BCFE3118AEBDA2004A7AAE /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - D0BCFE4018AEBDA2004A7AAE /* OpenGLES.framework in Frameworks */, - D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */, - D0BCFE3C18AEBDA2004A7AAE /* UIKit.framework in Frameworks */, - D0BCFE3E18AEBDA2004A7AAE /* GLKit.framework in Frameworks */, - D0BCFE3818AEBDA2004A7AAE /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D0BCFE5D18AEBDA3004A7AAE /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - D0BCFE6218AEBDA3004A7AAE /* XCTest.framework in Frameworks */, - D0BCFE6418AEBDA3004A7AAE /* UIKit.framework in Frameworks */, - D0BCFE6318AEBDA3004A7AAE /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - D0BCFE2B18AEBDA2004A7AAE = { - isa = PBXGroup; - children = ( - D0BCFE7918AEC06A004A7AAE /* godot_opt.iphone */, - D0BCFE7718AEBFEB004A7AAE /* data.pck */, - D0BCFE4118AEBDA2004A7AAE /* godot_ios */, - D0BCFE6718AEBDA3004A7AAE /* godot_iosTests */, - D0BCFE3618AEBDA2004A7AAE /* Frameworks */, - D0BCFE3518AEBDA2004A7AAE /* Products */, - ); - sourceTree = "<group>"; - }; - D0BCFE3518AEBDA2004A7AAE /* Products */ = { - isa = PBXGroup; - children = ( - D0BCFE3418AEBDA2004A7AAE /* godot_ios.app */, - D0BCFE6018AEBDA3004A7AAE /* godot_iosTests.xctest */, - ); - name = Products; - sourceTree = "<group>"; - }; - D0BCFE3618AEBDA2004A7AAE /* Frameworks */ = { - isa = PBXGroup; - children = ( - D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */, - D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */, - D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */, - D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */, - D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */, - D0BCFE6118AEBDA3004A7AAE /* XCTest.framework */, - ); - name = Frameworks; - sourceTree = "<group>"; - }; - D0BCFE4118AEBDA2004A7AAE /* godot_ios */ = { - isa = PBXGroup; - children = ( - D0BCFE4218AEBDA2004A7AAE /* Supporting Files */, - ); - path = godot_ios; - sourceTree = "<group>"; - }; - D0BCFE4218AEBDA2004A7AAE /* Supporting Files */ = { - isa = PBXGroup; - children = ( - D0BCFE4318AEBDA2004A7AAE /* godot_ios-Info.plist */, - D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */, - D0BCFE4918AEBDA2004A7AAE /* godot_ios-Prefix.pch */, - ); - name = "Supporting Files"; - sourceTree = "<group>"; - }; - D0BCFE6718AEBDA3004A7AAE /* godot_iosTests */ = { - isa = PBXGroup; - children = ( - D0BCFE6D18AEBDA3004A7AAE /* godot_iosTests.m */, - D0BCFE6818AEBDA3004A7AAE /* Supporting Files */, - ); - path = godot_iosTests; - sourceTree = "<group>"; - }; - D0BCFE6818AEBDA3004A7AAE /* Supporting Files */ = { - isa = PBXGroup; - children = ( - D0BCFE6918AEBDA3004A7AAE /* godot_iosTests-Info.plist */, - D0BCFE6A18AEBDA3004A7AAE /* InfoPlist.strings */, - ); - name = "Supporting Files"; - sourceTree = "<group>"; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - D0BCFE3318AEBDA2004A7AAE /* godot_ios */ = { - isa = PBXNativeTarget; - buildConfigurationList = D0BCFE7118AEBDA3004A7AAE /* Build configuration list for PBXNativeTarget "godot_ios" */; - buildPhases = ( - D0BCFE3018AEBDA2004A7AAE /* Sources */, - D0BCFE3118AEBDA2004A7AAE /* Frameworks */, - D0BCFE3218AEBDA2004A7AAE /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = godot_ios; - productName = godot_ios; - productReference = D0BCFE3418AEBDA2004A7AAE /* godot_ios.app */; - productType = "com.apple.product-type.application"; - }; - D0BCFE5F18AEBDA3004A7AAE /* godot_iosTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = D0BCFE7418AEBDA3004A7AAE /* Build configuration list for PBXNativeTarget "godot_iosTests" */; - buildPhases = ( - D0BCFE5C18AEBDA3004A7AAE /* Sources */, - D0BCFE5D18AEBDA3004A7AAE /* Frameworks */, - D0BCFE5E18AEBDA3004A7AAE /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - D0BCFE6618AEBDA3004A7AAE /* PBXTargetDependency */, - ); - name = godot_iosTests; - productName = godot_iosTests; - productReference = D0BCFE6018AEBDA3004A7AAE /* godot_iosTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - D0BCFE2C18AEBDA2004A7AAE /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0500; - ORGANIZATIONNAME = GodotEngine; - TargetAttributes = { - D0BCFE5F18AEBDA3004A7AAE = { - TestTargetID = D0BCFE3318AEBDA2004A7AAE; - }; - }; - }; - buildConfigurationList = D0BCFE2F18AEBDA2004A7AAE /* Build configuration list for PBXProject "godot_ios" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = D0BCFE2B18AEBDA2004A7AAE; - productRefGroup = D0BCFE3518AEBDA2004A7AAE /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - D0BCFE3318AEBDA2004A7AAE /* godot_ios */, - D0BCFE5F18AEBDA3004A7AAE /* godot_iosTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - D0BCFE3218AEBDA2004A7AAE /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D0BCFE7818AEBFEB004A7AAE /* data.pck in Resources */, - D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */, - D0BCFE7A18AEC06A004A7AAE /* godot_opt.iphone in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D0BCFE5E18AEBDA3004A7AAE /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D0BCFE6C18AEBDA3004A7AAE /* InfoPlist.strings in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - D0BCFE3018AEBDA2004A7AAE /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D0BCFE5C18AEBDA3004A7AAE /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D0BCFE6E18AEBDA3004A7AAE /* godot_iosTests.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - D0BCFE6618AEBDA3004A7AAE /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = D0BCFE3318AEBDA2004A7AAE /* godot_ios */; - targetProxy = D0BCFE6518AEBDA3004A7AAE /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - D0BCFE4518AEBDA2004A7AAE /* en */, - ); - name = InfoPlist.strings; - sourceTree = "<group>"; - }; - D0BCFE6A18AEBDA3004A7AAE /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - D0BCFE6B18AEBDA3004A7AAE /* en */, - ); - name = InfoPlist.strings; - sourceTree = "<group>"; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - D0BCFE6F18AEBDA3004A7AAE /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - D0BCFE7018AEBDA3004A7AAE /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - D0BCFE7218AEBDA3004A7AAE /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "godot_ios/godot_ios-Prefix.pch"; - INFOPLIST_FILE = "godot_ios/godot_ios-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALID_ARCHS = "armv7 armv7s"; - WRAPPER_EXTENSION = app; - }; - name = Debug; - }; - D0BCFE7318AEBDA3004A7AAE /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "godot_ios/godot_ios-Prefix.pch"; - INFOPLIST_FILE = "godot_ios/godot_ios-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALID_ARCHS = "armv7 armv7s"; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; - D0BCFE7518AEBDA3004A7AAE /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; - BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/godot_ios.app/godot_ios"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - "$(DEVELOPER_FRAMEWORKS_DIR)", - ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "godot_ios/godot_ios-Prefix.pch"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = "godot_iosTests/godot_iosTests-Info.plist"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUNDLE_LOADER)"; - WRAPPER_EXTENSION = xctest; - }; - name = Debug; - }; - D0BCFE7618AEBDA3004A7AAE /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; - BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/godot_ios.app/godot_ios"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - "$(DEVELOPER_FRAMEWORKS_DIR)", - ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "godot_ios/godot_ios-Prefix.pch"; - INFOPLIST_FILE = "godot_iosTests/godot_iosTests-Info.plist"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUNDLE_LOADER)"; - WRAPPER_EXTENSION = xctest; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - D0BCFE2F18AEBDA2004A7AAE /* Build configuration list for PBXProject "godot_ios" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D0BCFE6F18AEBDA3004A7AAE /* Debug */, - D0BCFE7018AEBDA3004A7AAE /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - D0BCFE7118AEBDA3004A7AAE /* Build configuration list for PBXNativeTarget "godot_ios" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D0BCFE7218AEBDA3004A7AAE /* Debug */, - D0BCFE7318AEBDA3004A7AAE /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; - D0BCFE7418AEBDA3004A7AAE /* Build configuration list for PBXNativeTarget "godot_iosTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D0BCFE7518AEBDA3004A7AAE /* Debug */, - D0BCFE7618AEBDA3004A7AAE /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; -/* End XCConfigurationList section */ - }; - rootObject = D0BCFE2C18AEBDA2004A7AAE /* Project object */; -} diff --git a/tools/ios_xcode_template/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/tools/ios_xcode_template/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 3c9ba38bbe..0000000000 --- a/tools/ios_xcode_template/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Workspace - version = "1.0"> - <FileRef - location = "self:godot_ios.xcodeproj"> - </FileRef> -</Workspace> diff --git a/tools/ios_xcode_template/godot_ios.xcodeproj/project.xcworkspace/xcuserdata/punto.xcuserdatad/UserInterfaceState.xcuserstate b/tools/ios_xcode_template/godot_ios.xcodeproj/project.xcworkspace/xcuserdata/punto.xcuserdatad/UserInterfaceState.xcuserstate Binary files differdeleted file mode 100644 index 7c338929ed..0000000000 --- a/tools/ios_xcode_template/godot_ios.xcodeproj/project.xcworkspace/xcuserdata/punto.xcuserdatad/UserInterfaceState.xcuserstate +++ /dev/null diff --git a/tools/ios_xcode_template/godot_ios.xcodeproj/xcuserdata/punto.xcuserdatad/xcschemes/godot_ios.xcscheme b/tools/ios_xcode_template/godot_ios.xcodeproj/xcuserdata/punto.xcuserdatad/xcschemes/godot_ios.xcscheme deleted file mode 100644 index 19af55b4a2..0000000000 --- a/tools/ios_xcode_template/godot_ios.xcodeproj/xcuserdata/punto.xcuserdatad/xcschemes/godot_ios.xcscheme +++ /dev/null @@ -1,96 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Scheme - LastUpgradeVersion = "0500" - version = "1.3"> - <BuildAction - parallelizeBuildables = "YES" - buildImplicitDependencies = "YES"> - <BuildActionEntries> - <BuildActionEntry - buildForTesting = "YES" - buildForRunning = "YES" - buildForProfiling = "YES" - buildForArchiving = "YES" - buildForAnalyzing = "YES"> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "D0BCFE3318AEBDA2004A7AAE" - BuildableName = "godot_ios.app" - BlueprintName = "godot_ios" - ReferencedContainer = "container:godot_ios.xcodeproj"> - </BuildableReference> - </BuildActionEntry> - </BuildActionEntries> - </BuildAction> - <TestAction - selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" - selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES" - buildConfiguration = "Debug"> - <Testables> - <TestableReference - skipped = "NO"> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "D0BCFE5F18AEBDA3004A7AAE" - BuildableName = "godot_iosTests.xctest" - BlueprintName = "godot_iosTests" - ReferencedContainer = "container:godot_ios.xcodeproj"> - </BuildableReference> - </TestableReference> - </Testables> - <MacroExpansion> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "D0BCFE3318AEBDA2004A7AAE" - BuildableName = "godot_ios.app" - BlueprintName = "godot_ios" - ReferencedContainer = "container:godot_ios.xcodeproj"> - </BuildableReference> - </MacroExpansion> - </TestAction> - <LaunchAction - selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" - selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - launchStyle = "0" - useCustomWorkingDirectory = "NO" - buildConfiguration = "Debug" - ignoresPersistentStateOnLaunch = "NO" - debugDocumentVersioning = "YES" - allowLocationSimulation = "YES"> - <BuildableProductRunnable> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "D0BCFE3318AEBDA2004A7AAE" - BuildableName = "godot_ios.app" - BlueprintName = "godot_ios" - ReferencedContainer = "container:godot_ios.xcodeproj"> - </BuildableReference> - </BuildableProductRunnable> - <AdditionalOptions> - </AdditionalOptions> - </LaunchAction> - <ProfileAction - shouldUseLaunchSchemeArgsEnv = "YES" - savedToolIdentifier = "" - useCustomWorkingDirectory = "NO" - buildConfiguration = "Release" - debugDocumentVersioning = "YES"> - <BuildableProductRunnable> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "D0BCFE3318AEBDA2004A7AAE" - BuildableName = "godot_ios.app" - BlueprintName = "godot_ios" - ReferencedContainer = "container:godot_ios.xcodeproj"> - </BuildableReference> - </BuildableProductRunnable> - </ProfileAction> - <AnalyzeAction - buildConfiguration = "Debug"> - </AnalyzeAction> - <ArchiveAction - buildConfiguration = "Release" - revealArchiveInOrganizer = "YES"> - </ArchiveAction> -</Scheme> diff --git a/tools/ios_xcode_template/godot_ios.xcodeproj/xcuserdata/punto.xcuserdatad/xcschemes/xcschememanagement.plist b/tools/ios_xcode_template/godot_ios.xcodeproj/xcuserdata/punto.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 4a3a16cbdb..0000000000 --- a/tools/ios_xcode_template/godot_ios.xcodeproj/xcuserdata/punto.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>SchemeUserState</key> - <dict> - <key>godot_ios.xcscheme</key> - <dict> - <key>orderHint</key> - <integer>0</integer> - </dict> - </dict> - <key>SuppressBuildableAutocreation</key> - <dict> - <key>D0BCFE3318AEBDA2004A7AAE</key> - <dict> - <key>primary</key> - <true/> - </dict> - <key>D0BCFE5F18AEBDA3004A7AAE</key> - <dict> - <key>primary</key> - <true/> - </dict> - </dict> -</dict> -</plist> diff --git a/tools/ios_xcode_template/godot_ios/en.lproj/InfoPlist.strings b/tools/ios_xcode_template/godot_ios/en.lproj/InfoPlist.strings deleted file mode 100644 index 477b28ff8f..0000000000 --- a/tools/ios_xcode_template/godot_ios/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,2 +0,0 @@ -/* Localized versions of Info.plist keys */ - diff --git a/tools/ios_xcode_template/godot_ios/godot_ios-Info.plist b/tools/ios_xcode_template/godot_ios/godot_ios-Info.plist deleted file mode 100644 index 357970920a..0000000000 --- a/tools/ios_xcode_template/godot_ios/godot_ios-Info.plist +++ /dev/null @@ -1,47 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundleDevelopmentRegion</key> - <string>en</string> - <key>CFBundleDisplayName</key> - <string>${PRODUCT_NAME}</string> - <key>CFBundleExecutable</key> - <string>godot_opt.iphone</string> - <key>CFBundleIdentifier</key> - <string>org.godotengine.${PRODUCT_NAME:rfc1034identifier}</string> - <key>CFBundleInfoDictionaryVersion</key> - <string>6.0</string> - <key>CFBundleName</key> - <string>${PRODUCT_NAME}</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleShortVersionString</key> - <string>1.0</string> - <key>CFBundleSignature</key> - <string>????</string> - <key>CFBundleVersion</key> - <string>1.0</string> - <key>LSRequiresIPhoneOS</key> - <true/> - <key>UIRequiredDeviceCapabilities</key> - <array> - <string>armv7</string> - </array> - <key>UIStatusBarHidden</key> - <true/> - <key>UISupportedInterfaceOrientations</key> - <array> - <string>UIInterfaceOrientationPortrait</string> - <string>UIInterfaceOrientationLandscapeLeft</string> - <string>UIInterfaceOrientationLandscapeRight</string> - </array> - <key>UISupportedInterfaceOrientations~ipad</key> - <array> - <string>UIInterfaceOrientationPortrait</string> - <string>UIInterfaceOrientationPortraitUpsideDown</string> - <string>UIInterfaceOrientationLandscapeLeft</string> - <string>UIInterfaceOrientationLandscapeRight</string> - </array> -</dict> -</plist> diff --git a/tools/ios_xcode_template/godot_ios/godot_ios-Prefix.pch b/tools/ios_xcode_template/godot_ios/godot_ios-Prefix.pch deleted file mode 100644 index 82a2bb4507..0000000000 --- a/tools/ios_xcode_template/godot_ios/godot_ios-Prefix.pch +++ /dev/null @@ -1,16 +0,0 @@ -// -// Prefix header -// -// The contents of this file are implicitly included at the beginning of every source file. -// - -#import <Availability.h> - -#ifndef __IPHONE_5_0 -#warning "This project uses features only available in iOS SDK 5.0 and later." -#endif - -#ifdef __OBJC__ - #import <UIKit/UIKit.h> - #import <Foundation/Foundation.h> -#endif diff --git a/tools/ios_xcode_template/godot_ios/main.m b/tools/ios_xcode_template/godot_ios/main.m deleted file mode 100644 index 3e4ea5e129..0000000000 --- a/tools/ios_xcode_template/godot_ios/main.m +++ /dev/null @@ -1,39 +0,0 @@ -/*************************************************************************/ -/* main.m */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#import <UIKit/UIKit.h> - -#import "AppDelegate.h" - -int main(int argc, char * argv[]) -{ - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/tools/ios_xcode_template/godot_iosTests/en.lproj/InfoPlist.strings b/tools/ios_xcode_template/godot_iosTests/en.lproj/InfoPlist.strings deleted file mode 100644 index 477b28ff8f..0000000000 --- a/tools/ios_xcode_template/godot_iosTests/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,2 +0,0 @@ -/* Localized versions of Info.plist keys */ - diff --git a/tools/ios_xcode_template/godot_iosTests/godot_iosTests-Info.plist b/tools/ios_xcode_template/godot_iosTests/godot_iosTests-Info.plist deleted file mode 100644 index 0f69aa80eb..0000000000 --- a/tools/ios_xcode_template/godot_iosTests/godot_iosTests-Info.plist +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundleDevelopmentRegion</key> - <string>en</string> - <key>CFBundleExecutable</key> - <string>${EXECUTABLE_NAME}</string> - <key>CFBundleIdentifier</key> - <string>org.godotengine.${PRODUCT_NAME:rfc1034identifier}</string> - <key>CFBundleInfoDictionaryVersion</key> - <string>6.0</string> - <key>CFBundlePackageType</key> - <string>BNDL</string> - <key>CFBundleShortVersionString</key> - <string>1.0</string> - <key>CFBundleSignature</key> - <string>????</string> - <key>CFBundleVersion</key> - <string>1</string> -</dict> -</plist> diff --git a/tools/ios_xcode_template/godot_iosTests/godot_iosTests.m b/tools/ios_xcode_template/godot_iosTests/godot_iosTests.m deleted file mode 100644 index d9fac0a250..0000000000 --- a/tools/ios_xcode_template/godot_iosTests/godot_iosTests.m +++ /dev/null @@ -1,55 +0,0 @@ -/*************************************************************************/ -/* godot_iosTests.m */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#import <XCTest/XCTest.h> - -@interface godot_iosTests : XCTestCase - -@end - -@implementation godot_iosTests - -- (void)setUp -{ - [super setUp]; - // Put setup code here. This method is called before the invocation of each test method in the class. -} - -- (void)tearDown -{ - // Put teardown code here. This method is called after the invocation of each test method in the class. - [super tearDown]; -} - -- (void)testExample -{ - XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); -} - -@end diff --git a/tools/pck/SCsub b/tools/pck/SCsub deleted file mode 100644 index cf98ae145d..0000000000 --- a/tools/pck/SCsub +++ /dev/null @@ -1,4 +0,0 @@ -Import('env') - -if env["tools"] == "yes": - env.add_source_files(env.tool_sources, "*.cpp") diff --git a/tools/script_plugins/terrain/plugin.cfg b/tools/script_plugins/terrain/plugin.cfg deleted file mode 100644 index d2f2917420..0000000000 --- a/tools/script_plugins/terrain/plugin.cfg +++ /dev/null @@ -1,16 +0,0 @@ -[plugin] - -name="Terrain" -description="Simple plugin for generating and editing grid-based terrains. This type of terrains were all the rage in the early 2000's, but lost popularity to hand crafted geometry towards the end of the decade." -author="Juan Linietsky" -version="1.0" -installs=true -script="terrain.gd" -install_files=["terrain.gd","terrain_node.gd","icon_terrain.png"] - - - - - - - diff --git a/tools/script_plugins/terrain/terrain.gd b/tools/script_plugins/terrain/terrain.gd deleted file mode 100644 index b3e3121e7a..0000000000 --- a/tools/script_plugins/terrain/terrain.gd +++ /dev/null @@ -1,17 +0,0 @@ -tool # Always declare as Tool, if it's meant to run in the editor. -extends EditorPlugin - - -func get_name(): - return "Terrain" - - -func _init(): - print("PLUGIN INIT") - - -func _enter_scene(): - add_custom_type("Terrain","Spatial",preload("terrain_node.gd"),preload("terrain.png")) - -func _exit_scene(): - remove_custom_type("Terrain") diff --git a/tools/script_plugins/terrain/terrain.png b/tools/script_plugins/terrain/terrain.png Binary files differdeleted file mode 100644 index 7c1c3d70d6..0000000000 --- a/tools/script_plugins/terrain/terrain.png +++ /dev/null diff --git a/tools/script_plugins/terrain/terrain_node.gd b/tools/script_plugins/terrain/terrain_node.gd deleted file mode 100644 index 91cf3fcb2b..0000000000 --- a/tools/script_plugins/terrain/terrain_node.gd +++ /dev/null @@ -1,3 +0,0 @@ -extends Spatial - - diff --git a/tools/script_plugins/time/plugin.cfg b/tools/script_plugins/time/plugin.cfg deleted file mode 100644 index 5430306a79..0000000000 --- a/tools/script_plugins/time/plugin.cfg +++ /dev/null @@ -1,14 +0,0 @@ -[plugin] - -name="The Time" -description="This plugin displays the current local time, with great accuracy, by harvesting the power of quartz crystals inside your computer.\nIt may also serve as simple example on how to write a non-installable editor plugin, or just remind you that it's time to go back home." -author="Juan Linietsky" -version="1.0" -installs=false -script="time.gd" - - - - - - diff --git a/tools/script_plugins/time/time.gd b/tools/script_plugins/time/time.gd deleted file mode 100644 index 2e56d89d4f..0000000000 --- a/tools/script_plugins/time/time.gd +++ /dev/null @@ -1,32 +0,0 @@ -tool # Always declare as Tool, if it's meant to run in the editor. -extends EditorPlugin - -var timer = null -var label = null - -func _timeout(): - if (label): - var time = OS.get_time() - label.set_text(str(time.hour).pad_zeros(2)+":"+str(time.minute).pad_zeros(2)+":"+str(time.second).pad_zeros(2)) - -func get_name(): - return "The Time" - - -func _init(): - print("PLUGIN INIT") - timer = Timer.new() - add_child(timer) - timer.set_wait_time(0.5) - timer.set_one_shot(false) - timer.connect("timeout",self,"_timeout") - -func _enter_tree(): - label = Label.new() - add_custom_control(CONTAINER_TOOLBAR,label) - timer.start() - -func _exit_tree(): - timer.stop() - label.free() - label=null diff --git a/tools/addheader/addheader.py b/tools/scripts/addheader.py index d040d8b5d6..d040d8b5d6 100644 --- a/tools/addheader/addheader.py +++ b/tools/scripts/addheader.py diff --git a/tools/bmfhdr/makehdr.py b/tools/scripts/make_bmfhdr.py index 0f6f453004..0f6f453004 100644 --- a/tools/bmfhdr/makehdr.py +++ b/tools/scripts/make_bmfhdr.py diff --git a/tools/scripts/make_glwrapper.py b/tools/scripts/make_glwrapper.py new file mode 100644 index 0000000000..b4c582f1eb --- /dev/null +++ b/tools/scripts/make_glwrapper.py @@ -0,0 +1,183 @@ +#! /usr/bin/env python +import sys + +if (len(sys.argv)<2): + print("usage: make_glwrapper.py <headers>") + sys.exit(255) + + +functions=[] +types=[] +constants=[] + +READ_FUNCTIONS=0 +READ_TYPES=1 +READ_CONSTANTS=2 + +read_what=READ_TYPES + +for x in (range(len(sys.argv)-1)): + f=open(sys.argv[x+1],"r") + + while(True): + + line=f.readline() + if (line==""): + break + + line=line.replace("\n","").strip() + """ + if (line.find("[types]")!=-1): + read_what=READ_TYPES + continue + elif (line.find("[constants]")!=-1): + read=READ_TYPES + continue + elif (line.find("[functions]")!=-1): + read_what=READ_FUNCTIONS + continue + """ + + if (line.find("#define")!=-1): + if (line.find("0x")==-1 and line.find("GL_VERSION")==-1): + continue + constants.append(line) + elif (line.find("typedef")!=-1): + if (line.find("(")!=-1 or line.find(")")!=-1 or line.find("ARB")!=-1 or line.find("EXT")!=-1 or line.find("GL")==-1): + continue + types.append(line) + elif (line.find("APIENTRY")!=-1 and line.find("GLAPI")!=-1): + + if (line.find("ARB")!=-1 or line.find("EXT")!=-1 or line.find("NV")!=-1): + continue + + line=line.replace("APIENTRY","") + line=line.replace("GLAPI","") + + glpos=line.find(" gl") + if (glpos==-1): + + glpos=line.find("\tgl") + if (glpos==-1): + continue + + ret=line[:glpos].strip(); + + line=line[glpos:].strip() + namepos=line.find("(") + + if (namepos==-1): + continue + + name=line[:namepos].strip() + line=line[namepos:] + + argpos=line.rfind(")") + if (argpos==-1): + continue + + args=line[1:argpos] + + funcdata={} + funcdata["ret"]=ret + funcdata["name"]=name + funcdata["args"]=args + + functions.append(funcdata) + print(funcdata) + + + +#print(types) +#print(constants) +#print(functions) + + +f=open("glwrapper.h","w") + +f.write("#ifndef GL_WRAPPER\n") +f.write("#define GL_WRAPPER\n\n\n") + +header_code="""\ +#if defined(__gl_h_) || defined(__GL_H__) +#error gl.h included before glwrapper.h +#endif +#if defined(__glext_h_) || defined(__GLEXT_H_) +#error glext.h included before glwrapper.h +#endif +#if defined(__gl_ATI_h_) +#error glATI.h included before glwrapper.h +#endif + +#define __gl_h_ +#define __GL_H__ +#define __glext_h_ +#define __GLEXT_H_ +#define __gl_ATI_h_ + +#define GL_TRUE 1 +#define GL_FALSE 0 + +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_NONE 0 +#define GL_NO_ERROR 0 + +\n\n +""" + +f.write("#include <stddef.h>\n\n\n") + +f.write(header_code); + +f.write("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n") +f.write("#if defined(_WIN32) && !defined(__CYGWIN__)\n") +f.write("#define GLWRP_APIENTRY __stdcall\n") +f.write("#else\n"); +f.write("#define GLWRP_APIENTRY \n") +f.write("#endif\n\n"); +for x in types: + f.write(x+"\n") + +f.write("\n\n") + +for x in constants: + f.write(x+"\n") + +f.write("\n\n") + +for x in functions: + f.write("extern "+x["ret"]+" GLWRP_APIENTRY (*__wrapper_"+x["name"]+")("+x["args"]+");\n") + f.write("#define "+x["name"]+" __wrapper_"+x["name"]+"\n") + +f.write("\n\n") +f.write("typedef void (*GLWrapperFuncPtr)(void);\n\n"); +f.write("void glWrapperInit( GLWrapperFuncPtr (*wrapperFunc)(const char*) );\n") + +f.write("#ifdef __cplusplus\n}\n#endif\n") + +f.write("#endif\n\n") + +f=open("glwrapper.c","w") + +f.write("\n\n") +f.write("#include \"glwrapper.h\"\n") +f.write("\n\n") + +for x in functions: + f.write(x["ret"]+" GLWRP_APIENTRY (*__wrapper_"+x["name"]+")("+x["args"]+")=NULL;\n") + +f.write("\n\n") +f.write("void glWrapperInit( GLWrapperFuncPtr (*wrapperFunc)(const char*) ) {\n") +f.write("\n") + +for x in functions: + f.write("\t__wrapper_"+x["name"]+"=("+x["ret"]+" GLWRP_APIENTRY (*)("+x["args"]+"))wrapperFunc(\""+x["name"]+"\");\n") + +f.write("\n\n") +f.write("}\n") +f.write("\n\n") + + + + diff --git a/tools/steam/make_icons.sh b/tools/scripts/make_icons.sh index 71037cd1c3..71037cd1c3 100644 --- a/tools/steam/make_icons.sh +++ b/tools/scripts/make_icons.sh diff --git a/tools/memsort.py b/tools/scripts/memsort.py index d2e4fe0226..d2e4fe0226 100644 --- a/tools/memsort.py +++ b/tools/scripts/memsort.py diff --git a/tools/translations/ar.po b/tools/translations/ar.po index 74393ad4f4..de03046e16 100644 --- a/tools/translations/ar.po +++ b/tools/translations/ar.po @@ -33,6 +33,12 @@ msgid "step argument is zero!" msgstr "" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "" @@ -156,6 +162,10 @@ msgid "Editing Signal:" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Change Expression" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "" @@ -200,6 +210,43 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Condition" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "نداء" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -328,6 +375,85 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid unique name." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid product GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -474,6 +600,10 @@ msgid "" "It only provides navigation data." msgstr "" +#: scene/3d/remote_transform.cpp +msgid "Path property must point to a valid Spatial node to work." +msgstr "" + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1111,10 +1241,6 @@ msgid "Method List For '%s':" msgstr "" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "نداء" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "" @@ -1233,6 +1359,12 @@ msgid "Method in target Node must be specified!" msgstr "" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "" @@ -1308,6 +1440,15 @@ msgstr "" msgid "Create New" msgstr "" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1577,14 +1718,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -1979,14 +2112,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2072,6 +2197,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2230,6 +2359,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2254,6 +2387,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2293,6 +2430,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3122,10 +3263,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3666,6 +3803,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4404,6 +4545,10 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +msgid "Close All" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4511,6 +4656,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4887,6 +5036,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5152,6 +5305,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -5963,6 +6120,10 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +msgid "New Script" +msgstr "" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -5979,10 +6140,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/bg.po b/tools/translations/bg.po index 9117731250..f1fdc9086a 100644 --- a/tools/translations/bg.po +++ b/tools/translations/bg.po @@ -35,6 +35,12 @@ msgid "step argument is zero!" msgstr "Стъпката на range() е нула!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp #, fuzzy msgid "Not a script with an instance" msgstr "Скриптът няма инстанция" @@ -165,6 +171,10 @@ msgid "Editing Signal:" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Change Expression" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "" @@ -209,6 +219,44 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "Преходи" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -339,6 +387,86 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Error creating the signature object." +msgstr "Имаше грешка при изнасяне на проекта!" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid unique name." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid product GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -511,6 +639,13 @@ msgid "" "It only provides navigation data." msgstr "" +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "" +"Параметърът 'Path' трябва да сочи към действителен възел Particles2D, за да " +"работи." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1148,10 +1283,6 @@ msgid "Method List For '%s':" msgstr "" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "" @@ -1270,6 +1401,12 @@ msgid "Method in target Node must be specified!" msgstr "" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "" @@ -1345,6 +1482,15 @@ msgstr "" msgid "Create New" msgstr "" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "Любими:" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1615,14 +1761,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "Любими:" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -2017,14 +2155,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2110,6 +2240,10 @@ msgid "Quit to Project List" msgstr "Изход до списъка с проекти" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "Внасяне на обекти в проекта." @@ -2268,6 +2402,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2292,6 +2430,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2331,6 +2473,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "Възел" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3161,10 +3307,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "Възел" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3705,6 +3847,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4443,6 +4589,11 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Избиране на всичко" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4550,6 +4701,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4926,6 +5081,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5191,6 +5350,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -6002,6 +6165,11 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "Нова сцена" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -6018,10 +6186,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/bn.po b/tools/translations/bn.po index d0827bf38f..19861e2158 100644 --- a/tools/translations/bn.po +++ b/tools/translations/bn.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2016-08-12 06:37+0000\n" +"PO-Revision-Date: 2016-09-02 13:47+0000\n" "Last-Translator: ABU MD. MARUF SARKER <maruf.webdev@gmail.com>\n" "Language-Team: Bengali <https://hosted.weblate.org/projects/godot-engine/" "godot/bn/>\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2.8-dev\n" +"X-Generator: Weblate 2.8\n" #: modules/gdscript/gd_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -33,6 +33,12 @@ msgid "step argument is zero!" msgstr "ধাপ মান শূন্য!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "ইনস্ট্যান্স বিহীন স্ক্রিপ্ট" @@ -102,19 +108,19 @@ msgstr "ফাংশনগুলি:" #: modules/visual_script/visual_script_editor.cpp msgid "Variables:" -msgstr "" +msgstr "ভেরিয়েবলস/চলকসমূহ:" #: modules/visual_script/visual_script_editor.cpp tools/editor/editor_help.cpp msgid "Signals:" -msgstr "" +msgstr "সিগন্যালস/সংকেতসমূহ:" #: modules/visual_script/visual_script_editor.cpp msgid "Name is not a valid identifier:" -msgstr "" +msgstr "নামটি কার্যকর সনাক্তকারী নয়:" #: modules/visual_script/visual_script_editor.cpp msgid "Name already in use by another func/var/signal:" -msgstr "" +msgstr "নামটি ইতিমধ্যেই অপর ফাংশন/চলক(ভেরিয়েবল)/সংকেত(সিগন্যাল)-এ ব্যবহৃত হয়েছে:" #: modules/visual_script/visual_script_editor.cpp msgid "Rename Function" @@ -122,23 +128,23 @@ msgstr "ফাংশনের (Function) নতুন নামকরণ কর #: modules/visual_script/visual_script_editor.cpp msgid "Rename Variable" -msgstr "" +msgstr "চলক/ভেরিয়েবল-এর নামান্তর করুন" #: modules/visual_script/visual_script_editor.cpp msgid "Rename Signal" -msgstr "" +msgstr "সংকেত/সিগন্যাল-এর নামান্তর করুন" #: modules/visual_script/visual_script_editor.cpp msgid "Add Function" -msgstr "" +msgstr "ফাংশন সংযোজন করুন" #: modules/visual_script/visual_script_editor.cpp msgid "Add Variable" -msgstr "" +msgstr "চলক/ভেরিয়েবল সংযোজন করুন" #: modules/visual_script/visual_script_editor.cpp msgid "Add Signal" -msgstr "" +msgstr "সংকেত/সিগন্যাল সংযোজন করুন" #: modules/visual_script/visual_script_editor.cpp msgid "Remove Function" @@ -146,11 +152,11 @@ msgstr "ফাংশন (Function) অপসারণ করুন" #: modules/visual_script/visual_script_editor.cpp msgid "Remove Variable" -msgstr "" +msgstr "চলক/ভেরিয়েবল অপসারণ করুন" #: modules/visual_script/visual_script_editor.cpp msgid "Editing Variable:" -msgstr "" +msgstr "চলক/ভেরিয়েবল সম্পাদন:" #: modules/visual_script/visual_script_editor.cpp msgid "Remove Signal" @@ -158,19 +164,28 @@ msgstr "সংকেত (Signal) অপসারণ করুন" #: modules/visual_script/visual_script_editor.cpp msgid "Editing Signal:" -msgstr "" +msgstr "সংকেত/সিগন্যাল সম্পাদন:" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "অ্যানিমেশনের (Anim) ট্র্যানজিশন/স্থানান্তরণ পরিবর্তন করুন" #: modules/visual_script/visual_script_editor.cpp msgid "Add Node" -msgstr "" +msgstr "নোড সংযোজন করুন" #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"গেটার (Getter) ফেলতে/নামাতে মেটা কী (Meta) চাপুন। জেনেরিক সিগনেচার (generic " +"signature) ফেলতে/নামাতে শিফট কী (Shift) চাপুন।" #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"গেটার (Getter) ফেলতে/নামাতে কন্ট্রোল কী (Ctrl) চাপুন। জেনেরিক সিগনেচার (generic " +"signature) ফেলতে/নামাতে শিফট কী (Shift) চাপুন।" #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a simple reference to the node." @@ -205,6 +220,44 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "অনুবাদসমূহ" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -276,9 +329,8 @@ msgid "Cut Nodes" msgstr "" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Paste Nodes" -msgstr "প্রতিলেপন/পেস্ট করুন" +msgstr "নোড-সমূহ প্রতিলেপন/পেস্ট করুন" #: modules/visual_script/visual_script_flow_control.cpp msgid "Input type not iterable: " @@ -334,6 +386,87 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "ফন্টের আকার অগ্র্যহনযোগ্য।" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "ফন্টের আকার অগ্র্যহনযোগ্য।" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -515,6 +648,11 @@ msgstr "" "NavigationMeshInstance-কে অবশ্যই Navigation-এর অংশ অথবা অংশের অংশ হতে হবে। " "এটা শুধুমাত্র ন্যাভিগেশনের তথ্য প্রদান করে।" +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "Path এর দিক অবশ্যই একটি কার্যকর Particles2D এর দিকে নির্দেশ করাতে হবে।" + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1165,10 +1303,6 @@ msgid "Method List For '%s':" msgstr "" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "" @@ -1287,6 +1421,12 @@ msgid "Method in target Node must be specified!" msgstr "" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "" @@ -1362,6 +1502,15 @@ msgstr "" msgid "Create New" msgstr "" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1634,14 +1783,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -2036,14 +2177,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2129,6 +2262,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2287,6 +2424,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2311,6 +2452,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2350,6 +2495,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3179,10 +3328,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3722,6 +3867,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4460,6 +4609,11 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "সবগুলি বাছাই করুন" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4567,6 +4721,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4943,6 +5101,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5208,6 +5370,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -6019,6 +6185,10 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +msgid "New Script" +msgstr "" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -6035,10 +6205,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" @@ -6051,14 +6217,12 @@ msgid "Sections:" msgstr "" #: tools/editor/property_selector.cpp -#, fuzzy msgid "Select Property" -msgstr "মোড (Mode) বাছাই করুন" +msgstr "গুণাগুণ/বৈশিষ্ট্য বাছাই করুন" #: tools/editor/property_selector.cpp -#, fuzzy msgid "Select Method" -msgstr "মোড (Mode) বাছাই করুন" +msgstr "মেথড/পদ্ধতি বাছাই করুন" #: tools/editor/pvrtc_compress.cpp msgid "Could not execute PVRTC tool:" diff --git a/tools/translations/ca.po b/tools/translations/ca.po index 14d523b88b..9922663465 100644 --- a/tools/translations/ca.po +++ b/tools/translations/ca.po @@ -1,13 +1,13 @@ -# LANGUAGE translation of the Godot Engine editor +# Catalan translation of the Godot Engine editor # Copyright (C) 2016 Juan Linietsky, Ariel Manzur and the Godot community # This file is distributed under the same license as the Godot source code. # -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# Roger BR <drai_kin@hotmail.com>, 2016. # msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2016-09-01 11:46+0000\n" +"PO-Revision-Date: 2016-09-11 09:26+0000\n" "Last-Translator: Roger BR <drai_kin@hotmail.com>\n" "Language-Team: Catalan <https://hosted.weblate.org/projects/godot-engine/" "godot/ca/>\n" @@ -34,6 +34,12 @@ msgid "step argument is zero!" msgstr "L'argument pas (step) és zero!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "Script sense instància" @@ -166,37 +172,45 @@ msgid "Editing Signal:" msgstr "Editant Senyal:" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "Canvia Transició" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Afegeix Node" #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"Retén Meta per dipositar un mètode Accessor (Getter). Retén Maj per " +"dipositar una firma genèrica." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"Retén Ctrl per dipositar un mètode Accessor (Getter). Retén Maj per " +"dipositar una firma genèrica." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a simple reference to the node." -msgstr "" +msgstr "Retén Meta per dipositar una referència simple al node." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a simple reference to the node." -msgstr "" +msgstr "Retén Ctrl per dipositar una referència simple al node." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a Variable Setter." -msgstr "" +msgstr "Retén Meta per dipositar una variable d'Actualització (Setter)." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Variable Setter." -msgstr "" +msgstr "Retén Ctrl per dipositar una Variable d'Actualització (Setter)." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Preload Node" -msgstr "Afegeix Node" +msgstr "Afegeix Node de Precàrrega" #: modules/visual_script/visual_script_editor.cpp msgid "Add Node(s) From Tree" @@ -204,11 +218,50 @@ msgstr "Afegeix Node(s) des d'Arbre" #: modules/visual_script/visual_script_editor.cpp msgid "Add Getter Property" -msgstr "Afegir Captador de Propietat (Getter)" +msgstr "Afegeix Propietat d'Accés (Getter)" #: modules/visual_script/visual_script_editor.cpp msgid "Add Setter Property" -msgstr "Afegeix Col.locador de Proprietat (Setter)" +msgstr "Afegeix Propietat d'Actualització (Setter)" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "Transició" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "Retorn:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "Crida" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" #: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -276,11 +329,11 @@ msgstr "Troba el Tipus del Node" #: modules/visual_script/visual_script_editor.cpp msgid "Copy Nodes" -msgstr "" +msgstr "Copia Nodes" #: modules/visual_script/visual_script_editor.cpp msgid "Cut Nodes" -msgstr "" +msgstr "Talla els Nodes" #: modules/visual_script/visual_script_editor.cpp #, fuzzy @@ -344,6 +397,88 @@ msgstr "" "Valor de retorn de _step() invàlid. Ha de ser un nombre enter (seq out), o " "una cadena de text (error)." +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "Nom no vàlid." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "La mida de la lletra no és vàlida." + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid background color." +msgstr "Lletra personalitzada no vàlida." + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -464,7 +599,7 @@ msgid "" "must be set to 'render target' mode." msgstr "" "Cal que la propietat Camí (Path) assenyali un node de Vista (Viewport) " -"vàlid. Aquest ha de ser especificat en el mode \"destí de renderització" +"vàlid. Aquest ha de ser especificat en el mode \"destinació de renderització" "\" (render target)." #: scene/2d/sprite.cpp @@ -472,9 +607,9 @@ msgid "" "The Viewport set in the path property must be set as 'render target' in " "order for this sprite to work." msgstr "" -"L'àrea de Visualització (Viewport) especificada en la propietat \"Camí" -"\" (Path) ha d'utilitzar el mode 'destí de renderització' (render target) " -"perquè l'sprite funcioni." +"La Vista (Viewport) especificada en la propietat \"Camí\" (Path) ha " +"d'utilitzar el mode 'Destinació de renderització' (render target) perquè " +"l'sprite funcioni." #: scene/2d/visibility_notifier_2d.cpp msgid "" @@ -534,6 +669,12 @@ msgstr "" "NavigationMeshInstance ha de ser fill o nét d'un node Navigation. Només " "proporciona dades de navegació." +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "" +"Cal que la propietat Camí (Path) assenyali cap a un node Particles2D vàlid." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -770,10 +911,10 @@ msgid "" "obtain a size. Otherwise, make it a RenderTarget and assign its internal " "texture to some node for display." msgstr "" -"L'àrea de Visualització (Viewport) no és el Destí de Renderització (render " -"target). Per mostrar-ne el contingut, especifiqueu-la com a filla d'un " -"Control de forma per tal d'obtenir-ne la mida. Altrament, establiu-la com a " -"Destí de Renderització i assigneu la textura interna a algun node." +"La Vista (Viewport) no és la Destinació de Renderització (render target). " +"Per mostrar-ne el contingut, especifiqueu-la com a filla d'un Control de " +"forma per tal d'obtenir-ne la mida. Altrament, establiu-la com a Destinació " +"de Renderització i assigneu-ne la textura interna a algun node." #: scene/resources/dynamic_font.cpp #: tools/editor/io_plugins/editor_font_import_plugin.cpp @@ -1186,10 +1327,6 @@ msgid "Method List For '%s':" msgstr "Llista de mètodes de '%s':" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "Crida" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "Llista de mètodes:" @@ -1308,6 +1445,12 @@ msgid "Method in target Node must be specified!" msgstr "Cal especificar un mètode per al Node objectiu!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "Connecta al Node:" @@ -1384,6 +1527,15 @@ msgstr "Senyals" msgid "Create New" msgstr "Crea Nou" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "Favorits:" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "Recents:" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1662,14 +1814,6 @@ msgstr "Mou Favorit Amunt" msgid "Move Favorite Down" msgstr "Mou Favorit Avall" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "Favorits:" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "Recents:" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "Previsualització:" @@ -1793,109 +1937,111 @@ msgstr "Vaja..." #: tools/editor/editor_node.cpp msgid "Can't open file for writing:" -msgstr "" +msgstr "No s'ha pogut escriure en el fitxer:" #: tools/editor/editor_node.cpp msgid "Requested file format unknown:" -msgstr "" +msgstr "Format de fitxer desconegut:" #: tools/editor/editor_node.cpp msgid "Error while saving." -msgstr "" +msgstr "Error en desar." #: tools/editor/editor_node.cpp msgid "Saving Scene" -msgstr "" +msgstr "Desant Escena" #: tools/editor/editor_node.cpp msgid "Analyzing" -msgstr "" +msgstr "Analitzant" #: tools/editor/editor_node.cpp msgid "Creating Thumbnail" -msgstr "" +msgstr "Creant Miniatura" #: tools/editor/editor_node.cpp msgid "" "Couldn't save scene. Likely dependencies (instances) couldn't be satisfied." msgstr "" +"No s'ha pogut desar l'escena. Probablement, no s'han pogut establir totes " +"les dependències (instàncies)." #: tools/editor/editor_node.cpp msgid "Failed to load resource." -msgstr "" +msgstr "No s'ha pogut carregar el recurs." #: tools/editor/editor_node.cpp msgid "Can't load MeshLibrary for merging!" -msgstr "" +msgstr "No s'ha pogut carregar MeshLibrary per combinar les dades!!" #: tools/editor/editor_node.cpp msgid "Error saving MeshLibrary!" -msgstr "" +msgstr "Error en desar MeshLibrary!" #: tools/editor/editor_node.cpp msgid "Can't load TileSet for merging!" -msgstr "" +msgstr "No s'ha pogut carregar TileSet per combinar les dades!" #: tools/editor/editor_node.cpp msgid "Error saving TileSet!" -msgstr "" +msgstr "Error en desar TileSet!" #: tools/editor/editor_node.cpp msgid "Can't open export templates zip." -msgstr "" +msgstr "No s'ha pogut obrir el zip amb les plantilles d'exportació." #: tools/editor/editor_node.cpp msgid "Loading Export Templates" -msgstr "" +msgstr "Carregant Plantilles d'Exportació" #: tools/editor/editor_node.cpp msgid "Error trying to save layout!" -msgstr "" +msgstr "Error en desar els canvis!" #: tools/editor/editor_node.cpp msgid "Default editor layout overridden." -msgstr "" +msgstr "S'han sobreescrit els Ajustos Predeterminats de l'Editor." #: tools/editor/editor_node.cpp msgid "Layout name not found!" -msgstr "" +msgstr "No s'ha trobat el nom de l'ajust!" #: tools/editor/editor_node.cpp msgid "Restored default layout to base settings." -msgstr "" +msgstr "S'ha restaurat la configuració predeterminada." #: tools/editor/editor_node.cpp msgid "Copy Params" -msgstr "" +msgstr "Copia Paràmetres" #: tools/editor/editor_node.cpp msgid "Paste Params" -msgstr "" +msgstr "Enganxa Paràmetres" #: tools/editor/editor_node.cpp #: tools/editor/plugins/resource_preloader_editor_plugin.cpp msgid "Paste Resource" -msgstr "" +msgstr "Enganxa Recurs" #: tools/editor/editor_node.cpp msgid "Copy Resource" -msgstr "" +msgstr "Copia Recurs" #: tools/editor/editor_node.cpp msgid "Make Built-In" -msgstr "" +msgstr "Crea'l Integrat" #: tools/editor/editor_node.cpp msgid "Make Sub-Resources Unique" -msgstr "" +msgstr "Crea SubRecurs Únic" #: tools/editor/editor_node.cpp msgid "Open in Help" -msgstr "" +msgstr "Obre dins l'Ajuda" #: tools/editor/editor_node.cpp msgid "There is no defined scene to run." -msgstr "" +msgstr "No s'ha definit cap escena per executar." #: tools/editor/editor_node.cpp msgid "" @@ -1903,6 +2049,9 @@ msgid "" "You can change it later in later in \"Project Settings\" under the " "'application' category." msgstr "" +"No s'ha definit cap escena principal. Seleccioneu-ne una.\n" +"És possible triar-ne una altra més endavant a \"Configuració del Projecte\" " +"en la categoria \"aplicació\"." #: tools/editor/editor_node.cpp msgid "" @@ -1910,6 +2059,9 @@ msgid "" "You can change it later in \"Project Settings\" under the 'application' " "category." msgstr "" +"L'escena '%s' no existeix. Seleccioneu-ne una de vàlida.\n" +"És possible triar-ne una altra més endavant a \"Configuració del Projecte\" " +"en la categoria \"aplicació\"." #: tools/editor/editor_node.cpp msgid "" @@ -1917,248 +2069,254 @@ msgid "" "You can change it later in \"Project Settings\" under the 'application' " "category." msgstr "" +"L'escena '%s' seleccionada no és un fitxer d'escena. Seleccioneu-ne un de " +"vàlid.\n" +"És possible triar-ne una altra més endavant a \"Configuració del Projecte\" " +"en la categoria \"aplicació\"." #: tools/editor/editor_node.cpp msgid "Current scene was never saved, please save it prior to running." msgstr "" +"L'escena actual no s'ha desat encara. Desa l'escena abans d'executar-la." #: tools/editor/editor_node.cpp msgid "Could not start subprocess!" -msgstr "" +msgstr "No s'ha pogut començar el subprocés!" #: tools/editor/editor_node.cpp msgid "Open Scene" -msgstr "" +msgstr "Obre Escena" #: tools/editor/editor_node.cpp msgid "Open Base Scene" -msgstr "" +msgstr "Obre Escena Base" #: tools/editor/editor_node.cpp msgid "Quick Open Scene.." -msgstr "" +msgstr "Obertura Ràpida d'Escenes..." #: tools/editor/editor_node.cpp msgid "Quick Open Script.." -msgstr "" +msgstr "Obertura Ràpida d'Scripts..." #: tools/editor/editor_node.cpp msgid "Yes" -msgstr "" +msgstr "Sí" #: tools/editor/editor_node.cpp msgid "Close scene? (Unsaved changes will be lost)" -msgstr "" +msgstr "Tanca l'Escena? (Es perdran els canvis sense desar)" #: tools/editor/editor_node.cpp msgid "Save Scene As.." -msgstr "" +msgstr "Desa Escena com..." #: tools/editor/editor_node.cpp msgid "This scene has never been saved. Save before running?" msgstr "" +"Aquesta Escena no s'ha desat mai encara. Voleu desar-la abans d'executar-la?" #: tools/editor/editor_node.cpp msgid "Please save the scene first." -msgstr "" +msgstr "Desa l'escena abans." #: tools/editor/editor_node.cpp msgid "Save Translatable Strings" -msgstr "" +msgstr "Desa els texts Traduïbles" #: tools/editor/editor_node.cpp msgid "Export Mesh Library" -msgstr "" +msgstr "Exporta Biblioteca de Models" #: tools/editor/editor_node.cpp msgid "Export Tile Set" -msgstr "" +msgstr "Exporta el joc de Mosaics (Tiles)" #: tools/editor/editor_node.cpp msgid "Quit" -msgstr "" +msgstr "Surt" #: tools/editor/editor_node.cpp msgid "Exit the editor?" -msgstr "" +msgstr "Voleu Sortir de l'editor?" #: tools/editor/editor_node.cpp msgid "Current scene not saved. Open anyway?" -msgstr "" +msgstr "L'escena actual no s'ha desat. Vol obrir igualment?" #: tools/editor/editor_node.cpp msgid "Can't reload a scene that was never saved." -msgstr "" +msgstr "No es pot recarregar una escena no desada." #: tools/editor/editor_node.cpp msgid "Revert" -msgstr "" +msgstr "Reverteix" #: tools/editor/editor_node.cpp msgid "This action cannot be undone. Revert anyway?" -msgstr "" +msgstr "No es pot desfer aquesta acció. Vol revertir igualament?" #: tools/editor/editor_node.cpp msgid "Quick Run Scene.." -msgstr "" +msgstr "Execució Ràpida de l'Escena..." #: tools/editor/editor_node.cpp msgid "" "Open Project Manager? \n" "(Unsaved changes will be lost)" msgstr "" +"Vol Obrir el Gestor de Projectes?\n" +"(Es perdran els canvis sense desar)" #: tools/editor/editor_node.cpp msgid "Pick a Main Scene" -msgstr "" +msgstr "Tria una Escena Principal" #: tools/editor/editor_node.cpp tools/editor/scene_tree_dock.cpp msgid "Ugh" -msgstr "" +msgstr "Uf..." #: tools/editor/editor_node.cpp msgid "" "Error loading scene, it must be inside the project path. Use 'Import' to " "open the scene, then save it inside the project path." msgstr "" +"No s'ha pogut carregar l'escena: No es troba dins del camí del projecte. " +"Utilitzeu 'Importa' per obrir l'escena i deseu-la dins del camí del projecte." #: tools/editor/editor_node.cpp msgid "Error loading scene." -msgstr "" +msgstr "No s'ha pogut carregar l'escena." #: tools/editor/editor_node.cpp msgid "Scene '%s' has broken dependencies:" -msgstr "" +msgstr "Escena '%s' té dependències no vàlides:" #: tools/editor/editor_node.cpp msgid "Save Layout" -msgstr "" +msgstr "Desar Disposició (Layout)" #: tools/editor/editor_node.cpp msgid "Delete Layout" -msgstr "" +msgstr "Elimina Disposició (Layout)" #: tools/editor/editor_node.cpp tools/editor/project_export.cpp msgid "Default" -msgstr "" +msgstr "Predeterminat" #: tools/editor/editor_node.cpp msgid "Switch Scene Tab" -msgstr "" +msgstr "Canvia la pestanya d'escena" #: tools/editor/editor_node.cpp msgid "%d more file(s)" -msgstr "" +msgstr "%d fitxer(s) més" #: tools/editor/editor_node.cpp msgid "%d more file(s) or folder(s)" -msgstr "" +msgstr "%d fitxer(s) o directori(s) més" #: tools/editor/editor_node.cpp #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Scene" -msgstr "" +msgstr "Escena" #: tools/editor/editor_node.cpp msgid "Go to previously opened scene." -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" +msgstr "Vés a l'escena oberta anteriorment." #: tools/editor/editor_node.cpp msgid "Next tab" -msgstr "" +msgstr "Pestanya Següent" #: tools/editor/editor_node.cpp msgid "Previous tab" -msgstr "" +msgstr "Pestanya Anterior" #: tools/editor/editor_node.cpp msgid "Operations with scene files." -msgstr "" +msgstr "Operacions amb fitxers d'escena." #: tools/editor/editor_node.cpp msgid "New Scene" -msgstr "" +msgstr "Nova Escena" #: tools/editor/editor_node.cpp msgid "New Inherited Scene.." -msgstr "" +msgstr "Nova Escena heretada..." #: tools/editor/editor_node.cpp msgid "Open Scene.." -msgstr "" +msgstr "Obre Escena..." #: tools/editor/editor_node.cpp msgid "Save Scene" -msgstr "" +msgstr "Desa Escena" #: tools/editor/editor_node.cpp msgid "Save all Scenes" -msgstr "" +msgstr "Desa Totes les Escenes" #: tools/editor/editor_node.cpp msgid "Close Scene" -msgstr "" +msgstr "Tanca l'Escena" #: tools/editor/editor_node.cpp msgid "Close Goto Prev. Scene" -msgstr "" +msgstr "Tanca i Vés a l'Escena anterior" #: tools/editor/editor_node.cpp msgid "Open Recent" -msgstr "" +msgstr "Obre Recent" #: tools/editor/editor_node.cpp msgid "Quick Filter Files.." -msgstr "" +msgstr "Filtrat Ràpid de Fitxers..." #: tools/editor/editor_node.cpp msgid "Convert To.." -msgstr "" +msgstr "Converteix a..." #: tools/editor/editor_node.cpp msgid "Translatable Strings.." -msgstr "" +msgstr "Cadenes Traduïbles..." #: tools/editor/editor_node.cpp msgid "MeshLibrary.." -msgstr "" +msgstr "Biblioteca de Models (MeshLibrary)..." #: tools/editor/editor_node.cpp msgid "TileSet.." -msgstr "" +msgstr "Joc de Mosaics (TileSet)..." #: tools/editor/editor_node.cpp tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Redo" -msgstr "" +msgstr "Refés" #: tools/editor/editor_node.cpp msgid "Run Script" -msgstr "" +msgstr "Executa Script" #: tools/editor/editor_node.cpp msgid "Project Settings" -msgstr "" +msgstr "Configuració del Projecte" #: tools/editor/editor_node.cpp msgid "Revert Scene" -msgstr "" +msgstr "Reverteix Escena" #: tools/editor/editor_node.cpp msgid "Quit to Project List" -msgstr "" +msgstr "Surt a la Llista de Projectes" + +#: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "Mode Lliure de Distraccions" #: tools/editor/editor_node.cpp msgid "Import assets to the project." -msgstr "" +msgstr "Importa actius al projecte." #: tools/editor/editor_node.cpp #: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp @@ -2170,83 +2328,85 @@ msgstr "" #: tools/editor/io_plugins/editor_translation_import_plugin.cpp #: tools/editor/project_manager.cpp msgid "Import" -msgstr "" +msgstr "Importa" #: tools/editor/editor_node.cpp msgid "Miscellaneous project or scene-wide tools." -msgstr "" +msgstr "Eines vàries o d'escena." #: tools/editor/editor_node.cpp msgid "Tools" -msgstr "" +msgstr "Eines" #: tools/editor/editor_node.cpp msgid "Export the project to many platforms." -msgstr "" +msgstr "Exporta el projecte a diverses plataformes." #: tools/editor/editor_node.cpp tools/editor/project_export.cpp msgid "Export" -msgstr "" +msgstr "Exporta" #: tools/editor/editor_node.cpp msgid "Play the project." -msgstr "" +msgstr "Reprodueix el projecte." #: tools/editor/editor_node.cpp #: tools/editor/plugins/sample_library_editor_plugin.cpp msgid "Play" -msgstr "" +msgstr "Reprodueix" #: tools/editor/editor_node.cpp msgid "Pause the scene" -msgstr "" +msgstr "Pausa l'escena" #: tools/editor/editor_node.cpp msgid "Pause Scene" -msgstr "" +msgstr "Pausa Escena" #: tools/editor/editor_node.cpp msgid "Stop the scene." -msgstr "" +msgstr "Atura l'escena." #: tools/editor/editor_node.cpp #: tools/editor/plugins/sample_library_editor_plugin.cpp msgid "Stop" -msgstr "" +msgstr "Atura" #: tools/editor/editor_node.cpp msgid "Play the edited scene." -msgstr "" +msgstr "Reprodueix l'escena editada." #: tools/editor/editor_node.cpp msgid "Play Scene" -msgstr "" +msgstr "Reprodueix Escena" #: tools/editor/editor_node.cpp msgid "Play custom scene" -msgstr "" +msgstr "Reprodueix escena personalitzada" #: tools/editor/editor_node.cpp msgid "Play Custom Scene" -msgstr "" +msgstr "Reprodueix Escena Personalitzada" #: tools/editor/editor_node.cpp msgid "Debug options" -msgstr "" +msgstr "Opcions de Depuració (Debug)" #: tools/editor/editor_node.cpp msgid "Deploy with Remote Debug" -msgstr "" +msgstr "Desplega amb Depuració Remota" #: tools/editor/editor_node.cpp msgid "" "When exporting or deploying, the resulting executable will attempt to " "connect to the IP of this computer in order to be debugged." msgstr "" +"En ser exportat o desplegat, l'executable resultant intenta connectar-se a " +"l'IP d'aquest equip per iniciar-ne la depuració." #: tools/editor/editor_node.cpp msgid "Small Deploy with Network FS" -msgstr "" +msgstr "Desplegament Reduït amb Sistema de Fitxers en Xarxa" #: tools/editor/editor_node.cpp msgid "" @@ -2257,30 +2417,40 @@ msgid "" "On Android, deploy will use the USB cable for faster performance. This " "option speeds up testing for games with a large footprint." msgstr "" +"Amb aquesta opció activada, 'Exportar' o 'Desplegar' generen un executable " +"reduït.\n" +"L'Editor proveeix el sistema de fitxers del projecte a través de la xarxa.\n" +"En sistemes Android, 'Desplegar' utilitzarà el cable USB per millorar-ne el " +"rendiment. Aquesta opció ajuda a accelerar els cicles de prova i verificació " +"en jocs de gran mida." #: tools/editor/editor_node.cpp msgid "Visible Collision Shapes" -msgstr "" +msgstr "Formes de Col·lisió Visibles" #: tools/editor/editor_node.cpp msgid "" "Collision shapes and raycast nodes (for 2D and 3D) will be visible on the " "running game if this option is turned on." msgstr "" +"Les formes de col·lisió i nodes de difusió de raigs (raycast) (per a 2D i " +"3D), son visibles durant l'execució del joc quan s'activa aquesta opció." #: tools/editor/editor_node.cpp msgid "Visible Navigation" -msgstr "" +msgstr "Navegació Visible" #: tools/editor/editor_node.cpp msgid "" "Navigation meshes and polygons will be visible on the running game if this " "option is turned on." msgstr "" +"Les malles i polígons de Navegació són visibles durant l'execució del joc " +"quan s'activa aquesta opció." #: tools/editor/editor_node.cpp msgid "Sync Scene Changes" -msgstr "" +msgstr "Sincronitza Canvis en Escenes" #: tools/editor/editor_node.cpp msgid "" @@ -2289,10 +2459,14 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" +"En activar aquesta opció, els canvis fets en l'Editor es repliquen en el joc " +"en execució.\n" +"En usar-se remotament en un dispositiu, un sistema de fitxers en xarxa en " +"millora el rendiment." #: tools/editor/editor_node.cpp msgid "Sync Script Changes" -msgstr "" +msgstr "Sincronitza Canvis en Scripts" #: tools/editor/editor_node.cpp msgid "" @@ -2301,382 +2475,403 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" +"En activar aquesta opció, els scripts, en ser desats, es recarreguen en el " +"joc en execució.\n" +"En usar-se remotament en un dispositiu, un sistema de fitxers en xarxa en " +"millora el rendiment." #: tools/editor/editor_node.cpp tools/editor/plugins/spatial_editor_plugin.cpp msgid "Settings" -msgstr "" +msgstr "Configuració" #: tools/editor/editor_node.cpp tools/editor/settings_config_dialog.cpp msgid "Editor Settings" -msgstr "" +msgstr "Configuració de l'Editor" #: tools/editor/editor_node.cpp msgid "Editor Layout" -msgstr "" +msgstr "Disposició de l'Editor" + +#: tools/editor/editor_node.cpp +#, fuzzy +msgid "Toggle Fullscreen" +msgstr "Mode Pantalla completa" #: tools/editor/editor_node.cpp msgid "Install Export Templates" -msgstr "" +msgstr "Instal·la Plantilles d'Exportació" #: tools/editor/editor_node.cpp msgid "About" -msgstr "" +msgstr "Quant a" #: tools/editor/editor_node.cpp msgid "Alerts when an external resource has changed." -msgstr "" +msgstr "Alerta en canviar un recurs extern." #: tools/editor/editor_node.cpp msgid "Spins when the editor window repaints!" -msgstr "" +msgstr "Gira en repintar-se la finestra de l'editor!" #: tools/editor/editor_node.cpp msgid "Update Always" -msgstr "" +msgstr "Actualitza Sempre" #: tools/editor/editor_node.cpp msgid "Update Changes" +msgstr "Actualitza Canvis" + +#: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" msgstr "" #: tools/editor/editor_node.cpp msgid "Inspector" -msgstr "" +msgstr "Inspector" #: tools/editor/editor_node.cpp msgid "Create a new resource in memory and edit it." -msgstr "" +msgstr "Crea un nou recurs en memòria i edita'l." #: tools/editor/editor_node.cpp msgid "Load an existing resource from disk and edit it." -msgstr "" +msgstr "Carrega un recurs des del disc i edita'l." #: tools/editor/editor_node.cpp msgid "Save the currently edited resource." -msgstr "" +msgstr "Desa el recurs editat ara." #: tools/editor/editor_node.cpp tools/editor/plugins/script_editor_plugin.cpp msgid "Save As.." -msgstr "" +msgstr "Desa Com..." #: tools/editor/editor_node.cpp msgid "Go to the previous edited object in history." -msgstr "" +msgstr "Vés a l'anterior objecte editat de l'historial." #: tools/editor/editor_node.cpp msgid "Go to the next edited object in history." -msgstr "" +msgstr "Vés al següent objecte editat de l'historial." #: tools/editor/editor_node.cpp msgid "History of recently edited objects." -msgstr "" +msgstr "Historial d'objectes editats recentment." #: tools/editor/editor_node.cpp msgid "Object properties." -msgstr "" +msgstr "Propietats de l'objecte." #: tools/editor/editor_node.cpp msgid "FileSystem" +msgstr "SistemaDeFitxers" + +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" msgstr "" #: tools/editor/editor_node.cpp msgid "Output" -msgstr "" +msgstr "Sortida" #: tools/editor/editor_node.cpp tools/editor/editor_reimport_dialog.cpp msgid "Re-Import" -msgstr "" +msgstr "ReImporta" #: tools/editor/editor_node.cpp tools/editor/editor_plugin_settings.cpp msgid "Update" -msgstr "" +msgstr "Actualitza" #: tools/editor/editor_node.cpp msgid "Thanks from the Godot community!" -msgstr "" +msgstr "Gràcies de la part de la Comunitat del Godot!" #: tools/editor/editor_node.cpp msgid "Thanks!" -msgstr "" +msgstr "Gràcies!" #: tools/editor/editor_node.cpp msgid "Import Templates From ZIP File" -msgstr "" +msgstr "Importa Plantilles des d'un Fitxer ZIP" #: tools/editor/editor_node.cpp tools/editor/project_export.cpp msgid "Export Project" -msgstr "" +msgstr "Exporta Projecte" #: tools/editor/editor_node.cpp msgid "Export Library" -msgstr "" +msgstr "Exporta Biblioteca" #: tools/editor/editor_node.cpp msgid "Merge With Existing" -msgstr "" +msgstr "Combina amb Existents" #: tools/editor/editor_node.cpp tools/editor/project_export.cpp msgid "Password:" -msgstr "" +msgstr "Contrasenya:" #: tools/editor/editor_node.cpp msgid "Open & Run a Script" -msgstr "" +msgstr "Obre i Executa un Script" #: tools/editor/editor_node.cpp msgid "Load Errors" -msgstr "" +msgstr "Errors de Càrrega" #: tools/editor/editor_plugin_settings.cpp msgid "Installed Plugins:" -msgstr "" +msgstr "Connectors Instal·lats:" #: tools/editor/editor_plugin_settings.cpp msgid "Version:" -msgstr "" +msgstr "Versió:" #: tools/editor/editor_plugin_settings.cpp msgid "Author:" -msgstr "" +msgstr "Autor:" #: tools/editor/editor_plugin_settings.cpp msgid "Status:" -msgstr "" +msgstr "Estat:" #: tools/editor/editor_profiler.cpp msgid "Stop Profiling" -msgstr "" +msgstr "Atura Perfilació" #: tools/editor/editor_profiler.cpp msgid "Start Profiling" -msgstr "" +msgstr "Comença Perfilació" #: tools/editor/editor_profiler.cpp msgid "Measure:" -msgstr "" +msgstr "Mesura:" #: tools/editor/editor_profiler.cpp msgid "Frame Time (sec)" -msgstr "" +msgstr "Duració del Fotograma (s)" #: tools/editor/editor_profiler.cpp msgid "Average Time (sec)" -msgstr "" +msgstr "Temps Mitjà (s)" #: tools/editor/editor_profiler.cpp msgid "Frame %" -msgstr "" +msgstr "% del Fotograma" #: tools/editor/editor_profiler.cpp msgid "Fixed Frame %" -msgstr "" +msgstr "% del Fotograma Fix" #: tools/editor/editor_profiler.cpp tools/editor/script_editor_debugger.cpp msgid "Time:" -msgstr "" +msgstr "Temps:" #: tools/editor/editor_profiler.cpp msgid "Inclusive" -msgstr "" +msgstr "Inclusiu" #: tools/editor/editor_profiler.cpp msgid "Self" -msgstr "" +msgstr "Propi" #: tools/editor/editor_profiler.cpp msgid "Frame #:" -msgstr "" +msgstr "Fotograma núm.:" #: tools/editor/editor_reimport_dialog.cpp msgid "Please wait for scan to complete." -msgstr "" +msgstr "Espera que s'acabi l'anàlisi." #: tools/editor/editor_reimport_dialog.cpp msgid "Current scene must be saved to re-import." -msgstr "" +msgstr "S'ha de desar l'escena abans de reimportar-la." #: tools/editor/editor_reimport_dialog.cpp msgid "Save & Re-Import" -msgstr "" +msgstr "Desa i ReImporta" #: tools/editor/editor_reimport_dialog.cpp msgid "Re-Import Changed Resources" -msgstr "" +msgstr "ReImporta Recursos Modificats" #: tools/editor/editor_run_script.cpp msgid "Write your logic in the _run() method." -msgstr "" +msgstr "Escriu la lògica en el mètode _run()." #: tools/editor/editor_run_script.cpp msgid "There is an edited scene already." -msgstr "" +msgstr "Ja hi ha un escena editada." #: tools/editor/editor_run_script.cpp msgid "Couldn't instance script:" -msgstr "" +msgstr "No s'ha pogut instanciar l'script:" #: tools/editor/editor_run_script.cpp msgid "Did you forget the 'tool' keyword?" -msgstr "" +msgstr "Podria mancar la paraula clau 'tool'?" #: tools/editor/editor_run_script.cpp msgid "Couldn't run script:" -msgstr "" +msgstr "No s'ha pogut executar l'script:" #: tools/editor/editor_run_script.cpp msgid "Did you forget the '_run' method?" -msgstr "" +msgstr "Podria mancar el mètode '_run'?" #: tools/editor/editor_settings.cpp msgid "Default (Same as Editor)" -msgstr "" +msgstr "Predeterminat (Idèntic a l'Editor)" #: tools/editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" -msgstr "" +msgstr "Selecciona Node(s) per Importar" #: tools/editor/editor_sub_scene.cpp msgid "Scene Path:" -msgstr "" +msgstr "Camí de l'Escena:" #: tools/editor/editor_sub_scene.cpp msgid "Import From Node:" -msgstr "" +msgstr "Importa des del Node:" #: tools/editor/file_type_cache.cpp msgid "Can't open file_type_cache.cch for writing, not saving file type cache!" msgstr "" +"No s'ha pogut escriure el fitxer file_type_cache.cch. No es desara el cau de " +"tipus de fitxers!" #: tools/editor/filesystem_dock.cpp msgid "Same source and destination files, doing nothing." msgstr "" +"Els fitxers d'origen i destinació són els mateixos. No s'ha produït cap " +"acció." #: tools/editor/filesystem_dock.cpp msgid "Same source and destination paths, doing nothing." -msgstr "" +msgstr "El camí d'origen i destinació es idèntic. No s'ha produït cap acció." #: tools/editor/filesystem_dock.cpp msgid "Can't move directories to within themselves." -msgstr "" +msgstr "No es poden moure directoris en si mateixos." #: tools/editor/filesystem_dock.cpp msgid "Can't operate on '..'" -msgstr "" +msgstr "No es pot operar en '..'" #: tools/editor/filesystem_dock.cpp msgid "Pick New Name and Location For:" -msgstr "" +msgstr "Tria un Nou Nom i Ubicació per a:" #: tools/editor/filesystem_dock.cpp msgid "No files selected!" -msgstr "" +msgstr "Cap fitxer seleccionat!" #: tools/editor/filesystem_dock.cpp msgid "Instance" -msgstr "" +msgstr "Instància" #: tools/editor/filesystem_dock.cpp msgid "Edit Dependencies.." -msgstr "" +msgstr "Edita Dependències..." #: tools/editor/filesystem_dock.cpp msgid "View Owners.." -msgstr "" +msgstr "Mostra Propietaris..." #: tools/editor/filesystem_dock.cpp msgid "Copy Path" -msgstr "" +msgstr "Copia Camí" #: tools/editor/filesystem_dock.cpp msgid "Rename or Move.." -msgstr "" +msgstr "Renomena o Mou..." #: tools/editor/filesystem_dock.cpp msgid "Move To.." -msgstr "" +msgstr "Mou cap a..." #: tools/editor/filesystem_dock.cpp msgid "Info" -msgstr "" +msgstr "Informació" #: tools/editor/filesystem_dock.cpp msgid "Show In File Manager" -msgstr "" +msgstr "Mostra en el Gestor de Fitxers" #: tools/editor/filesystem_dock.cpp msgid "Re-Import.." -msgstr "" +msgstr "ReImporta..." #: tools/editor/filesystem_dock.cpp msgid "Previous Directory" -msgstr "" +msgstr "Directori Anterior" #: tools/editor/filesystem_dock.cpp msgid "Next Directory" -msgstr "" +msgstr "Directori Següent" #: tools/editor/filesystem_dock.cpp msgid "Re-Scan Filesystem" -msgstr "" +msgstr "ReAnalitza Sistema de Fitxers" #: tools/editor/filesystem_dock.cpp msgid "Toggle folder status as Favorite" -msgstr "" +msgstr "Canvia l'estat del directori a Preferit" #: tools/editor/filesystem_dock.cpp msgid "Instance the selected scene(s) as child of the selected node." -msgstr "" +msgstr "Instancia les escenes seleccionades com a filles del node seleccionat." #: tools/editor/filesystem_dock.cpp msgid "Move" -msgstr "" +msgstr "Mou" #: tools/editor/groups_editor.cpp msgid "Add to Group" -msgstr "" +msgstr "Afegeix al Grup" #: tools/editor/groups_editor.cpp msgid "Remove from Group" -msgstr "" +msgstr "Treu del Grup" #: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp msgid "No bit masks to import!" -msgstr "" +msgstr "Cap màscara de bits per importar!" #: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp #: tools/editor/io_plugins/editor_sample_import_plugin.cpp #: tools/editor/io_plugins/editor_scene_import_plugin.cpp #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Target path is empty." -msgstr "" +msgstr "El camí de Destinació és buit." #: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp #: tools/editor/io_plugins/editor_sample_import_plugin.cpp #: tools/editor/io_plugins/editor_scene_import_plugin.cpp #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Target path must be a complete resource path." -msgstr "" +msgstr "El camí de Destinació ha de ser un camí de recursos complet." #: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp #: tools/editor/io_plugins/editor_sample_import_plugin.cpp #: tools/editor/io_plugins/editor_scene_import_plugin.cpp #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Target path must exist." -msgstr "" +msgstr "El camí de Destinació ha d'existir." #: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp #: tools/editor/io_plugins/editor_mesh_import_plugin.cpp #: tools/editor/io_plugins/editor_sample_import_plugin.cpp msgid "Save path is empty!" -msgstr "" +msgstr "El camí per desar és buit!" #: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp msgid "Import BitMasks" -msgstr "" +msgstr "Importa Màscares de Bit" #: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Source Texture(s):" -msgstr "" +msgstr "Textures Font:" #: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp #: tools/editor/io_plugins/editor_mesh_import_plugin.cpp @@ -2685,7 +2880,7 @@ msgstr "" #: tools/editor/io_plugins/editor_texture_import_plugin.cpp #: tools/editor/io_plugins/editor_translation_import_plugin.cpp msgid "Target Path:" -msgstr "" +msgstr "Camí de Destinació:" #: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp #: tools/editor/io_plugins/editor_font_import_plugin.cpp @@ -2694,318 +2889,326 @@ msgstr "" #: tools/editor/io_plugins/editor_texture_import_plugin.cpp #: tools/editor/io_plugins/editor_translation_import_plugin.cpp msgid "Accept" -msgstr "" +msgstr "Accepta" #: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp msgid "Bit Mask" -msgstr "" +msgstr "Màscara de bits" #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "No source font file!" -msgstr "" +msgstr "Cap fitxer de lletra font!" #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "No target font resource!" -msgstr "" +msgstr "Cap recurs de Lletra!" #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "" "Invalid file extension.\n" "Please use .fnt." msgstr "" +"Extensió de fitxer no vàlida.\n" +"Utilitzeu .fnt." #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "Can't load/process source font." -msgstr "" +msgstr "No es pot carregar/processar la lletra." #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "Couldn't save font." -msgstr "" +msgstr "No s'ha pogut desar la lletra." #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "Source Font:" -msgstr "" +msgstr "Lletra:" #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "Source Font Size:" -msgstr "" +msgstr "Mida de la lletra:" #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "Dest Resource:" -msgstr "" +msgstr "Recurs Objectiu:" #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "The quick brown fox jumps over the lazy dog." msgstr "" +"«Dóna amor que seràs feliç!». Això, il·lús veí i company geniüt, ja és un " +"lluït rètol d'onze kWh." #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "Test:" -msgstr "" +msgstr "Prova:" #: tools/editor/io_plugins/editor_font_import_plugin.cpp #: tools/editor/io_plugins/editor_mesh_import_plugin.cpp #: tools/editor/io_plugins/editor_sample_import_plugin.cpp #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Options:" -msgstr "" +msgstr "Opcions:" #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "Font Import" -msgstr "" +msgstr "Importa lletra" #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "" "This file is already a Godot font file, please supply a BMFont type file " "instead." msgstr "" +"Aquest fitxer ja és un fitxer de lletra de Godot. Proveïu un fitxer de tipus " +"BMFont." #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "Failed opening as BMFont file." -msgstr "" +msgstr "No s'ha pogut obrir com a fitxer BMFont." #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "Invalid font custom source." -msgstr "" +msgstr "Lletra personalitzada no vàlida." #: tools/editor/io_plugins/editor_font_import_plugin.cpp #: tools/editor/plugins/theme_editor_plugin.cpp msgid "Font" -msgstr "" +msgstr "Lletra" #: tools/editor/io_plugins/editor_mesh_import_plugin.cpp msgid "No meshes to import!" -msgstr "" +msgstr "Cap malla per importar!" #: tools/editor/io_plugins/editor_mesh_import_plugin.cpp msgid "Single Mesh Import" -msgstr "" +msgstr "Importa una Malla" #: tools/editor/io_plugins/editor_mesh_import_plugin.cpp msgid "Source Mesh(es):" -msgstr "" +msgstr "Malla/es :" #: tools/editor/io_plugins/editor_mesh_import_plugin.cpp #: tools/editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh" -msgstr "" +msgstr "Malla" #: tools/editor/io_plugins/editor_mesh_import_plugin.cpp msgid "Surface %d" -msgstr "" +msgstr "Superfície %d" #: tools/editor/io_plugins/editor_sample_import_plugin.cpp msgid "No samples to import!" -msgstr "" +msgstr "No s'ha trobat cap mostra d'Àudio per importar!" #: tools/editor/io_plugins/editor_sample_import_plugin.cpp msgid "Import Audio Samples" -msgstr "" +msgstr "Importa Mostra d'Àudio" #: tools/editor/io_plugins/editor_sample_import_plugin.cpp msgid "Source Sample(s):" -msgstr "" +msgstr "Mostra/es d'Origen:" #: tools/editor/io_plugins/editor_sample_import_plugin.cpp msgid "Audio Sample" -msgstr "" +msgstr "Mostra d'Àudio" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "New Clip" -msgstr "" +msgstr "Nou Clip" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Animation Options" -msgstr "" +msgstr "Opcions d'Animació" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#, fuzzy msgid "Flags" -msgstr "" +msgstr "Indicadors (flags)" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Bake FPS:" -msgstr "" +msgstr "Fer Bake dels FPS:" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Optimizer" -msgstr "" +msgstr "Optimitzador" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Max Linear Error" -msgstr "" +msgstr "Error Lineal Màxim" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Max Angular Error" -msgstr "" +msgstr "Error Angular Màxim" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Max Angle" -msgstr "" +msgstr "Angle Màxim" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Clips" -msgstr "" +msgstr "Clips" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Start(s)" -msgstr "" +msgstr "Inici/s" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "End(s)" -msgstr "" +msgstr "Final/s" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp #: tools/editor/plugins/sprite_frames_editor_plugin.cpp msgid "Loop" -msgstr "" +msgstr "Bucle" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Filters" -msgstr "" +msgstr "Filtres" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Source path is empty." -msgstr "" +msgstr "El camí d'origen és buit." #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Couldn't load post-import script." -msgstr "" +msgstr "No s'ha pogut carregar l'script de post-importació." #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Invalid/broken script for post-import." -msgstr "" +msgstr "L'script de post-importació no és vàlid ." #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Error importing scene." -msgstr "" +msgstr "No s'ha pogut importar l'escena." #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Import 3D Scene" -msgstr "" +msgstr "Importa Escena 3D" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Source Scene:" -msgstr "" +msgstr "Escena d'Origen:" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Same as Target Scene" -msgstr "" +msgstr "Igual que l'Escena de Destinació" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Shared" -msgstr "" +msgstr "Compartit" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Target Texture Folder:" -msgstr "" +msgstr "Directori per a Textures escollit:" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Post-Process Script:" -msgstr "" +msgstr "Script de Post-Processat:" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Custom Root Node Type:" -msgstr "" +msgstr "Tipus de Node Arrel Personalitzat:" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Auto" -msgstr "" +msgstr "Auto" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "The Following Files are Missing:" -msgstr "" +msgstr "Manquen els següents Fitxers:" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Import Anyway" -msgstr "" +msgstr "Importa Igualment" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Import & Open" -msgstr "" +msgstr "Importa i Obre" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Edited scene has not been saved, open imported scene anyway?" msgstr "" +"No s'ha desat l'escena editada. Vol obrir l'escena importada igualment?" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp #: tools/editor/plugins/cube_grid_theme_editor_plugin.cpp msgid "Import Scene" -msgstr "" +msgstr "Importa Escena" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Importing Scene.." -msgstr "" +msgstr "Important Escena..." #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Running Custom Script.." -msgstr "" +msgstr "Executant Script Personalitzat..." #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Couldn't load post-import script:" -msgstr "" +msgstr "No s'ha pogut carregar l'script de post-importació:" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Invalid/broken script for post-import (check console):" -msgstr "" +msgstr "L'script de post-importació no és vàlid (comprova el terminal):" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Error running post-import script:" -msgstr "" +msgstr "Error en l'execució de l'script de post-importació:" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Import Image:" -msgstr "" +msgstr "Importa Imatge:" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Can't import a file over itself:" -msgstr "" +msgstr "No es pot importar un fitxer dins de si mateix:" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Couldn't localize path: %s (already local)" -msgstr "" +msgstr "No s'ha pogut localitzar el camí: %s (ja és local)" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Saving.." -msgstr "" +msgstr "Desant..." #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "3D Scene Animation" -msgstr "" +msgstr "Animació d'Escenes 3D" #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Uncompressed" -msgstr "" +msgstr "Sense Compressió" #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Compress Lossless (PNG)" -msgstr "" +msgstr "Compressió sense Pèrdua (PNG)" #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Compress Lossy (WebP)" -msgstr "" +msgstr "Compressió amb Pèrdua (WebP)" #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Compress (VRAM)" -msgstr "" +msgstr "Compressió (VRAM)" #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Texture Format" -msgstr "" +msgstr "Format de Textura" #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Texture Compression Quality (WebP):" -msgstr "" +msgstr "Qualitat de Compressió de Textura (WebP):" #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Texture Options" -msgstr "" +msgstr "Opcions de Textura" #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Please specify some files!" -msgstr "" +msgstr "Cal especificar algun fitxer!" #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "At least one file needed for Atlas." -msgstr "" +msgstr "Es necessita com a mínim un fitxer per a l'Atles." #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Error importing:" @@ -3207,10 +3410,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3750,6 +3949,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4488,6 +4691,11 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Tanca" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4595,6 +4803,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4971,6 +5183,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5000,27 +5216,27 @@ msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "1 Viewport" -msgstr "" +msgstr "1 Vista" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "2 Viewports" -msgstr "" +msgstr "2 Vistes" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "2 Viewports (Alt)" -msgstr "" +msgstr "2 Vistes (Alt)" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "3 Viewports" -msgstr "" +msgstr "3 Vistes" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "3 Viewports (Alt)" -msgstr "" +msgstr "3 Vistes (Alt)" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "4 Viewports" -msgstr "" +msgstr "4 Vistes" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Display Normal" @@ -5048,7 +5264,7 @@ msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Snap Settings" -msgstr "" +msgstr "Configuració de Desplaçament" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Translate Snap:" @@ -5064,7 +5280,7 @@ msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Viewport Settings" -msgstr "" +msgstr "Configuració de la Vista" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Default Light Normal:" @@ -5236,6 +5452,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -5465,7 +5685,7 @@ msgstr "" #: tools/editor/project_export.cpp msgid "Project Export Settings" -msgstr "" +msgstr "Configuració d'Exportació de Projectes" #: tools/editor/project_export.cpp msgid "Target" @@ -5896,11 +6116,11 @@ msgstr "" #: tools/editor/project_settings.cpp msgid "Error saving settings." -msgstr "" +msgstr "No s'ha pogut desar la configuració." #: tools/editor/project_settings.cpp msgid "Settings saved OK." -msgstr "" +msgstr "Configuració desada correctament." #: tools/editor/project_settings.cpp msgid "Add Translation" @@ -5932,7 +6152,7 @@ msgstr "" #: tools/editor/project_settings.cpp msgid "Project Settings (engine.cfg)" -msgstr "" +msgstr "Configuració del Projecte (engine.cfg)" #: tools/editor/project_settings.cpp tools/editor/settings_config_dialog.cpp msgid "General" @@ -6047,6 +6267,11 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "Executa Script" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -6063,10 +6288,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" @@ -6150,7 +6371,7 @@ msgstr "" #: tools/editor/run_settings_dialog.cpp msgid "Scene Run Settings" -msgstr "" +msgstr "Configuració d'Execució d'Escenes" #: tools/editor/scene_tree_dock.cpp msgid "OK :(" diff --git a/tools/translations/cs.po b/tools/translations/cs.po index bbe2142bcb..0975e3c550 100644 --- a/tools/translations/cs.po +++ b/tools/translations/cs.po @@ -33,6 +33,12 @@ msgid "step argument is zero!" msgstr "" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "Skript nemá instanci" @@ -162,6 +168,11 @@ msgid "Editing Signal:" msgstr "Úprava signálu:" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "Animace: změna přechodu" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Přidat uzel" @@ -207,6 +218,45 @@ msgid "Add Setter Property" msgstr "Přidat vlastnost setter" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "Přechod" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "Vrátit:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "Volat" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -337,6 +387,87 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "Neplatný název." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "Neplatná velikost fontu." + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -514,6 +645,13 @@ msgstr "" "NavigationMeshInstance musí být dítětem nebo vnoučetem uzlu Navigation. " "Poskytuje pouze data pro navigaci." +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "" +"Aby ParticleAttractor2D fungoval, musí vlastnost path ukazovat na platný " +"uzel Particles2D." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1164,10 +1302,6 @@ msgid "Method List For '%s':" msgstr "Seznam metod '%s':" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "Volat" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "Seznam metod:" @@ -1286,6 +1420,12 @@ msgid "Method in target Node must be specified!" msgstr "Je nutné zadat metodu v cílovém uzlu!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "Připojit k uzlu:" @@ -1361,6 +1501,15 @@ msgstr "Signály" msgid "Create New" msgstr "Vytvořit nový" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1638,14 +1787,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -2040,14 +2181,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2133,6 +2266,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2291,6 +2428,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2315,6 +2456,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2354,6 +2499,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3183,10 +3332,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3727,6 +3872,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4465,6 +4614,11 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Zavřít" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4572,6 +4726,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4948,6 +5106,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5213,6 +5375,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -6024,6 +6190,10 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +msgid "New Script" +msgstr "" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -6040,10 +6210,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/da.po b/tools/translations/da.po index 640babcf07..3294ca2105 100644 --- a/tools/translations/da.po +++ b/tools/translations/da.po @@ -32,6 +32,12 @@ msgid "step argument is zero!" msgstr "trin argument er nul!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "Ikke et script med en instans" @@ -160,6 +166,11 @@ msgid "Editing Signal:" msgstr "Redigerer Signal:" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "Anim Skift Overgang" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Tilføj Node" @@ -205,6 +216,45 @@ msgid "Add Setter Property" msgstr "Tilføj Setter Egenskab" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "Overgang" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "Tilbage:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "Kald" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -338,6 +388,87 @@ msgstr "" "Ugyldig retur værdi fra _step(), skal være heltal (seq ud), eller en streng " "(fejl)." +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "Ugyldigt index egenskabsnavn." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "Ugyldig skriftstørrelse." + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -522,6 +653,11 @@ msgstr "" "NavigationMeshInstance skal være et barn eller barnebarn til en Navigation " "node. Det giver kun navigationsdata." +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "Egenskaben Path skal pege på en gyldig Particles2D node for at virke." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1172,10 +1308,6 @@ msgid "Method List For '%s':" msgstr "Metode liste For '%s':" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "Kald" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "Metode liste:" @@ -1294,6 +1426,12 @@ msgid "Method in target Node must be specified!" msgstr "Metode i target Node skal angives!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "Opret forbindelse til Node:" @@ -1369,6 +1507,15 @@ msgstr "Signaler" msgid "Create New" msgstr "Opret en ny" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1642,14 +1789,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -2044,14 +2183,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2137,6 +2268,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2295,6 +2430,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2319,6 +2458,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2358,6 +2501,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3187,10 +3334,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3730,6 +3873,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4468,6 +4615,11 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Luk" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4575,6 +4727,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4951,6 +5107,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5216,6 +5376,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -6027,6 +6191,10 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +msgid "New Script" +msgstr "" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -6043,10 +6211,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/de.po b/tools/translations/de.po index 4b1fb9d166..12351973d5 100644 --- a/tools/translations/de.po +++ b/tools/translations/de.po @@ -13,6 +13,7 @@ # Oliver Ruehl <oliver@ruehldesign.co>, 2016. # Paul-Vincent Roll <paviro@me.com>, 2016. # Peter Friedland <peter_friedland@gmx.de>, 2016. +# No need for a name <endoplasmatik@gmx.net>, 2016. # So Wieso <sowieso@dukun.de>, 2016. # Timo Schwarzer <account@timoschwarzer.com>, 2016. # viernullvier <hannes.breul+github@gmail.com>, 2016. @@ -21,7 +22,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2016-08-31 15:37+0000\n" +"PO-Revision-Date: 2016-09-30 03:13+0000\n" "Last-Translator: So Wieso <sowieso@dukun.de>\n" "Language-Team: German <https://hosted.weblate.org/projects/godot-engine/" "godot/de/>\n" @@ -30,7 +31,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2.8\n" +"X-Generator: Weblate 2.9-dev\n" #: modules/gdscript/gd_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -49,6 +50,12 @@ msgid "step argument is zero!" msgstr "Schrittargument ist null!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "Skript hat keine Instanz" @@ -58,25 +65,25 @@ msgstr "Nicht auf einem Skript basierend" #: modules/gdscript/gd_functions.cpp msgid "Not based on a resource file" -msgstr "Nicht auf einer Resourcendatei basierend" +msgstr "Nicht auf einer Ressourcendatei basierend" #: modules/gdscript/gd_functions.cpp msgid "Invalid instance dictionary format (missing @path)" -msgstr "Ungültiges Instanzverzeichnisformat (@path fehlt)" +msgstr "Ungültiges Instanz-Verzeichnisformat (@path fehlt)" #: modules/gdscript/gd_functions.cpp msgid "Invalid instance dictionary format (can't load script at @path)" msgstr "" -"Ungültiges Instanzverzeichnisformat (Skript in @path kann nicht geladen " +"Ungültiges Instanz-Verzeichnisformat (Skript in @path kann nicht geladen " "werden)" #: modules/gdscript/gd_functions.cpp msgid "Invalid instance dictionary format (invalid script at @path)" -msgstr "Ungültiges Instanzverzeichnisformat (ungültiges Skript in @path)" +msgstr "Ungültiges Instanz-Verzeichnisformat (ungültiges Skript in @path)" #: modules/gdscript/gd_functions.cpp msgid "Invalid instance dictionary (invalid subclasses)" -msgstr "Ungültiges Instanzverzeichnisformat (ungültige Unterklasse)" +msgstr "Ungültiges Instanz-Verzeichnisformat (ungültige Unterklasse)" #: modules/visual_script/visual_script.cpp msgid "" @@ -109,7 +116,7 @@ msgstr "Node gab ungültige Sequenzausgabe zurück: " #: modules/visual_script/visual_script.cpp msgid "Found sequence bit but not the node in the stack, report bug!" msgstr "" -"Sequenzbit gefunden aber kein entsprechendes Node auf dem Stack, bitte " +"Sequenzbit gefunden, aber kein entsprechendes Node auf dem Stack, bitte " "melden Sie den Bug!" #: modules/visual_script/visual_script.cpp @@ -181,37 +188,45 @@ msgid "Editing Signal:" msgstr "bearbeite Signal:" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "Typ ändern" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Node hinzufügen" #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"Alt-Taste gedrückt halten, um einen Getter zu setzen. Umschalt-Taste halten, " +"um eine allgemeine Signatur zu setzen." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"Strg-Taste halten um einen Getter zu setzen. Umschalt-Taste halten um eine " +"allgemeine Signatur zu setzen." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a simple reference to the node." -msgstr "" +msgstr "Alt-Taste halten um einfache Referenz zu Node hinzuzufügen." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a simple reference to the node." -msgstr "" +msgstr "Strg-Taste halten um einfache Referenz zu Node hinzuzufügen." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a Variable Setter." -msgstr "" +msgstr "Alt-Taste halten um einen Variablen-Setter zu setzen." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Variable Setter." -msgstr "" +msgstr "Strg-Taste halten um einen Variablen-Setter zu setzen." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Preload Node" -msgstr "Node hier anhängen" +msgstr "Preload-Node hinzufügen" #: modules/visual_script/visual_script_editor.cpp msgid "Add Node(s) From Tree" @@ -226,6 +241,47 @@ msgid "Add Setter Property" msgstr "Setter-Eigenschaft hinzufügen" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "Animation kopieren" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Switch" +msgstr "Tonhöhe" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "Rückgabe:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "Aufruf" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Get" +msgstr "Setzen" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "Setzen" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -286,28 +342,24 @@ msgid "Toggle Breakpoint" msgstr "Haltepunkt umschalten" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Find Node Type" -msgstr "Finde Node-Typ" +msgstr "Node-Typ finden" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Copy Nodes" -msgstr "Pose kopieren" +msgstr "Nodes kopieren" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Cut Nodes" -msgstr "Erzeuge Node" +msgstr "Nodes trennen" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Paste Nodes" -msgstr "Pose einfügen" +msgstr "Nodes einfügen" #: modules/visual_script/visual_script_flow_control.cpp msgid "Input type not iterable: " -msgstr "Eingabetyp nicht iterierbar: " +msgstr "Eingabetyp nicht wiederholbar: " #: modules/visual_script/visual_script_flow_control.cpp msgid "Iterator became invalid" @@ -363,6 +415,90 @@ msgstr "" "Ungültiger Rückgabewert von _step(), muss Integer (für Sequenzausgabe) oder " "String (für Fehler) sein." +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Error creating the signature object." +msgstr "Fehler beim Schreiben des Projekt-PCK!" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "Ungültiger Name." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "Ungültige Schriftgröße." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid publisher GUID." +msgstr "Ungültiger Pfad" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid background color." +msgstr "Eigene Schriftart-Quelle ist ungültig." + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -557,6 +693,11 @@ msgstr "" "Eine NavigationMesh-Instanz muss ein Unterobjekt erster oder höherer Ordnung " "eines Navigation-Nodes sein. Es liefert nur Navigationsdaten." +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "Die Pfad-Eigenschaft muss auf ein gültiges Particles2D-Node verweisen." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -903,7 +1044,7 @@ msgstr "Auswahl duplizieren" #: tools/editor/animation_editor.cpp msgid "Duplicate Transposed" -msgstr "Transponiert duplizieren" +msgstr "Transponierte duplizieren" #: tools/editor/animation_editor.cpp msgid "Remove Selection" @@ -1210,10 +1351,6 @@ msgid "Method List For '%s':" msgstr "Methodenliste für '%s':" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "Aufruf" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "Methodenliste:" @@ -1332,6 +1469,12 @@ msgid "Method in target Node must be specified!" msgstr "Methode in Ziel-Node muss angegeben werden!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "Verbinde mit Node:" @@ -1407,6 +1550,15 @@ msgstr "Signale" msgid "Create New" msgstr "Neu erstellen" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "Favoriten:" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "Kürzlich:" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1689,14 +1841,6 @@ msgstr "Favorit nach oben schieben" msgid "Move Favorite Down" msgstr "Favorit nach unten schieben" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "Favoriten:" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "Kürzlich:" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "Vorschau:" @@ -2110,14 +2254,6 @@ msgid "Go to previously opened scene." msgstr "Gehe zu vorher geöffneter Szene." #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "Vollbildmodus" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "Ablenkungsfreier Modus" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "Nächster Tab" @@ -2203,6 +2339,10 @@ msgid "Quit to Project List" msgstr "Verlasse zur Projektverwaltung" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "Ablenkungsfreier Modus" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "Importiere Medieninhalte ins Projekt." @@ -2236,7 +2376,7 @@ msgstr "Exportieren" #: tools/editor/editor_node.cpp msgid "Play the project." -msgstr "Projekt starten." +msgstr "Projekt abspielen." #: tools/editor/editor_node.cpp #: tools/editor/plugins/sample_library_editor_plugin.cpp @@ -2381,6 +2521,11 @@ msgid "Editor Layout" msgstr "Editorlayout" #: tools/editor/editor_node.cpp +#, fuzzy +msgid "Toggle Fullscreen" +msgstr "Vollbildmodus" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "Exportvorlagen installieren" @@ -2405,6 +2550,10 @@ msgid "Update Changes" msgstr "Änderungen aktualisieren" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "Inspektor" @@ -2444,6 +2593,10 @@ msgstr "Objekteigenschaften." msgid "FileSystem" msgstr "Dateisystem" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "Node" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "Ausgabe" @@ -2546,7 +2699,7 @@ msgstr "Inklusive" #: tools/editor/editor_profiler.cpp msgid "Self" -msgstr "Self" +msgstr "Selbst" #: tools/editor/editor_profiler.cpp msgid "Frame #:" @@ -3282,10 +3435,6 @@ msgid "MultiNode Set" msgstr "MultiNode setzen" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "Node" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "Gruppen" @@ -3333,7 +3482,6 @@ msgid "Add Animation" msgstr "Animation hinzufügen" #: tools/editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Blend Next Changed" msgstr "Überblende nächste Bearbeitung" @@ -3493,7 +3641,7 @@ msgstr "Blenden" #: tools/editor/plugins/animation_tree_editor_plugin.cpp msgid "Mix" -msgstr "Mix" +msgstr "Mischen" #: tools/editor/plugins/animation_tree_editor_plugin.cpp msgid "Auto Restart:" @@ -3541,14 +3689,12 @@ msgid "Add Input" msgstr "Eingang hinzufügen" #: tools/editor/plugins/animation_tree_editor_plugin.cpp -#, fuzzy msgid "Clear Auto-Advance" -msgstr "Stoppe automatisches Durchschalten" +msgstr "Lösche Auto-Fortschritt" #: tools/editor/plugins/animation_tree_editor_plugin.cpp -#, fuzzy msgid "Set Auto-Advance" -msgstr "Setze automatisches Durchschalten" +msgstr "Setze Auto-Fortschritt" #: tools/editor/plugins/animation_tree_editor_plugin.cpp msgid "Delete Input" @@ -3664,7 +3810,7 @@ msgstr "Nachbearbeiten von Textur #" #: tools/editor/plugins/baked_light_editor_plugin.cpp msgid "Bake!" -msgstr "Bake!" +msgstr "Backen!" #: tools/editor/plugins/baked_light_editor_plugin.cpp msgid "Reset the lightmap octree baking process (start over)." @@ -3834,6 +3980,11 @@ msgid "Clear Bones" msgstr "Knochen entfernen" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy +msgid "Show Bones" +msgstr "Knochen erstellen" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "IK-Kette erzeugen" @@ -4122,9 +4273,8 @@ msgid "Parent has no solid faces to populate." msgstr "Elternelement hat keine soliden Faces zu besetzen." #: tools/editor/plugins/multimesh_editor_plugin.cpp -#, fuzzy msgid "Couldn't map area." -msgstr "Gebiet konnte nicht abgebildet werden." +msgstr "Bereich konnte nicht abgebildet werden." #: tools/editor/plugins/multimesh_editor_plugin.cpp msgid "Select a Source Mesh:" @@ -4135,14 +4285,12 @@ msgid "Select a Target Surface:" msgstr "Ziel-Oberfläche auswählen:" #: tools/editor/plugins/multimesh_editor_plugin.cpp -#, fuzzy msgid "Populate Surface" -msgstr "Oberfläche besetzen" +msgstr "Oberfläche füllen" #: tools/editor/plugins/multimesh_editor_plugin.cpp -#, fuzzy msgid "Populate MultiMesh" -msgstr "MultiMesh besetzen" +msgstr "MultiMesh füllen" #: tools/editor/plugins/multimesh_editor_plugin.cpp msgid "Target Surface:" @@ -4181,9 +4329,8 @@ msgid "Random Scale:" msgstr "Zufällige Skalieren:" #: tools/editor/plugins/multimesh_editor_plugin.cpp -#, fuzzy msgid "Populate" -msgstr "Besetzen" +msgstr "Füllen" #: tools/editor/plugins/navigation_polygon_editor_plugin.cpp msgid "Create Navigation Polygon" @@ -4258,9 +4405,8 @@ msgid "Emission Positions:" msgstr "Emissionsorte:" #: tools/editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Emission Fill:" -msgstr "Emissionsausschüttung" +msgstr "Emissionsfüllung:" #: tools/editor/plugins/particles_editor_plugin.cpp msgid "Surface" @@ -4578,6 +4724,11 @@ msgid "Close Docs" msgstr "Dokumentation schließen" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Schließen" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4689,6 +4840,11 @@ msgstr "" "Eingebettete Skripte können nur bearbeitet werden wenn die entsprechende " "Szene geladen ist" +#: tools/editor/plugins/script_text_editor.cpp +#, fuzzy +msgid "Pick Color" +msgstr "Farbe" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "Schiebe hoch" @@ -5066,11 +5222,14 @@ msgstr "Animations-Schlüsselbild einfügen" #: tools/editor/plugins/spatial_editor_plugin.cpp #, fuzzy +msgid "Focus Origin" +msgstr "Zeige Ursprung" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" -msgstr "zur Auswahl springen" +msgstr "Auswahl fokussieren" #: tools/editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Align Selection With View" msgstr "Auswahl auf Ansicht ausrichten" @@ -5332,6 +5491,11 @@ msgid "Remove Item" msgstr "Entferne Element" #: tools/editor/plugins/theme_editor_plugin.cpp +#, fuzzy +msgid "Theme" +msgstr "Motiv speichern" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "Füge Klassen-Element hinzu" @@ -5994,9 +6158,8 @@ msgid "Erase Input Action Event" msgstr "Lösche Eingabeaktionsereignis" #: tools/editor/project_settings.cpp -#, fuzzy msgid "Toggle Persisting" -msgstr "Dauerhaft umschalten" +msgstr "Persistente an- und ausschalten" #: tools/editor/project_settings.cpp msgid "Error saving settings." @@ -6088,7 +6251,7 @@ msgstr "Hinzufügen.." #: tools/editor/project_settings.cpp msgid "Remaps" -msgstr "Remaps" +msgstr "Neu zuweisen" #: tools/editor/project_settings.cpp msgid "Resources:" @@ -6115,14 +6278,12 @@ msgid "Preset.." msgstr "Voreinstellungen.." #: tools/editor/property_editor.cpp -#, fuzzy msgid "Ease In" -msgstr "Einfahren" +msgstr "Einblenden" #: tools/editor/property_editor.cpp -#, fuzzy msgid "Ease Out" -msgstr "Ausfahren" +msgstr "Ausblenden" #: tools/editor/property_editor.cpp msgid "Zero" @@ -6153,6 +6314,11 @@ msgid "Assign" msgstr "Zuweisen" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "Nächstes Skript" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "Fehler beim Laden der Datei: Keine Ressource!" @@ -6169,11 +6335,6 @@ msgid "On" msgstr "An" #: tools/editor/property_editor.cpp -#, fuzzy -msgid "Set" -msgstr "Setzen" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "Eigenschaften:" @@ -6186,14 +6347,12 @@ msgid "Sections:" msgstr "Abschnitte:" #: tools/editor/property_selector.cpp -#, fuzzy msgid "Select Property" -msgstr "Punkte auswählen" +msgstr "Eigenschaft auswählen" #: tools/editor/property_selector.cpp -#, fuzzy msgid "Select Method" -msgstr "Auswahlmodus" +msgstr "Methode auswählen" #: tools/editor/pvrtc_compress.cpp msgid "Could not execute PVRTC tool:" @@ -6298,10 +6457,9 @@ msgid "Instance Scene(s)" msgstr "Instanz-Szene(n)" #: tools/editor/scene_tree_dock.cpp -#, fuzzy msgid "This operation can't be done on the tree root." msgstr "" -"Diese Aktion kann nicht auf der Wurzel des Szenenbaums ausgeführt werden." +"Diese Aktion kann nicht in der Wurzel des Szenenbaums ausgeführt werden." #: tools/editor/scene_tree_dock.cpp msgid "Move Node In Parent" @@ -6602,7 +6760,7 @@ msgstr "Nächste Instanz untersuchen" #: tools/editor/script_editor_debugger.cpp msgid "Stack Frames" -msgstr "Stack Frames" +msgstr "Einzelbilder stapeln" #: tools/editor/script_editor_debugger.cpp msgid "Variable" @@ -6617,16 +6775,14 @@ msgid "Stack Trace (if applicable):" msgstr "Stack Trace (falls geeignet):" #: tools/editor/script_editor_debugger.cpp -#, fuzzy msgid "Remote Inspector" -msgstr "Ferninspektor" +msgstr "Remote Inspektor" #: tools/editor/script_editor_debugger.cpp msgid "Live Scene Tree:" msgstr "Echtzeit Szenenbaum:" #: tools/editor/script_editor_debugger.cpp -#, fuzzy msgid "Remote Object Properties: " msgstr "Eigenschaften entfernter Objekte: " @@ -6711,9 +6867,8 @@ msgid "Change Sphere Shape Radius" msgstr "Ändere Radius der Kugelform" #: tools/editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Change Box Shape Extents" -msgstr "Ändere Ausmessungen der Kastenform" +msgstr "Ändere Ausmaße der Kastenform" #: tools/editor/spatial_editor_gizmos.cpp msgid "Change Capsule Shape Radius" @@ -6728,7 +6883,6 @@ msgid "Change Ray Shape Length" msgstr "Ändere Länge der Strahlenform" #: tools/editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Change Notifier Extents" msgstr "Ändere Ausmaße des Benachrichtigers" diff --git a/tools/translations/de_CH.po b/tools/translations/de_CH.po index bc64a20805..6c5e6b65c3 100644 --- a/tools/translations/de_CH.po +++ b/tools/translations/de_CH.po @@ -32,6 +32,12 @@ msgid "step argument is zero!" msgstr "" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "" @@ -158,6 +164,11 @@ msgstr "" #: modules/visual_script/visual_script_editor.cpp #, fuzzy +msgid "Change Expression" +msgstr "Typ ändern" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy msgid "Add Node" msgstr "Node" @@ -204,6 +215,43 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Condition" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -337,6 +385,86 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Error creating the signature object." +msgstr "Fehler beim Schreiben des Projekts PCK!" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid unique name." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid product GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -502,6 +630,11 @@ msgid "" "It only provides navigation data." msgstr "" +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "Die Pfad-Variable muss auf einen gültigen Particles2D Node verweisen." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1143,10 +1276,6 @@ msgid "Method List For '%s':" msgstr "" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "" @@ -1265,6 +1394,12 @@ msgid "Method in target Node must be specified!" msgstr "Die Methode muss im Ziel Node definiert werden!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp #, fuzzy msgid "Connect To Node:" msgstr "Verbindung zu Node:" @@ -1341,6 +1476,15 @@ msgstr "" msgid "Create New" msgstr "" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1610,14 +1754,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -2012,14 +2148,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2106,6 +2234,10 @@ msgid "Quit to Project List" msgstr "Zurück zur Projektliste" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "Assets zum Projekt importieren." @@ -2268,6 +2400,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2292,6 +2428,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2331,6 +2471,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "Node" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3164,10 +3308,6 @@ msgid "MultiNode Set" msgstr "MultiNode Set" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "Node" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3714,6 +3854,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4455,6 +4599,10 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +msgid "Close All" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4562,6 +4710,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4939,6 +5091,10 @@ msgid "Insert Animation Key" msgstr "Bild einfügen" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5204,6 +5360,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -6016,6 +6176,11 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "Script hinzufügen" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -6032,10 +6197,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/es.po b/tools/translations/es.po index f428d54d8b..c02a679529 100644 --- a/tools/translations/es.po +++ b/tools/translations/es.po @@ -13,8 +13,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2016-09-01 11:47+0000\n" -"Last-Translator: Roger BR <drai_kin@hotmail.com>\n" +"PO-Revision-Date: 2016-09-01 19:29+0000\n" +"Last-Translator: Swyter <swyterzone@gmail.com>\n" "Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/" "godot/es/>\n" "Language: es\n" @@ -43,6 +43,12 @@ msgid "step argument is zero!" msgstr "¡El argumento «step» es cero!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "No es un script con una instancia" @@ -177,37 +183,45 @@ msgid "Editing Signal:" msgstr "Editando señal:" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "Cambiar tipo" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Añadir nodo" #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"Mantén pulsado Meta para quitar un «Setter». Mantén pulsado Mayús para " +"quitar una firma genérica." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"Mantén pulsado Ctrl para quitar un «Getter». Mantén pulsado Mayús para " +"quitar una firma genérica." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a simple reference to the node." -msgstr "" +msgstr "Mantén pulsado Meta para quitar una referencia simple del nodo." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a simple reference to the node." -msgstr "" +msgstr "Mantén pulsado Ctrl para quitar una referencia simple del nodo." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a Variable Setter." -msgstr "" +msgstr "Mantén pulsado Meta para quitar un «Setter» de variable." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Variable Setter." -msgstr "" +msgstr "Mantén pulsado Ctrl para quitar un «Setter» de variable." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Preload Node" -msgstr "Añadir nodo hijo" +msgstr "Añadir nodo «Preload»" #: modules/visual_script/visual_script_editor.cpp msgid "Add Node(s) From Tree" @@ -222,6 +236,47 @@ msgid "Add Setter Property" msgstr "Añadir propiedad «Setter»" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "Copiar animación" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Switch" +msgstr "Altura" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "Devuelve:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "Llamada" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Get" +msgstr "Establecer" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "Establecer" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -358,6 +413,90 @@ msgstr "" "El valor devuelto por _step() no es correcto, debe ser un entero (seq out), " "o string/cadena (error)." +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Error creating the signature object." +msgstr "¡Error al escribir el PCK de proyecto!" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "El nombre no es correcto." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "Tamaño de tipografía incorrecto." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid publisher GUID." +msgstr "Ruta base incorrecta" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid background color." +msgstr "El origen personalizado de tipografía no es correcto." + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -544,6 +683,12 @@ msgstr "" "NavigationMeshInstance debe ser un hijo o nieto de un nodo Navigation. Ya " "que sólo proporciona los datos de navegación." +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "" +"La propiedad Path debe apuntar a un nodo Particles2D valido para funcionar." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -577,11 +722,11 @@ msgstr "Aceptar" #: scene/gui/dialogs.cpp msgid "Alert!" -msgstr "¡Advertencia!" +msgstr "Notificación" #: scene/gui/dialogs.cpp msgid "Please Confirm..." -msgstr "Confirmar decisión..." +msgstr "Confirmar decisión…" #: scene/gui/file_dialog.cpp tools/editor/editor_file_dialog.cpp msgid "File Exists, Overwrite?" @@ -1039,7 +1184,7 @@ msgstr "Paso (s):" #: tools/editor/animation_editor.cpp msgid "Cursor step snap (in seconds)." -msgstr "Snap de cursor por pasos (en segundos)." +msgstr "Fijado de cursor por pasos (en segundos)." #: tools/editor/animation_editor.cpp msgid "Enable/Disable looping in animation." @@ -1174,7 +1319,7 @@ msgstr "Sitio:" #: tools/editor/asset_library_editor_plugin.cpp msgid "Support.." -msgstr "Ayuda..." +msgstr "Ayuda…" #: tools/editor/asset_library_editor_plugin.cpp msgid "Official" @@ -1197,10 +1342,6 @@ msgid "Method List For '%s':" msgstr "Lista de métodos Para '%s':" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "Llamada" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "Lista de métodos:" @@ -1319,6 +1460,12 @@ msgid "Method in target Node must be specified!" msgstr "¡Debes establecer un método en el nodo seleccionado!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "Conectar a nodo:" @@ -1380,7 +1527,7 @@ msgstr "Crear suscripción" #: tools/editor/connections_dialog.cpp msgid "Connect.." -msgstr "Conectar..." +msgstr "Conectar…" #: tools/editor/connections_dialog.cpp #: tools/editor/plugins/animation_tree_editor_plugin.cpp @@ -1395,6 +1542,15 @@ msgstr "Señales" msgid "Create New" msgstr "Crear nuevo" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "Favoritos:" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "Recientes:" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1625,11 +1781,11 @@ msgstr "Actualizando escena" #: tools/editor/editor_data.cpp msgid "Storing local changes.." -msgstr "Guardando cambios locales.." +msgstr "Guardando cambios locales…" #: tools/editor/editor_data.cpp msgid "Updating scene.." -msgstr "Actualizando escena.." +msgstr "Actualizando escena…" #: tools/editor/editor_dir_dialog.cpp msgid "Choose a Directory" @@ -1679,14 +1835,6 @@ msgstr "Subir favorito" msgid "Move Favorite Down" msgstr "Bajar favorito" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "Favoritos:" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "Recientes:" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "Vista previa:" @@ -1774,7 +1922,7 @@ msgstr "Exportando para %s" #: tools/editor/editor_import_export.cpp msgid "Setting Up.." -msgstr "Configurando..." +msgstr "Configurando…" #: tools/editor/editor_log.cpp msgid " Output:" @@ -1802,11 +1950,11 @@ msgstr "¡Hubo un error al guardar el recurso!" #: tools/editor/plugins/animation_player_editor_plugin.cpp #: tools/editor/resources_dock.cpp msgid "Save Resource As.." -msgstr "Guardar recurso como.." +msgstr "Guardar recurso como…" #: tools/editor/editor_node.cpp tools/editor/scene_tree_dock.cpp msgid "I see.." -msgstr "Muy bien..." +msgstr "Muy bien…" #: tools/editor/editor_node.cpp msgid "Can't open file for writing:" @@ -1966,11 +2114,11 @@ msgstr "Abrir escena base" #: tools/editor/editor_node.cpp msgid "Quick Open Scene.." -msgstr "Abrir escena rápido.." +msgstr "Apertura rápida de escena…" #: tools/editor/editor_node.cpp msgid "Quick Open Script.." -msgstr "Abrir script rápido.." +msgstr "Apertura rápida de script…" #: tools/editor/editor_node.cpp msgid "Yes" @@ -1982,7 +2130,7 @@ msgstr "¿Quieres cerrar la escena? (Los cambios sin guardar se perderán)" #: tools/editor/editor_node.cpp msgid "Save Scene As.." -msgstr "Guardar escena como.." +msgstr "Guardar escena como…" #: tools/editor/editor_node.cpp msgid "This scene has never been saved. Save before running?" @@ -2031,7 +2179,7 @@ msgstr "Esta acción es irreversible. ¿Quieres revertirla de todos modos?" #: tools/editor/editor_node.cpp msgid "Quick Run Scene.." -msgstr "Ejecutar escena rápido.." +msgstr "Ejecución rápida de escena…" #: tools/editor/editor_node.cpp msgid "" @@ -2100,14 +2248,6 @@ msgid "Go to previously opened scene." msgstr "Ir a la escena abierta previamente." #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "Modo pantalla completa" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "Modo sin distracciones" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "Pestaña siguiente" @@ -2125,7 +2265,7 @@ msgstr "Nueva escena" #: tools/editor/editor_node.cpp msgid "New Inherited Scene.." -msgstr "Nueva escena heredada.." +msgstr "Nueva escena heredada…" #: tools/editor/editor_node.cpp msgid "Open Scene.." @@ -2153,23 +2293,23 @@ msgstr "Abrir reciente" #: tools/editor/editor_node.cpp msgid "Quick Filter Files.." -msgstr "Filtrado rápido de archivos..." +msgstr "Filtrado rápido de archivos…" #: tools/editor/editor_node.cpp msgid "Convert To.." -msgstr "Convertir a..." +msgstr "Convertir a…" #: tools/editor/editor_node.cpp msgid "Translatable Strings.." -msgstr "Cadenas traducibles..." +msgstr "Cadenas traducibles…" #: tools/editor/editor_node.cpp msgid "MeshLibrary.." -msgstr "MeshLibrary..." +msgstr "MeshLibrary…" #: tools/editor/editor_node.cpp msgid "TileSet.." -msgstr "TileSet.." +msgstr "TileSet…" #: tools/editor/editor_node.cpp tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp @@ -2193,6 +2333,10 @@ msgid "Quit to Project List" msgstr "Salir al listado del proyecto" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "Modo sin distracciones" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "Importar elementos al proyecto." @@ -2370,6 +2514,11 @@ msgid "Editor Layout" msgstr "Ajustes de diseño del editor" #: tools/editor/editor_node.cpp +#, fuzzy +msgid "Toggle Fullscreen" +msgstr "Modo pantalla completa" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "Instalar plantillas de exportación" @@ -2394,6 +2543,10 @@ msgid "Update Changes" msgstr "Actualizar cambios" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "Inspector" @@ -2411,7 +2564,7 @@ msgstr "Guardar el recurso editado actualmente." #: tools/editor/editor_node.cpp tools/editor/plugins/script_editor_plugin.cpp msgid "Save As.." -msgstr "Guardar como..." +msgstr "Guardar como…" #: tools/editor/editor_node.cpp msgid "Go to the previous edited object in history." @@ -2433,6 +2586,10 @@ msgstr "Propiedades del objeto." msgid "FileSystem" msgstr "SistDeArchivos" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "Nodo" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "Salida" @@ -2619,7 +2776,7 @@ msgstr "No se pueden mover carpetas dentro de si mismas." #: tools/editor/filesystem_dock.cpp msgid "Can't operate on '..'" -msgstr "No se puede operar en '..'" +msgstr "No se puede operar en «…»" #: tools/editor/filesystem_dock.cpp msgid "Pick New Name and Location For:" @@ -2635,11 +2792,11 @@ msgstr "Instanciar" #: tools/editor/filesystem_dock.cpp msgid "Edit Dependencies.." -msgstr "Editar dependencias.." +msgstr "Editar dependencias…" #: tools/editor/filesystem_dock.cpp msgid "View Owners.." -msgstr "Ver dueños.." +msgstr "Ver dueños…" #: tools/editor/filesystem_dock.cpp msgid "Copy Path" @@ -2647,11 +2804,11 @@ msgstr "Copiar ruta" #: tools/editor/filesystem_dock.cpp msgid "Rename or Move.." -msgstr "Renombrar o mover.." +msgstr "Renombrar o mover…" #: tools/editor/filesystem_dock.cpp msgid "Move To.." -msgstr "Mover a.." +msgstr "Mover a…" #: tools/editor/filesystem_dock.cpp msgid "Info" @@ -2663,7 +2820,7 @@ msgstr "Mostrar en el navegador de archivos" #: tools/editor/filesystem_dock.cpp msgid "Re-Import.." -msgstr "Reimportando.." +msgstr "Reimportando…" #: tools/editor/filesystem_dock.cpp msgid "Previous Directory" @@ -2999,11 +3156,11 @@ msgstr "Importar escena" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Importing Scene.." -msgstr "Importando escena.." +msgstr "Importando escena…" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Running Custom Script.." -msgstr "Ejecutando script personalizado.." +msgstr "Ejecutando script personalizado…" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Couldn't load post-import script:" @@ -3032,7 +3189,7 @@ msgstr "No se pudo encontrar la ruta: %s (ya es local)" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Saving.." -msgstr "Guardando.." +msgstr "Guardando…" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "3D Scene Animation" @@ -3276,10 +3433,6 @@ msgid "MultiNode Set" msgstr "Establecer multinodo" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "Nodo" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "Grupos" @@ -3597,7 +3750,7 @@ msgstr "Nodo de transición" #: tools/editor/plugins/animation_tree_editor_plugin.cpp msgid "Import Animations.." -msgstr "Importar animaciones.." +msgstr "Importar animaciones…" #: tools/editor/plugins/animation_tree_editor_plugin.cpp msgid "Edit Node Filters" @@ -3605,7 +3758,7 @@ msgstr "Editar filtros de nodo" #: tools/editor/plugins/animation_tree_editor_plugin.cpp msgid "Filters.." -msgstr "Filtros.." +msgstr "Filtros…" #: tools/editor/plugins/baked_light_baker.cpp msgid "Parsing %d Triangles:" @@ -3672,7 +3825,7 @@ msgstr "Vista previa" #: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Configure Snap" -msgstr "Configurar Snap" +msgstr "Ajustes de fijado" #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp @@ -3786,7 +3939,7 @@ msgstr "Restaurar la habilidad de seleccionar los hijos de un objeto." #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Use Snap" -msgstr "Usar Snap" +msgstr "Fijar a cuadrícula" #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp @@ -3795,20 +3948,20 @@ msgstr "Mostrar rejilla" #: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Rotation Snap" -msgstr "Usar Snap de Rotación" +msgstr "Fijar rotación" #: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap Relative" -msgstr "Usar Snap Relativo" +msgstr "Fijado relativo" #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Configure Snap.." -msgstr "Configurar Snap.." +msgstr "Configurar fijado…" #: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Pixel Snap" -msgstr "Usar Pixel Snap" +msgstr "Adherir a píxeles" #: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Expand to Parent" @@ -3816,7 +3969,7 @@ msgstr "Expandir al padre" #: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Skeleton.." -msgstr "Esqueleto.." +msgstr "Esqueleto…" #: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make Bones" @@ -3827,6 +3980,11 @@ msgid "Clear Bones" msgstr "Reestablecer huesos" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy +msgid "Show Bones" +msgstr "Crear huesos" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "Crear cadena IK" @@ -3845,7 +4003,7 @@ msgstr "Restablecer zoom" #: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Zoom Set.." -msgstr "Ajustar zoom..." +msgstr "Ajustar zoom…" #: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Center Selection" @@ -3885,7 +4043,7 @@ msgstr "Establecer valor" #: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap (Pixels):" -msgstr "Snap (Pixeles):" +msgstr "Fijar (Pixeles):" #: tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp #: tools/editor/plugins/light_occluder_2d_editor_plugin.cpp @@ -3942,7 +4100,7 @@ msgstr "Crear biblioteca de modelos 3D" #: tools/editor/plugins/cube_grid_theme_editor_plugin.cpp msgid "Thumbnail.." -msgstr "Miniatura.." +msgstr "Miniatura…" #: tools/editor/plugins/cube_grid_theme_editor_plugin.cpp msgid "Remove item %d?" @@ -4064,7 +4222,7 @@ msgstr "Crear colisión hermanada convexa" #: tools/editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Outline Mesh.." -msgstr "Crear modelo 3D de contorno.." +msgstr "Crear modelo 3D de contorno…" #: tools/editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Outline Mesh" @@ -4193,7 +4351,7 @@ msgstr "Error al cargar la imagen:" #: tools/editor/plugins/particles_2d_editor_plugin.cpp msgid "No pixels with transparency > 128 in image.." msgstr "" -"No hay píxeles que tengan menos de un 128/255 de transparencia en la imagen.." +"No hay píxeles que tengan menos de un 128/255 de transparencia en la imagen…" #: tools/editor/plugins/particles_2d_editor_plugin.cpp msgid "Set Emission Mask" @@ -4409,11 +4567,11 @@ msgstr "Limpiar UV" #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Snap" -msgstr "Esnapear" +msgstr "Adherir a cuadrícula" #: tools/editor/plugins/polygon_2d_editor_plugin.cpp msgid "Enable Snap" -msgstr "Activar Snap" +msgstr "Adherir a cuadrícula" #: tools/editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid" @@ -4520,7 +4678,7 @@ msgstr "Importar tema" #: tools/editor/plugins/script_editor_plugin.cpp msgid "Save Theme As.." -msgstr "Guardar tema como.." +msgstr "Guardar tema como…" #: tools/editor/plugins/script_editor_plugin.cpp msgid "Next script" @@ -4573,10 +4731,15 @@ msgid "Close Docs" msgstr "Cerrar documentación" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Cerrar" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." -msgstr "Buscar..." +msgstr "Buscar…" #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -4684,6 +4847,11 @@ msgstr "" "Los scripts integrados sólo se pueden editar cuando la escena a la que " "pertenecen está cargada" +#: tools/editor/plugins/script_text_editor.cpp +#, fuzzy +msgid "Pick Color" +msgstr "Color" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "Subir" @@ -4740,16 +4908,16 @@ msgstr "Buscar anterior" #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Replace.." -msgstr "Reemplazar..." +msgstr "Reemplazar…" #: tools/editor/plugins/script_text_editor.cpp msgid "Goto Function.." -msgstr "Ir a función..." +msgstr "Ir a función…" #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Goto Line.." -msgstr "Ir a línea.." +msgstr "Ir a línea…" #: tools/editor/plugins/script_text_editor.cpp msgid "Contextual Help" @@ -5062,6 +5230,11 @@ msgid "Insert Animation Key" msgstr "Insertar clave de animación" #: tools/editor/plugins/spatial_editor_plugin.cpp +#, fuzzy +msgid "Focus Origin" +msgstr "Ver origen" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "Seleccionar" @@ -5079,7 +5252,7 @@ msgstr "Coordenadas locales" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Transform Dialog.." -msgstr "Ventana de transformación.." +msgstr "Ventana de transformación…" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Use Default Light" @@ -5139,19 +5312,19 @@ msgstr "Ver rejilla" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Snap Settings" -msgstr "Ajustes de Snap" +msgstr "Ajustes de fijado" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Translate Snap:" -msgstr "Snap de Traslación:" +msgstr "Fijar desplazamiento:" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Rotate Snap (deg.):" -msgstr "Snap de Rotación (grados):" +msgstr "Fijar rotación (grados):" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Scale Snap (%):" -msgstr "Snap de Escala (%):" +msgstr "Fijar escala (%):" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Viewport Settings" @@ -5179,7 +5352,7 @@ msgstr "Profundidad máxima de vista:" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Transform Change" -msgstr "Cambio de transformación" +msgstr "Transformar" #: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Translate:" @@ -5271,7 +5444,7 @@ msgstr "Vista previa de StyleBox:" #: tools/editor/plugins/texture_region_editor_plugin.cpp msgid "Snap Mode:" -msgstr "Modo Snap:" +msgstr "Modo de fijado:" #: tools/editor/plugins/texture_region_editor_plugin.cpp msgid "<None>" @@ -5279,11 +5452,11 @@ msgstr "<Ninguno>" #: tools/editor/plugins/texture_region_editor_plugin.cpp msgid "Pixel Snap" -msgstr "Pixel Snap" +msgstr "Adherir a píxeles" #: tools/editor/plugins/texture_region_editor_plugin.cpp msgid "Grid Snap" -msgstr "Snap de Grilla" +msgstr "Adherir a cuadrícula" #: tools/editor/plugins/texture_region_editor_plugin.cpp msgid "Auto Slice" @@ -5327,6 +5500,11 @@ msgid "Remove Item" msgstr "Remover Item" #: tools/editor/plugins/theme_editor_plugin.cpp +#, fuzzy +msgid "Theme" +msgstr "Guardar tema" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "Añadir elementos de clase" @@ -5757,7 +5935,7 @@ msgstr "Exportar PCK del proyecto" #: tools/editor/project_export.cpp msgid "Export.." -msgstr "Exportar.." +msgstr "Exportar…" #: tools/editor/project_export.cpp msgid "Project Export" @@ -5931,7 +6109,7 @@ msgstr "Control+" #: tools/editor/project_settings.cpp tools/editor/settings_config_dialog.cpp msgid "Press a Key.." -msgstr "Presiona una tecla..." +msgstr "Presiona una tecla…" #: tools/editor/project_settings.cpp msgid "Mouse Button Index:" @@ -6047,7 +6225,7 @@ msgstr "Eliminar" #: tools/editor/project_settings.cpp msgid "Copy To Platform.." -msgstr "Copiar a plataforma.." +msgstr "Copiar a plataforma…" #: tools/editor/project_settings.cpp msgid "Input Map" @@ -6079,7 +6257,7 @@ msgstr "Traducciones:" #: tools/editor/project_settings.cpp msgid "Add.." -msgstr "Añadir..." +msgstr "Añadir…" #: tools/editor/project_settings.cpp msgid "Remaps" @@ -6107,7 +6285,7 @@ msgstr "Plugins" #: tools/editor/property_editor.cpp msgid "Preset.." -msgstr "Ajuste.." +msgstr "Ajuste…" #: tools/editor/property_editor.cpp msgid "Ease In" @@ -6131,11 +6309,11 @@ msgstr "Transición salida-entrada" #: tools/editor/property_editor.cpp msgid "File.." -msgstr "Archivo.." +msgstr "Archivo…" #: tools/editor/property_editor.cpp msgid "Dir.." -msgstr "Dir.." +msgstr "Dir…" #: tools/editor/property_editor.cpp msgid "Load" @@ -6146,6 +6324,11 @@ msgid "Assign" msgstr "Asignar" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "Script siguiente" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "Error al cargar el archivo: ¡No es un recurso!" @@ -6162,10 +6345,6 @@ msgid "On" msgstr "Activado" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "Establecer" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "Propiedades:" @@ -6322,7 +6501,7 @@ msgstr "Esta operación no puede realizarse en escenas instanciadas." #: tools/editor/scene_tree_dock.cpp msgid "Save New Scene As.." -msgstr "Guardar nueva escena como.." +msgstr "Guardar nueva escena como…" #: tools/editor/scene_tree_dock.cpp msgid "Makes Sense!" diff --git a/tools/translations/es_AR.po b/tools/translations/es_AR.po index 7a430aa695..6c266e74a7 100644 --- a/tools/translations/es_AR.po +++ b/tools/translations/es_AR.po @@ -3,14 +3,15 @@ # This file is distributed under the same license as the Godot source code. # # Lisandro Lorea <lisandrolorea@gmail.com>, 2016. +# Roger BR <drai_kin@hotmail.com>, 2016. # Sebastian Silva <sebastian@sugarlabs.org>, 2016. # msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2016-08-23 11:49+0000\n" -"Last-Translator: Sebastian Silva <sebastian@sugarlabs.org>\n" +"PO-Revision-Date: 2016-09-04 12:31+0000\n" +"Last-Translator: Roger BR <drai_kin@hotmail.com>\n" "Language-Team: Spanish (Argentina) <https://hosted.weblate.org/projects/" "godot-engine/godot/es_AR/>\n" "Language: es_AR\n" @@ -18,7 +19,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2.8-dev\n" +"X-Generator: Weblate 2.8\n" #: modules/gdscript/gd_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -36,6 +37,12 @@ msgid "step argument is zero!" msgstr "el argumento step es cero!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "No es un script con una instancia" @@ -168,37 +175,45 @@ msgid "Editing Signal:" msgstr "Editando Señal:" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "Cambiar Tipo" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Agregar Nodo" #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"Mantené pulsado Meta para depositar un Getter. Mantené pulsado Shift para " +"depositar una firma generica." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"Mantené pulsado Ctrl para depositar un Getter. Mantené pulsado Shift para " +"depositar una firma genérica." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a simple reference to the node." -msgstr "" +msgstr "Mantené pulsado Meta para depositar una referencia simple al nodo." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a simple reference to the node." -msgstr "" +msgstr "Mantené pulsado Ctrl para depositar una referencia simple al nodo." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a Variable Setter." -msgstr "" +msgstr "Mantené pulsado Meta para depositar un Variable Setter." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Variable Setter." -msgstr "" +msgstr "Mantené pulsado Ctrl para depositar un Variable Setter." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Preload Node" -msgstr "Agregar Nodo Hijo" +msgstr "Agregar Nodo Preload" #: modules/visual_script/visual_script_editor.cpp msgid "Add Node(s) From Tree" @@ -213,6 +228,47 @@ msgid "Add Setter Property" msgstr "Agregar Propiedad Setter" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "Copiar Animación" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Switch" +msgstr "Altura" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "Retornar:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "Llamar" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Get" +msgstr "Setear" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "Setear" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -272,24 +328,20 @@ msgid "Toggle Breakpoint" msgstr "Act/Desact. Breakpoint" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Find Node Type" msgstr "Encontrar Tipo de Nodo" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Copy Nodes" -msgstr "Copiar Pose" +msgstr "Copiar Nodo" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Cut Nodes" -msgstr "Crear Nodo" +msgstr "Cortar Nodos" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Paste Nodes" -msgstr "Pegar Pose" +msgstr "Pegar Nodos" #: modules/visual_script/visual_script_flow_control.cpp msgid "Input type not iterable: " @@ -349,6 +401,90 @@ msgstr "" "Valor de retorno inválido de _step(), debe ser un entero (seq out), o string " "(error)." +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Error creating the signature object." +msgstr "Error al escribir el PCK de proyecto!" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "Nombre inválido." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "Tamaño de tipografía inválido." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid publisher GUID." +msgstr "Ruta base inválida" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid background color." +msgstr "Origen personalizado de tipografía inválido." + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -534,6 +670,12 @@ msgstr "" "NavigationMeshInstance debe ser un hijo o nieto de un nodo Navigation. Solo " "provee datos de navegación." +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "" +"La propiedad Path debe apuntar a un nodo Particles2D valido para funcionar." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1185,10 +1327,6 @@ msgid "Method List For '%s':" msgstr "Lista de Métodos Para '%s':" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "Llamar" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "Lista de Métodos:" @@ -1307,6 +1445,12 @@ msgid "Method in target Node must be specified!" msgstr "El método en el Nodo objetivo debe ser especificado!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "Conectar a Nodo:" @@ -1382,6 +1526,15 @@ msgstr "Señales" msgid "Create New" msgstr "Crear Nuevo" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "Favoritos:" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "Recientes:" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1663,14 +1816,6 @@ msgstr "Subir Favorito" msgid "Move Favorite Down" msgstr "Bajar Favorito" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "Favoritos:" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "Recientes:" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "Vista Previa:" @@ -2081,14 +2226,6 @@ msgid "Go to previously opened scene." msgstr "Ir a la escena abierta previamente." #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "Modo Pantalla Completa" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "Modo Sin Distracciones" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "Pestaña siguiente" @@ -2134,7 +2271,7 @@ msgstr "Abrir Reciente" #: tools/editor/editor_node.cpp msgid "Quick Filter Files.." -msgstr "Filtrado Rapido de Archivos.." +msgstr "Filtrado Rápido de Archivos.." #: tools/editor/editor_node.cpp msgid "Convert To.." @@ -2174,6 +2311,10 @@ msgid "Quit to Project List" msgstr "Salir a Listado de Proyecto" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "Modo Sin Distracciones" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "Importar assets al proyecto." @@ -2265,7 +2406,7 @@ msgstr "" #: tools/editor/editor_node.cpp msgid "Small Deploy with Network FS" -msgstr "Depoy Pequeño con Network FS" +msgstr "Deploy Pequeño con Network FS" #: tools/editor/editor_node.cpp msgid "" @@ -2352,6 +2493,11 @@ msgid "Editor Layout" msgstr "Layout del Editor" #: tools/editor/editor_node.cpp +#, fuzzy +msgid "Toggle Fullscreen" +msgstr "Modo Pantalla Completa" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "Instalar Templates de Exportación" @@ -2376,6 +2522,10 @@ msgid "Update Changes" msgstr "Actualizar Cambios" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "Inspector" @@ -2415,6 +2565,10 @@ msgstr "Propiedades del objeto." msgid "FileSystem" msgstr "FileSystem" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "Nodo" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "Salida" @@ -2461,7 +2615,7 @@ msgstr "Abrir y Correr un Script" #: tools/editor/editor_node.cpp msgid "Load Errors" -msgstr "Cargar Errores" +msgstr "Erroes de carga" #: tools/editor/editor_plugin_settings.cpp msgid "Installed Plugins:" @@ -3255,10 +3409,6 @@ msgid "MultiNode Set" msgstr "Setear MultiNodo" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "Nodo" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "Grupos" @@ -3805,6 +3955,11 @@ msgid "Clear Bones" msgstr "Reestablecer Huesos" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy +msgid "Show Bones" +msgstr "Crear Huesos" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "Crear Cadena IK" @@ -4544,6 +4699,11 @@ msgid "Close Docs" msgstr "Cerrar Docs" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Cerrar" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4655,6 +4815,11 @@ msgstr "" "Los scripts built-in solo pueden ser editados cuando la escena a la que " "pertenecen esta cargada" +#: tools/editor/plugins/script_text_editor.cpp +#, fuzzy +msgid "Pick Color" +msgstr "Color" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "Subir" @@ -5031,6 +5196,11 @@ msgid "Insert Animation Key" msgstr "Insertar Clave de Animación" #: tools/editor/plugins/spatial_editor_plugin.cpp +#, fuzzy +msgid "Focus Origin" +msgstr "Ver Origen" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "Foco en Selección" @@ -5296,6 +5466,11 @@ msgid "Remove Item" msgstr "Remover Item" #: tools/editor/plugins/theme_editor_plugin.cpp +#, fuzzy +msgid "Theme" +msgstr "Guardar Tema" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "Agregar Items de Clases" @@ -6115,6 +6290,11 @@ msgid "Assign" msgstr "Asignar" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "Script siguiente" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "Error al cargar el archivo: No es un recurso!" @@ -6131,10 +6311,6 @@ msgid "On" msgstr "On" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "Setear" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "Propiedades:" @@ -6147,14 +6323,12 @@ msgid "Sections:" msgstr "Selecciones:" #: tools/editor/property_selector.cpp -#, fuzzy msgid "Select Property" -msgstr "Seleccionar Puntos" +msgstr "Seleccionar Propiedad" #: tools/editor/property_selector.cpp -#, fuzzy msgid "Select Method" -msgstr "Seleccionar Modo" +msgstr "Seleccionar Método" #: tools/editor/pvrtc_compress.cpp msgid "Could not execute PVRTC tool:" diff --git a/tools/translations/extract.py b/tools/translations/extract.py index 97bb7494a7..61b07b5799 100755 --- a/tools/translations/extract.py +++ b/tools/translations/extract.py @@ -107,6 +107,7 @@ f.write(main_po) f.close() if (os.name == "posix"): + print("Wrapping template at 79 characters for compatibility with Weblate.") os.system("msgmerge -w79 tools.pot tools.pot > tools.pot.wrap") shutil.move("tools.pot.wrap", "tools.pot") diff --git a/tools/translations/fa.po b/tools/translations/fa.po index dcc29135af..290c4a6309 100644 --- a/tools/translations/fa.po +++ b/tools/translations/fa.po @@ -38,6 +38,12 @@ msgid "step argument is zero!" msgstr "آرگومان step صفر است!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp #, fuzzy msgid "Not a script with an instance" msgstr "اسکریپتی با یک نمونه نیست ." @@ -171,6 +177,11 @@ msgid "Editing Signal:" msgstr "ویرایش سیگنال:" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "انتقال را در انیمیشن تغییر بده" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "افزودن گره" @@ -216,6 +227,45 @@ msgid "Add Setter Property" msgstr "دارایی Setter را اضافه کن" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "انتقال" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "بازگشت:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "فراخوانی" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -351,6 +401,87 @@ msgstr "" "مقدار بازگشتی نامعتبر از ()step_ ، باید integer (seq out) ، یا string " "(error) باشد." +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "نام نامعتبر." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "اندازهی قلم نامعتبر." + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -538,6 +669,11 @@ msgstr "" "NavigationMeshInstance باید یک فرزند یا نوهی یک گره Navigation باشد. این " "تنها دادهی پیمایش را فراهم میکند." +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "دارایی Path باید به یک گره Particles2D معتبر اشاره کند تا کار کند." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1190,10 +1326,6 @@ msgid "Method List For '%s':" msgstr "لیست متد برای 's%' :" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "فراخوانی" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "فهرست متدها:" @@ -1312,6 +1444,12 @@ msgid "Method in target Node must be specified!" msgstr "متد در گره مقصد باید مشخص شده باشد!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "اتصال به گره:" @@ -1388,6 +1526,15 @@ msgstr "سیگنالها" msgid "Create New" msgstr "جدید ایجاد کن" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1666,14 +1813,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -2068,14 +2207,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "حالت تمام صفحه" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "زبانه بعدی" @@ -2161,6 +2292,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2319,6 +2454,11 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +#, fuzzy +msgid "Toggle Fullscreen" +msgstr "حالت تمام صفحه" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2343,6 +2483,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2382,6 +2526,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "خروجی" @@ -3213,10 +3361,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3756,6 +3900,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4494,6 +4642,11 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "بستن" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4601,6 +4754,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4977,6 +5134,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5242,6 +5403,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -6055,6 +6220,11 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "صحنه جدید" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -6071,10 +6241,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/fr.po b/tools/translations/fr.po index 354934fefa..94d43d12ba 100644 --- a/tools/translations/fr.po +++ b/tools/translations/fr.po @@ -17,7 +17,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2016-08-29 13:56+0000\n" +"PO-Revision-Date: 2016-09-03 09:11+0000\n" "Last-Translator: Thomas Baijot <thomasbaijot@gmail.com>\n" "Language-Team: French <https://hosted.weblate.org/projects/godot-engine/" "godot/fr/>\n" @@ -26,7 +26,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 2.8-dev\n" +"X-Generator: Weblate 2.8\n" #: modules/gdscript/gd_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -43,6 +43,12 @@ msgid "step argument is zero!" msgstr "L'argument du pas est zéro!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "N'est pas un script avec une instance" @@ -106,11 +112,11 @@ msgstr "" #: modules/visual_script/visual_script_editor.cpp msgid "Functions:" -msgstr "Fonction :" +msgstr "Fonctions :" #: modules/visual_script/visual_script_editor.cpp msgid "Variables:" -msgstr "Variables:" +msgstr "Variables :" #: modules/visual_script/visual_script_editor.cpp tools/editor/editor_help.cpp msgid "Signals:" @@ -172,6 +178,11 @@ msgid "Editing Signal:" msgstr "Connecter un signal :" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "Changer le type" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Ajouter un nœud" @@ -217,6 +228,47 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "Copier l'animation" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Switch" +msgstr "Hauteur" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "Retourne :" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "Appel" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Get" +msgstr "Définir" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "Définir" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -322,7 +374,7 @@ msgstr "Le chemin ne mène pas au nœud !" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Invalid index property name '%s' in node %s." -msgstr "" +msgstr "Nom de propriété invalide '%s' dans le nœud %s." #: modules/visual_script/visual_script_nodes.cpp #, fuzzy @@ -331,15 +383,15 @@ msgstr "Nom de classe parent invalide" #: modules/visual_script/visual_script_nodes.cpp msgid ": Invalid arguments: " -msgstr ": Arguments invalides " +msgstr ": Arguments invalides: " #: modules/visual_script/visual_script_nodes.cpp msgid "VariableGet not found in script: " -msgstr "" +msgstr "VariableGet introuvable dans le script: " #: modules/visual_script/visual_script_nodes.cpp msgid "VariableSet not found in script: " -msgstr "" +msgstr "VariableSet introuvable dans le script: " #: modules/visual_script/visual_script_nodes.cpp msgid "Custom node has no _step() method, can't process graph." @@ -351,6 +403,90 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Error creating the signature object." +msgstr "Erreur d'écriture du PCK du projet !" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "Nom invalide." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "Taille de police invalide." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid publisher GUID." +msgstr "Chemin de base invalide" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid background color." +msgstr "Source personnalisée de police invalide." + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -542,6 +678,13 @@ msgstr "" "Un NavigationMeshInstance doit être enfant ou sous-enfant d'un nœud de type " "Navigation. Il fournit uniquement des données de navigation." +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "" +"La propriété Path doit pointer à un nœud de type Particles2D valide pour " +"fonctionner." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -997,7 +1140,7 @@ msgstr "Animation Inserer une clé" #: tools/editor/animation_editor.cpp msgid "Change Anim Len" -msgstr "Changer la longueur de l'animation" +msgstr "Modifier la longueur de l'animation" #: tools/editor/animation_editor.cpp msgid "Change Anim Loop" @@ -1193,10 +1336,6 @@ msgid "Method List For '%s':" msgstr "Liste des méthodes pour « %s » :" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "Appel" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "Liste des méthodes :" @@ -1315,6 +1454,12 @@ msgid "Method in target Node must be specified!" msgstr "La méthode du nœud cible doit être spécifiée !" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "Connecter au nœud :" @@ -1390,6 +1535,15 @@ msgstr "Signaux" msgid "Create New" msgstr "Créer un nouveau" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "Favoris :" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "Récents :" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1637,7 +1791,7 @@ msgstr "Choisir" #: tools/editor/editor_file_dialog.cpp msgid "Go Back" -msgstr "Revenir" +msgstr "Retour" #: tools/editor/editor_file_dialog.cpp msgid "Go Forward" @@ -1676,14 +1830,6 @@ msgstr "Déplacer le favori vers le haut" msgid "Move Favorite Down" msgstr "Déplacer le favori vers le bas" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "Favoris :" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "Récents :" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "Aperçu :" @@ -2099,14 +2245,6 @@ msgid "Go to previously opened scene." msgstr "Aller à la scène ouverte précédemment." #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "Mode plein écran" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "Mode sans distraction" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "Onglet suivant" @@ -2192,6 +2330,10 @@ msgid "Quit to Project List" msgstr "Quitter vers la liste des projets" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "Mode sans distraction" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "Importer des ressources dans le projet." @@ -2377,6 +2519,11 @@ msgid "Editor Layout" msgstr "Disposition de l'éditeur" #: tools/editor/editor_node.cpp +#, fuzzy +msgid "Toggle Fullscreen" +msgstr "Mode plein écran" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "Installer les modèles d'exportation" @@ -2401,6 +2548,10 @@ msgid "Update Changes" msgstr "Repeindre quand modifié" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "Inspecteur" @@ -2440,6 +2591,10 @@ msgstr "Propriétés de l'objet." msgid "FileSystem" msgstr "Système de fichiers" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "Nœud" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "Sortie" @@ -3288,10 +3443,6 @@ msgid "MultiNode Set" msgstr "Réglage multi-nœuds" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "Nœud" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "Groupes" @@ -3849,6 +4000,11 @@ msgid "Clear Bones" msgstr "Effacer les os" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy +msgid "Show Bones" +msgstr "Créer les os" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "Créer une chaîne IK" @@ -4598,6 +4754,11 @@ msgid "Close Docs" msgstr "Cloner en dessous" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Fermer" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4709,6 +4870,11 @@ msgstr "" "Les scripts intégrés ne peuvent être modifiés uniquement lorsque la scène à " "qui ils appartiennent est ouverte" +#: tools/editor/plugins/script_text_editor.cpp +#, fuzzy +msgid "Pick Color" +msgstr "Couleur" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "Déplacer vers le haut" @@ -5093,6 +5259,11 @@ msgstr "Coller l'animation" #: tools/editor/plugins/spatial_editor_plugin.cpp #, fuzzy +msgid "Focus Origin" +msgstr "Afficher l'origine" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +#, fuzzy msgid "Focus Selection" msgstr "Mettre à l'échelle la sélection" @@ -5366,6 +5537,11 @@ msgid "Remove Item" msgstr "Supprimer l'item" #: tools/editor/plugins/theme_editor_plugin.cpp +#, fuzzy +msgid "Theme" +msgstr "Enregistrer le thème" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "Ajouter des items de classe" @@ -6192,6 +6368,11 @@ msgid "Assign" msgstr "Assigner" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "Créer un script" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "Erreur de chargement du fichier : ce n'est pas une ressource !" @@ -6208,10 +6389,6 @@ msgid "On" msgstr "Activé" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "Définir" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "Propriétés :" diff --git a/tools/translations/id.po b/tools/translations/id.po index 0478612745..3f2ef7861f 100644 --- a/tools/translations/id.po +++ b/tools/translations/id.po @@ -36,6 +36,12 @@ msgid "step argument is zero!" msgstr "Langkah argumen adalah nol!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp #, fuzzy msgid "Not a script with an instance" msgstr "Skrip tidak mempunyai turunannya" @@ -167,6 +173,11 @@ msgid "Editing Signal:" msgstr "Mengedit Sinyal:" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "Ubah Transisi Anim" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Tambahkan Node" @@ -212,6 +223,45 @@ msgid "Add Setter Property" msgstr "Tambahkan Properti Setter" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "Transisi" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "Kembali:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "Panggil" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -346,6 +396,87 @@ msgstr "" "Nilai kembali dari _step() tidak sah, seharusnya integer (seq out), atau " "string (error)." +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "Nama tidak sah." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "Ukuran font tidak sah." + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -541,6 +672,13 @@ msgstr "" "NavigationMeshInstance harus menjadi child atau grandchild untuk sebuah node " "Navigation. Ini hanya menyediakan data navigasi." +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "" +"Properti path harus menunjuk ke sebuah node Particles2D yang sah agar " +"bekerja." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1214,10 +1352,6 @@ msgid "Method List For '%s':" msgstr "Daftar Fungsi Untuk '%s':" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "Panggil" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "Daftar Fungsi:" @@ -1341,6 +1475,12 @@ msgid "Method in target Node must be specified!" msgstr "Method dalam Node target harus spesifik!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "Sambungkan Ke Node:" @@ -1416,6 +1556,15 @@ msgstr "Sinyal-sinyal" msgid "Create New" msgstr "Buat Baru" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "Favorit:" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "Saat ini:" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1705,14 +1854,6 @@ msgstr "Pindahkan Favorit Keatas" msgid "Move Favorite Down" msgstr "Pindahkan Favorit Kebawah" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "Favorit:" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "Saat ini:" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "Pratinjau:" @@ -2126,14 +2267,6 @@ msgid "Go to previously opened scene." msgstr "Pergi ke scene yang dibuka sebelumnya." #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "Mode Layar Penuh" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "Mode Tanpa Gangguan" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "Tab selanjutnya" @@ -2219,6 +2352,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "Mode Tanpa Gangguan" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2377,6 +2514,11 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +#, fuzzy +msgid "Toggle Fullscreen" +msgstr "Mode Layar Penuh" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2401,6 +2543,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2440,6 +2586,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3269,10 +3419,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3812,6 +3958,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4550,6 +4700,11 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Tutup" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4657,6 +4812,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -5033,6 +5192,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5298,6 +5461,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -6109,6 +6276,11 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "Scene Baru" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -6125,10 +6297,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/is.po b/tools/translations/is.po new file mode 100644 index 0000000000..2a2abb8df4 --- /dev/null +++ b/tools/translations/is.po @@ -0,0 +1,6667 @@ +# LANGUAGE translation of the Godot Engine editor +# Copyright (C) 2016 Juan Linietsky, Ariel Manzur and the Godot community +# This file is distributed under the same license as the Godot source code. +# +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Godot Engine editor\n" +"Language: is\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8-bit\n" + +#: modules/gdscript/gd_functions.cpp +#: modules/visual_script/visual_script_builtin_funcs.cpp +msgid "Invalid type argument to convert(), use TYPE_* constants." +msgstr "" + +#: modules/gdscript/gd_functions.cpp +#: modules/visual_script/visual_script_builtin_funcs.cpp +msgid "Not enough bytes for decoding bytes, or invalid format." +msgstr "" + +#: modules/gdscript/gd_functions.cpp +msgid "step argument is zero!" +msgstr "" + +#: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp +msgid "Not a script with an instance" +msgstr "" + +#: modules/gdscript/gd_functions.cpp +msgid "Not based on a script" +msgstr "" + +#: modules/gdscript/gd_functions.cpp +msgid "Not based on a resource file" +msgstr "" + +#: modules/gdscript/gd_functions.cpp +msgid "Invalid instance dictionary format (missing @path)" +msgstr "" + +#: modules/gdscript/gd_functions.cpp +msgid "Invalid instance dictionary format (can't load script at @path)" +msgstr "" + +#: modules/gdscript/gd_functions.cpp +msgid "Invalid instance dictionary format (invalid script at @path)" +msgstr "" + +#: modules/gdscript/gd_functions.cpp +msgid "Invalid instance dictionary (invalid subclasses)" +msgstr "" + +#: modules/visual_script/visual_script.cpp +msgid "" +"A node yielded without working memory, please read the docs on how to yield " +"properly!" +msgstr "" + +#: modules/visual_script/visual_script.cpp +msgid "" +"Node yielded, but did not return a function state in the first working " +"memory." +msgstr "" + +#: modules/visual_script/visual_script.cpp +msgid "" +"Return value must be assigned to first element of node working memory! Fix " +"your node please." +msgstr "" + +#: modules/visual_script/visual_script.cpp +msgid "Node returned an invalid sequence output: " +msgstr "" + +#: modules/visual_script/visual_script.cpp +msgid "Found sequence bit but not the node in the stack, report bug!" +msgstr "" + +#: modules/visual_script/visual_script.cpp +msgid "Stack overflow with stack depth: " +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Functions:" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Variables:" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/editor_help.cpp +msgid "Signals:" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Name is not a valid identifier:" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Name already in use by another func/var/signal:" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Rename Function" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Rename Variable" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Rename Signal" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Add Function" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Add Variable" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Add Signal" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Remove Function" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Remove Variable" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Editing Variable:" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Remove Signal" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Editing Signal:" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Change Expression" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Add Node" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature." +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature." +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Hold Meta to drop a simple reference to the node." +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Hold Ctrl to drop a simple reference to the node." +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Hold Meta to drop a Variable Setter." +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Hold Ctrl to drop a Variable Setter." +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Add Preload Node" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Add Node(s) From Tree" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Add Getter Property" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Add Setter Property" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Condition" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +#: tools/editor/plugins/script_text_editor.cpp +#: tools/editor/plugins/shader_editor_plugin.cpp +#: tools/editor/project_manager.cpp +msgid "Edit" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Base Type:" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/editor_help.cpp +msgid "Members:" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Available Nodes:" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Select or create a function to edit graph" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +#: tools/editor/connections_dialog.cpp +#: tools/editor/plugins/animation_player_editor_plugin.cpp +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +#: tools/editor/plugins/resource_preloader_editor_plugin.cpp +#: tools/editor/plugins/sample_library_editor_plugin.cpp +#: tools/editor/plugins/script_editor_plugin.cpp +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +#: tools/editor/project_settings.cpp tools/editor/property_editor.cpp +#: tools/editor/run_settings_dialog.cpp tools/editor/settings_config_dialog.cpp +msgid "Close" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Edit Signal Arguments:" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Edit Variable:" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Change" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Delete Selected" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/plugins/script_text_editor.cpp +msgid "Toggle Breakpoint" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Find Node Type" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Copy Nodes" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Cut Nodes" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Paste Nodes" +msgstr "" + +#: modules/visual_script/visual_script_flow_control.cpp +msgid "Input type not iterable: " +msgstr "" + +#: modules/visual_script/visual_script_flow_control.cpp +msgid "Iterator became invalid" +msgstr "" + +#: modules/visual_script/visual_script_flow_control.cpp +msgid "Iterator became invalid: " +msgstr "" + +#: modules/visual_script/visual_script_func_nodes.cpp +msgid "Invalid index property name." +msgstr "" + +#: modules/visual_script/visual_script_func_nodes.cpp +msgid "Base object is not a Node!" +msgstr "" + +#: modules/visual_script/visual_script_func_nodes.cpp +msgid "Path does not lead Node!" +msgstr "" + +#: modules/visual_script/visual_script_func_nodes.cpp +msgid "Invalid index property name '%s' in node %s." +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid ": Invalid argument of type: " +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid ": Invalid arguments: " +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "VariableGet not found in script: " +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "VariableSet not found in script: " +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "Custom node has no _step() method, can't process graph." +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "" +"Invalid return value from _step(), must be integer (seq out), or string " +"(error)." +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid unique name." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid product GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + +#: scene/2d/animated_sprite.cpp +msgid "" +"A SpriteFrames resource must be created or set in the 'Frames' property in " +"order for AnimatedSprite to display frames." +msgstr "" + +#: scene/2d/canvas_modulate.cpp +msgid "" +"Only one visible CanvasModulate is allowed per scene (or set of instanced " +"scenes). The first created one will work, while the rest will be ignored." +msgstr "" + +#: scene/2d/collision_polygon_2d.cpp +msgid "" +"CollisionPolygon2D only serves to provide a collision shape to a " +"CollisionObject2D derived node. Please only use it as a child of Area2D, " +"StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape." +msgstr "" + +#: scene/2d/collision_polygon_2d.cpp +msgid "An empty CollisionPolygon2D has no effect on collision." +msgstr "" + +#: scene/2d/collision_shape_2d.cpp +msgid "" +"CollisionShape2D only serves to provide a collision shape to a " +"CollisionObject2D derived node. Please only use it as a child of Area2D, " +"StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape." +msgstr "" + +#: scene/2d/collision_shape_2d.cpp +msgid "" +"A shape must be provided for CollisionShape2D to function. Please create a " +"shape resource for it!" +msgstr "" + +#: scene/2d/light_2d.cpp +msgid "" +"A texture with the shape of the light must be supplied to the 'texture' " +"property." +msgstr "" + +#: scene/2d/light_occluder_2d.cpp +msgid "" +"An occluder polygon must be set (or drawn) for this occluder to take effect." +msgstr "" + +#: scene/2d/light_occluder_2d.cpp +msgid "The occluder polygon for this occluder is empty. Please draw a polygon!" +msgstr "" + +#: scene/2d/navigation_polygon.cpp +msgid "" +"A NavigationPolygon resource must be set or created for this node to work. " +"Please set a property or draw a polygon." +msgstr "" + +#: scene/2d/navigation_polygon.cpp +msgid "" +"NavigationPolygonInstance must be a child or grandchild to a Navigation2D " +"node. It only provides navigation data." +msgstr "" + +#: scene/2d/parallax_layer.cpp +msgid "" +"ParallaxLayer node only works when set as child of a ParallaxBackground node." +msgstr "" + +#: scene/2d/particles_2d.cpp +msgid "Path property must point to a valid Particles2D node to work." +msgstr "" + +#: scene/2d/path_2d.cpp +msgid "PathFollow2D only works when set as a child of a Path2D node." +msgstr "" + +#: scene/2d/remote_transform_2d.cpp +msgid "Path property must point to a valid Node2D node to work." +msgstr "" + +#: scene/2d/sample_player_2d.cpp scene/audio/sample_player.cpp +msgid "" +"A SampleLibrary resource must be created or set in the 'samples' property in " +"order for SamplePlayer to play sound." +msgstr "" + +#: scene/2d/sprite.cpp +msgid "" +"Path property must point to a valid Viewport node to work. Such Viewport " +"must be set to 'render target' mode." +msgstr "" + +#: scene/2d/sprite.cpp +msgid "" +"The Viewport set in the path property must be set as 'render target' in " +"order for this sprite to work." +msgstr "" + +#: scene/2d/visibility_notifier_2d.cpp +msgid "" +"VisibilityEnable2D works best when used with the edited scene root directly " +"as parent." +msgstr "" + +#: scene/3d/baked_light_instance.cpp +msgid "BakedLightInstance does not contain a BakedLight resource." +msgstr "" + +#: scene/3d/body_shape.cpp +msgid "" +"CollisionShape only serves to provide a collision shape to a CollisionObject " +"derived node. Please only use it as a child of Area, StaticBody, RigidBody, " +"KinematicBody, etc. to give them a shape." +msgstr "" + +#: scene/3d/body_shape.cpp +msgid "" +"A shape must be provided for CollisionShape to function. Please create a " +"shape resource for it!" +msgstr "" + +#: scene/3d/collision_polygon.cpp +msgid "" +"CollisionPolygon only serves to provide a collision shape to a " +"CollisionObject derived node. Please only use it as a child of Area, " +"StaticBody, RigidBody, KinematicBody, etc. to give them a shape." +msgstr "" + +#: scene/3d/collision_polygon.cpp +msgid "An empty CollisionPolygon has no effect on collision." +msgstr "" + +#: scene/3d/navigation_mesh.cpp +msgid "A NavigationMesh resource must be set or created for this node to work." +msgstr "" + +#: scene/3d/navigation_mesh.cpp +msgid "" +"NavigationMeshInstance must be a child or grandchild to a Navigation node. " +"It only provides navigation data." +msgstr "" + +#: scene/3d/remote_transform.cpp +msgid "Path property must point to a valid Spatial node to work." +msgstr "" + +#: scene/3d/scenario_fx.cpp +msgid "" +"Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." +msgstr "" + +#: scene/3d/spatial_sample_player.cpp +msgid "" +"A SampleLibrary resource must be created or set in the 'samples' property in " +"order for SpatialSamplePlayer to play sound." +msgstr "" + +#: scene/3d/sprite_3d.cpp +msgid "" +"A SpriteFrames resource must be created or set in the 'Frames' property in " +"order for AnimatedSprite3D to display frames." +msgstr "" + +#: scene/gui/dialogs.cpp tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Cancel" +msgstr "" + +#: scene/gui/dialogs.cpp tools/editor/scene_tree_dock.cpp +msgid "OK" +msgstr "" + +#: scene/gui/dialogs.cpp +msgid "Alert!" +msgstr "" + +#: scene/gui/dialogs.cpp +msgid "Please Confirm..." +msgstr "" + +#: scene/gui/file_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "File Exists, Overwrite?" +msgstr "" + +#: scene/gui/file_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "All Recognized" +msgstr "" + +#: scene/gui/file_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "All Files (*)" +msgstr "" + +#: scene/gui/file_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/editor_help.cpp tools/editor/editor_node.cpp +#: tools/editor/filesystem_dock.cpp +#: tools/editor/plugins/script_editor_plugin.cpp +#: tools/editor/property_selector.cpp tools/editor/quick_open.cpp +msgid "Open" +msgstr "" + +#: scene/gui/file_dialog.cpp +msgid "Open a File" +msgstr "" + +#: scene/gui/file_dialog.cpp +msgid "Open File(s)" +msgstr "" + +#: scene/gui/file_dialog.cpp +msgid "Open a Directory" +msgstr "" + +#: scene/gui/file_dialog.cpp +msgid "Open a File or Directory" +msgstr "" + +#: scene/gui/file_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/editor_node.cpp +#: tools/editor/plugins/animation_player_editor_plugin.cpp +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Save" +msgstr "" + +#: scene/gui/file_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Save a File" +msgstr "" + +#: scene/gui/file_dialog.cpp tools/editor/editor_dir_dialog.cpp +#: tools/editor/editor_file_dialog.cpp +msgid "Create Folder" +msgstr "" + +#: scene/gui/file_dialog.cpp tools/editor/editor_autoload_settings.cpp +#: tools/editor/editor_file_dialog.cpp +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +#: tools/editor/script_create_dialog.cpp +msgid "Path:" +msgstr "" + +#: scene/gui/file_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Directories & Files:" +msgstr "" + +#: scene/gui/file_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/script_editor_debugger.cpp +msgid "File:" +msgstr "" + +#: scene/gui/file_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Filter:" +msgstr "" + +#: scene/gui/file_dialog.cpp tools/editor/editor_dir_dialog.cpp +#: tools/editor/editor_file_dialog.cpp tools/editor/editor_plugin_settings.cpp +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Name:" +msgstr "" + +#: scene/gui/file_dialog.cpp tools/editor/editor_dir_dialog.cpp +#: tools/editor/editor_file_dialog.cpp +msgid "Could not create folder." +msgstr "" + +#: scene/gui/file_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Must use a valid extension." +msgstr "" + +#: scene/gui/input_action.cpp tools/editor/project_settings.cpp +#: tools/editor/settings_config_dialog.cpp +msgid "Shift+" +msgstr "" + +#: scene/gui/input_action.cpp tools/editor/project_settings.cpp +#: tools/editor/settings_config_dialog.cpp +msgid "Alt+" +msgstr "" + +#: scene/gui/input_action.cpp +msgid "Ctrl+" +msgstr "" + +#: scene/gui/input_action.cpp tools/editor/project_settings.cpp +#: tools/editor/settings_config_dialog.cpp +msgid "Meta+" +msgstr "" + +#: scene/gui/input_action.cpp tools/editor/project_settings.cpp +msgid "Device" +msgstr "" + +#: scene/gui/input_action.cpp tools/editor/project_settings.cpp +msgid "Button" +msgstr "" + +#: scene/gui/input_action.cpp tools/editor/project_settings.cpp +msgid "Left Button." +msgstr "" + +#: scene/gui/input_action.cpp tools/editor/project_settings.cpp +msgid "Right Button." +msgstr "" + +#: scene/gui/input_action.cpp tools/editor/project_settings.cpp +msgid "Middle Button." +msgstr "" + +#: scene/gui/input_action.cpp tools/editor/project_settings.cpp +msgid "Wheel Up." +msgstr "" + +#: scene/gui/input_action.cpp tools/editor/project_settings.cpp +msgid "Wheel Down." +msgstr "" + +#: scene/gui/input_action.cpp tools/editor/project_settings.cpp +msgid "Axis" +msgstr "" + +#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp +#: tools/editor/plugins/script_text_editor.cpp +#: tools/editor/plugins/shader_editor_plugin.cpp +msgid "Cut" +msgstr "" + +#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp +#: tools/editor/plugins/script_text_editor.cpp +#: tools/editor/plugins/shader_editor_plugin.cpp +#: tools/editor/property_editor.cpp tools/editor/resources_dock.cpp +msgid "Copy" +msgstr "" + +#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp +#: tools/editor/plugins/resource_preloader_editor_plugin.cpp +#: tools/editor/plugins/script_text_editor.cpp +#: tools/editor/plugins/shader_editor_plugin.cpp +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +#: tools/editor/property_editor.cpp tools/editor/resources_dock.cpp +msgid "Paste" +msgstr "" + +#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp +#: tools/editor/plugins/script_text_editor.cpp +#: tools/editor/plugins/shader_editor_plugin.cpp +#: tools/editor/project_export.cpp +msgid "Select All" +msgstr "" + +#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp tools/editor/editor_log.cpp +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +#: tools/editor/plugins/rich_text_editor_plugin.cpp +#: tools/editor/property_editor.cpp tools/editor/script_editor_debugger.cpp +msgid "Clear" +msgstr "" + +#: scene/gui/line_edit.cpp scene/gui/text_edit.cpp tools/editor/editor_node.cpp +#: tools/editor/plugins/script_text_editor.cpp +#: tools/editor/plugins/shader_editor_plugin.cpp +msgid "Undo" +msgstr "" + +#: scene/gui/popup.cpp +msgid "" +"Popups will hide by default unless you call popup() or any of the popup*() " +"functions. Making them visible for editing is fine though, but they will " +"hide upon running." +msgstr "" + +#: scene/main/viewport.cpp +msgid "" +"This viewport is not set as render target. If you intend for it to display " +"its contents directly to the screen, make it a child of a Control so it can " +"obtain a size. Otherwise, make it a RenderTarget and assign its internal " +"texture to some node for display." +msgstr "" + +#: scene/resources/dynamic_font.cpp +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "Error initializing FreeType." +msgstr "" + +#: scene/resources/dynamic_font.cpp +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "Unknown font format." +msgstr "" + +#: scene/resources/dynamic_font.cpp +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "Error loading font." +msgstr "" + +#: scene/resources/dynamic_font.cpp +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "Invalid font size." +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Disabled" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "All Selection" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Move Add Key" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Change Transition" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Change Transform" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Change Value" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Change Call" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Add Track" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Duplicate Keys" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Move Anim Track Up" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Move Anim Track Down" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Remove Anim Track" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Set Transitions to:" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Track Rename" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Track Change Interpolation" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Track Change Value Mode" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Edit Node Curve" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Edit Selection Curve" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Delete Keys" +msgstr "" + +#: tools/editor/animation_editor.cpp +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Duplicate Selection" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Duplicate Transposed" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Remove Selection" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Continuous" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Discrete" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Trigger" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Add Key" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Move Keys" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Scale Selection" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Scale From Cursor" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Goto Next Step" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Goto Prev Step" +msgstr "" + +#: tools/editor/animation_editor.cpp tools/editor/property_editor.cpp +msgid "Linear" +msgstr "" + +#: tools/editor/animation_editor.cpp +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Constant" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "In" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Out" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "In-Out" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Out-In" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Transitions" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Optimize Animation" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Clean-Up Animation" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Create NEW track for %s and insert key?" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Create %d NEW tracks and insert keys?" +msgstr "" + +#: tools/editor/animation_editor.cpp tools/editor/create_dialog.cpp +#: tools/editor/plugins/light_occluder_2d_editor_plugin.cpp +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +#: tools/editor/plugins/navigation_polygon_editor_plugin.cpp +#: tools/editor/plugins/particles_editor_plugin.cpp +#: tools/editor/project_manager.cpp tools/editor/script_create_dialog.cpp +msgid "Create" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Create & Insert" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Insert Track & Key" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Insert Key" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Change Anim Len" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Change Anim Loop" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Create Typed Value Key" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Insert" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Scale Keys" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim Add Call Track" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Animation zoom." +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Length (s):" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Animation length (in seconds)." +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Step (s):" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Cursor step snap (in seconds)." +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Enable/Disable looping in animation." +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Add new tracks." +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Move current track up." +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Move current track down." +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Remove selected track." +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Track tools" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Enable editing of individual keys by clicking them." +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Anim. Optimizer" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Max. Linear Error:" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Max. Angular Error:" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Max Optimizable Angle:" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Optimize" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Select an AnimationPlayer from the Scene Tree to edit animations." +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Key" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Transition" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Scale Ratio:" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Call Functions in Which Node?" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Remove invalid keys" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Remove unresolved and empty tracks" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Clean-up all animations" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Clean-Up Animation(s) (NO UNDO!)" +msgstr "" + +#: tools/editor/animation_editor.cpp +msgid "Clean-Up" +msgstr "" + +#: tools/editor/array_property_edit.cpp +msgid "Resize Array" +msgstr "" + +#: tools/editor/array_property_edit.cpp +msgid "Change Array Value Type" +msgstr "" + +#: tools/editor/array_property_edit.cpp +msgid "Change Array Value" +msgstr "" + +#: tools/editor/asset_library_editor_plugin.cpp tools/editor/create_dialog.cpp +#: tools/editor/editor_help.cpp tools/editor/editor_node.cpp +#: tools/editor/plugins/script_editor_plugin.cpp +#: tools/editor/property_selector.cpp tools/editor/quick_open.cpp +#: tools/editor/settings_config_dialog.cpp +msgid "Search:" +msgstr "" + +#: tools/editor/asset_library_editor_plugin.cpp +msgid "Sort:" +msgstr "" + +#: tools/editor/asset_library_editor_plugin.cpp +msgid "Reverse" +msgstr "" + +#: tools/editor/asset_library_editor_plugin.cpp +#: tools/editor/project_settings.cpp +msgid "Category:" +msgstr "" + +#: tools/editor/asset_library_editor_plugin.cpp +msgid "All" +msgstr "" + +#: tools/editor/asset_library_editor_plugin.cpp +msgid "Site:" +msgstr "" + +#: tools/editor/asset_library_editor_plugin.cpp +msgid "Support.." +msgstr "" + +#: tools/editor/asset_library_editor_plugin.cpp +msgid "Official" +msgstr "" + +#: tools/editor/asset_library_editor_plugin.cpp +msgid "Community" +msgstr "" + +#: tools/editor/asset_library_editor_plugin.cpp +msgid "Testing" +msgstr "" + +#: tools/editor/asset_library_editor_plugin.cpp +msgid "Assets ZIP File" +msgstr "" + +#: tools/editor/call_dialog.cpp +msgid "Method List For '%s':" +msgstr "" + +#: tools/editor/call_dialog.cpp +msgid "Method List:" +msgstr "" + +#: tools/editor/call_dialog.cpp +msgid "Arguments:" +msgstr "" + +#: tools/editor/call_dialog.cpp +msgid "Return:" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Go to Line" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Line Number:" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "No Matches" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Replaced %d Ocurrence(s)." +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Replace" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Replace All" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Match Case" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Whole Words" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Selection Only" +msgstr "" + +#: tools/editor/code_editor.cpp tools/editor/editor_help.cpp +#: tools/editor/plugins/script_editor_plugin.cpp +#: tools/editor/plugins/script_text_editor.cpp +#: tools/editor/plugins/shader_editor_plugin.cpp +#: tools/editor/project_settings.cpp +msgid "Search" +msgstr "" + +#: tools/editor/code_editor.cpp tools/editor/editor_help.cpp +msgid "Find" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Next" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Replaced %d ocurrence(s)." +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Not found!" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Replace By" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Case Sensitive" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Backwards" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Prompt On Replace" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Skip" +msgstr "" + +#: tools/editor/code_editor.cpp +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Zoom In" +msgstr "" + +#: tools/editor/code_editor.cpp +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Zoom Out" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Reset Zoom" +msgstr "" + +#: tools/editor/code_editor.cpp tools/editor/script_editor_debugger.cpp +msgid "Line:" +msgstr "" + +#: tools/editor/code_editor.cpp +msgid "Col:" +msgstr "" + +#: tools/editor/connections_dialog.cpp +msgid "Method in target Node must be specified!" +msgstr "" + +#: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp +msgid "Connect To Node:" +msgstr "" + +#: tools/editor/connections_dialog.cpp +#: tools/editor/editor_autoload_settings.cpp tools/editor/groups_editor.cpp +#: tools/editor/plugins/item_list_editor_plugin.cpp +#: tools/editor/plugins/theme_editor_plugin.cpp +#: tools/editor/project_settings.cpp +msgid "Add" +msgstr "" + +#: tools/editor/connections_dialog.cpp tools/editor/dependency_editor.cpp +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +#: tools/editor/plugins/theme_editor_plugin.cpp +#: tools/editor/project_manager.cpp +msgid "Remove" +msgstr "" + +#: tools/editor/connections_dialog.cpp +msgid "Add Extra Call Argument:" +msgstr "" + +#: tools/editor/connections_dialog.cpp +msgid "Extra Call Arguments:" +msgstr "" + +#: tools/editor/connections_dialog.cpp +msgid "Path to Node:" +msgstr "" + +#: tools/editor/connections_dialog.cpp +msgid "Make Function" +msgstr "" + +#: tools/editor/connections_dialog.cpp +msgid "Deferred" +msgstr "" + +#: tools/editor/connections_dialog.cpp +msgid "Oneshot" +msgstr "" + +#: tools/editor/connections_dialog.cpp +msgid "Connect" +msgstr "" + +#: tools/editor/connections_dialog.cpp +msgid "Connect '%s' to '%s'" +msgstr "" + +#: tools/editor/connections_dialog.cpp +msgid "Connecting Signal:" +msgstr "" + +#: tools/editor/connections_dialog.cpp +msgid "Create Subscription" +msgstr "" + +#: tools/editor/connections_dialog.cpp +msgid "Connect.." +msgstr "" + +#: tools/editor/connections_dialog.cpp +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Disconnect" +msgstr "" + +#: tools/editor/connections_dialog.cpp tools/editor/node_dock.cpp +msgid "Signals" +msgstr "" + +#: tools/editor/create_dialog.cpp +msgid "Create New" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp +#: tools/editor/plugins/script_editor_plugin.cpp +#: tools/editor/property_selector.cpp tools/editor/quick_open.cpp +msgid "Matches:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp +#: tools/editor/property_selector.cpp tools/editor/script_editor_debugger.cpp +msgid "Description:" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Search Replacement For:" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Dependencies For:" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "" +"Scene '%s' is currently being edited.\n" +"Changes will not take effect unless reloaded." +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "" +"Resource '%s' is in use.\n" +"Changes will take effect when reloaded." +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Dependencies" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Resource" +msgstr "" + +#: tools/editor/dependency_editor.cpp tools/editor/editor_autoload_settings.cpp +#: tools/editor/project_manager.cpp tools/editor/project_settings.cpp +msgid "Path" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Dependencies:" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Fix Broken" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Dependency Editor" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Search Replacement Resource:" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Owners Of:" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "" +"The files being removed are required by other resources in order for them to " +"work.\n" +"Remove them anyway? (no undo)" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Remove selected files from the project? (no undo)" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Error loading:" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Scene failed to load due to missing dependencies:" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Open Anyway" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Which action should be taken?" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Fix Dependencies" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Errors loading!" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Permanently delete %d item(s)? (No undo!)" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Owns" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Resources Without Explicit Ownership:" +msgstr "" + +#: tools/editor/dependency_editor.cpp tools/editor/editor_node.cpp +msgid "Orphan Resource Explorer" +msgstr "" + +#: tools/editor/dependency_editor.cpp +msgid "Delete selected files?" +msgstr "" + +#: tools/editor/dependency_editor.cpp tools/editor/editor_node.cpp +#: tools/editor/filesystem_dock.cpp +#: tools/editor/plugins/item_list_editor_plugin.cpp +#: tools/editor/scene_tree_dock.cpp +msgid "Delete" +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Invalid name." +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Valid characters:" +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Invalid name. Must not collide with an existing engine class name." +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Invalid name. Must not collide with an existing buit-in type name." +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Invalid name. Must not collide with an existing global constant name." +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Invalid Path." +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "File does not exist." +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Not in resource path." +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Add AutoLoad" +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Autoload '%s' already exists!" +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Rename Autoload" +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Toggle AutoLoad Globals" +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Move Autoload" +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Remove Autoload" +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Enable" +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Rearrange Autoloads" +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Node Name:" +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#: tools/editor/plugins/sample_library_editor_plugin.cpp +#: tools/editor/project_manager.cpp +msgid "Name" +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "Singleton" +msgstr "" + +#: tools/editor/editor_autoload_settings.cpp +msgid "List:" +msgstr "" + +#: tools/editor/editor_data.cpp +msgid "Updating Scene" +msgstr "" + +#: tools/editor/editor_data.cpp +msgid "Storing local changes.." +msgstr "" + +#: tools/editor/editor_data.cpp +msgid "Updating scene.." +msgstr "" + +#: tools/editor/editor_dir_dialog.cpp +msgid "Choose a Directory" +msgstr "" + +#: tools/editor/editor_dir_dialog.cpp +msgid "Choose" +msgstr "" + +#: tools/editor/editor_file_dialog.cpp +msgid "Go Back" +msgstr "" + +#: tools/editor/editor_file_dialog.cpp +msgid "Go Forward" +msgstr "" + +#: tools/editor/editor_file_dialog.cpp +msgid "Go Up" +msgstr "" + +#: tools/editor/editor_file_dialog.cpp +msgid "Refresh" +msgstr "" + +#: tools/editor/editor_file_dialog.cpp +msgid "Toggle Hidden Files" +msgstr "" + +#: tools/editor/editor_file_dialog.cpp +msgid "Toggle Favorite" +msgstr "" + +#: tools/editor/editor_file_dialog.cpp +msgid "Toggle Mode" +msgstr "" + +#: tools/editor/editor_file_dialog.cpp +msgid "Focus Path" +msgstr "" + +#: tools/editor/editor_file_dialog.cpp +msgid "Move Favorite Up" +msgstr "" + +#: tools/editor/editor_file_dialog.cpp +msgid "Move Favorite Down" +msgstr "" + +#: tools/editor/editor_file_dialog.cpp +msgid "Preview:" +msgstr "" + +#: tools/editor/editor_file_system.cpp +msgid "ScanSources" +msgstr "" + +#: tools/editor/editor_help.cpp tools/editor/plugins/script_editor_plugin.cpp +msgid "Search Help" +msgstr "" + +#: tools/editor/editor_help.cpp +msgid "Class List:" +msgstr "" + +#: tools/editor/editor_help.cpp +msgid "Search Classes" +msgstr "" + +#: tools/editor/editor_help.cpp tools/editor/property_editor.cpp +msgid "Class:" +msgstr "" + +#: tools/editor/editor_help.cpp tools/editor/scene_tree_editor.cpp +#: tools/editor/script_create_dialog.cpp +msgid "Inherits:" +msgstr "" + +#: tools/editor/editor_help.cpp +msgid "Inherited by:" +msgstr "" + +#: tools/editor/editor_help.cpp +msgid "Brief Description:" +msgstr "" + +#: tools/editor/editor_help.cpp +msgid "Public Methods:" +msgstr "" + +#: tools/editor/editor_help.cpp +msgid "GUI Theme Items:" +msgstr "" + +#: tools/editor/editor_help.cpp +msgid "Constants:" +msgstr "" + +#: tools/editor/editor_help.cpp +msgid "Method Description:" +msgstr "" + +#: tools/editor/editor_help.cpp +msgid "Search Text" +msgstr "" + +#: tools/editor/editor_import_export.cpp +msgid "Added:" +msgstr "" + +#: tools/editor/editor_import_export.cpp +msgid "Removed:" +msgstr "" + +#: tools/editor/editor_import_export.cpp tools/editor/project_export.cpp +msgid "Error saving atlas:" +msgstr "" + +#: tools/editor/editor_import_export.cpp +msgid "Could not save atlas subtexture:" +msgstr "" + +#: tools/editor/editor_import_export.cpp +msgid "Storing File:" +msgstr "" + +#: tools/editor/editor_import_export.cpp +msgid "Packing" +msgstr "" + +#: tools/editor/editor_import_export.cpp +msgid "Exporting for %s" +msgstr "" + +#: tools/editor/editor_import_export.cpp +msgid "Setting Up.." +msgstr "" + +#: tools/editor/editor_log.cpp +msgid " Output:" +msgstr "" + +#: tools/editor/editor_node.cpp tools/editor/editor_reimport_dialog.cpp +msgid "Re-Importing" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Importing:" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Node From Scene" +msgstr "" + +#: tools/editor/editor_node.cpp +#: tools/editor/plugins/animation_player_editor_plugin.cpp +#: tools/editor/resources_dock.cpp +msgid "Error saving resource!" +msgstr "" + +#: tools/editor/editor_node.cpp +#: tools/editor/plugins/animation_player_editor_plugin.cpp +#: tools/editor/resources_dock.cpp +msgid "Save Resource As.." +msgstr "" + +#: tools/editor/editor_node.cpp tools/editor/scene_tree_dock.cpp +msgid "I see.." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Can't open file for writing:" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Requested file format unknown:" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Error while saving." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Saving Scene" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Analyzing" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Creating Thumbnail" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "" +"Couldn't save scene. Likely dependencies (instances) couldn't be satisfied." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Failed to load resource." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Can't load MeshLibrary for merging!" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Error saving MeshLibrary!" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Can't load TileSet for merging!" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Error saving TileSet!" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Can't open export templates zip." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Loading Export Templates" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Error trying to save layout!" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Default editor layout overridden." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Layout name not found!" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Restored default layout to base settings." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Copy Params" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Paste Params" +msgstr "" + +#: tools/editor/editor_node.cpp +#: tools/editor/plugins/resource_preloader_editor_plugin.cpp +msgid "Paste Resource" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Copy Resource" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Make Built-In" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Make Sub-Resources Unique" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Open in Help" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "There is no defined scene to run." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "" +"No main scene has ever been defined, select one?\n" +"You can change it later in later in \"Project Settings\" under the " +"'application' category." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "" +"Selected scene '%s' does not exist, select a valid one?\n" +"You can change it later in \"Project Settings\" under the 'application' " +"category." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "" +"Selected scene '%s' is not a scene file, select a valid one?\n" +"You can change it later in \"Project Settings\" under the 'application' " +"category." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Current scene was never saved, please save it prior to running." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Could not start subprocess!" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Open Scene" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Open Base Scene" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Quick Open Scene.." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Quick Open Script.." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Yes" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Close scene? (Unsaved changes will be lost)" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Save Scene As.." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "This scene has never been saved. Save before running?" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Please save the scene first." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Save Translatable Strings" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Export Mesh Library" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Export Tile Set" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Quit" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Exit the editor?" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Current scene not saved. Open anyway?" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Can't reload a scene that was never saved." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Revert" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "This action cannot be undone. Revert anyway?" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Quick Run Scene.." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "" +"Open Project Manager? \n" +"(Unsaved changes will be lost)" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Pick a Main Scene" +msgstr "" + +#: tools/editor/editor_node.cpp tools/editor/scene_tree_dock.cpp +msgid "Ugh" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "" +"Error loading scene, it must be inside the project path. Use 'Import' to " +"open the scene, then save it inside the project path." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Error loading scene." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Scene '%s' has broken dependencies:" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Save Layout" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Delete Layout" +msgstr "" + +#: tools/editor/editor_node.cpp tools/editor/project_export.cpp +msgid "Default" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Switch Scene Tab" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "%d more file(s)" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "%d more file(s) or folder(s)" +msgstr "" + +#: tools/editor/editor_node.cpp +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Scene" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Go to previously opened scene." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Next tab" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Previous tab" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Operations with scene files." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "New Scene" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "New Inherited Scene.." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Open Scene.." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Save Scene" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Save all Scenes" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Close Scene" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Close Goto Prev. Scene" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Open Recent" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Quick Filter Files.." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Convert To.." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Translatable Strings.." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "MeshLibrary.." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "TileSet.." +msgstr "" + +#: tools/editor/editor_node.cpp tools/editor/plugins/script_text_editor.cpp +#: tools/editor/plugins/shader_editor_plugin.cpp +msgid "Redo" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Run Script" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Project Settings" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Revert Scene" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Quit to Project List" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Import assets to the project." +msgstr "" + +#: tools/editor/editor_node.cpp +#: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +#: tools/editor/io_plugins/editor_mesh_import_plugin.cpp +#: tools/editor/io_plugins/editor_sample_import_plugin.cpp +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +#: tools/editor/project_manager.cpp +msgid "Import" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Miscellaneous project or scene-wide tools." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Tools" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Export the project to many platforms." +msgstr "" + +#: tools/editor/editor_node.cpp tools/editor/project_export.cpp +msgid "Export" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Play the project." +msgstr "" + +#: tools/editor/editor_node.cpp +#: tools/editor/plugins/sample_library_editor_plugin.cpp +msgid "Play" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Pause the scene" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Pause Scene" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Stop the scene." +msgstr "" + +#: tools/editor/editor_node.cpp +#: tools/editor/plugins/sample_library_editor_plugin.cpp +msgid "Stop" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Play the edited scene." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Play Scene" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Play custom scene" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Play Custom Scene" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Debug options" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Deploy with Remote Debug" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "" +"When exporting or deploying, the resulting executable will attempt to " +"connect to the IP of this computer in order to be debugged." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Small Deploy with Network FS" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "" +"When this option is enabled, export or deploy will produce a minimal " +"executable.\n" +"The filesystem will be provided from the project by the editor over the " +"network.\n" +"On Android, deploy will use the USB cable for faster performance. This " +"option speeds up testing for games with a large footprint." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Visible Collision Shapes" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "" +"Collision shapes and raycast nodes (for 2D and 3D) will be visible on the " +"running game if this option is turned on." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Visible Navigation" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "" +"Navigation meshes and polygons will be visible on the running game if this " +"option is turned on." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Sync Scene Changes" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "" +"When this option is turned on, any changes made to the scene in the editor " +"will be replicated in the running game.\n" +"When used remotely on a device, this is more efficient with network " +"filesystem." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Sync Script Changes" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "" +"When this option is turned on, any script that is saved will be reloaded on " +"the running game.\n" +"When used remotely on a device, this is more efficient with network " +"filesystem." +msgstr "" + +#: tools/editor/editor_node.cpp tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Settings" +msgstr "" + +#: tools/editor/editor_node.cpp tools/editor/settings_config_dialog.cpp +msgid "Editor Settings" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Editor Layout" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Install Export Templates" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "About" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Alerts when an external resource has changed." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Spins when the editor window repaints!" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Update Always" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Update Changes" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Inspector" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Create a new resource in memory and edit it." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Load an existing resource from disk and edit it." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Save the currently edited resource." +msgstr "" + +#: tools/editor/editor_node.cpp tools/editor/plugins/script_editor_plugin.cpp +msgid "Save As.." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Go to the previous edited object in history." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Go to the next edited object in history." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "History of recently edited objects." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Object properties." +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "FileSystem" +msgstr "" + +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Output" +msgstr "" + +#: tools/editor/editor_node.cpp tools/editor/editor_reimport_dialog.cpp +msgid "Re-Import" +msgstr "" + +#: tools/editor/editor_node.cpp tools/editor/editor_plugin_settings.cpp +msgid "Update" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Thanks from the Godot community!" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Thanks!" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Import Templates From ZIP File" +msgstr "" + +#: tools/editor/editor_node.cpp tools/editor/project_export.cpp +msgid "Export Project" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Export Library" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Merge With Existing" +msgstr "" + +#: tools/editor/editor_node.cpp tools/editor/project_export.cpp +msgid "Password:" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Open & Run a Script" +msgstr "" + +#: tools/editor/editor_node.cpp +msgid "Load Errors" +msgstr "" + +#: tools/editor/editor_plugin_settings.cpp +msgid "Installed Plugins:" +msgstr "" + +#: tools/editor/editor_plugin_settings.cpp +msgid "Version:" +msgstr "" + +#: tools/editor/editor_plugin_settings.cpp +msgid "Author:" +msgstr "" + +#: tools/editor/editor_plugin_settings.cpp +msgid "Status:" +msgstr "" + +#: tools/editor/editor_profiler.cpp +msgid "Stop Profiling" +msgstr "" + +#: tools/editor/editor_profiler.cpp +msgid "Start Profiling" +msgstr "" + +#: tools/editor/editor_profiler.cpp +msgid "Measure:" +msgstr "" + +#: tools/editor/editor_profiler.cpp +msgid "Frame Time (sec)" +msgstr "" + +#: tools/editor/editor_profiler.cpp +msgid "Average Time (sec)" +msgstr "" + +#: tools/editor/editor_profiler.cpp +msgid "Frame %" +msgstr "" + +#: tools/editor/editor_profiler.cpp +msgid "Fixed Frame %" +msgstr "" + +#: tools/editor/editor_profiler.cpp tools/editor/script_editor_debugger.cpp +msgid "Time:" +msgstr "" + +#: tools/editor/editor_profiler.cpp +msgid "Inclusive" +msgstr "" + +#: tools/editor/editor_profiler.cpp +msgid "Self" +msgstr "" + +#: tools/editor/editor_profiler.cpp +msgid "Frame #:" +msgstr "" + +#: tools/editor/editor_reimport_dialog.cpp +msgid "Please wait for scan to complete." +msgstr "" + +#: tools/editor/editor_reimport_dialog.cpp +msgid "Current scene must be saved to re-import." +msgstr "" + +#: tools/editor/editor_reimport_dialog.cpp +msgid "Save & Re-Import" +msgstr "" + +#: tools/editor/editor_reimport_dialog.cpp +msgid "Re-Import Changed Resources" +msgstr "" + +#: tools/editor/editor_run_script.cpp +msgid "Write your logic in the _run() method." +msgstr "" + +#: tools/editor/editor_run_script.cpp +msgid "There is an edited scene already." +msgstr "" + +#: tools/editor/editor_run_script.cpp +msgid "Couldn't instance script:" +msgstr "" + +#: tools/editor/editor_run_script.cpp +msgid "Did you forget the 'tool' keyword?" +msgstr "" + +#: tools/editor/editor_run_script.cpp +msgid "Couldn't run script:" +msgstr "" + +#: tools/editor/editor_run_script.cpp +msgid "Did you forget the '_run' method?" +msgstr "" + +#: tools/editor/editor_settings.cpp +msgid "Default (Same as Editor)" +msgstr "" + +#: tools/editor/editor_sub_scene.cpp +msgid "Select Node(s) to Import" +msgstr "" + +#: tools/editor/editor_sub_scene.cpp +msgid "Scene Path:" +msgstr "" + +#: tools/editor/editor_sub_scene.cpp +msgid "Import From Node:" +msgstr "" + +#: tools/editor/file_type_cache.cpp +msgid "Can't open file_type_cache.cch for writing, not saving file type cache!" +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Same source and destination files, doing nothing." +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Same source and destination paths, doing nothing." +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Can't move directories to within themselves." +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Can't operate on '..'" +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Pick New Name and Location For:" +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "No files selected!" +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Instance" +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Edit Dependencies.." +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "View Owners.." +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Copy Path" +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Rename or Move.." +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Move To.." +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Info" +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Show In File Manager" +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Re-Import.." +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Previous Directory" +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Next Directory" +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Re-Scan Filesystem" +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Toggle folder status as Favorite" +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Instance the selected scene(s) as child of the selected node." +msgstr "" + +#: tools/editor/filesystem_dock.cpp +msgid "Move" +msgstr "" + +#: tools/editor/groups_editor.cpp +msgid "Add to Group" +msgstr "" + +#: tools/editor/groups_editor.cpp +msgid "Remove from Group" +msgstr "" + +#: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp +msgid "No bit masks to import!" +msgstr "" + +#: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp +#: tools/editor/io_plugins/editor_sample_import_plugin.cpp +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Target path is empty." +msgstr "" + +#: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp +#: tools/editor/io_plugins/editor_sample_import_plugin.cpp +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Target path must be a complete resource path." +msgstr "" + +#: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp +#: tools/editor/io_plugins/editor_sample_import_plugin.cpp +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Target path must exist." +msgstr "" + +#: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp +#: tools/editor/io_plugins/editor_mesh_import_plugin.cpp +#: tools/editor/io_plugins/editor_sample_import_plugin.cpp +msgid "Save path is empty!" +msgstr "" + +#: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp +msgid "Import BitMasks" +msgstr "" + +#: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Source Texture(s):" +msgstr "" + +#: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp +#: tools/editor/io_plugins/editor_mesh_import_plugin.cpp +#: tools/editor/io_plugins/editor_sample_import_plugin.cpp +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "Target Path:" +msgstr "" + +#: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +#: tools/editor/io_plugins/editor_sample_import_plugin.cpp +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "Accept" +msgstr "" + +#: tools/editor/io_plugins/editor_bitmask_import_plugin.cpp +msgid "Bit Mask" +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "No source font file!" +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "No target font resource!" +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "" +"Invalid file extension.\n" +"Please use .fnt." +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "Can't load/process source font." +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "Couldn't save font." +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "Source Font:" +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "Source Font Size:" +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "Dest Resource:" +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "The quick brown fox jumps over the lazy dog." +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "Test:" +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +#: tools/editor/io_plugins/editor_mesh_import_plugin.cpp +#: tools/editor/io_plugins/editor_sample_import_plugin.cpp +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Options:" +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "Font Import" +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "" +"This file is already a Godot font file, please supply a BMFont type file " +"instead." +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "Failed opening as BMFont file." +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +msgid "Invalid font custom source." +msgstr "" + +#: tools/editor/io_plugins/editor_font_import_plugin.cpp +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Font" +msgstr "" + +#: tools/editor/io_plugins/editor_mesh_import_plugin.cpp +msgid "No meshes to import!" +msgstr "" + +#: tools/editor/io_plugins/editor_mesh_import_plugin.cpp +msgid "Single Mesh Import" +msgstr "" + +#: tools/editor/io_plugins/editor_mesh_import_plugin.cpp +msgid "Source Mesh(es):" +msgstr "" + +#: tools/editor/io_plugins/editor_mesh_import_plugin.cpp +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Mesh" +msgstr "" + +#: tools/editor/io_plugins/editor_mesh_import_plugin.cpp +msgid "Surface %d" +msgstr "" + +#: tools/editor/io_plugins/editor_sample_import_plugin.cpp +msgid "No samples to import!" +msgstr "" + +#: tools/editor/io_plugins/editor_sample_import_plugin.cpp +msgid "Import Audio Samples" +msgstr "" + +#: tools/editor/io_plugins/editor_sample_import_plugin.cpp +msgid "Source Sample(s):" +msgstr "" + +#: tools/editor/io_plugins/editor_sample_import_plugin.cpp +msgid "Audio Sample" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "New Clip" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Animation Options" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Flags" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Bake FPS:" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Optimizer" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Max Linear Error" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Max Angular Error" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Max Angle" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Clips" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Start(s)" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "End(s)" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Loop" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Filters" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Source path is empty." +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Couldn't load post-import script." +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Invalid/broken script for post-import." +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Error importing scene." +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Import 3D Scene" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Source Scene:" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Same as Target Scene" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Shared" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Target Texture Folder:" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Post-Process Script:" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Custom Root Node Type:" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Auto" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "The Following Files are Missing:" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Import Anyway" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Import & Open" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Edited scene has not been saved, open imported scene anyway?" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#: tools/editor/plugins/cube_grid_theme_editor_plugin.cpp +msgid "Import Scene" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Importing Scene.." +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Running Custom Script.." +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Couldn't load post-import script:" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Invalid/broken script for post-import (check console):" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Error running post-import script:" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Import Image:" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Can't import a file over itself:" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Couldn't localize path: %s (already local)" +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "Saving.." +msgstr "" + +#: tools/editor/io_plugins/editor_scene_import_plugin.cpp +msgid "3D Scene Animation" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Uncompressed" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Compress Lossless (PNG)" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Compress Lossy (WebP)" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Compress (VRAM)" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Texture Format" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Texture Compression Quality (WebP):" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Texture Options" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Please specify some files!" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "At least one file needed for Atlas." +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Error importing:" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Only one file is required for large texture." +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Max Texture Size:" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Import Textures for Atlas (2D)" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Cell Size:" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Large Texture" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Import Large Textures (2D)" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Source Texture" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Base Atlas Texture" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Source Texture(s)" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Import Textures for 2D" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Import Textures for 3D" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Import Textures" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "2D Texture" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "3D Texture" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Atlas Texture" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "" +"NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to " +"the project." +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Crop empty space." +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Texture" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Import Large Texture" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Load Source Image" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Slicing" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Inserting" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Saving" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Couldn't save large texture:" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Build Atlas For:" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Loading Image:" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Couldn't load image:" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Converting Images" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Cropping Images" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Blitting Images" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Couldn't save atlas image:" +msgstr "" + +#: tools/editor/io_plugins/editor_texture_import_plugin.cpp +msgid "Couldn't save converted texture:" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "Invalid source!" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "Invalid translation source!" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "Column" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +#: tools/editor/script_create_dialog.cpp +msgid "Language" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "No items to import!" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "No target path!" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "Import Translations" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "Couldn't import!" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "Import Translation" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "Source CSV:" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "Ignore First Row" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "Compress" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "Add to Project (engine.cfg)" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "Import Languages:" +msgstr "" + +#: tools/editor/io_plugins/editor_translation_import_plugin.cpp +msgid "Translation" +msgstr "" + +#: tools/editor/multi_node_edit.cpp +msgid "MultiNode Set" +msgstr "" + +#: tools/editor/node_dock.cpp +msgid "Groups" +msgstr "" + +#: tools/editor/node_dock.cpp +msgid "Select a Node to edit Signals and Groups." +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Toggle Autoplay" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "New Animation Name:" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "New Anim" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Change Animation Name:" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Remove Animation" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "ERROR: Invalid animation name!" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "ERROR: Animation name already exists!" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Rename Animation" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Add Animation" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Blend Next Changed" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Change Blend Time" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Load Animation" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Duplicate Animation" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "ERROR: No animation to copy!" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "ERROR: No animation resource on clipboard!" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Pasted Animation" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Paste Animation" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "ERROR: No animation to edit!" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Play selected animation backwards from current pos. (A)" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Play selected animation backwards from end. (Shift+A)" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Stop animation playback. (S)" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Play selected animation from start. (Shift+D)" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Play selected animation from current pos. (D)" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Animation position (in seconds)." +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Scale animation playback globally for the node." +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Create new animation in player." +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Load animation from disk." +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Load an animation from disk." +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Save the current animation" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Save As" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Display list of animations in player." +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Autoplay on Load" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Edit Target Blend Times" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Animation Tools" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Copy Animation" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Create New Animation" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Animation Name:" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +#: tools/editor/plugins/resource_preloader_editor_plugin.cpp +#: tools/editor/plugins/sample_library_editor_plugin.cpp +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +#: tools/editor/property_editor.cpp tools/editor/script_create_dialog.cpp +msgid "Error!" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Blend Times:" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Next (Auto Queue):" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +msgid "Cross-Animation Blend Times" +msgstr "" + +#: tools/editor/plugins/animation_player_editor_plugin.cpp +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Animation" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "New name:" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Scale:" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Fade In (s):" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Fade Out (s):" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Blend" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Mix" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Auto Restart:" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Restart (s):" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Random Restart (s):" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Start!" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Amount:" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Blend:" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Blend 0:" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Blend 1:" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "X-Fade Time (s):" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Current:" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Add Input" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Clear Auto-Advance" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Set Auto-Advance" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Delete Input" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Rename" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Animation tree is valid." +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Animation tree is invalid." +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Animation Node" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "OneShot Node" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Mix Node" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Blend2 Node" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Blend3 Node" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Blend4 Node" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "TimeScale Node" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "TimeSeek Node" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Transition Node" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Import Animations.." +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Edit Node Filters" +msgstr "" + +#: tools/editor/plugins/animation_tree_editor_plugin.cpp +msgid "Filters.." +msgstr "" + +#: tools/editor/plugins/baked_light_baker.cpp +msgid "Parsing %d Triangles:" +msgstr "" + +#: tools/editor/plugins/baked_light_baker.cpp +msgid "Triangle #" +msgstr "" + +#: tools/editor/plugins/baked_light_baker.cpp +msgid "Light Baker Setup:" +msgstr "" + +#: tools/editor/plugins/baked_light_baker.cpp +msgid "Parsing Geometry" +msgstr "" + +#: tools/editor/plugins/baked_light_baker.cpp +msgid "Fixing Lights" +msgstr "" + +#: tools/editor/plugins/baked_light_baker.cpp +msgid "Making BVH" +msgstr "" + +#: tools/editor/plugins/baked_light_baker.cpp +msgid "Creating Light Octree" +msgstr "" + +#: tools/editor/plugins/baked_light_baker.cpp +msgid "Creating Octree Texture" +msgstr "" + +#: tools/editor/plugins/baked_light_baker.cpp +msgid "Transfer to Lightmaps:" +msgstr "" + +#: tools/editor/plugins/baked_light_baker.cpp +msgid "Allocating Texture #" +msgstr "" + +#: tools/editor/plugins/baked_light_baker.cpp +msgid "Baking Triangle #" +msgstr "" + +#: tools/editor/plugins/baked_light_baker.cpp +msgid "Post-Processing Texture #" +msgstr "" + +#: tools/editor/plugins/baked_light_editor_plugin.cpp +msgid "Bake!" +msgstr "" + +#: tools/editor/plugins/baked_light_editor_plugin.cpp +msgid "Reset the lightmap octree baking process (start over)." +msgstr "" + +#: tools/editor/plugins/camera_editor_plugin.cpp +#: tools/editor/plugins/sample_library_editor_plugin.cpp +msgid "Preview" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Configure Snap" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Grid Offset:" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Grid Step:" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Rotation Offset:" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Rotation Step:" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Move Pivot" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Move Action" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Edit IK Chain" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Edit CanvasItem" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Change Anchors" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Zoom (%):" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Paste Pose" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Select Mode" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Drag: Rotate" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Alt+Drag: Move" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving)." +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Alt+RMB: Depth list selection" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Move Mode" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Rotate Mode" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "" +"Show a list of all objects at the position clicked\n" +"(same as Alt+RMB in select mode)." +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Click to change object's rotation pivot." +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Pan Mode" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Lock the selected object in place (can't be moved)." +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Unlock the selected object (can be moved)." +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Makes sure the object's children are not selectable." +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Restores the object's children's ability to be selected." +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Use Snap" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Show Grid" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Use Rotation Snap" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Snap Relative" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Configure Snap.." +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Use Pixel Snap" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Expand to Parent" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Skeleton.." +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Make Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Clear Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Make IK Chain" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Clear IK Chain" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "View" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Zoom Reset" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Zoom Set.." +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Center Selection" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Frame Selection" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Anchor" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Insert Keys" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Insert Key" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Insert Key (Existing Tracks)" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Copy Pose" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Clear Pose" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Set a Value" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Snap (Pixels):" +msgstr "" + +#: tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp +#: tools/editor/plugins/light_occluder_2d_editor_plugin.cpp +#: tools/editor/plugins/navigation_polygon_editor_plugin.cpp +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Create Poly" +msgstr "" + +#: tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp +#: tools/editor/plugins/collision_polygon_editor_plugin.cpp +#: tools/editor/plugins/light_occluder_2d_editor_plugin.cpp +#: tools/editor/plugins/navigation_polygon_editor_plugin.cpp +#: tools/editor/plugins/path_2d_editor_plugin.cpp +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Edit Poly" +msgstr "" + +#: tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp +#: tools/editor/plugins/collision_polygon_editor_plugin.cpp +#: tools/editor/plugins/light_occluder_2d_editor_plugin.cpp +#: tools/editor/plugins/navigation_polygon_editor_plugin.cpp +#: tools/editor/plugins/path_2d_editor_plugin.cpp +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Edit Poly (Remove Point)" +msgstr "" + +#: tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp +#: tools/editor/plugins/light_occluder_2d_editor_plugin.cpp +#: tools/editor/plugins/navigation_polygon_editor_plugin.cpp +msgid "Create a new polygon from scratch." +msgstr "" + +#: tools/editor/plugins/collision_polygon_editor_plugin.cpp +msgid "Create Poly3D" +msgstr "" + +#: tools/editor/plugins/collision_shape_2d_editor_plugin.cpp +msgid "Set Handle" +msgstr "" + +#: tools/editor/plugins/color_ramp_editor_plugin.cpp +msgid "Add/Remove Color Ramp Point" +msgstr "" + +#: tools/editor/plugins/color_ramp_editor_plugin.cpp +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Modify Color Ramp" +msgstr "" + +#: tools/editor/plugins/cube_grid_theme_editor_plugin.cpp +msgid "Creating Mesh Library" +msgstr "" + +#: tools/editor/plugins/cube_grid_theme_editor_plugin.cpp +msgid "Thumbnail.." +msgstr "" + +#: tools/editor/plugins/cube_grid_theme_editor_plugin.cpp +msgid "Remove item %d?" +msgstr "" + +#: tools/editor/plugins/cube_grid_theme_editor_plugin.cpp +#: tools/editor/plugins/theme_editor_plugin.cpp +#: tools/editor/plugins/tile_set_editor_plugin.cpp +msgid "Add Item" +msgstr "" + +#: tools/editor/plugins/cube_grid_theme_editor_plugin.cpp +msgid "Remove Selected Item" +msgstr "" + +#: tools/editor/plugins/cube_grid_theme_editor_plugin.cpp +msgid "Import from Scene" +msgstr "" + +#: tools/editor/plugins/cube_grid_theme_editor_plugin.cpp +msgid "Update from Scene" +msgstr "" + +#: tools/editor/plugins/item_list_editor_plugin.cpp +msgid "Item %d" +msgstr "" + +#: tools/editor/plugins/item_list_editor_plugin.cpp +msgid "Items" +msgstr "" + +#: tools/editor/plugins/item_list_editor_plugin.cpp +msgid "Item List Editor" +msgstr "" + +#: tools/editor/plugins/light_occluder_2d_editor_plugin.cpp +msgid "Create Occluder Polygon" +msgstr "" + +#: tools/editor/plugins/light_occluder_2d_editor_plugin.cpp +#: tools/editor/plugins/navigation_polygon_editor_plugin.cpp +msgid "Edit existing polygon:" +msgstr "" + +#: tools/editor/plugins/light_occluder_2d_editor_plugin.cpp +#: tools/editor/plugins/navigation_polygon_editor_plugin.cpp +msgid "LMB: Move Point." +msgstr "" + +#: tools/editor/plugins/light_occluder_2d_editor_plugin.cpp +#: tools/editor/plugins/navigation_polygon_editor_plugin.cpp +msgid "Ctrl+LMB: Split Segment." +msgstr "" + +#: tools/editor/plugins/light_occluder_2d_editor_plugin.cpp +#: tools/editor/plugins/navigation_polygon_editor_plugin.cpp +msgid "RMB: Erase Point." +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Mesh is empty!" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Create Static Trimesh Body" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Create Static Convex Body" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "This doesn't work on scene root!" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Create Trimesh Shape" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Create Convex Shape" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Create Navigation Mesh" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "MeshInstance lacks a Mesh!" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Mesh has not surface to create outlines from!" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Could not create outline!" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Create Outline" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Create Trimesh Static Body" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Create Convex Static Body" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Create Trimesh Collision Sibling" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Create Convex Collision Sibling" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Create Outline Mesh.." +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Create Outline Mesh" +msgstr "" + +#: tools/editor/plugins/mesh_instance_editor_plugin.cpp +msgid "Outline Size:" +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "No mesh source specified (and no MultiMesh set in node)." +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "No mesh source specified (and MultiMesh contains no Mesh)." +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Mesh source is invalid (invalid path)." +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Mesh source is invalid (not a MeshInstance)." +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Mesh source is invalid (contains no Mesh resource)." +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "No surface source specified." +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Surface source is invalid (invalid path)." +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Surface source is invalid (no geometry)." +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Surface source is invalid (no faces)." +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Parent has no solid faces to populate." +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Couldn't map area." +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Select a Source Mesh:" +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Select a Target Surface:" +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Populate Surface" +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Populate MultiMesh" +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Target Surface:" +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Source Mesh:" +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "X-Axis" +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Y-Axis" +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Z-Axis" +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Mesh Up Axis:" +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Random Rotation:" +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Random Tilt:" +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Random Scale:" +msgstr "" + +#: tools/editor/plugins/multimesh_editor_plugin.cpp +msgid "Populate" +msgstr "" + +#: tools/editor/plugins/navigation_polygon_editor_plugin.cpp +msgid "Create Navigation Polygon" +msgstr "" + +#: tools/editor/plugins/navigation_polygon_editor_plugin.cpp +msgid "Remove Poly And Point" +msgstr "" + +#: tools/editor/plugins/particles_2d_editor_plugin.cpp +msgid "Error loading image:" +msgstr "" + +#: tools/editor/plugins/particles_2d_editor_plugin.cpp +msgid "No pixels with transparency > 128 in image.." +msgstr "" + +#: tools/editor/plugins/particles_2d_editor_plugin.cpp +msgid "Set Emission Mask" +msgstr "" + +#: tools/editor/plugins/particles_2d_editor_plugin.cpp +msgid "Clear Emission Mask" +msgstr "" + +#: tools/editor/plugins/particles_2d_editor_plugin.cpp +msgid "Load Emission Mask" +msgstr "" + +#: tools/editor/plugins/particles_2d_editor_plugin.cpp +msgid "Generated Point Count:" +msgstr "" + +#: tools/editor/plugins/particles_editor_plugin.cpp +msgid "Node does not contain geometry." +msgstr "" + +#: tools/editor/plugins/particles_editor_plugin.cpp +msgid "Node does not contain geometry (faces)." +msgstr "" + +#: tools/editor/plugins/particles_editor_plugin.cpp +msgid "Faces contain no area!" +msgstr "" + +#: tools/editor/plugins/particles_editor_plugin.cpp +msgid "No faces!" +msgstr "" + +#: tools/editor/plugins/particles_editor_plugin.cpp +msgid "Generate AABB" +msgstr "" + +#: tools/editor/plugins/particles_editor_plugin.cpp +msgid "Create Emitter From Mesh" +msgstr "" + +#: tools/editor/plugins/particles_editor_plugin.cpp +msgid "Create Emitter From Node" +msgstr "" + +#: tools/editor/plugins/particles_editor_plugin.cpp +msgid "Clear Emitter" +msgstr "" + +#: tools/editor/plugins/particles_editor_plugin.cpp +msgid "Create Emitter" +msgstr "" + +#: tools/editor/plugins/particles_editor_plugin.cpp +msgid "Emission Positions:" +msgstr "" + +#: tools/editor/plugins/particles_editor_plugin.cpp +msgid "Emission Fill:" +msgstr "" + +#: tools/editor/plugins/particles_editor_plugin.cpp +msgid "Surface" +msgstr "" + +#: tools/editor/plugins/particles_editor_plugin.cpp +msgid "Volume" +msgstr "" + +#: tools/editor/plugins/path_2d_editor_plugin.cpp +msgid "Remove Point from Curve" +msgstr "" + +#: tools/editor/plugins/path_2d_editor_plugin.cpp +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Add Point to Curve" +msgstr "" + +#: tools/editor/plugins/path_2d_editor_plugin.cpp +msgid "Move Point in Curve" +msgstr "" + +#: tools/editor/plugins/path_2d_editor_plugin.cpp +msgid "Move In-Control in Curve" +msgstr "" + +#: tools/editor/plugins/path_2d_editor_plugin.cpp +msgid "Move Out-Control in Curve" +msgstr "" + +#: tools/editor/plugins/path_2d_editor_plugin.cpp +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Select Points" +msgstr "" + +#: tools/editor/plugins/path_2d_editor_plugin.cpp +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Shift+Drag: Select Control Points" +msgstr "" + +#: tools/editor/plugins/path_2d_editor_plugin.cpp +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Click: Add Point" +msgstr "" + +#: tools/editor/plugins/path_2d_editor_plugin.cpp +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Right Click: Delete Point" +msgstr "" + +#: tools/editor/plugins/path_2d_editor_plugin.cpp +msgid "Select Control Points (Shift+Drag)" +msgstr "" + +#: tools/editor/plugins/path_2d_editor_plugin.cpp +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Add Point (in empty space)" +msgstr "" + +#: tools/editor/plugins/path_2d_editor_plugin.cpp +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Split Segment (in curve)" +msgstr "" + +#: tools/editor/plugins/path_2d_editor_plugin.cpp +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Delete Point" +msgstr "" + +#: tools/editor/plugins/path_2d_editor_plugin.cpp +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Close Curve" +msgstr "" + +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Curve Point #" +msgstr "" + +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Set Curve Point Pos" +msgstr "" + +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Set Curve In Pos" +msgstr "" + +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Set Curve Out Pos" +msgstr "" + +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Split Path" +msgstr "" + +#: tools/editor/plugins/path_editor_plugin.cpp +msgid "Remove Path Point" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Create UV Map" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Transform UV Map" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Polygon 2D UV Editor" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Move Point" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Ctrl: Rotate" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Shift: Move All" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Shift+Ctrl: Scale" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Move Polygon" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Rotate Polygon" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Scale Polygon" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Polygon->UV" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "UV->Polygon" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Clear UV" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Snap" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Enable Snap" +msgstr "" + +#: tools/editor/plugins/polygon_2d_editor_plugin.cpp +msgid "Grid" +msgstr "" + +#: tools/editor/plugins/resource_preloader_editor_plugin.cpp +msgid "ERROR: Couldn't load resource!" +msgstr "" + +#: tools/editor/plugins/resource_preloader_editor_plugin.cpp +msgid "Add Resource" +msgstr "" + +#: tools/editor/plugins/resource_preloader_editor_plugin.cpp +msgid "Rename Resource" +msgstr "" + +#: tools/editor/plugins/resource_preloader_editor_plugin.cpp +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Delete Resource" +msgstr "" + +#: tools/editor/plugins/resource_preloader_editor_plugin.cpp +msgid "Resource clipboard is empty!" +msgstr "" + +#: tools/editor/plugins/resource_preloader_editor_plugin.cpp +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Load Resource" +msgstr "" + +#: tools/editor/plugins/rich_text_editor_plugin.cpp +msgid "Parse BBCode" +msgstr "" + +#: tools/editor/plugins/sample_editor_plugin.cpp +msgid "Length:" +msgstr "" + +#: tools/editor/plugins/sample_library_editor_plugin.cpp +msgid "Open Sample File(s)" +msgstr "" + +#: tools/editor/plugins/sample_library_editor_plugin.cpp +msgid "ERROR: Couldn't load sample!" +msgstr "" + +#: tools/editor/plugins/sample_library_editor_plugin.cpp +msgid "Add Sample" +msgstr "" + +#: tools/editor/plugins/sample_library_editor_plugin.cpp +msgid "Rename Sample" +msgstr "" + +#: tools/editor/plugins/sample_library_editor_plugin.cpp +msgid "Delete Sample" +msgstr "" + +#: tools/editor/plugins/sample_library_editor_plugin.cpp +msgid "16 Bits" +msgstr "" + +#: tools/editor/plugins/sample_library_editor_plugin.cpp +msgid "8 Bits" +msgstr "" + +#: tools/editor/plugins/sample_library_editor_plugin.cpp +msgid "Stereo" +msgstr "" + +#: tools/editor/plugins/sample_library_editor_plugin.cpp +msgid "Mono" +msgstr "" + +#: tools/editor/plugins/sample_library_editor_plugin.cpp +#: tools/editor/script_editor_debugger.cpp +msgid "Format" +msgstr "" + +#: tools/editor/plugins/sample_library_editor_plugin.cpp +msgid "Pitch" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Error while saving theme" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Error saving" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Error importing theme" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Error importing" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Import Theme" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Save Theme As.." +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Next script" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Previous script" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +#: tools/editor/project_export.cpp +msgid "File" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +#: tools/editor/property_editor.cpp +msgid "New" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Save All" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Soft Reload Script" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "History Prev" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "History Next" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Reload Theme" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Save Theme" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Save Theme As" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Close Docs" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Close All" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +#: tools/editor/plugins/script_text_editor.cpp +#: tools/editor/plugins/shader_editor_plugin.cpp +msgid "Find.." +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +#: tools/editor/plugins/script_text_editor.cpp +#: tools/editor/plugins/shader_editor_plugin.cpp +msgid "Find Next" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Debug" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +#: tools/editor/script_editor_debugger.cpp +msgid "Step Over" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +#: tools/editor/script_editor_debugger.cpp +msgid "Step Into" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +#: tools/editor/script_editor_debugger.cpp +msgid "Break" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +#: tools/editor/script_editor_debugger.cpp +msgid "Continue" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Keep Debugger Open" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Window" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Move Left" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Move Right" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Tutorials" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Open https://godotengine.org at tutorials section." +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Classes" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Search the class hierarchy." +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Search the reference documentation." +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Go to previous edited document." +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Go to next edited document." +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Create Script" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "" +"The following files are newer on disk.\n" +"What action should be taken?:" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Reload" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "Resave" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +#: tools/editor/script_editor_debugger.cpp +msgid "Debugger" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp +msgid "" +"Built-in scripts can only be edited when the scene they belong to is loaded" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp +msgid "Move Up" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp +msgid "Move Down" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +msgid "Indent Left" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +msgid "Indent Right" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +msgid "Toggle Comment" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +msgid "Complete Symbol" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +msgid "Trim Trailing Whitespace" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +msgid "Auto Indent" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +msgid "Remove All Breakpoints" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +msgid "Goto Next Breakpoint" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +msgid "Goto Previous Breakpoint" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +#: tools/editor/plugins/shader_editor_plugin.cpp +msgid "Find Previous" +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +#: tools/editor/plugins/shader_editor_plugin.cpp +msgid "Replace.." +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +msgid "Goto Function.." +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +#: tools/editor/plugins/shader_editor_plugin.cpp +msgid "Goto Line.." +msgstr "" + +#: tools/editor/plugins/script_text_editor.cpp +msgid "Contextual Help" +msgstr "" + +#: tools/editor/plugins/shader_editor_plugin.cpp +msgid "Vertex" +msgstr "" + +#: tools/editor/plugins/shader_editor_plugin.cpp +msgid "Fragment" +msgstr "" + +#: tools/editor/plugins/shader_editor_plugin.cpp +msgid "Lighting" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change Scalar Constant" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change Vec Constant" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change RGB Constant" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change Scalar Operator" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change Vec Operator" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change Vec Scalar Operator" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change RGB Operator" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Toggle Rot Only" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change Scalar Function" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change Vec Function" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change Scalar Uniform" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change Vec Uniform" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change RGB Uniform" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change Default Value" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change XForm Uniform" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change Texture Uniform" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change Cubemap Uniform" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change Comment" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Add/Remove to Color Ramp" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Add/Remove to Curve Map" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Modify Curve Map" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Change Input Name" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Connect Graph Nodes" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Disconnect Graph Nodes" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Remove Shader Graph Node" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Move Shader Graph Node" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Duplicate Graph Node(s)" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Delete Shader Graph Node(s)" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Error: Cyclic Connection Link" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Error: Missing Input Connections" +msgstr "" + +#: tools/editor/plugins/shader_graph_editor_plugin.cpp +msgid "Add Shader Graph Node" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Orthogonal" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Perspective" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Transform Aborted." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "X-Axis Transform." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Y-Axis Transform." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Z-Axis Transform." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "View Plane Transform." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Scaling to %s%%." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Rotating %s degrees." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Bottom View." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Bottom" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Top View." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Top" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Rear View." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Rear" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Front View." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Front" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Left View." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Left" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Right View." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Right" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Keying is disabled (no key inserted)." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Animation Key Inserted." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Align with view" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Environment" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Audio Listener" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Gizmos" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "XForm Dialog" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "No scene selected to instance!" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Instance at Cursor" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Could not instance scene!" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Move Mode (W)" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Rotate Mode (E)" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Scale Mode (R)" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Bottom View" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Top View" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Rear View" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Front View" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Left View" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Right View" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Switch Perspective/Orthogonal view" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Insert Animation Key" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Selection" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Align Selection With View" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Transform" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Local Coords" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Transform Dialog.." +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Use Default Light" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Use Default sRGB" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "1 Viewport" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "2 Viewports" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "2 Viewports (Alt)" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "3 Viewports" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "3 Viewports (Alt)" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "4 Viewports" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Display Normal" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Display Wireframe" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Display Overdraw" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Display Shadeless" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "View Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "View Grid" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Snap Settings" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Translate Snap:" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Rotate Snap (deg.):" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Scale Snap (%):" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Viewport Settings" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Default Light Normal:" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Ambient Light Color:" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Perspective FOV (deg.):" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "View Z-Near:" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "View Z-Far:" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Transform Change" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Translate:" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Rotate (deg.):" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Scale (ratio):" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Transform Type" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Pre" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Post" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "ERROR: Couldn't load frame resource!" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Add Frame" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Resource clipboard is empty or not a texture!" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Paste Frame" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Add Empty" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Change Animation Loop" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Change Animation FPS" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "(empty)" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Animations" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Speed (FPS):" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Animation Frames" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Insert Empty (Before)" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Insert Empty (After)" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Up" +msgstr "" + +#: tools/editor/plugins/sprite_frames_editor_plugin.cpp +msgid "Down" +msgstr "" + +#: tools/editor/plugins/style_box_editor_plugin.cpp +msgid "StyleBox Preview:" +msgstr "" + +#: tools/editor/plugins/texture_region_editor_plugin.cpp +msgid "Snap Mode:" +msgstr "" + +#: tools/editor/plugins/texture_region_editor_plugin.cpp +msgid "<None>" +msgstr "" + +#: tools/editor/plugins/texture_region_editor_plugin.cpp +msgid "Pixel Snap" +msgstr "" + +#: tools/editor/plugins/texture_region_editor_plugin.cpp +msgid "Grid Snap" +msgstr "" + +#: tools/editor/plugins/texture_region_editor_plugin.cpp +msgid "Auto Slice" +msgstr "" + +#: tools/editor/plugins/texture_region_editor_plugin.cpp +msgid "Offset:" +msgstr "" + +#: tools/editor/plugins/texture_region_editor_plugin.cpp +msgid "Step:" +msgstr "" + +#: tools/editor/plugins/texture_region_editor_plugin.cpp +msgid "Separation:" +msgstr "" + +#: tools/editor/plugins/texture_region_editor_plugin.cpp +msgid "Texture Region" +msgstr "" + +#: tools/editor/plugins/texture_region_editor_plugin.cpp +msgid "Texture Region Editor" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Can't save theme to file:" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Add All Items" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Add All" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +#: tools/editor/plugins/tile_set_editor_plugin.cpp +msgid "Remove Item" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Add Class Items" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Remove Class Items" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Create Empty Template" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Create Empty Editor Template" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "CheckBox Radio1" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "CheckBox Radio2" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Item" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Check Item" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Checked Item" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Has" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Many" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp tools/editor/project_export.cpp +msgid "Options" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Have,Many,Several,Options!" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Tab 1" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Tab 2" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Tab 3" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +#: tools/editor/project_settings.cpp tools/editor/scene_tree_editor.cpp +#: tools/editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Data Type:" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Icon" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Style" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Color" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Paint TileMap" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +#: tools/editor/scene_tree_dock.cpp +msgid "Duplicate" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Erase TileMap" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Erase selection" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Find tile" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Transpose" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Mirror X" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Mirror Y" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Bucket" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Pick Tile" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Select" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Rotate 0 degrees" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Rotate 90 degrees" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Rotate 180 degrees" +msgstr "" + +#: tools/editor/plugins/tile_map_editor_plugin.cpp +msgid "Rotate 270 degrees" +msgstr "" + +#: tools/editor/plugins/tile_set_editor_plugin.cpp +msgid "Could not find tile:" +msgstr "" + +#: tools/editor/plugins/tile_set_editor_plugin.cpp +msgid "Item name or ID:" +msgstr "" + +#: tools/editor/plugins/tile_set_editor_plugin.cpp +msgid "Create from scene?" +msgstr "" + +#: tools/editor/plugins/tile_set_editor_plugin.cpp +msgid "Merge from scene?" +msgstr "" + +#: tools/editor/plugins/tile_set_editor_plugin.cpp +msgid "Create from Scene" +msgstr "" + +#: tools/editor/plugins/tile_set_editor_plugin.cpp +msgid "Merge from Scene" +msgstr "" + +#: tools/editor/plugins/tile_set_editor_plugin.cpp +#: tools/editor/script_editor_debugger.cpp +msgid "Error" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Edit Script Options" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Please export outside the project folder!" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Error exporting project!" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Error writing the project PCK!" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "No exporter for platform '%s' yet." +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Include" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Change Image Group" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Group name can't be empty!" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Invalid character in group name!" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Group name already exists!" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Add Image Group" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Delete Image Group" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Atlas Preview" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Project Export Settings" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Target" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Export to Platform" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Resources" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Export selected resources (including dependencies)." +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Export all resources in the project." +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Export all files in the project directory." +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Export Mode:" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Resources to Export:" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Action" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "" +"Filters to export non-resource files (comma-separated, e.g.: *.json, *.txt):" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Filters to exclude from export (comma-separated, e.g.: *.json, *.txt):" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Convert text scenes to binary on export." +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Images" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Keep Original" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Compress for Disk (Lossy, WebP)" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Compress for RAM (BC/PVRTC/ETC)" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Convert Images (*.png):" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Compress for Disk (Lossy) Quality:" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Shrink All Images:" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Compress Formats:" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Image Groups" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Groups:" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Compress Disk" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Compress RAM" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Compress Mode:" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Lossy Quality:" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Atlas:" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Shrink By:" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Preview Atlas" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Image Filter:" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Images:" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Select None" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Group" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Samples" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Sample Conversion Mode: (.wav files):" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Keep" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Compress (RAM - IMA-ADPCM)" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Sampling Rate Limit (Hz):" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Trim" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Trailing Silence:" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Script" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Script Export Mode:" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Text" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Compiled" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Encrypted (Provide Key Below)" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Script Encryption Key (256-bits as hex):" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Export PCK/Zip" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Export Project PCK" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Export.." +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Project Export" +msgstr "" + +#: tools/editor/project_export.cpp +msgid "Export Preset:" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Invalid project path, the path must exist!" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Invalid project path, engine.cfg must not exist." +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Invalid project path, engine.cfg must exist." +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Imported Project" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Invalid project path (changed anything?)." +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Couldn't create engine.cfg in project path." +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "The following files failed extraction from package:" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Package Installed Successfully!" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Import Existing Project" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Project Path (Must Exist):" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Project Name:" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Create New Project" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Project Path:" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Install Project:" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Install" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Browse" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "New Game Project" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "That's a BINGO!" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Unnamed Project" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Are you sure to open more than one project?" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Are you sure to run more than one project?" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Remove project from the list? (Folder contents will not be modified)" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "" +"You are about the scan %s folders for existing Godot projects. Do you " +"confirm?" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Project Manager" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Project List" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Run" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Scan" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Select a Folder to Scan" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "New Project" +msgstr "" + +#: tools/editor/project_manager.cpp +msgid "Exit" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Key " +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Joy Button" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Joy Axis" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Mouse Button" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Invalid action (anything goes but '/' or ':')." +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Action '%s' already exists!" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Rename Input Action Event" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Add Input Action Event" +msgstr "" + +#: tools/editor/project_settings.cpp tools/editor/settings_config_dialog.cpp +msgid "Control+" +msgstr "" + +#: tools/editor/project_settings.cpp tools/editor/settings_config_dialog.cpp +msgid "Press a Key.." +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Mouse Button Index:" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Left Button" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Right Button" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Middle Button" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Wheel Up Button" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Wheel Down Button" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Button 6" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Button 7" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Button 8" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Button 9" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Joystick Axis Index:" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Joystick Button Index:" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Add Input Action" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Erase Input Action Event" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Toggle Persisting" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Error saving settings." +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Settings saved OK." +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Add Translation" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Remove Translation" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Add Remapped Path" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Resource Remap Add Remap" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Change Resource Remap Language" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Remove Resource Remap" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Remove Resource Remap Option" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Project Settings (engine.cfg)" +msgstr "" + +#: tools/editor/project_settings.cpp tools/editor/settings_config_dialog.cpp +msgid "General" +msgstr "" + +#: tools/editor/project_settings.cpp tools/editor/property_editor.cpp +msgid "Property:" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Del" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Copy To Platform.." +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Input Map" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Action:" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Device:" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Index:" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Localization" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Translations" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Translations:" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Add.." +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Remaps" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Resources:" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Remaps by Locale:" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Locale" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "AutoLoad" +msgstr "" + +#: tools/editor/project_settings.cpp +msgid "Plugins" +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Preset.." +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Ease In" +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Ease Out" +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Zero" +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Easing In-Out" +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Easing Out-In" +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "File.." +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Dir.." +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Load" +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Assign" +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "New Script" +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Error loading file: Not a resource!" +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Couldn't load image" +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Bit %d, val %d." +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "On" +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Properties:" +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Global" +msgstr "" + +#: tools/editor/property_editor.cpp +msgid "Sections:" +msgstr "" + +#: tools/editor/property_selector.cpp +msgid "Select Property" +msgstr "" + +#: tools/editor/property_selector.cpp +msgid "Select Method" +msgstr "" + +#: tools/editor/pvrtc_compress.cpp +msgid "Could not execute PVRTC tool:" +msgstr "" + +#: tools/editor/pvrtc_compress.cpp +msgid "Can't load back converted image using PVRTC tool:" +msgstr "" + +#: tools/editor/reparent_dialog.cpp tools/editor/scene_tree_dock.cpp +msgid "Reparent Node" +msgstr "" + +#: tools/editor/reparent_dialog.cpp +msgid "Reparent Location (Select new Parent):" +msgstr "" + +#: tools/editor/reparent_dialog.cpp +msgid "Keep Global Transform" +msgstr "" + +#: tools/editor/reparent_dialog.cpp tools/editor/scene_tree_dock.cpp +msgid "Reparent" +msgstr "" + +#: tools/editor/resources_dock.cpp +msgid "Create New Resource" +msgstr "" + +#: tools/editor/resources_dock.cpp +msgid "Open Resource" +msgstr "" + +#: tools/editor/resources_dock.cpp +msgid "Save Resource" +msgstr "" + +#: tools/editor/resources_dock.cpp +msgid "Resource Tools" +msgstr "" + +#: tools/editor/resources_dock.cpp +msgid "Make Local" +msgstr "" + +#: tools/editor/run_settings_dialog.cpp +msgid "Run Mode:" +msgstr "" + +#: tools/editor/run_settings_dialog.cpp +msgid "Current Scene" +msgstr "" + +#: tools/editor/run_settings_dialog.cpp +msgid "Main Scene" +msgstr "" + +#: tools/editor/run_settings_dialog.cpp +msgid "Main Scene Arguments:" +msgstr "" + +#: tools/editor/run_settings_dialog.cpp +msgid "Scene Run Settings" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "OK :(" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "No parent to instance a child at." +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "No parent to instance the scenes at." +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Error loading scene from %s" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Error instancing scene from %s" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Ok" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "" +"Cannot instance the scene '%s' because the current scene exists within one " +"of its nodes." +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Instance Scene(s)" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "This operation can't be done on the tree root." +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Move Node In Parent" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Move Nodes In Parent" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Duplicate Node(s)" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Delete Node(s)?" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "This operation can't be done without a scene." +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "This operation requires a single selected node." +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "This operation can't be done on instanced scenes." +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Save New Scene As.." +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Makes Sense!" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Can't operate on nodes from a foreign scene!" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Can't operate on nodes the current scene inherits from!" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Remove Node(s)" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Create Node" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "" +"Couldn't save new scene. Likely dependencies (instances) couldn't be " +"satisfied." +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Error saving scene." +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Error duplicating scene to save it." +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Edit Groups" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Edit Connections" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Delete Node(s)" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Add Child Node" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Instance Child Scene" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Change Type" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Add Script" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Merge From Scene" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Save Branch as Scene" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Delete (No Confirm)" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Add/Create a New Node" +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "" +"Instance a scene file as a Node. Creates an inherited scene if no root node " +"exists." +msgstr "" + +#: tools/editor/scene_tree_dock.cpp +msgid "Create a new script for the selected node." +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "" +"This item cannot be made visible because the parent is hidden. Unhide the " +"parent first." +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "Toggle Spatial Visible" +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "Toggle CanvasItem Visible" +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "Invalid node name, the following characters are not allowed:" +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "Rename Node" +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "Scene Tree (Nodes):" +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "Editable Children" +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "Load As Placeholder" +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "Discard Instancing" +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "Clear Inheritance" +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "Clear Inheritance? (No Undo!)" +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "Clear!" +msgstr "" + +#: tools/editor/scene_tree_editor.cpp +msgid "Select a Node" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Invalid parent class name" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Valid chars:" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Invalid class name" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Valid name" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "N/A" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Class name is invalid!" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Parent class name is invalid!" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Invalid path!" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Could not create script in filesystem." +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Path is empty" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Path is not local" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Invalid base path" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "File exists" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Invalid extension" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Valid path" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Class Name:" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Built-In Script" +msgstr "" + +#: tools/editor/script_create_dialog.cpp +msgid "Create Node Script" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Bytes:" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Warning" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Error:" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Source:" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Function:" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Errors" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Child Process Connected" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Inspect Previous Instance" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Inspect Next Instance" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Stack Frames" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Variable" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Errors:" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Stack Trace (if applicable):" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Remote Inspector" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Live Scene Tree:" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Remote Object Properties: " +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Profiler" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Monitor" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Value" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Monitors" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "List of Video Memory Usage by Resource:" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Total:" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Video Mem" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Resource Path" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Type" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Usage" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Misc" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Clicked Control:" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Clicked Control Type:" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Live Edit Root:" +msgstr "" + +#: tools/editor/script_editor_debugger.cpp +msgid "Set From Tree" +msgstr "" + +#: tools/editor/settings_config_dialog.cpp +msgid "Shortcuts" +msgstr "" + +#: tools/editor/spatial_editor_gizmos.cpp +msgid "Change Light Radius" +msgstr "" + +#: tools/editor/spatial_editor_gizmos.cpp +msgid "Change Camera FOV" +msgstr "" + +#: tools/editor/spatial_editor_gizmos.cpp +msgid "Change Camera Size" +msgstr "" + +#: tools/editor/spatial_editor_gizmos.cpp +msgid "Change Sphere Shape Radius" +msgstr "" + +#: tools/editor/spatial_editor_gizmos.cpp +msgid "Change Box Shape Extents" +msgstr "" + +#: tools/editor/spatial_editor_gizmos.cpp +msgid "Change Capsule Shape Radius" +msgstr "" + +#: tools/editor/spatial_editor_gizmos.cpp +msgid "Change Capsule Shape Height" +msgstr "" + +#: tools/editor/spatial_editor_gizmos.cpp +msgid "Change Ray Shape Length" +msgstr "" + +#: tools/editor/spatial_editor_gizmos.cpp +msgid "Change Notifier Extents" +msgstr "" diff --git a/tools/translations/it.po b/tools/translations/it.po index 6f268298a7..1fa6a89605 100644 --- a/tools/translations/it.po +++ b/tools/translations/it.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2016-08-29 11:05+0000\n" +"PO-Revision-Date: 2016-09-10 22:09+0000\n" "Last-Translator: Dario Bonfanti <bonfi.96@hotmail.it>\n" "Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/" "godot/it/>\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2.8-dev\n" +"X-Generator: Weblate 2.8\n" #: modules/gdscript/gd_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -36,6 +36,12 @@ msgid "step argument is zero!" msgstr "step argument è zero!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "Non è uno script con un istanza" @@ -165,37 +171,45 @@ msgid "Editing Signal:" msgstr "Modifica Segnale:" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "Cambia Tipo" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Aggiungi Nodo" #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"Mantieni premuto Meta per rilasciare un Getter. Mantieni premuto Shift per " +"rilasciare una firma generica." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"Mantieni premuto Control per rilasciare un Getter. Mantieni premuto Shift " +"per rilasciare una firma generica." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a simple reference to the node." -msgstr "" +msgstr "Mantieni premuto Meta per rilasciare un riferimento semplice al nodo." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a simple reference to the node." -msgstr "" +msgstr "Mantieni premuto Ctrl per rilasciare un riferimento semplice al nodo." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a Variable Setter." -msgstr "" +msgstr "Mantieni premuto Meta per rilasciare un Setter Variabile." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Variable Setter." -msgstr "" +msgstr "Mantieni premuto Ctrl per rilasciare un Setter Variabile." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Preload Node" -msgstr "Aggiungi Nodo Figlio" +msgstr "Aggiungi Nodo Preload" #: modules/visual_script/visual_script_editor.cpp msgid "Add Node(s) From Tree" @@ -210,6 +224,47 @@ msgid "Add Setter Property" msgstr "Aggiungi Proprietà Setter" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "Copia Animazione" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Switch" +msgstr "Pitch" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "Ritorna:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "Chiama" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Get" +msgstr "Set" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "Set" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -269,24 +324,20 @@ msgid "Toggle Breakpoint" msgstr "Abilita Breakpoint" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Find Node Type" msgstr "Trova Tipo Nodo" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Copy Nodes" -msgstr "Copia Posa" +msgstr "Copia Nodi" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Cut Nodes" -msgstr "Crea Nodo" +msgstr "Taglia Nodi" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Paste Nodes" -msgstr "Incolla Posa" +msgstr "Incolla Nodi" #: modules/visual_script/visual_script_flow_control.cpp msgid "Input type not iterable: " @@ -346,6 +397,90 @@ msgstr "" "Valore di return invalido da _step(), deve esere intero (seq out), oppure " "stringa (errore)." +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Error creating the signature object." +msgstr "Errore di scrittura del PCK del progetto!" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "Nome Invalido." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "Dimensione font Invalida." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid publisher GUID." +msgstr "Percorso di base invalido" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid background color." +msgstr "Sorgente font personalizzato invalido." + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -542,6 +677,13 @@ msgstr "" "NavigationMeshInstance deve essere un figlio o nipote di un nodo Navigation. " "Fornisce solamente dati per la navigazione." +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "" +"La proprietà path deve puntare a un nodo Particles2D valido per poter " +"funzionare." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1193,10 +1335,6 @@ msgid "Method List For '%s':" msgstr "Lista Metodi Per '%s':" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "Chiama" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "Lista Metodi:" @@ -1315,6 +1453,12 @@ msgid "Method in target Node must be specified!" msgstr "Il Metodo nel nodo di target deve essere specificato!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "Connetti A Nodo:" @@ -1390,6 +1534,15 @@ msgstr "Segnali" msgid "Create New" msgstr "Crea Nuovo" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "Preferiti:" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "Recenti:" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1672,14 +1825,6 @@ msgstr "Sposta Preferito Su" msgid "Move Favorite Down" msgstr "Sposta Preferito Giù" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "Preferiti:" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "Recenti:" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "Anteprima:" @@ -2092,14 +2237,6 @@ msgid "Go to previously opened scene." msgstr "Vai alla scena precedentemente aperta." #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "Modalità Fullscreen" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "Modalità Senza Distrazioni" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "Scheda successiva" @@ -2185,6 +2322,10 @@ msgid "Quit to Project List" msgstr "Esci alla Lista Progetti" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "Modalità Senza Distrazioni" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "Importa asset nel progetto." @@ -2362,6 +2503,11 @@ msgid "Editor Layout" msgstr "Layout dell'Editor" #: tools/editor/editor_node.cpp +#, fuzzy +msgid "Toggle Fullscreen" +msgstr "Modalità Fullscreen" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "Installa Template di Esportazione" @@ -2386,6 +2532,10 @@ msgid "Update Changes" msgstr "Aggiorna Cambiamenti" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "Inspector" @@ -2425,6 +2575,10 @@ msgstr "Proprietà oggetto." msgid "FileSystem" msgstr "FileSystem" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "Nodo" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "Output" @@ -3266,10 +3420,6 @@ msgid "MultiNode Set" msgstr "MultiNode Set" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "Nodo" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "Gruppi" @@ -3814,6 +3964,11 @@ msgid "Clear Bones" msgstr "Elimina Ossa" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy +msgid "Show Bones" +msgstr "Crea Ossa" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "Crea Catena IK" @@ -4554,6 +4709,11 @@ msgid "Close Docs" msgstr "Chiudi Documentazione" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Chiudi" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4665,6 +4825,11 @@ msgstr "" "Gli script built-in possono essere modificati solamente quando la scena a " "cui appartengono è caricata" +#: tools/editor/plugins/script_text_editor.cpp +#, fuzzy +msgid "Pick Color" +msgstr "Colore" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "Sposta Su" @@ -5041,6 +5206,11 @@ msgid "Insert Animation Key" msgstr "Inserisci Key Animazione" #: tools/editor/plugins/spatial_editor_plugin.cpp +#, fuzzy +msgid "Focus Origin" +msgstr "Visualizza Origine" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "Centra a Selezione" @@ -5306,6 +5476,11 @@ msgid "Remove Item" msgstr "Rimuovi Elemento" #: tools/editor/plugins/theme_editor_plugin.cpp +#, fuzzy +msgid "Theme" +msgstr "Salva Tema" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "Aggiungi Elementi di Classe" @@ -6123,6 +6298,11 @@ msgid "Assign" msgstr "Assegna" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "Script successivo" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "Errore caricamento file: Non è una risorsa!" @@ -6139,10 +6319,6 @@ msgid "On" msgstr "On" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "Set" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "Proprietà:" @@ -6155,14 +6331,12 @@ msgid "Sections:" msgstr "Sezioni:" #: tools/editor/property_selector.cpp -#, fuzzy msgid "Select Property" -msgstr "Selezione Punti" +msgstr "Seleziona Proprietà" #: tools/editor/property_selector.cpp -#, fuzzy msgid "Select Method" -msgstr "Modalità di Selezione" +msgstr "Seleziona Metodo" #: tools/editor/pvrtc_compress.cpp msgid "Could not execute PVRTC tool:" diff --git a/tools/translations/ja.po b/tools/translations/ja.po index 1f0c073082..25003026c1 100644 --- a/tools/translations/ja.po +++ b/tools/translations/ja.po @@ -34,6 +34,12 @@ msgid "step argument is zero!" msgstr "ステップ引数はゼロです!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "インスタンスを使用していないスクリプトです" @@ -167,6 +173,10 @@ msgid "Editing Signal:" msgstr "信号を接続:" #: modules/visual_script/visual_script_editor.cpp +msgid "Change Expression" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "" @@ -212,6 +222,45 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "遷移" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "戻り値:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "呼び出し" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -343,6 +392,87 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "無効なフォント サイズです。" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "無効なフォント サイズです。" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -533,6 +663,13 @@ msgstr "" "NavigationMeshInstance は、ナビゲーションノードの子や孫である必要があります。" "これはナビゲーションデータのみ提供します。" +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "" +"Path プロパティは、動作するように有効な Particles2D ノードを示す必要がありま" +"す。" + #: scene/3d/scenario_fx.cpp #, fuzzy msgid "" @@ -1184,10 +1321,6 @@ msgid "Method List For '%s':" msgstr "'%s' のメソッド一覧:" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "呼び出し" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "メソッド一覧:" @@ -1306,6 +1439,12 @@ msgid "Method in target Node must be specified!" msgstr "対象となるノードのメソッドを指定する必要があります!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "ノードに接続します。" @@ -1382,6 +1521,15 @@ msgstr "" msgid "Create New" msgstr "" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1653,14 +1801,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -2066,14 +2206,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2160,6 +2292,10 @@ msgid "Quit to Project List" msgstr "終了してプロジェクトリストを開く" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2318,6 +2454,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2342,6 +2482,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2381,6 +2525,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3210,10 +3358,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3755,6 +3899,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4494,6 +4642,11 @@ msgid "Close Docs" msgstr "閉じる" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "閉じる" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4601,6 +4754,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4977,6 +5134,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5242,6 +5403,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -6053,6 +6218,10 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +msgid "New Script" +msgstr "" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -6069,10 +6238,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/ko.po b/tools/translations/ko.po index 72d9fc1167..a4d24d8b52 100644 --- a/tools/translations/ko.po +++ b/tools/translations/ko.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2016-08-17 10:07+0000\n" +"PO-Revision-Date: 2016-09-26 13:04+0000\n" "Last-Translator: 박한얼 <volzhs@gmail.com>\n" "Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/" "godot/ko/>\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 2.8-dev\n" +"X-Generator: Weblate 2.9-dev\n" #: modules/gdscript/gd_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -35,6 +35,12 @@ msgid "step argument is zero!" msgstr "스텝 인자가 제로입니다!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "스크립트의 인스턴스가 아님" @@ -159,6 +165,11 @@ msgid "Editing Signal:" msgstr "시그널 편집:" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "타입 변경" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "노드 추가" @@ -187,9 +198,8 @@ msgid "Hold Ctrl to drop a Variable Setter." msgstr "" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Preload Node" -msgstr "자식 노드 추가" +msgstr "Preload 노드 추가" #: modules/visual_script/visual_script_editor.cpp msgid "Add Node(s) From Tree" @@ -204,6 +214,47 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "애니메이션 복사" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Switch" +msgstr "피치" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "리턴:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "호출" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Get" +msgstr "설정" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "설정" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -263,24 +314,20 @@ msgid "Toggle Breakpoint" msgstr "중단점 토글" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Find Node Type" msgstr "노드 타입 찾기" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Copy Nodes" -msgstr "포즈 복사" +msgstr "노드 복사" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Cut Nodes" -msgstr "노드 생성" +msgstr "노드 잘라내기" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Paste Nodes" -msgstr "포즈 붙여넣기" +msgstr "노드 붙여넣기" #: modules/visual_script/visual_script_flow_control.cpp msgid "Input type not iterable: " @@ -336,6 +383,90 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Error creating the signature object." +msgstr "프로젝트 PCK 작성중 에러!" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "유효하지 않은 이름." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "유요하지 않은 폰트 사이즈." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid publisher GUID." +msgstr "기본 경로가 유요하지 않음" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid background color." +msgstr "사용자 지정 폰트 소스가 유효하지 않습니다." + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -516,6 +647,11 @@ msgstr "" "NavigationMeshInstance은 Navigation 노드의 하위에 있어야 합니다. 이것은 네비" "게이션 데이타만을 제공합니다." +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "Path 속성은 유효한 Particles2D 노드를 가리켜야 합니다." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1163,10 +1299,6 @@ msgid "Method List For '%s':" msgstr "'%s' 함수 목록:" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "호출" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "함수 목록:" @@ -1285,6 +1417,12 @@ msgid "Method in target Node must be specified!" msgstr "대상 노드의 함수를 명시해야합니다!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "연결할 노드:" @@ -1360,6 +1498,15 @@ msgstr "시그널" msgid "Create New" msgstr "새로 만들기" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "즐겨찾기:" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "최근:" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1637,14 +1784,6 @@ msgstr "즐겨찾기 위로 이동" msgid "Move Favorite Down" msgstr "즐겨찾기 아래로 이동" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "즐겨찾기:" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "최근:" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "미리보기:" @@ -2050,14 +2189,6 @@ msgid "Go to previously opened scene." msgstr "이전에 열었던 씬으로 가기." #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "전체화면 모드" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "초집중 모드" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "다음 탭" @@ -2143,6 +2274,10 @@ msgid "Quit to Project List" msgstr "종료하고 프로젝트 목록으로 돌아가기" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "초집중 모드" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "프로젝트로 에셋 가져오기." @@ -2321,6 +2456,11 @@ msgid "Editor Layout" msgstr "에디터 레이아웃" #: tools/editor/editor_node.cpp +#, fuzzy +msgid "Toggle Fullscreen" +msgstr "전체화면 모드" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "내보내기 템플릿 설치" @@ -2345,6 +2485,10 @@ msgid "Update Changes" msgstr "변경사항만 갱신" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "인스펙터" @@ -2384,6 +2528,10 @@ msgstr "오브젝트 속성." msgid "FileSystem" msgstr "파일 시스템" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "노드" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "출력" @@ -3220,10 +3368,6 @@ msgid "MultiNode Set" msgstr "다중 노드 설정" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "노드" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "그룹" @@ -3765,6 +3909,11 @@ msgid "Clear Bones" msgstr "Bones 없애기" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy +msgid "Show Bones" +msgstr "Bones 만들기" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "IK 체인 만들기" @@ -4503,6 +4652,11 @@ msgid "Close Docs" msgstr "문서 닫기" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "닫기" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4612,6 +4766,11 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "내장 스크립트는 종속된 씬이 열린 상태에서만 편집이 가능합니다" +#: tools/editor/plugins/script_text_editor.cpp +#, fuzzy +msgid "Pick Color" +msgstr "색깔" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "위로 이동" @@ -4988,6 +5147,11 @@ msgid "Insert Animation Key" msgstr "애니메이션 키 삽입" #: tools/editor/plugins/spatial_editor_plugin.cpp +#, fuzzy +msgid "Focus Origin" +msgstr "원점 보기" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "선택 포커스" @@ -5253,6 +5417,11 @@ msgid "Remove Item" msgstr "아이템 삭제" #: tools/editor/plugins/theme_editor_plugin.cpp +#, fuzzy +msgid "Theme" +msgstr "테마 저장" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "클래스 아이템 추가" @@ -6065,6 +6234,11 @@ msgid "Assign" msgstr "할당" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "다음 스크립트" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "파일 로드 에러: 리소스가 아닙니다!" @@ -6081,10 +6255,6 @@ msgid "On" msgstr "사용" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "설정" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "속성:" @@ -6097,14 +6267,12 @@ msgid "Sections:" msgstr "부문:" #: tools/editor/property_selector.cpp -#, fuzzy msgid "Select Property" -msgstr "포인트 선택" +msgstr "속성 선택" #: tools/editor/property_selector.cpp -#, fuzzy msgid "Select Method" -msgstr "선택 모드" +msgstr "메소드 선택" #: tools/editor/pvrtc_compress.cpp msgid "Could not execute PVRTC tool:" diff --git a/tools/translations/nb.po b/tools/translations/nb.po index 41903096cf..d8d1a2771b 100644 --- a/tools/translations/nb.po +++ b/tools/translations/nb.po @@ -32,6 +32,12 @@ msgid "step argument is zero!" msgstr "" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "" @@ -154,6 +160,10 @@ msgid "Editing Signal:" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Change Expression" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "" @@ -198,6 +208,43 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Condition" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -326,6 +373,85 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid unique name." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid product GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -468,6 +594,10 @@ msgid "" "It only provides navigation data." msgstr "" +#: scene/3d/remote_transform.cpp +msgid "Path property must point to a valid Spatial node to work." +msgstr "" + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1105,10 +1235,6 @@ msgid "Method List For '%s':" msgstr "" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "" @@ -1227,6 +1353,12 @@ msgid "Method in target Node must be specified!" msgstr "" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "" @@ -1302,6 +1434,15 @@ msgstr "" msgid "Create New" msgstr "" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1571,14 +1712,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -1973,14 +2106,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2066,6 +2191,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2224,6 +2353,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2248,6 +2381,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2287,6 +2424,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3116,10 +3257,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3659,6 +3796,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4397,6 +4538,10 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +msgid "Close All" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4504,6 +4649,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4880,6 +5029,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5145,6 +5298,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -5956,6 +6113,10 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +msgid "New Script" +msgstr "" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -5972,10 +6133,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/pl.po b/tools/translations/pl.po index 23966ce78c..78b1964fad 100644 --- a/tools/translations/pl.po +++ b/tools/translations/pl.po @@ -39,6 +39,12 @@ msgid "step argument is zero!" msgstr "argument kroku jest zerowy!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "Nie jest to skrypt z instancją" @@ -164,6 +170,11 @@ msgid "Editing Signal:" msgstr "Edytuj sygnał:" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "Zmień typ" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Dodaj węzeł" @@ -209,6 +220,47 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "Skopiuj animacje" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Switch" +msgstr "Wysokość" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "Zwraca:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "Wywołanie" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Get" +msgstr "Ustaw" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "Ustaw" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -342,6 +394,90 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Error creating the signature object." +msgstr "Błąd przy eksporcie projektu!" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "Niewłaściwa nazwa." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "Niepoprawny rozmiar fonta." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid publisher GUID." +msgstr "Niepoprawna ścieżka bazowa" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid background color." +msgstr "Nie rozpoznano typu czcionki." + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -529,6 +665,12 @@ msgstr "" "NavigationMeshInstance musi być dzieckiem lub wnukiem węzła typu Navigation. " "Udostępnia on tylko dane nawigacyjne." +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "" +"Żeby zadziałało, pole Path musi wskazywać na istniejący węzeł Particles2D." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1181,10 +1323,6 @@ msgid "Method List For '%s':" msgstr "Lista metod '%s':" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "Wywołanie" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "Lista metod:" @@ -1303,6 +1441,12 @@ msgid "Method in target Node must be specified!" msgstr "Wybierz metodę w wybranym węźle!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "Podłączanie Do Węzła:" @@ -1379,6 +1523,15 @@ msgstr "Sygnały" msgid "Create New" msgstr "Utwórz nowy" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "Ulubione:" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "Ostatnie:" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1651,14 +1804,6 @@ msgstr "Przesuń Ulubiony w górę" msgid "Move Favorite Down" msgstr "Przesuń Ulubiony w dół" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "Ulubione:" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "Ostatnie:" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "Podgląd:" @@ -2070,14 +2215,6 @@ msgid "Go to previously opened scene." msgstr "Idź do poprzednio otwartej sceny." #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "Pełny ekran" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "Tryb bez rozproszeń" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "Następna zakładka" @@ -2163,6 +2300,10 @@ msgid "Quit to Project List" msgstr "Wyjdź do Listy Projektów" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "Tryb bez rozproszeń" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "Importuj zasoby do projektu." @@ -2337,6 +2478,11 @@ msgid "Editor Layout" msgstr "Layout edytora" #: tools/editor/editor_node.cpp +#, fuzzy +msgid "Toggle Fullscreen" +msgstr "Pełny ekran" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "Zainstaluj Szablony Eksportu" @@ -2361,6 +2507,10 @@ msgid "Update Changes" msgstr "Odśwież Zmiany" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "Inspektor" @@ -2400,6 +2550,10 @@ msgstr "Właściwości obiektu." msgid "FileSystem" msgstr "System plików" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "Węzeł" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "Konsola" @@ -3241,10 +3395,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "Węzeł" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "Grupy" @@ -3787,6 +3937,11 @@ msgid "Clear Bones" msgstr "Wyczyść Kości" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy +msgid "Show Bones" +msgstr "Utwórz Kości" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "Utwórz Łańcuch IK" @@ -4525,6 +4680,11 @@ msgid "Close Docs" msgstr "Zamknij pliki pomocy" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Zamknij" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4632,6 +4792,11 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +#, fuzzy +msgid "Pick Color" +msgstr "Kolor" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "Przesuń w górę" @@ -5008,6 +5173,10 @@ msgid "Insert Animation Key" msgstr "Wstaw klucz animacji" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5273,6 +5442,11 @@ msgid "Remove Item" msgstr "Usuń element" #: tools/editor/plugins/theme_editor_plugin.cpp +#, fuzzy +msgid "Theme" +msgstr "Zapisz motyw" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -6084,6 +6258,11 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "Następny skrypt" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "Błąd wczytania pliku: Brak zasobu!" @@ -6100,10 +6279,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "Ustaw" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "Właściwości:" diff --git a/tools/translations/pt_BR.po b/tools/translations/pt_BR.po index 0b80ed2b0e..de8b9920a5 100644 --- a/tools/translations/pt_BR.po +++ b/tools/translations/pt_BR.po @@ -5,13 +5,14 @@ # António Sarmento <antonio.luis.sarmento@gmail.com>, 2016. # George Marques <george@gmarqu.es>, 2016. # Joaquim Ferreira <joaquimferreira1996@bol.com.br>, 2016. +# Mailson Silva Marins <mailsons335@gmail.com>, 2016. # msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: 2016-05-30\n" -"PO-Revision-Date: 2016-08-11 15:38+0000\n" -"Last-Translator: António Sarmento <antonio.luis.sarmento@gmail.com>\n" +"PO-Revision-Date: 2016-09-02 21:07+0000\n" +"Last-Translator: Mailson Silva Marins <mailsons335@gmail.com>\n" "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/" "godot-engine/godot/pt_BR/>\n" "Language: pt_BR\n" @@ -19,12 +20,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 2.8-dev\n" +"X-Generator: Weblate 2.8\n" #: modules/gdscript/gd_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Invalid type argument to convert(), use TYPE_* constants." -msgstr "Argumento de tipo inválido para convert(), use constantes TYPE_*." +msgstr "Argumento de tipo inválido para converter(), use constantes TYPE_*." #: modules/gdscript/gd_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -36,6 +37,12 @@ msgid "step argument is zero!" msgstr "o argumento step é zero!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "Não é um script com uma instância" @@ -120,9 +127,8 @@ msgid "Rename Function" msgstr "Renomear Função" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Rename Variable" -msgstr "Renomear Amostra" +msgstr "renomeie variável" #: modules/visual_script/visual_script_editor.cpp msgid "Rename Signal" @@ -161,6 +167,11 @@ msgid "Editing Signal:" msgstr "Editando Sinal:" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "Alterar Tipo" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Adicionar Nó" @@ -207,6 +218,47 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "Copiar Animação" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Switch" +msgstr "Pitch" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "Retornar:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "Chamar" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Get" +msgstr "Definir" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "Definir" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -216,9 +268,8 @@ msgid "Edit" msgstr "Editar" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Base Type:" -msgstr "Tipo de Dados:" +msgstr "Tipo de Base:" #: modules/visual_script/visual_script_editor.cpp tools/editor/editor_help.cpp msgid "Members:" @@ -343,6 +394,90 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Error creating the signature object." +msgstr "Erro ao escrever o PCK do projeto!" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "Nome Inválido." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "Tamanho de fonte inválido." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid publisher GUID." +msgstr "Caminho base inválido" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid background color." +msgstr "Origem personalizada da fonte inválida." + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -531,6 +666,11 @@ msgstr "" "NavigationMeshInstance deve ser filho ou neto de um nó Navigation. Ele " "apenas fornece dados de navegação." +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "A propriedade Caminho deve apontar a um nó Particles2D para funcionar." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1181,10 +1321,6 @@ msgid "Method List For '%s':" msgstr "Lista de Métodos para \"%s\":" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "Chamar" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "Lista de Métodos:" @@ -1303,6 +1439,12 @@ msgid "Method in target Node must be specified!" msgstr "O método no Nó destino precisa ser especificado!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "Conectar ao Nó:" @@ -1378,6 +1520,15 @@ msgstr "Sinais" msgid "Create New" msgstr "Criar Novo" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "Favoritos:" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "Recente:" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1657,14 +1808,6 @@ msgstr "Mover Favorito Acima" msgid "Move Favorite Down" msgstr "Mover Favorito Abaixo" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "Favoritos:" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "Recente:" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "Previsualização:" @@ -2074,14 +2217,6 @@ msgid "Go to previously opened scene." msgstr "Ir para cena aberta anteriormente." #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "Modo Tela-Cheia" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "Modo Sem Distrações" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "Próxima guia" @@ -2167,6 +2302,10 @@ msgid "Quit to Project List" msgstr "Sair para a Lista de Projetos" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "Modo Sem Distrações" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "Importar assets ao projeto." @@ -2344,6 +2483,11 @@ msgid "Editor Layout" msgstr "Layout do Editor" #: tools/editor/editor_node.cpp +#, fuzzy +msgid "Toggle Fullscreen" +msgstr "Modo Tela-Cheia" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "Instalar Models de Exportação" @@ -2368,6 +2512,10 @@ msgid "Update Changes" msgstr "Atualizar nas Mudanças" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "Inspetor" @@ -2407,6 +2555,10 @@ msgstr "Propriedades do objeto." msgid "FileSystem" msgstr "Arquivos" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "Nó" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "Saída" @@ -3246,10 +3398,6 @@ msgid "MultiNode Set" msgstr "Múltiplos Nós definidos" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "Nó" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "Grupos" @@ -3799,6 +3947,11 @@ msgid "Clear Bones" msgstr "Limpar Ossos" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy +msgid "Show Bones" +msgstr "Fazer Ossos" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "Fazer Cadeia de IK" @@ -4538,6 +4691,11 @@ msgid "Close Docs" msgstr "Fechar Docs" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Fechar" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4649,6 +4807,11 @@ msgstr "" "Scripts embutidos só podem ser editados quando a cena a qual pertencem está " "carregada" +#: tools/editor/plugins/script_text_editor.cpp +#, fuzzy +msgid "Pick Color" +msgstr "Cor" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "Mover para Cima" @@ -5025,6 +5188,11 @@ msgid "Insert Animation Key" msgstr "Inserir Chanve de Animação" #: tools/editor/plugins/spatial_editor_plugin.cpp +#, fuzzy +msgid "Focus Origin" +msgstr "Ver Origem" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "Focar Seleção" @@ -5290,6 +5458,11 @@ msgid "Remove Item" msgstr "Remover Item" #: tools/editor/plugins/theme_editor_plugin.cpp +#, fuzzy +msgid "Theme" +msgstr "Salvar Tema" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "Adicionar Itens de Classe" @@ -6108,6 +6281,11 @@ msgid "Assign" msgstr "Atribuir" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "Próximo Script" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "Erro ao carregar arquivo: Não é um recurso!" @@ -6124,10 +6302,6 @@ msgid "On" msgstr "Ativo" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "Definir" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "Propriedades:" diff --git a/tools/translations/pt_PT.po b/tools/translations/pt_PT.po index 21792d3857..21727ce186 100644 --- a/tools/translations/pt_PT.po +++ b/tools/translations/pt_PT.po @@ -33,6 +33,12 @@ msgid "step argument is zero!" msgstr "o argumento \"step\" é zero!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "Não é um script com uma instância" @@ -164,6 +170,10 @@ msgid "Editing Signal:" msgstr "A editar Sinal:" #: modules/visual_script/visual_script_editor.cpp +msgid "Change Expression" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Adicionar Nó" @@ -209,6 +219,43 @@ msgid "Add Setter Property" msgstr "Adicionar propriedade Setter" #: modules/visual_script/visual_script_editor.cpp +msgid "Condition" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -338,6 +385,86 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "Nome de índice propriedade inválido." + +#: platform/winrt/export/export.cpp +msgid "Invalid product GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -480,6 +607,10 @@ msgid "" "It only provides navigation data." msgstr "" +#: scene/3d/remote_transform.cpp +msgid "Path property must point to a valid Spatial node to work." +msgstr "" + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1117,10 +1248,6 @@ msgid "Method List For '%s':" msgstr "" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "" @@ -1239,6 +1366,12 @@ msgid "Method in target Node must be specified!" msgstr "" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "" @@ -1314,6 +1447,15 @@ msgstr "" msgid "Create New" msgstr "" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1583,14 +1725,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -1985,14 +2119,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2078,6 +2204,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2236,6 +2366,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2260,6 +2394,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2299,6 +2437,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3128,10 +3270,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3671,6 +3809,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4409,6 +4551,11 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Fechar" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4516,6 +4663,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4892,6 +5043,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5157,6 +5312,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -5968,6 +6127,10 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +msgid "New Script" +msgstr "" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -5984,10 +6147,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/ro.po b/tools/translations/ro.po index 8e0dc574be..e4782fec64 100644 --- a/tools/translations/ro.po +++ b/tools/translations/ro.po @@ -26,6 +26,12 @@ msgid "step argument is zero!" msgstr "" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "" @@ -148,6 +154,10 @@ msgid "Editing Signal:" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Change Expression" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "" @@ -192,6 +202,43 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Condition" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -320,6 +367,85 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid unique name." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid product GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -462,6 +588,10 @@ msgid "" "It only provides navigation data." msgstr "" +#: scene/3d/remote_transform.cpp +msgid "Path property must point to a valid Spatial node to work." +msgstr "" + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1099,10 +1229,6 @@ msgid "Method List For '%s':" msgstr "" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "" @@ -1221,6 +1347,12 @@ msgid "Method in target Node must be specified!" msgstr "" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "" @@ -1296,6 +1428,15 @@ msgstr "" msgid "Create New" msgstr "" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1565,14 +1706,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -1967,14 +2100,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2060,6 +2185,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2218,6 +2347,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2242,6 +2375,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2281,6 +2418,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3110,10 +3251,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3653,6 +3790,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4391,6 +4532,10 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +msgid "Close All" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4498,6 +4643,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4874,6 +5023,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5139,6 +5292,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -5950,6 +6107,10 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +msgid "New Script" +msgstr "" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -5966,10 +6127,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/ru.po b/tools/translations/ru.po index 7b047d9a1e..b8288d07a4 100644 --- a/tools/translations/ru.po +++ b/tools/translations/ru.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2016-08-17 20:35+0000\n" +"PO-Revision-Date: 2016-09-14 21:55+0000\n" "Last-Translator: DimOkGamer <dimokgamer@gmail.com>\n" "Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/" "godot/ru/>\n" @@ -20,7 +20,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 2.8-dev\n" +"X-Generator: Weblate 2.8\n" #: modules/gdscript/gd_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -37,6 +37,12 @@ msgid "step argument is zero!" msgstr "Аргумент шага равен нулю!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "Скрипт без экземпляра" @@ -166,37 +172,45 @@ msgid "Editing Signal:" msgstr "Редактирование сигнала:" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Change Expression" +msgstr "Изменить тип" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Добавить узел" #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"Зажмите Meta, чтобы добавить Getter. Зажмите Shift, чтобы добавить " +"универсальную подпись." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"Зажмите Ctrl, чтобы добавить Getter. Зажмите Shift, чтобы добавить " +"универсальную подпись." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a simple reference to the node." -msgstr "" +msgstr "Зажмите Meta, чтобы добавить простую ссылку на узел." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a simple reference to the node." -msgstr "" +msgstr "Зажмите Ctrl, чтобы добавить простую ссылку на узел." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Meta to drop a Variable Setter." -msgstr "" +msgstr "Зажмите Meta, чтобы добавить Variable Setter." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Variable Setter." -msgstr "" +msgstr "Зажмите Ctrl, чтобы добавить Variable Setter." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Preload Node" -msgstr "Добавить дочерний узел" +msgstr "Добавить предзагрузочный узел" #: modules/visual_script/visual_script_editor.cpp msgid "Add Node(s) From Tree" @@ -211,6 +225,47 @@ msgid "Add Setter Property" msgstr "Добавить устанавливающее свойство" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "Копировать анимацию" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Switch" +msgstr "Высота" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "Возвращение:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "Вызов" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Get" +msgstr "Задан" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "Задан" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -270,24 +325,20 @@ msgid "Toggle Breakpoint" msgstr "Точка остановки" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Find Node Type" msgstr "Найти тип узла" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Copy Nodes" -msgstr "Копировать позу" +msgstr "Копировать узлы" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Cut Nodes" -msgstr "Создать узел" +msgstr "Вырезать узлы" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Paste Nodes" -msgstr "Вставить позу" +msgstr "Вставить узлы" #: modules/visual_script/visual_script_flow_control.cpp msgid "Input type not iterable: " @@ -346,6 +397,90 @@ msgstr "" "Недопустимое значение, возвращаемое _step(), должно быть целое число(seq " "out) или строка (error)." +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Error creating the signature object." +msgstr "Ошибка записи PCK файла!" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "Недопустимое имя." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "Недопустимый размер шрифта." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid publisher GUID." +msgstr "Недопустимый базовый путь" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid background color." +msgstr "Недопустимый шрифт пользовательского источника." + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -537,6 +672,13 @@ msgstr "" "NavigationMeshInstance должен быть дочерним или под-дочерним узлом " "Navigation. Он предоставляет только навигационные данные." +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "" +"Для корректной работы свойство Path должно указывать на действующий узел " +"Particles2D." + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1188,10 +1330,6 @@ msgid "Method List For '%s':" msgstr "Список способ для '%s':" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "Вызов" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "Список методов:" @@ -1310,6 +1448,12 @@ msgid "Method in target Node must be specified!" msgstr "Метод должен быть указан в целевом Узле!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "Присоединить к узлу:" @@ -1385,6 +1529,15 @@ msgstr "Сигналы" msgid "Create New" msgstr "Создать новый" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "Избранное:" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "Недавнее:" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1666,14 +1819,6 @@ msgstr "Переместить избранное вверх" msgid "Move Favorite Down" msgstr "Переместить избранное вниз" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "Избранное:" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "Недавнее:" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "Предпросмотр:" @@ -2084,14 +2229,6 @@ msgid "Go to previously opened scene." msgstr "Перейти к предыдущей открытой сцене." #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "Полноэкранный режим" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "Свободный режим" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "Следующая вкладка" @@ -2177,6 +2314,10 @@ msgid "Quit to Project List" msgstr "Выйти в список проектов" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "Свободный режим" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "Импортировать ассеты в проект." @@ -2354,6 +2495,11 @@ msgid "Editor Layout" msgstr "Макет редактора" #: tools/editor/editor_node.cpp +#, fuzzy +msgid "Toggle Fullscreen" +msgstr "Полноэкранный режим" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "Установить шаблоны экспорта" @@ -2378,6 +2524,10 @@ msgid "Update Changes" msgstr "Обновлять при изменениях" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "Инспектор" @@ -2417,6 +2567,10 @@ msgstr "Свойства объекта." msgid "FileSystem" msgstr "Файловая система" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "Узел" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "Вывод" @@ -3258,10 +3412,6 @@ msgid "MultiNode Set" msgstr "Мульти-узловый набор" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "Узел" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "Группы" @@ -3808,6 +3958,11 @@ msgid "Clear Bones" msgstr "Очистить кости" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy +msgid "Show Bones" +msgstr "Создать кости" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "Создать цепь ИК" @@ -4546,6 +4701,11 @@ msgid "Close Docs" msgstr "Закрыть документацию" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Закрыть" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4657,6 +4817,11 @@ msgstr "" "Встроенные скрипты могут быть изменены только, когда сцена, которой они " "принадлежат, загружена" +#: tools/editor/plugins/script_text_editor.cpp +#, fuzzy +msgid "Pick Color" +msgstr "Цвет" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "Переместить вверх" @@ -5033,6 +5198,11 @@ msgid "Insert Animation Key" msgstr "Вставить ключ анимации" #: tools/editor/plugins/spatial_editor_plugin.cpp +#, fuzzy +msgid "Focus Origin" +msgstr "Отображать начало координат" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "Показать выбранное" @@ -5298,6 +5468,11 @@ msgid "Remove Item" msgstr "Удалить элемент" #: tools/editor/plugins/theme_editor_plugin.cpp +#, fuzzy +msgid "Theme" +msgstr "Сохранить тему" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "Добавить элемент класса" @@ -6113,6 +6288,11 @@ msgid "Assign" msgstr "Назначить" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "Следующий скрипт" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "Ошибка загрузки файла: Это не ресурс!" @@ -6129,10 +6309,6 @@ msgid "On" msgstr "Вкл" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "Задан" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "Свойства:" @@ -6145,14 +6321,12 @@ msgid "Sections:" msgstr "Разделы:" #: tools/editor/property_selector.cpp -#, fuzzy msgid "Select Property" -msgstr "Выбрать точки" +msgstr "Выбрать свойство" #: tools/editor/property_selector.cpp -#, fuzzy msgid "Select Method" -msgstr "Режим выделения" +msgstr "Выбрать метод" #: tools/editor/pvrtc_compress.cpp msgid "Could not execute PVRTC tool:" @@ -6294,7 +6468,7 @@ msgstr "Сохранить новую Сцену как.." #: tools/editor/scene_tree_dock.cpp msgid "Makes Sense!" -msgstr "Уууу круто!" +msgstr "Имеет смысл!" #: tools/editor/scene_tree_dock.cpp msgid "Can't operate on nodes from a foreign scene!" diff --git a/tools/translations/sk.po b/tools/translations/sk.po index 4f3175ddd8..0e21e5a94f 100644 --- a/tools/translations/sk.po +++ b/tools/translations/sk.po @@ -32,6 +32,12 @@ msgid "step argument is zero!" msgstr "argument \"step\"/krok je nulový!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "" @@ -159,6 +165,10 @@ msgid "Editing Signal:" msgstr "Signály:" #: modules/visual_script/visual_script_editor.cpp +msgid "Change Expression" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "" @@ -203,6 +213,43 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Condition" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -332,6 +379,85 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid unique name." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid product GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -481,6 +607,10 @@ msgid "" "It only provides navigation data." msgstr "" +#: scene/3d/remote_transform.cpp +msgid "Path property must point to a valid Spatial node to work." +msgstr "" + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1119,10 +1249,6 @@ msgid "Method List For '%s':" msgstr "" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "" @@ -1241,6 +1367,12 @@ msgid "Method in target Node must be specified!" msgstr "" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "" @@ -1316,6 +1448,15 @@ msgstr "" msgid "Create New" msgstr "" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1585,14 +1726,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -1987,14 +2120,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2081,6 +2206,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2239,6 +2368,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2263,6 +2396,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2302,6 +2439,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3131,10 +3272,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3674,6 +3811,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4413,6 +4554,10 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +msgid "Close All" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4520,6 +4665,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4896,6 +5045,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp #, fuzzy msgid "Focus Selection" msgstr "Všetky vybrané" @@ -5164,6 +5317,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -5975,6 +6132,11 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "Popis:" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -5991,10 +6153,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/sl.po b/tools/translations/sl.po index 33a9bc3e23..41ebecad54 100644 --- a/tools/translations/sl.po +++ b/tools/translations/sl.po @@ -33,6 +33,12 @@ msgid "step argument is zero!" msgstr "stopnja argumenta je nič!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "To ni skripta z instanco" @@ -162,6 +168,10 @@ msgid "Editing Signal:" msgstr "Urejanje Signala:" #: modules/visual_script/visual_script_editor.cpp +msgid "Change Expression" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Dodaj Node" @@ -207,6 +217,43 @@ msgid "Add Setter Property" msgstr "Dodaj Setter Lastnost" #: modules/visual_script/visual_script_editor.cpp +msgid "Condition" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -338,6 +385,86 @@ msgstr "" "Neveljavna vrnitev vrednosti od _step(), mora biti število (seq out), ali " "string (error)." +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "Neveljaven indeks lastnosti imena." + +#: platform/winrt/export/export.cpp +msgid "Invalid product GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -492,6 +619,10 @@ msgid "" "It only provides navigation data." msgstr "" +#: scene/3d/remote_transform.cpp +msgid "Path property must point to a valid Spatial node to work." +msgstr "" + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1129,10 +1260,6 @@ msgid "Method List For '%s':" msgstr "" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "" @@ -1251,6 +1378,12 @@ msgid "Method in target Node must be specified!" msgstr "" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "" @@ -1326,6 +1459,15 @@ msgstr "" msgid "Create New" msgstr "" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1595,14 +1737,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -1997,14 +2131,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2090,6 +2216,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2248,6 +2378,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2272,6 +2406,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2311,6 +2449,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3140,10 +3282,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3683,6 +3821,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4421,6 +4563,11 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Zapri" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4528,6 +4675,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4904,6 +5055,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5169,6 +5324,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -5980,6 +6139,10 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +msgid "New Script" +msgstr "" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -5996,10 +6159,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/tools.pot b/tools/translations/tools.pot index c86586a055..5453c5d9e2 100644 --- a/tools/translations/tools.pot +++ b/tools/translations/tools.pot @@ -26,6 +26,12 @@ msgid "step argument is zero!" msgstr "" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "" @@ -148,6 +154,10 @@ msgid "Editing Signal:" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Change Expression" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "" @@ -192,6 +202,43 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Condition" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -320,6 +367,85 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid unique name." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid product GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -462,6 +588,10 @@ msgid "" "It only provides navigation data." msgstr "" +#: scene/3d/remote_transform.cpp +msgid "Path property must point to a valid Spatial node to work." +msgstr "" + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1099,10 +1229,6 @@ msgid "Method List For '%s':" msgstr "" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "" @@ -1221,6 +1347,12 @@ msgid "Method in target Node must be specified!" msgstr "" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "" @@ -1296,6 +1428,15 @@ msgstr "" msgid "Create New" msgstr "" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1565,14 +1706,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -1967,14 +2100,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2060,6 +2185,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2218,6 +2347,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2242,6 +2375,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2281,6 +2418,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3110,10 +3251,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3653,6 +3790,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4391,6 +4532,10 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +msgid "Close All" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4498,6 +4643,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4874,6 +5023,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5139,6 +5292,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -5950,6 +6107,10 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +msgid "New Script" +msgstr "" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -5966,10 +6127,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/tr.po b/tools/translations/tr.po index 0c27abe7c5..823082ef17 100644 --- a/tools/translations/tr.po +++ b/tools/translations/tr.po @@ -33,6 +33,12 @@ msgid "step argument is zero!" msgstr "" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "" @@ -155,6 +161,10 @@ msgid "Editing Signal:" msgstr "Sinyal Düzenleniyor:" #: modules/visual_script/visual_script_editor.cpp +msgid "Change Expression" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Düğüm Ekle" @@ -200,6 +210,44 @@ msgid "Add Setter Property" msgstr "Düzenleyici Özellik Ekle" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "Animasyon Yükle" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -333,6 +381,88 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "Geçersiz isim." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "Geçersiz yazı tipi boyutu." + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid publisher GUID." +msgstr "Geçersiz üst yol" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -475,6 +605,10 @@ msgid "" "It only provides navigation data." msgstr "" +#: scene/3d/remote_transform.cpp +msgid "Path property must point to a valid Spatial node to work." +msgstr "" + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1112,10 +1246,6 @@ msgid "Method List For '%s':" msgstr "" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "" @@ -1234,6 +1364,12 @@ msgid "Method in target Node must be specified!" msgstr "" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "Düğüme bağlan:" @@ -1309,6 +1445,15 @@ msgstr "" msgid "Create New" msgstr "Yeni oluştur" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "Favoriler:" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "Yakın zamanda:" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1584,14 +1729,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "Favoriler:" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "Yakın zamanda:" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "Ön izleme:" @@ -1987,14 +2124,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2081,6 +2210,10 @@ msgid "Quit to Project List" msgstr "Proje Listesine Git" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2239,6 +2372,10 @@ msgid "Editor Layout" msgstr "Editör Düzeni" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2263,6 +2400,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2302,6 +2443,10 @@ msgstr "Nesne özellikleri." msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3132,10 +3277,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3677,6 +3818,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4416,6 +4561,11 @@ msgid "Close Docs" msgstr "Kapat" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "Kapat" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4523,6 +4673,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4899,6 +5053,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5164,6 +5322,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -5976,6 +6138,11 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "Betiği Çalıştır" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -5992,10 +6159,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/ur_PK.po b/tools/translations/ur_PK.po index 0ac56d847b..188d2bb4c2 100644 --- a/tools/translations/ur_PK.po +++ b/tools/translations/ur_PK.po @@ -33,6 +33,12 @@ msgid "step argument is zero!" msgstr "سٹیپ کے ارگمنٹس سفر ہیں!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr ".یہ انسٹینس کے بغیر سکرپٹ نہی ہوتی" @@ -158,6 +164,10 @@ msgid "Editing Signal:" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Change Expression" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "" @@ -202,6 +212,43 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Condition" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -330,6 +377,85 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid unique name." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid product GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -472,6 +598,10 @@ msgid "" "It only provides navigation data." msgstr "" +#: scene/3d/remote_transform.cpp +msgid "Path property must point to a valid Spatial node to work." +msgstr "" + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1110,10 +1240,6 @@ msgid "Method List For '%s':" msgstr "" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "" @@ -1232,6 +1358,12 @@ msgid "Method in target Node must be specified!" msgstr "" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "" @@ -1307,6 +1439,15 @@ msgstr "" msgid "Create New" msgstr "" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1579,14 +1720,6 @@ msgstr "پسندیدہ اوپر منتقل کریں" msgid "Move Favorite Down" msgstr "پسندیدہ نیچے منتقل کریں" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -1982,14 +2115,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2075,6 +2200,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2233,6 +2362,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2257,6 +2390,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2296,6 +2433,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3125,10 +3266,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3669,6 +3806,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4408,6 +4549,10 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +msgid "Close All" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4515,6 +4660,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4891,6 +5040,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp #, fuzzy msgid "Focus Selection" msgstr ".تمام کا انتخاب" @@ -5158,6 +5311,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -5969,6 +6126,11 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "سب سکریپشن بنائیں" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -5985,10 +6147,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/zh_CN.po b/tools/translations/zh_CN.po index a53d4ba4ed..318d4186f3 100644 --- a/tools/translations/zh_CN.po +++ b/tools/translations/zh_CN.po @@ -4,16 +4,18 @@ # # 纯洁的坏蛋 <tqj.zyy@gmail.com>, 2016. # 孤月蓝风 <trlanfeng@foxmail.com>, 2016. +# Bruce Guo <guoboism@hotmail.com>, 2016. # Geequlim <geequlim@gmail.com>, 2016. # Luo Jun <vipsbpig@gmail.com>, 2016. +# oberon-tonya <360119124@qq.com>, 2016. # wanfang liu <wanfang.liu@gmail.com>, 2016. # msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2016-08-23 09:17+0000\n" -"Last-Translator: 孤月蓝风 <trlanfeng@foxmail.com>\n" +"PO-Revision-Date: 2016-10-01 09:03+0000\n" +"Last-Translator: oberon-tonya <360119124@qq.com>\n" "Language-Team: Chinese (China) <https://hosted.weblate.org/projects/godot-" "engine/godot/zh_CN/>\n" "Language: zh_CN\n" @@ -21,7 +23,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 2.8-dev\n" +"X-Generator: Weblate 2.9-dev\n" #: modules/gdscript/gd_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -38,6 +40,12 @@ msgid "step argument is zero!" msgstr "step参数为0!" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "脚本没有实例化" @@ -47,7 +55,7 @@ msgstr "没有基于脚本" #: modules/gdscript/gd_functions.cpp msgid "Not based on a resource file" -msgstr "不是一个资源文件" +msgstr "没有基于一个资源文件" #: modules/gdscript/gd_functions.cpp msgid "Invalid instance dictionary format (missing @path)" @@ -174,12 +182,18 @@ msgstr "连接事件:" #: modules/visual_script/visual_script_editor.cpp #, fuzzy +msgid "Change Expression" +msgstr "更改类型" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy msgid "Add Node" msgstr "添加子节点" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy msgid "Hold Meta to drop a Getter. Hold Shift to drop a generic signature." -msgstr "" +msgstr "按住Meta键放置一个访问器,按住Shift键放置一个通用签名" #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature." @@ -198,8 +212,9 @@ msgid "Hold Meta to drop a Variable Setter." msgstr "" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy msgid "Hold Ctrl to drop a Variable Setter." -msgstr "" +msgstr "按住Ctrl键放置一个变量设定器。" #: modules/visual_script/visual_script_editor.cpp #, fuzzy @@ -220,6 +235,46 @@ msgid "Add Setter Property" msgstr "添加设置器" #: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Condition" +msgstr "拷贝动画" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Return" +msgstr "返回:" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "调用" + +#: modules/visual_script/visual_script_editor.cpp +#, fuzzy +msgid "Get" +msgstr "设置" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "设置" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -350,8 +405,9 @@ msgid "VariableSet not found in script: " msgstr "脚本中未找到VariableSet: " #: modules/visual_script/visual_script_nodes.cpp +#, fuzzy msgid "Custom node has no _step() method, can't process graph." -msgstr "" +msgstr "自定义节点具备no_step()方法,不能生成图像" #: modules/visual_script/visual_script_nodes.cpp msgid "" @@ -359,6 +415,90 @@ msgid "" "(error)." msgstr "_step()的返回值无效,必须是整形(seq out),或字符串(error)。" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Error creating the signature object." +msgstr "写入项目PCK文件出错!" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "名称非法:" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "字体大小非法。" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid publisher GUID." +msgstr "父路径非法" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid background color." +msgstr "自定义字体文件非法。" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -525,6 +665,11 @@ msgid "" msgstr "" "NavigationMeshInstance类型节点必须作为Navigation节点的子孙才能提供导航数据。" +#: scene/3d/remote_transform.cpp +#, fuzzy +msgid "Path property must point to a valid Spatial node to work." +msgstr "path属性必须指向一个合法的Particles2D节点才能正常工作。" + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -748,19 +893,20 @@ msgid "" "functions. Making them visible for editing is fine though, but they will " "hide upon running." msgstr "" -"Popup对象在你调用popup()方法之前将保持隐藏,这里设置为可见并不代表执行场景时" -"它会出现。" +"Popup对象默认保持隐藏,除非你调用popup()方法。编辑时可以让它们保持可见,但运" +"行时它们会自动隐藏。" #: scene/main/viewport.cpp +#, fuzzy msgid "" "This viewport is not set as render target. If you intend for it to display " "its contents directly to the screen, make it a child of a Control so it can " "obtain a size. Otherwise, make it a RenderTarget and assign its internal " "texture to some node for display." msgstr "" -"这个Viewport未设置render target。如果你刻意为之,直接在屏幕上显示其内容,使其" -"成为子控件的所以它可以获取大小。否则请设置render target,将其内部纹理分配给一" -"些节点显示。" +"这个Viewport未设置为render target。如果你刻意打算让其直接在屏幕上显示其内容," +"使其成为子控件的所以它可以有一个尺寸大小值。否则请设置为Render target,并将其" +"内部纹理分配给一些节点以显示。" #: scene/resources/dynamic_font.cpp #: tools/editor/io_plugins/editor_font_import_plugin.cpp @@ -787,8 +933,9 @@ msgid "Disabled" msgstr "已禁用" #: tools/editor/animation_editor.cpp +#, fuzzy msgid "All Selection" -msgstr "所有选项" +msgstr "所有选中项" #: tools/editor/animation_editor.cpp msgid "Move Add Key" @@ -1175,10 +1322,6 @@ msgid "Method List For '%s':" msgstr "%s的方法列表" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "调用" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "方法列表:" @@ -1297,6 +1440,12 @@ msgid "Method in target Node must be specified!" msgstr "必须设置方法的对象节点!" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "连接到节点:" @@ -1374,6 +1523,15 @@ msgstr "信号" msgid "Create New" msgstr "新建" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "收藏:" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "最近文件:" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1643,14 +1801,6 @@ msgstr "向上移动收藏" msgid "Move Favorite Down" msgstr "向下移动收藏" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "收藏:" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "最近文件:" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "预览" @@ -1794,7 +1944,7 @@ msgstr "正在分析" #: tools/editor/editor_node.cpp msgid "Creating Thumbnail" -msgstr "" +msgstr "创建缩略图" #: tools/editor/editor_node.cpp msgid "" @@ -1863,12 +2013,14 @@ msgid "Copy Resource" msgstr "拷贝资源" #: tools/editor/editor_node.cpp +#, fuzzy msgid "Make Built-In" -msgstr "" +msgstr "使之内置" #: tools/editor/editor_node.cpp +#, fuzzy msgid "Make Sub-Resources Unique" -msgstr "" +msgstr "使子资源唯一化" #: tools/editor/editor_node.cpp msgid "Open in Help" @@ -2052,14 +2204,6 @@ msgid "Go to previously opened scene." msgstr "前往上一个打开的场景。" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "全屏模式" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "下一项" @@ -2145,6 +2289,11 @@ msgid "Quit to Project List" msgstr "退出到项目列表" #: tools/editor/editor_node.cpp +#, fuzzy +msgid "Distraction Free Mode" +msgstr "无干扰模式" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "导入资源" @@ -2161,8 +2310,9 @@ msgid "Import" msgstr "导入" #: tools/editor/editor_node.cpp +#, fuzzy msgid "Miscellaneous project or scene-wide tools." -msgstr "" +msgstr "其他工程或全场景工具" #: tools/editor/editor_node.cpp msgid "Tools" @@ -2312,6 +2462,11 @@ msgid "Editor Layout" msgstr "编辑器布局" #: tools/editor/editor_node.cpp +#, fuzzy +msgid "Toggle Fullscreen" +msgstr "全屏模式" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "安装导出模板" @@ -2336,6 +2491,10 @@ msgid "Update Changes" msgstr "有更改时更新UI" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "属性面板" @@ -2375,6 +2534,10 @@ msgstr "对象属性。" msgid "FileSystem" msgstr "文件系统" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "节点" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "输出" @@ -2472,12 +2635,14 @@ msgid "Time:" msgstr "时间:" #: tools/editor/editor_profiler.cpp +#, fuzzy msgid "Inclusive" -msgstr "" +msgstr "包含" #: tools/editor/editor_profiler.cpp +#, fuzzy msgid "Self" -msgstr "" +msgstr "自身" #: tools/editor/editor_profiler.cpp msgid "Frame #:" @@ -2706,10 +2871,13 @@ msgid "No target font resource!" msgstr "请设置目标字体资源!" #: tools/editor/io_plugins/editor_font_import_plugin.cpp +#, fuzzy msgid "" "Invalid file extension.\n" "Please use .fnt." msgstr "" +"文件扩展名不合法\n" +"请使用.fnt文件" #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "Can't load/process source font." @@ -2809,8 +2977,9 @@ msgid "Audio Sample" msgstr "音效" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#, fuzzy msgid "New Clip" -msgstr "" +msgstr "新片段" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Animation Options" @@ -2829,28 +2998,34 @@ msgid "Optimizer" msgstr "优化" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#, fuzzy msgid "Max Linear Error" -msgstr "" +msgstr "最大线性误差" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#, fuzzy msgid "Max Angular Error" -msgstr "" +msgstr "最大角度误差" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#, fuzzy msgid "Max Angle" -msgstr "" +msgstr "最大角度" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#, fuzzy msgid "Clips" -msgstr "" +msgstr "剪辑" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#, fuzzy msgid "Start(s)" -msgstr "" +msgstr "起点" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#, fuzzy msgid "End(s)" -msgstr "" +msgstr "终点" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp #: tools/editor/plugins/sprite_frames_editor_plugin.cpp @@ -2866,12 +3041,14 @@ msgid "Source path is empty." msgstr "源路径为空。" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#, fuzzy msgid "Couldn't load post-import script." -msgstr "" +msgstr "无法载入后导入脚本" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#, fuzzy msgid "Invalid/broken script for post-import." -msgstr "" +msgstr "后导入脚本被损坏或不合法" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Error importing scene." @@ -2898,8 +3075,9 @@ msgid "Target Texture Folder:" msgstr "目标贴图目录:" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#, fuzzy msgid "Post-Process Script:" -msgstr "" +msgstr "后处理脚本:" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Custom Root Node Type:" @@ -2939,16 +3117,19 @@ msgid "Running Custom Script.." msgstr "执行自定义脚本.." #: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#, fuzzy msgid "Couldn't load post-import script:" -msgstr "" +msgstr "无法载入后导入脚本:" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#, fuzzy msgid "Invalid/broken script for post-import (check console):" -msgstr "" +msgstr "后处理脚本被损坏或不合法(查看控制台):" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp +#, fuzzy msgid "Error running post-import script:" -msgstr "" +msgstr "后处理脚本运行发生错误" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Import Image:" @@ -2960,7 +3141,7 @@ msgstr "不允许导入文件本身:" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Couldn't localize path: %s (already local)" -msgstr "" +msgstr "无法本地化路径:%s (已经是本地路径)" #: tools/editor/io_plugins/editor_scene_import_plugin.cpp msgid "Saving.." @@ -3095,11 +3276,11 @@ msgstr "加载源图片" #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Slicing" -msgstr "" +msgstr "切片中" #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Inserting" -msgstr "" +msgstr "插入中" #: tools/editor/io_plugins/editor_texture_import_plugin.cpp msgid "Saving" @@ -3203,12 +3384,9 @@ msgid "Translation" msgstr "语言" #: tools/editor/multi_node_edit.cpp +#, fuzzy msgid "MultiNode Set" -msgstr "" - -#: tools/editor/node_dock.cpp -msgid "Node" -msgstr "节点" +msgstr "多节点组" #: tools/editor/node_dock.cpp msgid "Groups" @@ -3384,7 +3562,7 @@ msgstr "混合时间:" #: tools/editor/plugins/animation_player_editor_plugin.cpp msgid "Next (Auto Queue):" -msgstr "" +msgstr "接下来(自动排列):" #: tools/editor/plugins/animation_player_editor_plugin.cpp msgid "Cross-Animation Blend Times" @@ -3754,6 +3932,11 @@ msgid "Clear Bones" msgstr "清除骨骼" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy +msgid "Show Bones" +msgstr "添加骨骼" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "添加IK链" @@ -4493,6 +4676,11 @@ msgid "Close Docs" msgstr "拷贝到下一行" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "关闭" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4602,6 +4790,11 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +#, fuzzy +msgid "Pick Color" +msgstr "颜色" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "向上移动" @@ -4981,6 +5174,11 @@ msgid "Insert Animation Key" msgstr "插入动画帧" #: tools/editor/plugins/spatial_editor_plugin.cpp +#, fuzzy +msgid "Focus Origin" +msgstr "显示原点" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "选中选中项" @@ -5246,6 +5444,11 @@ msgid "Remove Item" msgstr "移除项目" #: tools/editor/plugins/theme_editor_plugin.cpp +#, fuzzy +msgid "Theme" +msgstr "保存主题" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "添加类项目" @@ -6064,6 +6267,11 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "下一个脚本" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "加载文件出错:不是资源文件!" @@ -6080,10 +6288,6 @@ msgid "On" msgstr "启用" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "设置" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "属性:" @@ -6621,8 +6825,9 @@ msgid "Change Capsule Shape Height" msgstr "更改胶囊高度" #: tools/editor/spatial_editor_gizmos.cpp +#, fuzzy msgid "Change Ray Shape Length" -msgstr "" +msgstr "更改射线形状长度" #: tools/editor/spatial_editor_gizmos.cpp #, fuzzy diff --git a/tools/translations/zh_HK.po b/tools/translations/zh_HK.po index 1d2ab3f8fb..9f6d7786ac 100644 --- a/tools/translations/zh_HK.po +++ b/tools/translations/zh_HK.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2016-08-13 09:55+0000\n" +"PO-Revision-Date: 2016-09-05 13:21+0000\n" "Last-Translator: zx-wt <ZX_WT@ymail.com>\n" "Language-Team: Chinese (Hong Kong) <https://hosted.weblate.org/projects/" "godot-engine/godot/zh_HK/>\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 2.8-dev\n" +"X-Generator: Weblate 2.8\n" #: modules/gdscript/gd_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -33,6 +33,12 @@ msgid "step argument is zero!" msgstr "" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "" @@ -161,6 +167,10 @@ msgid "Editing Signal:" msgstr "連接" #: modules/visual_script/visual_script_editor.cpp +msgid "Change Expression" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "新增節點" @@ -206,6 +216,43 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Condition" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -336,6 +383,87 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid unique name." +msgstr "無效名稱" + +#: platform/winrt/export/export.cpp +#, fuzzy +msgid "Invalid product GUID." +msgstr "無效字型" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -478,6 +606,10 @@ msgid "" "It only provides navigation data." msgstr "" +#: scene/3d/remote_transform.cpp +msgid "Path property must point to a valid Spatial node to work." +msgstr "" + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -517,7 +649,7 @@ msgstr "檔案已存在, 要覆蓋嗎?" #: scene/gui/file_dialog.cpp tools/editor/editor_file_dialog.cpp msgid "All Recognized" -msgstr "" +msgstr "所有類型" #: scene/gui/file_dialog.cpp tools/editor/editor_file_dialog.cpp msgid "All Files (*)" @@ -601,21 +733,21 @@ msgstr "請用有效的副檔名" #: scene/gui/input_action.cpp tools/editor/project_settings.cpp #: tools/editor/settings_config_dialog.cpp msgid "Shift+" -msgstr "" +msgstr "Shift+" #: scene/gui/input_action.cpp tools/editor/project_settings.cpp #: tools/editor/settings_config_dialog.cpp msgid "Alt+" -msgstr "" +msgstr "Alt+" #: scene/gui/input_action.cpp msgid "Ctrl+" -msgstr "" +msgstr "Ctrl+" #: scene/gui/input_action.cpp tools/editor/project_settings.cpp #: tools/editor/settings_config_dialog.cpp msgid "Meta+" -msgstr "" +msgstr "Meta+" #: scene/gui/input_action.cpp tools/editor/project_settings.cpp msgid "Device" @@ -623,7 +755,7 @@ msgstr "設備" #: scene/gui/input_action.cpp tools/editor/project_settings.cpp msgid "Button" -msgstr "" +msgstr "按鍵" #: scene/gui/input_action.cpp tools/editor/project_settings.cpp msgid "Left Button." @@ -715,7 +847,7 @@ msgstr "" #: scene/resources/dynamic_font.cpp #: tools/editor/io_plugins/editor_font_import_plugin.cpp msgid "Unknown font format." -msgstr "不明字形格式" +msgstr "字形格式不明" #: scene/resources/dynamic_font.cpp #: tools/editor/io_plugins/editor_font_import_plugin.cpp @@ -733,11 +865,12 @@ msgstr "已停用" #: tools/editor/animation_editor.cpp msgid "All Selection" -msgstr "" +msgstr "所有選項" #: tools/editor/animation_editor.cpp +#, fuzzy msgid "Move Add Key" -msgstr "" +msgstr "移動" #: tools/editor/animation_editor.cpp msgid "Anim Change Transition" @@ -772,8 +905,9 @@ msgid "Move Anim Track Down" msgstr "" #: tools/editor/animation_editor.cpp +#, fuzzy msgid "Remove Anim Track" -msgstr "" +msgstr "移除動畫" #: tools/editor/animation_editor.cpp msgid "Set Transitions to:" @@ -1082,7 +1216,7 @@ msgstr "" #: tools/editor/asset_library_editor_plugin.cpp #: tools/editor/project_settings.cpp msgid "Category:" -msgstr "" +msgstr "分類:" #: tools/editor/asset_library_editor_plugin.cpp msgid "All" @@ -1090,7 +1224,7 @@ msgstr "全部" #: tools/editor/asset_library_editor_plugin.cpp msgid "Site:" -msgstr "" +msgstr "地址:" #: tools/editor/asset_library_editor_plugin.cpp msgid "Support.." @@ -1098,11 +1232,11 @@ msgstr "" #: tools/editor/asset_library_editor_plugin.cpp msgid "Official" -msgstr "" +msgstr "官方" #: tools/editor/asset_library_editor_plugin.cpp msgid "Community" -msgstr "" +msgstr "社群" #: tools/editor/asset_library_editor_plugin.cpp msgid "Testing" @@ -1117,10 +1251,6 @@ msgid "Method List For '%s':" msgstr "" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "" @@ -1158,11 +1288,11 @@ msgstr "全部替換" #: tools/editor/code_editor.cpp msgid "Match Case" -msgstr "" +msgstr "符合大小寫" #: tools/editor/code_editor.cpp msgid "Whole Words" -msgstr "" +msgstr "完整詞語" #: tools/editor/code_editor.cpp msgid "Selection Only" @@ -1174,7 +1304,7 @@ msgstr "只限選中" #: tools/editor/plugins/shader_editor_plugin.cpp #: tools/editor/project_settings.cpp msgid "Search" -msgstr "" +msgstr "搜尋" #: tools/editor/code_editor.cpp tools/editor/editor_help.cpp msgid "Find" @@ -1227,18 +1357,25 @@ msgid "Reset Zoom" msgstr "重設縮放比例" #: tools/editor/code_editor.cpp tools/editor/script_editor_debugger.cpp +#, fuzzy msgid "Line:" -msgstr "" +msgstr "行:" #: tools/editor/code_editor.cpp msgid "Col:" -msgstr "" +msgstr "列:" #: tools/editor/connections_dialog.cpp msgid "Method in target Node must be specified!" msgstr "" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp #, fuzzy msgid "Connect To Node:" msgstr "連到" @@ -1315,11 +1452,21 @@ msgstr "訊號" msgid "Create New" msgstr "新增" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "最近:" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp +#, fuzzy msgid "Matches:" -msgstr "" +msgstr "吻合" #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/property_selector.cpp tools/editor/script_editor_debugger.cpp @@ -1443,11 +1590,12 @@ msgstr "刪除" #: tools/editor/editor_autoload_settings.cpp msgid "Invalid name." -msgstr "" +msgstr "無效名稱" #: tools/editor/editor_autoload_settings.cpp +#, fuzzy msgid "Valid characters:" -msgstr "" +msgstr "有效字符:" #: tools/editor/editor_autoload_settings.cpp msgid "Invalid name. Must not collide with an existing engine class name." @@ -1498,8 +1646,9 @@ msgid "Remove Autoload" msgstr "" #: tools/editor/editor_autoload_settings.cpp +#, fuzzy msgid "Enable" -msgstr "" +msgstr "啟用" #: tools/editor/editor_autoload_settings.cpp msgid "Rearrange Autoloads" @@ -1514,7 +1663,7 @@ msgstr "" #: tools/editor/plugins/sample_library_editor_plugin.cpp #: tools/editor/project_manager.cpp msgid "Name" -msgstr "" +msgstr "名稱" #: tools/editor/editor_autoload_settings.cpp msgid "Singleton" @@ -1534,7 +1683,7 @@ msgstr "" #: tools/editor/editor_data.cpp msgid "Updating scene.." -msgstr "" +msgstr "正在更新場景..." #: tools/editor/editor_dir_dialog.cpp msgid "Choose a Directory" @@ -1558,7 +1707,7 @@ msgstr "" #: tools/editor/editor_file_dialog.cpp msgid "Refresh" -msgstr "" +msgstr "重新整理" #: tools/editor/editor_file_dialog.cpp msgid "Toggle Hidden Files" @@ -1586,14 +1735,6 @@ msgstr "上移" msgid "Move Favorite Down" msgstr "下移" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "最近:" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "預覽:" @@ -1709,7 +1850,7 @@ msgstr "" #: tools/editor/plugins/animation_player_editor_plugin.cpp #: tools/editor/resources_dock.cpp msgid "Save Resource As.." -msgstr "" +msgstr "把資源另存為..." #: tools/editor/editor_node.cpp tools/editor/scene_tree_dock.cpp msgid "I see.." @@ -1736,8 +1877,9 @@ msgid "Analyzing" msgstr "分析中" #: tools/editor/editor_node.cpp +#, fuzzy msgid "Creating Thumbnail" -msgstr "" +msgstr "正在建立縮圖" #: tools/editor/editor_node.cpp msgid "" @@ -1745,8 +1887,9 @@ msgid "" msgstr "" #: tools/editor/editor_node.cpp +#, fuzzy msgid "Failed to load resource." -msgstr "" +msgstr "資源加載失敗" #: tools/editor/editor_node.cpp msgid "Can't load MeshLibrary for merging!" @@ -1989,14 +2132,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp #, fuzzy msgid "Next tab" msgstr "下一個" @@ -2083,6 +2218,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2241,6 +2380,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2265,6 +2408,10 @@ msgid "Update Changes" msgstr "當改變時更新" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "監視器" @@ -2304,6 +2451,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3133,10 +3284,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3676,6 +3823,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4415,6 +4566,11 @@ msgid "Close Docs" msgstr "關閉場景" #: tools/editor/plugins/script_editor_plugin.cpp +#, fuzzy +msgid "Close All" +msgstr "關閉" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4522,6 +4678,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "上移" @@ -4898,6 +5058,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp #, fuzzy msgid "Focus Selection" msgstr "只限選中" @@ -5164,6 +5328,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -5975,6 +6143,11 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +#, fuzzy +msgid "New Script" +msgstr "下一個腳本" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -5991,10 +6164,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" diff --git a/tools/translations/zh_TW.po b/tools/translations/zh_TW.po index 9be46b18e8..af66795003 100644 --- a/tools/translations/zh_TW.po +++ b/tools/translations/zh_TW.po @@ -32,6 +32,12 @@ msgid "step argument is zero!" msgstr "" #: modules/gdscript/gd_functions.cpp +msgid "" +"Paths cannot start with '/', absolute paths must start with 'res://', " +"'user://', or 'local://'" +msgstr "" + +#: modules/gdscript/gd_functions.cpp msgid "Not a script with an instance" msgstr "" @@ -154,6 +160,10 @@ msgid "Editing Signal:" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Change Expression" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "" @@ -198,6 +208,43 @@ msgid "Add Setter Property" msgstr "" #: modules/visual_script/visual_script_editor.cpp +msgid "Condition" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Sequence" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Switch" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Iterator" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "While" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Return" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp tools/editor/call_dialog.cpp +msgid "Call" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +msgid "Get" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp +#: tools/editor/property_editor.cpp +msgid "Set" +msgstr "" + +#: modules/visual_script/visual_script_editor.cpp #: tools/editor/plugins/canvas_item_editor_plugin.cpp #: tools/editor/plugins/polygon_2d_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp @@ -326,6 +373,85 @@ msgid "" "(error)." msgstr "" +#: modules/visual_script/visual_script_nodes.cpp +msgid "just pressed" +msgstr "" + +#: modules/visual_script/visual_script_nodes.cpp +msgid "just released" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"Couldn't read the certficate file. Are the path and password both correct?" +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the signature object." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Error creating the package signature." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "" +"No export templates found.\n" +"Download and install export templates." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom debug package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Custom release package not found." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid unique name." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid product GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid publisher GUID." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid background color." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid Store Logo image dimensions (should be 50x50)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." +msgstr "" + +#: platform/winrt/export/export.cpp +msgid "Invalid splash screen image dimensions (should be 620x300)." +msgstr "" + #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " @@ -474,6 +600,10 @@ msgid "" "It only provides navigation data." msgstr "" +#: scene/3d/remote_transform.cpp +msgid "Path property must point to a valid Spatial node to work." +msgstr "" + #: scene/3d/scenario_fx.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." @@ -1111,10 +1241,6 @@ msgid "Method List For '%s':" msgstr "" #: tools/editor/call_dialog.cpp -msgid "Call" -msgstr "" - -#: tools/editor/call_dialog.cpp msgid "Method List:" msgstr "" @@ -1233,6 +1359,12 @@ msgid "Method in target Node must be specified!" msgstr "" #: tools/editor/connections_dialog.cpp +msgid "" +"Target method not found! Specify a valid method or attach a script to target " +"Node." +msgstr "" + +#: tools/editor/connections_dialog.cpp msgid "Connect To Node:" msgstr "" @@ -1308,6 +1440,15 @@ msgstr "" msgid "Create New" msgstr "" +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +#: tools/editor/filesystem_dock.cpp +msgid "Favorites:" +msgstr "" + +#: tools/editor/create_dialog.cpp tools/editor/editor_file_dialog.cpp +msgid "Recent:" +msgstr "" + #: tools/editor/create_dialog.cpp tools/editor/editor_help.cpp #: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/property_selector.cpp tools/editor/quick_open.cpp @@ -1577,14 +1718,6 @@ msgstr "" msgid "Move Favorite Down" msgstr "" -#: tools/editor/editor_file_dialog.cpp tools/editor/filesystem_dock.cpp -msgid "Favorites:" -msgstr "" - -#: tools/editor/editor_file_dialog.cpp -msgid "Recent:" -msgstr "" - #: tools/editor/editor_file_dialog.cpp msgid "Preview:" msgstr "" @@ -1979,14 +2112,6 @@ msgid "Go to previously opened scene." msgstr "" #: tools/editor/editor_node.cpp -msgid "Fullscreen Mode" -msgstr "" - -#: tools/editor/editor_node.cpp -msgid "Distraction Free Mode" -msgstr "" - -#: tools/editor/editor_node.cpp msgid "Next tab" msgstr "" @@ -2072,6 +2197,10 @@ msgid "Quit to Project List" msgstr "" #: tools/editor/editor_node.cpp +msgid "Distraction Free Mode" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Import assets to the project." msgstr "" @@ -2230,6 +2359,10 @@ msgid "Editor Layout" msgstr "" #: tools/editor/editor_node.cpp +msgid "Toggle Fullscreen" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Install Export Templates" msgstr "" @@ -2254,6 +2387,10 @@ msgid "Update Changes" msgstr "" #: tools/editor/editor_node.cpp +msgid "Disable Update Spinner" +msgstr "" + +#: tools/editor/editor_node.cpp msgid "Inspector" msgstr "" @@ -2293,6 +2430,10 @@ msgstr "" msgid "FileSystem" msgstr "" +#: tools/editor/editor_node.cpp tools/editor/node_dock.cpp +msgid "Node" +msgstr "" + #: tools/editor/editor_node.cpp msgid "Output" msgstr "" @@ -3122,10 +3263,6 @@ msgid "MultiNode Set" msgstr "" #: tools/editor/node_dock.cpp -msgid "Node" -msgstr "" - -#: tools/editor/node_dock.cpp msgid "Groups" msgstr "" @@ -3665,6 +3802,10 @@ msgid "Clear Bones" msgstr "" #: tools/editor/plugins/canvas_item_editor_plugin.cpp +msgid "Show Bones" +msgstr "" + +#: tools/editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" msgstr "" @@ -4403,6 +4544,10 @@ msgid "Close Docs" msgstr "" #: tools/editor/plugins/script_editor_plugin.cpp +msgid "Close All" +msgstr "" + +#: tools/editor/plugins/script_editor_plugin.cpp #: tools/editor/plugins/script_text_editor.cpp #: tools/editor/plugins/shader_editor_plugin.cpp msgid "Find.." @@ -4510,6 +4655,10 @@ msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +#: tools/editor/plugins/script_text_editor.cpp +msgid "Pick Color" +msgstr "" + #: tools/editor/plugins/script_text_editor.cpp tools/editor/scene_tree_dock.cpp msgid "Move Up" msgstr "" @@ -4886,6 +5035,10 @@ msgid "Insert Animation Key" msgstr "" #: tools/editor/plugins/spatial_editor_plugin.cpp +msgid "Focus Origin" +msgstr "" + +#: tools/editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" msgstr "" @@ -5151,6 +5304,10 @@ msgid "Remove Item" msgstr "" #: tools/editor/plugins/theme_editor_plugin.cpp +msgid "Theme" +msgstr "" + +#: tools/editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" msgstr "" @@ -5962,6 +6119,10 @@ msgid "Assign" msgstr "" #: tools/editor/property_editor.cpp +msgid "New Script" +msgstr "" + +#: tools/editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "" @@ -5978,10 +6139,6 @@ msgid "On" msgstr "" #: tools/editor/property_editor.cpp -msgid "Set" -msgstr "" - -#: tools/editor/property_editor.cpp msgid "Properties:" msgstr "" |